summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt4
-rw-r--r--Source/CMakeVersion.cmake4
-rw-r--r--Source/CPack/cpack.cxx18
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx71
-rw-r--r--Source/CTest/cmCTestSubmitHandler.h12
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx39
-rw-r--r--Source/CTest/cmCTestTestHandler.h2
-rw-r--r--Source/CTest/cmParseGTMCoverage.cxx9
-rw-r--r--Source/cmAddSubDirectoryCommand.cxx6
-rw-r--r--Source/cmArchiveWrite.cxx2
-rw-r--r--Source/cmCMakePolicyCommand.cxx33
-rw-r--r--Source/cmCMakePolicyCommand.h1
-rw-r--r--Source/cmCTest.cxx68
-rw-r--r--Source/cmCTest.h34
-rw-r--r--Source/cmCacheManager.cxx3
-rw-r--r--Source/cmComputeComponentGraph.cxx4
-rw-r--r--Source/cmComputeLinkDepends.cxx14
-rw-r--r--Source/cmComputeLinkInformation.cxx29
-rw-r--r--Source/cmComputeTargetDepends.cxx57
-rw-r--r--Source/cmComputeTargetDepends.h3
-rw-r--r--Source/cmConditionEvaluator.cxx6
-rw-r--r--Source/cmConfigureFileCommand.cxx14
-rw-r--r--Source/cmCustomCommand.cxx10
-rw-r--r--Source/cmCustomCommand.h13
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx7
-rw-r--r--Source/cmExtraKateGenerator.cxx3
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx7
-rw-r--r--Source/cmFileCommand.cxx2
-rw-r--r--Source/cmFindBase.cxx4
-rw-r--r--Source/cmFindCommon.cxx4
-rw-r--r--Source/cmFindPackageCommand.cxx37
-rw-r--r--Source/cmFindPackageCommand.h3
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx12
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h1
-rw-r--r--Source/cmGeneratorExpressionNode.cxx3
-rw-r--r--Source/cmGeneratorTarget.cxx486
-rw-r--r--Source/cmGeneratorTarget.h45
-rw-r--r--Source/cmGetFilenameComponentCommand.cxx10
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx9
-rw-r--r--Source/cmGlobalGenerator.cxx66
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx10
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx9
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx4
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx29
-rw-r--r--Source/cmGlobalXCodeGenerator.h3
-rw-r--r--Source/cmGraphAdjacencyList.h8
-rw-r--r--Source/cmGraphVizWriter.cxx33
-rw-r--r--Source/cmGraphVizWriter.h4
-rw-r--r--Source/cmInstallCommand.cxx412
-rw-r--r--Source/cmInstallCommand.h22
-rw-r--r--Source/cmInstallCommandArguments.cxx6
-rw-r--r--Source/cmInstallCommandArguments.h2
-rw-r--r--Source/cmInstallGenerator.cxx13
-rw-r--r--Source/cmInstallGenerator.h4
-rw-r--r--Source/cmInstallScriptGenerator.cxx4
-rw-r--r--Source/cmInstallSubdirectoryGenerator.cxx77
-rw-r--r--Source/cmInstallSubdirectoryGenerator.h41
-rw-r--r--Source/cmInstallTargetGenerator.cxx3
-rw-r--r--Source/cmInstallTargetGenerator.h15
-rw-r--r--Source/cmLinkItem.cxx12
-rw-r--r--Source/cmLinkItem.h9
-rw-r--r--Source/cmListCommand.cxx54
-rw-r--r--Source/cmListFileCache.cxx20
-rw-r--r--Source/cmListFileCache.h33
-rw-r--r--Source/cmLocalGenerator.cxx256
-rw-r--r--Source/cmLocalGenerator.h32
-rw-r--r--Source/cmLocalNinjaGenerator.cxx4
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx11
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx6
-rw-r--r--Source/cmMakefile.cxx21
-rw-r--r--Source/cmMakefile.h10
-rw-r--r--Source/cmMakefileTargetGenerator.cxx5
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx1
-rw-r--r--Source/cmOrderDirectories.cxx2
-rw-r--r--Source/cmOutputConverter.cxx6
-rw-r--r--Source/cmOutputRequiredFilesCommand.cxx6
-rw-r--r--Source/cmPolicies.h16
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx185
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.h47
-rw-r--r--Source/cmQtAutoGenInitializer.cxx372
-rw-r--r--Source/cmQtAutoGenInitializer.h58
-rw-r--r--Source/cmRST.cxx3
-rw-r--r--Source/cmRulePlaceholderExpander.cxx4
-rw-r--r--Source/cmSetCommand.cxx8
-rw-r--r--Source/cmState.cxx8
-rw-r--r--Source/cmStringCommand.cxx7
-rw-r--r--Source/cmSystemTools.cxx4
-rw-r--r--Source/cmTarget.cxx24
-rw-r--r--Source/cmTarget.h11
-rw-r--r--Source/cmTargetDepend.h6
-rw-r--r--Source/cmTargetPropCommandBase.cxx25
-rw-r--r--Source/cmVS141CLFlagTable.h2
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx85
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h2
-rw-r--r--Source/cmVisualStudioSlnParser.cxx6
-rw-r--r--Source/cmake.cxx19
-rw-r--r--Source/cmcldeps.cxx2
-rw-r--r--Source/cmcmd.cxx46
-rw-r--r--Source/kwsys/CMakeLists.txt1
101 files changed, 2381 insertions, 906 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 311f3f4..9aebfa7 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -260,6 +260,8 @@ set(SRCS
cmInstallFilesGenerator.cxx
cmInstallScriptGenerator.h
cmInstallScriptGenerator.cxx
+ cmInstallSubdirectoryGenerator.h
+ cmInstallSubdirectoryGenerator.cxx
cmInstallTargetGenerator.h
cmInstallTargetGenerator.cxx
cmInstallDirectoryGenerator.h
@@ -318,6 +320,8 @@ set(SRCS
cmQtAutoGen.h
cmQtAutoGenerator.cxx
cmQtAutoGenerator.h
+ cmQtAutoGenGlobalInitializer.cxx
+ cmQtAutoGenGlobalInitializer.h
cmQtAutoGenInitializer.cxx
cmQtAutoGenInitializer.h
cmQtAutoGeneratorMocUic.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 5f103dc..eec8d1a 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 13)
-set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 3)
+set(CMake_VERSION_PATCH 20181119)
+#set(CMake_VERSION_RC 1)
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index c083945..7cf69fc 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -21,6 +21,7 @@
#include "cmCPackLog.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
+#include "cmDocumentationFormatter.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmStateSnapshot.h"
@@ -358,8 +359,21 @@ int main(int argc, char const* const* argv)
cpackGenerator->SetTraceExpand(traceExpand);
} else {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Cannot initialize CPack generator: " << gen
- << std::endl);
+ "Could not create CPack generator: " << gen
+ << std::endl);
+ // Print out all the valid generators
+ cmDocumentation generatorDocs;
+ std::vector<cmDocumentationEntry> v;
+ for (auto const& g : generators.GetGeneratorsList()) {
+ cmDocumentationEntry e;
+ e.Name = g.first;
+ e.Brief = g.second;
+ v.push_back(std::move(e));
+ }
+ generatorDocs.SetSection("Generators", v);
+ std::cerr << "\n";
+ generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators,
+ std::cerr);
parsed = 0;
}
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index ecf309a..98872a5 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestCurl.h"
#include "cmCTestScriptHandler.h"
@@ -55,6 +56,7 @@ public:
std::string Filename;
std::string MD5;
std::string Message;
+ std::string BuildID;
private:
std::vector<char> CurrentValue;
@@ -96,6 +98,8 @@ private:
this->MD5 = this->GetCurrentValue();
} else if (name == "message") {
this->Message = this->GetCurrentValue();
+ } else if (name == "buildId") {
+ this->BuildID = this->GetCurrentValue();
}
}
};
@@ -152,10 +156,9 @@ void cmCTestSubmitHandler::Initialize()
this->Files.clear();
}
-bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url)
+bool cmCTestSubmitHandler::SubmitUsingFTP(
+ const std::string& localprefix, const std::vector<std::string>& files,
+ const std::string& remoteprefix, const std::string& url)
{
CURL* curl;
CURLcode res;
@@ -299,10 +302,9 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix,
}
// Uploading files is simpler
-bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url)
+bool cmCTestSubmitHandler::SubmitUsingHTTP(
+ const std::string& localprefix, const std::vector<std::string>& files,
+ const std::string& remoteprefix, const std::string& url)
{
CURL* curl;
CURLcode res;
@@ -465,6 +467,17 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
cmSystemTools::ComputeFileHash(local_file, cmCryptoHash::AlgoMD5);
}
+ // Generate Done.xml right before it is submitted.
+ // The reason for this is two-fold:
+ // 1) It must be generated after some other part has been submitted
+ // so we have a buildId to refer to in its contents.
+ // 2) By generating Done.xml here its timestamp will be as late as
+ // possible. This gives us a more accurate record of how long the
+ // entire build took to complete.
+ if (file == "Done.xml") {
+ this->CTest->GenerateDoneFile();
+ }
+
if (!cmSystemTools::FileExists(local_file)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
" Cannot find file: " << local_file << std::endl);
@@ -646,6 +659,7 @@ void cmCTestSubmitHandler::ParseResponse(
" Submission failed: " << parser.Message << std::endl);
return;
}
+ this->CTest->SetBuildID(parser.BuildID);
}
output = cmSystemTools::UpperCase(output);
if (output.find("WARNING") != std::string::npos) {
@@ -662,9 +676,9 @@ void cmCTestSubmitHandler::ParseResponse(
}
}
-bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url)
+bool cmCTestSubmitHandler::TriggerUsingHTTP(
+ const std::vector<std::string>& files, const std::string& remoteprefix,
+ const std::string& url)
{
CURL* curl;
char error_buffer[1024];
@@ -792,11 +806,10 @@ bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<std::string>& files,
return true;
}
-bool cmCTestSubmitHandler::SubmitUsingSCP(const std::string& scp_command,
- const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url)
+bool cmCTestSubmitHandler::SubmitUsingSCP(
+ const std::string& scp_command, const std::string& localprefix,
+ const std::vector<std::string>& files, const std::string& remoteprefix,
+ const std::string& url)
{
if (scp_command.empty() || localprefix.empty() || files.empty() ||
remoteprefix.empty() || url.empty()) {
@@ -890,7 +903,7 @@ bool cmCTestSubmitHandler::SubmitUsingSCP(const std::string& scp_command,
}
bool cmCTestSubmitHandler::SubmitUsingCP(const std::string& localprefix,
- const std::set<std::string>& files,
+ const std::vector<std::string>& files,
const std::string& remoteprefix,
const std::string& destination)
{
@@ -925,7 +938,7 @@ bool cmCTestSubmitHandler::SubmitUsingCP(const std::string& localprefix,
#if defined(CTEST_USE_XMLRPC)
bool cmCTestSubmitHandler::SubmitUsingXMLRPC(
- const std::string& localprefix, const std::set<std::string>& files,
+ const std::string& localprefix, const std::vector<std::string>& files,
const std::string& remoteprefix, const std::string& url)
{
xmlrpc_env env;
@@ -1020,7 +1033,7 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC(
}
#else
bool cmCTestSubmitHandler::SubmitUsingXMLRPC(
- std::string const& /*unused*/, std::set<std::string> const& /*unused*/,
+ std::string const& /*unused*/, std::vector<std::string> const& /*unused*/,
std::string const& /*unused*/, std::string const& /*unused*/)
{
return false;
@@ -1351,13 +1364,13 @@ int cmCTestSubmitHandler::ProcessHandler()
cmGeneratedFileStream ofs;
this->StartLogFile("Submit", ofs);
- cmCTest::SetOfStrings files;
+ std::vector<std::string> files;
std::string prefix = this->GetSubmitResultsPrefix();
if (!this->Files.empty()) {
// Submit the explicitly selected files:
//
- files.insert(this->Files.begin(), this->Files.end());
+ files.insert(files.end(), this->Files.begin(), this->Files.end());
}
// Add to the list of files to submit from any selected, existing parts:
@@ -1404,7 +1417,21 @@ int cmCTestSubmitHandler::ProcessHandler()
// Submit files from this part.
std::vector<std::string> const& pfiles = this->CTest->GetSubmitFiles(p);
- files.insert(pfiles.begin(), pfiles.end());
+ files.insert(files.end(), pfiles.begin(), pfiles.end());
+ }
+
+ // Make sure files are unique, but preserve order.
+ {
+ // This endPos intermediate is needed to work around non-conformant C++11
+ // standard libraries that have erase(iterator,iterator) instead of
+ // erase(const_iterator,const_iterator).
+ size_t endPos = cmRemoveDuplicates(files) - files.cbegin();
+ files.erase(files.begin() + endPos, files.end());
+ }
+
+ // Submit Done.xml last
+ if (this->SubmitPart[cmCTest::PartDone]) {
+ files.push_back("Done.xml");
}
if (ofs) {
diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h
index b4d0e77..66f2173 100644
--- a/Source/CTest/cmCTestSubmitHandler.h
+++ b/Source/CTest/cmCTestSubmitHandler.h
@@ -57,27 +57,27 @@ private:
* Submit file using various ways
*/
bool SubmitUsingFTP(const std::string& localprefix,
- const std::set<std::string>& files,
+ const std::vector<std::string>& files,
const std::string& remoteprefix, const std::string& url);
bool SubmitUsingHTTP(const std::string& localprefix,
- const std::set<std::string>& files,
+ const std::vector<std::string>& files,
const std::string& remoteprefix,
const std::string& url);
bool SubmitUsingSCP(const std::string& scp_command,
const std::string& localprefix,
- const std::set<std::string>& files,
+ const std::vector<std::string>& files,
const std::string& remoteprefix, const std::string& url);
bool SubmitUsingCP(const std::string& localprefix,
- const std::set<std::string>& files,
+ const std::vector<std::string>& files,
const std::string& remoteprefix, const std::string& url);
- bool TriggerUsingHTTP(const std::set<std::string>& files,
+ bool TriggerUsingHTTP(const std::vector<std::string>& files,
const std::string& remoteprefix,
const std::string& url);
bool SubmitUsingXMLRPC(const std::string& localprefix,
- const std::set<std::string>& files,
+ const std::vector<std::string>& files,
const std::string& remoteprefix,
const std::string& url);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index c936910..1d938e6 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -535,11 +535,21 @@ int cmCTestTestHandler::ProcessHandler()
percent = 99;
}
+ std::string passColorCode;
+ std::string failedColorCode;
+ if (failed.empty()) {
+ passColorCode = this->CTest->GetColorCode(cmCTest::Color::GREEN);
+ } else {
+ failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED);
+ }
cmCTestLog(this->CTest, HANDLER_OUTPUT,
std::endl
- << static_cast<int>(percent + .5f) << "% tests passed, "
- << failed.size() << " tests failed out of " << total
- << std::endl);
+ << passColorCode << static_cast<int>(percent + .5f)
+ << "% tests passed"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << ", " << failedColorCode << failed.size() << " tests failed"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << " out of " << total << std::endl);
if ((!this->CTest->GetLabelsForSubprojects().empty() &&
this->CTest->GetSubprojectSummary())) {
this->PrintLabelOrSubprojectSummary(true);
@@ -562,6 +572,8 @@ int cmCTestTestHandler::ProcessHandler()
this->StartLogFile("TestsDisabled", ofs);
const char* disabled_reason;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetColorCode(cmCTest::Color::BLUE));
for (cmCTestTestResult const& dt : disabledTests) {
ofs << dt.TestCount << ":" << dt.Name << std::endl;
if (dt.CompletionStatus == "Disabled") {
@@ -573,6 +585,8 @@ int cmCTestTestHandler::ProcessHandler()
"\t" << std::setw(3) << dt.TestCount << " - " << dt.Name
<< " (" << disabled_reason << ")" << std::endl);
}
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR));
}
if (!failed.empty()) {
@@ -587,10 +601,17 @@ int cmCTestTestHandler::ProcessHandler()
!cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") &&
ft.CompletionStatus != "Disabled") {
ofs << ft.TestCount << ":" << ft.Name << std::endl;
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- "\t" << std::setw(3) << ft.TestCount << " - " << ft.Name
- << " (" << this->GetTestStatus(ft) << ")"
- << std::endl);
+ auto testColor = cmCTest::Color::RED;
+ if (this->GetTestStatus(ft) == "Not Run") {
+ testColor = cmCTest::Color::YELLOW;
+ }
+ cmCTestLog(
+ this->CTest, HANDLER_OUTPUT,
+ "\t" << this->CTest->GetColorCode(testColor) << std::setw(3)
+ << ft.TestCount << " - " << ft.Name << " ("
+ << this->GetTestStatus(ft) << ")"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << std::endl);
}
}
}
@@ -1725,7 +1746,7 @@ void cmCTestTestHandler::UseExcludeRegExp()
this->UseExcludeRegExpFirst = !this->UseIncludeRegExpFlag;
}
-const char* cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result)
+std::string cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result)
{
static const char* statuses[] = { "Not Run", "Timeout", "SEGFAULT",
"ILLEGAL", "INTERRUPT", "NUMERICAL",
@@ -1737,7 +1758,7 @@ const char* cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result)
return "No Status";
}
if (status == cmCTestTestHandler::OTHER_FAULT) {
- return result.ExceptionStatus.c_str();
+ return result.ExceptionStatus;
}
return statuses[status];
}
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index d2694a1..bcacf23 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -274,7 +274,7 @@ private:
*/
std::string FindTheExecutable(const char* exe);
- const char* GetTestStatus(cmCTestTestResult const&);
+ std::string GetTestStatus(cmCTestTestResult const&);
void ExpandTestsToRunInformation(size_t numPossibleTests);
void ExpandTestsToRunInformationForRerunFailed();
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index 83dde3f..0722753 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -1,5 +1,6 @@
#include "cmParseGTMCoverage.h"
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
#include "cmSystemTools.h"
@@ -86,6 +87,10 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
}
// Find the full path to the file
bool found = this->FindMumpsFile(routine, filepath);
+ if (!found && cmHasLiteralSuffix(routine, "%")) {
+ routine.erase(0, 1);
+ found = this->FindMumpsFile(routine, filepath);
+ }
if (found) {
int lineoffset = 0;
if (this->FindFunctionInMumpsFile(filepath, function, lineoffset)) {
@@ -192,8 +197,8 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
done = true;
}
} else {
- // all chars except ", (, and % get stored in the arg string
- if (cur != '\"' && cur != '(' && cur != '%') {
+ // all chars except " and ( get stored in the arg string
+ if (cur != '\"' && cur != '(') {
arg.append(1, line[pos]);
}
}
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 75bd6fb..75e5aa4 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -20,7 +20,7 @@ bool cmAddSubDirectoryCommand::InitialPass(
}
// store the binpath
- std::string const& srcArg = args[0];
+ std::string const& srcArg = args.front();
std::string binArg;
bool excludeFromAll = false;
@@ -84,10 +84,10 @@ bool cmAddSubDirectoryCommand::InitialPass(
const std::string& bin = this->Makefile->GetCurrentBinaryDirectory();
size_t srcLen = src.length();
size_t binLen = bin.length();
- if (srcLen > 0 && src[srcLen - 1] == '/') {
+ if (srcLen > 0 && src.back() == '/') {
--srcLen;
}
- if (binLen > 0 && bin[binLen - 1] == '/') {
+ if (binLen > 0 && bin.back() == '/') {
--binLen;
}
binPath = bin.substr(0, binLen) + srcPath.substr(srcLen);
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 6031781..3f2e784 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -178,7 +178,7 @@ bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix,
bool recursive)
{
if (this->Okay()) {
- if (!path.empty() && path[path.size() - 1] == '/') {
+ if (!path.empty() && path.back() == '/') {
path.erase(path.size() - 1);
}
this->AddPath(path.c_str(), skip, prefix, recursive);
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index adf9ef8..3209ea5 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -46,6 +46,9 @@ bool cmCMakePolicyCommand::InitialPass(std::vector<std::string> const& args,
if (args[0] == "VERSION") {
return this->HandleVersionMode(args);
}
+ if (args[0] == "GET_WARNING") {
+ return this->HandleGetWarningMode(args);
+ }
std::ostringstream e;
e << "given unknown first argument \"" << args[0] << "\"";
@@ -181,3 +184,33 @@ bool cmCMakePolicyCommand::HandleVersionMode(
this->Makefile->SetPolicyVersion(version_min, version_max);
return true;
}
+
+bool cmCMakePolicyCommand::HandleGetWarningMode(
+ std::vector<std::string> const& args)
+{
+ if (args.size() != 3) {
+ this->SetError(
+ "GET_WARNING must be given exactly 2 additional arguments.");
+ return false;
+ }
+
+ // Get arguments.
+ std::string const& id = args[1];
+ std::string const& var = args[2];
+
+ // Lookup the policy number.
+ cmPolicies::PolicyID pid;
+ if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
+ std::ostringstream e;
+ e << "GET_WARNING given policy \"" << id
+ << "\" which is not known to this version of CMake.";
+ this->SetError(e.str());
+ return false;
+ }
+
+ // Lookup the policy warning.
+ this->Makefile->AddDefinition(var,
+ cmPolicies::GetPolicyWarning(pid).c_str());
+
+ return true;
+}
diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h
index b18576c..cca1406 100644
--- a/Source/cmCMakePolicyCommand.h
+++ b/Source/cmCMakePolicyCommand.h
@@ -37,6 +37,7 @@ private:
bool HandleSetMode(std::vector<std::string> const& args);
bool HandleGetMode(std::vector<std::string> const& args);
bool HandleVersionMode(std::vector<std::string> const& args);
+ bool HandleGetWarningMode(std::vector<std::string> const& args);
};
#endif
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 908eea1..c2b6575 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -294,7 +294,9 @@ cmCTest::cmCTest()
this->SuppressUpdatingCTestConfiguration = false;
this->DartVersion = 1;
this->DropSiteCDash = false;
+ this->BuildID = "";
this->OutputTestOutputOnTestFailure = false;
+ this->OutputColorCode = this->ColoredOutputSupportedByConsole();
this->RepeatTests = 1; // default to run each test once
this->RepeatUntilFail = false;
@@ -320,6 +322,7 @@ cmCTest::cmCTest()
this->Parts[PartNotes].SetName("Notes");
this->Parts[PartExtraFiles].SetName("ExtraFiles");
this->Parts[PartUpload].SetName("Upload");
+ this->Parts[PartDone].SetName("Done");
// Fill the part name-to-id map.
for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
@@ -612,6 +615,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
std::string bld_dir = this->GetCTestConfiguration("BuildDirectory");
this->DartVersion = 1;
this->DropSiteCDash = false;
+ this->BuildID = "";
for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
this->Parts[p].SubmitFiles.clear();
}
@@ -724,7 +728,7 @@ bool cmCTest::UpdateCTestConfiguration()
if (line.empty()) {
continue;
}
- while (fin && (line[line.size() - 1] == '\\')) {
+ while (fin && (line.back() == '\\')) {
line = line.substr(0, line.size() - 1);
buffer[0] = 0;
fin.getline(buffer, 1023);
@@ -1565,6 +1569,24 @@ int cmCTest::GenerateNotesFile(const char* cfiles)
return this->GenerateNotesFile(files);
}
+int cmCTest::GenerateDoneFile()
+{
+ cmGeneratedFileStream ofs;
+ if (!this->OpenOutputFile(this->CurrentTag, "Done.xml", ofs)) {
+ cmCTestLog(this, ERROR_MESSAGE, "Cannot open done file" << std::endl);
+ return 1;
+ }
+ cmXMLWriter xml(ofs);
+ xml.StartDocument();
+ xml.StartElement("Done");
+ xml.Element("buildId", this->BuildID);
+ xml.Element("time", std::chrono::system_clock::now());
+ xml.EndElement(); // Done
+ xml.EndDocument();
+
+ return 0;
+}
+
std::string cmCTest::Base64GzipEncodeFile(std::string const& file)
{
std::string tarFile = file + "_temp.tar.gz";
@@ -2054,7 +2076,18 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
return true;
}
-bool cmCTest::ProgressOutputSupportedByConsole() const
+#if !defined(_WIN32)
+bool cmCTest::ConsoleIsNotDumb()
+{
+ std::string term_env_variable;
+ if (cmSystemTools::GetEnv("TERM", term_env_variable)) {
+ return isatty(1) && term_env_variable != "dumb";
+ }
+ return false;
+}
+#endif
+
+bool cmCTest::ProgressOutputSupportedByConsole()
{
#if defined(_WIN32)
// On Windows we need a console buffer.
@@ -2063,12 +2096,19 @@ bool cmCTest::ProgressOutputSupportedByConsole() const
return GetConsoleScreenBufferInfo(console, &csbi);
#else
// On UNIX we need a non-dumb tty.
- std::string term_env_variable;
- if (cmSystemTools::GetEnv("TERM", term_env_variable)) {
- return isatty(1) && term_env_variable != "dumb";
- }
+ return ConsoleIsNotDumb();
#endif
+}
+
+bool cmCTest::ColoredOutputSupportedByConsole()
+{
+#if defined(_WIN32)
+ // Not supported on Windows
return false;
+#else
+ // On UNIX we need a non-dumb tty.
+ return ConsoleIsNotDumb();
+#endif
}
// handle the -S -SR and -SP arguments
@@ -2554,7 +2594,7 @@ std::string cmCTest::GetShortPathToFile(const char* cfname)
cmSystemTools::ConvertToUnixSlashes(*res);
path = "./" + *res;
- if (path[path.size() - 1] == '/') {
+ if (path.back() == '/') {
path = path.substr(0, path.size() - 1);
}
}
@@ -2937,6 +2977,20 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,
}
}
+std::string cmCTest::GetColorCode(Color color) const
+{
+ if (this->OutputColorCode) {
+#if defined(_WIN32)
+ // Not supported on Windows
+ static_cast<void>(color);
+#else
+ return "\033[0;" + std::to_string(static_cast<int>(color)) + "m";
+#endif
+ }
+
+ return "";
+}
+
cmDuration cmCTest::GetRemainingTimeAllowed()
{
if (!this->GetHandler("script")) {
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 345b538..427049d 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -50,6 +50,7 @@ public:
PartNotes,
PartExtraFiles,
PartUpload,
+ PartDone,
PartCount // Update names in constructor when adding a part
};
@@ -373,6 +374,9 @@ public:
/** Create XML file that contains all the notes specified */
int GenerateNotesFile(const VectorOfStrings& files);
+ /** Create XML file to indicate that build is complete */
+ int GenerateDoneFile();
+
/** Submit extra files to the server */
bool SubmitExtraFiles(const char* files);
bool SubmitExtraFiles(const VectorOfStrings& files);
@@ -401,10 +405,27 @@ public:
void Log(int logType, const char* file, int line, const char* msg,
bool suppress = false);
+ /** Color values */
+ enum class Color
+ {
+ CLEAR_COLOR = 0,
+ RED = 31,
+ GREEN = 32,
+ YELLOW = 33,
+ BLUE = 34
+ };
+
+ /** Get color code characters for a specific color */
+ std::string GetColorCode(Color color) const;
+
/** Get the version of dart server */
int GetDartVersion() { return this->DartVersion; }
int GetDropSiteCDash() { return this->DropSiteCDash; }
+ /** The Build ID is assigned by CDash */
+ void SetBuildID(const std::string& id) { this->BuildID = id; }
+ std::string GetBuildID() { return this->BuildID; }
+
/** Add file to be submitted */
void AddSubmitFile(Part part, const char* name);
std::vector<std::string> const& GetSubmitFiles(Part part)
@@ -567,8 +588,16 @@ private:
bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args,
std::string& errormsg);
+#if !defined(_WIN32)
/** returns true iff the console supports progress output */
- bool ProgressOutputSupportedByConsole() const;
+ static bool ConsoleIsNotDumb();
+#endif
+
+ /** returns true iff the console supports progress output */
+ static bool ProgressOutputSupportedByConsole();
+
+ /** returns true iff the console supports colored output */
+ static bool ColoredOutputSupportedByConsole();
/** handle the -S -SP and -SR arguments */
void HandleScriptArguments(size_t& i, std::vector<std::string>& args,
@@ -607,6 +636,8 @@ private:
int DartVersion;
bool DropSiteCDash;
+ std::string BuildID;
+
std::vector<std::string> InitialCommandLineArguments;
int SubmitIndex;
@@ -615,6 +646,7 @@ private:
int OutputLogFileLastTag;
bool OutputTestOutputOnTestFailure;
+ bool OutputColorCode;
std::map<std::string, std::string> Definitions;
};
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index b391dc4..0305677 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -415,8 +415,7 @@ void cmCacheManager::OutputValueNoNewlines(std::ostream& fout,
std::string const& value)
{
// if value has trailing space or tab, enclose it in single quotes
- if (!value.empty() &&
- (value[value.size() - 1] == ' ' || value[value.size() - 1] == '\t')) {
+ if (!value.empty() && (value.back() == ' ' || value.back() == '\t')) {
fout << '\'' << value << '\'';
} else {
fout << value;
diff --git a/Source/cmComputeComponentGraph.cxx b/Source/cmComputeComponentGraph.cxx
index a7dc1ca..5820df6 100644
--- a/Source/cmComputeComponentGraph.cxx
+++ b/Source/cmComputeComponentGraph.cxx
@@ -125,8 +125,8 @@ void cmComputeComponentGraph::TransferEdges()
if (i_component != j_component) {
// We do not attempt to combine duplicate edges, but instead
// store the inter-component edges with suitable multiplicity.
- this->ComponentGraph[i_component].emplace_back(j_component,
- ni.IsStrong());
+ this->ComponentGraph[i_component].emplace_back(
+ j_component, ni.IsStrong(), ni.GetBacktrace());
}
}
}
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index aa17de6..4717cf6 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -6,6 +6,7 @@
#include "cmComputeComponentGraph.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
@@ -419,7 +420,8 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
// This shared library dependency must follow the item that listed
// it.
- this->EntryConstraintGraph[dep.DependerIndex].push_back(index);
+ this->EntryConstraintGraph[dep.DependerIndex].emplace_back(
+ index, true, cmListFileBacktrace());
// Target items may have their own dependencies.
if (entry.Target) {
@@ -522,7 +524,8 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
// The dependee must come after the depender.
if (depender_index >= 0) {
- this->EntryConstraintGraph[depender_index].push_back(dependee_index);
+ this->EntryConstraintGraph[depender_index].emplace_back(
+ dependee_index, false, cmListFileBacktrace());
} else {
// This is a direct dependency of the target being linked.
this->OriginalEntries.push_back(dependee_index);
@@ -565,7 +568,7 @@ cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index,
from = depender;
}
}
- return from->ResolveLinkItem(name);
+ return from->ResolveLinkItem(name, cmListFileBacktrace());
}
void cmComputeLinkDepends::InferDependencies()
@@ -594,7 +597,10 @@ void cmComputeLinkDepends::InferDependencies()
// Add the inferred dependencies to the graph.
cmGraphEdgeList& edges = this->EntryConstraintGraph[depender_index];
- edges.insert(edges.end(), common.begin(), common.end());
+ edges.reserve(edges.size() + common.size());
+ for (auto const& c : common) {
+ edges.emplace_back(c, true, cmListFileBacktrace());
+ }
}
}
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 0e48ca8..27b8599 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -421,7 +421,8 @@ std::string cmComputeLinkInformation::GetRPathLinkString() const
return "";
}
- // Construct the linker runtime search path.
+ // Construct the linker runtime search path. These MUST NOT contain tokens
+ // such as $ORIGIN, see https://sourceware.org/bugzilla/show_bug.cgi?id=16936
return cmJoin(this->OrderDependentRPath->GetOrderedDirectories(), ":");
}
@@ -1702,6 +1703,14 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") &&
this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
+ // Select whether to use $ORIGIN in RPATHs for artifacts in the build tree.
+ std::string const& originToken = this->Makefile->GetSafeDefinition(
+ "CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN");
+ std::string targetOutputDir = this->Target->GetDirectory(this->Config);
+ bool use_relative_build_rpath =
+ this->Target->GetPropertyAsBool("BUILD_RPATH_USE_ORIGIN") &&
+ !originToken.empty() && !targetOutputDir.empty();
+
// Construct the RPATH.
std::set<std::string> emitted;
if (use_install_rpath) {
@@ -1711,6 +1720,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
if (use_build_rpath) {
// Add directories explicitly specified by user
if (const char* build_rpath = this->Target->GetProperty("BUILD_RPATH")) {
+ // This will not resolve entries to use $ORIGIN, the user is expected to
+ // do that if necessary.
cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted);
}
}
@@ -1728,6 +1739,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
cmSystemTools::ConvertToUnixSlashes(rootPath);
std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath();
+ std::string const& topBinaryDir =
+ this->CMakeInstance->GetHomeOutputDirectory();
for (std::string const& ri : rdirs) {
// Put this directory in the rpath if using build-tree rpath
// support or if using the link path as an rpath.
@@ -1741,6 +1754,18 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
d += "/";
d += suffix;
cmSystemTools::ConvertToUnixSlashes(d);
+ } else if (use_relative_build_rpath) {
+ // If expansion of the $ORIGIN token is supported and permitted per
+ // policy, use relative paths in the RPATH.
+ if (cmSystemTools::ComparePath(d, topBinaryDir) ||
+ cmSystemTools::IsSubDirectory(d, topBinaryDir)) {
+ d = cmSystemTools::RelativePath(targetOutputDir, d);
+ if (!d.empty()) {
+ d = originToken + "/" + d;
+ } else {
+ d = originToken;
+ }
+ }
}
if (emitted.insert(d).second) {
runtimeDirs.push_back(std::move(d));
@@ -1749,8 +1774,6 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
// Do not add any path inside the source or build tree.
std::string const& topSourceDir =
this->CMakeInstance->GetHomeDirectory();
- std::string const& topBinaryDir =
- this->CMakeInstance->GetHomeOutputDirectory();
if (!cmSystemTools::ComparePath(ri, topSourceDir) &&
!cmSystemTools::ComparePath(ri, topBinaryDir) &&
!cmSystemTools::IsSubDirectory(ri, topSourceDir) &&
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 268e749..f8ac333 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -6,6 +6,7 @@
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
@@ -22,8 +23,6 @@
#include <stdio.h>
#include <utility>
-class cmListFileBacktrace;
-
/*
This class is meant to analyze inter-target dependencies globally
@@ -152,6 +151,7 @@ void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t,
cmGeneratorTarget const* dep = this->Targets[ni];
cmTargetDependSet::iterator di = deps.insert(dep).first;
di->SetType(ni.IsStrong());
+ di->SetBacktrace(ni.GetBacktrace());
}
}
@@ -208,7 +208,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
for (cmSourceFile const* o : objectFiles) {
std::string const& objLib = o->GetObjectLibrary();
if (!objLib.empty()) {
- cmLinkItem const& objItem = depender->ResolveLinkItem(objLib);
+ cmLinkItem const& objItem =
+ depender->ResolveLinkItem(objLib, cmListFileBacktrace());
if (emitted.insert(objItem).second) {
if (depender->GetType() != cmStateEnums::EXECUTABLE &&
depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
@@ -230,7 +231,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
cmLinkImplementation const* impl = depender->GetLinkImplementation(it);
// A target should not depend on itself.
- emitted.insert(cmLinkItem(depender));
+ emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
for (cmLinkImplItem const& lib : impl->Libraries) {
// Don't emit the same library twice for this target.
if (emitted.insert(lib).second) {
@@ -246,7 +247,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
std::set<cmLinkItem> emitted;
// A target should not depend on itself.
- emitted.insert(cmLinkItem(depender));
+ emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
for (cmLinkItem const& litem : tutils) {
// Don't emit the same utility twice for this target.
if (emitted.insert(litem).second) {
@@ -258,7 +259,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
void cmComputeTargetDepends::AddInterfaceDepends(
int depender_index, const cmGeneratorTarget* dependee,
- const std::string& config, std::set<cmLinkItem>& emitted)
+ cmListFileBacktrace const& dependee_backtrace, const std::string& config,
+ std::set<cmLinkItem>& emitted)
{
cmGeneratorTarget const* depender = this->Targets[depender_index];
if (cmLinkInterface const* iface =
@@ -266,8 +268,13 @@ void cmComputeTargetDepends::AddInterfaceDepends(
for (cmLinkItem const& lib : iface->Libraries) {
// Don't emit the same library twice for this target.
if (emitted.insert(lib).second) {
- this->AddTargetDepend(depender_index, lib, true);
- this->AddInterfaceDepends(depender_index, lib, config, emitted);
+ // Inject the backtrace of the original link dependency whose
+ // link interface we are adding. This indicates the line of
+ // code in the project that caused this dependency to be added.
+ cmLinkItem libBT = lib;
+ libBT.Backtrace = dependee_backtrace;
+ this->AddTargetDepend(depender_index, libBT, true);
+ this->AddInterfaceDepends(depender_index, libBT, config, emitted);
}
}
}
@@ -289,8 +296,9 @@ void cmComputeTargetDepends::AddInterfaceDepends(
if (dependee) {
// A target should not depend on itself.
- emitted.insert(cmLinkItem(depender));
- this->AddInterfaceDepends(depender_index, dependee, config, emitted);
+ emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
+ this->AddInterfaceDepends(depender_index, dependee,
+ dependee_name.Backtrace, config, emitted);
}
}
@@ -327,13 +335,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
e << "The dependency target \"" << dependee_name << "\" of target \""
<< depender->GetName() << "\" does not exist.";
- cmListFileBacktrace const* backtrace =
- depender->GetUtilityBacktrace(dependee_name.AsStr());
- if (backtrace) {
- cm->IssueMessage(messageType, e.str(), *backtrace);
- } else {
- cm->IssueMessage(messageType, e.str());
- }
+ cm->IssueMessage(messageType, e.str(), dependee_name.Backtrace);
}
}
@@ -346,13 +348,14 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
}
if (dependee) {
- this->AddTargetDepend(depender_index, dependee, linking);
+ this->AddTargetDepend(depender_index, dependee, dependee_name.Backtrace,
+ linking);
}
}
-void cmComputeTargetDepends::AddTargetDepend(int depender_index,
- const cmGeneratorTarget* dependee,
- bool linking)
+void cmComputeTargetDepends::AddTargetDepend(
+ int depender_index, cmGeneratorTarget const* dependee,
+ cmListFileBacktrace const& dependee_backtrace, bool linking)
{
if (dependee->IsImported() ||
dependee->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
@@ -361,7 +364,8 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
std::set<cmLinkItem> const& utils = dependee->GetUtilityItems();
for (cmLinkItem const& i : utils) {
if (cmGeneratorTarget const* transitive_dependee = i.Target) {
- this->AddTargetDepend(depender_index, transitive_dependee, false);
+ this->AddTargetDepend(depender_index, transitive_dependee, i.Backtrace,
+ false);
}
}
} else {
@@ -373,7 +377,8 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
int dependee_index = tii->second;
// Add this entry to the dependency graph.
- this->InitialGraph[depender_index].emplace_back(dependee_index, !linking);
+ this->InitialGraph[depender_index].emplace_back(dependee_index, !linking,
+ dependee_backtrace);
}
}
@@ -507,7 +512,7 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
for (cmGraphEdge const& edge : el) {
int j = edge;
if (cmap[j] == c && edge.IsStrong()) {
- this->FinalGraph[i].emplace_back(j, true);
+ this->FinalGraph[i].emplace_back(j, true, edge.GetBacktrace());
if (!this->IntraComponent(cmap, c, j, head, emitted, visited)) {
return false;
}
@@ -516,7 +521,7 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
// Prepend to a linear linked-list of intra-component edges.
if (*head >= 0) {
- this->FinalGraph[i].emplace_back(*head, false);
+ this->FinalGraph[i].emplace_back(*head, false, cmListFileBacktrace());
} else {
this->ComponentTail[c] = i;
}
@@ -567,7 +572,7 @@ bool cmComputeTargetDepends::ComputeFinalDepends(
int dependee_component = ni;
int dependee_component_head = this->ComponentHead[dependee_component];
this->FinalGraph[depender_component_tail].emplace_back(
- dependee_component_head, ni.IsStrong());
+ dependee_component_head, ni.IsStrong(), ni.GetBacktrace());
}
}
return true;
diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h
index 3046e8a..3840bd7 100644
--- a/Source/cmComputeTargetDepends.h
+++ b/Source/cmComputeTargetDepends.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmGraphAdjacencyList.h"
+#include "cmListFileCache.h"
#include <map>
#include <set>
@@ -47,6 +48,7 @@ private:
void AddTargetDepend(int depender_index, cmLinkItem const& dependee_name,
bool linking);
void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee,
+ cmListFileBacktrace const& dependee_backtrace,
bool linking);
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
@@ -54,6 +56,7 @@ private:
std::set<cmLinkItem>& emitted);
void AddInterfaceDepends(int depender_index,
cmGeneratorTarget const* dependee,
+ cmListFileBacktrace const& dependee_backtrace,
const std::string& config,
std::set<cmLinkItem>& emitted);
cmGlobalGenerator* GlobalGenerator;
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 172ef92..3b4206f 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -495,6 +495,12 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
argP1->GetValue().operator[](argP1len - 1) == '}') {
std::string env = argP1->GetValue().substr(4, argP1len - 5);
bdef = cmSystemTools::HasEnv(env);
+ } else if (argP1len > 6 &&
+ argP1->GetValue().substr(0, 6) == "CACHE{" &&
+ argP1->GetValue().operator[](argP1len - 1) == '}') {
+ std::string cache = argP1->GetValue().substr(6, argP1len - 7);
+ bdef =
+ this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr;
} else {
bdef = this->Makefile.IsDefinitionSet(argP1->GetValue());
}
diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx
index b5a639a..305262d 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -20,11 +20,8 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args,
}
std::string const& inFile = args[0];
- if (!cmSystemTools::FileIsFullPath(inFile)) {
- this->InputFile = this->Makefile->GetCurrentSourceDirectory();
- this->InputFile += "/";
- }
- this->InputFile += inFile;
+ this->InputFile = cmSystemTools::CollapseFullPath(
+ inFile, this->Makefile->GetCurrentSourceDirectory());
// If the input location is a directory, error out.
if (cmSystemTools::FileIsDirectory(this->InputFile)) {
@@ -39,11 +36,8 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args,
}
std::string const& outFile = args[1];
- if (!cmSystemTools::FileIsFullPath(outFile)) {
- this->OutputFile = this->Makefile->GetCurrentBinaryDirectory();
- this->OutputFile += "/";
- }
- this->OutputFile += outFile;
+ this->OutputFile = cmSystemTools::CollapseFullPath(
+ outFile, this->Makefile->GetCurrentBinaryDirectory());
// If the output location is already a directory put the file in it.
if (cmSystemTools::FileIsDirectory(this->OutputFile)) {
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index cfd260c..e87eb1e 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -4,16 +4,6 @@
#include "cmMakefile.h"
-cmCustomCommand::cmCustomCommand()
- : Backtrace()
-{
- this->HaveComment = false;
- this->EscapeOldStyle = true;
- this->EscapeAllowMakeVars = false;
- this->UsesTerminal = false;
- this->CommandExpandLists = false;
-}
-
cmCustomCommand::cmCustomCommand(cmMakefile const* mf,
const std::vector<std::string>& outputs,
const std::vector<std::string>& byproducts,
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 9e82f25..d82160b 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -22,9 +22,6 @@ class cmMakefile;
class cmCustomCommand
{
public:
- /** Default and copy constructors for STL containers. */
- cmCustomCommand();
-
/** Main constructor specifies all information for the command. */
cmCustomCommand(cmMakefile const* mf,
const std::vector<std::string>& outputs,
@@ -103,11 +100,11 @@ private:
std::string Comment;
std::string WorkingDirectory;
std::string Depfile;
- bool HaveComment;
- bool EscapeAllowMakeVars;
- bool EscapeOldStyle;
- bool UsesTerminal;
- bool CommandExpandLists;
+ bool HaveComment = false;
+ bool EscapeAllowMakeVars = false;
+ bool EscapeOldStyle = true;
+ bool UsesTerminal = false;
+ bool CommandExpandLists = false;
};
#endif
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 34f58ad..87ee382 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -976,9 +976,9 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
lg->GetIndividualFileTargets(objectFileTargets);
for (std::string const& f : objectFileTargets) {
const char* prefix = "[obj] ";
- if (f[f.length() - 1] == 's') {
+ if (f.back() == 's') {
prefix = "[to asm] ";
- } else if (f[f.length() - 1] == 'i') {
+ } else if (f.back() == 'i') {
prefix = "[pre] ";
}
this->AppendTarget(xml, f, make, makeArgs, subdir, prefix);
@@ -1035,8 +1035,7 @@ std::string cmExtraEclipseCDT4Generator::GetPathBasename(
{
std::string outputBasename = path;
while (!outputBasename.empty() &&
- (outputBasename[outputBasename.size() - 1] == '/' ||
- outputBasename[outputBasename.size() - 1] == '\\')) {
+ (outputBasename.back() == '/' || outputBasename.back() == '\\')) {
outputBasename.resize(outputBasename.size() - 1);
}
std::string::size_type loc = outputBasename.find_last_of("/\\");
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index f5c4c93..9410690 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -294,8 +294,7 @@ std::string cmExtraKateGenerator::GetPathBasename(
{
std::string outputBasename = path;
while (!outputBasename.empty() &&
- (outputBasename[outputBasename.size() - 1] == '/' ||
- outputBasename[outputBasename.size() - 1] == '\\')) {
+ (outputBasename.back() == '/' || outputBasename.back() == '\\')) {
outputBasename.resize(outputBasename.size() - 1);
}
std::string::size_type loc = outputBasename.find_last_of("/\\");
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index c4cca07..882d39f 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -384,13 +384,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
language);
- // Add the export symbol definition for shared library objects.
- if (const char* exportMacro = target->GetExportMacro()) {
- lg->AppendDefines(defines, exportMacro);
- }
-
// Add preprocessor definitions for this target and configuration.
- lg->AddCompileDefinitions(defines, target, config, language);
+ lg->GetTargetDefines(target, config, language, defines);
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
lg->AppendDefines(
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 1f76703..f86e5e2 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -2525,7 +2525,7 @@ bool cmFileCommand::HandleCMakePathCommand(
// remove double quotes in the path
std::string& s = *j;
- if (s.size() > 1 && s[0] == '\"' && s[s.size() - 1] == '\"') {
+ if (s.size() > 1 && s.front() == '\"' && s.back() == '\"') {
s = s.substr(1, s.size() - 2);
}
}
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 865595b..425546a 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -129,13 +129,13 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
this->VariableDocumentation += "the (unknown) library be found";
} else if (this->Names.size() == 1) {
this->VariableDocumentation +=
- "the " + this->Names[0] + " library be found";
+ "the " + this->Names.front() + " library be found";
} else {
this->VariableDocumentation += "one of the ";
this->VariableDocumentation +=
cmJoin(cmMakeRange(this->Names).retreat(1), ", ");
this->VariableDocumentation +=
- " or " + this->Names[this->Names.size() - 1] + " libraries be found";
+ " or " + this->Names.back() + " libraries be found";
}
}
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index fbaacfc..009f0e3 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -293,13 +293,13 @@ void cmFindCommon::AddPathSuffix(std::string const& arg)
if (suffix.empty()) {
return;
}
- if (suffix[0] == '/') {
+ if (suffix.front() == '/') {
suffix = suffix.substr(1);
}
if (suffix.empty()) {
return;
}
- if (suffix[suffix.size() - 1] == '/') {
+ if (suffix.back() == '/') {
suffix = suffix.substr(0, suffix.size() - 1);
}
if (suffix.empty()) {
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 96de6ad..bf928fc 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -111,6 +111,8 @@ cmFindPackageCommand::cmFindPackageCommand()
this->SortOrder = None;
this->SortDirection = Asc;
this->AppendSearchPathGroups();
+
+ this->DeprecatedFindModules["Qt"] = cmPolicies::CMP0084;
}
void cmFindPackageCommand::AppendSearchPathGroups()
@@ -653,8 +655,31 @@ bool cmFindPackageCommand::FindModule(bool& found)
std::string module = "Find";
module += this->Name;
module += ".cmake";
- std::string mfile = this->Makefile->GetModulesFile(module.c_str());
+ bool system = false;
+ std::string mfile = this->Makefile->GetModulesFile(module.c_str(), system);
if (!mfile.empty()) {
+ if (system) {
+ auto it = this->DeprecatedFindModules.find(this->Name);
+ if (it != this->DeprecatedFindModules.end()) {
+ cmPolicies::PolicyStatus status =
+ this->Makefile->GetPolicyStatus(it->second);
+ switch (status) {
+ case cmPolicies::WARN: {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(it->second) << "\n";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ CM_FALLTHROUGH;
+ }
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ return true;
+ }
+ }
+ }
+
// Load the module we found, and set "<name>_FIND_MODULE" to true
// while inside it.
found = true;
@@ -1429,7 +1454,7 @@ void cmFindPackageCommand::FillPrefixesUserHints()
bool cmFindPackageCommand::SearchDirectory(std::string const& dir)
{
- assert(!dir.empty() && dir[dir.size() - 1] == '/');
+ assert(!dir.empty() && dir.back() == '/');
// Check each path suffix on this directory.
for (std::string const& s : this->SearchPathSuffixes) {
@@ -1447,7 +1472,7 @@ bool cmFindPackageCommand::SearchDirectory(std::string const& dir)
bool cmFindPackageCommand::CheckDirectory(std::string const& dir)
{
- assert(!dir.empty() && dir[dir.size() - 1] == '/');
+ assert(!dir.empty() && dir.back() == '/');
// Look for the file in this directory.
std::string d = dir.substr(0, dir.size() - 1);
@@ -2001,7 +2026,7 @@ private:
bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ assert(!prefix_in.empty() && prefix_in.back() == '/');
if (this->DebugMode) {
fprintf(stderr, "Checking prefix [%s]\n", prefix_in.c_str());
}
@@ -2157,7 +2182,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ assert(!prefix_in.empty() && prefix_in.back() == '/');
if (this->DebugMode) {
fprintf(stderr, "Checking framework prefix [%s]\n", prefix_in.c_str());
}
@@ -2218,7 +2243,7 @@ bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in)
bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ assert(!prefix_in.empty() && prefix_in.back() == '/');
if (this->DebugMode) {
fprintf(stderr, "Checking bundle prefix [%s]\n", prefix_in.c_str());
}
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index 48f17ef..05bad49 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -4,6 +4,7 @@
#define cmFindPackageCommand_h
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmPolicies.h"
#include "cm_kwiml.h"
#include <cstddef>
@@ -148,6 +149,8 @@ private:
};
std::map<std::string, OriginalDef> OriginalDefs;
+ std::map<std::string, cmPolicies::PolicyID> DeprecatedFindModules;
+
std::string Name;
std::string Variable;
std::string Version;
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 8d57441..56eb2bf 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -166,6 +166,18 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression()
return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL";
}
+bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression()
+{
+ const cmGeneratorExpressionDAGChecker* top = this;
+ const cmGeneratorExpressionDAGChecker* parent = this->Parent;
+ while (parent) {
+ top = parent;
+ parent = parent->Parent;
+ }
+
+ return top->Property == "INTERFACE_POSITION_INDEPENDENT_CODE";
+}
+
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
cmGeneratorTarget const* tgt)
{
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index a5134c3..1525c39 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -66,6 +66,7 @@ struct cmGeneratorExpressionDAGChecker
const std::string& expr);
bool EvaluatingGenexExpression();
+ bool EvaluatingPICExpression();
bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr);
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index f901215..49b97fb 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1225,7 +1225,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
const char* prop = target->GetProperty(propertyName);
if (dagCheckerParent) {
- if (dagCheckerParent->EvaluatingGenexExpression()) {
+ if (dagCheckerParent->EvaluatingGenexExpression() ||
+ dagCheckerParent->EvaluatingPICExpression()) {
// No check required.
} else if (dagCheckerParent->EvaluatingLinkLibraries()) {
#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 5c294f8..0b28d1e 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -439,7 +439,7 @@ static void handleSystemIncludesDep(
KindedSources const& kinded = this->GetKindedSources(config); \
for (SourceAndKind const& s : kinded.Sources) { \
if (s.Kind == KIND) { \
- data.push_back(s.Source); \
+ data.push_back(s.Source.Value); \
} \
} \
}
@@ -495,6 +495,36 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
return this->LocalGenerator->GetFeature(feature, config);
}
+const char* cmGeneratorTarget::GetLinkPIEProperty(
+ const std::string& config) const
+{
+ static std::string PICValue;
+
+ PICValue = this->GetLinkInterfaceDependentStringAsBoolProperty(
+ "POSITION_INDEPENDENT_CODE", config);
+
+ if (PICValue == "(unset)") {
+ // POSITION_INDEPENDENT_CODE is not set
+ return nullptr;
+ }
+
+ switch (this->GetPolicyStatusCMP0083()) {
+ case cmPolicies::WARN: {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0083);
+ this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ CM_FALLTHROUGH;
+ }
+ case cmPolicies::OLD:
+ return nullptr;
+ default:
+ // nothing to do
+ break;
+ }
+
+ return PICValue.c_str();
+}
+
bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
std::string const& config) const
{
@@ -674,13 +704,13 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
{
if (!this->UtilityItemsDone) {
this->UtilityItemsDone = true;
- std::set<std::string> const& utilities = this->GetUtilities();
- for (std::string const& i : utilities) {
+ std::set<BT<std::string>> const& utilities = this->GetUtilities();
+ for (BT<std::string> const& i : utilities) {
if (cmGeneratorTarget* gt =
- this->LocalGenerator->FindGeneratorTargetToUse(i)) {
- this->UtilityItems.insert(cmLinkItem(gt));
+ this->LocalGenerator->FindGeneratorTargetToUse(i.Value)) {
+ this->UtilityItems.insert(cmLinkItem(gt, i.Backtrace));
} else {
- this->UtilityItems.insert(cmLinkItem(i));
+ this->UtilityItems.insert(cmLinkItem(i.Value, i.Backtrace));
}
}
}
@@ -865,7 +895,8 @@ static void AddObjectEntries(
static bool processSources(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& srcs, std::unordered_set<std::string>& uniqueSrcs,
+ std::vector<BT<std::string>>& srcs,
+ std::unordered_set<std::string>& uniqueSrcs,
cmGeneratorExpressionDAGChecker* dagChecker, std::string const& config,
bool debugSources)
{
@@ -916,7 +947,7 @@ static bool processSources(
std::string usedSources;
for (std::string const& src : entrySources) {
if (uniqueSrcs.insert(src).second) {
- srcs.push_back(src);
+ srcs.emplace_back(src, entry->ge->GetBacktrace());
if (debugSources) {
usedSources += " * " + src + "\n";
}
@@ -933,9 +964,10 @@ static bool processSources(
return contextDependent;
}
-void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
- const std::string& config) const
+std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
+ std::string const& config) const
{
+ std::vector<BT<std::string>> files;
assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
@@ -951,13 +983,13 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
cmSystemTools::ExpandListArgument(entry, items);
for (std::string const& item : items) {
if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") &&
- item[item.size() - 1] == '>') {
+ item.back() == '>') {
continue;
}
files.push_back(item);
}
}
- return;
+ return files;
}
std::vector<std::string> debugProperties;
@@ -1009,11 +1041,23 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
cmDeleteAll(linkInterfaceSourcesEntries);
cmDeleteAll(linkObjectsEntries);
+ return files;
}
void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
const std::string& config) const
{
+ std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
+ files.reserve(tmp.size());
+ for (BT<cmSourceFile*>& v : tmp) {
+ files.push_back(v.Value);
+ }
+}
+
+std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
+ std::string const& config) const
+{
+ std::vector<BT<cmSourceFile*>> files;
if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
// Since we are still configuring not all sources may exist yet,
// so we need to avoid full source classification because that
@@ -1021,16 +1065,15 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
// Since this is only for compatibility with old policies that
// projects should not depend on anymore, just compute the files
// without memoizing them.
- std::vector<std::string> srcs;
- this->GetSourceFiles(srcs, config);
+ std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
std::set<cmSourceFile*> emitted;
- for (std::string const& s : srcs) {
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(s);
+ for (BT<std::string> const& s : srcs) {
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
if (emitted.insert(sf).second) {
- files.push_back(sf);
+ files.emplace_back(sf, s.Backtrace);
}
}
- return;
+ return files;
}
KindedSources const& kinded = this->GetKindedSources(config);
@@ -1038,18 +1081,33 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
for (SourceAndKind const& si : kinded.Sources) {
files.push_back(si.Source);
}
+ return files;
}
void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
std::vector<cmSourceFile*>& files, const std::string& config) const
{
+ std::vector<BT<cmSourceFile*>> tmp =
+ this->GetSourceFilesWithoutObjectLibraries(config);
+ files.reserve(tmp.size());
+ for (BT<cmSourceFile*>& v : tmp) {
+ files.push_back(v.Value);
+ }
+}
+
+std::vector<BT<cmSourceFile*>>
+cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
+ std::string const& config) const
+{
+ std::vector<BT<cmSourceFile*>> files;
KindedSources const& kinded = this->GetKindedSources(config);
files.reserve(kinded.Sources.size());
for (SourceAndKind const& si : kinded.Sources) {
- if (si.Source->GetObjectLibrary().empty()) {
+ if (si.Source.Value->GetObjectLibrary().empty()) {
files.push_back(si.Source);
}
}
+ return files;
}
cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
@@ -1089,16 +1147,15 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
std::string const& config) const
{
// Get the source file paths by string.
- std::vector<std::string> srcs;
- this->GetSourceFiles(srcs, config);
+ std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
std::vector<cmSourceFile*> badObjLib;
std::set<cmSourceFile*> emitted;
- for (std::string const& s : srcs) {
+ for (BT<std::string> const& s : srcs) {
// Create each source at most once.
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(s);
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
if (!emitted.insert(sf).second) {
continue;
}
@@ -1161,7 +1218,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
}
// Save this classified source file in the result vector.
- files.Sources.push_back({ sf, kind });
+ files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
}
if (!badObjLib.empty()) {
@@ -1197,14 +1254,14 @@ void cmGeneratorTarget::ComputeAllConfigSources() const
KindedSources const& sources = this->GetKindedSources(configs[ci]);
for (SourceAndKind const& src : sources.Sources) {
std::map<cmSourceFile const*, size_t>::iterator mi =
- index.find(src.Source);
+ index.find(src.Source.Value);
if (mi == index.end()) {
AllConfigSource acs;
- acs.Source = src.Source;
+ acs.Source = src.Source.Value;
acs.Kind = src.Kind;
this->AllConfigSources.push_back(std::move(acs));
std::map<cmSourceFile const*, size_t>::value_type entry(
- src.Source, this->AllConfigSources.size() - 1);
+ src.Source.Value, this->AllConfigSources.size() - 1);
mi = index.insert(entry).first;
}
this->AllConfigSources[mi->second].Configs.push_back(ci);
@@ -1710,17 +1767,11 @@ cmListFileBacktrace cmGeneratorTarget::GetBacktrace() const
return this->Target->GetBacktrace();
}
-const std::set<std::string>& cmGeneratorTarget::GetUtilities() const
+const std::set<BT<std::string>>& cmGeneratorTarget::GetUtilities() const
{
return this->Target->GetUtilities();
}
-const cmListFileBacktrace* cmGeneratorTarget::GetUtilityBacktrace(
- const std::string& u) const
-{
- return this->Target->GetUtilityBacktrace(u);
-}
-
bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const
{
return this->GetType() == cmStateEnums::STATIC_LIBRARY ||
@@ -1730,7 +1781,7 @@ bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const
this->GetType() == cmStateEnums::EXECUTABLE;
}
-const char* cmGeneratorTarget::GetExportMacro() const
+const std::string* cmGeneratorTarget::GetExportMacro() const
{
// Define the symbol for targets that export symbols.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
@@ -1743,7 +1794,7 @@ const char* cmGeneratorTarget::GetExportMacro() const
in += "_EXPORTS";
this->ExportMacro = cmSystemTools::MakeCidentifier(in);
}
- return this->ExportMacro.c_str();
+ return &this->ExportMacro;
}
return nullptr;
}
@@ -2480,7 +2531,7 @@ std::string cmGeneratorTarget::GetCreateRuleVariable(
static void processIncludeDirectories(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& includes,
+ std::vector<BT<std::string>>& includes,
std::unordered_set<std::string>& uniqueIncludes,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugIncludes, const std::string& language)
@@ -2572,7 +2623,7 @@ static void processIncludeDirectories(
std::string inc = entryInclude;
if (uniqueIncludes.insert(inc).second) {
- includes.push_back(inc);
+ includes.emplace_back(inc, entry->ge->GetBacktrace());
if (debugIncludes) {
usedIncludes += " * " + inc + "\n";
}
@@ -2588,10 +2639,10 @@ static void processIncludeDirectories(
}
}
-std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
+std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
const std::string& config, const std::string& lang) const
{
- std::vector<std::string> includes;
+ std::vector<BT<std::string>> includes;
std::unordered_set<std::string> uniqueIncludes;
cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
@@ -2661,7 +2712,7 @@ enum class OptionsParse
static void processOptionsInternal(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
+ std::vector<BT<std::string>>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugOptions, const char* logName, std::string const& language,
@@ -2678,9 +2729,13 @@ static void processOptionsInternal(
if (uniqueOptions.insert(opt).second) {
if (parse == OptionsParse::Shell &&
cmHasLiteralPrefix(opt, "SHELL:")) {
- cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, options);
+ std::vector<std::string> tmp;
+ cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp);
+ for (std::string& o : tmp) {
+ options.emplace_back(std::move(o), entry->ge->GetBacktrace());
+ }
} else {
- options.push_back(opt);
+ options.emplace_back(opt, entry->ge->GetBacktrace());
}
if (debugOptions) {
usedOptions += " * " + opt + "\n";
@@ -2700,7 +2755,7 @@ static void processOptionsInternal(
static void processCompileOptions(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
+ std::vector<BT<std::string>>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugOptions, std::string const& language)
@@ -2714,6 +2769,17 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const
{
+ std::vector<BT<std::string>> tmp = this->GetCompileOptions(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
@@ -2749,12 +2815,13 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
language);
cmDeleteAll(linkInterfaceCompileOptionsEntries);
+ return result;
}
static void processCompileFeatures(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
+ std::vector<BT<std::string>>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugOptions)
@@ -2767,6 +2834,17 @@ static void processCompileFeatures(
void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
const std::string& config) const
{
+ std::vector<BT<std::string>> tmp = this->GetCompileFeatures(config);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures(
+ std::string const& config) const
+{
+ std::vector<BT<std::string>> result;
std::unordered_set<std::string> uniqueFeatures;
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
@@ -2799,12 +2877,13 @@ void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
uniqueFeatures, &dagChecker, config, debugFeatures);
cmDeleteAll(linkInterfaceCompileFeaturesEntries);
+ return result;
}
static void processCompileDefinitions(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
+ std::vector<BT<std::string>>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugOptions, std::string const& language)
@@ -2815,9 +2894,21 @@ static void processCompileDefinitions(
}
void cmGeneratorTarget::GetCompileDefinitions(
- std::vector<std::string>& list, const std::string& config,
+ std::vector<std::string>& result, const std::string& config,
const std::string& language) const
{
+ std::vector<BT<std::string>> tmp =
+ this->GetCompileDefinitions(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> list;
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
@@ -2878,13 +2969,14 @@ void cmGeneratorTarget::GetCompileDefinitions(
language);
cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
+ return list;
}
namespace {
void processLinkOptions(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
+ std::vector<BT<std::string>>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugOptions, std::string const& language)
@@ -2899,6 +2991,17 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const
{
+ std::vector<BT<std::string>> tmp = this->GetLinkOptions(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
@@ -2952,21 +3055,24 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
const std::string SHELL{ "SHELL:" };
const std::string LINKER_SHELL = LINKER + SHELL;
- std::vector<std::string>::iterator entry;
+ std::vector<BT<std::string>>::iterator entry;
while ((entry = std::find_if(result.begin(), result.end(),
- [&LINKER](const std::string& item) -> bool {
- return item.compare(0, LINKER.length(),
- LINKER) == 0;
+ [&LINKER](BT<std::string> const& item) -> bool {
+ return item.Value.compare(0, LINKER.length(),
+ LINKER) == 0;
})) != result.end()) {
+ std::string value = std::move(entry->Value);
+ cmListFileBacktrace bt = std::move(entry->Backtrace);
+ entry = result.erase(entry);
+
std::vector<std::string> linkerOptions;
- if (entry->compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) {
+ if (value.compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) {
cmSystemTools::ParseUnixCommandLine(
- entry->c_str() + LINKER_SHELL.length(), linkerOptions);
+ value.c_str() + LINKER_SHELL.length(), linkerOptions);
} else {
linkerOptions =
- cmSystemTools::tokenize(entry->substr(LINKER.length()), ",");
+ cmSystemTools::tokenize(value.substr(LINKER.length()), ",");
}
- entry = result.erase(entry);
if (linkerOptions.empty() ||
(linkerOptions.size() == 1 && linkerOptions.front().empty())) {
@@ -2982,56 +3088,64 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
cmake::FATAL_ERROR,
"'SHELL:' prefix is not supported as part of 'LINKER:' arguments.",
this->GetBacktrace());
- return;
+ return result;
}
+ std::vector<BT<std::string>> options;
if (wrapperFlag.empty()) {
// nothing specified, insert elements as is
- result.insert(entry, linkerOptions.begin(), linkerOptions.end());
+ options.reserve(linkerOptions.size());
+ for (std::string& o : linkerOptions) {
+ options.emplace_back(std::move(o), bt);
+ }
} else {
- std::vector<std::string> options;
-
if (!wrapperSep.empty()) {
if (concatFlagAndArgs) {
// insert flag elements except last one
- options.insert(options.end(), wrapperFlag.begin(),
- wrapperFlag.end() - 1);
+ for (auto i = wrapperFlag.begin(); i != wrapperFlag.end() - 1; ++i) {
+ options.emplace_back(*i, bt);
+ }
// concatenate last flag element and all LINKER list values
// in one option
- options.push_back(wrapperFlag.back() +
- cmJoin(linkerOptions, wrapperSep));
+ options.emplace_back(
+ wrapperFlag.back() + cmJoin(linkerOptions, wrapperSep), bt);
} else {
- options.insert(options.end(), wrapperFlag.begin(),
- wrapperFlag.end());
+ for (std::string const& i : wrapperFlag) {
+ options.emplace_back(i, bt);
+ }
// concatenate all LINKER list values in one option
- options.push_back(cmJoin(linkerOptions, wrapperSep));
+ options.emplace_back(cmJoin(linkerOptions, wrapperSep), bt);
}
} else {
// prefix each element of LINKER list with wrapper
if (concatFlagAndArgs) {
- std::transform(
- linkerOptions.begin(), linkerOptions.end(), linkerOptions.begin(),
- [&wrapperFlag](const std::string& value) -> std::string {
- return wrapperFlag.back() + value;
- });
+ std::transform(linkerOptions.begin(), linkerOptions.end(),
+ linkerOptions.begin(),
+ [&wrapperFlag](std::string const& o) -> std::string {
+ return wrapperFlag.back() + o;
+ });
}
- for (const auto& value : linkerOptions) {
- options.insert(options.end(), wrapperFlag.begin(),
- concatFlagAndArgs ? wrapperFlag.end() - 1
- : wrapperFlag.end());
- options.push_back(value);
+ for (std::string& o : linkerOptions) {
+ for (auto i = wrapperFlag.begin(),
+ e = concatFlagAndArgs ? wrapperFlag.end() - 1
+ : wrapperFlag.end();
+ i != e; ++i) {
+ options.emplace_back(*i, bt);
+ }
+ options.emplace_back(std::move(o), bt);
}
}
- result.insert(entry, options.begin(), options.end());
}
+ result.insert(entry, options.begin(), options.end());
}
+ return result;
}
namespace {
void processStaticLibraryLinkOptions(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
+ std::vector<BT<std::string>>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
std::string const& language)
@@ -3046,6 +3160,18 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions(
std::vector<std::string>& result, const std::string& config,
const std::string& language) const
{
+ std::vector<BT<std::string>> tmp =
+ this->GetStaticLibraryLinkOptions(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries;
std::unordered_set<std::string> uniqueOptions;
@@ -3066,13 +3192,14 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions(
&dagChecker, config, language);
cmDeleteAll(entries);
+ return result;
}
namespace {
void processLinkDirectories(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& directories,
+ std::vector<BT<std::string>>& directories,
std::unordered_set<std::string>& uniqueDirectories,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugDirectories, std::string const& language)
@@ -3151,6 +3278,18 @@ void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const
{
+ std::vector<BT<std::string>> tmp =
+ this->GetLinkDirectories(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
std::unordered_set<std::string> uniqueDirectories;
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr,
@@ -3186,13 +3325,14 @@ void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
debugDirectories, language);
cmDeleteAll(linkInterfaceLinkDirectoriesEntries);
+ return result;
}
namespace {
void processLinkDepends(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
+ std::vector<BT<std::string>>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
std::string const& language)
@@ -3207,6 +3347,17 @@ void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const
{
+ std::vector<BT<std::string>> tmp = this->GetLinkDepends(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries;
std::unordered_set<std::string> uniqueOptions;
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
@@ -3228,6 +3379,7 @@ void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
&dagChecker, config, language);
cmDeleteAll(linkDependsEntries);
+ return result;
}
void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
@@ -3293,10 +3445,9 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
{
- std::vector<std::string> features;
- this->GetCompileFeatures(features, config);
- for (std::string const& f : features) {
- if (!this->Makefile->AddRequiredTargetFeature(this->Target, f)) {
+ std::vector<BT<std::string>> features = this->GetCompileFeatures(config);
+ for (BT<std::string> const& f : features) {
+ if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) {
return false;
}
}
@@ -4116,6 +4267,29 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
}
}
+template <typename PropertyType>
+std::string valueAsString(PropertyType);
+template <>
+std::string valueAsString<bool>(bool value)
+{
+ return value ? "TRUE" : "FALSE";
+}
+template <>
+std::string valueAsString<const char*>(const char* value)
+{
+ return value ? value : "(unset)";
+}
+template <>
+std::string valueAsString<std::string>(std::string value)
+{
+ return value;
+}
+template <>
+std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
+{
+ return "(unset)";
+}
+
std::string compatibilityType(CompatibleType t)
{
switch (t) {
@@ -4147,34 +4321,49 @@ std::string compatibilityAgree(CompatibleType t, bool dominant)
}
template <typename PropertyType>
-PropertyType getTypedProperty(cmGeneratorTarget const* tgt,
- const std::string& prop);
+PropertyType getTypedProperty(
+ cmGeneratorTarget const* tgt, const std::string& prop,
+ cmGeneratorExpressionInterpreter* genexInterpreter = nullptr);
template <>
bool getTypedProperty<bool>(cmGeneratorTarget const* tgt,
- const std::string& prop)
+ const std::string& prop,
+ cmGeneratorExpressionInterpreter* genexInterpreter)
{
- return tgt->GetPropertyAsBool(prop);
-}
+ if (genexInterpreter == nullptr) {
+ return tgt->GetPropertyAsBool(prop);
+ }
-template <>
-const char* getTypedProperty<const char*>(cmGeneratorTarget const* tgt,
- const std::string& prop)
-{
- return tgt->GetProperty(prop);
+ const char* value = tgt->GetProperty(prop);
+ return cmSystemTools::IsOn(genexInterpreter->Evaluate(value, prop));
}
-template <typename PropertyType>
-std::string valueAsString(PropertyType);
template <>
-std::string valueAsString<bool>(bool value)
+const char* getTypedProperty<const char*>(
+ cmGeneratorTarget const* tgt, const std::string& prop,
+ cmGeneratorExpressionInterpreter* genexInterpreter)
{
- return value ? "TRUE" : "FALSE";
+ const char* value = tgt->GetProperty(prop);
+
+ if (genexInterpreter == nullptr) {
+ return value;
+ }
+
+ return genexInterpreter->Evaluate(value, prop).c_str();
}
+
template <>
-std::string valueAsString<const char*>(const char* value)
+std::string getTypedProperty<std::string>(
+ cmGeneratorTarget const* tgt, const std::string& prop,
+ cmGeneratorExpressionInterpreter* genexInterpreter)
{
- return value ? value : "(unset)";
+ const char* value = tgt->GetProperty(prop);
+
+ if (genexInterpreter == nullptr) {
+ return valueAsString(value);
+ }
+
+ return genexInterpreter->Evaluate(value, prop);
}
template <typename PropertyType>
@@ -4189,6 +4378,12 @@ const char* impliedValue<const char*>(const char* /*unused*/)
{
return "";
}
+template <>
+std::string impliedValue<std::string>(
+ std::string /*unused*/) // NOLINT(clang-tidy)
+{
+ return std::string();
+}
template <typename PropertyType>
std::pair<bool, PropertyType> consistentProperty(PropertyType lhs,
@@ -4209,6 +4404,13 @@ std::pair<bool, const char*> consistentStringProperty(const char* lhs,
return std::make_pair(b, b ? lhs : nullptr);
}
+std::pair<bool, std::string> consistentStringProperty(const std::string& lhs,
+ const std::string& rhs)
+{
+ const bool b = lhs == rhs;
+ return std::make_pair(b, b ? lhs : valueAsString(nullptr));
+}
+
std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
const char* rhs,
CompatibleType t)
@@ -4251,9 +4453,10 @@ std::pair<bool, const char*> consistentProperty(const char* lhs,
const char* const null_ptr = nullptr;
switch (t) {
- case BoolType:
- assert(false && "consistentProperty for strings called with BoolType");
- return std::pair<bool, const char*>(false, null_ptr);
+ case BoolType: {
+ bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs);
+ return std::make_pair(same, same ? lhs : nullptr);
+ }
case StringType:
return consistentStringProperty(lhs, rhs);
case NumberMinType:
@@ -4264,6 +4467,40 @@ std::pair<bool, const char*> consistentProperty(const char* lhs,
return std::pair<bool, const char*>(false, null_ptr);
}
+std::pair<bool, std::string> consistentProperty(const std::string& lhs,
+ const std::string& rhs,
+ CompatibleType t)
+{
+ const std::string null_ptr = valueAsString(nullptr);
+
+ if (lhs == null_ptr && rhs == null_ptr) {
+ return std::make_pair(true, lhs);
+ }
+ if (lhs == null_ptr) {
+ return std::make_pair(true, rhs);
+ }
+ if (rhs == null_ptr) {
+ return std::make_pair(true, lhs);
+ }
+
+ switch (t) {
+ case BoolType: {
+ bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs);
+ return std::make_pair(same, same ? lhs : null_ptr);
+ }
+ case StringType:
+ return consistentStringProperty(lhs, rhs);
+ case NumberMinType:
+ case NumberMaxType: {
+ auto value = consistentNumberProperty(lhs.c_str(), rhs.c_str(), t);
+ return std::make_pair(
+ value.first, value.first ? std::string(value.second) : null_ptr);
+ }
+ }
+ assert(false && "Unreachable!");
+ return std::pair<bool, std::string>(false, null_ptr);
+}
+
template <typename PropertyType>
PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
const std::string& p,
@@ -4273,6 +4510,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
PropertyType* /*unused*/)
{
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p);
+
std::vector<std::string> headPropKeys = tgt->GetPropertyKeys();
const bool explicitlySet =
std::find(headPropKeys.begin(), headPropKeys.end(), p) !=
@@ -4302,6 +4540,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
}
std::string interfaceProperty = "INTERFACE_" + p;
+ std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter(
+ p == "POSITION_INDEPENDENT_CODE" ? new cmGeneratorExpressionInterpreter(
+ tgt->GetLocalGenerator(), config, tgt)
+ : nullptr);
+
for (cmGeneratorTarget const* theTarget : deps) {
// An error should be reported if one dependency
// has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
@@ -4313,8 +4556,8 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
const bool ifaceIsSet = std::find(propKeys.begin(), propKeys.end(),
interfaceProperty) != propKeys.end();
- PropertyType ifacePropContent =
- getTypedProperty<PropertyType>(theTarget, interfaceProperty);
+ PropertyType ifacePropContent = getTypedProperty<PropertyType>(
+ theTarget, interfaceProperty, genexInterpreter.get());
std::string reportEntry;
if (ifaceIsSet) {
@@ -4412,6 +4655,13 @@ bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty(
BoolType, nullptr);
}
+std::string cmGeneratorTarget::GetLinkInterfaceDependentStringAsBoolProperty(
+ const std::string& p, const std::string& config) const
+{
+ return checkInterfacePropertyCompatibility<std::string>(
+ this, p, config, "FALSE", BoolType, nullptr);
+}
+
const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty(
const std::string& p, const std::string& config) const
{
@@ -4618,6 +4868,7 @@ void cmGeneratorTarget::ReportPropertyOrigin(
}
void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
+ cmListFileBacktrace const& bt,
std::vector<cmLinkItem>& items) const
{
for (std::string const& n : names) {
@@ -4625,7 +4876,7 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
if (name == this->GetName() || name.empty()) {
continue;
}
- items.push_back(this->ResolveLinkItem(name));
+ items.push_back(this->ResolveLinkItem(name, bt));
}
}
@@ -4647,7 +4898,7 @@ void cmGeneratorTarget::ExpandLinkItems(
false, headTarget, this,
&dagChecker),
libs);
- this->LookupLinkItems(libs, items);
+ this->LookupLinkItems(libs, cge->GetBacktrace(), items);
hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
}
@@ -5200,7 +5451,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
iface.HadHeadSensitiveCondition);
std::vector<std::string> deps;
cmSystemTools::ExpandListArgument(info->SharedDeps, deps);
- this->LookupLinkItems(deps, iface.SharedDeps);
+ this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps);
}
return &iface;
@@ -5490,8 +5741,7 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026(
std::vector<std::string> files;
cmSystemTools::ExpandListArgument(entry, files);
for (std::string const& li : files) {
- if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") &&
- li[li.size() - 1] == '>') {
+ if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') {
std::string objLibName = li.substr(17, li.size() - 18);
if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
@@ -5739,7 +5989,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
}
// The entry is meant for this configuration.
- impl.Libraries.emplace_back(this->ResolveLinkItem(name), *btIt,
+ impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt),
evaluated != *le);
}
@@ -5767,7 +6017,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
continue;
}
// Support OLD behavior for CMP0003.
- impl.WrongConfigLibraries.push_back(this->ResolveLinkItem(name));
+ impl.WrongConfigLibraries.push_back(
+ this->ResolveLinkItem(name, cmListFileBacktrace()));
}
}
}
@@ -5814,12 +6065,13 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference(
return resolved;
}
-cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const
+cmLinkItem cmGeneratorTarget::ResolveLinkItem(
+ std::string const& name, cmListFileBacktrace const& bt) const
{
TargetOrString resolved = this->ResolveTargetReference(name);
if (!resolved.Target) {
- return cmLinkItem(resolved.String);
+ return cmLinkItem(resolved.String, bt);
}
// Skip targets that will not really be linked. This is probably a
@@ -5827,10 +6079,10 @@ cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const
// within the project.
if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE &&
!resolved.Target->IsExecutableWithExports()) {
- return cmLinkItem(resolved.Target->GetName());
+ return cmLinkItem(resolved.Target->GetName(), bt);
}
- return cmLinkItem(resolved.Target);
+ return cmLinkItem(resolved.Target, bt);
}
std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 5ed8e5a..52defee 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -75,8 +75,8 @@ public:
bool GetPropertyAsBool(const std::string& prop) const;
void GetSourceFiles(std::vector<cmSourceFile*>& files,
const std::string& config) const;
- void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files,
- const std::string& config) const;
+ std::vector<BT<cmSourceFile*>> GetSourceFiles(
+ std::string const& config) const;
/** Source file kinds (classifications).
Generators use this to decide how to treat a source file. */
@@ -99,7 +99,7 @@ public:
/** A source file paired with a kind (classification). */
struct SourceAndKind
{
- cmSourceFile* Source;
+ BT<cmSourceFile*> Source;
SourceKind Kind;
};
@@ -173,6 +173,8 @@ public:
const char* GetFeature(const std::string& feature,
const std::string& config) const;
+ const char* GetLinkPIEProperty(const std::string& config) const;
+
bool IsIPOEnabled(std::string const& lang, std::string const& config) const;
bool IsLinkInterfaceDependentBoolProperty(const std::string& p,
@@ -273,8 +275,7 @@ public:
cmListFileBacktrace GetBacktrace() const;
- std::set<std::string> const& GetUtilities() const;
- cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const;
+ std::set<BT<std::string>> const& GetUtilities() const;
bool LinkLanguagePropagatesToDependents() const
{
@@ -283,7 +284,7 @@ public:
/** Get the macro to define when building sources in this target.
If no macro should be defined null is returned. */
- const char* GetExportMacro() const;
+ const std::string* GetExportMacro() const;
/** Get the soname of the target. Allowed only for a shared library. */
std::string GetSOName(const std::string& config) const;
@@ -362,7 +363,8 @@ public:
};
TargetOrString ResolveTargetReference(std::string const& name) const;
- cmLinkItem ResolveLinkItem(std::string const& name) const;
+ cmLinkItem ResolveLinkItem(std::string const& name,
+ cmListFileBacktrace const& bt) const;
// Compute the set of languages compiled by the target. This is
// computed every time it is called because the languages can change
@@ -408,34 +410,49 @@ public:
std::string const& config) const;
/** Get the include directories for this target. */
- std::vector<std::string> GetIncludeDirectories(
+ std::vector<BT<std::string>> GetIncludeDirectories(
const std::string& config, const std::string& lang) const;
void GetCompileOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
+ std::vector<BT<std::string>> GetCompileOptions(
+ std::string const& config, std::string const& language) const;
void GetCompileFeatures(std::vector<std::string>& features,
const std::string& config) const;
+ std::vector<BT<std::string>> GetCompileFeatures(
+ std::string const& config) const;
void GetCompileDefinitions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
+ std::vector<BT<std::string>> GetCompileDefinitions(
+ std::string const& config, std::string const& language) const;
void GetLinkOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
+ std::vector<BT<std::string>> GetLinkOptions(
+ std::string const& config, std::string const& language) const;
+
void GetStaticLibraryLinkOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
+ std::vector<BT<std::string>> GetStaticLibraryLinkOptions(
+ std::string const& config, std::string const& language) const;
void GetLinkDirectories(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
+ std::vector<BT<std::string>> GetLinkDirectories(
+ std::string const& config, std::string const& language) const;
void GetLinkDepends(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
+ std::vector<BT<std::string>> GetLinkDepends(
+ std::string const& config, std::string const& language) const;
bool IsSystemIncludeDirectory(const std::string& dir,
const std::string& config,
@@ -774,6 +791,9 @@ private:
cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceUsageRequirementsMap(
std::string const& config) const;
+ std::string GetLinkInterfaceDependentStringAsBoolProperty(
+ const std::string& p, const std::string& config) const;
+
// Cache import information from properties for each configuration.
struct ImportInfo
{
@@ -834,10 +854,15 @@ private:
std::vector<cmLinkItem>& items,
bool& hadHeadSensitiveCondition) const;
void LookupLinkItems(std::vector<std::string> const& names,
+ cmListFileBacktrace const& bt,
std::vector<cmLinkItem>& items) const;
- void GetSourceFiles(std::vector<std::string>& files,
- const std::string& config) const;
+ std::vector<BT<std::string>> GetSourceFilePaths(
+ std::string const& config) const;
+ std::vector<BT<cmSourceFile*>> GetSourceFilesWithoutObjectLibraries(
+ std::string const& config) const;
+ void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files,
+ const std::string& config) const;
struct HeadToLinkImplementationMap
: public std::map<cmGeneratorTarget const*, cmOptionalLinkImplementation>
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index 1b358ab..ffb895e 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -19,8 +19,8 @@ bool cmGetFilenameComponentCommand::InitialPass(
// Check and see if the value has been stored in the cache
// already, if so use that value
- if (args.size() >= 4 && args[args.size() - 1] == "CACHE") {
- const char* cacheValue = this->Makefile->GetDefinition(args[0]);
+ if (args.size() >= 4 && args.back() == "CACHE") {
+ const char* cacheValue = this->Makefile->GetDefinition(args.front());
if (cacheValue && !cmSystemTools::IsNOTFOUND(cacheValue)) {
return true;
}
@@ -113,20 +113,20 @@ bool cmGetFilenameComponentCommand::InitialPass(
return false;
}
- if (args.size() >= 4 && args[args.size() - 1] == "CACHE") {
+ if (args.size() >= 4 && args.back() == "CACHE") {
if (!programArgs.empty() && !storeArgs.empty()) {
this->Makefile->AddCacheDefinition(
storeArgs, programArgs.c_str(), "",
args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
}
this->Makefile->AddCacheDefinition(
- args[0], result.c_str(), "",
+ args.front(), result.c_str(), "",
args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
} else {
if (!programArgs.empty() && !storeArgs.empty()) {
this->Makefile->AddDefinition(storeArgs, programArgs.c_str());
}
- this->Makefile->AddDefinition(args[0], result.c_str());
+ this->Makefile->AddDefinition(args.front(), result.c_str());
}
return true;
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 847230a..4d98d55 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -267,14 +267,9 @@ std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language,
if (i == this->DefinesByLanguage.end()) {
std::set<std::string> defines;
const char* lang = language.c_str();
- // Add the export symbol definition for shared library objects.
- if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
- this->LocalGenerator->AppendDefines(defines, exportMacro);
- }
-
// Add preprocessor definitions for this target and configuration.
- this->LocalGenerator->AddCompileDefinitions(defines, this->GeneratorTarget,
- config, language);
+ this->LocalGenerator->GetTargetDefines(this->GeneratorTarget, config,
+ language, defines);
std::string definesString;
this->LocalGenerator->JoinDefines(defines, definesString, lang);
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 71e844e..2805395 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -34,8 +34,6 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmQtAutoGen.h"
-#include "cmQtAutoGenInitializer.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -46,6 +44,7 @@
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmCryptoHash.h"
+# include "cmQtAutoGenGlobalInitializer.h"
# include "cm_jsoncpp_value.h"
# include "cm_jsoncpp_writer.h"
#endif
@@ -1469,64 +1468,11 @@ bool cmGlobalGenerator::ComputeTargetDepends()
bool cmGlobalGenerator::QtAutoGen()
{
#ifdef CMAKE_BUILD_WITH_CMAKE
- std::vector<std::unique_ptr<cmQtAutoGenInitializer>> autogenInits;
-
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
- const std::vector<cmGeneratorTarget*>& targets =
- localGen->GetGeneratorTargets();
- // Find targets that require AUTOGEN processing
- for (cmGeneratorTarget* target : targets) {
- if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
- continue;
- }
- if (target->GetType() != cmStateEnums::EXECUTABLE &&
- target->GetType() != cmStateEnums::STATIC_LIBRARY &&
- target->GetType() != cmStateEnums::SHARED_LIBRARY &&
- target->GetType() != cmStateEnums::MODULE_LIBRARY &&
- target->GetType() != cmStateEnums::OBJECT_LIBRARY) {
- continue;
- }
- if (target->IsImported()) {
- continue;
- }
-
- const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
- const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
- const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
- if (!mocEnabled && !uicEnabled && !rccEnabled) {
- continue;
- }
-
- auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target);
- // don't do anything if there is no Qt4 or Qt5Core (which contains moc)
- if (qtVersion.Major != 4 && qtVersion.Major != 5) {
- continue;
- }
-
- autogenInits.emplace_back(cm::make_unique<cmQtAutoGenInitializer>(
- target, mocEnabled, uicEnabled, rccEnabled, qtVersion));
- }
- }
-
- if (!autogenInits.empty()) {
- // Initialize custom targets
- for (auto& autoGen : autogenInits) {
- if (!autoGen->InitCustomTargets()) {
- return false;
- }
- }
-
- // Setup custom targets
- for (auto& autoGen : autogenInits) {
- if (!autoGen->SetupCustomTargets()) {
- return false;
- }
- autoGen.reset(nullptr);
- }
- }
-#endif
-
+ cmQtAutoGenGlobalInitializer initializer(this->LocalGenerators);
+ return initializer.generate();
+#else
return true;
+#endif
}
cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
@@ -2265,7 +2211,7 @@ bool cmGlobalGenerator::NameResolvesToFramework(
inline std::string removeQuotes(const std::string& s)
{
- if (s[0] == '\"' && s[s.size() - 1] == '\"') {
+ if (s.front() == '\"' && s.back() == '\"') {
return s.substr(1, s.size() - 2);
}
return s;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index f513403..fbc756c 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -19,6 +19,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
@@ -837,7 +838,7 @@ static void EnsureTrailingSlash(std::string& path)
if (path.empty()) {
return;
}
- std::string::value_type last = path[path.size() - 1];
+ std::string::value_type last = path.back();
#ifdef _WIN32
if (last != '\\') {
path += '\\';
@@ -1008,10 +1009,11 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
{
if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
// These depend only on other CMake-provided targets, e.g. "all".
- std::set<std::string> const& utils = target->GetUtilities();
- for (std::string const& util : utils) {
+ std::set<BT<std::string>> const& utils = target->GetUtilities();
+ for (BT<std::string> const& util : utils) {
std::string d =
- target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + util;
+ target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" +
+ util.Value;
outputs.push_back(this->ConvertToNinjaPath(d));
}
} else {
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index ba12fac..3be09b0 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -159,7 +159,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends(
// executables to the libraries it uses are also done here
void cmGlobalVisualStudio71Generator::WriteExternalProject(
std::ostream& fout, const std::string& name, const char* location,
- const char* typeGuid, const std::set<std::string>& depends)
+ const char* typeGuid, const std::set<BT<std::string>>& depends)
{
fout << "Project(\"{"
<< (typeGuid ? typeGuid : this->ExternalProjectType(location))
@@ -171,9 +171,10 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject(
// project instead of in the global section
if (!depends.empty()) {
fout << "\tProjectSection(ProjectDependencies) = postProject\n";
- for (std::string const& it : depends) {
- if (!it.empty()) {
- fout << "\t\t{" << this->GetGUID(it) << "} = {" << this->GetGUID(it)
+ for (BT<std::string> const& it : depends) {
+ std::string const& dep = it.Value;
+ if (!dep.empty()) {
+ fout << "\t\t{" << this->GetGUID(dep) << "} = {" << this->GetGUID(dep)
<< "}\n";
}
}
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 054c342..b6e3131 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -33,7 +33,7 @@ protected:
const std::string& platformMapping = "") override;
void WriteExternalProject(std::ostream& fout, const std::string& name,
const char* path, const char* typeGuid,
- const std::set<std::string>& depends) override;
+ const std::set<BT<std::string>>& depends) override;
void WriteSLNHeader(std::ostream& fout) override;
// Folders are not supported by VS 7.1.
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 0c9dd88..251478d 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -145,7 +145,7 @@ protected:
virtual void WriteExternalProject(
std::ostream& fout, const std::string& name, const char* path,
- const char* typeGuid, const std::set<std::string>& dependencies) = 0;
+ const char* typeGuid, const std::set<BT<std::string>>& dependencies) = 0;
std::string ConvertToSolutionPath(const char* path);
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index ba138c2..b155d9c 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -315,9 +315,9 @@ bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies(
cmGeneratorTarget* target)
{
// Look for utility dependencies that magically link.
- for (std::string const& ui : target->GetUtilities()) {
+ for (BT<std::string> const& ui : target->GetUtilities()) {
if (cmGeneratorTarget* depTarget =
- target->GetLocalGenerator()->FindGeneratorTargetToUse(ui)) {
+ target->GetLocalGenerator()->FindGeneratorTargetToUse(ui.Value)) {
if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
depTarget->GetProperty("EXTERNAL_MSPROJECT")) {
// This utility dependency names an external .vcproj target.
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index e353a37..8a38f9b 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -546,7 +546,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
target->GetType() == cmStateEnums::STATIC_LIBRARY ||
target->GetType() == cmStateEnums::SHARED_LIBRARY ||
target->GetType() == cmStateEnums::MODULE_LIBRARY))) {
- makeHelper[makeHelper.size() - 1] = // fill placeholder
+ makeHelper.back() = // fill placeholder
this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)");
cmCustomCommandLines commandLines;
commandLines.push_back(makeHelper);
@@ -1755,6 +1755,26 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
}
}
+void cmGlobalXCodeGenerator::AddPositionIndependentLinkAttribute(
+ cmGeneratorTarget* target, cmXCodeObject* buildSettings,
+ const std::string& configName)
+{
+ // For now, only EXECUTABLE is concerned
+ if (target->GetType() != cmStateEnums::EXECUTABLE) {
+ return;
+ }
+
+ const char* PICValue = target->GetLinkPIEProperty(configName);
+ if (PICValue == nullptr) {
+ // POSITION_INDEPENDENT_CODE is not set
+ return;
+ }
+
+ buildSettings->AddAttribute(
+ "LD_NO_PIE",
+ this->CreateString(cmSystemTools::IsOn(PICValue) ? "NO" : "YES"));
+}
+
void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
const std::string& configName)
@@ -1806,6 +1826,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue));
}
+ // Handle PIE linker configuration
+ this->AddPositionIndependentLinkAttribute(gtgt, buildSettings, configName);
+
// Add define flags
this->CurrentLocalGenerator->AppendFlags(
defFlags, this->CurrentMakefile->GetDefineFlags());
@@ -1814,9 +1837,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
BuildObjectListOrString ppDefs(this, true);
this->AppendDefines(
ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
- if (const char* exportMacro = gtgt->GetExportMacro()) {
+ if (const std::string* exportMacro = gtgt->GetExportMacro()) {
// Add the export symbol definition for shared library objects.
- this->AppendDefines(ppDefs, exportMacro);
+ this->AppendDefines(ppDefs, exportMacro->c_str());
}
std::vector<std::string> targetDefines;
if (!langForPreprocessor.empty()) {
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 62f7030..9b0d4fe 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -171,6 +171,9 @@ private:
const std::string& configName);
cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt);
void AddDependAndLinkInformation(cmXCodeObject* target);
+ void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
+ cmXCodeObject* buildSettings,
+ const std::string& configName);
void CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
const std::string& buildType);
diff --git a/Source/cmGraphAdjacencyList.h b/Source/cmGraphAdjacencyList.h
index 6a0a799..fb2eee2 100644
--- a/Source/cmGraphAdjacencyList.h
+++ b/Source/cmGraphAdjacencyList.h
@@ -5,6 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmListFileCache.h"
+
#include <vector>
/**
@@ -15,18 +17,22 @@
class cmGraphEdge
{
public:
- cmGraphEdge(int n = 0, bool s = true)
+ cmGraphEdge(int n, bool s, cmListFileBacktrace const& bt)
: Dest(n)
, Strong(s)
+ , Backtrace(bt)
{
}
operator int() const { return this->Dest; }
bool IsStrong() const { return this->Strong; }
+ cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+
private:
int Dest;
bool Strong;
+ cmListFileBacktrace Backtrace;
};
struct cmGraphEdgeList : public std::vector<cmGraphEdge>
{
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index fcdf03f..754fa7d 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -68,7 +68,7 @@ const char* getShapeForTarget(const cmGeneratorTarget* target)
}
std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget(
- cmTarget* Target)
+ cmTarget* Target, const cmGlobalGenerator* globalGenerator)
{
char sep = ';';
std::map<std::string, LinkLibraryScopeType> tokens;
@@ -95,6 +95,13 @@ std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget(
}
std::string element = interfaceLinkLibraries.substr(start, end - start);
+ if (globalGenerator->IsAlias(element)) {
+ const auto tgt = globalGenerator->FindTarget(element);
+ if (tgt) {
+ element = tgt->GetName();
+ }
+ }
+
if (std::string::npos == element.find("$<LINK_ONLY:", 0)) {
// we assume first, that this library is an interface library.
// if we find it again in the linklibraries property, we promote it to an
@@ -116,6 +123,12 @@ std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget(
}
std::string element = linkLibraries.substr(start, end - start);
+ if (globalGenerator->IsAlias(element)) {
+ const auto tgt = globalGenerator->FindTarget(element);
+ if (tgt) {
+ element = tgt->GetName();
+ }
+ }
if (tokens.find(element) == tokens.end()) {
// this library is not found in interfaceLinkLibraries but in
@@ -137,13 +150,13 @@ std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget(
}
}
-cmGraphVizWriter::cmGraphVizWriter(
- const std::vector<cmLocalGenerator*>& localGenerators)
+cmGraphVizWriter::cmGraphVizWriter(const cmGlobalGenerator* globalGenerator)
: GraphType("digraph")
, GraphName("GG")
, GraphHeader("node [\n fontsize = \"12\"\n];")
, GraphNodePrefix("node")
- , LocalGenerators(localGenerators)
+ , GlobalGenerator(globalGenerator)
+ , LocalGenerators(globalGenerator->GetLocalGenerators())
, GenerateForExecutables(true)
, GenerateForStaticLibs(true)
, GenerateForSharedLibs(true)
@@ -374,7 +387,8 @@ void cmGraphVizWriter::WriteConnections(
std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
std::map<std::string, LinkLibraryScopeType> ll =
- getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target);
+ getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target,
+ GlobalGenerator);
for (auto const& llit : ll) {
const char* libName = llit.first.c_str();
@@ -439,7 +453,7 @@ void cmGraphVizWriter::WriteDependerConnections(
// Now we have a target, check whether it links against targetName.
// If so, draw a connection, and then continue with dependers on that one.
std::map<std::string, LinkLibraryScopeType> ll =
- getScopedLinkLibrariesFromTarget(tptr.second->Target);
+ getScopedLinkLibrariesFromTarget(tptr.second->Target, GlobalGenerator);
for (auto const& llit : ll) {
if (llit.first == targetName) {
@@ -540,6 +554,13 @@ int cmGraphVizWriter::CollectAllExternalLibs(int cnt)
continue;
}
+ if (GlobalGenerator->IsAlias(libName)) {
+ const auto tgt = GlobalGenerator->FindTarget(libName);
+ if (tgt) {
+ libName = tgt->GetName().c_str();
+ }
+ }
+
std::map<std::string, const cmGeneratorTarget*>::const_iterator tarIt =
this->TargetPtrs.find(libName);
if (tarIt == this->TargetPtrs.end()) {
diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h
index ac20da9..ed242f0 100644
--- a/Source/cmGraphVizWriter.h
+++ b/Source/cmGraphVizWriter.h
@@ -16,13 +16,14 @@
class cmGeneratedFileStream;
class cmGeneratorTarget;
class cmLocalGenerator;
+class cmGlobalGenerator;
/** This class implements writing files for graphviz (dot) for graphs
* representing the dependencies between the targets in the project. */
class cmGraphVizWriter
{
public:
- cmGraphVizWriter(const std::vector<cmLocalGenerator*>& localGenerators);
+ cmGraphVizWriter(const cmGlobalGenerator* globalGenerator);
void ReadSettings(const char* settingsFileName,
const char* fallbackSettingsFileName);
@@ -69,6 +70,7 @@ protected:
std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex;
+ const cmGlobalGenerator* GlobalGenerator;
const std::vector<cmLocalGenerator*>& LocalGenerators;
std::map<std::string, const cmGeneratorTarget*> TargetPtrs;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 6e33cf7..7c8458a 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -3,6 +3,7 @@
#include "cmInstallCommand.h"
#include "cmsys/Glob.hxx"
+#include <set>
#include <sstream>
#include <stddef.h>
#include <utility>
@@ -20,6 +21,7 @@
#include "cmInstallGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
@@ -32,6 +34,7 @@ class cmExecutionStatus;
static cmInstallTargetGenerator* CreateInstallTargetGenerator(
cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
+ cmListFileBacktrace const& backtrace, const std::string& destination,
bool forceOpt = false, bool namelink = false)
{
cmInstallGenerator::MessageLevel message =
@@ -40,24 +43,49 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator(
const char* component = namelink ? args.GetNamelinkComponent().c_str()
: args.GetComponent().c_str();
return new cmInstallTargetGenerator(
- target.GetName(), args.GetDestination().c_str(), impLib,
+ target.GetName(), destination.c_str(), impLib,
args.GetPermissions().c_str(), args.GetConfigurations(), component,
- message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt);
+ message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt,
+ backtrace);
+}
+
+static cmInstallTargetGenerator* CreateInstallTargetGenerator(
+ cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
+ cmListFileBacktrace const& backtrace, bool forceOpt = false,
+ bool namelink = false)
+{
+ return CreateInstallTargetGenerator(target, args, impLib, backtrace,
+ args.GetDestination(), forceOpt,
+ namelink);
}
static cmInstallFilesGenerator* CreateInstallFilesGenerator(
cmMakefile* mf, const std::vector<std::string>& absFiles,
- const cmInstallCommandArguments& args, bool programs)
+ const cmInstallCommandArguments& args, bool programs,
+ const std::string& destination)
{
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(mf);
return new cmInstallFilesGenerator(
- absFiles, args.GetDestination().c_str(), programs,
- args.GetPermissions().c_str(), args.GetConfigurations(),
- args.GetComponent().c_str(), message, args.GetExcludeFromAll(),
- args.GetRename().c_str(), args.GetOptional());
+ absFiles, destination.c_str(), programs, args.GetPermissions().c_str(),
+ args.GetConfigurations(), args.GetComponent().c_str(), message,
+ args.GetExcludeFromAll(), args.GetRename().c_str(), args.GetOptional());
}
+static cmInstallFilesGenerator* CreateInstallFilesGenerator(
+ cmMakefile* mf, const std::vector<std::string>& absFiles,
+ const cmInstallCommandArguments& args, bool programs)
+{
+ return CreateInstallFilesGenerator(mf, absFiles, args, programs,
+ args.GetDestination());
+}
+
+static const std::set<std::string> allowedTypes{
+ "BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF",
+ "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO",
+ "LOCALE", "MAN", "DOC",
+};
+
// cmInstallCommand
bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
@@ -332,6 +360,17 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
"At most one of these two options may be specified.");
return false;
}
+ if (!genericArgs.GetType().empty() || !archiveArgs.GetType().empty() ||
+ !libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() ||
+ !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() ||
+ !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() ||
+ !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) {
+ std::ostringstream e;
+ e << "TARGETS given TYPE option. The TYPE option may only be specified in "
+ " install(FILES) and install(DIRECTORIES).";
+ this->SetError(e.str());
+ return false;
+ }
// Select the mode for installing symlinks to versioned shared libraries.
cmInstallTargetGenerator::NamelinkModeType namelinkMode =
@@ -435,17 +474,21 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// This is a DLL platform.
if (!archiveArgs.GetDestination().empty()) {
// The import library uses the ARCHIVE properties.
- archiveGenerator =
- CreateInstallTargetGenerator(target, archiveArgs, true);
+ archiveGenerator = CreateInstallTargetGenerator(
+ target, archiveArgs, true, this->Makefile->GetBacktrace());
}
if (!runtimeArgs.GetDestination().empty()) {
// The DLL uses the RUNTIME properties.
- runtimeGenerator =
- CreateInstallTargetGenerator(target, runtimeArgs, false);
+ runtimeGenerator = CreateInstallTargetGenerator(
+ target, runtimeArgs, false, this->Makefile->GetBacktrace());
}
if ((archiveGenerator == nullptr) && (runtimeGenerator == nullptr)) {
- this->SetError("Library TARGETS given no DESTINATION!");
- return false;
+ archiveGenerator = CreateInstallTargetGenerator(
+ target, archiveArgs, true, this->Makefile->GetBacktrace(),
+ this->GetArchiveDestination(nullptr));
+ runtimeGenerator = CreateInstallTargetGenerator(
+ target, runtimeArgs, false, this->Makefile->GetBacktrace(),
+ this->GetRuntimeDestination(nullptr));
}
} else {
// This is a non-DLL platform.
@@ -459,8 +502,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Use the FRAMEWORK properties.
if (!frameworkArgs.GetDestination().empty()) {
- frameworkGenerator =
- CreateInstallTargetGenerator(target, frameworkArgs, false);
+ frameworkGenerator = CreateInstallTargetGenerator(
+ target, frameworkArgs, false, this->Makefile->GetBacktrace());
} else {
std::ostringstream e;
e << "TARGETS given no FRAMEWORK DESTINATION for shared library "
@@ -471,29 +514,22 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
} else {
// The shared library uses the LIBRARY properties.
- if (!libraryArgs.GetDestination().empty()) {
- if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
- libraryGenerator =
- CreateInstallTargetGenerator(target, libraryArgs, false);
- libraryGenerator->SetNamelinkMode(
- cmInstallTargetGenerator::NamelinkModeSkip);
- }
- if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
- namelinkGenerator = CreateInstallTargetGenerator(
- target, libraryArgs, false, false, true);
- namelinkGenerator->SetNamelinkMode(
- cmInstallTargetGenerator::NamelinkModeOnly);
- }
- namelinkOnly =
- (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
- } else {
- std::ostringstream e;
- e << "TARGETS given no LIBRARY DESTINATION for shared library "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
+ if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
+ libraryGenerator = CreateInstallTargetGenerator(
+ target, libraryArgs, false, this->Makefile->GetBacktrace(),
+ this->GetLibraryDestination(&libraryArgs));
+ libraryGenerator->SetNamelinkMode(
+ cmInstallTargetGenerator::NamelinkModeSkip);
+ }
+ if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
+ namelinkGenerator = CreateInstallTargetGenerator(
+ target, libraryArgs, false, this->Makefile->GetBacktrace(),
+ this->GetLibraryDestination(&libraryArgs), false, true);
+ namelinkGenerator->SetNamelinkMode(
+ cmInstallTargetGenerator::NamelinkModeOnly);
}
+ namelinkOnly =
+ (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
}
}
} break;
@@ -508,8 +544,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Use the FRAMEWORK properties.
if (!frameworkArgs.GetDestination().empty()) {
- frameworkGenerator =
- CreateInstallTargetGenerator(target, frameworkArgs, false);
+ frameworkGenerator = CreateInstallTargetGenerator(
+ target, frameworkArgs, false, this->Makefile->GetBacktrace());
} else {
std::ostringstream e;
e << "TARGETS given no FRAMEWORK DESTINATION for static library "
@@ -520,24 +556,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
} else {
// Static libraries use ARCHIVE properties.
- if (!archiveArgs.GetDestination().empty()) {
- archiveGenerator =
- CreateInstallTargetGenerator(target, archiveArgs, false);
- } else {
- std::ostringstream e;
- e << "TARGETS given no ARCHIVE DESTINATION for static library "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
- }
+ archiveGenerator = CreateInstallTargetGenerator(
+ target, archiveArgs, false, this->Makefile->GetBacktrace(),
+ this->GetArchiveDestination(&archiveArgs));
}
} break;
case cmStateEnums::MODULE_LIBRARY: {
// Modules use LIBRARY properties.
if (!libraryArgs.GetDestination().empty()) {
- libraryGenerator =
- CreateInstallTargetGenerator(target, libraryArgs, false);
+ libraryGenerator = CreateInstallTargetGenerator(
+ target, libraryArgs, false, this->Makefile->GetBacktrace());
libraryGenerator->SetNamelinkMode(namelinkMode);
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
@@ -563,8 +591,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
return false;
}
- objectGenerator =
- CreateInstallTargetGenerator(target, objectArgs, false);
+ objectGenerator = CreateInstallTargetGenerator(
+ target, objectArgs, false, this->Makefile->GetBacktrace());
} else {
// Installing an OBJECT library without a destination transforms
// it to an INTERFACE library. It installs no files but can be
@@ -575,15 +603,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
if (target.IsAppBundleOnApple()) {
// Application bundles use the BUNDLE properties.
if (!bundleArgs.GetDestination().empty()) {
- bundleGenerator =
- CreateInstallTargetGenerator(target, bundleArgs, false);
+ bundleGenerator = CreateInstallTargetGenerator(
+ target, bundleArgs, false, this->Makefile->GetBacktrace());
} else if (!runtimeArgs.GetDestination().empty()) {
bool failure = false;
if (this->CheckCMP0006(failure)) {
// For CMake 2.4 compatibility fallback to the RUNTIME
// properties.
- bundleGenerator =
- CreateInstallTargetGenerator(target, runtimeArgs, false);
+ bundleGenerator = CreateInstallTargetGenerator(
+ target, runtimeArgs, false, this->Makefile->GetBacktrace());
} else if (failure) {
return false;
}
@@ -598,17 +626,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
} else {
// Executables use the RUNTIME properties.
- if (!runtimeArgs.GetDestination().empty()) {
- runtimeGenerator =
- CreateInstallTargetGenerator(target, runtimeArgs, false);
- } else {
- std::ostringstream e;
- e << "TARGETS given no RUNTIME DESTINATION for executable "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
- }
+ runtimeGenerator = CreateInstallTargetGenerator(
+ target, runtimeArgs, false, this->Makefile->GetBacktrace(),
+ this->GetRuntimeDestination(&runtimeArgs));
}
// On DLL platforms an executable may also have an import
@@ -617,8 +637,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
if (dll_platform && !archiveArgs.GetDestination().empty() &&
target.IsExecutableWithExports()) {
// The import library uses the ARCHIVE properties.
- archiveGenerator =
- CreateInstallTargetGenerator(target, archiveArgs, true, true);
+ archiveGenerator = CreateInstallTargetGenerator(
+ target, archiveArgs, true, this->Makefile->GetBacktrace(), true);
}
} break;
case cmStateEnums::INTERFACE_LIBRARY:
@@ -655,15 +675,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
// Create the files install generator.
- if (!privateHeaderArgs.GetDestination().empty()) {
- privateHeaderGenerator = CreateInstallFilesGenerator(
- this->Makefile, absFiles, privateHeaderArgs, false);
- } else {
- std::ostringstream e;
- e << "INSTALL TARGETS - target " << target.GetName() << " has "
- << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
- cmSystemTools::Message(e.str().c_str(), "Warning");
- }
+ privateHeaderGenerator = CreateInstallFilesGenerator(
+ this->Makefile, absFiles, privateHeaderArgs, false,
+ this->GetIncludeDestination(&privateHeaderArgs));
}
files = target.GetProperty("PUBLIC_HEADER");
@@ -676,15 +690,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
// Create the files install generator.
- if (!publicHeaderArgs.GetDestination().empty()) {
- publicHeaderGenerator = CreateInstallFilesGenerator(
- this->Makefile, absFiles, publicHeaderArgs, false);
- } else {
- std::ostringstream e;
- e << "INSTALL TARGETS - target " << target.GetName() << " has "
- << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
- cmSystemTools::Message(e.str().c_str(), "Warning");
- }
+ publicHeaderGenerator = CreateInstallFilesGenerator(
+ this->Makefile, absFiles, publicHeaderArgs, false,
+ this->GetIncludeDestination(&publicHeaderArgs));
}
files = target.GetProperty("RESOURCE");
@@ -820,6 +828,14 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
return false;
}
+ std::string type = ica.GetType();
+ if (!type.empty() && allowedTypes.count(type) == 0) {
+ std::ostringstream e;
+ e << args[0] << " given non-type \"" << type << "\" with TYPE argument.";
+ this->SetError(e.str());
+ return false;
+ }
+
const std::vector<std::string>& filesVector = files.GetVector();
// Check if there is something to do.
@@ -882,7 +898,17 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
return false;
}
- if (ica.GetDestination().empty()) {
+ if (!type.empty() && !ica.GetDestination().empty()) {
+ std::ostringstream e;
+ e << args[0]
+ << " given both TYPE and DESTINATION arguments. You may only specify "
+ "one.";
+ this->SetError(e.str());
+ return false;
+ }
+
+ std::string destination = this->GetDestinationForType(&ica, type);
+ if (destination.empty()) {
// A destination is required.
std::ostringstream e;
e << args[0] << " given no DESTINATION!";
@@ -891,8 +917,8 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
}
// Create the files install generator.
- this->Makefile->AddInstallGenerator(
- CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs));
+ this->Makefile->AddInstallGenerator(CreateInstallFilesGenerator(
+ this->Makefile, absFiles, ica, programs, destination));
// Tell the global generator about any installation component names
// specified.
@@ -916,7 +942,8 @@ bool cmInstallCommand::HandleDirectoryMode(
DoingPermsDir,
DoingPermsMatch,
DoingConfigurations,
- DoingComponent
+ DoingComponent,
+ DoingType
};
Doing doing = DoingDirs;
bool in_match_mode = false;
@@ -930,6 +957,7 @@ bool cmInstallCommand::HandleDirectoryMode(
std::vector<std::string> configurations;
std::string component = this->DefaultComponentName;
std::string literal_args;
+ std::string type;
for (unsigned int i = 1; i < args.size(); ++i) {
if (args[i] == "DESTINATION") {
if (in_match_mode) {
@@ -942,6 +970,17 @@ bool cmInstallCommand::HandleDirectoryMode(
// Switch to setting the destination property.
doing = DoingDestination;
+ } else if (args[i] == "TYPE") {
+ if (in_match_mode) {
+ std::ostringstream e;
+ e << args[0] << " does not allow \"" << args[i]
+ << "\" after PATTERN or REGEX.";
+ this->SetError(e.str());
+ return false;
+ }
+
+ // Switch to setting the type.
+ doing = DoingType;
} else if (args[i] == "OPTIONAL") {
if (in_match_mode) {
std::ostringstream e;
@@ -1102,6 +1141,17 @@ bool cmInstallCommand::HandleDirectoryMode(
} else if (doing == DoingDestination) {
destination = args[i].c_str();
doing = DoingNone;
+ } else if (doing == DoingType) {
+ if (allowedTypes.count(args[i]) == 0) {
+ std::ostringstream e;
+ e << args[0] << " given non-type \"" << args[i]
+ << "\" with TYPE argument.";
+ this->SetError(e.str());
+ return false;
+ }
+
+ type = args[i];
+ doing = DoingNone;
} else if (doing == DoingPattern) {
// Convert the pattern to a regular expression. Require a
// leading slash and trailing end-of-string in the matched
@@ -1175,10 +1225,22 @@ bool cmInstallCommand::HandleDirectoryMode(
if (dirs.empty()) {
return true;
}
+ std::string destinationStr;
if (!destination) {
- // A destination is required.
+ if (type.empty()) {
+ // A destination is required.
+ std::ostringstream e;
+ e << args[0] << " given no DESTINATION!";
+ this->SetError(e.str());
+ return false;
+ }
+ destinationStr = this->GetDestinationForType(nullptr, type);
+ destination = destinationStr.c_str();
+ } else if (!type.empty()) {
std::ostringstream e;
- e << args[0] << " given no DESTINATION!";
+ e << args[0]
+ << " given both TYPE and DESTINATION arguments. You may only specify "
+ "one.";
this->SetError(e.str());
return false;
}
@@ -1452,3 +1514,163 @@ bool cmInstallCommand::CheckCMP0006(bool& failure)
}
return false;
}
+
+std::string cmInstallCommand::GetDestination(
+ const cmInstallCommandArguments* args, const std::string& varName,
+ const std::string& guess)
+{
+ if (args && !args->GetDestination().empty()) {
+ return args->GetDestination();
+ }
+ std::string val = this->Makefile->GetSafeDefinition(varName);
+ if (!val.empty()) {
+ return val;
+ }
+ return guess;
+}
+
+std::string cmInstallCommand::GetRuntimeDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin");
+}
+
+std::string cmInstallCommand::GetSbinDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin");
+}
+
+std::string cmInstallCommand::GetArchiveDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
+}
+
+std::string cmInstallCommand::GetLibraryDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
+}
+
+std::string cmInstallCommand::GetIncludeDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include");
+}
+
+std::string cmInstallCommand::GetSysconfDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc");
+}
+
+std::string cmInstallCommand::GetSharedStateDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com");
+}
+
+std::string cmInstallCommand::GetLocalStateDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var");
+}
+
+std::string cmInstallCommand::GetRunStateDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR",
+ this->GetLocalStateDestination(nullptr) +
+ "/run");
+}
+
+std::string cmInstallCommand::GetDataRootDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share");
+}
+
+std::string cmInstallCommand::GetDataDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_DATADIR",
+ this->GetDataRootDestination(nullptr));
+}
+
+std::string cmInstallCommand::GetInfoDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_INFODIR",
+ this->GetDataRootDestination(nullptr) + "/info");
+}
+
+std::string cmInstallCommand::GetLocaleDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR",
+ this->GetDataRootDestination(nullptr) +
+ "/locale");
+}
+
+std::string cmInstallCommand::GetManDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_MANDIR",
+ this->GetDataRootDestination(nullptr) + "/man");
+}
+
+std::string cmInstallCommand::GetDocDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR",
+ this->GetDataRootDestination(nullptr) + "/doc");
+}
+
+std::string cmInstallCommand::GetDestinationForType(
+ const cmInstallCommandArguments* args, const std::string& type)
+{
+ if (args && !args->GetDestination().empty()) {
+ return args->GetDestination();
+ }
+ if (type == "BIN") {
+ return this->GetRuntimeDestination(nullptr);
+ }
+ if (type == "SBIN") {
+ return this->GetSbinDestination(nullptr);
+ }
+ if (type == "SYSCONF") {
+ return this->GetSysconfDestination(nullptr);
+ }
+ if (type == "SHAREDSTATE") {
+ return this->GetSharedStateDestination(nullptr);
+ }
+ if (type == "LOCALSTATE") {
+ return this->GetLocalStateDestination(nullptr);
+ }
+ if (type == "RUNSTATE") {
+ return this->GetRunStateDestination(nullptr);
+ }
+ if (type == "LIB") {
+ return this->GetLibraryDestination(nullptr);
+ }
+ if (type == "INCLUDE") {
+ return this->GetIncludeDestination(nullptr);
+ }
+ if (type == "DATA") {
+ return this->GetDataDestination(nullptr);
+ }
+ if (type == "INFO") {
+ return this->GetInfoDestination(nullptr);
+ }
+ if (type == "LOCALE") {
+ return this->GetLocaleDestination(nullptr);
+ }
+ if (type == "MAN") {
+ return this->GetManDestination(nullptr);
+ }
+ if (type == "DOC") {
+ return this->GetDocDestination(nullptr);
+ }
+ return "";
+}
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index 8bd0159..202c438 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -11,6 +11,7 @@
#include "cmCommand.h"
class cmExecutionStatus;
+class cmInstallCommandArguments;
/** \class cmInstallCommand
* \brief Specifies where to install some files
@@ -45,6 +46,27 @@ private:
std::vector<std::string>& absFiles);
bool CheckCMP0006(bool& failure);
+ std::string GetDestination(const cmInstallCommandArguments* args,
+ const std::string& varName,
+ const std::string& guess);
+ std::string GetRuntimeDestination(const cmInstallCommandArguments* args);
+ std::string GetSbinDestination(const cmInstallCommandArguments* args);
+ std::string GetArchiveDestination(const cmInstallCommandArguments* args);
+ std::string GetLibraryDestination(const cmInstallCommandArguments* args);
+ std::string GetIncludeDestination(const cmInstallCommandArguments* args);
+ std::string GetSysconfDestination(const cmInstallCommandArguments* args);
+ std::string GetSharedStateDestination(const cmInstallCommandArguments* args);
+ std::string GetLocalStateDestination(const cmInstallCommandArguments* args);
+ std::string GetRunStateDestination(const cmInstallCommandArguments* args);
+ std::string GetDataRootDestination(const cmInstallCommandArguments* args);
+ std::string GetDataDestination(const cmInstallCommandArguments* args);
+ std::string GetInfoDestination(const cmInstallCommandArguments* args);
+ std::string GetLocaleDestination(const cmInstallCommandArguments* args);
+ std::string GetManDestination(const cmInstallCommandArguments* args);
+ std::string GetDocDestination(const cmInstallCommandArguments* args);
+ std::string GetDestinationForType(const cmInstallCommandArguments* args,
+ const std::string& type);
+
std::string DefaultComponentName;
};
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 2d6dc12..63bdb00 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -29,6 +29,7 @@ cmInstallCommandArguments::cmInstallCommandArguments(
, Optional(&Parser, "OPTIONAL", &ArgumentGroup)
, NamelinkOnly(&Parser, "NAMELINK_ONLY", &ArgumentGroup)
, NamelinkSkip(&Parser, "NAMELINK_SKIP", &ArgumentGroup)
+ , Type(&Parser, "TYPE", &ArgumentGroup)
, GenericArguments(nullptr)
, DefaultComponentName(defaultComponent)
{
@@ -145,6 +146,11 @@ bool cmInstallCommandArguments::HasNamelinkComponent() const
return false;
}
+const std::string& cmInstallCommandArguments::GetType() const
+{
+ return this->Type.GetString();
+}
+
const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
const
{
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index ee6e865..425e58a 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -35,6 +35,7 @@ public:
bool GetNamelinkOnly() const;
bool GetNamelinkSkip() const;
bool HasNamelinkComponent() const;
+ const std::string& GetType() const;
// once HandleDirectoryMode() is also switched to using
// cmInstallCommandArguments then these two functions can become non-static
@@ -55,6 +56,7 @@ private:
cmCAEnabler Optional;
cmCAEnabler NamelinkOnly;
cmCAEnabler NamelinkSkip;
+ cmCAString Type;
std::string DestinationString;
std::string PermissionsString;
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 53ac716..2b23658 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -22,6 +22,19 @@ cmInstallGenerator::~cmInstallGenerator()
{
}
+bool cmInstallGenerator::HaveInstall()
+{
+ return true;
+}
+
+void cmInstallGenerator::CheckCMP0082(bool& haveSubdirectoryInstall,
+ bool& haveInstallAfterSubdirectory)
+{
+ if (haveSubdirectoryInstall) {
+ haveInstallAfterSubdirectory = true;
+ }
+}
+
void cmInstallGenerator::AddInstallRule(
std::ostream& os, std::string const& dest, cmInstallType type,
std::vector<std::string> const& files, bool optional /* = false */,
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index fc1ce86..e5b88c3 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -38,6 +38,10 @@ public:
bool exclude_from_all);
~cmInstallGenerator() override;
+ virtual bool HaveInstall();
+ virtual void CheckCMP0082(bool& haveSubdirectoryInstall,
+ bool& haveInstallAfterSubdirectory);
+
void AddInstallRule(
std::ostream& os, std::string const& dest, cmInstallType type,
std::vector<std::string> const& files, bool optional = false,
diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx
index f7e6e44..7d77b7c 100644
--- a/Source/cmInstallScriptGenerator.cxx
+++ b/Source/cmInstallScriptGenerator.cxx
@@ -30,9 +30,9 @@ void cmInstallScriptGenerator::GenerateScript(std::ostream& os)
os << indent << "if(" << component_test << ")\n";
if (this->Code) {
- os << indent.Next() << this->Script << "\n";
+ os << indent << this->Script << "\n";
} else {
- os << indent.Next() << "include(\"" << this->Script << "\")\n";
+ os << indent << "include(\"" << this->Script << "\")\n";
}
os << indent << "endif()\n\n";
diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx
new file mode 100644
index 0000000..ca9f134
--- /dev/null
+++ b/Source/cmInstallSubdirectoryGenerator.cxx
@@ -0,0 +1,77 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallSubdirectoryGenerator.h"
+
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmScriptGenerator.h"
+#include "cmSystemTools.h"
+
+#include <sstream>
+#include <vector>
+
+cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator(
+ cmMakefile* makefile, const char* binaryDirectory, bool excludeFromAll)
+ : cmInstallGenerator(nullptr, std::vector<std::string>(), nullptr,
+ MessageDefault, excludeFromAll)
+ , Makefile(makefile)
+ , BinaryDirectory(binaryDirectory)
+{
+}
+
+cmInstallSubdirectoryGenerator::~cmInstallSubdirectoryGenerator()
+{
+}
+
+bool cmInstallSubdirectoryGenerator::HaveInstall()
+{
+ for (auto generator : this->Makefile->GetInstallGenerators()) {
+ if (generator->HaveInstall()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void cmInstallSubdirectoryGenerator::CheckCMP0082(
+ bool& haveSubdirectoryInstall, bool& /*unused*/)
+{
+ if (this->HaveInstall()) {
+ haveSubdirectoryInstall = true;
+ }
+}
+
+void cmInstallSubdirectoryGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+}
+
+void cmInstallSubdirectoryGenerator::GenerateScript(std::ostream& os)
+{
+ if (!this->ExcludeFromAll) {
+ cmPolicies::PolicyStatus status =
+ this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0082);
+ switch (status) {
+ case cmPolicies::WARN:
+ case cmPolicies::OLD:
+ // OLD behavior is handled in cmLocalGenerator::GenerateInstallRules()
+ break;
+
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS: {
+ Indent indent;
+ std::string odir = this->BinaryDirectory;
+ cmSystemTools::ConvertToUnixSlashes(odir);
+ os << indent << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n"
+ << indent.Next()
+ << "# Include the install script for the subdirectory.\n"
+ << indent.Next() << "include(\"" << odir
+ << "/cmake_install.cmake\")\n"
+ << indent << "endif()\n\n";
+ } break;
+ }
+ }
+}
diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h
new file mode 100644
index 0000000..35471dd
--- /dev/null
+++ b/Source/cmInstallSubdirectoryGenerator.h
@@ -0,0 +1,41 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmInstallSubdirectoryGenerator_h
+#define cmInstallSubdirectoryGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmInstallGenerator.h"
+
+#include <iosfwd>
+#include <string>
+
+class cmLocalGenerator;
+class cmMakefile;
+
+/** \class cmInstallSubdirectoryGenerator
+ * \brief Generate target installation rules.
+ */
+class cmInstallSubdirectoryGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallSubdirectoryGenerator(cmMakefile* makefile,
+ const char* binaryDirectory,
+ bool excludeFromAll);
+ ~cmInstallSubdirectoryGenerator() override;
+
+ bool HaveInstall() override;
+ void CheckCMP0082(bool& haveSubdirectoryInstall,
+ bool& haveInstallAfterSubdirectory) override;
+
+ void Compute(cmLocalGenerator* lg) override;
+
+protected:
+ void GenerateScript(std::ostream& os) override;
+
+ cmMakefile* Makefile;
+ std::string BinaryDirectory;
+ cmLocalGenerator* LocalGenerator;
+};
+
+#endif
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 8b8f79b..ea3d522 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -24,7 +24,7 @@ cmInstallTargetGenerator::cmInstallTargetGenerator(
const std::string& targetName, const char* dest, bool implib,
const char* file_permissions, std::vector<std::string> const& configurations,
const char* component, MessageLevel message, bool exclude_from_all,
- bool optional)
+ bool optional, cmListFileBacktrace const& backtrace)
: cmInstallGenerator(dest, configurations, component, message,
exclude_from_all)
, TargetName(targetName)
@@ -32,6 +32,7 @@ cmInstallTargetGenerator::cmInstallTargetGenerator(
, FilePermissions(file_permissions)
, ImportLibrary(implib)
, Optional(optional)
+ , Backtrace(backtrace)
{
this->ActionsPerConfig = true;
this->NamelinkMode = NamelinkModeNone;
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index f6bec20..bf625d1 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
#include "cmScriptGenerator.h"
#include <iosfwd>
@@ -21,11 +22,12 @@ class cmLocalGenerator;
class cmInstallTargetGenerator : public cmInstallGenerator
{
public:
- cmInstallTargetGenerator(std::string const& targetName, const char* dest,
- bool implib, const char* file_permissions,
- std::vector<std::string> const& configurations,
- const char* component, MessageLevel message,
- bool exclude_from_all, bool optional);
+ cmInstallTargetGenerator(
+ std::string const& targetName, const char* dest, bool implib,
+ const char* file_permissions,
+ std::vector<std::string> const& configurations, const char* component,
+ MessageLevel message, bool exclude_from_all, bool optional,
+ cmListFileBacktrace const& backtrace = cmListFileBacktrace());
~cmInstallTargetGenerator() override;
/** Select the policy for installing shared library linkable name
@@ -64,6 +66,8 @@ public:
std::string GetDestination(std::string const& config) const;
+ cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+
protected:
void GenerateScript(std::ostream& os) override;
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
@@ -108,6 +112,7 @@ protected:
NamelinkModeType NamelinkMode;
bool ImportLibrary;
bool Optional;
+ cmListFileBacktrace Backtrace;
};
#endif
diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx
index 69b6821..121731d 100644
--- a/Source/cmLinkItem.cxx
+++ b/Source/cmLinkItem.cxx
@@ -12,15 +12,18 @@ cmLinkItem::cmLinkItem()
{
}
-cmLinkItem::cmLinkItem(std::string const& n)
+cmLinkItem::cmLinkItem(std::string const& n, cmListFileBacktrace const& bt)
: String(n)
, Target(nullptr)
+ , Backtrace(bt)
{
}
-cmLinkItem::cmLinkItem(cmGeneratorTarget const* t)
+cmLinkItem::cmLinkItem(cmGeneratorTarget const* t,
+ cmListFileBacktrace const& bt)
: String()
, Target(t)
+ , Backtrace(bt)
{
}
@@ -58,15 +61,12 @@ std::ostream& operator<<(std::ostream& os, cmLinkItem const& item)
cmLinkImplItem::cmLinkImplItem()
: cmLinkItem()
- , Backtrace()
, FromGenex(false)
{
}
-cmLinkImplItem::cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt,
- bool fromGenex)
+cmLinkImplItem::cmLinkImplItem(cmLinkItem item, bool fromGenex)
: cmLinkItem(std::move(item))
- , Backtrace(bt)
, FromGenex(fromGenex)
{
}
diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h
index 74fd298..e1ddd22 100644
--- a/Source/cmLinkItem.h
+++ b/Source/cmLinkItem.h
@@ -24,10 +24,11 @@ class cmLinkItem
public:
cmLinkItem();
- explicit cmLinkItem(std::string const& s);
- explicit cmLinkItem(cmGeneratorTarget const* t);
+ cmLinkItem(std::string const& s, cmListFileBacktrace const& bt);
+ cmLinkItem(cmGeneratorTarget const* t, cmListFileBacktrace const& bt);
std::string const& AsStr() const;
cmGeneratorTarget const* Target;
+ cmListFileBacktrace Backtrace;
friend bool operator<(cmLinkItem const& l, cmLinkItem const& r);
friend bool operator==(cmLinkItem const& l, cmLinkItem const& r);
friend std::ostream& operator<<(std::ostream& os, cmLinkItem const& item);
@@ -37,9 +38,7 @@ class cmLinkImplItem : public cmLinkItem
{
public:
cmLinkImplItem();
- cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt,
- bool fromGenex);
- cmListFileBacktrace Backtrace;
+ cmLinkImplItem(cmLinkItem item, bool fromGenex);
bool FromGenex;
};
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index d7de2fa..9b63d24 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -152,7 +152,7 @@ bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args)
}
const std::string& listName = args[1];
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
std::vector<std::string> varArgsExpanded;
// do not check the return value here
// if the list var is not found varArgsExpanded will have size 0
@@ -174,7 +174,7 @@ bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args)
}
const std::string& listName = args[1];
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
// expand the variable
std::vector<std::string> varArgsExpanded;
if (!this->GetList(varArgsExpanded, listName)) {
@@ -243,7 +243,7 @@ bool cmListCommand::HandleFindCommand(std::vector<std::string> const& args)
}
const std::string& listName = args[1];
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
// expand the variable
std::vector<std::string> varArgsExpanded;
if (!this->GetList(varArgsExpanded, listName)) {
@@ -346,8 +346,7 @@ bool cmListCommand::HandleRemoveItemCommand(
// expand the variable
std::vector<std::string> varArgsExpanded;
if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command REMOVE_ITEM requires list to be present.");
- return false;
+ return true;
}
std::vector<std::string> remove(args.begin() + 2, args.end());
@@ -376,8 +375,7 @@ bool cmListCommand::HandleReverseCommand(std::vector<std::string> const& args)
// expand the variable
std::vector<std::string> varArgsExpanded;
if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command REVERSE requires list to be present.");
- return false;
+ return true;
}
std::string value = cmJoin(cmReverseRange(varArgsExpanded), ";");
@@ -399,9 +397,7 @@ bool cmListCommand::HandleRemoveDuplicatesCommand(
// expand the variable
std::vector<std::string> varArgsExpanded;
if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError(
- "sub-command REMOVE_DUPLICATES requires list to be present.");
- return false;
+ return true;
}
std::vector<std::string>::const_iterator argsEnd =
@@ -1152,8 +1148,7 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
// expand the variable
std::vector<std::string> varArgsExpanded;
if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command SORT requires list to be present.");
- return false;
+ return true;
}
if ((sortCompare == cmStringSorter::Compare::STRING) &&
@@ -1181,7 +1176,7 @@ bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args)
}
const std::string& listName = args[1];
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
// expand the variable
std::vector<std::string> varArgsExpanded;
@@ -1230,13 +1225,17 @@ bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args)
const std::string& listName = args[1];
// expand the variable
std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command REMOVE_AT requires list to be present.");
- return false;
- }
- // FIXME: Add policy to make non-existing lists an error like empty lists.
- if (varArgsExpanded.empty()) {
- this->SetError("REMOVE_AT given empty list");
+ if (!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) {
+ std::ostringstream str;
+ str << "index: ";
+ for (size_t i = 1; i < args.size(); ++i) {
+ str << args[i];
+ if (i != args.size() - 1) {
+ str << ", ";
+ }
+ }
+ str << " out of range (0, 0)";
+ this->SetError(str.str());
return false;
}
@@ -1289,14 +1288,6 @@ bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args)
return false;
}
- const std::string& listName = args[1];
- // expand the variable
- std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command FILTER requires list to be present.");
- return false;
- }
-
const std::string& op = args[2];
bool includeMatches;
if (op == "INCLUDE") {
@@ -1308,6 +1299,13 @@ bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args)
return false;
}
+ const std::string& listName = args[1];
+ // expand the variable
+ std::vector<std::string> varArgsExpanded;
+ if (!this->GetList(varArgsExpanded, listName)) {
+ return true;
+ }
+
const std::string& mode = args[3];
if (mode == "REGEX") {
if (args.size() != 5) {
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 4d7e1e2..4689f42 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -9,10 +9,10 @@
#include "cmSystemTools.h"
#include "cmake.h"
-#include <algorithm>
#include <assert.h>
#include <memory>
#include <sstream>
+#include <utility>
cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=(
std::string const& name)
@@ -474,3 +474,21 @@ bool operator!=(const cmListFileContext& lhs, const cmListFileContext& rhs)
{
return !(lhs == rhs);
}
+
+std::ostream& operator<<(std::ostream& os, BT<std::string> const& s)
+{
+ return os << s.Value;
+}
+
+std::vector<BT<std::string>> ExpandListWithBacktrace(
+ std::string const& list, cmListFileBacktrace const& bt)
+{
+ std::vector<BT<std::string>> result;
+ std::vector<std::string> tmp;
+ cmSystemTools::ExpandListArgument(list, tmp);
+ result.reserve(tmp.size());
+ for (std::string& i : tmp) {
+ result.emplace_back(std::move(i), bt);
+ }
+ return result;
+}
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 3d3afdf..9e4a833 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -9,6 +9,7 @@
#include <memory> // IWYU pragma: keep
#include <stddef.h>
#include <string>
+#include <utility>
#include <vector>
#include "cmStateSnapshot.h"
@@ -169,6 +170,38 @@ private:
cmListFileBacktrace(std::shared_ptr<Entry const> top);
};
+// Wrap type T as a value with a backtrace. For purposes of
+// ordering and equality comparison, only the original value is
+// used. The backtrace is considered incidental.
+template <typename T>
+class BT
+{
+public:
+ BT(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
+ : Value(std::move(v))
+ , Backtrace(std::move(bt))
+ {
+ }
+ T Value;
+ cmListFileBacktrace Backtrace;
+ friend bool operator==(BT<T> const& l, BT<T> const& r)
+ {
+ return l.Value == r.Value;
+ }
+ friend bool operator<(BT<T> const& l, BT<T> const& r)
+ {
+ return l.Value < r.Value;
+ }
+ friend bool operator==(BT<T> const& l, T const& r) { return l.Value == r; }
+ friend bool operator==(T const& l, BT<T> const& r) { return l == r.Value; }
+};
+
+std::ostream& operator<<(std::ostream& os, BT<std::string> const& s);
+
+std::vector<BT<std::string>> ExpandListWithBacktrace(
+ std::string const& list,
+ cmListFileBacktrace const& bt = cmListFileBacktrace());
+
struct cmListFile
{
bool ParseFile(const char* path, cmMessenger* messenger,
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 7030725..da48950 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -65,6 +65,7 @@ static const char* ruleReplaceVars[] = {
"CMAKE_CURRENT_BINARY_DIR",
"CMAKE_RANLIB",
"CMAKE_LINKER",
+ "CMAKE_MT",
"CMAKE_CUDA_HOST_COMPILER",
"CMAKE_CUDA_HOST_LINK_LAUNCHER",
"CMAKE_CL_SHOWINCLUDES_PREFIX"
@@ -202,9 +203,10 @@ void cmLocalGenerator::ComputeObjectMaxPath()
this->ObjectMaxPathViolations.clear();
}
-void cmLocalGenerator::MoveSystemIncludesToEnd(
- std::vector<std::string>& includeDirs, const std::string& config,
- const std::string& lang, const cmGeneratorTarget* target) const
+static void MoveSystemIncludesToEnd(std::vector<std::string>& includeDirs,
+ const std::string& config,
+ const std::string& lang,
+ const cmGeneratorTarget* target)
{
if (!target) {
return;
@@ -218,6 +220,24 @@ void cmLocalGenerator::MoveSystemIncludesToEnd(
});
}
+static void MoveSystemIncludesToEnd(std::vector<BT<std::string>>& includeDirs,
+ const std::string& config,
+ const std::string& lang,
+ const cmGeneratorTarget* target)
+{
+ if (!target) {
+ return;
+ }
+
+ std::stable_sort(includeDirs.begin(), includeDirs.end(),
+ [target, &config, &lang](BT<std::string> const& a,
+ BT<std::string> const& b) {
+ return !target->IsSystemIncludeDirectory(a.Value, config,
+ lang) &&
+ target->IsSystemIncludeDirectory(b.Value, config, lang);
+ });
+}
+
void cmLocalGenerator::TraceDependencies()
{
std::vector<std::string> configs;
@@ -517,31 +537,62 @@ void cmLocalGenerator::GenerateInstallRules()
}
// Ask each install generator to write its code.
+ cmPolicies::PolicyStatus status = this->GetPolicyStatus(cmPolicies::CMP0082);
std::vector<cmInstallGenerator*> const& installers =
this->Makefile->GetInstallGenerators();
- for (cmInstallGenerator* installer : installers) {
- installer->Generate(fout, config, configurationTypes);
+ bool haveSubdirectoryInstall = false;
+ bool haveInstallAfterSubdirectory = false;
+ if (status == cmPolicies::WARN) {
+ for (cmInstallGenerator* installer : installers) {
+ installer->CheckCMP0082(haveSubdirectoryInstall,
+ haveInstallAfterSubdirectory);
+ installer->Generate(fout, config, configurationTypes);
+ }
+ } else {
+ for (cmInstallGenerator* installer : installers) {
+ installer->Generate(fout, config, configurationTypes);
+ }
}
// Write rules from old-style specification stored in targets.
this->GenerateTargetInstallRules(fout, config, configurationTypes);
// Include install scripts from subdirectories.
- std::vector<cmStateSnapshot> children =
- this->Makefile->GetStateSnapshot().GetChildren();
- if (!children.empty()) {
- fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
- fout << " # Include the install script for each subdirectory.\n";
- for (cmStateSnapshot const& c : children) {
- if (!c.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
- std::string odir = c.GetDirectory().GetCurrentBinary();
- cmSystemTools::ConvertToUnixSlashes(odir);
- fout << " include(\"" << odir << "/cmake_install.cmake\")"
- << std::endl;
+ switch (status) {
+ case cmPolicies::WARN:
+ if (haveInstallAfterSubdirectory &&
+ this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0082")) {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0082) << "\n";
+ this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
}
- }
- fout << "\n";
- fout << "endif()\n\n";
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD: {
+ std::vector<cmStateSnapshot> children =
+ this->Makefile->GetStateSnapshot().GetChildren();
+ if (!children.empty()) {
+ fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
+ fout << " # Include the install script for each subdirectory.\n";
+ for (cmStateSnapshot const& c : children) {
+ if (!c.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ std::string odir = c.GetDirectory().GetCurrentBinary();
+ cmSystemTools::ConvertToUnixSlashes(odir);
+ fout << " include(\"" << odir << "/cmake_install.cmake\")"
+ << std::endl;
+ }
+ }
+ fout << "\n";
+ fout << "endif()\n\n";
+ }
+ } break;
+
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // NEW behavior is handled in
+ // cmInstallSubdirectoryGenerator::GenerateScript()
+ break;
}
// Record the install manifest.
@@ -676,7 +727,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
}
std::vector<std::string> includes = includeDirs;
- this->MoveSystemIncludesToEnd(includes, config, lang, target);
+ MoveSystemIncludesToEnd(includes, config, lang, target);
OutputFormat shellFormat = forResponseFile ? RESPONSE : SHELL;
std::ostringstream includeFlags;
@@ -756,33 +807,23 @@ std::string cmLocalGenerator::GetIncludeFlags(
}
std::string includePath =
this->ConvertToIncludeReference(i, shellFormat, forceFullPaths);
- if (quotePaths && !includePath.empty() && includePath[0] != '\"') {
+ if (quotePaths && !includePath.empty() && includePath.front() != '\"') {
includeFlags << "\"";
}
includeFlags << includePath;
- if (quotePaths && !includePath.empty() && includePath[0] != '\"') {
+ if (quotePaths && !includePath.empty() && includePath.front() != '\"') {
includeFlags << "\"";
}
includeFlags << sep;
}
std::string flags = includeFlags.str();
// remove trailing separators
- if ((sep[0] != ' ') && !flags.empty() && flags[flags.size() - 1] == sep[0]) {
- flags[flags.size() - 1] = ' ';
+ if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) {
+ flags.back() = ' ';
}
return flags;
}
-void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines,
- cmGeneratorTarget const* target,
- const std::string& config,
- const std::string& lang) const
-{
- std::vector<std::string> targetDefines;
- target->GetCompileDefinitions(targetDefines, config, lang);
- this->AppendDefines(defines, targetDefines);
-}
-
void cmLocalGenerator::AddCompileOptions(std::string& flags,
cmGeneratorTarget* target,
const std::string& lang,
@@ -847,6 +888,21 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
bool stripImplicitDirs,
bool appendAllImplicitDirs) const
{
+ std::vector<BT<std::string>> tmp = this->GetIncludeDirectories(
+ target, lang, config, stripImplicitDirs, appendAllImplicitDirs);
+ dirs.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ dirs.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectories(
+ cmGeneratorTarget const* target, std::string const& lang,
+ std::string const& config, bool stripImplicitDirs,
+ bool appendAllImplicitDirs) const
+{
+ std::vector<BT<std::string>> result;
+
// Do not repeat an include path.
std::set<std::string> emitted;
@@ -863,7 +919,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
std::string binDir =
this->StateSnapshot.GetDirectory().GetCurrentBinary();
if (emitted.insert(binDir).second) {
- dirs.push_back(std::move(binDir));
+ result.emplace_back(std::move(binDir));
}
}
// Current source directory
@@ -871,13 +927,13 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
std::string srcDir =
this->StateSnapshot.GetDirectory().GetCurrentSource();
if (emitted.insert(srcDir).second) {
- dirs.push_back(std::move(srcDir));
+ result.emplace_back(std::move(srcDir));
}
}
}
if (!target) {
- return;
+ return result;
}
// Implicit include directories
@@ -910,7 +966,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
}
// Get the target-specific include directories.
- std::vector<std::string> userDirs =
+ std::vector<BT<std::string>> userDirs =
target->GetIncludeDirectories(config, lang);
// Support putting all the in-project include directories first if
@@ -918,44 +974,44 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) {
std::string const &topSourceDir = this->GetState()->GetSourceDirectory(),
&topBinaryDir = this->GetState()->GetBinaryDirectory();
- for (std::string const& i : userDirs) {
+ for (BT<std::string> const& i : userDirs) {
// Emit this directory only if it is a subdirectory of the
// top-level source or binary tree.
- if (cmSystemTools::ComparePath(i, topSourceDir) ||
- cmSystemTools::ComparePath(i, topBinaryDir) ||
- cmSystemTools::IsSubDirectory(i, topSourceDir) ||
- cmSystemTools::IsSubDirectory(i, topBinaryDir)) {
- if (emitted.insert(i).second) {
- dirs.push_back(i);
+ if (cmSystemTools::ComparePath(i.Value, topSourceDir) ||
+ cmSystemTools::ComparePath(i.Value, topBinaryDir) ||
+ cmSystemTools::IsSubDirectory(i.Value, topSourceDir) ||
+ cmSystemTools::IsSubDirectory(i.Value, topBinaryDir)) {
+ if (emitted.insert(i.Value).second) {
+ result.push_back(i);
}
}
}
}
// Construct the final ordered include directory list.
- for (std::string const& i : userDirs) {
- if (emitted.insert(i).second) {
- dirs.push_back(i);
+ for (BT<std::string> const& i : userDirs) {
+ if (emitted.insert(i.Value).second) {
+ result.push_back(i);
}
}
- this->MoveSystemIncludesToEnd(dirs, config, lang, target);
+ MoveSystemIncludesToEnd(result, config, lang, target);
// Add standard include directories for this language.
{
- std::vector<std::string>::size_type const before = userDirs.size();
+ std::vector<std::string> userStandardDirs;
{
std::string key = "CMAKE_";
key += lang;
key += "_STANDARD_INCLUDE_DIRECTORIES";
std::string const value = this->Makefile->GetSafeDefinition(key);
- cmSystemTools::ExpandListArgument(value, userDirs);
+ cmSystemTools::ExpandListArgument(value, userStandardDirs);
}
- for (std::vector<std::string>::iterator i = userDirs.begin() + before,
- ie = userDirs.end();
- i != ie; ++i) {
- cmSystemTools::ConvertToUnixSlashes(*i);
- dirs.push_back(*i);
+ userDirs.reserve(userDirs.size() + userStandardDirs.size());
+ for (std::string& d : userStandardDirs) {
+ cmSystemTools::ConvertToUnixSlashes(d);
+ result.emplace_back(d);
+ userDirs.emplace_back(std::move(d));
}
}
@@ -963,18 +1019,20 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
// Append only implicit directories that were requested by the user
for (std::string const& i : implicitDirs) {
if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) {
- dirs.push_back(i);
+ result.emplace_back(i);
}
}
// Append remaining implicit directories on demand
if (appendAllImplicitDirs) {
for (std::string const& i : implicitDirs) {
- if (std::find(dirs.begin(), dirs.end(), i) == dirs.end()) {
- dirs.push_back(i);
+ if (std::find(result.begin(), result.end(), i) == result.end()) {
+ result.emplace_back(i);
}
}
}
}
+
+ return result;
}
void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
@@ -1143,6 +1201,8 @@ void cmLocalGenerator::GetTargetFlags(
break;
}
+ this->AppendPositionIndependentLinkerFlags(linkFlags, target, config,
+ linkLanguage);
this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage);
}
@@ -1231,13 +1291,29 @@ void cmLocalGenerator::GetTargetDefines(cmGeneratorTarget const* target,
std::string const& lang,
std::set<std::string>& defines) const
{
+ std::set<BT<std::string>> tmp = this->GetTargetDefines(target, config, lang);
+ for (BT<std::string> const& v : tmp) {
+ defines.emplace(v.Value);
+ }
+}
+
+std::set<BT<std::string>> cmLocalGenerator::GetTargetDefines(
+ cmGeneratorTarget const* target, std::string const& config,
+ std::string const& lang) const
+{
+ std::set<BT<std::string>> defines;
+
// Add the export symbol definition for shared library objects.
- if (const char* exportMacro = target->GetExportMacro()) {
- this->AppendDefines(defines, exportMacro);
+ if (const std::string* exportMacro = target->GetExportMacro()) {
+ this->AppendDefines(defines, *exportMacro);
}
// Add preprocessor definitions for this target and configuration.
- this->AddCompileDefinitions(defines, target, config, lang);
+ std::vector<BT<std::string>> targetDefines =
+ target->GetCompileDefinitions(config, lang);
+ this->AppendDefines(defines, targetDefines);
+
+ return defines;
}
std::string cmLocalGenerator::GetTargetFortranFlags(
@@ -1953,6 +2029,36 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
}
}
+void cmLocalGenerator::AppendPositionIndependentLinkerFlags(
+ std::string& flags, cmGeneratorTarget* target, const std::string& config,
+ const std::string& lang)
+{
+ // For now, only EXECUTABLE is concerned
+ if (target->GetType() != cmStateEnums::EXECUTABLE) {
+ return;
+ }
+
+ const char* PICValue = target->GetLinkPIEProperty(config);
+ if (PICValue == nullptr) {
+ // POSITION_INDEPENDENT_CODE is not set
+ return;
+ }
+
+ std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_";
+ name += cmSystemTools::IsOn(PICValue) ? "PIE" : "NO_PIE";
+
+ auto pieFlags = this->Makefile->GetSafeDefinition(name);
+ if (pieFlags.empty()) {
+ return;
+ }
+
+ std::vector<std::string> flagsList;
+ cmSystemTools::ExpandListArgument(pieFlags, flagsList);
+ for (const auto& flag : flagsList) {
+ this->AppendFlagEscape(flags, flag);
+ }
+}
+
void cmLocalGenerator::AppendCompileOptions(std::string& options,
const char* options_list,
const char* regex) const
@@ -2035,26 +2141,34 @@ void cmLocalGenerator::AppendIncludeDirectories(
}
void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
- const char* defines_list) const
+ std::string const& defines_list) const
+{
+ std::set<BT<std::string>> tmp;
+ this->AppendDefines(tmp, ExpandListWithBacktrace(defines_list));
+ for (BT<std::string> const& i : tmp) {
+ defines.emplace(i.Value);
+ }
+}
+
+void cmLocalGenerator::AppendDefines(std::set<BT<std::string>>& defines,
+ std::string const& defines_list) const
{
// Short-circuit if there are no definitions.
- if (!defines_list) {
+ if (defines_list.empty()) {
return;
}
// Expand the list of definitions.
- std::vector<std::string> defines_vec;
- cmSystemTools::ExpandListArgument(defines_list, defines_vec);
- this->AppendDefines(defines, defines_vec);
+ this->AppendDefines(defines, ExpandListWithBacktrace(defines_list));
}
void cmLocalGenerator::AppendDefines(
- std::set<std::string>& defines,
- const std::vector<std::string>& defines_vec) const
+ std::set<BT<std::string>>& defines,
+ const std::vector<BT<std::string>>& defines_vec) const
{
- for (std::string const& d : defines_vec) {
+ for (BT<std::string> const& d : defines_vec) {
// Skip unsupported definitions.
- if (!this->CheckDefinition(d)) {
+ if (!this->CheckDefinition(d.Value)) {
continue;
}
defines.insert(d);
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 58b7762..2fa0070 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -126,6 +126,10 @@ public:
void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
+ void AppendPositionIndependentLinkerFlags(std::string& flags,
+ cmGeneratorTarget* target,
+ const std::string& config,
+ const std::string& lang);
///! Get the include flags for the current makefile and language
std::string GetIncludeFlags(const std::vector<std::string>& includes,
cmGeneratorTarget* target,
@@ -169,14 +173,11 @@ public:
* command line.
*/
void AppendDefines(std::set<std::string>& defines,
- const char* defines_list) const;
- void AppendDefines(std::set<std::string>& defines,
- std::string const& defines_list) const
- {
- this->AppendDefines(defines, defines_list.c_str());
- }
- void AppendDefines(std::set<std::string>& defines,
- const std::vector<std::string>& defines_vec) const;
+ std::string const& defines_list) const;
+ void AppendDefines(std::set<BT<std::string>>& defines,
+ std::string const& defines_list) const;
+ void AppendDefines(std::set<BT<std::string>>& defines,
+ const std::vector<BT<std::string>>& defines_vec) const;
/**
* Encode a list of compile options for the compiler
@@ -249,12 +250,12 @@ public:
const std::string& config = "",
bool stripImplicitDirs = true,
bool appendAllImplicitDirs = false) const;
+ std::vector<BT<std::string>> GetIncludeDirectories(
+ cmGeneratorTarget const* target, std::string const& lang = "C",
+ std::string const& config = "", bool stripImplicitDirs = true,
+ bool appendAllImplicitDirs = false) const;
void AddCompileOptions(std::string& flags, cmGeneratorTarget* target,
const std::string& lang, const std::string& config);
- void AddCompileDefinitions(std::set<std::string>& defines,
- cmGeneratorTarget const* target,
- const std::string& config,
- const std::string& lang) const;
std::string GetProjectName() const;
@@ -336,6 +337,9 @@ public:
void GetTargetDefines(cmGeneratorTarget const* target,
std::string const& config, std::string const& lang,
std::set<std::string>& defines) const;
+ std::set<BT<std::string>> GetTargetDefines(cmGeneratorTarget const* target,
+ std::string const& config,
+ std::string const& lang) const;
void GetTargetCompileFlags(cmGeneratorTarget* target,
std::string const& config,
std::string const& lang, std::string& flags);
@@ -418,10 +422,6 @@ private:
int targetType);
void ComputeObjectMaxPath();
- void MoveSystemIncludesToEnd(std::vector<std::string>& includeDirs,
- const std::string& config,
- const std::string& lang,
- cmGeneratorTarget const* target) const;
};
#if defined(CMAKE_BUILD_WITH_CMAKE)
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index eb31478..66edc91 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -17,6 +17,7 @@
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalNinjaGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmNinjaTargetGenerator.h"
#include "cmRulePlaceholderExpander.h"
@@ -40,8 +41,7 @@ cmRulePlaceholderExpander*
cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const
{
cmRulePlaceholderExpander* ret =
- new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings,
- this->CompilerSysroot, this->LinkerSysroot);
+ this->cmLocalGenerator::CreateRulePlaceholderExpander();
ret->SetTargetImpLib("$TARGET_IMPLIB");
return ret;
}
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 4d19b3a..6a535c1 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -17,6 +17,7 @@
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMakefileTargetGenerator.h"
@@ -1546,8 +1547,10 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
if (!text) {
text = "Running external command ...";
}
- depends.insert(depends.end(), gt->GetUtilities().begin(),
- gt->GetUtilities().end());
+ depends.reserve(gt->GetUtilities().size());
+ for (BT<std::string> const& u : gt->GetUtilities()) {
+ depends.push_back(u.Value);
+ }
this->AppendEcho(commands, text,
cmLocalUnixMakefileGenerator3::EchoGlobal);
@@ -1819,8 +1822,8 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
// Build a list of preprocessor definitions for the target.
std::set<std::string> defines;
- this->AddCompileDefinitions(defines, target, this->ConfigName,
- implicitLang.first);
+ this->GetTargetDefines(target, this->ConfigName, implicitLang.first,
+ defines);
if (!defines.empty()) {
/* clang-format off */
cmakefileStream
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 8428672..7630691 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -735,8 +735,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
targetOptions.AddDefine(configDefine);
// Add the export symbol definition for shared library objects.
- if (const char* exportMacro = target->GetExportMacro()) {
- targetOptions.AddDefine(exportMacro);
+ if (const std::string* exportMacro = target->GetExportMacro()) {
+ targetOptions.AddDefine(*exportMacro);
}
// The intermediate directory name consists of a directory for the
@@ -1347,7 +1347,7 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
d != dirs.end(); ++d) {
// Remove any trailing slash and skip empty paths.
std::string dir = *d;
- if (dir[dir.size() - 1] == '/') {
+ if (dir.back() == '/') {
dir = dir.substr(0, dir.size() - 1);
}
if (dir.empty()) {
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 8d163b7..790f6e0 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -28,6 +28,7 @@
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGlobalGenerator.h"
#include "cmInstallGenerator.h" // IWYU pragma: keep
+#include "cmInstallSubdirectoryGenerator.h"
#include "cmListFileCache.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
@@ -66,7 +67,7 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
- this->SuppressWatches = false;
+ this->SuppressSideEffects = false;
// Setup the default include complaint regular expression (match nothing).
this->ComplainFileRegularExpression = "^$";
@@ -1669,6 +1670,9 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
} else {
this->UnConfiguredDirectories.push_back(subMf);
}
+
+ this->AddInstallGenerator(new cmInstallSubdirectoryGenerator(
+ subMf, binPath.c_str(), excludeFromAll));
}
const std::string& cmMakefile::GetCurrentSourceDirectory() const
@@ -2417,7 +2421,7 @@ const std::string* cmMakefile::GetDef(const std::string& name) const
}
#ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* vv = this->GetVariableWatch();
- if (vv && !this->SuppressWatches) {
+ if (vv && !this->SuppressSideEffects) {
bool const watch_function_executed =
vv->VariableAccessed(name,
def ? cmVariableWatch::VARIABLE_READ_ACCESS
@@ -2504,11 +2508,11 @@ const std::string& cmMakefile::ExpandVariablesInString(
compareResults = true;
// Suppress variable watches to avoid calling hooks twice. Suppress new
// dereferences since the OLD behavior is still what is actually used.
- this->SuppressWatches = true;
+ this->SuppressSideEffects = true;
newError = ExpandVariablesInStringNew(
newErrorstr, newResult, escapeQuotes, noEscapes, atOnly, filename,
line, removeEmpty, replaceAt);
- this->SuppressWatches = false;
+ this->SuppressSideEffects = false;
CM_FALLTHROUGH;
}
case cmPolicies::OLD:
@@ -2762,7 +2766,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
} else {
varresult = value;
}
- } else if (!removeEmpty) {
+ } else if (!removeEmpty && !this->SuppressSideEffects) {
// check to see if we need to print a warning
// if strict mode is on and the variable has
// not been "cleared"/initialized with a set(foo ) call
@@ -3496,7 +3500,8 @@ void cmMakefile::DisplayStatus(const char* message, float s) const
cm->UpdateProgress(message, s);
}
-std::string cmMakefile::GetModulesFile(const char* filename) const
+std::string cmMakefile::GetModulesFile(const char* filename,
+ bool& system) const
{
std::string result;
@@ -3543,8 +3548,10 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
// Normally, prefer the files found in CMAKE_MODULE_PATH. Only when the file
// from which we are being called is located itself in CMAKE_ROOT, then
// prefer results from CMAKE_ROOT depending on the policy setting.
+ system = false;
result = moduleInCMakeModulePath;
if (result.empty()) {
+ system = true;
result = moduleInCMakeRoot;
}
@@ -3567,11 +3574,13 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
CM_FALLTHROUGH;
}
case cmPolicies::OLD:
+ system = false;
result = moduleInCMakeModulePath;
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
+ system = true;
result = moduleInCMakeRoot;
break;
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index b30f281..aa94054 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -689,7 +689,13 @@ public:
/**
* Return a location of a file in cmake or custom modules directory
*/
- std::string GetModulesFile(const char* name) const;
+ std::string GetModulesFile(const char* name) const
+ {
+ bool system;
+ return this->GetModulesFile(name, system);
+ }
+
+ std::string GetModulesFile(const char* name, bool& system) const;
///! Set/Get a property of this directory
void SetProperty(const std::string& prop, const char* value);
@@ -1025,7 +1031,7 @@ private:
bool CheckCMP0000;
std::set<std::string> WarnedCMP0074;
bool IsSourceFileTryCompile;
- mutable bool SuppressWatches;
+ mutable bool SuppressSideEffects;
};
#endif
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index f423560..9acae49 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -97,6 +97,9 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags(
this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage);
// LINK_OPTIONS are escaped.
this->LocalGenerator->AppendCompileOptions(flags, opts);
+
+ this->LocalGenerator->AppendPositionIndependentLinkerFlags(
+ flags, this->GeneratorTarget, this->ConfigName, linkLanguage);
}
void cmMakefileTargetGenerator::CreateRuleFile()
@@ -590,7 +593,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
// mingw32-make incorrectly interprets 'a\ b c' as 'a b' and 'c'
// (but 'a\ b "c"' as 'a\', 'b', and 'c'!). Workaround this by
// avoiding a trailing backslash in the argument.
- targetOutPathCompilePDB[targetOutPathCompilePDB.size() - 1] = '/';
+ targetOutPathCompilePDB.back() = '/';
}
}
cmRulePlaceholderExpander::RuleVariables vars;
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 6436969..1386706 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -506,7 +506,6 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
/*realname=*/true));
cmakeCommand += targetOutputReal;
- cmakeCommand += " || true";
linkCmds.push_back(std::move(cmakeCommand));
}
return linkCmds;
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 04a9318..7fd7732 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -186,7 +186,7 @@ bool cmOrderDirectoriesConstraintSOName::FindConflict(std::string const& dir)
// file name. Usually the soname starts with the library name.
std::string base = this->FileName;
std::set<std::string>::const_iterator first = files.lower_bound(base);
- ++base[base.size() - 1];
+ ++base.back();
std::set<std::string>::const_iterator last = files.upper_bound(base);
if (first != last) {
return true;
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index dbe6fa1..43a0107 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -118,11 +118,11 @@ std::string cmOutputConverter::ForceToRelativePath(
std::string const& local_path, std::string const& remote_path)
{
// The paths should never be quoted.
- assert(local_path[0] != '\"');
- assert(remote_path[0] != '\"');
+ assert(local_path.front() != '\"');
+ assert(remote_path.front() != '\"');
// The local path should never have a trailing slash.
- assert(local_path.empty() || local_path[local_path.size() - 1] != '/');
+ assert(local_path.empty() || local_path.back() != '/');
// If the path is already relative then just return the path.
if (!cmSystemTools::FileIsFullPath(remote_path)) {
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index e2de3f9..87c1ec0 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -340,7 +340,7 @@ protected:
} else {
// try to guess which include path to use
for (std::string incpath : this->IncludeDirectories) {
- if (!incpath.empty() && incpath[incpath.size() - 1] != '/') {
+ if (!incpath.empty() && incpath.back() != '/') {
incpath = incpath + "/";
}
incpath = incpath + path;
@@ -421,7 +421,7 @@ protected:
}
for (std::string path : this->IncludeDirectories) {
- if (!path.empty() && path[path.size() - 1] != '/') {
+ if (!path.empty() && path.back() != '/') {
path = path + "/";
}
path = path + fname;
@@ -435,7 +435,7 @@ protected:
if (extraPath) {
std::string path = extraPath;
- if (!path.empty() && path[path.size() - 1] != '/') {
+ if (!path.empty() && path.back() != '/') {
path = path + "/";
}
path = path + fname;
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index a367e47..6b1314f 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -236,11 +236,20 @@ class cmMakefile;
"target_link_libraries allows use with targets in other directories.", 3, \
13, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0080, \
- "BundleUtilities cannot be included at configure time", 3, 13, 0, \
+ "BundleUtilities cannot be included at configure time.", 3, 13, 0, \
cmPolicies::WARN) \
SELECT(POLICY, CMP0081, \
"Relative paths not allowed in LINK_DIRECTORIES target property.", \
- 3, 13, 0, cmPolicies::WARN)
+ 3, 13, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0082, \
+ "Install rules from add_subdirectory() are interleaved with those " \
+ "in caller.", \
+ 3, 14, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0083, "Add PIE options when linking executable.", 3, 14, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0084, \
+ "The FindQt module does not exist for find_package().", 3, 14, 0, \
+ cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -267,7 +276,8 @@ class cmMakefile;
F(CMP0069) \
F(CMP0073) \
F(CMP0076) \
- F(CMP0081)
+ F(CMP0081) \
+ F(CMP0083)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
new file mode 100644
index 0000000..5470ec3
--- /dev/null
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -0,0 +1,185 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoGenGlobalInitializer.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenInitializer.h"
+
+#include "cmAlgorithms.h"
+#include "cmCustomCommandLines.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+
+#include <memory>
+#include <utility>
+
+cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
+ std::vector<cmLocalGenerator*> const& localGenerators)
+{
+ for (cmLocalGenerator* localGen : localGenerators) {
+ // Detect global autogen and autorcc target names
+ bool globalAutoGenTarget = false;
+ bool globalAutoRccTarget = false;
+ {
+ cmMakefile* makefile = localGen->GetMakefile();
+ // Detect global autogen target name
+ if (cmSystemTools::IsOn(
+ makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET"))) {
+ std::string targetName =
+ makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET_NAME");
+ if (targetName.empty()) {
+ targetName = "autogen";
+ }
+ GlobalAutoGenTargets_.emplace(localGen, std::move(targetName));
+ globalAutoGenTarget = true;
+ }
+
+ // Detect global autorcc target name
+ if (cmSystemTools::IsOn(
+ makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET"))) {
+ std::string targetName =
+ makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET_NAME");
+ if (targetName.empty()) {
+ targetName = "autorcc";
+ }
+ GlobalAutoRccTargets_.emplace(localGen, std::move(targetName));
+ globalAutoRccTarget = true;
+ }
+ }
+
+ // Find targets that require AUTOMOC/UIC/RCC processing
+ for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) {
+ // Process only certain target types
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ // Process target
+ break;
+ default:
+ // Don't process target
+ continue;
+ }
+ if (target->IsImported()) {
+ // Don't process target
+ continue;
+ }
+
+ bool const moc = target->GetPropertyAsBool("AUTOMOC");
+ bool const uic = target->GetPropertyAsBool("AUTOUIC");
+ bool const rcc = target->GetPropertyAsBool("AUTORCC");
+ if (moc || uic || rcc) {
+ // We support Qt4 and Qt5
+ auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target);
+ if ((qtVersion.Major == 4) || (qtVersion.Major == 5)) {
+ // Create autogen target initializer
+ Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>(
+ this, target, qtVersion, moc, uic, rcc, globalAutoGenTarget,
+ globalAutoRccTarget));
+ }
+ }
+ }
+ }
+}
+
+cmQtAutoGenGlobalInitializer::~cmQtAutoGenGlobalInitializer()
+{
+}
+
+void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
+ cmLocalGenerator* localGen, std::string const& name,
+ std::string const& comment)
+{
+ // Test if the target already exists
+ if (localGen->FindGeneratorTargetToUse(name) == nullptr) {
+ cmMakefile* makefile = localGen->GetMakefile();
+
+ // Create utility target
+ cmTarget* target = makefile->AddUtilityCommand(
+ name, cmMakefile::TargetOrigin::Generator, true,
+ makefile->GetHomeOutputDirectory().c_str() /*work dir*/,
+ std::vector<std::string>() /*output*/,
+ std::vector<std::string>() /*depends*/, cmCustomCommandLines(), false,
+ comment.c_str());
+ localGen->AddGeneratorTarget(new cmGeneratorTarget(target, localGen));
+
+ // Set FOLDER property in the target
+ {
+ char const* folder =
+ makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
+ if (folder != nullptr) {
+ target->SetProperty("FOLDER", folder);
+ }
+ }
+ }
+}
+
+void cmQtAutoGenGlobalInitializer::AddToGlobalAutoGen(
+ cmLocalGenerator* localGen, std::string const& targetName)
+{
+ auto it = GlobalAutoGenTargets_.find(localGen);
+ if (it != GlobalAutoGenTargets_.end()) {
+ cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second);
+ if (target != nullptr) {
+ target->Target->AddUtility(targetName, localGen->GetMakefile());
+ }
+ }
+}
+
+void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc(
+ cmLocalGenerator* localGen, std::string const& targetName)
+{
+ auto it = GlobalAutoRccTargets_.find(localGen);
+ if (it != GlobalAutoRccTargets_.end()) {
+ cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second);
+ if (target != nullptr) {
+ target->Target->AddUtility(targetName, localGen->GetMakefile());
+ }
+ }
+}
+
+bool cmQtAutoGenGlobalInitializer::generate()
+{
+ return (InitializeCustomTargets() && SetupCustomTargets());
+}
+
+bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets()
+{
+ // Initialize global autogen targets
+ {
+ std::string const comment = "Global AUTOGEN target";
+ for (auto const& pair : GlobalAutoGenTargets_) {
+ GetOrCreateGlobalTarget(pair.first, pair.second, comment);
+ }
+ }
+ // Initialize global autorcc targets
+ {
+ std::string const comment = "Global AUTORCC target";
+ for (auto const& pair : GlobalAutoRccTargets_) {
+ GetOrCreateGlobalTarget(pair.first, pair.second, comment);
+ }
+ }
+ // Initialize per target autogen targets
+ for (auto& initializer : Initializers_) {
+ if (!initializer->InitCustomTargets()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoGenGlobalInitializer::SetupCustomTargets()
+{
+ for (auto& initializer : Initializers_) {
+ if (!initializer->SetupCustomTargets()) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h
new file mode 100644
index 0000000..9e6bac0
--- /dev/null
+++ b/Source/cmQtAutoGenGlobalInitializer.h
@@ -0,0 +1,47 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoGenGlobalInitializer_h
+#define cmQtAutoGenGlobalInitializer_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <memory> // IWYU pragma: keep
+#include <string>
+#include <vector>
+
+class cmLocalGenerator;
+class cmQtAutoGenInitializer;
+
+/// @brief Initializes the QtAutoGen generators
+class cmQtAutoGenGlobalInitializer
+{
+public:
+ cmQtAutoGenGlobalInitializer(
+ std::vector<cmLocalGenerator*> const& localGenerators);
+ ~cmQtAutoGenGlobalInitializer();
+
+ bool generate();
+
+private:
+ friend class cmQtAutoGenInitializer;
+
+ bool InitializeCustomTargets();
+ bool SetupCustomTargets();
+
+ void GetOrCreateGlobalTarget(cmLocalGenerator* localGen,
+ std::string const& name,
+ std::string const& comment);
+
+ void AddToGlobalAutoGen(cmLocalGenerator* localGen,
+ std::string const& targetName);
+ void AddToGlobalAutoRcc(cmLocalGenerator* localGen,
+ std::string const& targetName);
+
+private:
+ std::vector<std::unique_ptr<cmQtAutoGenInitializer>> Initializers_;
+ std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_;
+ std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_;
+};
+
+#endif
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 8a202a2..e71feac 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -2,16 +2,17 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQtAutoGenInitializer.h"
#include "cmQtAutoGen.h"
+#include "cmQtAutoGenGlobalInitializer.h"
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmFilePathChecksum.h"
-#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
@@ -173,17 +174,116 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
return cycle;
}
-cmQtAutoGenInitializer::cmQtAutoGenInitializer(cmGeneratorTarget* target,
- bool mocEnabled,
- bool uicEnabled,
- bool rccEnabled,
- IntegerVersion const& qtVersion)
- : Target(target)
+cmQtAutoGenInitializer::InfoWriter::InfoWriter(std::string const& filename)
+{
+ Ofs_.SetCopyIfDifferent(true);
+ Ofs_.Open(filename, false, true);
+}
+
+template <class IT>
+std::string cmQtAutoGenInitializer::InfoWriter::ListJoin(IT it_begin,
+ IT it_end)
+{
+ std::string res;
+ for (IT it = it_begin; it != it_end; ++it) {
+ if (it != it_begin) {
+ res += ';';
+ }
+ for (const char* c = it->c_str(); *c; ++c) {
+ if (*c == '"') {
+ // Escape the double quote to avoid ending the argument.
+ res += "\\\"";
+ } else if (*c == '$') {
+ // Escape the dollar to avoid expanding variables.
+ res += "\\$";
+ } else if (*c == '\\') {
+ // Escape the backslash to avoid other escapes.
+ res += "\\\\";
+ } else if (*c == ';') {
+ // Escape the semicolon to avoid list expansion.
+ res += "\\;";
+ } else {
+ // Other characters will be parsed correctly.
+ res += *c;
+ }
+ }
+ }
+ return res;
+}
+
+std::string cmQtAutoGenInitializer::InfoWriter::ConfigKey(
+ const char* key, std::string const& config)
+{
+ std::string ckey = key;
+ ckey += '_';
+ ckey += config;
+ return ckey;
+}
+
+void cmQtAutoGenInitializer::InfoWriter::Write(const char* key,
+ std::string const& value)
+{
+ Ofs_ << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
+ << ")\n";
+};
+
+void cmQtAutoGenInitializer::InfoWriter::WriteUInt(const char* key,
+ unsigned int value)
+{
+ Ofs_ << "set(" << key << " " << value << ")\n";
+};
+
+template <class C>
+void cmQtAutoGenInitializer::InfoWriter::WriteStrings(const char* key,
+ C const& container)
+{
+ Ofs_ << "set(" << key << " \""
+ << ListJoin(container.begin(), container.end()) << "\")\n";
+}
+
+void cmQtAutoGenInitializer::InfoWriter::WriteConfig(
+ const char* key, std::map<std::string, std::string> const& map)
+{
+ for (auto const& item : map) {
+ Write(ConfigKey(key, item.first).c_str(), item.second);
+ }
+};
+
+template <class C>
+void cmQtAutoGenInitializer::InfoWriter::WriteConfigStrings(
+ const char* key, std::map<std::string, C> const& map)
+{
+ for (auto const& item : map) {
+ WriteStrings(ConfigKey(key, item.first).c_str(), item.second);
+ }
+}
+
+void cmQtAutoGenInitializer::InfoWriter::WriteNestedLists(
+ const char* key, std::vector<std::vector<std::string>> const& lists)
+{
+ std::vector<std::string> seplist;
+ for (const std::vector<std::string>& list : lists) {
+ std::string blist = "{";
+ blist += ListJoin(list.begin(), list.end());
+ blist += "}";
+ seplist.push_back(std::move(blist));
+ }
+ Write(key, cmJoin(seplist, cmQtAutoGen::ListSep));
+};
+
+cmQtAutoGenInitializer::cmQtAutoGenInitializer(
+ cmQtAutoGenGlobalInitializer* globalInitializer, cmGeneratorTarget* target,
+ IntegerVersion const& qtVersion, bool mocEnabled, bool uicEnabled,
+ bool rccEnabled, bool globalAutogenTarget, bool globalAutoRccTarget)
+ : GlobalInitializer(globalInitializer)
+ , Target(target)
, QtVersion(qtVersion)
{
+ AutogenTarget.GlobalTarget = globalAutogenTarget;
Moc.Enabled = mocEnabled;
Uic.Enabled = uicEnabled;
Rcc.Enabled = rccEnabled;
+ Rcc.GlobalTarget = globalAutoRccTarget;
}
bool cmQtAutoGenInitializer::InitCustomTargets()
@@ -321,6 +421,9 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
// Autogen target: Compute user defined dependencies
{
+ this->AutogenTarget.DependOrigin =
+ this->Target->GetPropertyAsBool("AUTOGEN_ORIGIN_DEPENDS");
+
std::string const deps =
this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
if (!deps.empty()) {
@@ -388,14 +491,15 @@ bool cmQtAutoGenInitializer::InitMoc()
{
bool const appendImplicit = (this->QtVersion.Major == 5);
auto GetIncludeDirs =
- [this, localGen, appendImplicit](std::string const& cfg) -> std::string {
+ [this, localGen,
+ appendImplicit](std::string const& cfg) -> std::vector<std::string> {
// Get the include dirs for this target, without stripping the implicit
// include dirs off, see
// https://gitlab.kitware.com/cmake/cmake/issues/13667
std::vector<std::string> dirs;
localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false,
appendImplicit);
- return cmJoin(dirs, ";");
+ return dirs;
};
// Default configuration include directories
@@ -403,7 +507,7 @@ bool cmQtAutoGenInitializer::InitMoc()
// Other configuration settings
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
- std::string dirs = GetIncludeDirs(cfg);
+ std::vector<std::string> dirs = GetIncludeDirs(cfg);
if (dirs != this->Moc.Includes) {
this->Moc.ConfigIncludes[cfg] = std::move(dirs);
}
@@ -414,10 +518,10 @@ bool cmQtAutoGenInitializer::InitMoc()
// Moc compile definitions
{
auto GetCompileDefinitions =
- [this, localGen](std::string const& cfg) -> std::string {
+ [this, localGen](std::string const& cfg) -> std::set<std::string> {
std::set<std::string> defines;
- localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");
- return cmJoin(defines, ";");
+ localGen->GetTargetDefines(this->Target, cfg, "CXX", defines);
+ return defines;
};
// Default configuration defines
@@ -425,7 +529,7 @@ bool cmQtAutoGenInitializer::InitMoc()
// Other configuration defines
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
- std::string defines = GetCompileDefinitions(cfg);
+ std::set<std::string> defines = GetCompileDefinitions(cfg);
if (defines != this->Moc.Defines) {
this->Moc.ConfigDefines[cfg] = std::move(defines);
}
@@ -459,10 +563,11 @@ bool cmQtAutoGenInitializer::InitUic()
}
// Uic target options
{
- auto UicGetOpts = [this](std::string const& cfg) -> std::string {
+ auto UicGetOpts =
+ [this](std::string const& cfg) -> std::vector<std::string> {
std::vector<std::string> opts;
this->Target->GetAutoUicOptions(opts, cfg);
- return cmJoin(opts, ";");
+ return opts;
};
// Default settings
@@ -471,7 +576,7 @@ bool cmQtAutoGenInitializer::InitUic()
// Configuration specific settings
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
- std::string options = UicGetOpts(cfg);
+ std::vector<std::string> options = UicGetOpts(cfg);
if (options != this->Uic.Options) {
this->Uic.ConfigOptions[cfg] = std::move(options);
}
@@ -878,6 +983,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
if (!this->AutogenTarget.DependFiles.empty()) {
usePRE_BUILD = false;
}
+ // Cannot use PRE_BUILD when a global autogen target is in place
+ if (AutogenTarget.GlobalTarget) {
+ usePRE_BUILD = false;
+ }
}
// Create the autogen target/command
if (usePRE_BUILD) {
@@ -903,7 +1012,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// Add link library target dependencies to the autogen target
// dependencies
- {
+ if (this->AutogenTarget.DependOrigin) {
// add_dependencies/addUtility do not support generator expressions.
// We depend only on the libraries found in all configs therefore.
std::map<cmGeneratorTarget const*, std::size_t> commonTargets;
@@ -940,8 +1049,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
new cmGeneratorTarget(autogenTarget, localGen));
// Forward origin utilities to autogen target
- for (std::string const& depName : this->Target->Target->GetUtilities()) {
- autogenTarget->AddUtility(depName, makefile);
+ if (this->AutogenTarget.DependOrigin) {
+ for (BT<std::string> const& depName : this->Target->GetUtilities()) {
+ autogenTarget->AddUtility(depName.Value, makefile);
+ }
}
// Add additional autogen target dependencies to autogen target
for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
@@ -955,6 +1066,12 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// Add autogen target to the origin target dependencies
this->Target->Target->AddUtility(this->AutogenTarget.Name, makefile);
+
+ // Add autogen target to the global autogen target dependencies
+ if (this->AutogenTarget.GlobalTarget) {
+ this->GlobalInitializer->AddToGlobalAutoGen(localGen,
+ this->AutogenTarget.Name);
+ }
}
return true;
@@ -998,7 +1115,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
std::string ccComment = "Automatic RCC for ";
ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);
- if (qrc.Generated) {
+ if (qrc.Generated || this->Rcc.GlobalTarget) {
// Create custom rcc target
std::string ccName;
{
@@ -1029,6 +1146,11 @@ bool cmQtAutoGenInitializer::InitRccTargets()
}
// Add autogen target to the origin target dependencies
this->Target->Target->AddUtility(ccName, makefile);
+
+ // Add autogen target to the global autogen target dependencies
+ if (this->Rcc.GlobalTarget) {
+ this->GlobalInitializer->AddToGlobalAutoRcc(localGen, ccName);
+ }
} else {
// Create custom rcc command
{
@@ -1084,104 +1206,72 @@ bool cmQtAutoGenInitializer::SetupCustomTargets()
bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
{
- cmMakefile* makefile = this->Target->Target->GetMakefile();
-
- cmGeneratedFileStream ofs;
- ofs.SetCopyIfDifferent(true);
- ofs.Open(this->AutogenTarget.InfoFile, false, true);
+ InfoWriter ofs(this->AutogenTarget.InfoFile);
if (ofs) {
// Utility lambdas
- auto CWrite = [&ofs](const char* key, std::string const& value) {
- ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
- << ")\n";
- };
- auto CWriteUInt = [&ofs](const char* key, unsigned int value) {
- ofs << "set(" << key << " " << value << ")\n";
- };
- auto CWriteList = [&CWrite](const char* key,
- std::vector<std::string> const& list) {
- CWrite(key, cmJoin(list, ";"));
- };
- auto CWriteNestedLists =
- [&CWrite](const char* key,
- std::vector<std::vector<std::string>> const& lists) {
- std::vector<std::string> seplist;
- for (const std::vector<std::string>& list : lists) {
- std::string blist = "{";
- blist += cmJoin(list, ";");
- blist += "}";
- seplist.push_back(std::move(blist));
- }
- CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
- };
- auto CWriteSet = [&CWrite](const char* key,
- std::set<std::string> const& list) {
- CWrite(key, cmJoin(list, ";"));
- };
- auto CWriteMap = [&ofs](const char* key,
- std::map<std::string, std::string> const& map) {
- for (auto const& item : map) {
- ofs << "set(" << key << "_" << item.first << " "
- << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
- }
- };
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
auto MfDef = [makefile](const char* key) {
return makefile->GetSafeDefinition(key);
};
- // Write
- ofs << "# Meta\n";
- CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
- CWrite("AM_PARALLEL", this->AutogenTarget.Parallel);
- CWrite("AM_VERBOSITY", this->Verbosity);
-
- ofs << "# Directories\n";
- CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
- CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
- CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
- CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
- CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
- MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
- CWrite("AM_BUILD_DIR", this->Dir.Build);
- CWrite("AM_INCLUDE_DIR", this->Dir.Include);
- CWriteMap("AM_INCLUDE_DIR", this->Dir.ConfigInclude);
-
- ofs << "# Files\n";
- CWriteList("AM_SOURCES", this->AutogenTarget.Sources);
- CWriteList("AM_HEADERS", this->AutogenTarget.Headers);
- CWrite("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile);
- CWriteMap("AM_SETTINGS_FILE", this->AutogenTarget.ConfigSettingsFile);
-
- ofs << "# Qt\n";
- CWriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major);
- CWrite("AM_QT_MOC_EXECUTABLE", this->Moc.Executable);
- CWrite("AM_QT_UIC_EXECUTABLE", this->Uic.Executable);
-
+ // Write common settings
+ ofs.Write("# Meta\n");
+ ofs.Write("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
+ ofs.Write("AM_PARALLEL", this->AutogenTarget.Parallel);
+ ofs.Write("AM_VERBOSITY", this->Verbosity);
+
+ ofs.Write("# Directories\n");
+ ofs.Write("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+ ofs.Write("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+ ofs.Write("AM_CMAKE_CURRENT_SOURCE_DIR",
+ MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+ ofs.Write("AM_CMAKE_CURRENT_BINARY_DIR",
+ MfDef("CMAKE_CURRENT_BINARY_DIR"));
+ ofs.Write("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
+ MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
+ ofs.Write("AM_BUILD_DIR", this->Dir.Build);
+ ofs.Write("AM_INCLUDE_DIR", this->Dir.Include);
+ ofs.WriteConfig("AM_INCLUDE_DIR", this->Dir.ConfigInclude);
+
+ ofs.Write("# Files\n");
+ ofs.WriteStrings("AM_SOURCES", this->AutogenTarget.Sources);
+ ofs.WriteStrings("AM_HEADERS", this->AutogenTarget.Headers);
+ ofs.Write("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile);
+ ofs.WriteConfig("AM_SETTINGS_FILE",
+ this->AutogenTarget.ConfigSettingsFile);
+
+ ofs.Write("# Qt\n");
+ ofs.WriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major);
+ ofs.Write("AM_QT_MOC_EXECUTABLE", this->Moc.Executable);
+ ofs.Write("AM_QT_UIC_EXECUTABLE", this->Uic.Executable);
+
+ // Write moc settings
if (this->Moc.Enabled) {
- ofs << "# MOC settings\n";
- CWriteSet("AM_MOC_SKIP", this->Moc.Skip);
- CWrite("AM_MOC_DEFINITIONS", this->Moc.Defines);
- CWriteMap("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines);
- CWrite("AM_MOC_INCLUDES", this->Moc.Includes);
- CWriteMap("AM_MOC_INCLUDES", this->Moc.ConfigIncludes);
- CWrite("AM_MOC_OPTIONS",
- this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS"));
- CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
- CWrite("AM_MOC_MACRO_NAMES",
- this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES"));
- CWrite("AM_MOC_DEPEND_FILTERS",
- this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
- CWrite("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
+ ofs.Write("# MOC settings\n");
+ ofs.WriteStrings("AM_MOC_SKIP", this->Moc.Skip);
+ ofs.WriteStrings("AM_MOC_DEFINITIONS", this->Moc.Defines);
+ ofs.WriteConfigStrings("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines);
+ ofs.WriteStrings("AM_MOC_INCLUDES", this->Moc.Includes);
+ ofs.WriteConfigStrings("AM_MOC_INCLUDES", this->Moc.ConfigIncludes);
+ ofs.Write("AM_MOC_OPTIONS",
+ this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS"));
+ ofs.Write("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
+ ofs.Write("AM_MOC_MACRO_NAMES",
+ this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES"));
+ ofs.Write("AM_MOC_DEPEND_FILTERS",
+ this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
+ ofs.Write("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
}
+ // Write uic settings
if (this->Uic.Enabled) {
- ofs << "# UIC settings\n";
- CWriteSet("AM_UIC_SKIP", this->Uic.Skip);
- CWrite("AM_UIC_TARGET_OPTIONS", this->Uic.Options);
- CWriteMap("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions);
- CWriteList("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles);
- CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions);
- CWriteList("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths);
+ ofs.Write("# UIC settings\n");
+ ofs.WriteStrings("AM_UIC_SKIP", this->Uic.Skip);
+ ofs.WriteStrings("AM_UIC_TARGET_OPTIONS", this->Uic.Options);
+ ofs.WriteConfigStrings("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions);
+ ofs.WriteStrings("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles);
+ ofs.WriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions);
+ ofs.WriteStrings("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths);
}
} else {
std::string err = "AutoGen: Could not write file ";
@@ -1196,47 +1286,33 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
bool cmQtAutoGenInitializer::SetupWriteRccInfo()
{
for (Qrc const& qrc : this->Rcc.Qrcs) {
- cmGeneratedFileStream ofs;
- ofs.SetCopyIfDifferent(true);
- ofs.Open(qrc.InfoFile, false, true);
+ InfoWriter ofs(qrc.InfoFile);
if (ofs) {
- // Utility lambdas
- auto CWrite = [&ofs](const char* key, std::string const& value) {
- ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
- << ")\n";
- };
- auto CWriteMap = [&ofs](const char* key,
- std::map<std::string, std::string> const& map) {
- for (auto const& item : map) {
- ofs << "set(" << key << "_" << item.first << " "
- << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
- }
- };
-
// Write
- ofs << "# Configurations\n";
- CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
- CWrite("ARCC_VERBOSITY", this->Verbosity);
- ofs << "# Settings file\n";
- CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
- CWriteMap("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile);
-
- ofs << "# Directories\n";
- CWrite("ARCC_BUILD_DIR", this->Dir.Build);
- CWrite("ARCC_INCLUDE_DIR", this->Dir.Include);
- CWriteMap("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude);
-
- ofs << "# Rcc executable\n";
- CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);
- CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->Rcc.ListOptions, ";"));
-
- ofs << "# Rcc job\n";
- CWrite("ARCC_LOCK_FILE", qrc.LockFile);
- CWrite("ARCC_SOURCE", qrc.QrcFile);
- CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
- CWrite("ARCC_OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.RccFile));
- CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
- CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
+ ofs.Write("# Configurations\n");
+ ofs.Write("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
+ ofs.Write("ARCC_VERBOSITY", this->Verbosity);
+ ofs.Write("# Settings file\n");
+ ofs.Write("ARCC_SETTINGS_FILE", qrc.SettingsFile);
+ ofs.WriteConfig("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile);
+
+ ofs.Write("# Directories\n");
+ ofs.Write("ARCC_BUILD_DIR", this->Dir.Build);
+ ofs.Write("ARCC_INCLUDE_DIR", this->Dir.Include);
+ ofs.WriteConfig("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude);
+
+ ofs.Write("# Rcc executable\n");
+ ofs.Write("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);
+ ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS", this->Rcc.ListOptions);
+
+ ofs.Write("# Rcc job\n");
+ ofs.Write("ARCC_LOCK_FILE", qrc.LockFile);
+ ofs.Write("ARCC_SOURCE", qrc.QrcFile);
+ ofs.Write("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
+ ofs.Write("ARCC_OUTPUT_NAME",
+ cmSystemTools::GetFilenameName(qrc.RccFile));
+ ofs.WriteStrings("ARCC_OPTIONS", qrc.Options);
+ ofs.WriteStrings("ARCC_INPUTS", qrc.Resources);
} else {
std::string err = "AutoRcc: Could not write file ";
err += qrc.InfoFile;
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index ce00e00..903ec85 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -4,15 +4,18 @@
#define cmQtAutoGenInitializer_h
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
#include <map>
+#include <ostream>
#include <set>
#include <string>
#include <vector>
class cmGeneratorTarget;
class cmTarget;
+class cmQtAutoGenGlobalInitializer;
/// @brief Initializes the QtAutoGen generators
class cmQtAutoGenInitializer : public cmQtAutoGen
@@ -43,12 +46,47 @@ public:
std::vector<std::string> Resources;
};
+ /// @brief Writes a CMake info file
+ class InfoWriter
+ {
+ public:
+ /// @brief Open the given file
+ InfoWriter(std::string const& filename);
+
+ /// @return True if the file is open
+ operator bool() const { return static_cast<bool>(Ofs_); }
+
+ void Write(const char* text) { Ofs_ << text; }
+ void Write(const char* key, std::string const& value);
+ void WriteUInt(const char* key, unsigned int value);
+
+ template <class C>
+ void WriteStrings(const char* key, C const& container);
+ void WriteConfig(const char* key,
+ std::map<std::string, std::string> const& map);
+ template <class C>
+ void WriteConfigStrings(const char* key,
+ std::map<std::string, C> const& map);
+ void WriteNestedLists(const char* key,
+ std::vector<std::vector<std::string>> const& lists);
+
+ private:
+ template <class IT>
+ static std::string ListJoin(IT it_begin, IT it_end);
+ static std::string ConfigKey(const char* key, std::string const& config);
+
+ private:
+ cmGeneratedFileStream Ofs_;
+ };
+
public:
static IntegerVersion GetQtVersion(cmGeneratorTarget const* target);
- cmQtAutoGenInitializer(cmGeneratorTarget* target, bool mocEnabled,
+ cmQtAutoGenInitializer(cmQtAutoGenGlobalInitializer* globalInitializer,
+ cmGeneratorTarget* target,
+ IntegerVersion const& qtVersion, bool mocEnabled,
bool uicEnabled, bool rccEnabled,
- IntegerVersion const& qtVersion);
+ bool globalAutogenTarget, bool globalAutoRccTarget);
bool InitCustomTargets();
bool SetupCustomTargets();
@@ -76,6 +114,7 @@ private:
std::string& errorMessage);
private:
+ cmQtAutoGenGlobalInitializer* GlobalInitializer;
cmGeneratorTarget* Target;
// Configuration
@@ -100,6 +139,7 @@ private:
struct
{
std::string Name;
+ bool GlobalTarget = false;
// Settings
std::string Parallel;
// Configuration files
@@ -107,6 +147,7 @@ private:
std::string SettingsFile;
std::map<std::string, std::string> ConfigSettingsFile;
// Dependencies
+ bool DependOrigin = false;
std::set<std::string> DependFiles;
std::set<cmTarget*> DependTargets;
// Sources to process
@@ -123,10 +164,10 @@ private:
std::string Executable;
std::string PredefsCmd;
std::set<std::string> Skip;
- std::string Includes;
- std::map<std::string, std::string> ConfigIncludes;
- std::string Defines;
- std::map<std::string, std::string> ConfigDefines;
+ std::vector<std::string> Includes;
+ std::map<std::string, std::vector<std::string>> ConfigIncludes;
+ std::set<std::string> Defines;
+ std::map<std::string, std::set<std::string>> ConfigDefines;
std::string MocsCompilation;
} Moc;
@@ -137,8 +178,8 @@ private:
std::string Executable;
std::set<std::string> Skip;
std::vector<std::string> SearchPaths;
- std::string Options;
- std::map<std::string, std::string> ConfigOptions;
+ std::vector<std::string> Options;
+ std::map<std::string, std::vector<std::string>> ConfigOptions;
std::vector<std::string> FileFiles;
std::vector<std::vector<std::string>> FileOptions;
} Uic;
@@ -147,6 +188,7 @@ private:
struct
{
bool Enabled = false;
+ bool GlobalTarget = false;
std::string Executable;
std::vector<std::string> ListOptions;
std::vector<Qrc> Qrcs;
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index 32ad0b0..8a04c1f 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -228,8 +228,7 @@ void cmRST::ProcessLine(std::string const& line)
else {
this->NormalLine(line);
this->LastLineEndedInColonColon =
- (line.size() >= 2 && line[line.size() - 2] == ':' &&
- line[line.size() - 1] == ':');
+ (line.size() >= 2 && line[line.size() - 2] == ':' && line.back() == ':');
}
}
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index a71861a..0dfb797 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -110,7 +110,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
if (replaceValues.Target) {
if (variable == "TARGET_QUOTED") {
std::string targetQuoted = replaceValues.Target;
- if (!targetQuoted.empty() && targetQuoted[0] != '\"') {
+ if (!targetQuoted.empty() && targetQuoted.front() != '\"') {
targetQuoted = '\"';
targetQuoted += replaceValues.Target;
targetQuoted += '\"';
@@ -120,7 +120,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
if (variable == "TARGET_UNQUOTED") {
std::string unquoted = replaceValues.Target;
std::string::size_type sz = unquoted.size();
- if (sz > 2 && unquoted[0] == '\"' && unquoted[sz - 1] == '\"') {
+ if (sz > 2 && unquoted.front() == '\"' && unquoted.back() == '\"') {
unquoted = unquoted.substr(1, sz - 2);
}
return unquoted;
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index 985aac8..1a2d1c6 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -54,7 +54,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
}
// SET (VAR PARENT_SCOPE) // Removes the definition of VAR
// in the parent scope.
- if (args.size() == 2 && args[args.size() - 1] == "PARENT_SCOPE") {
+ if (args.size() == 2 && args.back() == "PARENT_SCOPE") {
this->Makefile->RaiseScope(variable, nullptr);
return true;
}
@@ -74,12 +74,12 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
unsigned int ignoreLastArgs = 0;
// look for PARENT_SCOPE argument
- if (args.size() > 1 && args[args.size() - 1] == "PARENT_SCOPE") {
+ if (args.size() > 1 && args.back() == "PARENT_SCOPE") {
parentScope = true;
ignoreLastArgs++;
} else {
// look for FORCE argument
- if (args.size() > 4 && args[args.size() - 1] == "FORCE") {
+ if (args.size() > 4 && args.back() == "FORCE") {
force = true;
ignoreLastArgs++;
}
@@ -103,7 +103,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
// we should be nice and try to catch some simple screwups if the last or
// next to last args are CACHE then they screwed up. If they used FORCE
// without CACHE they screwed up
- if ((args[args.size() - 1] == "CACHE") ||
+ if ((args.back() == "CACHE") ||
(args.size() > 1 && args[args.size() - 2] == "CACHE") ||
(force && !cache)) {
this->SetError("given invalid arguments for CACHE mode.");
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index a2008a0..4bbd2e0 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -867,8 +867,8 @@ static bool ParseEntryWithoutType(const std::string& entry, std::string& var,
// if value is enclosed in single quotes ('foo') then remove them
// it is used to enclose trailing space or tab
- if (flag && value.size() >= 2 && value[0] == '\'' &&
- value[value.size() - 1] == '\'') {
+ if (flag && value.size() >= 2 && value.front() == '\'' &&
+ value.back() == '\'') {
value = value.substr(1, value.size() - 2);
}
@@ -900,8 +900,8 @@ bool cmState::ParseCacheEntry(const std::string& entry, std::string& var,
// if value is enclosed in single quotes ('foo') then remove them
// it is used to enclose trailing space or tab
- if (flag && value.size() >= 2 && value[0] == '\'' &&
- value[value.size() - 1] == '\'') {
+ if (flag && value.size() >= 2 && value.front() == '\'' &&
+ value.back() == '\'') {
value = value.substr(1, value.size() - 2);
}
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 1605fd7..91d6190 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -156,7 +156,7 @@ bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args)
return false;
}
std::string::size_type cc;
- std::string const& outvar = args[args.size() - 1];
+ std::string const& outvar = args.back();
std::string output;
for (cc = 1; cc < args.size() - 1; cc++) {
int ch = atoi(args[cc].c_str());
@@ -755,7 +755,7 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
this->SetError("sub-command RANDOM invoked with bad length.");
return false;
}
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
std::vector<char> result;
@@ -765,8 +765,7 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
}
const char* alphaPtr = alphabet.c_str();
- int cc;
- for (cc = 0; cc < length; cc++) {
+ for (int cc = 0; cc < length; cc++) {
int idx = static_cast<int>(sizeofAlphabet * rand() / (RAND_MAX + 1.0));
result.push_back(*(alphaPtr + idx));
}
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 568ee82..9866d13 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1301,7 +1301,7 @@ bool cmSystemTools::SimpleGlob(const std::string& glob,
int type /* = 0 */)
{
files.clear();
- if (glob[glob.size() - 1] != '*') {
+ if (glob.back() != '*') {
return false;
}
std::string path = cmSystemTools::GetFilenamePath(glob);
@@ -1318,7 +1318,7 @@ bool cmSystemTools::SimpleGlob(const std::string& glob,
if ((std::string(d.GetFile(i)) != ".") &&
(std::string(d.GetFile(i)) != "..")) {
std::string fname = path;
- if (path[path.size() - 1] != '/') {
+ if (path.back() != '/') {
fname += "/";
}
fname += d.GetFile(i);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index f0d6519..92d5505 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -87,7 +87,7 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>(
cmSystemTools::ExpandListArgument(entry, files);
for (std::string const& file : files) {
if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") &&
- file[file.size() - 1] == '>') {
+ file.back() == '>') {
std::string objLibName = file.substr(17, file.size() - 18);
if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
@@ -218,6 +218,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->SetPropertyDefault("ANDROID_ASSETS_DIRECTORIES", nullptr);
this->SetPropertyDefault("ANDROID_ANT_ADDITIONAL_OPTIONS", nullptr);
this->SetPropertyDefault("BUILD_RPATH", nullptr);
+ this->SetPropertyDefault("BUILD_RPATH_USE_ORIGIN", nullptr);
this->SetPropertyDefault("INSTALL_NAME_DIR", nullptr);
this->SetPropertyDefault("INSTALL_RPATH", "");
this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF");
@@ -238,6 +239,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->SetPropertyDefault("AUTOMOC", nullptr);
this->SetPropertyDefault("AUTOUIC", nullptr);
this->SetPropertyDefault("AUTORCC", nullptr);
+ this->SetPropertyDefault("AUTOGEN_ORIGIN_DEPENDS", nullptr);
this->SetPropertyDefault("AUTOGEN_PARALLEL", nullptr);
this->SetPropertyDefault("AUTOMOC_COMPILER_PREDEFINES", nullptr);
this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", nullptr);
@@ -486,24 +488,10 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
return this->GetMakefile()->GetGlobalGenerator();
}
-void cmTarget::AddUtility(const std::string& u, cmMakefile* makefile)
+void cmTarget::AddUtility(std::string const& u, cmMakefile* mf)
{
- if (this->Utilities.insert(u).second && makefile) {
- this->UtilityBacktraces.insert(
- std::make_pair(u, makefile->GetBacktrace()));
- }
-}
-
-cmListFileBacktrace const* cmTarget::GetUtilityBacktrace(
- const std::string& u) const
-{
- std::map<std::string, cmListFileBacktrace>::const_iterator i =
- this->UtilityBacktraces.find(u);
- if (i == this->UtilityBacktraces.end()) {
- return nullptr;
- }
-
- return &i->second;
+ BT<std::string> util(u, mf ? mf->GetBacktrace() : cmListFileBacktrace());
+ this->Utilities.insert(util);
}
cmListFileBacktrace const& cmTarget::GetBacktrace() const
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 694de1c..aa2859d 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -190,10 +190,12 @@ public:
* name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE
* commands. It is not a full path nor does it have an extension.
*/
- void AddUtility(const std::string& u, cmMakefile* makefile = nullptr);
+ void AddUtility(std::string const& u, cmMakefile* mf = nullptr);
///! Get the utilities used by this target
- std::set<std::string> const& GetUtilities() const { return this->Utilities; }
- cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const;
+ std::set<BT<std::string>> const& GetUtilities() const
+ {
+ return this->Utilities;
+ }
///! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
@@ -307,8 +309,7 @@ private:
bool IsGeneratorProvided;
cmPropertyMap Properties;
std::set<std::string> SystemIncludeDirectories;
- std::set<std::string> Utilities;
- std::map<std::string, cmListFileBacktrace> UtilityBacktraces;
+ std::set<BT<std::string>> Utilities;
cmPolicies::PolicyMap PolicyMap;
std::string Name;
std::string InstallPath;
diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h
index b698db6..5ea0085 100644
--- a/Source/cmTargetDepend.h
+++ b/Source/cmTargetDepend.h
@@ -19,6 +19,7 @@ class cmTargetDepend
// mutable members to achieve a map with set syntax.
mutable bool Link;
mutable bool Util;
+ mutable cmListFileBacktrace Backtrace;
public:
cmTargetDepend(cmGeneratorTarget const* t)
@@ -42,8 +43,13 @@ public:
this->Link = true;
}
}
+ void SetBacktrace(cmListFileBacktrace const& bt) const
+ {
+ this->Backtrace = bt;
+ }
bool IsLink() const { return this->Link; }
bool IsUtil() const { return this->Util; }
+ cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
};
/** Unordered set of (direct) dependencies of a target. */
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 9a8fd96..1b8ee81 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -84,15 +84,6 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
this->SetError("called with invalid arguments");
return false;
}
- if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
- scope != "INTERFACE") {
- this->SetError("may only set INTERFACE properties on INTERFACE targets");
- return false;
- }
- if (this->Target->IsImported() && scope != "INTERFACE") {
- this->SetError("may only set INTERFACE properties on IMPORTED targets");
- return false;
- }
++argIndex;
@@ -101,10 +92,21 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) {
if (args[i] == "PUBLIC" || args[i] == "PRIVATE" ||
args[i] == "INTERFACE") {
- return this->PopulateTargetProperies(scope, content, prepend, system);
+ break;
}
content.push_back(args[i]);
}
+ if (!content.empty()) {
+ if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
+ scope != "INTERFACE") {
+ this->SetError("may only set INTERFACE properties on INTERFACE targets");
+ return false;
+ }
+ if (this->Target->IsImported() && scope != "INTERFACE") {
+ this->SetError("may only set INTERFACE properties on IMPORTED targets");
+ return false;
+ }
+ }
return this->PopulateTargetProperies(scope, content, prepend, system);
}
@@ -112,6 +114,9 @@ bool cmTargetPropCommandBase::PopulateTargetProperies(
const std::string& scope, const std::vector<std::string>& content,
bool prepend, bool system)
{
+ if (content.empty()) {
+ return true;
+ }
if (scope == "PRIVATE" || scope == "PUBLIC") {
if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
return false;
diff --git a/Source/cmVS141CLFlagTable.h b/Source/cmVS141CLFlagTable.h
index 2a9944a..7d219be 100644
--- a/Source/cmVS141CLFlagTable.h
+++ b/Source/cmVS141CLFlagTable.h
@@ -194,6 +194,8 @@ static cmVS7FlagTable cmVS141CLFlagTable[] = {
{ "EnablePREfast", "analyze", "", "true", 0 },
{ "UseFullPaths", "FC", "", "true", 0 },
{ "OmitDefaultLibName", "Zl", "", "true", 0 },
+ { "SupportJustMyCode", "JMC-", "", "false", 0 },
+ { "SupportJustMyCode", "JMC", "", "true", 0 },
// Bool Properties With Argument
{ "MultiProcessorCompilation", "MP", "", "true",
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 334c15b..e9a1a67 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -45,24 +45,21 @@ struct cmVisualStudio10TargetGenerator::Elem
bool HasContent = false;
std::string Tag;
- Elem(std::ostream& s)
+ Elem(std::ostream& s, const char* tag)
: S(s)
, Indent(0)
+ , Tag(tag)
{
+ this->StartElement();
}
Elem(const Elem&) = delete;
- Elem(Elem& par)
- : S(par.S)
- , Indent(par.Indent + 1)
- {
- par.SetHasElements();
- }
Elem(Elem& par, const char* tag)
: S(par.S)
, Indent(par.Indent + 1)
+ , Tag(tag)
{
par.SetHasElements();
- this->StartElement(tag);
+ this->StartElement();
}
void SetHasElements()
{
@@ -72,12 +69,7 @@ struct cmVisualStudio10TargetGenerator::Elem
}
}
std::ostream& WriteString(const char* line);
- Elem& StartElement(const std::string& tag)
- {
- this->Tag = tag;
- this->WriteString("<") << tag;
- return *this;
- }
+ void StartElement() { this->WriteString("<") << this->Tag; }
void Element(const char* tag, const std::string& val)
{
Elem(*this, tag).Content(val);
@@ -87,8 +79,6 @@ struct cmVisualStudio10TargetGenerator::Elem
this->S << " " << an << "=\"" << cmVS10EscapeAttr(av) << "\"";
return *this;
}
- // This method for now assumes that this->Tag has been set, e.g. by calling
- // StartElement().
void Content(const std::string& val)
{
if (!this->HasContent) {
@@ -379,8 +369,7 @@ void cmVisualStudio10TargetGenerator::Generate()
<< this->GlobalGenerator->Encoding() << "\"?>"
<< "\n";
{
- Elem e0(BuildFileStream);
- e0.StartElement("Project");
+ Elem e0(BuildFileStream, "Project");
e0.Attribute("DefaultTargets", "Build");
e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
e0.Attribute("xmlns",
@@ -921,8 +910,8 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
xamlType = "Page";
}
- Elem e2(e1);
- this->WriteSource(e2, xamlType, oi);
+ Elem e2(e1, xamlType);
+ this->WriteSource(e2, oi);
e2.SetHasElements();
if (this->ProjectType == csproj && !this->InSourceBuild) {
// add <Link> tag to written XAML source if necessary
@@ -1278,15 +1267,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
std::unique_ptr<Elem> spe2;
if (this->ProjectType != csproj) {
spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
- spe2 = cm::make_unique<Elem>(*spe1);
- this->WriteSource(*spe2, "CustomBuild", source);
+ spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild");
+ this->WriteSource(*spe2, source);
spe2->SetHasElements();
} else {
Elem e1(e0, "ItemGroup");
- Elem e2(e1);
+ Elem e2(e1, "None");
std::string link;
this->GetCSharpSourceLink(source, link);
- this->WriteSource(e2, "None", source);
+ this->WriteSource(e2, source);
e2.SetHasElements();
if (!link.empty()) {
e2.Element("Link", link);
@@ -1419,8 +1408,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
<< this->GlobalGenerator->Encoding() << "\"?>"
<< "\n";
{
- Elem e0(fout);
- e0.StartElement("Project");
+ Elem e0(fout, "Project");
e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
e0.Attribute("xmlns",
"http://schemas.microsoft.com/developer/msbuild/2003");
@@ -1571,8 +1559,8 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1,
cmSourceFile const* sf)
{
std::string const& fileName = sf->GetFullPath();
- Elem e2(e1);
- this->WriteSource(e2, "ClInclude", sf);
+ Elem e2(e1, "ClInclude");
+ this->WriteSource(e2, sf);
if (this->IsResxHeader(fileName)) {
e2.Element("FileType", "CppForm");
} else if (this->IsXamlHeader(fileName)) {
@@ -1740,8 +1728,8 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
}
- Elem e2(e1);
- this->WriteSource(e2, tool, sf);
+ Elem e2(e1, tool);
+ this->WriteSource(e2, sf);
if (toolHasSettings) {
e2.SetHasElements();
@@ -1861,7 +1849,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
- std::string const& tool,
cmSourceFile const* sf)
{
// Visual Studio tools append relative paths to the current dir, as in:
@@ -1897,11 +1884,10 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
}
}
ConvertToWindowsSlash(sourceFile);
- e2.StartElement(tool);
e2.Attribute("Include", sourceFile);
ToolSource toolSource = { sf, forceRelative };
- this->Tools[tool].push_back(toolSource);
+ this->Tools[e2.Tag].push_back(toolSource);
}
void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
@@ -2005,8 +1991,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
include_configs.begin(), include_configs.end(),
std::back_inserter(exclude_configs));
- Elem e2(e1);
- this->WriteSource(e2, tool, si.Source);
+ Elem e2(e1, tool);
+ this->WriteSource(e2, si.Source);
if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) {
this->OutputSourceSpecificFlags(e2, si.Source);
}
@@ -2582,8 +2568,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
configDefine += configName;
configDefine += "\"";
clOptions.AddDefine(configDefine);
- if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
- clOptions.AddDefine(exportMacro);
+ if (const std::string* exportMacro =
+ this->GeneratorTarget->GetExportMacro()) {
+ clOptions.AddDefine(*exportMacro);
}
if (this->MSTools) {
@@ -2879,8 +2866,9 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
configDefine += configName;
configDefine += "\"";
cudaOptions.AddDefine(configDefine);
- if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
- cudaOptions.AddDefine(exportMacro);
+ if (const std::string* exportMacro =
+ this->GeneratorTarget->GetExportMacro()) {
+ cudaOptions.AddDefine(*exportMacro);
}
// Get includes for this target
@@ -3884,15 +3872,13 @@ void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension(
void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
{
std::vector<std::string> sdkReferences;
- Elem e1(e0);
- bool hasWrittenItemGroup = false;
+ std::unique_ptr<Elem> spe1;
if (const char* vsSDKReferences =
this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) {
cmSystemTools::ExpandListArgument(vsSDKReferences, sdkReferences);
- e1.StartElement("ItemGroup");
- hasWrittenItemGroup = true;
+ spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
for (std::string const& ri : sdkReferences) {
- Elem(e1, "SDKReference").Attribute("Include", ri);
+ Elem(*spe1, "SDKReference").Attribute("Include", ri);
}
}
@@ -3908,19 +3894,20 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
if (desktopExtensionsVersion || mobileExtensionsVersion ||
iotExtensionsVersion) {
- if (!hasWrittenItemGroup) {
- e1.StartElement("ItemGroup");
+ if (!spe1) {
+ spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
}
if (desktopExtensionsVersion) {
- this->WriteSingleSDKReference(e1, "WindowsDesktop",
+ this->WriteSingleSDKReference(*spe1, "WindowsDesktop",
desktopExtensionsVersion);
}
if (mobileExtensionsVersion) {
- this->WriteSingleSDKReference(e1, "WindowsMobile",
+ this->WriteSingleSDKReference(*spe1, "WindowsMobile",
mobileExtensionsVersion);
}
if (iotExtensionsVersion) {
- this->WriteSingleSDKReference(e1, "WindowsIoT", iotExtensionsVersion);
+ this->WriteSingleSDKReference(*spe1, "WindowsIoT",
+ iotExtensionsVersion);
}
}
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 0dc03b6..b17b5f8 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -63,7 +63,7 @@ private:
void WriteExtraSource(Elem& e1, cmSourceFile const* sf);
void WriteNsightTegraConfigurationValues(Elem& e1,
std::string const& config);
- void WriteSource(Elem& e2, std::string const& tool, cmSourceFile const* sf);
+ void WriteSource(Elem& e2, cmSourceFile const* sf);
void WriteExcludeFromBuild(Elem& e2,
std::vector<size_t> const& exclude_configs);
void WriteAllSources(Elem& e0);
diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx
index a9acb3f..9353276 100644
--- a/Source/cmVisualStudioSlnParser.cxx
+++ b/Source/cmVisualStudioSlnParser.cxx
@@ -602,8 +602,8 @@ bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag,
}
const std::string& arg = cmSystemTools::TrimWhitespace(
fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1));
- if (arg[0] == '"') {
- if (arg[arg.size() - 1] != '"') {
+ if (arg.front() == '"') {
+ if (arg.back() != '"') {
this->LastResult.SetError(ResultErrorInputStructure,
state.GetCurrentLine());
return false;
@@ -620,7 +620,7 @@ bool cmVisualStudioSlnParser::ParseValue(const std::string& value,
const std::string& trimmed = cmSystemTools::TrimWhitespace(value);
if (trimmed.empty())
parsedLine.AddValue(trimmed);
- else if (trimmed[0] == '"' && trimmed[trimmed.size() - 1] == '"')
+ else if (trimmed.front() == '"' && trimmed.back() == '"')
parsedLine.AddQuotedValue(trimmed.substr(1, trimmed.size() - 2));
else
parsedLine.AddValue(trimmed);
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 889a5fb..35730b8 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -676,10 +676,25 @@ void cmake::SetArgs(const std::vector<std::string>& args,
#endif
else if (arg.find("-D", 0) == 0) {
// skip for now
+ // in case '-D var=val' is given, also skip the next
+ // in case '-Dvar=val' is given, don't skip the next
+ if (arg.size() == 2) {
+ ++i;
+ }
} else if (arg.find("-U", 0) == 0) {
// skip for now
+ // in case '-U var' is given, also skip the next
+ // in case '-Uvar' is given, don't skip the next
+ if (arg.size() == 2) {
+ ++i;
+ }
} else if (arg.find("-C", 0) == 0) {
// skip for now
+ // in case '-C path' is given, also skip the next
+ // in case '-Cpath' is given, don't skip the next
+ if (arg.size() == 2) {
+ ++i;
+ }
} else if (arg.find("-P", 0) == 0) {
// skip for now
i++;
@@ -2114,7 +2129,7 @@ void cmake::TruncateOutputLog(const char* fname)
inline std::string removeQuotes(const std::string& s)
{
- if (s[0] == '\"' && s[s.size() - 1] == '\"') {
+ if (s.front() == '\"' && s.back() == '\"') {
return s.substr(1, s.size() - 2);
}
return s;
@@ -2128,7 +2143,7 @@ void cmake::MarkCliAsUsed(const std::string& variable)
void cmake::GenerateGraphViz(const char* fileName) const
{
#ifdef CMAKE_BUILD_WITH_CMAKE
- cmGraphVizWriter gvWriter(this->GetGlobalGenerator()->GetLocalGenerators());
+ cmGraphVizWriter gvWriter(this->GetGlobalGenerator());
std::string settingsFile = this->GetHomeOutputDirectory();
settingsFile += "/CMakeGraphVizOptions.cmake";
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 0c5bbe2..1a10666 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -221,7 +221,7 @@ static int process(const std::string& srcfilename, const std::string& dfile,
while (std::getline(ss, line)) {
if (startsWith(line, prefix)) {
std::string inc = trimLeadingSpace(line.substr(prefix.size()).c_str());
- if (inc[inc.size() - 1] == '\r') // blech, stupid \r\n
+ if (inc.back() == '\r') // blech, stupid \r\n
inc = inc.substr(0, inc.size() - 1);
includes.push_back(inc);
} else {
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 1d2f741..45881aa 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -323,11 +323,15 @@ static int HandleCppCheck(const std::string& runCmd,
stdErr.find("(performance)") != std::string::npos ||
stdErr.find("(portability)") != std::string::npos ||
stdErr.find("(information)") != std::string::npos) {
- std::cerr << "Warning: cppcheck reported diagnostics:\n";
+ if (ret == 0) {
+ std::cerr << "Warning: cppcheck reported diagnostics:\n";
+ } else {
+ std::cerr << "Error: cppcheck reported failure:\n";
+ }
}
std::cerr << stdErr;
- // ignore errors so build continues
- return 0;
+
+ return ret;
}
typedef int (*CoCompileHandler)(const std::string&, const std::string&,
@@ -464,18 +468,18 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// If multiple source files specified,
// then destination must be directory
if ((args.size() > 4) &&
- (!cmSystemTools::FileIsDirectory(args[args.size() - 1]))) {
- std::cerr << "Error: Target (for copy command) \""
- << args[args.size() - 1] << "\" is not a directory.\n";
+ (!cmSystemTools::FileIsDirectory(args.back()))) {
+ std::cerr << "Error: Target (for copy command) \"" << args.back()
+ << "\" is not a directory.\n";
return 1;
}
// If error occurs we want to continue copying next files.
bool return_value = false;
for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) {
if (!cmSystemTools::cmCopyFile(args[cc].c_str(),
- args[args.size() - 1].c_str())) {
+ args.back().c_str())) {
std::cerr << "Error copying file \"" << args[cc] << "\" to \""
- << args[args.size() - 1] << "\".\n";
+ << args.back() << "\".\n";
return_value = true;
}
}
@@ -487,18 +491,18 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// If multiple source files specified,
// then destination must be directory
if ((args.size() > 4) &&
- (!cmSystemTools::FileIsDirectory(args[args.size() - 1]))) {
+ (!cmSystemTools::FileIsDirectory(args.back()))) {
std::cerr << "Error: Target (for copy_if_different command) \""
- << args[args.size() - 1] << "\" is not a directory.\n";
+ << args.back() << "\" is not a directory.\n";
return 1;
}
// If error occurs we want to continue copying next files.
bool return_value = false;
for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) {
- if (!cmSystemTools::CopyFileIfDifferent(
- args[cc].c_str(), args[args.size() - 1].c_str())) {
+ if (!cmSystemTools::CopyFileIfDifferent(args[cc].c_str(),
+ args.back().c_str())) {
std::cerr << "Error copying file (if different) from \"" << args[cc]
- << "\" to \"" << args[args.size() - 1] << "\".\n";
+ << "\" to \"" << args.back() << "\".\n";
return_value = true;
}
}
@@ -510,9 +514,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// If error occurs we want to continue copying next files.
bool return_value = false;
for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) {
- if (!cmSystemTools::CopyADirectory(args[cc], args[args.size() - 1])) {
+ if (!cmSystemTools::CopyADirectory(args[cc], args.back())) {
std::cerr << "Error copying directory from \"" << args[cc]
- << "\" to \"" << args[args.size() - 1] << "\".\n";
+ << "\" to \"" << args.back() << "\".\n";
return_value = true;
}
}
@@ -1517,6 +1521,8 @@ class cmVSLink
std::string ManifestFileRC;
std::string ManifestFileRes;
std::string TargetFile;
+ std::string MtPath;
+ std::string RcPath;
public:
cmVSLink(int type, bool verbose)
@@ -1660,6 +1666,12 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
} else if (cmHasLiteralPrefix(*arg, "--intdir=")) {
intDir = arg->substr(9);
++arg;
+ } else if (cmHasLiteralPrefix(*arg, "--rc=")) {
+ this->RcPath = arg->substr(5);
+ ++arg;
+ } else if (cmHasLiteralPrefix(*arg, "--mt=")) {
+ this->MtPath = arg->substr(5);
+ ++arg;
} else {
std::cerr << "unknown argument '" << *arg << "'\n";
return false;
@@ -1799,7 +1811,7 @@ int cmVSLink::LinkIncremental()
// Compile the resource file.
std::vector<std::string> rcCommand;
- rcCommand.push_back("rc");
+ rcCommand.push_back(this->RcPath.empty() ? "rc" : this->RcPath);
rcCommand.push_back("/fo" + this->ManifestFileRes);
rcCommand.push_back(this->ManifestFileRC);
if (!RunCommand("RC Pass 1", rcCommand, this->Verbose, FORMAT_DECIMAL)) {
@@ -1858,7 +1870,7 @@ int cmVSLink::LinkNonIncremental()
int cmVSLink::RunMT(std::string const& out, bool notify)
{
std::vector<std::string> mtCommand;
- mtCommand.push_back("mt");
+ mtCommand.push_back(this->MtPath.empty() ? "mt" : this->MtPath);
mtCommand.push_back("/nologo");
mtCommand.push_back("/manifest");
if (this->LinkGeneratesManifest) {
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 43aec00..a2fcc16 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -90,6 +90,7 @@ FOREACH(p
CMP0048 # CMake 3.0, Let the project command manage version variables.
CMP0056 # CMake 3.2, Honor link flags in try_compile() source-file signature.
CMP0063 # CMake 3.3, Honor visibility properties for all target types.
+ CMP0069 # CMake 3.9, INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.
)
IF(POLICY ${p})
CMAKE_POLICY(SET ${p} NEW)