summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt14
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/bills-comments.txt68
-rw-r--r--Source/CPack/cmCPackFreeBSDGenerator.cxx2
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx26
-rw-r--r--Source/CPack/cpack.cxx2
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx7
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.h2
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx40
-rw-r--r--Source/CTest/cmCTestGIT.cxx2
-rw-r--r--Source/CTest/cmCTestLaunch.cxx2
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx4
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h6
-rw-r--r--Source/CTest/cmCTestP4.cxx2
-rw-r--r--Source/CTest/cmCTestSVN.cxx4
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx33
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h28
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx4
-rw-r--r--Source/CTest/cmCTestTestHandler.h4
-rw-r--r--Source/CTest/cmParseJacocoCoverage.cxx1
-rw-r--r--Source/LexerParser/cmCommandArgumentParser.cxx2
-rw-r--r--Source/QtDialog/CMakeSetup.cxx3
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx1
-rw-r--r--Source/cmAddLibraryCommand.cxx4
-rw-r--r--Source/cmArgumentParser.cxx93
-rw-r--r--Source/cmArgumentParser.h143
-rw-r--r--Source/cmCMakeMinimumRequired.cxx2
-rw-r--r--Source/cmCMakePolicyCommand.cxx2
-rw-r--r--Source/cmCacheManager.h24
-rw-r--r--Source/cmCallVisualStudioMacro.cxx30
-rw-r--r--Source/cmCallVisualStudioMacro.h12
-rw-r--r--Source/cmCommandArgumentsHelper.cxx233
-rw-r--r--Source/cmCommandArgumentsHelper.h194
-rw-r--r--Source/cmCoreTryCompile.cxx22
-rw-r--r--Source/cmDepends.cxx154
-rw-r--r--Source/cmDepends.h20
-rw-r--r--Source/cmDependsC.cxx8
-rw-r--r--Source/cmDependsC.h5
-rw-r--r--Source/cmDependsFortran.cxx2
-rw-r--r--Source/cmDependsJava.cxx3
-rw-r--r--Source/cmDependsJava.h7
-rw-r--r--Source/cmDependsJavaParserHelper.cxx13
-rw-r--r--Source/cmExecuteProcessCommand.cxx280
-rw-r--r--Source/cmExportCommand.cxx102
-rw-r--r--Source/cmExportCommand.h24
-rw-r--r--Source/cmExternalMakefileProjectGenerator.h10
-rw-r--r--Source/cmExtraKateGenerator.cxx2
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx8
-rw-r--r--Source/cmFileCommand.cxx155
-rw-r--r--Source/cmFileInstaller.cxx2
-rw-r--r--Source/cmFileTime.h2
-rw-r--r--Source/cmFileTimeCache.cxx11
-rw-r--r--Source/cmFileTimeCache.h11
-rw-r--r--Source/cmGeneratorExpressionNode.cxx358
-rw-r--r--Source/cmGeneratorTarget.cxx190
-rw-r--r--Source/cmGeneratorTarget.h23
-rw-r--r--Source/cmGhsMultiGpj.cxx4
-rw-r--r--Source/cmGhsMultiGpj.h3
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx449
-rw-r--r--Source/cmGhsMultiTargetGenerator.h25
-rw-r--r--Source/cmGlobVerificationManager.h12
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx2
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.h4
-rw-r--r--Source/cmGlobalGenerator.cxx118
-rw-r--r--Source/cmGlobalGenerator.h22
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx476
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h76
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h2
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.h2
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.h2
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h2
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx6
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx8
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h2
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h6
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx1
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.h2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx48
-rw-r--r--Source/cmGlobalXCodeGenerator.h8
-rw-r--r--Source/cmInstallCommand.cxx175
-rw-r--r--Source/cmInstallCommandArguments.cxx66
-rw-r--r--Source/cmInstallCommandArguments.h35
-rw-r--r--Source/cmInstallExportGenerator.cxx2
-rw-r--r--Source/cmInstallGenerator.cxx2
-rw-r--r--Source/cmInstallTargetsCommand.cxx4
-rw-r--r--Source/cmLoadCommandCommand.cxx2
-rw-r--r--Source/cmLocalGenerator.cxx38
-rw-r--r--Source/cmLocalGenerator.h12
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx6
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h11
-rw-r--r--Source/cmLocalVisualStudio10Generator.h2
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx10
-rw-r--r--Source/cmLocalVisualStudio7Generator.h2
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx1
-rw-r--r--Source/cmLocalXCodeGenerator.h2
-rw-r--r--Source/cmMakefile.h16
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx3
-rw-r--r--Source/cmOutputConverter.h2
-rw-r--r--Source/cmParseArgumentsCommand.cxx159
-rw-r--r--Source/cmPolicies.cxx8
-rw-r--r--Source/cmPolicies.h12
-rw-r--r--Source/cmProjectCommand.cxx48
-rw-r--r--Source/cmProjectCommand.h1
-rw-r--r--Source/cmQtAutoGen.cxx164
-rw-r--r--Source/cmQtAutoGen.h62
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx30
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.h30
-rw-r--r--Source/cmQtAutoGenInitializer.cxx133
-rw-r--r--Source/cmQtAutoGenInitializer.h20
-rw-r--r--Source/cmQtAutoGenerator.cxx483
-rw-r--r--Source/cmQtAutoGenerator.h153
-rw-r--r--Source/cmQtAutoGeneratorRcc.cxx666
-rw-r--r--Source/cmQtAutoMocUic.cxx (renamed from Source/cmQtAutoGeneratorMocUic.cxx)1203
-rw-r--r--Source/cmQtAutoMocUic.h (renamed from Source/cmQtAutoGeneratorMocUic.h)295
-rw-r--r--Source/cmQtAutoRcc.cxx516
-rw-r--r--Source/cmQtAutoRcc.h (renamed from Source/cmQtAutoGeneratorRcc.h)71
-rw-r--r--Source/cmRST.cxx8
-rw-r--r--Source/cmSetPropertyCommand.cxx2
-rw-r--r--Source/cmSourceFile.h8
-rw-r--r--Source/cmSourceGroupCommand.cxx1
-rw-r--r--Source/cmState.h2
-rw-r--r--Source/cmStringCommand.cxx61
-rw-r--r--Source/cmStringCommand.h1
-rw-r--r--Source/cmSystemTools.cxx6
-rw-r--r--Source/cmSystemTools.h22
-rw-r--r--Source/cmTarget.cxx984
-rw-r--r--Source/cmTarget.h233
-rw-r--r--Source/cmTargetPropertyComputer.cxx2
-rw-r--r--Source/cmTargetPropertyComputer.h2
-rw-r--r--Source/cmTest.h4
-rw-r--r--Source/cmUseMangledMesaCommand.cxx2
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx69
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h2
-rw-r--r--Source/cmWorkerPool.cxx770
-rw-r--r--Source/cmWorkerPool.h219
-rw-r--r--Source/cmXMLWriter.cxx2
-rw-r--r--Source/cmake.cxx5
-rw-r--r--Source/cmake.h48
-rw-r--r--Source/cmcmd.cxx155
-rw-r--r--Source/cmcmd.h14
-rw-r--r--Source/kwsys/CMakeLists.txt17
-rw-r--r--Source/kwsys/DynamicLoader.cxx110
-rw-r--r--Source/kwsys/DynamicLoader.hxx.in15
-rw-r--r--Source/kwsys/SystemTools.cxx8
-rw-r--r--Source/kwsys/testDynamicLoader.cxx28
-rw-r--r--Source/kwsys/testDynloadImpl.c10
-rw-r--r--Source/kwsys/testDynloadImpl.h15
-rw-r--r--Source/kwsys/testDynloadUse.c15
152 files changed, 5999 insertions, 4982 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 52f6742..49f237f 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -143,6 +143,8 @@ set(SRCS
cmAffinity.cxx
cmAffinity.h
cmArchiveWrite.cxx
+ cmArgumentParser.cxx
+ cmArgumentParser.h
cmBase32.cxx
cmCacheManager.cxx
cmCacheManager.h
@@ -348,10 +350,10 @@ set(SRCS
cmQtAutoGenGlobalInitializer.h
cmQtAutoGenInitializer.cxx
cmQtAutoGenInitializer.h
- cmQtAutoGeneratorMocUic.cxx
- cmQtAutoGeneratorMocUic.h
- cmQtAutoGeneratorRcc.cxx
- cmQtAutoGeneratorRcc.h
+ cmQtAutoMocUic.cxx
+ cmQtAutoMocUic.h
+ cmQtAutoRcc.cxx
+ cmQtAutoRcc.h
cmRST.cxx
cmRST.h
cmScriptGenerator.h
@@ -389,6 +391,8 @@ set(SRCS
cmVariableWatch.h
cmVersion.cxx
cmVersion.h
+ cmWorkerPool.cxx
+ cmWorkerPool.h
cmWorkingDirectory.cxx
cmWorkingDirectory.h
cmXMLParser.cxx
@@ -443,8 +447,6 @@ set(SRCS
cmCMakeMinimumRequired.h
cmCMakePolicyCommand.cxx
cmCMakePolicyCommand.h
- cmCommandArgumentsHelper.cxx
- cmCommandArgumentsHelper.h
cmConditionEvaluator.cxx
cmConditionEvaluator.h
cmConfigureFileCommand.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index ea96cc2..636d332 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 14)
-set(CMake_VERSION_PATCH 20190323)
+set(CMake_VERSION_PATCH 20190416)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CPack/bills-comments.txt b/Source/CPack/bills-comments.txt
deleted file mode 100644
index 1aaf9af..0000000
--- a/Source/CPack/bills-comments.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-cpack.cxx
-
-cmCPackGenerators -- creates cmCPackGenericGenerator's via NewGenerator
- - a cmCPackGenericGenerator factory
-
-
-cmCPackGenericGenerator::Initialize
- this->InitializeInternal
- CPACK_INCLUDE_TOPLEVEL_DIRECTORY = 0 turns off
-
-
-// binary package run
-cmCPackGenericGenerator::ProcessGenerator // DoPackage
- cmCPackGenericGenerator::PrepareNames -- sets a bunch of CPACK_vars
- cmCPackGenericGenerator::InstallProject
- run preinstall (make preinstall/fast)
- call ReadListFile(cmake_install.cmake)
- glob recurse in install directory to get list of files
- this->CompressFiles with the list of files
-
-
-// source package run
-cmCPackGenericGenerator::ProcessGenerator // DoPackage
- cmCPackGenericGenerator::PrepareNames -- sets a bunch of CPACK_vars
- cmCPackGenericGenerator::InstallProject -->
- if set CPACK_INSTALLED_DIRECTORIES
- glob the files in that directory
- copy those files to the tmp install directory _CPack something
- glob recurse in install directory to get list of files
- this->CompressFiles with the list of files
-
-
-cmCPackGenericGenerator::InstallProject is used for both source and binary
-packages. It is controlled based on values set in CPACK_ variables.
-
-
-InstallProject
- 1. CPACK_INSTALL_COMMANDS - a list of commands used to install the package
-
- 2. CPACK_INSTALLED_DIRECTORIES - copy this directory to CPACK_TEMPORARY_DIRECTORY
-
- 3. CPACK_INSTALL_CMAKE_PROJECTS - a cmake install script
- - run make preinstall
- - run cmake_install.cmake
- - set CMAKE_INSTALL_PREFIX to the temp directory
- - CPACK_BUILD_CONFIG check this and set the BUILD_TYPE to it
- - ReadListFile on the install script cmake_install.cmake
- - run strip on the executables and libraries if CPACK_STRIP_FILES is TRUE
-
-Recommendations:
-
-rename cmCPackGenerators to cmCPackGeneratorFactory
-
-rename cmCPackGenericGenerator --> cmCPackGenerator
-
-rename cmCPackGenericGenerator::ProcessGenerator -> cmCPackGenerator::DoPackage
-
-
-break up cmCPackGenerator::InstallProject so it calls the following:
-
-// run user provided install commands
- cmCPackGenerator::RunInstallCommands();
-// copy entire directories that need no processing like source trees
- cmCPackGenerator::CopyPreInstalledDirectories();
-// run the cmake install scripts if provided
- cmCPackGenerator::RunCMakeInstallScripts()
-
--
diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx
index dd8127d..9fdafa4 100644
--- a/Source/CPack/cmCPackFreeBSDGenerator.cxx
+++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx
@@ -181,7 +181,7 @@ public:
{
s << "{\n";
for (std::string const& elem : value) {
- s << " \"" << elem << "\": {\"origin\": \"" << elem << "\"},\n";
+ s << " \"" << elem << R"(": {"origin": ")" << elem << "\"},\n";
}
s << '}';
}
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 6afd7d5..e2020c5 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -182,7 +182,7 @@ int cmCPackNSISGenerator::PackageFiles()
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC", "");
this->SetOptionIfNotSet("CPACK_NSIS_PAGE_COMPONENTS", "");
this->SetOptionIfNotSet("CPACK_NSIS_FULL_INSTALL",
- "File /r \"${INST_DIR}\\*.*\"");
+ R"(File /r "${INST_DIR}\*.*")");
this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTIONS", "");
this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTION_LIST", "");
this->SetOptionIfNotSet("CPACK_NSIS_SECTION_SELECTED_VARS", "");
@@ -242,7 +242,7 @@ int cmCPackNSISGenerator::PackageFiles()
}
// Add this component to the various section lists.
- sectionList += " !insertmacro \"${MacroName}\" \"";
+ sectionList += R"( !insertmacro "${MacroName}" ")";
sectionList += comp.first;
sectionList += "\"\n";
selectedVarsList += "Var " + comp.first + "_selected\n";
@@ -494,10 +494,10 @@ int cmCPackNSISGenerator::InitializeInternal()
std::string execName = *it;
++it;
std::string linkName = *it;
- str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
- << ".lnk\" \"$INSTDIR\\" << cpackNsisExecutablesDirectory << "\\"
+ str << R"( CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\)" << linkName
+ << R"(.lnk" "$INSTDIR\)" << cpackNsisExecutablesDirectory << "\\"
<< execName << ".exe\"" << std::endl;
- deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
+ deleteStr << R"( Delete "$SMPROGRAMS\$MUI_TEMP\)" << linkName
<< ".lnk\"" << std::endl;
// see if CPACK_CREATE_DESKTOP_LINK_ExeName is on
// if so add a desktop link
@@ -507,7 +507,7 @@ int cmCPackNSISGenerator::InitializeInternal()
execName) != cpackPackageDesktopLinksVector.end()) {
str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
str << " CreateShortCut \"$DESKTOP\\" << linkName
- << ".lnk\" \"$INSTDIR\\" << cpackNsisExecutablesDirectory << "\\"
+ << R"(.lnk" "$INSTDIR\)" << cpackNsisExecutablesDirectory << "\\"
<< execName << ".exe\"" << std::endl;
deleteStr << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
deleteStr << " Delete \"$DESKTOP\\" << linkName << ".lnk\""
@@ -563,15 +563,15 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str,
++it;
std::string linkName = *it;
if (!url) {
- str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
- << ".lnk\" \"$INSTDIR\\" << sourceName << "\"" << std::endl;
- deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
+ str << R"( CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\)" << linkName
+ << R"(.lnk" "$INSTDIR\)" << sourceName << "\"" << std::endl;
+ deleteStr << R"( Delete "$SMPROGRAMS\$MUI_TEMP\)" << linkName
<< ".lnk\"" << std::endl;
} else {
- str << " WriteINIStr \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
- << ".url\" \"InternetShortcut\" \"URL\" \"" << sourceName << "\""
+ str << R"( WriteINIStr "$SMPROGRAMS\$STARTMENU_FOLDER\)" << linkName
+ << R"(.url" "InternetShortcut" "URL" ")" << sourceName << "\""
<< std::endl;
- deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
+ deleteStr << R"( Delete "$SMPROGRAMS\$MUI_TEMP\)" << linkName
<< ".url\"" << std::endl;
}
// see if CPACK_CREATE_DESKTOP_LINK_ExeName is on
@@ -581,7 +581,7 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str,
if (this->IsSet(desktop)) {
str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
str << " CreateShortCut \"$DESKTOP\\" << linkName
- << ".lnk\" \"$INSTDIR\\" << sourceName << "\"" << std::endl;
+ << R"(.lnk" "$INSTDIR\)" << sourceName << "\"" << std::endl;
deleteStr << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
deleteStr << " Delete \"$DESKTOP\\" << linkName << ".lnk\""
<< std::endl;
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index da9575b..3ceb824 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -82,7 +82,7 @@ int cpackDefinitionArgument(const char* argument, const char* cValue,
return 0;
}
std::string key = value.substr(0, pos);
- value = value.c_str() + pos + 1;
+ value = value.substr(pos + 1);
def->Map[key] = value;
cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG,
"Set CPack variable: " << key << " to \"" << value << "\""
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index a7d4455..9ad9669 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -126,11 +126,12 @@ public:
cmSystemTools::SetStdoutCallback([&s](std::string const& m) { s += m; });
cmSystemTools::SetStderrCallback([&s](std::string const& m) { s += m; });
- this->CM.SetProgressCallback(
- [&s](const std::string& msg, float /*unused*/) {
+ this->CM.SetProgressCallback([&s](const std::string& msg, float prog) {
+ if (prog < 0) {
s += msg;
s += "\n";
- });
+ }
+ });
}
~cmCTestBuildAndTestCaptureRAII()
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h
index 5e6d0aa..2d47b15 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -44,7 +44,7 @@ public:
void Initialize() override;
protected:
- ///! Run CMake and build a test and then run it as a single test.
+ //! Run CMake and build a test and then run it as a single test.
int RunCMakeAndTest(std::string* output);
int RunCMake(std::string* outstring, std::ostringstream& out,
std::string& cmakeOutString, cmake* cm);
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 8ea9a83..1e17e1c 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -32,13 +32,13 @@ static const char* cmCTestErrorMatches[] = {
"^Error: ",
"^Error ",
"[0-9] ERROR: ",
- "^\"[^\"]+\", line [0-9]+: [^Ww]",
+ R"(^"[^"]+", line [0-9]+: [^Ww])",
"^cc[^C]*CC: ERROR File = ([^,]+), Line = ([0-9]+)",
"^ld([^:])*:([ \\t])*ERROR([^:])*:",
- "^ild:([ \\t])*\\(undefined symbol\\)",
+ R"(^ild:([ \t])*\(undefined symbol\))",
"([^ :]+) : (error|fatal error|catastrophic error)",
"([^:]+): (Error:|error|undefined reference|multiply defined)",
- "([^:]+)\\(([^\\)]+)\\) ?: (error|fatal error|catastrophic error)",
+ R"(([^:]+)\(([^\)]+)\) ?: (error|fatal error|catastrophic error))",
"^fatal error C[0-9]+:",
": syntax error ",
"^collect2: ld returned 1 exit status",
@@ -50,14 +50,14 @@ static const char* cmCTestErrorMatches[] = {
"^CMake Error.*:",
":[ \\t]cannot find",
":[ \\t]can't find",
- ": \\*\\*\\* No rule to make target [`'].*\\'. Stop",
- ": \\*\\*\\* No targets specified and no makefile found",
+ R"(: \*\*\* No rule to make target [`'].*\'. Stop)",
+ R"(: \*\*\* No targets specified and no makefile found)",
": Invalid loader fixup for symbol",
": Invalid fixups exist",
": Can't find library for",
": internal link edit command failed",
": Unrecognized option [`'].*\\'",
- "\", line [0-9]+\\.[0-9]+: [0-9]+-[0-9]+ \\([^WI]\\)",
+ R"(", line [0-9]+\.[0-9]+: [0-9]+-[0-9]+ \([^WI]\))",
"ld: 0706-006 Cannot find or open library file: -l ",
"ild: \\(argument error\\) can't find library argument ::",
"^could not be found and will not be loaded.",
@@ -66,11 +66,11 @@ static const char* cmCTestErrorMatches[] = {
"ld: 0711-993 Error occurred while writing to the output file:",
"ld: fatal: ",
"final link failed:",
- "make: \\*\\*\\*.*Error",
- "make\\[.*\\]: \\*\\*\\*.*Error",
- "\\*\\*\\* Error code",
+ R"(make: \*\*\*.*Error)",
+ R"(make\[.*\]: \*\*\*.*Error)",
+ R"(\*\*\* Error code)",
"nternal error:",
- "Makefile:[0-9]+: \\*\\*\\* .* Stop\\.",
+ R"(Makefile:[0-9]+: \*\*\* .* Stop\.)",
": No such file or directory",
": Invalid argument",
"^The project cannot be built\\.",
@@ -101,19 +101,19 @@ static const char* cmCTestWarningMatches[] = {
"^cc[^C]*CC: WARNING File = ([^,]+), Line = ([0-9]+)",
"^ld([^:])*:([ \\t])*WARNING([^:])*:",
"([^:]+): warning ([0-9]+):",
- "^\"[^\"]+\", line [0-9]+: [Ww](arning|arnung)",
+ R"(^"[^"]+", line [0-9]+: [Ww](arning|arnung))",
"([^:]+): warning[ \\t]*[0-9]+[ \\t]*:",
"^(Warning|Warnung) ([0-9]+):",
"^(Warning|Warnung)[ :]",
"WARNING: ",
"([^ :]+) : warning",
"([^:]+): warning",
- "\", line [0-9]+\\.[0-9]+: [0-9]+-[0-9]+ \\([WI]\\)",
+ R"(", line [0-9]+\.[0-9]+: [0-9]+-[0-9]+ \([WI]\))",
"^cxx: Warning:",
".*file: .* has no symbols",
"([^ :]+):([0-9]+): (Warning|Warnung)",
"\\([0-9]*\\): remark #[0-9]*",
- "\".*\", line [0-9]+: remark\\([0-9]*\\):",
+ R"(".*", line [0-9]+: remark\([0-9]*\):)",
"cc-[0-9]* CC: REMARK File = .*, Line = [0-9]*",
"^CMake Warning.*:",
"^\\[WARNING\\]",
@@ -121,9 +121,9 @@ static const char* cmCTestWarningMatches[] = {
};
static const char* cmCTestWarningExceptions[] = {
- "/usr/.*/X11/Xlib\\.h:[0-9]+: war.*: ANSI C\\+\\+ forbids declaration",
- "/usr/.*/X11/Xutil\\.h:[0-9]+: war.*: ANSI C\\+\\+ forbids declaration",
- "/usr/.*/X11/XResource\\.h:[0-9]+: war.*: ANSI C\\+\\+ forbids declaration",
+ R"(/usr/.*/X11/Xlib\.h:[0-9]+: war.*: ANSI C\+\+ forbids declaration)",
+ R"(/usr/.*/X11/Xutil\.h:[0-9]+: war.*: ANSI C\+\+ forbids declaration)",
+ R"(/usr/.*/X11/XResource\.h:[0-9]+: war.*: ANSI C\+\+ forbids declaration)",
"WARNING 84 :",
"WARNING 47 :",
"makefile:",
@@ -150,8 +150,8 @@ struct cmCTestBuildCompileErrorWarningRex
static cmCTestBuildCompileErrorWarningRex cmCTestWarningErrorFileLine[] = {
{ "^Warning W[0-9]+ ([a-zA-Z.\\:/0-9_+ ~-]+) ([0-9]+):", 1, 2 },
{ "^([a-zA-Z./0-9_+ ~-]+):([0-9]+):", 1, 2 },
- { "^([a-zA-Z.\\:/0-9_+ ~-]+)\\(([0-9]+)\\)", 1, 2 },
- { "^[0-9]+>([a-zA-Z.\\:/0-9_+ ~-]+)\\(([0-9]+)\\)", 1, 2 },
+ { R"(^([a-zA-Z.\:/0-9_+ ~-]+)\(([0-9]+)\))", 1, 2 },
+ { R"(^[0-9]+>([a-zA-Z.\:/0-9_+ ~-]+)\(([0-9]+)\))", 1, 2 },
{ "^([a-zA-Z./0-9_+ ~-]+)\\(([0-9]+)\\)", 1, 2 },
{ "\"([a-zA-Z./0-9_+ ~-]+)\", line ([0-9]+)", 1, 2 },
{ "File = ([a-zA-Z./0-9_+ ~-]+), Line = ([0-9]+)", 1, 2 },
@@ -387,7 +387,7 @@ int cmCTestBuildHandler::ProcessHandler()
std::string srcdirrep;
for (cc = srcdir.size() - 2; cc > 0; cc--) {
if (srcdir[cc] == '/') {
- srcdirrep = srcdir.c_str() + cc;
+ srcdirrep = srcdir.substr(cc);
srcdirrep = "/..." + srcdirrep;
srcdir = srcdir.substr(0, cc + 1);
break;
@@ -401,7 +401,7 @@ int cmCTestBuildHandler::ProcessHandler()
std::string bindirrep;
for (cc = bindir.size() - 2; cc > 0; cc--) {
if (bindir[cc] == '/') {
- bindirrep = bindir.c_str() + cc;
+ bindirrep = bindir.substr(cc);
bindirrep = "/..." + bindirrep;
bindir = bindir.substr(0, cc + 1);
break;
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 11cd005..9d9761c 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -547,7 +547,7 @@ private:
{
// Look for header fields that we need.
if (cmHasLiteralPrefix(this->Line, "commit ")) {
- this->Rev.Rev = this->Line.c_str() + 7;
+ this->Rev.Rev = this->Line.substr(7);
} else if (cmHasLiteralPrefix(this->Line, "author ")) {
Person author;
this->ParsePerson(this->Line.c_str() + 7, author);
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index 5e66e05..a96513e 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -308,7 +308,7 @@ void cmCTestLaunch::LoadLabels()
if (line[0] == ' ') {
// Label lines appear indented by one space.
if (inTarget || inSource) {
- this->Labels.insert(line.c_str() + 1);
+ this->Labels.insert(line.substr(1));
}
} else if (!this->OptionSource.empty() && !inSource) {
// Non-indented lines specify a source file name. The first one
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 22c8469..b09e7bb 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -815,9 +815,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*==");
cmsys::RegularExpression vgFIM(
- "== .*Invalid free\\(\\) / delete / delete\\[\\]");
+ R"(== .*Invalid free\(\) / delete / delete\[\])");
cmsys::RegularExpression vgFMM(
- "== .*Mismatched free\\(\\) / delete / delete \\[\\]");
+ R"(== .*Mismatched free\(\) / delete / delete \[\])");
cmsys::RegularExpression vgMLK1(
"== .*[0-9,]+ bytes in [0-9,]+ blocks are definitely lost"
" in loss record [0-9,]+ of [0-9,]+");
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index 8880dac..746d72c 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -114,7 +114,7 @@ private:
// this type of checker
void InitializeResultsVectors();
- ///! Initialize memory checking subsystem.
+ //! Initialize memory checking subsystem.
bool InitializeMemoryChecking();
/**
@@ -143,11 +143,11 @@ private:
void PostProcessTest(cmCTestTestResult& res, int test);
void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test);
- ///! append MemoryTesterOutputFile to the test log
+ //! append MemoryTesterOutputFile to the test log
void AppendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res,
std::string const& filename);
- ///! generate the output filename for the given test index
+ //! generate the output filename for the given test index
void TestOutputFileNames(int test, std::vector<std::string>& files);
};
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
index 7adf640..aa42810 100644
--- a/Source/CTest/cmCTestP4.cxx
+++ b/Source/CTest/cmCTestP4.cxx
@@ -194,7 +194,7 @@ public:
{
this->SetLog(&P4->Log, prefix);
this->RegexHeader.compile("^Change ([0-9]+) by (.+)@(.+) on (.*)$");
- this->RegexDiff.compile("^\\.\\.\\. (.*)#[0-9]+ ([^ ]+)$");
+ this->RegexDiff.compile(R"(^\.\.\. (.*)#[0-9]+ ([^ ]+)$)");
}
private:
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index b7a4e4c..04749b7 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -515,7 +515,7 @@ private:
if (path.size() > this->SVN->SourceDirectory.size() &&
strncmp(path.c_str(), this->SVN->SourceDirectory.c_str(),
this->SVN->SourceDirectory.size()) == 0) {
- local_path = path.c_str() + this->SVN->SourceDirectory.size() + 1;
+ local_path = path.substr(this->SVN->SourceDirectory.size() + 1);
} else {
local_path = path;
}
@@ -554,7 +554,7 @@ std::string cmCTestSVN::SVNInfo::BuildLocalPath(std::string const& path) const
// Add path with base prefix removed
if (path.size() > this->Base.size() &&
strncmp(path.c_str(), this->Base.c_str(), this->Base.size()) == 0) {
- local_path += (path.c_str() + this->Base.size());
+ local_path += path.substr(this->Base.size());
} else {
local_path += path;
}
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index e31d982..afc3e67 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -12,6 +12,29 @@
class cmExecutionStatus;
+cmCTestSubmitCommand::cmCTestSubmitCommand()
+{
+ this->PartsMentioned = false;
+ this->FilesMentioned = false;
+ this->InternalTest = false;
+ this->RetryCount = "";
+ this->RetryDelay = "";
+ this->CDashUpload = false;
+ this->Arguments[cts_BUILD_ID] = "BUILD_ID";
+ this->Last = cts_LAST;
+}
+
+/**
+ * This is a virtual constructor for the command.
+ */
+cmCommand* cmCTestSubmitCommand::Clone()
+{
+ cmCTestSubmitCommand* ni = new cmCTestSubmitCommand;
+ ni->CTest = this->CTest;
+ ni->CTestScriptHandler = this->CTestScriptHandler;
+ return ni;
+}
+
cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
{
const char* submitURL = !this->SubmitURL.empty()
@@ -111,7 +134,15 @@ bool cmCTestSubmitCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
this->CDashUpload = !args.empty() && args[0] == "CDASH_UPLOAD";
- return this->cmCTestHandlerCommand::InitialPass(args, status);
+
+ bool ret = this->cmCTestHandlerCommand::InitialPass(args, status);
+
+ if (this->Values[cts_BUILD_ID] && *this->Values[cts_BUILD_ID]) {
+ this->Makefile->AddDefinition(this->Values[cts_BUILD_ID],
+ this->CTest->GetBuildID().c_str());
+ }
+
+ return ret;
}
bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg)
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index 4b1bb26..1e27046 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -25,26 +25,8 @@ class cmExecutionStatus;
class cmCTestSubmitCommand : public cmCTestHandlerCommand
{
public:
- cmCTestSubmitCommand()
- {
- this->PartsMentioned = false;
- this->FilesMentioned = false;
- this->InternalTest = false;
- this->RetryCount = "";
- this->RetryDelay = "";
- this->CDashUpload = false;
- }
-
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() override
- {
- cmCTestSubmitCommand* ni = new cmCTestSubmitCommand;
- ni->CTest = this->CTest;
- ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
- }
+ cmCTestSubmitCommand();
+ cmCommand* Clone() override;
bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status) override;
@@ -75,6 +57,12 @@ protected:
ArgumentDoingLast2
};
+ enum
+ {
+ cts_BUILD_ID = ct_LAST,
+ cts_LAST
+ };
+
bool PartsMentioned;
std::set<cmCTest::Part> Parts;
bool FilesMentioned;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index c9783e4..0ed56c8 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -2265,8 +2265,8 @@ bool cmCTestTestHandler::SetTestsProperties(
size_t pos = val.find_first_of('=');
if (pos != std::string::npos) {
std::string mKey = val.substr(0, pos);
- const char* mVal = val.c_str() + pos + 1;
- rt.Measurements[mKey] = mVal;
+ std::string mVal = val.substr(pos + 1);
+ rt.Measurements[mKey] = std::move(mVal);
} else {
rt.Measurements[val] = "1";
}
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 17d5f3f..7f3f5e4 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -59,7 +59,7 @@ public:
*/
void PopulateCustomVectors(cmMakefile* mf) override;
- ///! Control the use of the regular expresisons, call these methods to turn
+ //! Control the use of the regular expresisons, call these methods to turn
/// them on
void UseIncludeRegExp();
void UseExcludeRegExp();
@@ -78,7 +78,7 @@ public:
this->CustomMaximumFailedTestOutputSize = n;
}
- ///! pass the -I argument down
+ //! pass the -I argument down
void SetTestsToRunInformation(const char*);
cmCTestTestHandler();
diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx
index 61c5dcb..b78142a 100644
--- a/Source/CTest/cmParseJacocoCoverage.cxx
+++ b/Source/CTest/cmParseJacocoCoverage.cxx
@@ -29,6 +29,7 @@ protected:
this->PackageName = atts[1];
this->PackagePath.clear();
} else if (name == "sourcefile") {
+ this->FilePath.clear();
std::string fileName = atts[1];
if (this->PackagePath.empty()) {
diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx
index 68b9e6c..b965b32 100644
--- a/Source/LexerParser/cmCommandArgumentParser.cxx
+++ b/Source/LexerParser/cmCommandArgumentParser.cxx
@@ -513,7 +513,7 @@ static const yytype_uint8 yyrline[] =
static const char *const yytname[] =
{
"$end", "error", "$undefined", "cal_ENVCURLY", "cal_NCURLY",
- "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"",
+ "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", R"("\\")",
"cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start",
"GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable",
"EnvVarName", "MultipleIds", "ID", YY_NULLPTR
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index cd30ad5..8d9a50c 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -48,6 +48,9 @@ Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
#if defined(USE_QWindowsIntegrationPlugin)
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
+# if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
+Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin);
+# endif
#endif
int main(int argc, char** argv)
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 72cce9f..5f6ccca 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -303,7 +303,6 @@ void CMakeSetupDialog::initialize()
#ifdef QT_WINEXTRAS
this->TaskbarButton = new QWinTaskbarButton(this);
this->TaskbarButton->setWindow(this->windowHandle());
- this->TaskbarButton->setOverlayIcon(QIcon(":/loading.png"));
#endif
}
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index 5149333..adf4464 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -222,7 +222,9 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
aliasedType != cmStateEnums::STATIC_LIBRARY &&
aliasedType != cmStateEnums::MODULE_LIBRARY &&
aliasedType != cmStateEnums::OBJECT_LIBRARY &&
- aliasedType != cmStateEnums::INTERFACE_LIBRARY) {
+ aliasedType != cmStateEnums::INTERFACE_LIBRARY &&
+ !(aliasedType == cmStateEnums::UNKNOWN_LIBRARY &&
+ aliasedTarget->IsImported())) {
std::ostringstream e;
e << "cannot create ALIAS target \"" << libName << "\" because target \""
<< aliasedName << "\" is not a library.";
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
new file mode 100644
index 0000000..751d117
--- /dev/null
+++ b/Source/cmArgumentParser.cxx
@@ -0,0 +1,93 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmArgumentParser.h"
+
+#include <algorithm>
+#include <type_traits>
+
+namespace ArgumentParser {
+
+auto ActionMap::Emplace(cm::string_view name, Action action)
+ -> std::pair<iterator, bool>
+{
+ auto const it =
+ std::lower_bound(this->begin(), this->end(), name,
+ [](value_type const& elem, cm::string_view const& k) {
+ return elem.first < k;
+ });
+ return (it != this->end() && it->first == name)
+ ? std::make_pair(it, false)
+ : std::make_pair(this->emplace(it, name, std::move(action)), true);
+}
+
+auto ActionMap::Find(cm::string_view name) const -> const_iterator
+{
+ auto const it =
+ std::lower_bound(this->begin(), this->end(), name,
+ [](value_type const& elem, cm::string_view const& k) {
+ return elem.first < k;
+ });
+ return (it != this->end() && it->first == name) ? it : this->end();
+}
+
+void Instance::Bind(bool& val)
+{
+ val = true;
+ this->CurrentString = nullptr;
+ this->CurrentList = nullptr;
+ this->ExpectValue = false;
+}
+
+void Instance::Bind(std::string& val)
+{
+ this->CurrentString = &val;
+ this->CurrentList = nullptr;
+ this->ExpectValue = true;
+}
+
+void Instance::Bind(StringList& val)
+{
+ this->CurrentString = nullptr;
+ this->CurrentList = &val;
+ this->ExpectValue = true;
+}
+
+void Instance::Bind(MultiStringList& val)
+{
+ this->CurrentString = nullptr;
+ this->CurrentList = (static_cast<void>(val.emplace_back()), &val.back());
+ this->ExpectValue = false;
+}
+
+void Instance::Consume(cm::string_view arg, void* result,
+ std::vector<std::string>* unparsedArguments,
+ std::vector<std::string>* keywordsMissingValue)
+{
+ auto const it = this->Bindings.Find(arg);
+ if (it != this->Bindings.end()) {
+ it->second(*this, result);
+ if (this->ExpectValue && keywordsMissingValue != nullptr) {
+ keywordsMissingValue->emplace_back(arg);
+ }
+ return;
+ }
+
+ if (this->CurrentString != nullptr) {
+ this->CurrentString->assign(std::string(arg));
+ this->CurrentString = nullptr;
+ this->CurrentList = nullptr;
+ } else if (this->CurrentList != nullptr) {
+ this->CurrentList->emplace_back(arg);
+ } else if (unparsedArguments != nullptr) {
+ unparsedArguments->emplace_back(arg);
+ }
+
+ if (this->ExpectValue) {
+ if (keywordsMissingValue != nullptr) {
+ keywordsMissingValue->pop_back();
+ }
+ this->ExpectValue = false;
+ }
+}
+
+} // namespace ArgumentParser
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
new file mode 100644
index 0000000..6cfe946
--- /dev/null
+++ b/Source/cmArgumentParser.h
@@ -0,0 +1,143 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmArgumentParser_h
+#define cmArgumentParser_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_static_string_view.hxx"
+#include "cm_string_view.hxx"
+
+#include <cassert>
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace ArgumentParser {
+
+using StringList = std::vector<std::string>;
+using MultiStringList = std::vector<StringList>;
+
+class Instance;
+using Action = std::function<void(Instance&, void*)>;
+
+// using ActionMap = cm::flat_map<cm::string_view, Action>;
+class ActionMap : public std::vector<std::pair<cm::string_view, Action>>
+{
+public:
+ std::pair<iterator, bool> Emplace(cm::string_view name, Action action);
+ const_iterator Find(cm::string_view name) const;
+};
+
+class Instance
+{
+public:
+ Instance(ActionMap const& bindings)
+ : Bindings(bindings)
+ {
+ }
+
+ void Bind(bool& val);
+ void Bind(std::string& val);
+ void Bind(StringList& val);
+ void Bind(MultiStringList& val);
+
+ void Consume(cm::string_view arg, void* result,
+ std::vector<std::string>* unparsedArguments,
+ std::vector<std::string>* keywordsMissingValue);
+
+private:
+ ActionMap const& Bindings;
+ std::string* CurrentString = nullptr;
+ StringList* CurrentList = nullptr;
+ bool ExpectValue = false;
+};
+
+} // namespace ArgumentParser
+
+template <typename Result>
+class cmArgumentParser
+{
+public:
+ // I *think* this function could be made `constexpr` when the code is
+ // compiled as C++20. This would allow building a parser at compile time.
+ template <typename T>
+ cmArgumentParser& Bind(cm::static_string_view name, T Result::*member)
+ {
+ bool const inserted =
+ this->Bindings
+ .Emplace(name,
+ [member](ArgumentParser::Instance& instance, void* result) {
+ instance.Bind(static_cast<Result*>(result)->*member);
+ })
+ .second;
+ assert(inserted), (void)inserted;
+ return *this;
+ }
+
+ template <typename Range>
+ void Parse(Result& result, Range const& args,
+ std::vector<std::string>* unparsedArguments = nullptr,
+ std::vector<std::string>* keywordsMissingValue = nullptr) const
+ {
+ ArgumentParser::Instance instance(this->Bindings);
+ for (cm::string_view arg : args) {
+ instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue);
+ }
+ }
+
+ template <typename Range>
+ Result Parse(Range const& args,
+ std::vector<std::string>* unparsedArguments = nullptr,
+ std::vector<std::string>* keywordsMissingValue = nullptr) const
+ {
+ Result result;
+ this->Parse(result, args, unparsedArguments, keywordsMissingValue);
+ return result;
+ }
+
+private:
+ ArgumentParser::ActionMap Bindings;
+};
+
+template <>
+class cmArgumentParser<void>
+{
+public:
+ template <typename T>
+ cmArgumentParser& Bind(cm::static_string_view name, T& ref)
+ {
+ bool const inserted = this->Bind(cm::string_view(name), ref);
+ assert(inserted), (void)inserted;
+ return *this;
+ }
+
+ template <typename Range>
+ void Parse(Range const& args,
+ std::vector<std::string>* unparsedArguments = nullptr,
+ std::vector<std::string>* keywordsMissingValue = nullptr) const
+ {
+ ArgumentParser::Instance instance(this->Bindings);
+ for (cm::string_view arg : args) {
+ instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue);
+ }
+ }
+
+protected:
+ template <typename T>
+ bool Bind(cm::string_view name, T& ref)
+ {
+ return this->Bindings
+ .Emplace(name,
+ [&ref](ArgumentParser::Instance& instance, void*) {
+ instance.Bind(ref);
+ })
+ .second;
+ }
+
+private:
+ ArgumentParser::ActionMap Bindings;
+};
+
+#endif
diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx
index 4218d81..4b4bca2 100644
--- a/Source/cmCMakeMinimumRequired.cxx
+++ b/Source/cmCMakeMinimumRequired.cxx
@@ -55,7 +55,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
(version_min.empty() || version_max.empty())) {
std::ostringstream e;
e << "VERSION \"" << version_string
- << "\" does not have a version on both sides of \"...\".";
+ << R"(" does not have a version on both sides of "...".)";
this->SetError(e.str());
return false;
}
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index ac30e1a..8da5ef7 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -176,7 +176,7 @@ bool cmCMakePolicyCommand::HandleVersionMode(
(version_min.empty() || version_max.empty())) {
std::ostringstream e;
e << "VERSION \"" << version_string
- << "\" does not have a version on both sides of \"...\".";
+ << R"(" does not have a version on both sides of "...".)";
this->SetError(e.str());
return false;
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index 0c70ed2..65f22f7 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -93,33 +93,33 @@ public:
CacheEntry& GetEntry() { return this->Position->second; }
};
- ///! return an iterator to iterate through the cache map
+ //! return an iterator to iterate through the cache map
cmCacheManager::CacheIterator NewIterator() { return CacheIterator(*this); }
- ///! Load a cache for given makefile. Loads from path/CMakeCache.txt.
+ //! Load a cache for given makefile. Loads from path/CMakeCache.txt.
bool LoadCache(const std::string& path, bool internal,
std::set<std::string>& excludes,
std::set<std::string>& includes);
- ///! Save cache for given makefile. Saves to output path/CMakeCache.txt
+ //! Save cache for given makefile. Saves to output path/CMakeCache.txt
bool SaveCache(const std::string& path, cmMessenger* messenger);
- ///! Delete the cache given
+ //! Delete the cache given
bool DeleteCache(const std::string& path);
- ///! Print the cache to a stream
+ //! Print the cache to a stream
void PrintCache(std::ostream&) const;
- ///! Get the iterator for an entry with a given key.
+ //! Get the iterator for an entry with a given key.
cmCacheManager::CacheIterator GetCacheIterator(const char* key = nullptr);
- ///! Remove an entry from the cache
+ //! Remove an entry from the cache
void RemoveCacheEntry(const std::string& key);
- ///! Get the number of entries in the cache
+ //! Get the number of entries in the cache
int GetSize() { return static_cast<int>(this->Cache.size()); }
- ///! Get a value from the cache given a key
+ //! Get a value from the cache given a key
const std::string* GetInitializedCacheValue(const std::string& key) const;
const char* GetCacheEntryValue(const std::string& key)
@@ -197,14 +197,14 @@ public:
unsigned int GetCacheMinorVersion() const { return this->CacheMinorVersion; }
protected:
- ///! Add an entry into the cache
+ //! Add an entry into the cache
void AddCacheEntry(const std::string& key, const char* value,
const char* helpString,
cmStateEnums::CacheEntryType type);
- ///! Get a cache entry object for a key
+ //! Get a cache entry object for a key
CacheEntry* GetCacheEntry(const std::string& key);
- ///! Clean out the CMakeFiles directory if no CMakeCache.txt
+ //! Clean out the CMakeFiles directory if no CMakeCache.txt
void CleanCMakeFiles(const std::string& path);
// Cache version info
diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx
index ee5feee..2f6cf64 100644
--- a/Source/cmCallVisualStudioMacro.cxx
+++ b/Source/cmCallVisualStudioMacro.cxx
@@ -35,8 +35,8 @@ static bool LogErrorsAsMessages;
# endif
# endif
-///! Use ReportHRESULT to make a cmSystemTools::Message after calling
-///! a COM method that may have failed.
+//! Use ReportHRESULT to make a cmSystemTools::Message after calling
+//! a COM method that may have failed.
# define ReportHRESULT(hr, context) \
if (FAILED(hr)) { \
if (LogErrorsAsMessages) { \
@@ -50,7 +50,7 @@ static bool LogErrorsAsMessages;
} \
}
-///! Using the given instance of Visual Studio, call the named macro
+//! Using the given instance of Visual Studio, call the named macro
HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro,
const std::string& args)
{
@@ -133,7 +133,7 @@ HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro,
return hr;
}
-///! Get the Solution object from the IDE object
+//! Get the Solution object from the IDE object
HRESULT GetSolutionObject(IDispatch* vsIDE, IDispatchPtr& vsSolution)
{
HRESULT hr = E_POINTER;
@@ -176,7 +176,7 @@ HRESULT GetSolutionObject(IDispatch* vsIDE, IDispatchPtr& vsSolution)
return hr;
}
-///! Get the FullName property from the Solution object
+//! Get the FullName property from the Solution object
HRESULT GetSolutionFullName(IDispatch* vsSolution, std::string& fullName)
{
HRESULT hr = E_POINTER;
@@ -220,7 +220,7 @@ HRESULT GetSolutionFullName(IDispatch* vsSolution, std::string& fullName)
return hr;
}
-///! Get the FullName property from the Solution object, given the IDE object
+//! Get the FullName property from the Solution object, given the IDE object
HRESULT GetIDESolutionFullName(IDispatch* vsIDE, std::string& fullName)
{
IDispatchPtr vsSolution;
@@ -235,8 +235,8 @@ HRESULT GetIDESolutionFullName(IDispatch* vsIDE, std::string& fullName)
return hr;
}
-///! Get all running objects from the Windows running object table.
-///! Save them in a map by their display names.
+//! Get all running objects from the Windows running object table.
+//! Save them in a map by their display names.
HRESULT GetRunningInstances(std::map<std::string, IUnknownPtr>& mrot)
{
// mrot == Map of the Running Object Table
@@ -292,8 +292,8 @@ HRESULT GetRunningInstances(std::map<std::string, IUnknownPtr>& mrot)
return hr;
}
-///! Do the two file names refer to the same Visual Studio solution? Or are
-///! we perhaps looking for any and all solutions?
+//! Do the two file names refer to the same Visual Studio solution? Or are
+//! we perhaps looking for any and all solutions?
bool FilesSameSolution(const std::string& slnFile, const std::string& slnName)
{
if (slnFile == "ALL" || slnName == "ALL") {
@@ -310,9 +310,9 @@ bool FilesSameSolution(const std::string& slnFile, const std::string& slnName)
return s1 == s2;
}
-///! Find instances of Visual Studio with the given solution file
-///! open. Pass "ALL" for slnFile to gather all running instances
-///! of Visual Studio.
+//! Find instances of Visual Studio with the given solution file
+//! open. Pass "ALL" for slnFile to gather all running instances
+//! of Visual Studio.
HRESULT FindVisualStudioInstances(const std::string& slnFile,
std::vector<IDispatchPtr>& instances)
{
@@ -384,8 +384,8 @@ int cmCallVisualStudioMacro::GetNumberOfRunningVisualStudioInstances(
return count;
}
-///! Get all running objects from the Windows running object table.
-///! Save them in a map by their display names.
+//! Get all running objects from the Windows running object table.
+//! Save them in a map by their display names.
int cmCallVisualStudioMacro::CallMacro(const std::string& slnFile,
const std::string& macro,
const std::string& args,
diff --git a/Source/cmCallVisualStudioMacro.h b/Source/cmCallVisualStudioMacro.h
index fdc9e66..9b5b3a8 100644
--- a/Source/cmCallVisualStudioMacro.h
+++ b/Source/cmCallVisualStudioMacro.h
@@ -16,16 +16,16 @@
class cmCallVisualStudioMacro
{
public:
- ///! Call the named macro in instances of Visual Studio with the
- ///! given solution file open. Pass "ALL" for slnFile to call the
- ///! macro in each Visual Studio instance.
+ //! Call the named macro in instances of Visual Studio with the
+ //! given solution file open. Pass "ALL" for slnFile to call the
+ //! macro in each Visual Studio instance.
static int CallMacro(const std::string& slnFile, const std::string& macro,
const std::string& args,
const bool logErrorsAsMessages);
- ///! Count the number of running instances of Visual Studio with the
- ///! given solution file open. Pass "ALL" for slnFile to count all
- ///! running Visual Studio instances.
+ //! Count the number of running instances of Visual Studio with the
+ //! given solution file open. Pass "ALL" for slnFile to count all
+ //! running Visual Studio instances.
static int GetNumberOfRunningVisualStudioInstances(
const std::string& slnFile);
diff --git a/Source/cmCommandArgumentsHelper.cxx b/Source/cmCommandArgumentsHelper.cxx
deleted file mode 100644
index 968b17c..0000000
--- a/Source/cmCommandArgumentsHelper.cxx
+++ /dev/null
@@ -1,233 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCommandArgumentsHelper.h"
-
-cmCommandArgument::cmCommandArgument(cmCommandArgumentsHelper* args,
- const char* key,
- cmCommandArgumentGroup* group)
- : Key(key)
- , Group(group)
- , WasActive(false)
- , ArgumentsBeforeEmpty(true)
- , CurrentIndex(0)
-{
- if (args != nullptr) {
- args->AddArgument(this);
- }
-
- if (this->Group != nullptr) {
- this->Group->ContainedArguments.push_back(this);
- }
-}
-
-void cmCommandArgument::Reset()
-{
- this->WasActive = false;
- this->CurrentIndex = 0;
- this->DoReset();
-}
-
-void cmCommandArgument::Follows(const cmCommandArgument* arg)
-{
- this->ArgumentsBeforeEmpty = false;
- this->ArgumentsBefore.insert(arg);
-}
-
-void cmCommandArgument::FollowsGroup(const cmCommandArgumentGroup* group)
-{
- if (group != nullptr) {
- this->ArgumentsBeforeEmpty = false;
- this->ArgumentsBefore.insert(group->ContainedArguments.begin(),
- group->ContainedArguments.end());
- }
-}
-
-bool cmCommandArgument::MayFollow(const cmCommandArgument* current) const
-{
- if (this->ArgumentsBeforeEmpty) {
- return true;
- }
- return this->ArgumentsBefore.find(current) != this->ArgumentsBefore.end();
-}
-
-bool cmCommandArgument::KeyMatches(const std::string& key) const
-{
- if ((this->Key == nullptr) || (this->Key[0] == '\0')) {
- return true;
- }
- return (key == this->Key);
-}
-
-void cmCommandArgument::ApplyOwnGroup()
-{
- if (this->Group != nullptr) {
- for (cmCommandArgument* cargs : this->Group->ContainedArguments) {
- if (cargs != this) {
- this->ArgumentsBefore.insert(cargs);
- }
- }
- }
-}
-
-void cmCommandArgument::Activate()
-{
- this->WasActive = true;
- this->CurrentIndex = 0;
-}
-
-bool cmCommandArgument::Consume(const std::string& arg)
-{
- bool res = this->DoConsume(arg, this->CurrentIndex);
- this->CurrentIndex++;
- return res;
-}
-
-cmCAStringVector::cmCAStringVector(cmCommandArgumentsHelper* args,
- const char* key,
- cmCommandArgumentGroup* group)
- : cmCommandArgument(args, key, group)
- , Ignore(nullptr)
-{
- if ((key == nullptr) || (*key == 0)) {
- this->DataStart = 0;
- } else {
- this->DataStart = 1;
- }
-}
-
-bool cmCAStringVector::DoConsume(const std::string& arg, unsigned int index)
-{
- if (index >= this->DataStart) {
- if ((this->Ignore == nullptr) || (arg != this->Ignore)) {
- this->Vector.push_back(arg);
- }
- }
-
- return false;
-}
-
-void cmCAStringVector::DoReset()
-{
- this->Vector.clear();
-}
-
-cmCAString::cmCAString(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group)
- : cmCommandArgument(args, key, group)
-{
- if ((key == nullptr) || (*key == 0)) {
- this->DataStart = 0;
- } else {
- this->DataStart = 1;
- }
-}
-
-bool cmCAString::DoConsume(const std::string& arg, unsigned int index)
-{
- if (index == this->DataStart) {
- this->String = arg;
- }
-
- return index >= this->DataStart;
-}
-
-void cmCAString::DoReset()
-{
- this->String.clear();
-}
-
-cmCAEnabler::cmCAEnabler(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group)
- : cmCommandArgument(args, key, group)
- , Enabled(false)
-{
-}
-
-bool cmCAEnabler::DoConsume(const std::string&, unsigned int index)
-{
- if (index == 0) {
- this->Enabled = true;
- }
- return true;
-}
-
-void cmCAEnabler::DoReset()
-{
- this->Enabled = false;
-}
-
-cmCADisabler::cmCADisabler(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group)
- : cmCommandArgument(args, key, group)
- , Enabled(true)
-{
-}
-
-bool cmCADisabler::DoConsume(const std::string&, unsigned int index)
-{
- if (index == 0) {
- this->Enabled = false;
- }
- return true;
-}
-
-void cmCADisabler::DoReset()
-{
- this->Enabled = true;
-}
-
-void cmCommandArgumentGroup::Follows(const cmCommandArgument* arg)
-{
- for (cmCommandArgument* ca : this->ContainedArguments) {
- ca->Follows(arg);
- }
-}
-
-void cmCommandArgumentGroup::FollowsGroup(const cmCommandArgumentGroup* group)
-{
- for (cmCommandArgument* ca : this->ContainedArguments) {
- ca->FollowsGroup(group);
- }
-}
-
-void cmCommandArgumentsHelper::Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs)
-{
- if (args == nullptr) {
- return;
- }
-
- for (cmCommandArgument* ca : this->Arguments) {
- ca->ApplyOwnGroup();
- ca->Reset();
- }
-
- cmCommandArgument* activeArgument = nullptr;
- const cmCommandArgument* previousArgument = nullptr;
- for (std::string const& it : *args) {
- for (cmCommandArgument* ca : this->Arguments) {
- if (ca->KeyMatches(it) && (ca->MayFollow(previousArgument))) {
- activeArgument = ca;
- activeArgument->Activate();
- break;
- }
- }
-
- if (activeArgument) {
- bool argDone = activeArgument->Consume(it);
- previousArgument = activeArgument;
- if (argDone) {
- activeArgument = nullptr;
- }
- } else {
- if (unconsumedArgs != nullptr) {
- unconsumedArgs->push_back(it);
- }
- }
- }
-}
-
-void cmCommandArgumentsHelper::AddArgument(cmCommandArgument* arg)
-{
- this->Arguments.push_back(arg);
-}
diff --git a/Source/cmCommandArgumentsHelper.h b/Source/cmCommandArgumentsHelper.h
deleted file mode 100644
index dc934be..0000000
--- a/Source/cmCommandArgumentsHelper.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCommandArgumentsHelper_h
-#define cmCommandArgumentsHelper_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <set>
-#include <string>
-#include <vector>
-
-class cmCommandArgumentGroup;
-class cmCommandArgumentsHelper;
-
-/* cmCommandArgumentsHelper, cmCommandArgumentGroup and cmCommandArgument (i.e.
-its derived classes cmCAXXX can be used to simplify the processing of
-arguments to cmake commands. Maybe they can also be used to generate
-documentation.
-
-For every argument supported by a command one cmCommandArgument is created
-and added to cmCommandArgumentsHelper. cmCommand has a cmCommandArgumentsHelper
-as member variable so this should be used.
-
-The order of the arguments is defined using the Follows(arg) method. It says
-that this argument follows immediateley the given argument. It can be used
-with multiple arguments if the argument can follow after different arguments.
-
-Arguments can be arranged in groups using cmCommandArgumentGroup. Every
-member of a group can follow any other member of the group. These groups
-can also be used to define the order.
-
-Once all arguments and groups are set up, cmCommandArgumentsHelper::Parse()
-is called and afterwards the values of the arguments can be evaluated.
-
-For an example see cmExportCommand.cxx.
-*/
-class cmCommandArgument
-{
-public:
- cmCommandArgument(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = nullptr);
- virtual ~cmCommandArgument() = default;
-
- /// this argument may follow after arg. 0 means it comes first.
- void Follows(const cmCommandArgument* arg);
-
- /// this argument may follow after any of the arguments in the given group
- void FollowsGroup(const cmCommandArgumentGroup* group);
-
- /// Returns true if the argument was found in the argument list
- bool WasFound() const { return this->WasActive; }
-
- // The following methods are only called from
- // cmCommandArgumentsHelper::Parse(), but making this a friend would
- // give it access to everything
-
- /// Make the current argument the currently active argument
- void Activate();
- /// Consume the current string
- bool Consume(const std::string& arg);
-
- /// Return true if this argument may follow after the given argument.
- bool MayFollow(const cmCommandArgument* current) const;
-
- /** Returns true if the given key matches the key for this argument.
- If this argument has an empty key everything matches. */
- bool KeyMatches(const std::string& key) const;
-
- /// Make this argument follow all members of the own group
- void ApplyOwnGroup();
-
- /// Reset argument, so it's back to its initial state
- void Reset();
-
-private:
- const char* Key;
- std::set<const cmCommandArgument*> ArgumentsBefore;
- cmCommandArgumentGroup* Group;
- bool WasActive;
- bool ArgumentsBeforeEmpty;
- unsigned int CurrentIndex;
-
- virtual bool DoConsume(const std::string& arg, unsigned int index) = 0;
- virtual void DoReset() = 0;
-};
-
-/** cmCAStringVector is to be used for arguments which can consist of more
-than one string, e.g. the FILES argument in INSTALL(FILES f1 f2 f3 ...). */
-class cmCAStringVector : public cmCommandArgument
-{
-public:
- cmCAStringVector(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = nullptr);
-
- /// Return the vector of strings
- const std::vector<std::string>& GetVector() const { return this->Vector; }
-
- /** Is there a keyword which should be skipped in
- the arguments (e.g. ARGS for ADD_CUSTOM_COMMAND) ? */
- void SetIgnore(const char* ignore) { this->Ignore = ignore; }
-
-private:
- std::vector<std::string> Vector;
- unsigned int DataStart;
- const char* Ignore;
- bool DoConsume(const std::string& arg, unsigned int index) override;
- void DoReset() override;
-};
-
-/** cmCAString is to be used for arguments which consist of one value,
-e.g. the executable name in ADD_EXECUTABLE(). */
-class cmCAString : public cmCommandArgument
-{
-public:
- cmCAString(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = nullptr);
-
- /// Return the string
- const std::string& GetString() const { return this->String; }
- const char* GetCString() const { return this->String.c_str(); }
-
-private:
- std::string String;
- unsigned int DataStart;
- bool DoConsume(const std::string& arg, unsigned int index) override;
- void DoReset() override;
-};
-
-/** cmCAEnabler is to be used for options which are off by default and can be
-enabled using a special argument, e.g. EXCLUDE_FROM_ALL in ADD_EXECUTABLE(). */
-class cmCAEnabler : public cmCommandArgument
-{
-public:
- cmCAEnabler(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = nullptr);
-
- /// Has it been enabled ?
- bool IsEnabled() const { return this->Enabled; }
-
-private:
- bool Enabled;
- bool DoConsume(const std::string& arg, unsigned int index) override;
- void DoReset() override;
-};
-
-/** cmCADisable is to be used for options which are on by default and can be
-disabled using a special argument.*/
-class cmCADisabler : public cmCommandArgument
-{
-public:
- cmCADisabler(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = nullptr);
-
- /// Is it still enabled ?
- bool IsEnabled() const { return this->Enabled; }
-
-private:
- bool Enabled;
- bool DoConsume(const std::string& arg, unsigned int index) override;
- void DoReset() override;
-};
-
-/** Group of arguments, needed for ordering. E.g. WIN32, EXCLUDE_FROM_ALL and
-MACSOX_BUNDLE from ADD_EXECUTABLE() are a group.
-*/
-class cmCommandArgumentGroup
-{
- friend class cmCommandArgument;
-
-public:
- /// All members of this group may follow the given argument
- void Follows(const cmCommandArgument* arg);
-
- /// All members of this group may follow all members of the given group
- void FollowsGroup(const cmCommandArgumentGroup* group);
-
-private:
- std::vector<cmCommandArgument*> ContainedArguments;
-};
-
-class cmCommandArgumentsHelper
-{
-public:
- /// Parse the argument list
- void Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs);
- /// Add an argument.
- void AddArgument(cmCommandArgument* arg);
-
-private:
- std::vector<cmCommandArgument*> Arguments;
-};
-
-#endif
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 69d4374..dcb1ff5 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -60,7 +60,8 @@ static std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED";
/* GHS Multi platform variables */
static std::set<std::string> ghs_platform_vars{
"GHS_TARGET_PLATFORM", "GHS_PRIMARY_TARGET", "GHS_TOOLSET_ROOT",
- "GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME"
+ "GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME",
+ "GHS_OS_DIR_OPTION"
};
static void writeProperty(FILE* fout, std::string const& targetName,
@@ -123,6 +124,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::string targetName;
std::vector<std::string> cmakeFlags(1, "CMAKE_FLAGS"); // fake argv[0]
std::vector<std::string> compileDefs;
+ std::string cmakeInternal;
std::string outputVariable;
std::string copyFile;
std::string copyFileError;
@@ -174,7 +176,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
DoingCExtensions,
DoingCxxExtensions,
DoingCudaExtensions,
- DoingSources
+ DoingSources,
+ DoingCMakeInternal
};
Doing doing = useSources ? DoingSources : DoingNone;
for (size_t i = 3; i < argv.size(); ++i) {
@@ -223,6 +226,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (argv[i] == "CUDA_EXTENSIONS") {
doing = DoingCudaExtensions;
didCudaExtensions = true;
+ } else if (argv[i] == "__CMAKE_INTERNAL") {
+ doing = DoingCMakeInternal;
} else if (doing == DoingCMakeFlags) {
cmakeFlags.push_back(argv[i]);
} else if (doing == DoingCompileDefinitions) {
@@ -296,6 +301,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
doing = DoingNone;
} else if (doing == DoingSources) {
sources.push_back(argv[i]);
+ } else if (doing == DoingCMakeInternal) {
+ cmakeInternal = argv[i];
+ doing = DoingNone;
} else if (i == 3) {
this->SrcFileSignature = false;
projectName = argv[i].c_str();
@@ -508,6 +516,14 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
fprintf(fout, "project(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str());
+ if (cmakeInternal == "ABI") {
+ // This is the ABI detection step, also used for implicit includes.
+ // Erase any include_directories() calls from the toolchain file so
+ // that we do not see them as implicit. Our ABI detection source
+ // does not include any system headers anyway.
+ fprintf(fout,
+ "set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES \"\")\n");
+ }
fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n");
for (std::string const& li : testLangs) {
std::string langFlags = "CMAKE_" + li + "_FLAGS";
@@ -881,7 +897,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// Forward the GHS variables to the inner project cache.
for (std::string const& var : ghs_platform_vars) {
if (const char* val = this->Makefile->GetDefinition(var)) {
- std::string flag = "-D" + var + "=" + val;
+ std::string flag = "-D" + var + "=" + "'" + val + "'";
cmakeFlags.push_back(std::move(flag));
}
}
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index efadaf1..ed76dbf 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDepends.h"
+#include "cmFileTime.h"
#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
#include "cmLocalGenerator.h"
@@ -10,22 +11,15 @@
#include "cmsys/FStream.hxx"
#include <sstream>
-#include <string.h>
#include <utility>
cmDepends::cmDepends(cmLocalGenerator* lg, std::string targetDir)
: LocalGenerator(lg)
, TargetDirectory(std::move(targetDir))
- , Dependee(new char[MaxPath])
- , Depender(new char[MaxPath])
{
}
-cmDepends::~cmDepends()
-{
- delete[] this->Dependee;
- delete[] this->Depender;
-}
+cmDepends::~cmDepends() = default;
bool cmDepends::Write(std::ostream& makeDepends, std::ostream& internalDepends)
{
@@ -67,7 +61,7 @@ bool cmDepends::Finalize(std::ostream& /*unused*/, std::ostream& /*unused*/)
bool cmDepends::Check(const std::string& makeFile,
const std::string& internalFile,
- std::map<std::string, DependencyVector>& validDeps)
+ DependencyMap& validDeps)
{
// Check whether dependencies must be regenerated.
bool okay = true;
@@ -76,9 +70,9 @@ bool cmDepends::Check(const std::string& makeFile,
// Clear all dependencies so they will be regenerated.
this->Clear(makeFile);
cmSystemTools::RemoveFile(internalFile);
+ this->FileTimeCache->Remove(internalFile);
okay = false;
}
-
return okay;
}
@@ -107,48 +101,62 @@ bool cmDepends::WriteDependencies(const std::set<std::string>& /*unused*/,
return false;
}
-bool cmDepends::CheckDependencies(
- std::istream& internalDepends, const std::string& internalDependsFileName,
- std::map<std::string, DependencyVector>& validDeps)
+bool cmDepends::CheckDependencies(std::istream& internalDepends,
+ const std::string& internalDependsFileName,
+ DependencyMap& validDeps)
{
+ // Read internal depends file time
+ cmFileTime internalDependsTime;
+ if (!this->FileTimeCache->Load(internalDependsFileName,
+ internalDependsTime)) {
+ return false;
+ }
+
// Parse dependencies from the stream. If any dependee is missing
// or newer than the depender then dependencies should be
// regenerated.
bool okay = true;
bool dependerExists = false;
- DependencyVector* currentDependencies = nullptr;
- while (internalDepends.getline(this->Dependee, this->MaxPath)) {
- if (this->Dependee[0] == 0 || this->Dependee[0] == '#' ||
- this->Dependee[0] == '\r') {
+ std::string line;
+ line.reserve(1024);
+ std::string depender;
+ std::string dependee;
+ cmFileTime dependerTime;
+ cmFileTime dependeeTime;
+ std::vector<std::string>* currentDependencies = nullptr;
+
+ while (std::getline(internalDepends, line)) {
+ // Check if this an empty or a comment line
+ if (line.empty() || line.front() == '#') {
continue;
}
- size_t len = internalDepends.gcount() - 1;
- if (this->Dependee[len - 1] == '\r') {
- len--;
- this->Dependee[len] = 0;
+ // Drop carriage return character at the end
+ if (line.back() == '\r') {
+ line.pop_back();
+ if (line.empty()) {
+ continue;
+ }
}
- if (this->Dependee[0] != ' ') {
- memcpy(this->Depender, this->Dependee, len + 1);
- // Calling FileExists() for the depender here saves in many cases 50%
- // of the calls to FileExists() further down in the loop. E.g. for
- // kdelibs/khtml this reduces the number of calls from 184k down to 92k,
- // or the time for cmake -E cmake_depends from 0.3 s down to 0.21 s.
- dependerExists = cmSystemTools::FileExists(this->Depender);
+ // Check if this a depender line
+ if (line.front() != ' ') {
+ depender = line;
+ dependerExists = this->FileTimeCache->Load(depender, dependerTime);
// If we erase validDeps[this->Depender] by overwriting it with an empty
// vector, we lose dependencies for dependers that have multiple
// entries. No need to initialize the entry, std::map will do so on first
// access.
- currentDependencies = &validDeps[this->Depender];
+ currentDependencies = &validDeps[depender];
continue;
}
- /*
- // Parse the dependency line.
- if(!this->ParseDependency(line.c_str()))
- {
- continue;
- }
- */
+
+ // This is a dependee line
+ dependee = line.substr(1);
+
+ // Add dependee to depender's list
+ if (currentDependencies != nullptr) {
+ currentDependencies->push_back(dependee);
+ }
// Dependencies must be regenerated
// * if the dependee does not exist
@@ -156,13 +164,8 @@ bool cmDepends::CheckDependencies(
// * if the depender does not exist, but the dependee is newer than the
// depends file
bool regenerate = false;
- const std::string dependee(this->Dependee + 1);
- const std::string depender(this->Depender);
- if (currentDependencies != nullptr) {
- currentDependencies->push_back(dependee);
- }
-
- if (!cmSystemTools::FileExists(dependee)) {
+ bool dependeeExists = this->FileTimeCache->Load(dependee, dependeeTime);
+ if (!dependeeExists) {
// The dependee does not exist.
regenerate = true;
@@ -173,44 +176,38 @@ bool cmDepends::CheckDependencies(
<< depender << "\"." << std::endl;
cmSystemTools::Stdout(msg.str());
}
- } else {
- if (dependerExists) {
- // The dependee and depender both exist. Compare file times.
- int result = 0;
- if ((!this->FileTimeCache->Compare(depender, dependee, &result) ||
- result < 0)) {
- // The depender is older than the dependee.
- regenerate = true;
-
- // Print verbose output.
- if (this->Verbose) {
- std::ostringstream msg;
- msg << "Dependee \"" << dependee << "\" is newer than depender \""
- << depender << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str());
- }
+ } else if (dependerExists) {
+ // The dependee and depender both exist. Compare file times.
+ if (dependerTime.Older(dependeeTime)) {
+ // The depender is older than the dependee.
+ regenerate = true;
+
+ // Print verbose output.
+ if (this->Verbose) {
+ std::ostringstream msg;
+ msg << "Dependee \"" << dependee << "\" is newer than depender \""
+ << depender << "\"." << std::endl;
+ cmSystemTools::Stdout(msg.str());
}
- } else {
- // The dependee exists, but the depender doesn't. Regenerate if the
- // internalDepends file is older than the dependee.
- int result = 0;
- if ((!this->FileTimeCache->Compare(internalDependsFileName, dependee,
- &result) ||
- result < 0)) {
- // The depends-file is older than the dependee.
- regenerate = true;
-
- // Print verbose output.
- if (this->Verbose) {
- std::ostringstream msg;
- msg << "Dependee \"" << dependee
- << "\" is newer than depends file \""
- << internalDependsFileName << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str());
- }
+ }
+ } else {
+ // The dependee exists, but the depender doesn't. Regenerate if the
+ // internalDepends file is older than the dependee.
+ if (internalDependsTime.Older(dependeeTime)) {
+ // The depends-file is older than the dependee.
+ regenerate = true;
+
+ // Print verbose output.
+ if (this->Verbose) {
+ std::ostringstream msg;
+ msg << "Dependee \"" << dependee
+ << "\" is newer than depends file \"" << internalDependsFileName
+ << "\"." << std::endl;
+ cmSystemTools::Stdout(msg.str());
}
}
}
+
if (regenerate) {
// Dependencies must be regenerated.
okay = false;
@@ -218,13 +215,14 @@ bool cmDepends::CheckDependencies(
// Remove the information of this depender from the map, it needs
// to be rescanned
if (currentDependencies != nullptr) {
- validDeps.erase(this->Depender);
+ validDeps.erase(depender);
currentDependencies = nullptr;
}
// Remove the depender to be sure it is rebuilt.
if (dependerExists) {
cmSystemTools::RemoveFile(depender);
+ this->FileTimeCache->Remove(depender);
dependerExists = false;
}
}
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index fc6571d..b7475f0 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -8,7 +8,6 @@
#include <iosfwd>
#include <map>
#include <set>
-#include <stddef.h>
#include <string>
#include <vector>
@@ -25,6 +24,9 @@ class cmLocalGenerator;
class cmDepends
{
public:
+ typedef std::map<std::string, std::vector<std::string>> DependencyMap;
+
+public:
/** Instances need to know the build directory name and the relative
path from the build directory to the target file. */
cmDepends(cmLocalGenerator* lg = nullptr, std::string targetDir = "");
@@ -56,17 +58,13 @@ public:
/** Write dependencies for the target file. */
bool Write(std::ostream& makeDepends, std::ostream& internalDepends);
- class DependencyVector : public std::vector<std::string>
- {
- };
-
/** Check dependencies for the target file. Returns true if
dependencies are okay and false if they must be generated. If
they must be generated Clear has already been called to wipe out
the old dependencies.
Dependencies which are still valid will be stored in validDeps. */
bool Check(const std::string& makeFile, const std::string& internalFile,
- std::map<std::string, DependencyVector>& validDeps);
+ DependencyMap& validDeps);
/** Clear dependencies for the target file so they will be regenerated. */
void Clear(const std::string& file);
@@ -85,9 +83,9 @@ protected:
// Check dependencies for the target file in the given stream.
// Return false if dependencies must be regenerated and true
// otherwise.
- virtual bool CheckDependencies(
- std::istream& internalDepends, const std::string& internalDependsFileName,
- std::map<std::string, DependencyVector>& validDeps);
+ virtual bool CheckDependencies(std::istream& internalDepends,
+ const std::string& internalDependsFileName,
+ DependencyMap& validDeps);
// Finalize the dependency information for the target.
virtual bool Finalize(std::ostream& makeDepends,
@@ -105,10 +103,6 @@ protected:
// The full path to the target's build directory.
std::string TargetDirectory;
- size_t MaxPath = 16384;
- char* Dependee;
- char* Depender;
-
// The include file search path.
std::vector<std::string> IncludePath;
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 7b78767..dc49c18 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -21,9 +21,8 @@
cmDependsC::cmDependsC() = default;
-cmDependsC::cmDependsC(
- cmLocalGenerator* lg, const std::string& targetDir, const std::string& lang,
- const std::map<std::string, DependencyVector>* validDeps)
+cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir,
+ const std::string& lang, const DependencyMap* validDeps)
: cmDepends(lg, targetDir)
, ValidDeps(validDeps)
{
@@ -102,8 +101,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
this->LocalGenerator->MaybeConvertToRelativePath(binDir, obj);
if (this->ValidDeps != nullptr) {
- std::map<std::string, DependencyVector>::const_iterator tmpIt =
- this->ValidDeps->find(obj_i);
+ auto const tmpIt = this->ValidDeps->find(obj_i);
if (tmpIt != this->ValidDeps->end()) {
dependencies.insert(tmpIt->second.begin(), tmpIt->second.end());
haveDeps = true;
diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h
index eee5ae1..3fc839e 100644
--- a/Source/cmDependsC.h
+++ b/Source/cmDependsC.h
@@ -27,8 +27,7 @@ public:
relative path from the build directory to the target file. */
cmDependsC();
cmDependsC(cmLocalGenerator* lg, const std::string& targetDir,
- const std::string& lang,
- const std::map<std::string, DependencyVector>* validDeps);
+ const std::string& lang, const DependencyMap* validDeps);
/** Virtual destructor to cleanup subclasses properly. */
~cmDependsC() override;
@@ -81,7 +80,7 @@ public:
};
protected:
- const std::map<std::string, DependencyVector>* ValidDeps = nullptr;
+ const DependencyMap* ValidDeps = nullptr;
std::set<std::string> Encountered;
std::queue<UnscannedEntry> Unscanned;
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 3f036a9..178e18b 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -295,7 +295,7 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin,
// They do not include the ".mod" extension.
mod += ".mod";
}
- this->ConsiderModule(mod.c_str() + 1, stampDir);
+ this->ConsiderModule(mod.substr(1), stampDir);
}
} else if (line == "provides") {
doing_provides = true;
diff --git a/Source/cmDependsJava.cxx b/Source/cmDependsJava.cxx
index 2485e15..b17b2ba 100644
--- a/Source/cmDependsJava.cxx
+++ b/Source/cmDependsJava.cxx
@@ -24,8 +24,7 @@ bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources,
bool cmDependsJava::CheckDependencies(
std::istream& /*internalDepends*/,
- const std::string& /*internalDependsFileName*/,
- std::map<std::string, DependencyVector>& /*validDeps*/)
+ const std::string& /*internalDependsFileName*/, DependencyMap& /*validDeps*/)
{
return true;
}
diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h
index 109ef13..dd671a1 100644
--- a/Source/cmDependsJava.h
+++ b/Source/cmDependsJava.h
@@ -8,7 +8,6 @@
#include "cmDepends.h"
#include <iosfwd>
-#include <map>
#include <set>
#include <string>
@@ -33,9 +32,9 @@ protected:
bool WriteDependencies(const std::set<std::string>& sources,
const std::string& file, std::ostream& makeDepends,
std::ostream& internalDepends) override;
- bool CheckDependencies(
- std::istream& internalDepends, const std::string& internalDependsFileName,
- std::map<std::string, DependencyVector>& validDeps) override;
+ bool CheckDependencies(std::istream& internalDepends,
+ const std::string& internalDependsFileName,
+ DependencyMap& validDeps) override;
};
#endif
diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx
index 792db48..12d875d 100644
--- a/Source/cmDependsJavaParserHelper.cxx
+++ b/Source/cmDependsJavaParserHelper.cxx
@@ -5,6 +5,7 @@
#include "cmDependsJavaLexer.h"
#include "cmSystemTools.h"
+#include "cm_string_view.hxx"
#include "cmsys/FStream.hxx"
#include <iostream>
#include <stdio.h>
@@ -298,14 +299,10 @@ void cmDependsJavaParserHelper::Error(const char* str)
unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
fprintf(stderr, "JPError: %s (%lu / Line: %d)\n", str, pos,
this->CurrentLine);
- int cc;
- std::cerr << "String: [";
- for (cc = 0;
- cc < 30 && *(this->InputBuffer.c_str() + this->InputBufferPos + cc);
- cc++) {
- std::cerr << *(this->InputBuffer.c_str() + this->InputBufferPos + cc);
- }
- std::cerr << "]" << std::endl;
+ std::cerr << "String: ["
+ << cm::string_view{ this->InputBuffer }.substr(
+ this->InputBufferPos, 30)
+ << "]" << std::endl;
}
void cmDependsJavaParserHelper::UpdateCombine(const char* str1,
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 03eac5b..ff6340f 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -2,12 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExecuteProcessCommand.h"
+#include "cm_static_string_view.hxx"
#include "cmsys/Process.h"
+#include <algorithm>
#include <ctype.h> /* isspace */
-#include <sstream>
#include <stdio.h>
#include "cmAlgorithms.h"
+#include "cmArgumentParser.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
#include "cmSystemTools.h"
@@ -32,157 +34,85 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
this->SetError("called with incorrect number of arguments");
return false;
}
- std::vector<std::vector<const char*>> cmds;
- std::string arguments;
- bool doing_command = false;
- size_t command_index = 0;
- bool output_quiet = false;
- bool error_quiet = false;
- bool output_strip_trailing_whitespace = false;
- bool error_strip_trailing_whitespace = false;
- std::string timeout_string;
- std::string input_file;
- std::string output_file;
- std::string error_file;
- std::string output_variable;
- std::string error_variable;
- std::string result_variable;
- std::string results_variable;
- std::string working_directory;
- cmProcessOutput::Encoding encoding = cmProcessOutput::None;
- for (size_t i = 0; i < args.size(); ++i) {
- if (args[i] == "COMMAND") {
- doing_command = true;
- command_index = cmds.size();
- cmds.emplace_back();
- } else if (args[i] == "OUTPUT_VARIABLE") {
- doing_command = false;
- if (++i < args.size()) {
- output_variable = args[i];
- } else {
- this->SetError(" called with no value for OUTPUT_VARIABLE.");
- return false;
- }
- } else if (args[i] == "ERROR_VARIABLE") {
- doing_command = false;
- if (++i < args.size()) {
- error_variable = args[i];
- } else {
- this->SetError(" called with no value for ERROR_VARIABLE.");
- return false;
- }
- } else if (args[i] == "RESULT_VARIABLE") {
- doing_command = false;
- if (++i < args.size()) {
- result_variable = args[i];
- } else {
- this->SetError(" called with no value for RESULT_VARIABLE.");
- return false;
- }
- } else if (args[i] == "RESULTS_VARIABLE") {
- doing_command = false;
- if (++i < args.size()) {
- results_variable = args[i];
- } else {
- this->SetError(" called with no value for RESULTS_VARIABLE.");
- return false;
- }
- } else if (args[i] == "WORKING_DIRECTORY") {
- doing_command = false;
- if (++i < args.size()) {
- working_directory = args[i];
- } else {
- this->SetError(" called with no value for WORKING_DIRECTORY.");
- return false;
- }
- } else if (args[i] == "INPUT_FILE") {
- doing_command = false;
- if (++i < args.size()) {
- input_file = args[i];
- } else {
- this->SetError(" called with no value for INPUT_FILE.");
- return false;
- }
- } else if (args[i] == "OUTPUT_FILE") {
- doing_command = false;
- if (++i < args.size()) {
- output_file = args[i];
- } else {
- this->SetError(" called with no value for OUTPUT_FILE.");
- return false;
- }
- } else if (args[i] == "ERROR_FILE") {
- doing_command = false;
- if (++i < args.size()) {
- error_file = args[i];
- } else {
- this->SetError(" called with no value for ERROR_FILE.");
- return false;
- }
- } else if (args[i] == "TIMEOUT") {
- doing_command = false;
- if (++i < args.size()) {
- timeout_string = args[i];
- } else {
- this->SetError(" called with no value for TIMEOUT.");
- return false;
- }
- } else if (args[i] == "OUTPUT_QUIET") {
- doing_command = false;
- output_quiet = true;
- } else if (args[i] == "ERROR_QUIET") {
- doing_command = false;
- error_quiet = true;
- } else if (args[i] == "OUTPUT_STRIP_TRAILING_WHITESPACE") {
- doing_command = false;
- output_strip_trailing_whitespace = true;
- } else if (args[i] == "ERROR_STRIP_TRAILING_WHITESPACE") {
- doing_command = false;
- error_strip_trailing_whitespace = true;
- } else if (args[i] == "ENCODING") {
- doing_command = false;
- if (++i < args.size()) {
- encoding = cmProcessOutput::FindEncoding(args[i]);
- } else {
- this->SetError(" called with no value for ENCODING.");
- return false;
- }
- } else if (doing_command) {
- cmds[command_index].push_back(args[i].c_str());
- } else {
- std::ostringstream e;
- e << " given unknown argument \"" << args[i] << "\".";
- this->SetError(e.str());
- return false;
- }
+
+ struct Arguments
+ {
+ std::vector<std::vector<std::string>> Commands;
+ std::string OutputVariable;
+ std::string ErrorVariable;
+ std::string ResultVariable;
+ std::string ResultsVariable;
+ std::string WorkingDirectory;
+ std::string InputFile;
+ std::string OutputFile;
+ std::string ErrorFile;
+ std::string Timeout;
+ bool OutputQuiet = false;
+ bool ErrorQuiet = false;
+ bool OutputStripTrailingWhitespace = false;
+ bool ErrorStripTrailingWhitespace = false;
+ std::string Encoding;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("COMMAND"_s, &Arguments::Commands)
+ .Bind("OUTPUT_VARIABLE"_s, &Arguments::OutputVariable)
+ .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable)
+ .Bind("RESULT_VARIABLE"_s, &Arguments::ResultVariable)
+ .Bind("RESULTS_VARIABLE"_s, &Arguments::ResultsVariable)
+ .Bind("WORKING_DIRECTORY"_s, &Arguments::WorkingDirectory)
+ .Bind("INPUT_FILE"_s, &Arguments::InputFile)
+ .Bind("OUTPUT_FILE"_s, &Arguments::OutputFile)
+ .Bind("ERROR_FILE"_s, &Arguments::ErrorFile)
+ .Bind("TIMEOUT"_s, &Arguments::Timeout)
+ .Bind("OUTPUT_QUIET"_s, &Arguments::OutputQuiet)
+ .Bind("ERROR_QUIET"_s, &Arguments::ErrorQuiet)
+ .Bind("OUTPUT_STRIP_TRAILING_WHITESPACE"_s,
+ &Arguments::OutputStripTrailingWhitespace)
+ .Bind("ERROR_STRIP_TRAILING_WHITESPACE"_s,
+ &Arguments::ErrorStripTrailingWhitespace)
+ .Bind("ENCODING"_s, &Arguments::Encoding);
+
+ std::vector<std::string> unparsedArguments;
+ std::vector<std::string> keywordsMissingValue;
+ Arguments const arguments =
+ parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
+
+ if (!keywordsMissingValue.empty()) {
+ this->SetError(" called with no value for " +
+ keywordsMissingValue.front() + ".");
+ return false;
+ }
+ if (!unparsedArguments.empty()) {
+ this->SetError(" given unknown argument \"" + unparsedArguments.front() +
+ "\".");
+ return false;
}
- if (!this->Makefile->CanIWriteThisFile(output_file)) {
- std::string e = "attempted to output into a file: " + output_file +
- " into a source directory.";
- this->SetError(e);
+ if (!this->Makefile->CanIWriteThisFile(arguments.OutputFile)) {
+ this->SetError("attempted to output into a file: " + arguments.OutputFile +
+ " into a source directory.");
cmSystemTools::SetFatalErrorOccured();
return false;
}
// Check for commands given.
- if (cmds.empty()) {
+ if (arguments.Commands.empty()) {
this->SetError(" called with no COMMAND argument.");
return false;
}
- for (auto& cmd : cmds) {
+ for (std::vector<std::string> const& cmd : arguments.Commands) {
if (cmd.empty()) {
this->SetError(" given COMMAND argument with no value.");
return false;
}
- // Add the null terminating pointer to the command argument list.
- cmd.push_back(nullptr);
}
// Parse the timeout string.
double timeout = -1;
- if (!timeout_string.empty()) {
- if (sscanf(timeout_string.c_str(), "%lg", &timeout) != 1) {
+ if (!arguments.Timeout.empty()) {
+ if (sscanf(arguments.Timeout.c_str(), "%lg", &timeout) != 1) {
this->SetError(" called with TIMEOUT value that could not be parsed.");
return false;
}
@@ -192,13 +122,17 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
cmsysProcess* cp = cmsysProcess_New();
// Set the command sequence.
- for (auto const& cmd : cmds) {
- cmsysProcess_AddCommand(cp, cmd.data());
+ for (std::vector<std::string> const& cmd : arguments.Commands) {
+ std::vector<const char*> argv(cmd.size() + 1);
+ std::transform(cmd.begin(), cmd.end(), argv.begin(),
+ [](std::string const& s) { return s.c_str(); });
+ argv.back() = nullptr;
+ cmsysProcess_AddCommand(cp, argv.data());
}
// Set the process working directory.
- if (!working_directory.empty()) {
- cmsysProcess_SetWorkingDirectory(cp, working_directory.c_str());
+ if (!arguments.WorkingDirectory.empty()) {
+ cmsysProcess_SetWorkingDirectory(cp, arguments.WorkingDirectory.c_str());
}
// Always hide the process window.
@@ -206,22 +140,24 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
// Check the output variables.
bool merge_output = false;
- if (!input_file.empty()) {
- cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN, input_file.c_str());
+ if (!arguments.InputFile.empty()) {
+ cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN,
+ arguments.InputFile.c_str());
}
- if (!output_file.empty()) {
+ if (!arguments.OutputFile.empty()) {
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDOUT,
- output_file.c_str());
+ arguments.OutputFile.c_str());
}
- if (!error_file.empty()) {
- if (error_file == output_file) {
+ if (!arguments.ErrorFile.empty()) {
+ if (arguments.ErrorFile == arguments.OutputFile) {
merge_output = true;
} else {
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR,
- error_file.c_str());
+ arguments.ErrorFile.c_str());
}
}
- if (!output_variable.empty() && output_variable == error_variable) {
+ if (!arguments.OutputVariable.empty() &&
+ arguments.OutputVariable == arguments.ErrorVariable) {
merge_output = true;
}
if (merge_output) {
@@ -242,19 +178,20 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
int length;
char* data;
int p;
- cmProcessOutput processOutput(encoding);
+ cmProcessOutput processOutput(
+ cmProcessOutput::FindEncoding(arguments.Encoding));
std::string strdata;
while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
// Put the output in the right place.
- if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) {
- if (output_variable.empty()) {
+ if (p == cmsysProcess_Pipe_STDOUT && !arguments.OutputQuiet) {
+ if (arguments.OutputVariable.empty()) {
processOutput.DecodeText(data, length, strdata, 1);
cmSystemTools::Stdout(strdata);
} else {
cmExecuteProcessCommandAppend(tempOutput, data, length);
}
- } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) {
- if (error_variable.empty()) {
+ } else if (p == cmsysProcess_Pipe_STDERR && !arguments.ErrorQuiet) {
+ if (arguments.ErrorVariable.empty()) {
processOutput.DecodeText(data, length, strdata, 2);
cmSystemTools::Stderr(strdata);
} else {
@@ -262,13 +199,13 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
}
}
}
- if (!output_quiet && output_variable.empty()) {
+ if (!arguments.OutputQuiet && arguments.OutputVariable.empty()) {
processOutput.DecodeText(std::string(), strdata, 1);
if (!strdata.empty()) {
cmSystemTools::Stdout(strdata);
}
}
- if (!error_quiet && error_variable.empty()) {
+ if (!arguments.ErrorQuiet && arguments.ErrorVariable.empty()) {
processOutput.DecodeText(std::string(), strdata, 2);
if (!strdata.empty()) {
cmSystemTools::Stderr(strdata);
@@ -281,46 +218,49 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
processOutput.DecodeText(tempError, tempError);
// Fix the text in the output strings.
- cmExecuteProcessCommandFixText(tempOutput, output_strip_trailing_whitespace);
- cmExecuteProcessCommandFixText(tempError, error_strip_trailing_whitespace);
+ cmExecuteProcessCommandFixText(tempOutput,
+ arguments.OutputStripTrailingWhitespace);
+ cmExecuteProcessCommandFixText(tempError,
+ arguments.ErrorStripTrailingWhitespace);
// Store the output obtained.
- if (!output_variable.empty() && !tempOutput.empty()) {
- this->Makefile->AddDefinition(output_variable, tempOutput.data());
+ if (!arguments.OutputVariable.empty() && !tempOutput.empty()) {
+ this->Makefile->AddDefinition(arguments.OutputVariable, tempOutput.data());
}
- if (!merge_output && !error_variable.empty() && !tempError.empty()) {
- this->Makefile->AddDefinition(error_variable, tempError.data());
+ if (!merge_output && !arguments.ErrorVariable.empty() &&
+ !tempError.empty()) {
+ this->Makefile->AddDefinition(arguments.ErrorVariable, tempError.data());
}
// Store the result of running the process.
- if (!result_variable.empty()) {
+ if (!arguments.ResultVariable.empty()) {
switch (cmsysProcess_GetState(cp)) {
case cmsysProcess_State_Exited: {
int v = cmsysProcess_GetExitValue(cp);
char buf[16];
sprintf(buf, "%d", v);
- this->Makefile->AddDefinition(result_variable, buf);
+ this->Makefile->AddDefinition(arguments.ResultVariable, buf);
} break;
case cmsysProcess_State_Exception:
- this->Makefile->AddDefinition(result_variable,
+ this->Makefile->AddDefinition(arguments.ResultVariable,
cmsysProcess_GetExceptionString(cp));
break;
case cmsysProcess_State_Error:
- this->Makefile->AddDefinition(result_variable,
+ this->Makefile->AddDefinition(arguments.ResultVariable,
cmsysProcess_GetErrorString(cp));
break;
case cmsysProcess_State_Expired:
- this->Makefile->AddDefinition(result_variable,
+ this->Makefile->AddDefinition(arguments.ResultVariable,
"Process terminated due to timeout");
break;
}
}
// Store the result of running the processes.
- if (!results_variable.empty()) {
+ if (!arguments.ResultsVariable.empty()) {
switch (cmsysProcess_GetState(cp)) {
case cmsysProcess_State_Exited: {
std::vector<std::string> res;
- for (size_t i = 0; i < cmds.size(); ++i) {
+ for (size_t i = 0; i < arguments.Commands.size(); ++i) {
switch (cmsysProcess_GetStateByIndex(cp, static_cast<int>(i))) {
case kwsysProcess_StateByIndex_Exited: {
int exitCode =
@@ -339,19 +279,19 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
break;
}
}
- this->Makefile->AddDefinition(results_variable,
+ this->Makefile->AddDefinition(arguments.ResultsVariable,
cmJoin(res, ";").c_str());
} break;
case cmsysProcess_State_Exception:
- this->Makefile->AddDefinition(results_variable,
+ this->Makefile->AddDefinition(arguments.ResultsVariable,
cmsysProcess_GetExceptionString(cp));
break;
case cmsysProcess_State_Error:
- this->Makefile->AddDefinition(results_variable,
+ this->Makefile->AddDefinition(arguments.ResultsVariable,
cmsysProcess_GetErrorString(cp));
break;
case cmsysProcess_State_Expired:
- this->Makefile->AddDefinition(results_variable,
+ this->Makefile->AddDefinition(arguments.ResultsVariable,
"Process terminated due to timeout");
break;
}
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index c25e1f4..5b611c0 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -2,10 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportCommand.h"
+#include "cm_static_string_view.hxx"
#include "cmsys/RegularExpression.hxx"
#include <map>
#include <sstream>
+#include <utility>
+#include "cmArgumentParser.h"
#include "cmExportBuildAndroidMKGenerator.h"
#include "cmExportBuildFileGenerator.h"
#include "cmExportSetMap.h"
@@ -18,6 +21,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
+class cmExportSet;
class cmExecutionStatus;
#if defined(__HAIKU__)
@@ -25,19 +29,6 @@ class cmExecutionStatus;
# include <StorageDefs.h>
#endif
-cmExportCommand::cmExportCommand()
- : Targets(&Helper, "TARGETS")
- , Append(&Helper, "APPEND", &ArgumentGroup)
- , ExportSetName(&Helper, "EXPORT", &ArgumentGroup)
- , Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
- , Filename(&Helper, "FILE", &ArgumentGroup)
- , ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup)
- , AndroidMKFile(&Helper, "ANDROID_MK")
-{
- this->ExportSet = nullptr;
-}
-
-// cmExportCommand
bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
@@ -49,45 +40,62 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
if (args[0] == "PACKAGE") {
return this->HandlePackage(args);
}
+
+ struct Arguments
+ {
+ std::string ExportSetName;
+ std::vector<std::string> Targets;
+ std::string Namespace;
+ std::string Filename;
+ std::string AndroidMKFile;
+ bool Append = false;
+ bool ExportOld = false;
+ };
+
+ auto parser = cmArgumentParser<Arguments>{}
+ .Bind("NAMESPACE"_s, &Arguments::Namespace)
+ .Bind("FILE"_s, &Arguments::Filename);
+
if (args[0] == "EXPORT") {
- this->ExportSetName.Follows(nullptr);
- this->ArgumentGroup.Follows(&this->ExportSetName);
+ parser.Bind("EXPORT"_s, &Arguments::ExportSetName);
} else {
- this->Targets.Follows(nullptr);
- this->ArgumentGroup.Follows(&this->Targets);
+ parser.Bind("TARGETS"_s, &Arguments::Targets);
+ parser.Bind("ANDROID_MK"_s, &Arguments::AndroidMKFile);
+ parser.Bind("APPEND"_s, &Arguments::Append);
+ parser.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, &Arguments::ExportOld);
}
std::vector<std::string> unknownArgs;
- this->Helper.Parse(&args, &unknownArgs);
+ Arguments const arguments = parser.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
- this->SetError("Unknown arguments.");
+ this->SetError("Unknown argument: \"" + unknownArgs.front() + "\".");
return false;
}
std::string fname;
bool android = false;
- if (this->AndroidMKFile.WasFound()) {
- fname = this->AndroidMKFile.GetString();
+ if (!arguments.AndroidMKFile.empty()) {
+ fname = arguments.AndroidMKFile;
android = true;
}
- if (!this->Filename.WasFound() && fname.empty()) {
+ if (arguments.Filename.empty() && fname.empty()) {
if (args[0] != "EXPORT") {
this->SetError("FILE <filename> option missing.");
return false;
}
- fname = this->ExportSetName.GetString() + ".cmake";
+ fname = arguments.ExportSetName + ".cmake";
} else if (fname.empty()) {
// Make sure the file has a .cmake extension.
- if (cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString()) !=
+ if (cmSystemTools::GetFilenameLastExtension(arguments.Filename) !=
".cmake") {
std::ostringstream e;
- e << "FILE option given filename \"" << this->Filename.GetString()
+ e << "FILE option given filename \"" << arguments.Filename
<< "\" which does not have an extension of \".cmake\".\n";
this->SetError(e.str());
return false;
}
- fname = this->Filename.GetString();
+ fname = arguments.Filename;
}
// Get the file to write.
@@ -109,33 +117,19 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
+ cmExportSet* ExportSet = nullptr;
if (args[0] == "EXPORT") {
- if (this->Append.IsEnabled()) {
- std::ostringstream e;
- e << "EXPORT signature does not recognise the APPEND option.";
- this->SetError(e.str());
- return false;
- }
-
- if (this->ExportOld.IsEnabled()) {
- std::ostringstream e;
- e << "EXPORT signature does not recognise the "
- "EXPORT_LINK_INTERFACE_LIBRARIES option.";
- this->SetError(e.str());
- return false;
- }
-
cmExportSetMap& setMap = gg->GetExportSets();
- std::string setName = this->ExportSetName.GetString();
- if (setMap.find(setName) == setMap.end()) {
+ auto const it = setMap.find(arguments.ExportSetName);
+ if (it == setMap.end()) {
std::ostringstream e;
- e << "Export set \"" << setName << "\" not found.";
+ e << "Export set \"" << arguments.ExportSetName << "\" not found.";
this->SetError(e.str());
return false;
}
- this->ExportSet = setMap[setName];
- } else if (this->Targets.WasFound()) {
- for (std::string const& currentTarget : this->Targets.GetVector()) {
+ ExportSet = it->second;
+ } else if (!arguments.Targets.empty()) {
+ for (std::string const& currentTarget : arguments.Targets) {
if (this->Makefile->IsAlias(currentTarget)) {
std::ostringstream e;
e << "given ALIAS target \"" << currentTarget
@@ -159,7 +153,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
}
targets.push_back(currentTarget);
}
- if (this->Append.IsEnabled()) {
+ if (arguments.Append) {
if (cmExportBuildFileGenerator* ebfg =
gg->GetExportedTargetsFile(fname)) {
ebfg->AppendTargets(targets);
@@ -179,15 +173,15 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
ebfg = new cmExportBuildFileGenerator;
}
ebfg->SetExportFile(fname.c_str());
- ebfg->SetNamespace(this->Namespace.GetCString());
- ebfg->SetAppendMode(this->Append.IsEnabled());
- if (this->ExportSet) {
- ebfg->SetExportSet(this->ExportSet);
+ ebfg->SetNamespace(arguments.Namespace);
+ ebfg->SetAppendMode(arguments.Append);
+ if (ExportSet != nullptr) {
+ ebfg->SetExportSet(ExportSet);
} else {
ebfg->SetTargets(targets);
}
this->Makefile->AddExportBuildFileGenerator(ebfg);
- ebfg->SetExportOld(this->ExportOld.IsEnabled());
+ ebfg->SetExportOld(arguments.ExportOld);
// Compute the set of configurations exported.
std::vector<std::string> configurationTypes;
@@ -198,7 +192,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
for (std::string const& ct : configurationTypes) {
ebfg->AddConfiguration(ct);
}
- if (this->ExportSet) {
+ if (ExportSet != nullptr) {
gg->AddBuildExportExportSet(ebfg);
} else {
gg->AddBuildExportSet(ebfg);
diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h
index a5c6751..99f9932 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -9,21 +9,12 @@
#include <vector>
#include "cmCommand.h"
-#include "cmCommandArgumentsHelper.h"
class cmExecutionStatus;
-class cmExportSet;
-/** \class cmExportLibraryDependenciesCommand
- * \brief Add a test to the lists of tests to run.
- *
- * cmExportLibraryDependenciesCommand adds a test to the list of tests to run
- *
- */
class cmExportCommand : public cmCommand
{
public:
- cmExportCommand();
/**
* This is a virtual constructor for the command.
*/
@@ -37,21 +28,6 @@ public:
cmExecutionStatus& status) override;
private:
- cmCommandArgumentsHelper Helper;
- cmCommandArgumentGroup ArgumentGroup;
- cmCAStringVector Targets;
- cmCAEnabler Append;
- cmCAString ExportSetName;
- cmCAString Namespace;
- cmCAString Filename;
- cmCAEnabler ExportOld;
- cmCAString AndroidMKFile;
-
- cmExportSet* ExportSet;
-
- friend class cmExportBuildFileGenerator;
- std::string ErrorMessage;
-
bool HandlePackage(std::vector<std::string> const& args);
void StorePackageRegistryWin(std::string const& package, const char* content,
const char* hash);
diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h
index 4438f28..a472a06 100644
--- a/Source/cmExternalMakefileProjectGenerator.h
+++ b/Source/cmExternalMakefileProjectGenerator.h
@@ -31,13 +31,13 @@ public:
virtual void EnableLanguage(std::vector<std::string> const& languages,
cmMakefile*, bool optional);
- ///! set the global generator which will generate the makefiles
+ //! set the global generator which will generate the makefiles
virtual void SetGlobalGenerator(cmGlobalGenerator* generator)
{
this->GlobalGenerator = generator;
}
- ///! Return the list of global generators supported by this extra generator
+ //! Return the list of global generators supported by this extra generator
const std::vector<std::string>& GetSupportedGlobalGenerators() const
{
return this->SupportedGlobalGenerators;
@@ -49,7 +49,7 @@ public:
static std::string CreateFullGeneratorName(
const std::string& globalGenerator, const std::string& extraGenerator);
- ///! Generate the project files, the Makefiles have already been generated
+ //! Generate the project files, the Makefiles have already been generated
virtual void Generate() = 0;
void SetName(const std::string& n) { Name = n; }
@@ -59,9 +59,9 @@ public:
bool dryRun);
protected:
- ///! Contains the names of the global generators support by this generator.
+ //! Contains the names of the global generators support by this generator.
std::vector<std::string> SupportedGlobalGenerators;
- ///! the global generator which creates the makefiles
+ //! the global generator which creates the makefiles
const cmGlobalGenerator* GlobalGenerator = nullptr;
std::string Name;
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index 76de75d..877f109 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -196,7 +196,7 @@ void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout,
{
static char JsonSep = ' ';
- fout << "\t\t\t" << JsonSep << "{\"name\":\"" << target
+ fout << "\t\t\t" << JsonSep << R"({"name":")" << target
<< "\", "
"\"build_cmd\":\""
<< make << " -C \\\"" << (this->UseNinja ? homeOutputDir : path)
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 59cfdca..71c8fcd 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -263,7 +263,7 @@ void cmExtraSublimeTextGenerator::AppendTarget(
// Regular expression to extract compiler flags from a string
// https://gist.github.com/3944250
const char* regexString =
- "(^|[ ])-[DIOUWfgs][^= ]+(=\\\"[^\"]+\\\"|=[^\"][^ ]+)?";
+ R"((^|[ ])-[DIOUWfgs][^= ]+(=\"[^"]+\"|=[^"][^ ]+)?)";
flagRegex.compile(regexString);
std::string workString =
flagsString + " " + definesString + " " + includesString;
@@ -315,12 +315,12 @@ std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
std::string generator = this->GlobalGenerator->GetName();
if (generator == "NMake Makefiles") {
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- command += ", \"/NOLOGO\", \"/f\", \"";
+ command += R"(, "/NOLOGO", "/f", ")";
command += makefileName + "\"";
command += ", \"" + target + "\"";
} else if (generator == "Ninja") {
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- command += ", \"-f\", \"";
+ command += R"(, "-f", ")";
command += makefileName + "\"";
command += ", \"" + target + "\"";
} else {
@@ -332,7 +332,7 @@ std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
} else {
makefileName = cmSystemTools::ConvertToOutputPath(makefile);
}
- command += ", \"-f\", \"";
+ command += R"(, "-f", ")";
command += makefileName + "\"";
command += ", \"" + target + "\"";
}
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index d2bc851..f5ec9fe 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -3,6 +3,7 @@
#include "cmFileCommand.h"
#include "cm_kwiml.h"
+#include "cm_static_string_view.hxx"
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
@@ -19,7 +20,7 @@
#include <vector>
#include "cmAlgorithms.h"
-#include "cmCommandArgumentsHelper.h"
+#include "cmArgumentParser.h"
#include "cmCryptoHash.h"
#include "cmFileCopier.h"
#include "cmFileInstaller.h"
@@ -268,36 +269,34 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
return false;
}
- cmCommandArgumentsHelper argHelper;
- cmCommandArgumentGroup group;
+ std::string const& fileNameArg = args[1];
+ std::string const& variable = args[2];
- cmCAString readArg(&argHelper, "READ");
- cmCAString fileNameArg(&argHelper, nullptr);
- cmCAString resultArg(&argHelper, nullptr);
+ struct Arguments
+ {
+ std::string Offset;
+ std::string Limit;
+ bool Hex = false;
+ };
+
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("OFFSET"_s, &Arguments::Offset)
+ .Bind("LIMIT"_s, &Arguments::Limit)
+ .Bind("HEX"_s, &Arguments::Hex);
- cmCAString offsetArg(&argHelper, "OFFSET", &group);
- cmCAString limitArg(&argHelper, "LIMIT", &group);
- cmCAEnabler hexOutputArg(&argHelper, "HEX", &group);
- readArg.Follows(nullptr);
- fileNameArg.Follows(&readArg);
- resultArg.Follows(&fileNameArg);
- group.Follows(&resultArg);
- argHelper.Parse(&args, nullptr);
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3));
- std::string fileName = fileNameArg.GetString();
+ std::string fileName = fileNameArg;
if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
fileName = this->Makefile->GetCurrentSourceDirectory();
- fileName += "/" + fileNameArg.GetString();
+ fileName += "/" + fileNameArg;
}
- std::string variable = resultArg.GetString();
-
// Open the specified file.
#if defined(_WIN32) || defined(__CYGWIN__)
- cmsys::ifstream file(
- fileName.c_str(),
- std::ios::in |
- (hexOutputArg.IsEnabled() ? std::ios::binary : std::ios::in));
+ cmsys::ifstream file(fileName.c_str(),
+ arguments.Hex ? (std::ios::binary | std::ios::in)
+ : std::ios::in);
#else
cmsys::ifstream file(fileName.c_str());
#endif
@@ -313,21 +312,21 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
// is there a limit?
long sizeLimit = -1;
- if (!limitArg.GetString().empty()) {
- sizeLimit = atoi(limitArg.GetCString());
+ if (!arguments.Limit.empty()) {
+ sizeLimit = atoi(arguments.Limit.c_str());
}
// is there an offset?
long offset = 0;
- if (!offsetArg.GetString().empty()) {
- offset = atoi(offsetArg.GetCString());
+ if (!arguments.Offset.empty()) {
+ offset = atoi(arguments.Offset.c_str());
}
file.seekg(offset, std::ios::beg); // explicit ios::beg for IBM VisualAge 6
std::string output;
- if (hexOutputArg.IsEnabled()) {
+ if (arguments.Hex) {
// Convert part of the file into hex code
char c;
while ((sizeLimit != 0) && (file.get(c))) {
@@ -1272,55 +1271,54 @@ bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args)
return false;
}
- cmCommandArgumentsHelper argHelper;
- cmCommandArgumentGroup group;
-
- cmCAString readArg(&argHelper, "READ_ELF");
- cmCAString fileNameArg(&argHelper, nullptr);
+ std::string const& fileNameArg = args[1];
- cmCAString rpathArg(&argHelper, "RPATH", &group);
- cmCAString runpathArg(&argHelper, "RUNPATH", &group);
- cmCAString errorArg(&argHelper, "CAPTURE_ERROR", &group);
+ struct Arguments
+ {
+ std::string RPath;
+ std::string RunPath;
+ std::string Error;
+ };
- readArg.Follows(nullptr);
- fileNameArg.Follows(&readArg);
- group.Follows(&fileNameArg);
- argHelper.Parse(&args, nullptr);
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("RPATH"_s, &Arguments::RPath)
+ .Bind("RUNPATH"_s, &Arguments::RunPath)
+ .Bind("CAPTURE_ERROR"_s, &Arguments::Error);
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2));
- if (!cmSystemTools::FileExists(fileNameArg.GetString(), true)) {
+ if (!cmSystemTools::FileExists(fileNameArg, true)) {
std::ostringstream e;
- e << "READ_ELF given FILE \"" << fileNameArg.GetString()
- << "\" that does not exist.";
+ e << "READ_ELF given FILE \"" << fileNameArg << "\" that does not exist.";
this->SetError(e.str());
return false;
}
#if defined(CMAKE_USE_ELF_PARSER)
- cmELF elf(fileNameArg.GetCString());
+ cmELF elf(fileNameArg.c_str());
- if (!rpathArg.GetString().empty()) {
+ if (!arguments.RPath.empty()) {
if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
std::string rpath(se_rpath->Value);
std::replace(rpath.begin(), rpath.end(), ':', ';');
- this->Makefile->AddDefinition(rpathArg.GetString(), rpath.c_str());
+ this->Makefile->AddDefinition(arguments.RPath, rpath.c_str());
}
}
- if (!runpathArg.GetString().empty()) {
+ if (!arguments.RunPath.empty()) {
if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) {
std::string runpath(se_runpath->Value);
std::replace(runpath.begin(), runpath.end(), ':', ';');
- this->Makefile->AddDefinition(runpathArg.GetString(), runpath.c_str());
+ this->Makefile->AddDefinition(arguments.RunPath, runpath.c_str());
}
}
return true;
#else
std::string error = "ELF parser not available on this platform.";
- if (errorArg.GetString().empty()) {
+ if (arguments.Error.empty()) {
this->SetError(error);
return false;
}
- this->Makefile->AddDefinition(errorArg.GetString(), error.c_str());
+ this->Makefile->AddDefinition(arguments.Error, error.c_str());
return true;
#endif
}
@@ -2597,44 +2595,39 @@ bool cmFileCommand::HandleCreateLinkCommand(
return false;
}
- cmCommandArgumentsHelper argHelper;
- cmCommandArgumentGroup group;
-
- cmCAString linkArg(&argHelper, "CREATE_LINK");
- cmCAString fileArg(&argHelper, nullptr);
- cmCAString newFileArg(&argHelper, nullptr);
+ std::string const& fileName = args[1];
+ std::string const& newFileName = args[2];
- cmCAString resultArg(&argHelper, "RESULT", &group);
- cmCAEnabler copyOnErrorArg(&argHelper, "COPY_ON_ERROR", &group);
- cmCAEnabler symbolicArg(&argHelper, "SYMBOLIC", &group);
+ struct Arguments
+ {
+ std::string Result;
+ bool CopyOnError = false;
+ bool Symbolic = false;
+ };
- linkArg.Follows(nullptr);
- fileArg.Follows(&linkArg);
- newFileArg.Follows(&fileArg);
- group.Follows(&newFileArg);
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("RESULT"_s, &Arguments::Result)
+ .Bind("COPY_ON_ERROR"_s, &Arguments::CopyOnError)
+ .Bind("SYMBOLIC"_s, &Arguments::Symbolic);
std::vector<std::string> unconsumedArgs;
- argHelper.Parse(&args, &unconsumedArgs);
+ Arguments const arguments =
+ parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs);
if (!unconsumedArgs.empty()) {
this->SetError("unknown argument: \"" + unconsumedArgs.front() + '\"');
return false;
}
- std::string fileName = fileArg.GetString();
- std::string newFileName = newFileArg.GetString();
-
- // Output variable for storing the result.
- const std::string& resultVar = resultArg.GetString();
-
// The system error message generated in the operation.
std::string result;
// Check if the paths are distinct.
if (fileName == newFileName) {
result = "CREATE_LINK cannot use same file and newfile";
- if (!resultVar.empty()) {
- this->Makefile->AddDefinition(resultVar, result.c_str());
+ if (!arguments.Result.empty()) {
+ this->Makefile->AddDefinition(arguments.Result, result.c_str());
return true;
}
this->SetError(result);
@@ -2642,10 +2635,10 @@ bool cmFileCommand::HandleCreateLinkCommand(
}
// Hard link requires original file to exist.
- if (!symbolicArg.IsEnabled() && !cmSystemTools::FileExists(fileName)) {
+ if (!arguments.Symbolic && !cmSystemTools::FileExists(fileName)) {
result = "Cannot hard link \'" + fileName + "\' as it does not exist.";
- if (!resultVar.empty()) {
- this->Makefile->AddDefinition(resultVar, result.c_str());
+ if (!arguments.Result.empty()) {
+ this->Makefile->AddDefinition(arguments.Result, result.c_str());
return true;
}
this->SetError(result);
@@ -2661,8 +2654,8 @@ bool cmFileCommand::HandleCreateLinkCommand(
<< "' because existing path cannot be removed: "
<< cmSystemTools::GetLastSystemError() << "\n";
- if (!resultVar.empty()) {
- this->Makefile->AddDefinition(resultVar, e.str().c_str());
+ if (!arguments.Result.empty()) {
+ this->Makefile->AddDefinition(arguments.Result, e.str().c_str());
return true;
}
this->SetError(e.str());
@@ -2673,14 +2666,14 @@ bool cmFileCommand::HandleCreateLinkCommand(
bool completed = false;
// Check if the command requires a symbolic link.
- if (symbolicArg.IsEnabled()) {
+ if (arguments.Symbolic) {
completed = cmSystemTools::CreateSymlink(fileName, newFileName, &result);
} else {
completed = cmSystemTools::CreateLink(fileName, newFileName, &result);
}
// Check if copy-on-error is enabled in the arguments.
- if (!completed && copyOnErrorArg.IsEnabled()) {
+ if (!completed && arguments.CopyOnError) {
completed = cmsys::SystemTools::CopyFileAlways(fileName, newFileName);
if (!completed) {
result = "Copy failed: " + cmSystemTools::GetLastSystemError();
@@ -2690,14 +2683,14 @@ bool cmFileCommand::HandleCreateLinkCommand(
// Check if the operation was successful.
if (completed) {
result = "0";
- } else if (resultVar.empty()) {
+ } else if (arguments.Result.empty()) {
// The operation failed and the result is not reported in a variable.
this->SetError(result);
return false;
}
- if (!resultVar.empty()) {
- this->Makefile->AddDefinition(resultVar, result.c_str());
+ if (!arguments.Result.empty()) {
+ this->Makefile->AddDefinition(arguments.Result, result.c_str());
}
return true;
diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx
index f3544c1..d4f76fd 100644
--- a/Source/cmFileInstaller.cxx
+++ b/Source/cmFileInstaller.cxx
@@ -319,7 +319,7 @@ bool cmFileInstaller::HandleInstallDestination()
return false;
}
}
- destination = sdestdir + (destination.c_str() + skip);
+ destination = sdestdir + destination.substr(skip);
this->DestDirLength = int(sdestdir.size());
}
diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h
index 4c8e556..d4de4e0 100644
--- a/Source/cmFileTime.h
+++ b/Source/cmFileTime.h
@@ -50,7 +50,7 @@ public:
* @brief Compare file modification times.
* @return -1, 0, +1 for this older, same, or newer than ftm.
*/
- int Compare(cmFileTime const& ftm)
+ int Compare(cmFileTime const& ftm) const
{
NSC const diff = this->NS - ftm.NS;
if (diff == 0) {
diff --git a/Source/cmFileTimeCache.cxx b/Source/cmFileTimeCache.cxx
index 1fff6a9..24d6bf6 100644
--- a/Source/cmFileTimeCache.cxx
+++ b/Source/cmFileTimeCache.cxx
@@ -14,8 +14,8 @@ bool cmFileTimeCache::Load(std::string const& fileName, cmFileTime& fileTime)
{
// Use the stored time if available.
{
- auto fit = this->FileTimes.find(fileName);
- if (fit != this->FileTimes.end()) {
+ auto fit = this->Cache.find(fileName);
+ if (fit != this->Cache.end()) {
fileTime = fit->second;
return true;
}
@@ -25,10 +25,15 @@ bool cmFileTimeCache::Load(std::string const& fileName, cmFileTime& fileTime)
return false;
}
// Store file time in cache
- this->FileTimes[fileName] = fileTime;
+ this->Cache[fileName] = fileTime;
return true;
}
+bool cmFileTimeCache::Remove(std::string const& fileName)
+{
+ return (this->Cache.erase(fileName) != 0);
+}
+
bool cmFileTimeCache::Compare(std::string const& f1, std::string const& f2,
int* result)
{
diff --git a/Source/cmFileTimeCache.h b/Source/cmFileTimeCache.h
index a47904c..4f1a3a2 100644
--- a/Source/cmFileTimeCache.h
+++ b/Source/cmFileTimeCache.h
@@ -5,7 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmFileTime.h"
+#include "cmFileTime.h" // IWYU pragma: keep
#include <string>
#include <unordered_map>
@@ -28,6 +28,12 @@ public:
bool Load(std::string const& fileName, cmFileTime& fileTime);
/**
+ * @brief Removes a file time from the cache
+ * @return true if the file was found in the cache and removed
+ */
+ bool Remove(std::string const& fileName);
+
+ /**
* @brief Compare file modification times.
* @return true for successful comparison and false for error.
*
@@ -44,8 +50,7 @@ public:
bool DifferS(std::string const& f1, std::string const& f2);
private:
- typedef std::unordered_map<std::string, cmFileTime> FileTimeMap;
- FileTimeMap FileTimes;
+ std::unordered_map<std::string, cmFileTime> Cache;
};
#endif
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 50413c8..8b3d9d6 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -15,6 +15,7 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
@@ -27,6 +28,7 @@
#include <algorithm>
#include <assert.h>
#include <errno.h>
+#include <iterator>
#include <map>
#include <memory> // IWYU pragma: keep
#include <set>
@@ -326,6 +328,79 @@ static const struct InListNode : public cmGeneratorExpressionNode
}
} inListNode;
+static const struct FilterNode : public cmGeneratorExpressionNode
+{
+ FilterNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 3; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 3) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<FILTER:...> expression requires three parameters");
+ return {};
+ }
+
+ if (parameters[1] != "INCLUDE" && parameters[1] != "EXCLUDE") {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<FILTER:...> second parameter must be either INCLUDE or EXCLUDE");
+ return {};
+ }
+
+ const bool exclude = parameters[1] == "EXCLUDE";
+
+ cmsys::RegularExpression re;
+ if (!re.compile(parameters[2])) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<FILTER:...> failed to compile regex");
+ return {};
+ }
+
+ std::vector<std::string> values, result;
+ cmSystemTools::ExpandListArgument(parameters.front(), values, true);
+
+ std::copy_if(values.cbegin(), values.cend(), std::back_inserter(result),
+ [&re, exclude](std::string const& input) {
+ return exclude ^ re.find(input);
+ });
+ return cmJoin(cmMakeRange(result.cbegin(), result.cend()), ";");
+ }
+} filterNode;
+
+static const struct RemoveDuplicatesNode : public cmGeneratorExpressionNode
+{
+ RemoveDuplicatesNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<REMOVE_DUPLICATES:...> expression requires one parameter");
+ }
+
+ std::vector<std::string> values;
+ cmSystemTools::ExpandListArgument(parameters.front(), values, true);
+
+ auto valuesEnd = cmRemoveDuplicates(values);
+ auto valuesBegin = values.cbegin();
+ return cmJoin(cmMakeRange(valuesBegin, valuesEnd), ";");
+ }
+
+} removeDuplicatesNode;
+
static const struct TargetExistsNode : public cmGeneratorExpressionNode
{
TargetExistsNode() {} // NOLINT(modernize-use-equals-default)
@@ -1994,18 +2069,16 @@ struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
static std::string Get(const std::string& result) { return result; }
};
-template <typename ArtifactT, typename ComponentT>
-struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
+struct TargetArtifactBase : public cmGeneratorExpressionNode
{
- TargetFilesystemArtifact() {} // NOLINT(modernize-use-equals-default)
+ TargetArtifactBase() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const override { return 1; }
-
- std::string Evaluate(
+protected:
+ cmGeneratorTarget* GetTarget(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const override
+ cmGeneratorExpressionDAGChecker* dagChecker) const
{
// Lookup the referenced target.
std::string name = parameters.front();
@@ -2013,20 +2086,20 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
if (!cmGeneratorExpression::IsValidTargetName(name)) {
::reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
- return std::string();
+ return nullptr;
}
cmGeneratorTarget* target = context->LG->FindGeneratorTargetToUse(name);
if (!target) {
::reportError(context, content->GetOriginalExpression(),
"No target \"" + name + "\"");
- return std::string();
+ return nullptr;
}
if (target->GetType() >= cmStateEnums::OBJECT_LIBRARY &&
target->GetType() != cmStateEnums::UNKNOWN_LIBRARY) {
::reportError(context, content->GetOriginalExpression(),
"Target \"" + name +
"\" is not an executable or library.");
- return std::string();
+ return nullptr;
}
if (dagChecker &&
(dagChecker->EvaluatingLinkLibraries(target) ||
@@ -2035,6 +2108,29 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
::reportError(context, content->GetOriginalExpression(),
"Expressions which require the linker language may not "
"be used while evaluating link libraries");
+ return nullptr;
+ }
+
+ return target;
+ }
+};
+
+template <typename ArtifactT, typename ComponentT>
+struct TargetFilesystemArtifact : public TargetArtifactBase
+{
+ TargetFilesystemArtifact() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ cmGeneratorTarget* target =
+ this->GetTarget(parameters, context, content, dagChecker);
+ if (!target) {
return std::string();
}
context->DependTargets.insert(target);
@@ -2081,6 +2177,239 @@ static const TargetFilesystemArtifact<ArtifactBundleContentDirTag,
ArtifactPathTag>
targetBundleContentDirNode;
+//
+// To retrieve base name for various artifacts
+//
+template <typename ArtifactT>
+struct TargetOutputNameArtifactResultGetter
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content);
+};
+
+template <>
+struct TargetOutputNameArtifactResultGetter<ArtifactNameTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* /*unused*/)
+ {
+ return target->GetOutputName(context->Config,
+ cmStateEnums::RuntimeBinaryArtifact);
+ }
+};
+
+template <>
+struct TargetOutputNameArtifactResultGetter<ArtifactLinkerTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ // The file used to link to the target (.so, .lib, .a).
+ if (!target->IsLinkable()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_LINKER_FILE_BASE_NAME is allowed only for "
+ "libraries and executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+ cmStateEnums::ArtifactType artifact =
+ target->HasImportLibrary(context->Config)
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+ return target->GetOutputName(context->Config, artifact);
+ }
+};
+
+template <>
+struct TargetOutputNameArtifactResultGetter<ArtifactPdbTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (target->IsImported()) {
+ ::reportError(
+ context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE_BASE_NAME not allowed for IMPORTED targets.");
+ return std::string();
+ }
+
+ std::string language = target->GetLinkerLanguage(context->Config);
+
+ std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";
+
+ if (!context->LG->GetMakefile()->IsOn(pdbSupportVar)) {
+ ::reportError(
+ context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE_BASE_NAME is not supported by the target linker.");
+ return std::string();
+ }
+
+ cmStateEnums::TargetType targetType = target->GetType();
+
+ if (targetType != cmStateEnums::SHARED_LIBRARY &&
+ targetType != cmStateEnums::MODULE_LIBRARY &&
+ targetType != cmStateEnums::EXECUTABLE) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE_BASE_NAME is allowed only for "
+ "targets with linker created artifacts.");
+ return std::string();
+ }
+
+ return target->GetPDBOutputName(context->Config);
+ }
+};
+
+template <typename ArtifactT>
+struct TargetFileBaseNameArtifact : public TargetArtifactBase
+{
+ TargetFileBaseNameArtifact() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ cmGeneratorTarget* target =
+ this->GetTarget(parameters, context, content, dagChecker);
+ if (!target) {
+ return std::string();
+ }
+
+ std::string result = TargetOutputNameArtifactResultGetter<ArtifactT>::Get(
+ target, context, content);
+ if (context->HadError) {
+ return std::string();
+ }
+ return result;
+ }
+};
+
+static const TargetFileBaseNameArtifact<ArtifactNameTag>
+ targetFileBaseNameNode;
+static const TargetFileBaseNameArtifact<ArtifactLinkerTag>
+ targetLinkerFileBaseNameNode;
+static const TargetFileBaseNameArtifact<ArtifactPdbTag>
+ targetPdbFileBaseNameNode;
+
+class ArtifactFilePrefixTag;
+class ArtifactLinkerFilePrefixTag;
+class ArtifactFileSuffixTag;
+class ArtifactLinkerFileSuffixTag;
+
+template <typename ArtifactT>
+struct TargetFileArtifactResultGetter
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content);
+};
+
+template <>
+struct TargetFileArtifactResultGetter<ArtifactFilePrefixTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent*)
+ {
+ return target->GetFilePrefix(context->Config);
+ }
+};
+template <>
+struct TargetFileArtifactResultGetter<ArtifactLinkerFilePrefixTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (!target->IsLinkable()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_LINKER_PREFIX is allowed only for libraries and "
+ "executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+
+ cmStateEnums::ArtifactType artifact =
+ target->HasImportLibrary(context->Config)
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+
+ return target->GetFilePrefix(context->Config, artifact);
+ }
+};
+template <>
+struct TargetFileArtifactResultGetter<ArtifactFileSuffixTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent*)
+ {
+ return target->GetFileSuffix(context->Config);
+ }
+};
+template <>
+struct TargetFileArtifactResultGetter<ArtifactLinkerFileSuffixTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (!target->IsLinkable()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_LINKER_SUFFIX is allowed only for libraries and "
+ "executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+
+ cmStateEnums::ArtifactType artifact =
+ target->HasImportLibrary(context->Config)
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+
+ return target->GetFileSuffix(context->Config, artifact);
+ }
+};
+
+template <typename ArtifactT>
+struct TargetFileArtifact : public TargetArtifactBase
+{
+ TargetFileArtifact() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ cmGeneratorTarget* target =
+ this->GetTarget(parameters, context, content, dagChecker);
+ if (!target) {
+ return std::string();
+ }
+
+ std::string result =
+ TargetFileArtifactResultGetter<ArtifactT>::Get(target, context, content);
+ if (context->HadError) {
+ return std::string();
+ }
+ return result;
+ }
+};
+
+static const TargetFileArtifact<ArtifactFilePrefixTag> targetFilePrefixNode;
+static const TargetFileArtifact<ArtifactLinkerFilePrefixTag>
+ targetLinkerFilePrefixNode;
+static const TargetFileArtifact<ArtifactFileSuffixTag> targetFileSuffixNode;
+static const TargetFileArtifact<ArtifactLinkerFileSuffixTag>
+ targetLinkerFileSuffixNode;
+
static const struct ShellPathNode : public cmGeneratorExpressionNode
{
ShellPathNode() {} // NOLINT(modernize-use-equals-default)
@@ -2145,6 +2474,13 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "TARGET_LINKER_FILE", &targetLinkerNodeGroup.File },
{ "TARGET_SONAME_FILE", &targetSoNameNodeGroup.File },
{ "TARGET_PDB_FILE", &targetPdbNodeGroup.File },
+ { "TARGET_FILE_BASE_NAME", &targetFileBaseNameNode },
+ { "TARGET_LINKER_FILE_BASE_NAME", &targetLinkerFileBaseNameNode },
+ { "TARGET_PDB_FILE_BASE_NAME", &targetPdbFileBaseNameNode },
+ { "TARGET_FILE_PREFIX", &targetFilePrefixNode },
+ { "TARGET_LINKER_FILE_PREFIX", &targetLinkerFilePrefixNode },
+ { "TARGET_FILE_SUFFIX", &targetFileSuffixNode },
+ { "TARGET_LINKER_FILE_SUFFIX", &targetLinkerFileSuffixNode },
{ "TARGET_FILE_NAME", &targetNodeGroup.FileName },
{ "TARGET_LINKER_FILE_NAME", &targetLinkerNodeGroup.FileName },
{ "TARGET_SONAME_FILE_NAME", &targetSoNameNodeGroup.FileName },
@@ -2158,6 +2494,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "STREQUAL", &strEqualNode },
{ "EQUAL", &equalNode },
{ "IN_LIST", &inListNode },
+ { "FILTER", &filterNode },
+ { "REMOVE_DUPLICATES", &removeDuplicatesNode },
{ "LOWER_CASE", &lowerCaseNode },
{ "UPPER_CASE", &upperCaseNode },
{ "MAKE_C_IDENTIFIER", &makeCIdentifierNode },
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 5916fcc..3fb95bf 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -262,7 +262,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
this->DLLPlatform =
!this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
- this->PolicyMap = t->PolicyMap;
+ this->PolicyMap = t->GetPolicyMap();
}
cmGeneratorTarget::~cmGeneratorTarget()
@@ -464,6 +464,134 @@ std::string cmGeneratorTarget::GetOutputName(
return i->second;
}
+std::string cmGeneratorTarget::GetFilePrefix(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ if (this->IsImported()) {
+ const char* prefix = this->GetFilePrefixInternal(artifact);
+
+ return prefix ? prefix : std::string();
+ }
+
+ std::string prefix, suffix, base;
+ this->GetFullNameInternal(config, artifact, prefix, base, suffix);
+ return prefix;
+}
+std::string cmGeneratorTarget::GetFileSuffix(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ if (this->IsImported()) {
+ const char* suffix = this->GetFileSuffixInternal(artifact);
+
+ return suffix ? suffix : std::string();
+ }
+
+ std::string prefix, suffix, base;
+ this->GetFullNameInternal(config, artifact, prefix, base, suffix);
+ return suffix;
+}
+
+const char* cmGeneratorTarget::GetFilePrefixInternal(
+ cmStateEnums::ArtifactType artifact, const std::string& language) const
+{
+ // no prefix for non-main target types.
+ if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ return nullptr;
+ }
+
+ const bool isImportedLibraryArtifact =
+ (artifact == cmStateEnums::ImportLibraryArtifact);
+
+ // Return an empty prefix for the import library if this platform
+ // does not support import libraries.
+ if (isImportedLibraryArtifact &&
+ !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+ return nullptr;
+ }
+
+ // The implib option is only allowed for shared libraries, module
+ // libraries, and executables.
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ artifact = cmStateEnums::RuntimeBinaryArtifact;
+ }
+
+ // Compute prefix value.
+ const char* targetPrefix =
+ (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX")
+ : this->GetProperty("PREFIX"));
+
+ if (!targetPrefix) {
+ const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact);
+ if (!language.empty() && prefixVar && *prefixVar) {
+ std::string langPrefix = prefixVar + std::string("_") + language;
+ targetPrefix = this->Makefile->GetDefinition(langPrefix);
+ }
+
+ // if there is no prefix on the target nor specific language
+ // use the cmake definition.
+ if (!targetPrefix && prefixVar) {
+ targetPrefix = this->Makefile->GetDefinition(prefixVar);
+ }
+ }
+
+ return targetPrefix;
+}
+const char* cmGeneratorTarget::GetFileSuffixInternal(
+ cmStateEnums::ArtifactType artifact, const std::string& language) const
+{
+ // no suffix for non-main target types.
+ if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ return nullptr;
+ }
+
+ const bool isImportedLibraryArtifact =
+ (artifact == cmStateEnums::ImportLibraryArtifact);
+
+ // Return an empty suffix for the import library if this platform
+ // does not support import libraries.
+ if (isImportedLibraryArtifact &&
+ !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+ return nullptr;
+ }
+
+ // The implib option is only allowed for shared libraries, module
+ // libraries, and executables.
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ artifact = cmStateEnums::RuntimeBinaryArtifact;
+ }
+
+ // Compute suffix value.
+ const char* targetSuffix =
+ (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX")
+ : this->GetProperty("SUFFIX"));
+
+ if (!targetSuffix) {
+ const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact);
+ if (!language.empty() && suffixVar && *suffixVar) {
+ std::string langSuffix = suffixVar + std::string("_") + language;
+ targetSuffix = this->Makefile->GetDefinition(langSuffix);
+ }
+
+ // if there is no suffix on the target nor specific language
+ // use the cmake definition.
+ if (!targetSuffix && suffixVar) {
+ targetSuffix = this->Makefile->GetDefinition(suffixVar);
+ }
+ }
+
+ return targetSuffix;
+}
+
void cmGeneratorTarget::ClearSourcesCache()
{
this->KindedSourcesMap.clear();
@@ -3788,6 +3916,11 @@ void cmGeneratorTarget::GetFullNameInternal(
return;
}
+ // retrieve prefix and suffix
+ std::string ll = this->GetLinkerLanguage(config);
+ const char* targetPrefix = this->GetFilePrefixInternal(artifact, ll);
+ const char* targetSuffix = this->GetFileSuffixInternal(artifact, ll);
+
// The implib option is only allowed for shared libraries, module
// libraries, and executables.
if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
@@ -3797,12 +3930,6 @@ void cmGeneratorTarget::GetFullNameInternal(
}
// Compute the full name for main target types.
- const char* targetPrefix =
- (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX")
- : this->GetProperty("PREFIX"));
- const char* targetSuffix =
- (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX")
- : this->GetProperty("SUFFIX"));
const char* configPostfix = nullptr;
if (!config.empty()) {
std::string configProp = cmSystemTools::UpperCase(config);
@@ -3814,30 +3941,6 @@ void cmGeneratorTarget::GetFullNameInternal(
configPostfix = nullptr;
}
}
- const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact);
- const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact);
-
- // Check for language-specific default prefix and suffix.
- std::string ll = this->GetLinkerLanguage(config);
- if (!ll.empty()) {
- if (!targetSuffix && suffixVar && *suffixVar) {
- std::string langSuff = suffixVar + std::string("_") + ll;
- targetSuffix = this->Makefile->GetDefinition(langSuff);
- }
- if (!targetPrefix && prefixVar && *prefixVar) {
- std::string langPrefix = prefixVar + std::string("_") + ll;
- targetPrefix = this->Makefile->GetDefinition(langPrefix);
- }
- }
-
- // if there is no prefix on the target use the cmake definition
- if (!targetPrefix && prefixVar) {
- targetPrefix = this->Makefile->GetSafeDefinition(prefixVar).c_str();
- }
- // if there is no suffix on the target use the cmake definition
- if (!targetSuffix && suffixVar) {
- targetSuffix = this->Makefile->GetSafeDefinition(suffixVar).c_str();
- }
// frameworks have directory prefix but no suffix
std::string fw_prefix;
@@ -3884,6 +3987,31 @@ std::string cmGeneratorTarget::GetLinkerLanguage(
return this->GetLinkClosure(config)->LinkerLanguage;
}
+std::string cmGeneratorTarget::GetPDBOutputName(
+ const std::string& config) const
+{
+ std::string base =
+ this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
+
+ std::vector<std::string> props;
+ std::string configUpper = cmSystemTools::UpperCase(config);
+ if (!configUpper.empty()) {
+ // PDB_NAME_<CONFIG>
+ props.push_back("PDB_NAME_" + configUpper);
+ }
+
+ // PDB_NAME
+ props.emplace_back("PDB_NAME");
+
+ for (std::string const& p : props) {
+ if (const char* outName = this->GetProperty(p)) {
+ base = outName;
+ break;
+ }
+ }
+ return base;
+}
+
std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
{
std::string prefix;
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index bc966e1..81f5255 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -69,9 +69,9 @@ public:
std::string GetExportName() const;
std::vector<std::string> GetPropertyKeys() const;
- ///! Might return a nullptr if the property is not set or invalid
+ //! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
- ///! Always returns a valid pointer
+ //! Always returns a valid pointer
const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
void GetSourceFiles(std::vector<cmSourceFile*>& files,
@@ -503,6 +503,9 @@ public:
OutputInfo const* GetOutputInfo(const std::string& config) const;
+ // Get the target PDB base name.
+ std::string GetPDBOutputName(const std::string& config) const;
+
/** Get the name of the pdb file for the target. */
std::string GetPDBName(const std::string& config = "") const;
@@ -531,6 +534,15 @@ public:
std::string GetOutputName(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
+ /** Get target file prefix */
+ std::string GetFilePrefix(const std::string& config,
+ cmStateEnums::ArtifactType artifact =
+ cmStateEnums::RuntimeBinaryArtifact) const;
+ /** Get target file prefix */
+ std::string GetFileSuffix(const std::string& config,
+ cmStateEnums::ArtifactType artifact =
+ cmStateEnums::RuntimeBinaryArtifact) const;
+
/** Clears cached meta data for local and external source files.
* The meta data will be recomputed on demand.
*/
@@ -602,7 +614,7 @@ public:
pdb output directory is given. */
std::string GetPDBDirectory(const std::string& config) const;
- ///! Return the preferred linker language for this target
+ //! Return the preferred linker language for this target
std::string GetLinkerLanguage(const std::string& config) const;
/** Does this target have a GNU implib to convert to MS format? */
@@ -725,6 +737,11 @@ private:
mutable std::map<std::string, bool> DebugCompatiblePropertiesDone;
+ const char* GetFilePrefixInternal(cmStateEnums::ArtifactType artifact,
+ const std::string& language = "") const;
+ const char* GetFileSuffixInternal(cmStateEnums::ArtifactType artifact,
+ const std::string& language = "") const;
+
std::string GetFullNameInternal(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
void GetFullNameInternal(const std::string& config,
diff --git a/Source/cmGhsMultiGpj.cxx b/Source/cmGhsMultiGpj.cxx
index 8b69b51..da27971 100644
--- a/Source/cmGhsMultiGpj.cxx
+++ b/Source/cmGhsMultiGpj.cxx
@@ -9,7 +9,8 @@ static const char* GHS_TAG[] = { "[INTEGRITY Application]",
"[Project]",
"[Program]",
"[Reference]",
- "[Subproject]" };
+ "[Subproject]",
+ "[Custom Target]" };
const char* GhsMultiGpj::GetGpjTag(Types gpjType)
{
@@ -21,6 +22,7 @@ const char* GhsMultiGpj::GetGpjTag(Types gpjType)
case PROGRAM:
case REFERENCE:
case SUBPROJECT:
+ case CUSTOM_TARGET:
tag = GHS_TAG[gpjType];
break;
default:
diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h
index 420eab1..e588150 100644
--- a/Source/cmGhsMultiGpj.h
+++ b/Source/cmGhsMultiGpj.h
@@ -16,7 +16,8 @@ public:
PROJECT,
PROGRAM,
REFERENCE,
- SUBPROJECT
+ SUBPROJECT,
+ CUSTOM_TARGET
};
static void WriteGpjTag(Types gpjType, std::ostream& fout);
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 668bcbd..b80da72 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -3,7 +3,7 @@
#include "cmGhsMultiTargetGenerator.h"
#include "cmCustomCommand.h"
-#include "cmCustomCommandLines.h"
+#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGhsMultiGenerator.h"
@@ -11,17 +11,17 @@
#include "cmLocalGenerator.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
+#include "cmOutputConverter.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
#include "cmSourceGroup.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmTargetDepend.h"
#include <algorithm>
-#include <assert.h>
#include <ostream>
#include <set>
#include <utility>
@@ -32,6 +32,11 @@ cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target)
static_cast<cmLocalGhsMultiGenerator*>(target->GetLocalGenerator()))
, Makefile(target->Target->GetMakefile())
, Name(target->GetName())
+#ifdef _WIN32
+ , CmdWindowsShell(true)
+#else
+ , CmdWindowsShell(false)
+#endif
{
// Store the configuration name that is being used
if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
@@ -85,10 +90,19 @@ void cmGhsMultiTargetGenerator::Generate()
return;
}
case cmStateEnums::UTILITY: {
- std::string msg = "add_custom_target(<name> ...) not supported: ";
- msg += this->Name;
- cmSystemTools::Message(msg);
- return;
+ this->TargetNameReal = this->GeneratorTarget->GetName();
+ this->TagType = GhsMultiGpj::CUSTOM_TARGET;
+ break;
+ }
+ case cmStateEnums::GLOBAL_TARGET: {
+ this->TargetNameReal = this->GeneratorTarget->GetName();
+ if (this->TargetNameReal ==
+ this->GetGlobalGenerator()->GetInstallTargetName()) {
+ this->TagType = GhsMultiGpj::CUSTOM_TARGET;
+ } else {
+ return;
+ }
+ break;
}
default:
return;
@@ -105,29 +119,29 @@ void cmGhsMultiTargetGenerator::Generate()
void cmGhsMultiTargetGenerator::GenerateTarget()
{
- // Open the filestream in copy-if-different mode.
- std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory();
- fname += "/";
- fname += this->Name;
- fname += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
- cmGeneratedFileStream fout(fname);
+ // Open the target file in copy-if-different mode.
+ std::string fproj = this->LocalGenerator->GetCurrentBinaryDirectory();
+ fproj += "/";
+ fproj += this->Name;
+ fproj += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
+ cmGeneratedFileStream fout(fproj);
fout.SetCopyIfDifferent(true);
this->GetGlobalGenerator()->WriteFileHeader(fout);
GhsMultiGpj::WriteGpjTag(this->TagType, fout);
- const std::string language(
- this->GeneratorTarget->GetLinkerLanguage(this->ConfigName));
-
- this->WriteTargetSpecifics(fout, this->ConfigName);
- this->SetCompilerFlags(this->ConfigName, language);
- this->WriteCompilerFlags(fout, this->ConfigName, language);
- this->WriteCompilerDefinitions(fout, this->ConfigName, language);
- this->WriteIncludes(fout, this->ConfigName, language);
- this->WriteTargetLinkLine(fout, this->ConfigName);
- this->WriteCustomCommands(fout);
+ if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
+ const std::string language(
+ this->GeneratorTarget->GetLinkerLanguage(this->ConfigName));
+ this->WriteTargetSpecifics(fout, this->ConfigName);
+ this->SetCompilerFlags(this->ConfigName, language);
+ this->WriteCompilerFlags(fout, this->ConfigName, language);
+ this->WriteCompilerDefinitions(fout, this->ConfigName, language);
+ this->WriteIncludes(fout, this->ConfigName, language);
+ this->WriteTargetLinkLine(fout, this->ConfigName);
+ this->WriteBuildEvents(fout);
+ }
this->WriteSources(fout);
- this->WriteReferences(fout);
fout.Close();
}
@@ -304,47 +318,145 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout,
}
}
-void cmGhsMultiTargetGenerator::WriteCustomCommands(std::ostream& fout)
+void cmGhsMultiTargetGenerator::WriteBuildEvents(std::ostream& fout)
{
- WriteCustomCommandsHelper(fout, this->GeneratorTarget->GetPreBuildCommands(),
- cmTarget::PRE_BUILD);
- WriteCustomCommandsHelper(
- fout, this->GeneratorTarget->GetPostBuildCommands(), cmTarget::POST_BUILD);
+ this->WriteBuildEventsHelper(
+ fout, this->GeneratorTarget->GetPreBuildCommands(),
+ std::string("prebuild"), std::string("preexecShell"));
+
+ if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
+ this->WriteBuildEventsHelper(
+ fout, this->GeneratorTarget->GetPreLinkCommands(),
+ std::string("prelink"), std::string("preexecShell"));
+ }
+
+ this->WriteBuildEventsHelper(
+ fout, this->GeneratorTarget->GetPostBuildCommands(),
+ std::string("postbuild"), std::string("postexecShell"));
+}
+
+void cmGhsMultiTargetGenerator::WriteBuildEventsHelper(
+ std::ostream& fout, const std::vector<cmCustomCommand>& ccv,
+ std::string const& name, std::string const& cmd)
+{
+ int cmdcount = 0;
+
+ for (cmCustomCommand const& cc : ccv) {
+ cmCustomCommandGenerator ccg(cc, this->ConfigName, this->LocalGenerator);
+ // Open the filestream for this custom command
+ std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory();
+ fname +=
+ "/" + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ fname += "/" + this->Name + "_" + name;
+ fname += std::to_string(cmdcount++);
+ fname += this->CmdWindowsShell ? ".bat" : ".sh";
+ cmGeneratedFileStream f(fname);
+ f.SetCopyIfDifferent(true);
+ this->WriteCustomCommandsHelper(f, ccg);
+ f.Close();
+ if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
+ fout << " :" << cmd << "=\"" << fname << "\"" << std::endl;
+ } else {
+ fout << fname << std::endl;
+ fout << " :outputName=\"" << fname << ".rule\"" << std::endl;
+ }
+ for (auto& byp : ccg.GetByproducts()) {
+ fout << " :extraOutputFile=\"" << byp << "\"" << std::endl;
+ }
+ }
}
void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
- std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet,
- cmTarget::CustomCommandType const commandType)
+ std::ostream& fout, cmCustomCommandGenerator const& ccg)
{
- for (cmCustomCommand const& customCommand : commandsSet) {
- cmCustomCommandLines const& commandLines = customCommand.GetCommandLines();
- for (cmCustomCommandLine const& command : commandLines) {
- switch (commandType) {
- case cmTarget::PRE_BUILD:
- fout << " :preexecShellSafe=";
- break;
- case cmTarget::POST_BUILD:
- fout << " :postexecShellSafe=";
- break;
- default:
- assert("Only pre and post are supported");
+ std::vector<std::string> cmdLines;
+
+ // if the command specified a working directory use it.
+ std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory();
+ std::string currentBinDir = dir;
+ std::string workingDir = ccg.GetWorkingDirectory();
+ if (!workingDir.empty()) {
+ dir = workingDir;
+ }
+
+ // Line to check for error between commands.
+#ifdef _WIN32
+ std::string check_error = "if %errorlevel% neq 0 exit /b %errorlevel%";
+#else
+ std::string check_error = "if [[ $? -ne 0 ]]; then exit 1; fi";
+#endif
+
+#ifdef _WIN32
+ cmdLines.push_back("@echo off");
+#endif
+ // Echo the custom command's comment text.
+ const char* comment = ccg.GetComment();
+ if (comment && *comment) {
+ std::string echocmd = "echo ";
+ echocmd += comment;
+ cmdLines.push_back(std::move(echocmd));
+ }
+
+ // Switch to working directory
+ std::string cdCmd;
+#ifdef _WIN32
+ std::string cdStr = "cd /D ";
+#else
+ std::string cdStr = "cd ";
+#endif
+ cdCmd = cdStr +
+ this->LocalGenerator->ConvertToOutputFormat(dir, cmOutputConverter::SHELL);
+ cmdLines.push_back(std::move(cdCmd));
+
+ for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
+ // Build the command line in a single string.
+ std::string cmd = ccg.GetCommand(c);
+ if (!cmd.empty()) {
+ // Use "call " before any invocations of .bat or .cmd files
+ // invoked as custom commands in the WindowsShell.
+ //
+ bool useCall = false;
+
+ if (this->CmdWindowsShell) {
+ std::string suffix;
+ if (cmd.size() > 4) {
+ suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size() - 4));
+ if (suffix == ".bat" || suffix == ".cmd") {
+ useCall = true;
+ }
+ }
}
- bool firstIteration = true;
- for (std::string const& commandLine : command) {
- std::string subCommandE =
- this->LocalGenerator->EscapeForShell(commandLine, true);
- fout << (firstIteration ? "'" : " ");
- // Need to double escape backslashes
- cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
- fout << subCommandE;
- firstIteration = false;
+ cmSystemTools::ReplaceString(cmd, "/./", "/");
+ // Convert the command to a relative path only if the current
+ // working directory will be the start-output directory.
+ bool had_slash = cmd.find('/') != std::string::npos;
+ if (workingDir.empty()) {
+ cmd =
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, cmd);
}
- if (!command.empty()) {
- fout << "'" << std::endl;
+ bool has_slash = cmd.find('/') != std::string::npos;
+ if (had_slash && !has_slash) {
+ // This command was specified as a path to a file in the
+ // current directory. Add a leading "./" so it can run
+ // without the current directory being in the search path.
+ cmd = "./" + cmd;
}
+ cmd = this->LocalGenerator->ConvertToOutputFormat(
+ cmd, cmOutputConverter::SHELL);
+ if (useCall) {
+ cmd = "call " + cmd;
+ }
+ ccg.AppendArguments(c, cmd);
+ cmdLines.push_back(std::move(cmd));
}
}
+
+ // push back the custom commands
+ for (auto const& c : cmdLines) {
+ fout << c << std::endl;
+ fout << check_error << std::endl;
+ }
}
void cmGhsMultiTargetGenerator::WriteSourceProperty(
@@ -385,7 +497,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
/* list of known groups and the order they are displayed in a project file */
const std::vector<std::string> standardGroups = {
- "Header Files", "Source Files", "CMake Rules",
+ "CMake Rules", "Header Files", "Source Files",
"Object Files", "Object Libraries", "Resources"
};
@@ -403,6 +515,14 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
groupFilesList[i] = *n;
i += 1;
groupNames.erase(gn);
+ } else if (this->TagType == GhsMultiGpj::CUSTOM_TARGET &&
+ gn == "CMake Rules") {
+ /* make sure that rules folder always exists in case of custom targets
+ * that have no custom commands except for pre or post build events.
+ */
+ groupFilesList.resize(groupFilesList.size() + 1);
+ groupFilesList[i] = gn;
+ i += 1;
}
}
@@ -433,7 +553,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
/* write files into the proper project file
* -- groups go into main project file
- * unless FOLDER property or variable is set.
+ * unless NO_SOURCE_GROUP_FILE property or variable is set.
*/
for (auto& sg : groupFilesList) {
std::ostream* fout;
@@ -472,33 +592,98 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
} else {
*fout << "{comment} " << sg << std::endl;
}
+ } else if (sg.empty()) {
+ *fout << "{comment} Others" << std::endl;
}
- /* output rule for each source file */
- for (const cmSourceFile* si : groupFiles[sg]) {
-
- // Convert filename to native system
- // WORKAROUND: GHS MULTI 6.1.4 and 6.1.6 are known to need backslash on
- // windows when opening some files from the search window.
- std::string fname(si->GetFullPath());
- cmSystemTools::ConvertToOutputSlashes(fname);
- *fout << fname << std::endl;
-
- if ("ld" != si->GetExtension() && "int" != si->GetExtension() &&
- "bsp" != si->GetExtension()) {
- WriteObjectLangOverride(*fout, si);
+ if (sg != "CMake Rules") {
+ /* output rule for each source file */
+ for (const cmSourceFile* si : groupFiles[sg]) {
+ bool compile = true;
+ // Convert filename to native system
+ // WORKAROUND: GHS MULTI 6.1.4 and 6.1.6 are known to need backslash on
+ // windows when opening some files from the search window.
+ std::string fname(si->GetFullPath());
+ cmSystemTools::ConvertToOutputSlashes(fname);
+
+ /* For custom targets list any associated sources,
+ * comment out source code to prevent it from being
+ * compiled when processing this target.
+ * Otherwise, comment out any custom command (main) dependencies that
+ * are listed as source files to prevent them from being considered
+ * part of the build.
+ */
+ std::string comment;
+ if ((this->TagType == GhsMultiGpj::CUSTOM_TARGET &&
+ !si->GetLanguage().empty()) ||
+ si->GetCustomCommand()) {
+ comment = "{comment} ";
+ compile = false;
+ }
+
+ *fout << comment << fname << std::endl;
+ if (compile) {
+ if ("ld" != si->GetExtension() && "int" != si->GetExtension() &&
+ "bsp" != si->GetExtension()) {
+ WriteObjectLangOverride(*fout, si);
+ }
+
+ this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I");
+ this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D");
+ this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", "");
+
+ /* to avoid clutter in the GUI only print out the objectName if it
+ * has been renamed */
+ std::string objectName = this->GeneratorTarget->GetObjectName(si);
+ if (!objectName.empty() &&
+ this->GeneratorTarget->HasExplicitObjectName(si)) {
+ *fout << " -o " << objectName << std::endl;
+ }
+ }
}
-
- this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I");
- this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D");
- this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", "");
-
- /* to avoid clutter in the gui only print out the objectName if it has
- * been renamed */
- std::string objectName = this->GeneratorTarget->GetObjectName(si);
- if (!objectName.empty() &&
- this->GeneratorTarget->HasExplicitObjectName(si)) {
- *fout << " -o " << objectName << std::endl;
+ } else {
+ std::vector<cmSourceFile const*> customCommands;
+ if (ComputeCustomCommandOrder(customCommands)) {
+ std::string message = "The custom commands for target [" +
+ this->GeneratorTarget->GetName() + "] had a cycle.\n";
+ cmSystemTools::Error(message);
+ } else {
+ /* Custom targets do not have a dependency on SOURCES files.
+ * Therefore the dependency list may include SOURCES files after the
+ * custom target. Because nothing can depend on the custom target just
+ * move it to the last item.
+ */
+ for (auto sf = customCommands.begin(); sf != customCommands.end();
+ ++sf) {
+ if (((*sf)->GetLocation()).GetName() == this->Name + ".rule") {
+ std::rotate(sf, sf + 1, customCommands.end());
+ break;
+ }
+ }
+ int cmdcount = 0;
+ for (auto& sf : customCommands) {
+ const cmCustomCommand* cc = sf->GetCustomCommand();
+ cmCustomCommandGenerator ccg(*cc, this->ConfigName,
+ this->LocalGenerator);
+
+ // Open the filestream for this custom command
+ std::string fname =
+ this->LocalGenerator->GetCurrentBinaryDirectory();
+ fname += "/" +
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ fname += "/" + this->Name + "_cc";
+ fname += std::to_string(cmdcount++) + "_";
+ fname += (sf->GetLocation()).GetName();
+ fname += this->CmdWindowsShell ? ".bat" : ".sh";
+ cmGeneratedFileStream f(fname);
+ f.SetCopyIfDifferent(true);
+ this->WriteCustomCommandsHelper(f, ccg);
+ f.Close();
+ this->WriteCustomCommandLine(*fout, fname, ccg);
+ }
+ }
+ if (this->TagType == GhsMultiGpj::CUSTOM_TARGET) {
+ this->WriteBuildEvents(*fout);
}
}
}
@@ -508,6 +693,33 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
}
}
+void cmGhsMultiTargetGenerator::WriteCustomCommandLine(
+ std::ostream& fout, std::string& fname, cmCustomCommandGenerator const& ccg)
+{
+ /* NOTE: Customization Files are not well documented. Testing showed
+ * that ":outputName=file" can only be used once per script. The
+ * script will only run if ":outputName=file" is missing or just run
+ * once if ":outputName=file" is not specified. If there are
+ * multiple outputs then the script needs to be listed multiple times
+ * for each output. Otherwise it won't rerun the script if one of
+ * the outputs is manually deleted.
+ */
+ bool specifyExtra = true;
+ for (auto& out : ccg.GetOutputs()) {
+ fout << fname << std::endl;
+ fout << " :outputName=\"" << out << "\"" << std::endl;
+ if (specifyExtra) {
+ for (auto& byp : ccg.GetByproducts()) {
+ fout << " :extraOutputFile=\"" << byp << "\"" << std::endl;
+ }
+ for (auto& dep : ccg.GetDepends()) {
+ fout << " :depends=\"" << dep << "\"" << std::endl;
+ }
+ specifyExtra = false;
+ }
+ }
+}
+
void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
std::ostream& fout, const cmSourceFile* sourceFile)
{
@@ -521,35 +733,6 @@ void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
}
}
-void cmGhsMultiTargetGenerator::WriteReferences(std::ostream& fout)
-{
- // This only applies to INTEGRITY Applications
- if (this->TagType != GhsMultiGpj::INTERGRITY_APPLICATION) {
- return;
- }
-
- // Get the targets that this one depends upon
- cmTargetDependSet unordered =
- this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget);
- cmGlobalGhsMultiGenerator::OrderedTargetDependSet ordered(unordered,
- this->Name);
- for (auto& t : ordered) {
- std::string tname = t->GetName();
- std::string tpath = t->LocalGenerator->GetCurrentBinaryDirectory();
- std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
- std::string outpath =
- this->LocalGenerator->MaybeConvertToRelativePath(rootpath, tpath) + "/" +
- tname + "REF" + cmGlobalGhsMultiGenerator::FILE_EXTENSION;
-
- fout << outpath;
- fout << " ";
- GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fout);
-
- // Tell the global generator that a refernce project needs to be created
- t->Target->SetProperty("GHS_REFERENCE_PROJECT", "ON");
- }
-}
-
bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()
{
const char* p = this->GeneratorTarget->GetProperty("ghs_integrity_app");
@@ -566,3 +749,51 @@ bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()
}
return false;
}
+
+bool cmGhsMultiTargetGenerator::ComputeCustomCommandOrder(
+ std::vector<cmSourceFile const*>& order)
+{
+ std::set<cmSourceFile const*> temp;
+ std::set<cmSourceFile const*> perm;
+
+ // Collect all custom commands for this target
+ std::vector<cmSourceFile const*> customCommands;
+ this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
+
+ for (cmSourceFile const* si : customCommands) {
+ bool r = VisitCustomCommand(temp, perm, order, si);
+ if (r) {
+ return r;
+ }
+ }
+ return false;
+}
+
+bool cmGhsMultiTargetGenerator::VisitCustomCommand(
+ std::set<cmSourceFile const*>& temp, std::set<cmSourceFile const*>& perm,
+ std::vector<cmSourceFile const*>& order, cmSourceFile const* si)
+{
+ /* check if permanent mark is set*/
+ if (perm.find(si) == perm.end()) {
+ /* set temporary mark; check if revisit*/
+ if (temp.insert(si).second) {
+ for (auto& di : si->GetCustomCommand()->GetDepends()) {
+ cmSourceFile const* sf = this->GeneratorTarget->GetLocalGenerator()
+ ->GetMakefile()
+ ->GetSourceFileWithOutput(di);
+ /* if sf exists then visit */
+ if (sf && this->VisitCustomCommand(temp, perm, order, sf)) {
+ return true;
+ }
+ }
+ /* mark as complete; insert into beginning of list*/
+ perm.insert(si);
+ order.push_back(si);
+ return false;
+ }
+ /* revisiting item - not a DAG */
+ return true;
+ }
+ /* already complete */
+ return false;
+}
diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h
index a4e23d9..a131567 100644
--- a/Source/cmGhsMultiTargetGenerator.h
+++ b/Source/cmGhsMultiTargetGenerator.h
@@ -5,14 +5,14 @@
#include "cmGhsMultiGpj.h"
-#include "cmTarget.h"
-
#include <iosfwd>
#include <map>
+#include <set>
#include <string>
#include <vector>
class cmCustomCommand;
+class cmCustomCommandGenerator;
class cmGeneratorTarget;
class cmGlobalGhsMultiGenerator;
class cmLocalGhsMultiGenerator;
@@ -49,15 +49,23 @@ private:
void WriteIncludes(std::ostream& fout, const std::string& config,
const std::string& language);
void WriteTargetLinkLine(std::ostream& fout, std::string const& config);
- void WriteCustomCommands(std::ostream& fout);
- void WriteCustomCommandsHelper(
- std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet,
- cmTarget::CustomCommandType commandType);
+ void WriteBuildEvents(std::ostream& fout);
+ void WriteBuildEventsHelper(std::ostream& fout,
+ const std::vector<cmCustomCommand>& ccv,
+ std::string const& name, std::string const& cmd);
+ void WriteCustomCommandsHelper(std::ostream& fout,
+ cmCustomCommandGenerator const& ccg);
+ void WriteCustomCommandLine(std::ostream& fout, std::string& fname,
+ cmCustomCommandGenerator const& ccg);
+ bool ComputeCustomCommandOrder(std::vector<cmSourceFile const*>& order);
+ bool VisitCustomCommand(std::set<cmSourceFile const*>& temp,
+ std::set<cmSourceFile const*>& perm,
+ std::vector<cmSourceFile const*>& order,
+ cmSourceFile const* sf);
void WriteSources(std::ostream& fout_proj);
void WriteSourceProperty(std::ostream& fout, const cmSourceFile* sf,
std::string const& propName,
std::string const& propFlag);
- void WriteReferences(std::ostream& fout);
static void WriteObjectLangOverride(std::ostream& fout,
const cmSourceFile* sourceFile);
@@ -71,7 +79,8 @@ private:
std::string TargetNameReal;
GhsMultiGpj::Types TagType;
std::string const Name;
- std::string ConfigName; /* CMAKE_BUILD_TYPE */
+ std::string ConfigName; /* CMAKE_BUILD_TYPE */
+ bool const CmdWindowsShell; /* custom commands run in cmd.exe or /bin/sh */
};
#endif // ! cmGhsMultiTargetGenerator_h
diff --git a/Source/cmGlobVerificationManager.h b/Source/cmGlobVerificationManager.h
index f7146be..48606d3 100644
--- a/Source/cmGlobVerificationManager.h
+++ b/Source/cmGlobVerificationManager.h
@@ -22,11 +22,11 @@
class cmGlobVerificationManager
{
protected:
- ///! Save verification script for given makefile.
- ///! Saves to output <path>/<CMakeFilesDirectory>/VerifyGlobs.cmake
+ //! Save verification script for given makefile.
+ //! Saves to output <path>/<CMakeFilesDirectory>/VerifyGlobs.cmake
bool SaveVerificationScript(const std::string& path);
- ///! Add an entry into the glob cache
+ //! Add an entry into the glob cache
void AddCacheEntry(bool recurse, bool listDirectories, bool followSymlinks,
const std::string& relative,
const std::string& expression,
@@ -34,13 +34,13 @@ protected:
const std::string& variable,
const cmListFileBacktrace& bt);
- ///! Clear the glob cache for state reset.
+ //! Clear the glob cache for state reset.
void Reset();
- ///! Check targets should be written in generated build system.
+ //! Check targets should be written in generated build system.
bool DoWriteVerifyTarget() const;
- ///! Get the paths to the generated script and stamp files
+ //! Get the paths to the generated script and stamp files
std::string const& GetVerifyScript() const { return this->VerifyScript; }
std::string const& GetVerifyStamp() const { return this->VerifyStamp; }
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 281d371..51d681d 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -34,7 +34,7 @@ void cmGlobalBorlandMakefileGenerator::EnableLanguage(
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(
cmMakefile* mf)
{
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index 02d0d5f..ee7de70 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -22,7 +22,7 @@ public:
cmGlobalBorlandMakefileGenerator>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
std::string GetName() const override
{
return cmGlobalBorlandMakefileGenerator::GetActualName();
@@ -32,7 +32,7 @@ public:
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
+ //! Create a local generator appropriate to this Global Generator
cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/**
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 00781c3..8223dd1 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -272,8 +272,7 @@ void cmGlobalGenerator::AddBuildExportExportSet(
bool cmGlobalGenerator::GenerateImportFile(const std::string& file)
{
- std::map<std::string, cmExportBuildFileGenerator*>::iterator it =
- this->BuildExportSets.find(file);
+ auto const it = this->BuildExportSets.find(file);
if (it != this->BuildExportSets.end()) {
bool result = it->second->GenerateImportFile();
@@ -299,10 +298,7 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const
{
bool failed = false;
for (cmLocalGenerator* localGen : this->LocalGenerators) {
- const std::vector<cmGeneratorTarget*>& targets =
- localGen->GetGeneratorTargets();
-
- for (cmGeneratorTarget* target : targets) {
+ for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) {
if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
target->GetType() == cmStateEnums::TargetType::UTILITY ||
@@ -338,8 +334,7 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const
bool cmGlobalGenerator::IsExportedTargetsFile(
const std::string& filename) const
{
- const std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it =
- this->BuildExportSets.find(filename);
+ auto const it = this->BuildExportSets.find(filename);
if (it == this->BuildExportSets.end()) {
return false;
}
@@ -900,7 +895,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
/* clang-format off */
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0025) << "\n"
"Converting " << lang <<
- " compiler id \"AppleClang\" to \"Clang\" for compatibility."
+ R"( compiler id "AppleClang" to "Clang" for compatibility.)"
;
/* clang-format on */
mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
@@ -930,7 +925,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
/* clang-format off */
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0047) << "\n"
"Converting " << lang <<
- " compiler id \"QCC\" to \"GNU\" for compatibility."
+ R"( compiler id "QCC" to "GNU" for compatibility.)"
;
/* clang-format on */
mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
@@ -966,7 +961,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
/* clang-format off */
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0089) << "\n"
"Converting " << lang <<
- " compiler id \"XLClang\" to \"XL\" for compatibility."
+ R"( compiler id "XLClang" to "XL" for compatibility.)"
;
/* clang-format on */
mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
@@ -993,9 +988,7 @@ std::string cmGlobalGenerator::GetLanguageOutputExtension(
{
const std::string& lang = source.GetLanguage();
if (!lang.empty()) {
- std::map<std::string, std::string>::const_iterator it =
- this->LanguageToOutputExtension.find(lang);
-
+ auto const it = this->LanguageToOutputExtension.find(lang);
if (it != this->LanguageToOutputExtension.end()) {
return it->second;
}
@@ -1020,8 +1013,7 @@ std::string cmGlobalGenerator::GetLanguageFromExtension(const char* ext) const
if (ext && *ext == '.') {
++ext;
}
- std::map<std::string, std::string>::const_iterator it =
- this->ExtensionToLanguage.find(ext);
+ auto const it = this->ExtensionToLanguage.find(ext);
if (it != this->ExtensionToLanguage.end()) {
return it->second;
}
@@ -1272,7 +1264,7 @@ void cmGlobalGenerator::CreateImportedGenerationObjects(
std::vector<const cmGeneratorTarget*>& exports)
{
this->CreateGenerationObjects(ImportedOnly);
- std::vector<cmMakefile*>::iterator mfit =
+ auto const mfit =
std::find(this->Makefiles.begin(), this->Makefiles.end(), mf);
cmLocalGenerator* lg =
this->LocalGenerators[std::distance(this->Makefiles.begin(), mfit)];
@@ -1287,8 +1279,7 @@ void cmGlobalGenerator::CreateImportedGenerationObjects(
cmExportBuildFileGenerator* cmGlobalGenerator::GetExportedTargetsFile(
const std::string& filename) const
{
- std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it =
- this->BuildExportSets.find(filename);
+ auto const it = this->BuildExportSets.find(filename);
return it == this->BuildExportSets.end() ? nullptr : it->second;
}
@@ -1502,8 +1493,7 @@ bool cmGlobalGenerator::ComputeTargetDepends()
if (!ctd.Compute()) {
return false;
}
- std::vector<cmGeneratorTarget const*> const& targets = ctd.GetTargets();
- for (cmGeneratorTarget const* target : targets) {
+ for (cmGeneratorTarget const* target : ctd.GetTargets()) {
ctd.GetTargetDirectDepends(target, this->TargetDependencies[target]);
}
return true;
@@ -1543,8 +1533,7 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
const cmBacktraceRange noconfig_compile_definitions_bts =
mf->GetCompileDefinitionsBacktraces();
- cmTargets& targets = mf->GetTargets();
- for (auto& target : targets) {
+ for (auto& target : mf->GetTargets()) {
cmTarget* t = &target.second;
if (t->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
@@ -1556,12 +1545,12 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
continue;
}
- cmBacktraceRange::const_iterator btIt =
- noconfig_compile_definitions_bts.begin();
- for (cmStringRange::const_iterator it =
- noconfig_compile_definitions.begin();
- it != noconfig_compile_definitions.end(); ++it, ++btIt) {
- t->InsertCompileDefinition(*it, *btIt);
+ {
+ auto btIt = noconfig_compile_definitions_bts.begin();
+ auto it = noconfig_compile_definitions.begin();
+ for (; it != noconfig_compile_definitions.end(); ++it, ++btIt) {
+ t->InsertCompileDefinition(*it, *btIt);
+ }
}
cmPolicies::PolicyStatus polSt =
@@ -1601,17 +1590,14 @@ void cmGlobalGenerator::CreateGeneratorTargets(
std::map<cmTarget*, cmGeneratorTarget*> const& importedMap)
{
if (targetTypes == AllTargets) {
- cmTargets& targets = mf->GetTargets();
- for (auto& target : targets) {
+ for (auto& target : mf->GetTargets()) {
cmTarget* t = &target.second;
cmGeneratorTarget* gt = new cmGeneratorTarget(t, lg);
lg->AddGeneratorTarget(gt);
}
}
- std::vector<cmTarget*> itgts = mf->GetImportedTargets();
-
- for (cmTarget* t : itgts) {
+ for (cmTarget* t : mf->GetImportedTargets()) {
lg->AddImportedGeneratorTarget(importedMap.find(t)->second);
}
}
@@ -1672,14 +1658,11 @@ void cmGlobalGenerator::CheckTargetProperties()
cmState* state = this->GetCMakeInstance()->GetState();
for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
this->Makefiles[i]->ConfigureFinalPass();
- cmTargets& targets = this->Makefiles[i]->GetTargets();
- for (auto const& target : targets) {
+ for (auto const& target : this->Makefiles[i]->GetTargets()) {
if (target.second.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- const cmTarget::LinkLibraryVectorType& libs =
- target.second.GetOriginalLinkLibraries();
- for (auto const& lib : libs) {
+ for (auto const& lib : target.second.GetOriginalLinkLibraries()) {
if (lib.first.size() > 9 &&
cmSystemTools::IsNOTFOUND(lib.first.c_str())) {
std::string varName = lib.first.substr(0, lib.first.size() - 9);
@@ -2072,8 +2055,7 @@ void cmGlobalGenerator::GetEnabledLanguages(
int cmGlobalGenerator::GetLinkerPreference(const std::string& lang) const
{
- std::map<std::string, int>::const_iterator it =
- this->LanguageToLinkerPreference.find(lang);
+ auto const it = this->LanguageToLinkerPreference.find(lang);
if (it != this->LanguageToLinkerPreference.end()) {
return it->second;
}
@@ -2100,9 +2082,9 @@ void cmGlobalGenerator::FillProjectMap()
cmMakefile* cmGlobalGenerator::FindMakefile(const std::string& start_dir) const
{
- MakefileMap::const_iterator i = this->MakefileSearchIndex.find(start_dir);
- if (i != this->MakefileSearchIndex.end()) {
- return i->second;
+ auto const it = this->MakefileSearchIndex.find(start_dir);
+ if (it != this->MakefileSearchIndex.end()) {
+ return it->second;
}
return nullptr;
}
@@ -2110,10 +2092,9 @@ cmMakefile* cmGlobalGenerator::FindMakefile(const std::string& start_dir) const
cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(
cmDirectoryId const& id) const
{
- LocalGeneratorMap::const_iterator i =
- this->LocalGeneratorSearchIndex.find(id.String);
- if (i != this->LocalGeneratorSearchIndex.end()) {
- return i->second;
+ auto const it = this->LocalGeneratorSearchIndex.find(id.String);
+ if (it != this->LocalGeneratorSearchIndex.end()) {
+ return it->second;
}
return nullptr;
}
@@ -2187,9 +2168,9 @@ void cmGlobalGenerator::IndexLocalGenerator(cmLocalGenerator* lg)
cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const
{
- TargetMap::const_iterator i = this->TargetSearchIndex.find(name);
- if (i != this->TargetSearchIndex.end()) {
- return i->second;
+ auto const it = this->TargetSearchIndex.find(name);
+ if (it != this->TargetSearchIndex.end()) {
+ return it->second;
}
return nullptr;
}
@@ -2197,10 +2178,9 @@ cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const
cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTargetImpl(
std::string const& name) const
{
- GeneratorTargetMap::const_iterator i =
- this->GeneratorTargetSearchIndex.find(name);
- if (i != this->GeneratorTargetSearchIndex.end()) {
- return i->second;
+ auto const it = this->GeneratorTargetSearchIndex.find(name);
+ if (it != this->GeneratorTargetSearchIndex.end()) {
+ return it->second;
}
return nullptr;
}
@@ -2209,8 +2189,7 @@ cmTarget* cmGlobalGenerator::FindTarget(const std::string& name,
bool excludeAliases) const
{
if (!excludeAliases) {
- std::map<std::string, std::string>::const_iterator ai =
- this->AliasTargets.find(name);
+ auto const ai = this->AliasTargets.find(name);
if (ai != this->AliasTargets.end()) {
return this->FindTargetImpl(ai->second);
}
@@ -2221,8 +2200,7 @@ cmTarget* cmGlobalGenerator::FindTarget(const std::string& name,
cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTarget(
const std::string& name) const
{
- std::map<std::string, std::string>::const_iterator ai =
- this->AliasTargets.find(name);
+ auto const ai = this->AliasTargets.find(name);
if (ai != this->AliasTargets.end()) {
return this->FindGeneratorTargetImpl(ai->second);
}
@@ -2653,8 +2631,7 @@ bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const
std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
std::string const& l) const
{
- std::map<std::string, std::string>::const_iterator it =
- this->LanguageToOriginalSharedLibFlags.find(l);
+ auto const it = this->LanguageToOriginalSharedLibFlags.find(l);
if (it != this->LanguageToOriginalSharedLibFlags.end()) {
return it->second;
}
@@ -2732,11 +2709,8 @@ void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets,
if (this->IsExcluded(root, generator)) {
continue;
}
- // Get the targets in the makefile
- const std::vector<cmGeneratorTarget*>& tgts =
- generator->GetGeneratorTargets();
- // loop over all the targets
- for (cmGeneratorTarget* target : tgts) {
+ // loop over all the generator targets in the makefile
+ for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) {
if (this->IsRootOnlyTarget(target) &&
target->GetLocalGenerator() != root) {
continue;
@@ -2762,8 +2736,7 @@ void cmGlobalGenerator::AddTargetDepends(cmGeneratorTarget const* target,
if (projectTargets.insert(target).second) {
// This is the first time we have encountered the target.
// Recursively follow its dependencies.
- TargetDependSet const& ts = this->GetTargetDirectDepends(target);
- for (auto const& t : ts) {
+ for (auto const& t : this->GetTargetDirectDepends(target)) {
this->AddTargetDepends(t, projectTargets);
}
}
@@ -2875,8 +2848,7 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
fname = line.substr(33);
// Look for a hash for this file's rule.
- std::map<std::string, RuleHash>::const_iterator rhi =
- this->RuleHashes.find(fname);
+ auto const rhi = this->RuleHashes.find(fname);
if (rhi != this->RuleHashes.end()) {
// Compare the rule hash in the file to that we were given.
if (strncmp(line.c_str(), rhi->second.Data, 32) != 0) {
@@ -2926,8 +2898,7 @@ void cmGlobalGenerator::WriteSummary()
cmGeneratedFileStream fout(fname);
for (cmLocalGenerator* lg : this->LocalGenerators) {
- const std::vector<cmGeneratorTarget*>& tgts = lg->GetGeneratorTargets();
- for (cmGeneratorTarget* tgt : tgts) {
+ for (cmGeneratorTarget* tgt : lg->GetGeneratorTargets()) {
if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -3015,8 +2986,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
for (std::string const& c : configs) {
target->GetSourceFiles(sources, c);
}
- std::vector<cmSourceFile*>::const_iterator sourcesEnd =
- cmRemoveDuplicates(sources);
+ auto const sourcesEnd = cmRemoveDuplicates(sources);
for (cmSourceFile* sf : cmMakeRange(sources.cbegin(), sourcesEnd)) {
Json::Value& lj_source = lj_sources.append(Json::objectValue);
std::string const& sfp = sf->GetFullPath();
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 17eb340..88c586a 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -86,13 +86,13 @@ struct GeneratedMakeCommand
class cmGlobalGenerator
{
public:
- ///! Free any memory allocated with the GlobalGenerator
+ //! Free any memory allocated with the GlobalGenerator
cmGlobalGenerator(cmake* cm);
virtual ~cmGlobalGenerator();
virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
- ///! Get the name for this generator
+ //! Get the name for this generator
virtual std::string GetName() const { return "Generic"; }
/** Check whether the given name matches the current generator. */
@@ -236,7 +236,7 @@ public:
const std::string& native,
bool ignoreErrors);
- ///! Get the CMake instance
+ //! Get the CMake instance
cmake* GetCMakeInstance() const { return this->CMakeInstance; }
void SetConfiguredFilesPath(cmGlobalGenerator* gen);
@@ -261,7 +261,7 @@ public:
void AddMakefile(cmMakefile* mf);
- ///! Set an generator for an "external makefile based project"
+ //! Set an generator for an "external makefile based project"
void SetExternalMakefileProjectGenerator(
cmExternalMakefileProjectGenerator* extraGenerator);
@@ -290,19 +290,19 @@ public:
bool GetForceUnixPaths() const { return this->ForceUnixPaths; }
bool GetToolSupportsColor() const { return this->ToolSupportsColor; }
- ///! return the language for the given extension
+ //! return the language for the given extension
std::string GetLanguageFromExtension(const char* ext) const;
- ///! is an extension to be ignored
+ //! is an extension to be ignored
bool IgnoreFile(const char* ext) const;
- ///! What is the preference for linkers and this language (None or Preferred)
+ //! What is the preference for linkers and this language (None or Preferred)
int GetLinkerPreference(const std::string& lang) const;
- ///! What is the object file extension for a given source file?
+ //! What is the object file extension for a given source file?
std::string GetLanguageOutputExtension(cmSourceFile const&) const;
- ///! What is the configurations directory variable called?
+ //! What is the configurations directory variable called?
virtual const char* GetCMakeCFGIntDir() const { return "."; }
- ///! expand CFGIntDir for a configuration
+ //! expand CFGIntDir for a configuration
virtual std::string ExpandCFGIntDir(const std::string& str,
const std::string& config) const;
@@ -318,7 +318,7 @@ public:
*/
virtual bool FindMakeProgram(cmMakefile*);
- ///! Find a target by name by searching the local generators.
+ //! Find a target by name by searching the local generators.
cmTarget* FindTarget(const std::string& name,
bool excludeAliases = false) const;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index e6a1d78..b69dea0 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -119,10 +119,11 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
cmMakefile* mf)
{
+ std::string arch;
if (p.empty()) {
cmSystemTools::Message(
"Green Hills MULTI: -A <arch> not specified; defaulting to \"arm\"");
- std::string arch = "arm";
+ arch = "arm";
/* store the platform name for later use
* -- already done if -A<arch> was specified
@@ -130,19 +131,51 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch.c_str(),
"Name of generator platform.",
cmStateEnums::INTERNAL);
+ } else {
+ arch = p;
}
- const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM");
- if (tgtPlatform == nullptr) {
- cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not "
- "specified; defaulting to \"integrity\"");
- tgtPlatform = "integrity";
+ /* check if OS location has been updated by platform scripts */
+ std::string platform = mf->GetSafeDefinition("GHS_TARGET_PLATFORM");
+ std::string osdir = mf->GetSafeDefinition("GHS_OS_DIR");
+ if (cmSystemTools::IsOff(osdir.c_str()) &&
+ platform.find("integrity") != std::string::npos) {
+ if (!this->CMakeInstance->GetIsInTryCompile()) {
+ /* required OS location is not found */
+ std::string m =
+ "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \"";
+ m += mf->GetSafeDefinition("GHS_OS_ROOT");
+ m += "\"";
+ cmSystemTools::Message(m);
+ }
+ osdir = "GHS_OS_DIR-NOT-SPECIFIED";
+ } else if (!this->CMakeInstance->GetIsInTryCompile() &&
+ cmSystemTools::IsOff(this->OsDir) &&
+ !cmSystemTools::IsOff(osdir)) {
+ /* OS location was updated by auto-selection */
+ std::string m = "Green Hills MULTI: GHS_OS_DIR not specified; found \"";
+ m += osdir;
+ m += "\"";
+ cmSystemTools::Message(m);
}
+ this->OsDir = osdir;
- /* store the platform name for later use */
- mf->AddCacheDefinition("GHS_TARGET_PLATFORM", tgtPlatform,
- "Name of GHS target platform.",
- cmStateEnums::INTERNAL);
+ // Determine GHS_BSP_NAME
+ std::string bspName = mf->GetSafeDefinition("GHS_BSP_NAME");
+
+ if (cmSystemTools::IsOff(bspName.c_str()) &&
+ platform.find("integrity") != std::string::npos) {
+ bspName = "sim" + arch;
+ /* write back the calculate name for next time */
+ mf->AddCacheDefinition("GHS_BSP_NAME", bspName.c_str(),
+ "Name of GHS target platform.",
+ cmStateEnums::STRING, true);
+ std::string m =
+ "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \"";
+ m += bspName;
+ m += "\"";
+ cmSystemTools::Message(m);
+ }
return true;
}
@@ -153,6 +186,21 @@ void cmGlobalGhsMultiGenerator::EnableLanguage(
mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
+
+ const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM");
+ if (!tgtPlatform) {
+ cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not "
+ "specified; defaulting to \"integrity\"");
+ tgtPlatform = "integrity";
+ }
+
+ /* store the platform name for later use */
+ mf->AddCacheDefinition("GHS_TARGET_PLATFORM", tgtPlatform,
+ "Name of GHS target platform.", cmStateEnums::STRING);
+
+ /* store original OS location */
+ this->OsDir = mf->GetSafeDefinition("GHS_OS_DIR");
+
this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
}
@@ -217,132 +265,239 @@ void cmGlobalGhsMultiGenerator::WriteFileHeader(std::ostream& fout)
<< std::endl;
}
-void cmGlobalGhsMultiGenerator::WriteTopLevelProject(
- std::ostream& fout, cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
+void cmGlobalGhsMultiGenerator::WriteCustomRuleBOD(std::ostream& fout)
{
- WriteFileHeader(fout);
+ fout << "Commands {\n"
+ " Custom_Rule_Command {\n"
+ " name = \"Custom Rule Command\"\n"
+ " exec = \"";
+#ifdef _WIN32
+ fout << "cmd.exe";
+#else
+ fout << "/bin/sh";
+#endif
+ fout << "\"\n"
+ " options = {\"SpecialOptions\"}\n"
+ " }\n"
+ "}\n";
+
+ fout << "\n\n";
+ fout << "FileTypes {\n"
+ " CmakeRule {\n"
+ " name = \"Custom Rule\"\n"
+ " action = \"&Run\"\n"
+ " extensions = {\"";
+#ifdef _WIN32
+ fout << "bat";
+#else
+ fout << "sh";
+#endif
+ fout << "\"}\n"
+ " grepable = false\n"
+ " command = \"Custom Rule Command\"\n"
+ " commandLine = \"$COMMAND ";
+#ifdef _WIN32
+ fout << "/c";
+#endif
+ fout << " $INPUTFILE\"\n"
+ " progress = \"Processing Custom Rule\"\n"
+ " promoteToFirstPass = true\n"
+ " outputType = \"None\"\n"
+ " color = \"#800080\"\n"
+ " }\n"
+ "}\n";
+}
- this->WriteMacros(fout);
- this->WriteHighLevelDirectives(fout);
+void cmGlobalGhsMultiGenerator::WriteCustomTargetBOD(std::ostream& fout)
+{
+ fout << "FileTypes {\n"
+ " CmakeTarget {\n"
+ " name = \"Custom Target\"\n"
+ " action = \"&Execute\"\n"
+ " grepable = false\n"
+ " outputType = \"None\"\n"
+ " color = \"#800080\"\n"
+ " }\n"
+ "}\n";
+}
+
+void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout,
+ cmLocalGenerator* root)
+{
+ this->WriteFileHeader(fout);
+ this->WriteMacros(fout, root);
+ this->WriteHighLevelDirectives(root, fout);
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout);
fout << "# Top Level Project File" << std::endl;
// Specify BSP option if supplied by user
- // -- not all platforms require this entry in the project file
- // integrity platforms require this field; use default if needed
- std::string platform;
- if (const char* p =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM")) {
- platform = p;
- }
-
- std::string bspName;
- if (char const* bspCache =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME")) {
- bspName = bspCache;
- this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME");
- } else {
- bspName = "IGNORE";
- }
-
- if (platform.find("integrity") != std::string::npos &&
- cmSystemTools::IsOff(bspName.c_str())) {
- const char* a =
- this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM");
- bspName = "sim";
- bspName += (a ? a : "");
- }
-
- if (!cmSystemTools::IsOff(bspName.c_str())) {
+ const char* bspName =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME");
+ if (!cmSystemTools::IsOff(bspName)) {
fout << " -bsp " << bspName << std::endl;
}
// Specify OS DIR if supplied by user
// -- not all platforms require this entry in the project file
- std::string osDir;
- std::string osDirOption;
- if (char const* osDirCache =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR")) {
- osDir = osDirCache;
+ if (!cmSystemTools::IsOff(this->OsDir.c_str())) {
+ const char* osDirOption =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION");
+ std::replace(this->OsDir.begin(), this->OsDir.end(), '\\', '/');
+ fout << " ";
+ if (cmSystemTools::IsOff(osDirOption)) {
+ fout << "";
+ } else {
+ fout << osDirOption;
+ }
+ fout << "\"" << this->OsDir << "\"" << std::endl;
}
+}
- if (char const* osDirOptionCache =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION")) {
- osDirOption = osDirOptionCache;
+void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout,
+ std::string& all_target)
+{
+ fout << "CMakeFiles/" << all_target << " [Project]" << std::endl;
+ // All known targets
+ for (cmGeneratorTarget const* target : this->ProjectTargets) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ (target->GetType() == cmStateEnums::GLOBAL_TARGET &&
+ target->GetName() != GetInstallTargetName())) {
+ continue;
+ }
+ fout << "CMakeFiles/" << target->GetName() + ".tgt" + FILE_EXTENSION
+ << " [Project]" << std::endl;
}
+}
- if (!cmSystemTools::IsOff(osDir.c_str()) ||
- platform.find("integrity") != std::string::npos) {
- std::replace(osDir.begin(), osDir.end(), '\\', '/');
- fout << " " << osDirOption << "\"" << osDir << "\"" << std::endl;
+void cmGlobalGhsMultiGenerator::WriteProjectLine(
+ std::ostream& fout, cmGeneratorTarget const* target, cmLocalGenerator* root,
+ std::string& rootBinaryDir)
+{
+ const char* projName = target->GetProperty("GENERATOR_FILE_NAME");
+ const char* projType = target->GetProperty("GENERATOR_FILE_NAME_EXT");
+ if (projName && projType) {
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ std::string dir = lg->GetCurrentBinaryDirectory();
+ dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir);
+ if (dir == ".") {
+ dir.clear();
+ } else {
+ if (dir.back() != '/') {
+ dir += "/";
+ }
+ }
+
+ std::string projFile = dir + projName + FILE_EXTENSION;
+ fout << projFile;
+ fout << " " << projType << std::endl;
+ } else {
+ /* Should never happen */
+ std::string message =
+ "The project file for target [" + target->GetName() + "] is missing.\n";
+ cmSystemTools::Error(message);
+ fout << "{comment} " << target->GetName() << " [missing project file]\n";
}
+}
- WriteSubProjects(fout, root, generators);
+void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
+{
+ std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
+ rootBinaryDir += "/CMakeFiles";
+
+ // All known targets
+ for (cmGeneratorTarget const* target : this->ProjectTargets) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ (target->GetType() == cmStateEnums::GLOBAL_TARGET &&
+ target->GetName() != GetInstallTargetName())) {
+ continue;
+ }
+
+ // create target build file
+ std::string name = target->GetName() + ".tgt" + FILE_EXTENSION;
+ std::string fname = rootBinaryDir + "/" + name;
+ cmGeneratedFileStream fbld(fname);
+ fbld.SetCopyIfDifferent(true);
+ this->WriteFileHeader(fbld);
+ GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld);
+ std::vector<cmGeneratorTarget const*> build;
+ if (ComputeTargetBuildOrder(target, build)) {
+ std::string message = "The inter-target dependency graph for target [" +
+ target->GetName() + "] had a cycle.\n";
+ cmSystemTools::Error(message);
+ } else {
+ for (auto& tgt : build) {
+ WriteProjectLine(fbld, tgt, root, rootBinaryDir);
+ }
+ }
+ fbld.Close();
+ }
}
-void cmGlobalGhsMultiGenerator::WriteSubProjects(
- std::ostream& fout, cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators)
+void cmGlobalGhsMultiGenerator::WriteAllTarget(
+ cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators,
+ std::string& all_target)
{
+ this->ProjectTargets.clear();
+
+ // create target build file
+ all_target = root->GetProjectName() + "." + this->GetAllTargetName() +
+ ".tgt" + FILE_EXTENSION;
+ std::string fname =
+ root->GetCurrentBinaryDirectory() + "/CMakeFiles/" + all_target;
+ cmGeneratedFileStream fbld(fname);
+ fbld.SetCopyIfDifferent(true);
+ this->WriteFileHeader(fbld);
+ GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld);
+
// Collect all targets under this root generator and the transitive
// closure of their dependencies.
TargetDependSet projectTargets;
TargetDependSet originalTargets;
this->GetTargetSets(projectTargets, originalTargets, root, generators);
- OrderedTargetDependSet orderedProjectTargets(projectTargets, "");
-
- // write out all the sub-projects
- std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
- for (cmGeneratorTarget const* target : orderedProjectTargets) {
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ OrderedTargetDependSet sortedProjectTargets(projectTargets, "");
+ std::vector<cmGeneratorTarget const*> defaultTargets;
+ for (cmGeneratorTarget const* t : sortedProjectTargets) {
+ /* save list of all targets in sorted order */
+ this->ProjectTargets.push_back(t);
+ }
+ for (cmGeneratorTarget const* t : sortedProjectTargets) {
+ if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
-
- const char* projName = target->GetProperty("GENERATOR_FILE_NAME");
- const char* projType = target->GetProperty("GENERATOR_FILE_NAME_EXT");
- if (projName && projType) {
- cmLocalGenerator* lg = target->GetLocalGenerator();
- std::string dir = lg->GetCurrentBinaryDirectory();
- dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir);
- if (dir == ".") {
- dir.clear();
- } else {
- if (dir.back() != '/') {
- dir += "/";
- }
- }
-
- if (cmSystemTools::IsOn(target->GetProperty("EXCLUDE_FROM_ALL"))) {
- fout << "{comment} ";
- }
- std::string projFile = dir + projName + FILE_EXTENSION;
- fout << projFile;
- fout << " " << projType << std::endl;
-
- if (cmSystemTools::IsOn(target->GetProperty("GHS_REFERENCE_PROJECT"))) {
- // create reference project
- std::string fname = dir;
- fname += target->GetName();
- fname += "REF";
- fname += FILE_EXTENSION;
-
- cmGeneratedFileStream fref(fname);
- fref.SetCopyIfDifferent(true);
-
- this->WriteFileHeader(fref);
- GhsMultiGpj::WriteGpjTag(GhsMultiGpj::REFERENCE, fref);
- fref << " :reference=" << projFile << std::endl;
-
- fref.Close();
+ if (!cmSystemTools::IsOn(t->GetProperty("EXCLUDE_FROM_ALL"))) {
+ defaultTargets.push_back(t);
+ }
+ }
+ std::vector<cmGeneratorTarget const*> build;
+ if (ComputeTargetBuildOrder(defaultTargets, build)) {
+ std::string message = "The inter-target dependency graph for project [" +
+ root->GetProjectName() + "] had a cycle.\n";
+ cmSystemTools::Error(message);
+ } else {
+ // determine the targets for ALL target
+ std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
+ rootBinaryDir += "/CMakeFiles";
+ for (cmGeneratorTarget const* target : build) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ target->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ continue;
}
+ this->WriteProjectLine(fbld, target, root, rootBinaryDir);
}
}
+ fbld.Close();
}
void cmGlobalGhsMultiGenerator::Generate()
{
+ std::string fname;
+
// first do the superclass method
this->cmGlobalGenerator::Generate();
@@ -350,11 +505,32 @@ void cmGlobalGhsMultiGenerator::Generate()
for (auto& it : this->ProjectMap) {
this->OutputTopLevelProject(it.second[0], it.second);
}
+
+ // create custom rule BOD file
+ fname = this->GetCMakeInstance()->GetHomeOutputDirectory() +
+ "/CMakeFiles/custom_rule.bod";
+ cmGeneratedFileStream frule(fname);
+ frule.SetCopyIfDifferent(true);
+ this->WriteFileHeader(frule);
+ this->WriteCustomRuleBOD(frule);
+ frule.Close();
+
+ // create custom target BOD file
+ fname = this->GetCMakeInstance()->GetHomeOutputDirectory() +
+ "/CMakeFiles/custom_target.bod";
+ cmGeneratedFileStream ftarget(fname);
+ ftarget.SetCopyIfDifferent(true);
+ this->WriteFileHeader(ftarget);
+ this->WriteCustomTargetBOD(ftarget);
+ ftarget.Close();
}
void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
+ std::string fname;
+ std::string all_target;
+
if (generators.empty()) {
return;
}
@@ -363,18 +539,21 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
* with target projects. This avoid the issue where the project has
* the same name as the executable target.
*/
- std::string fname = root->GetCurrentBinaryDirectory();
+ fname = root->GetCurrentBinaryDirectory();
fname += "/";
fname += root->GetProjectName();
fname += ".top";
fname += FILE_EXTENSION;
- cmGeneratedFileStream fout(fname);
- fout.SetCopyIfDifferent(true);
+ cmGeneratedFileStream top(fname);
+ top.SetCopyIfDifferent(true);
+ this->WriteTopLevelProject(top, root);
- this->WriteTopLevelProject(fout, root, generators);
+ this->WriteAllTarget(root, generators, all_target);
+ this->WriteTargets(root);
- fout.Close();
+ this->WriteSubProjects(top, all_target);
+ top.Close();
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
@@ -406,6 +585,9 @@ cmGlobalGhsMultiGenerator::GenerateBuildCommand(
std::vector<std::string> files;
cmSystemTools::Glob(projectDir, ".*\\.top\\.gpj", files);
if (!files.empty()) {
+ /* if multiple top-projects are found in build directory
+ * then prefer projectName top-project.
+ */
auto p = std::find(files.begin(), files.end(), proj);
if (p == files.end()) {
proj = files.at(0);
@@ -420,20 +602,24 @@ cmGlobalGhsMultiGenerator::GenerateBuildCommand(
} else {
for (const auto& tname : targetNames) {
if (!tname.empty()) {
- if (tname.compare(tname.size() - 4, 4, ".gpj") == 0) {
- makeCommand.Add(tname);
- } else {
- makeCommand.Add(tname + ".gpj");
- }
+ makeCommand.Add(tname + ".tgt.gpj");
}
}
}
+ } else {
+ /* transform name to default build */;
+ std::string all = proj;
+ all.replace(all.end() - 7, all.end(),
+ std::string(this->GetAllTargetName()) + ".tgt.gpj");
+ makeCommand.Add(all);
}
return { makeCommand };
}
-void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout)
+void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout,
+ cmLocalGenerator* root)
{
+ fout << "macro PROJ_NAME=" << root->GetProjectName() << std::endl;
char const* ghsGpjMacros =
this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
if (nullptr != ghsGpjMacros) {
@@ -445,13 +631,14 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout)
}
}
-void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(std::ostream& fout)
+void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
+ cmLocalGenerator* root, std::ostream& fout)
{
/* set primary target */
std::string tgt;
const char* t =
this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET");
- if (t) {
+ if (t && *t != '\0') {
tgt = t;
this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET");
} else {
@@ -466,16 +653,20 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(std::ostream& fout)
}
fout << "primaryTarget=" << tgt << std::endl;
+ fout << "customization=" << root->GetBinaryDirectory()
+ << "/CMakeFiles/custom_rule.bod" << std::endl;
+ fout << "customization=" << root->GetBinaryDirectory()
+ << "/CMakeFiles/custom_target.bod" << std::endl;
char const* const customization =
this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
if (nullptr != customization && strlen(customization) > 0) {
- fout << "customization=" << trimQuotes(customization) << std::endl;
+ fout << "customization=" << this->TrimQuotes(customization) << std::endl;
this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION");
}
}
-std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str)
+std::string cmGlobalGhsMultiGenerator::TrimQuotes(std::string const& str)
{
std::string result;
result.reserve(str.size());
@@ -508,3 +699,56 @@ cmGlobalGhsMultiGenerator::OrderedTargetDependSet::OrderedTargetDependSet(
{
this->insert(targets.begin(), targets.end());
}
+
+bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
+ cmGeneratorTarget const* tgt, std::vector<cmGeneratorTarget const*>& build)
+{
+ std::vector<cmGeneratorTarget const*> t{ tgt };
+ return ComputeTargetBuildOrder(t, build);
+}
+
+bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
+ std::vector<cmGeneratorTarget const*>& tgt,
+ std::vector<cmGeneratorTarget const*>& build)
+{
+ std::set<cmGeneratorTarget const*> temp;
+ std::set<cmGeneratorTarget const*> perm;
+
+ for (auto ti : tgt) {
+ bool r = VisitTarget(temp, perm, build, ti);
+ if (r) {
+ return r;
+ }
+ }
+ return false;
+}
+
+bool cmGlobalGhsMultiGenerator::VisitTarget(
+ std::set<cmGeneratorTarget const*>& temp,
+ std::set<cmGeneratorTarget const*>& perm,
+ std::vector<cmGeneratorTarget const*>& order, cmGeneratorTarget const* ti)
+{
+ /* check if permanent mark is set*/
+ if (perm.find(ti) == perm.end()) {
+ /* set temporary mark; check if revisit*/
+ if (temp.insert(ti).second) {
+ /* sort targets lexicographically to ensure that nodes are always visited
+ * in the same order */
+ OrderedTargetDependSet sortedTargets(this->GetTargetDirectDepends(ti),
+ "");
+ for (auto& di : sortedTargets) {
+ if (this->VisitTarget(temp, perm, order, di)) {
+ return true;
+ }
+ }
+ /* mark as complete; insert into beginning of list*/
+ perm.insert(ti);
+ order.push_back(ti);
+ return false;
+ }
+ /* revisiting item - not a DAG */
+ return true;
+ }
+ /* already complete */
+ return false;
+}
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index f8df6ef..98358c7 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -34,13 +34,13 @@ public:
return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>();
}
- ///! create the correct local generator
+ //! create the correct local generator
cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/// @return the name of this generator.
static std::string GetActualName() { return "Green Hills MULTI"; }
- ///! Get the name for this generator
+ //! Get the name for this generator
std::string GetName() const override { return GetActualName(); }
/// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
@@ -78,23 +78,7 @@ public:
// Write the common disclaimer text at the top of each build file.
void WriteFileHeader(std::ostream& fout);
- // Target dependency sorting
- class TargetSet : public std::set<cmGeneratorTarget const*>
- {
- };
- class TargetCompare
- {
- std::string First;
-
- public:
- TargetCompare(std::string first)
- : First(std::move(first))
- {
- }
- bool operator()(cmGeneratorTarget const* l,
- cmGeneratorTarget const* r) const;
- };
- class OrderedTargetDependSet;
+ const char* GetInstallTargetName() const override { return "install"; }
protected:
void Generate() override;
@@ -111,17 +95,53 @@ private:
/* top-level project */
void OutputTopLevelProject(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
- void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators);
- void WriteMacros(std::ostream& fout);
- void WriteHighLevelDirectives(std::ostream& fout);
- void WriteSubProjects(std::ostream& fout, cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators);
-
- std::string trimQuotes(std::string const& str);
-
+ void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root);
+ void WriteMacros(std::ostream& fout, cmLocalGenerator* root);
+ void WriteHighLevelDirectives(cmLocalGenerator* root, std::ostream& fout);
+ void WriteSubProjects(std::ostream& fout, std::string& all_target);
+ void WriteTargets(cmLocalGenerator* root);
+ void WriteProjectLine(std::ostream& fout, cmGeneratorTarget const* target,
+ cmLocalGenerator* root, std::string& rootBinaryDir);
+ void WriteCustomRuleBOD(std::ostream& fout);
+ void WriteCustomTargetBOD(std::ostream& fout);
+ void WriteAllTarget(cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators,
+ std::string& all_target);
+
+ std::string TrimQuotes(std::string const& str);
+
+ std::string OsDir;
static const char* DEFAULT_BUILD_PROGRAM;
static const char* DEFAULT_TOOLSET_ROOT;
+
+ bool ComputeTargetBuildOrder(cmGeneratorTarget const* tgt,
+ std::vector<cmGeneratorTarget const*>& build);
+ bool ComputeTargetBuildOrder(std::vector<cmGeneratorTarget const*>& tgt,
+ std::vector<cmGeneratorTarget const*>& build);
+ bool VisitTarget(std::set<cmGeneratorTarget const*>& temp,
+ std::set<cmGeneratorTarget const*>& perm,
+ std::vector<cmGeneratorTarget const*>& order,
+ cmGeneratorTarget const* ti);
+
+ std::vector<cmGeneratorTarget const*> ProjectTargets;
+
+ // Target sorting
+ class TargetSet : public std::set<cmGeneratorTarget const*>
+ {
+ };
+ class TargetCompare
+ {
+ std::string First;
+
+ public:
+ TargetCompare(std::string first)
+ : First(std::move(first))
+ {
+ }
+ bool operator()(cmGeneratorTarget const* l,
+ cmGeneratorTarget const* r) const;
+ };
+ class OrderedTargetDependSet;
};
class cmGlobalGhsMultiGenerator::OrderedTargetDependSet
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index 341b2dd..df3aec9 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -20,7 +20,7 @@ public:
{
return new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
std::string GetName() const override
{
return cmGlobalJOMMakefileGenerator::GetActualName();
diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h
index 23dbc5e..d6e4847 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.h
+++ b/Source/cmGlobalMSYSMakefileGenerator.h
@@ -19,7 +19,7 @@ public:
return new cmGlobalGeneratorSimpleFactory<cmGlobalMSYSMakefileGenerator>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
virtual std::string GetName() const
{
return cmGlobalMSYSMakefileGenerator::GetActualName();
diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h
index a994c92..15297e3 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.h
+++ b/Source/cmGlobalMinGWMakefileGenerator.h
@@ -19,7 +19,7 @@ public:
return new cmGlobalGeneratorSimpleFactory<
cmGlobalMinGWMakefileGenerator>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
virtual std::string GetName() const
{
return cmGlobalMinGWMakefileGenerator::GetActualName();
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index 1fc2f9c..2fdf1ce 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -21,7 +21,7 @@ public:
return new cmGlobalGeneratorSimpleFactory<
cmGlobalNMakeMakefileGenerator>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
std::string GetName() const override
{
return cmGlobalNMakeMakefileGenerator::GetActualName();
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index e443678..4fa6ee6 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -906,11 +906,11 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand(
/* clang-format off */
*this->CompileCommandsStream << "\n{\n"
- << " \"directory\": \""
+ << R"( "directory": ")"
<< cmGlobalGenerator::EscapeJSON(buildFileDir) << "\",\n"
- << " \"command\": \""
+ << R"( "command": ")"
<< cmGlobalGenerator::EscapeJSON(commandLine) << "\",\n"
- << " \"file\": \""
+ << R"( "file": ")"
<< cmGlobalGenerator::EscapeJSON(sourceFileName) << "\"\n"
<< "}";
/* clang-format on */
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 3381c81..65d816e 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -57,7 +57,7 @@ void cmGlobalUnixMakefileGenerator3::EnableLanguage(
}
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(
cmMakefile* mf)
{
@@ -177,13 +177,13 @@ void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
*this->CommandDatabase << "," << std::endl;
}
*this->CommandDatabase << "{" << std::endl
- << " \"directory\": \""
+ << R"( "directory": ")"
<< cmGlobalGenerator::EscapeJSON(workingDirectory)
<< "\"," << std::endl
- << " \"command\": \""
+ << R"( "command": ")"
<< cmGlobalGenerator::EscapeJSON(compileCommand)
<< "\"," << std::endl
- << " \"file\": \""
+ << R"( "file": ")"
<< cmGlobalGenerator::EscapeJSON(sourceFile) << "\""
<< std::endl
<< "}";
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 496104d..e919d38 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -67,7 +67,7 @@ public:
cmGlobalUnixMakefileGenerator3>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
std::string GetName() const override
{
return cmGlobalUnixMakefileGenerator3::GetActualName();
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 26fd62b..4fa89d0 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -509,7 +509,7 @@ std::string cmGlobalVisualStudio10Generator::SelectWindowsCEToolset() const
return "";
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator(
cmMakefile* mf)
{
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 26db929..2f532a6 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -29,7 +29,7 @@ public:
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
- ///! create the correct local generator
+ //! create the correct local generator
cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/**
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index c694902..d7630e4 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -248,7 +248,7 @@ cmGlobalVisualStudio7Generator::GenerateBuildCommand(
return makeCommands;
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator(
cmMakefile* mf)
{
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 954d1d3..1e76383 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -20,7 +20,7 @@ class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator
public:
~cmGlobalVisualStudio7Generator();
- ///! Create a local generator appropriate to this Global Generator
+ //! Create a local generator appropriate to this Global Generator
cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
#if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -64,7 +64,7 @@ public:
*/
virtual void OutputSLNFile();
- ///! Lookup a stored GUID or compute one deterministically.
+ //! Lookup a stored GUID or compute one deterministically.
std::string GetGUID(std::string const& name);
/** Append the subdirectory for the given configuration. */
@@ -73,7 +73,7 @@ public:
const std::string& suffix,
std::string& dir) override;
- ///! What is the configurations directory variable called?
+ //! What is the configurations directory variable called?
const char* GetCMakeCFGIntDir() const override
{
return "$(ConfigurationName)";
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index 75f4778..352bc3c 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -13,7 +13,7 @@
class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator
{
public:
- ///! Get the name for the generator.
+ //! Get the name for the generator.
std::string GetName() const override { return this->Name; }
/** Get the name of the main stamp list file. */
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index bc40a5c..280c986 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -12,6 +12,7 @@
#include "cmAlgorithms.h"
#include "cmCallVisualStudioMacro.h"
+#include "cmCustomCommand.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudioGenerator.h"
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index c96dc72..3ca5e7d 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -29,7 +29,7 @@ public:
{
return new cmGlobalGeneratorSimpleFactory<cmGlobalWatcomWMakeGenerator>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
std::string GetName() const override
{
return cmGlobalWatcomWMakeGenerator::GetActualName();
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 4025073..db673bb 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -12,6 +12,7 @@
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
@@ -388,7 +389,7 @@ cmGlobalXCodeGenerator::GenerateBuildCommand(
return { std::move(makeCommand) };
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf)
{
return new cmLocalXCodeGenerator(this, mf);
@@ -1145,6 +1146,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
// Add CMakeLists.txt file for user convenience.
this->AddXCodeProjBuildRule(gtgt, classes);
+ // Add the Info.plist we are about to generate for an App Bundle.
+ if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(plist, true);
+ classes.push_back(sf);
+ }
+
std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
gtgt->ComputeObjectMapping();
@@ -1799,6 +1807,10 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang,
configName);
+ if (gtgt->IsIPOEnabled(lang, configName)) {
+ this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
+ }
+
// Add shared-library flags if needed.
this->CurrentLocalGenerator->AddCMP0018Flags(flags, gtgt, lang,
configName);
@@ -2857,13 +2869,13 @@ bool cmGlobalXCodeGenerator::CreateGroups(
continue;
}
- // add the soon to be generated Info.plist file as a source for a
- // MACOSX_BUNDLE file
- if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
- std::string plist = this->ComputeInfoPListLocation(gtgt);
- mf->GetOrCreateSource(plist, true);
- gtgt->AddSource(plist);
- }
+ auto addSourceToGroup = [this, mf, gtgt,
+ &sourceGroups](std::string const& source) {
+ cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups);
+ cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
+ std::string key = GetGroupMapKeyFromPath(gtgt, source);
+ this->GroupMap[key] = pbxgroup;
+ };
// Put cmSourceFile instances in proper groups:
for (auto const& si : gtgt->GetAllConfigSources()) {
@@ -2872,12 +2884,7 @@ bool cmGlobalXCodeGenerator::CreateGroups(
// Object library files go on the link line instead.
continue;
}
- // Add the file to the list of sources.
- std::string const& source = sf->GetFullPath();
- cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups);
- cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
- std::string key = GetGroupMapKeyFromPath(gtgt, source);
- this->GroupMap[key] = pbxgroup;
+ addSourceToGroup(sf->GetFullPath());
}
// Add CMakeLists.txt file for user convenience.
@@ -2886,11 +2893,14 @@ bool cmGlobalXCodeGenerator::CreateGroups(
gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
listfile += "/CMakeLists.txt";
cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(listfile);
- std::string const& source = sf->GetFullPath();
- cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups);
- cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
- std::string key = GetGroupMapKeyFromPath(gtgt, source);
- this->GroupMap[key] = pbxgroup;
+ addSourceToGroup(sf->GetFullPath());
+ }
+
+ // Add the Info.plist we are about to generate for an App Bundle.
+ if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(plist, true);
+ addSourceToGroup(sf->GetFullPath());
}
}
}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 8daa95b..71446f9 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -36,7 +36,7 @@ public:
unsigned int version_number);
static cmGlobalGeneratorFactory* NewFactory();
- ///! Get the name for the generator.
+ //! Get the name for the generator.
std::string GetName() const override
{
return cmGlobalXCodeGenerator::GetActualName();
@@ -46,7 +46,7 @@ public:
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
+ //! Create a local generator appropriate to this Global Generator
cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/**
@@ -81,9 +81,9 @@ public:
bool FindMakeProgram(cmMakefile*) override;
- ///! What is the configurations directory variable called?
+ //! What is the configurations directory variable called?
const char* GetCMakeCFGIntDir() const override;
- ///! expand CFGIntDir
+ //! expand CFGIntDir
std::string ExpandCFGIntDir(const std::string& str,
const std::string& config) const override;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 20d1a31..dba4bbb 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCommand.h"
+#include "cm_static_string_view.hxx"
#include "cmsys/Glob.hxx"
#include <set>
#include <sstream>
@@ -9,7 +10,7 @@
#include <utility>
#include "cmAlgorithms.h"
-#include "cmCommandArgumentsHelper.h"
+#include "cmArgumentParser.h"
#include "cmExportSet.h"
#include "cmExportSetMap.h"
#include "cmGeneratorExpression.h"
@@ -219,49 +220,51 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
return true;
}
-/*struct InstallPart
-{
- InstallPart(cmCommandArgumentsHelper* helper, const char* key,
- cmCommandArgumentGroup* group);
- cmCAStringVector argVector;
- cmInstallCommandArguments args;
-};*/
-
bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
{
// This is the TARGETS mode.
std::vector<cmTarget*> targets;
- cmCommandArgumentsHelper argHelper;
- cmCommandArgumentGroup group;
- cmCAStringVector genericArgVector(&argHelper, nullptr);
- cmCAStringVector archiveArgVector(&argHelper, "ARCHIVE", &group);
- cmCAStringVector libraryArgVector(&argHelper, "LIBRARY", &group);
- cmCAStringVector runtimeArgVector(&argHelper, "RUNTIME", &group);
- cmCAStringVector objectArgVector(&argHelper, "OBJECTS", &group);
- cmCAStringVector frameworkArgVector(&argHelper, "FRAMEWORK", &group);
- cmCAStringVector bundleArgVector(&argHelper, "BUNDLE", &group);
- cmCAStringVector includesArgVector(&argHelper, "INCLUDES", &group);
- cmCAStringVector privateHeaderArgVector(&argHelper, "PRIVATE_HEADER",
- &group);
- cmCAStringVector publicHeaderArgVector(&argHelper, "PUBLIC_HEADER", &group);
- cmCAStringVector resourceArgVector(&argHelper, "RESOURCE", &group);
- genericArgVector.Follows(nullptr);
- group.Follows(&genericArgVector);
-
- argHelper.Parse(&args, nullptr);
+ struct ArgVectors
+ {
+ std::vector<std::string> Archive;
+ std::vector<std::string> Library;
+ std::vector<std::string> Runtime;
+ std::vector<std::string> Object;
+ std::vector<std::string> Framework;
+ std::vector<std::string> Bundle;
+ std::vector<std::string> Includes;
+ std::vector<std::string> PrivateHeader;
+ std::vector<std::string> PublicHeader;
+ std::vector<std::string> Resource;
+ };
+
+ static auto const argHelper =
+ cmArgumentParser<ArgVectors>{}
+ .Bind("ARCHIVE"_s, &ArgVectors::Archive)
+ .Bind("LIBRARY"_s, &ArgVectors::Library)
+ .Bind("RUNTIME"_s, &ArgVectors::Runtime)
+ .Bind("OBJECTS"_s, &ArgVectors::Object)
+ .Bind("FRAMEWORK"_s, &ArgVectors::Framework)
+ .Bind("BUNDLE"_s, &ArgVectors::Bundle)
+ .Bind("INCLUDES"_s, &ArgVectors::Includes)
+ .Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader)
+ .Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader)
+ .Bind("RESOURCE"_s, &ArgVectors::Resource);
+
+ std::vector<std::string> genericArgVector;
+ ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
// now parse the generic args (i.e. the ones not specialized on LIBRARY/
// ARCHIVE, RUNTIME etc. (see above)
// These generic args also contain the targets and the export stuff
+ std::vector<std::string> targetList;
+ std::string exports;
std::vector<std::string> unknownArgs;
cmInstallCommandArguments genericArgs(this->DefaultComponentName);
- cmCAStringVector targetList(&genericArgs.Parser, "TARGETS");
- cmCAString exports(&genericArgs.Parser, "EXPORT",
- &genericArgs.ArgumentGroup);
- targetList.Follows(nullptr);
- genericArgs.ArgumentGroup.Follows(&targetList);
- genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs);
+ genericArgs.Bind("TARGETS"_s, targetList);
+ genericArgs.Bind("EXPORT"_s, exports);
+ genericArgs.Parse(genericArgVector, &unknownArgs);
bool success = genericArgs.Finalize();
cmInstallCommandArguments archiveArgs(this->DefaultComponentName);
@@ -277,16 +280,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
- archiveArgs.Parse(&archiveArgVector.GetVector(), &unknownArgs);
- libraryArgs.Parse(&libraryArgVector.GetVector(), &unknownArgs);
- runtimeArgs.Parse(&runtimeArgVector.GetVector(), &unknownArgs);
- objectArgs.Parse(&objectArgVector.GetVector(), &unknownArgs);
- frameworkArgs.Parse(&frameworkArgVector.GetVector(), &unknownArgs);
- bundleArgs.Parse(&bundleArgVector.GetVector(), &unknownArgs);
- privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
- publicHeaderArgs.Parse(&publicHeaderArgVector.GetVector(), &unknownArgs);
- resourceArgs.Parse(&resourceArgVector.GetVector(), &unknownArgs);
- includesArgs.Parse(&includesArgVector.GetVector(), &unknownArgs);
+ archiveArgs.Parse(argVectors.Archive, &unknownArgs);
+ libraryArgs.Parse(argVectors.Library, &unknownArgs);
+ runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
+ objectArgs.Parse(argVectors.Object, &unknownArgs);
+ frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
+ bundleArgs.Parse(argVectors.Bundle, &unknownArgs);
+ privateHeaderArgs.Parse(argVectors.PrivateHeader, &unknownArgs);
+ publicHeaderArgs.Parse(argVectors.PublicHeader, &unknownArgs);
+ resourceArgs.Parse(argVectors.Resource, &unknownArgs);
+ includesArgs.Parse(&argVectors.Includes, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
@@ -382,7 +385,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
// Check if there is something to do.
- if (targetList.GetVector().empty()) {
+ if (targetList.empty()) {
return true;
}
@@ -390,7 +393,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
bool dll_platform =
!this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
- for (std::string const& tgt : targetList.GetVector()) {
+ for (std::string const& tgt : targetList) {
if (this->Makefile->IsAlias(tgt)) {
std::ostringstream e;
@@ -663,8 +666,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// generators for them.
bool createInstallGeneratorsForTargetFileSets = true;
- if (target.IsFrameworkOnApple() ||
- target.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (target.IsFrameworkOnApple()) {
createInstallGeneratorsForTargetFileSets = false;
}
@@ -748,7 +750,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Add this install rule to an export if one was specified and
// this is not a namelink-only rule.
- if (!exports.GetString().empty() && !namelinkOnly) {
+ if (!exports.empty() && !namelinkOnly) {
cmTargetExport* te = new cmTargetExport;
te->TargetName = target.GetName();
te->ArchiveGenerator = archiveGenerator;
@@ -759,7 +761,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
te->RuntimeGenerator = runtimeGenerator;
te->ObjectsGenerator = objectGenerator;
this->Makefile->GetGlobalGenerator()
- ->GetExportSets()[exports.GetString()]
+ ->GetExportSets()[exports]
->AddTargetExport(te);
te->InterfaceIncludeDirectories =
@@ -818,11 +820,10 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
// This is the FILES mode.
bool programs = (args[0] == "PROGRAMS");
cmInstallCommandArguments ica(this->DefaultComponentName);
- cmCAStringVector files(&ica.Parser, programs ? "PROGRAMS" : "FILES");
- files.Follows(nullptr);
- ica.ArgumentGroup.Follows(&files);
+ std::vector<std::string> files;
+ ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files);
std::vector<std::string> unknownArgs;
- ica.Parse(&args, &unknownArgs);
+ ica.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
@@ -840,7 +841,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
return false;
}
- const std::vector<std::string>& filesVector = files.GetVector();
+ const std::vector<std::string>& filesVector = files;
// Check if there is something to do.
if (filesVector.empty()) {
@@ -1271,16 +1272,19 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
#ifdef CMAKE_BUILD_WITH_CMAKE
// This is the EXPORT mode.
cmInstallCommandArguments ica(this->DefaultComponentName);
- cmCAString exp(&ica.Parser, "EXPORT_ANDROID_MK");
- cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
- cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
- &ica.ArgumentGroup);
- cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
- exp.Follows(nullptr);
-
- ica.ArgumentGroup.Follows(&exp);
+
+ std::string exp;
+ std::string name_space;
+ bool exportOld = false;
+ std::string filename;
+
+ ica.Bind("EXPORT_ANDROID_MK"_s, exp);
+ ica.Bind("NAMESPACE"_s, name_space);
+ ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
+ ica.Bind("FILE"_s, filename);
+
std::vector<std::string> unknownArgs;
- ica.Parse(&args, &unknownArgs);
+ ica.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
@@ -1304,7 +1308,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
}
// Check the file name.
- std::string fname = filename.GetString();
+ std::string fname = filename;
if (fname.find_first_of(":/\\") != std::string::npos) {
std::ostringstream e;
e << args[0] << " given invalid export file name \"" << fname << "\". "
@@ -1325,7 +1329,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
}
if (fname.find_first_of(":/\\") != std::string::npos) {
std::ostringstream e;
- e << args[0] << " given export name \"" << exp.GetString() << "\". "
+ e << args[0] << " given export name \"" << exp << "\". "
<< "This name cannot be safely converted to a file name. "
<< "Specify a different export name or use the FILE option to set "
<< "a file name explicitly.";
@@ -1338,7 +1342,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
}
cmExportSet* exportSet =
- this->Makefile->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
+ this->Makefile->GetGlobalGenerator()->GetExportSets()[exp];
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(this->Makefile);
@@ -1347,8 +1351,8 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
ica.GetConfigurations(), ica.GetComponent().c_str(), message,
- ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
- exportOld.IsEnabled(), true);
+ ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld,
+ true);
this->Makefile->AddInstallGenerator(exportGenerator);
return true;
@@ -1363,16 +1367,19 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
{
// This is the EXPORT mode.
cmInstallCommandArguments ica(this->DefaultComponentName);
- cmCAString exp(&ica.Parser, "EXPORT");
- cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
- cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
- &ica.ArgumentGroup);
- cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
- exp.Follows(nullptr);
-
- ica.ArgumentGroup.Follows(&exp);
+
+ std::string exp;
+ std::string name_space;
+ bool exportOld = false;
+ std::string filename;
+
+ ica.Bind("EXPORT"_s, exp);
+ ica.Bind("NAMESPACE"_s, name_space);
+ ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
+ ica.Bind("FILE"_s, filename);
+
std::vector<std::string> unknownArgs;
- ica.Parse(&args, &unknownArgs);
+ ica.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
@@ -1396,7 +1403,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
}
// Check the file name.
- std::string fname = filename.GetString();
+ std::string fname = filename;
if (fname.find_first_of(":/\\") != std::string::npos) {
std::ostringstream e;
e << args[0] << " given invalid export file name \"" << fname << "\". "
@@ -1418,12 +1425,12 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
// Construct the file name.
if (fname.empty()) {
- fname = exp.GetString();
+ fname = exp;
fname += ".cmake";
if (fname.find_first_of(":/\\") != std::string::npos) {
std::ostringstream e;
- e << args[0] << " given export name \"" << exp.GetString() << "\". "
+ e << args[0] << " given export name \"" << exp << "\". "
<< "This name cannot be safely converted to a file name. "
<< "Specify a different export name or use the FILE option to set "
<< "a file name explicitly.";
@@ -1433,8 +1440,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
}
cmExportSet* exportSet =
- this->Makefile->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
- if (exportOld.IsEnabled()) {
+ this->Makefile->GetGlobalGenerator()->GetExportSets()[exp];
+ if (exportOld) {
for (cmTargetExport* te : *exportSet->GetTargetExports()) {
cmTarget* tgt =
this->Makefile->GetGlobalGenerator()->FindTarget(te->TargetName);
@@ -1461,8 +1468,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
ica.GetConfigurations(), ica.GetComponent().c_str(), message,
- ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
- exportOld.IsEnabled(), false);
+ ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld,
+ false);
this->Makefile->AddInstallGenerator(exportGenerator);
return true;
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index c64bd8a..8b33782 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -4,6 +4,7 @@
#include "cmRange.h"
#include "cmSystemTools.h"
+#include "cm_static_string_view.hxx"
#include <utility>
@@ -18,20 +19,19 @@ const std::string cmInstallCommandArguments::EmptyString;
cmInstallCommandArguments::cmInstallCommandArguments(
std::string defaultComponent)
- : Destination(&Parser, "DESTINATION", &ArgumentGroup)
- , Component(&Parser, "COMPONENT", &ArgumentGroup)
- , NamelinkComponent(&Parser, "NAMELINK_COMPONENT", &ArgumentGroup)
- , ExcludeFromAll(&Parser, "EXCLUDE_FROM_ALL", &ArgumentGroup)
- , Rename(&Parser, "RENAME", &ArgumentGroup)
- , Permissions(&Parser, "PERMISSIONS", &ArgumentGroup)
- , Configurations(&Parser, "CONFIGURATIONS", &ArgumentGroup)
- , Optional(&Parser, "OPTIONAL", &ArgumentGroup)
- , NamelinkOnly(&Parser, "NAMELINK_ONLY", &ArgumentGroup)
- , NamelinkSkip(&Parser, "NAMELINK_SKIP", &ArgumentGroup)
- , Type(&Parser, "TYPE", &ArgumentGroup)
- , GenericArguments(nullptr)
- , DefaultComponentName(std::move(defaultComponent))
+ : DefaultComponentName(std::move(defaultComponent))
{
+ this->Bind("DESTINATION"_s, this->Destination);
+ this->Bind("COMPONENT"_s, this->Component);
+ this->Bind("NAMELINK_COMPONENT"_s, this->NamelinkComponent);
+ this->Bind("EXCLUDE_FROM_ALL"_s, this->ExcludeFromAll);
+ this->Bind("RENAME"_s, this->Rename);
+ this->Bind("PERMISSIONS"_s, this->Permissions);
+ this->Bind("CONFIGURATIONS"_s, this->Configurations);
+ this->Bind("OPTIONAL"_s, this->Optional);
+ this->Bind("NAMELINK_ONLY"_s, this->NamelinkOnly);
+ this->Bind("NAMELINK_SKIP"_s, this->NamelinkSkip);
+ this->Bind("TYPE"_s, this->Type);
}
const std::string& cmInstallCommandArguments::GetDestination() const
@@ -47,8 +47,8 @@ const std::string& cmInstallCommandArguments::GetDestination() const
const std::string& cmInstallCommandArguments::GetComponent() const
{
- if (!this->Component.GetString().empty()) {
- return this->Component.GetString();
+ if (!this->Component.empty()) {
+ return this->Component;
}
if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetComponent();
@@ -62,16 +62,16 @@ const std::string& cmInstallCommandArguments::GetComponent() const
const std::string& cmInstallCommandArguments::GetNamelinkComponent() const
{
- if (!this->NamelinkComponent.GetString().empty()) {
- return this->NamelinkComponent.GetString();
+ if (!this->NamelinkComponent.empty()) {
+ return this->NamelinkComponent;
}
return this->GetComponent();
}
const std::string& cmInstallCommandArguments::GetRename() const
{
- if (!this->Rename.GetString().empty()) {
- return this->Rename.GetString();
+ if (!this->Rename.empty()) {
+ return this->Rename;
}
if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetRename();
@@ -92,7 +92,7 @@ const std::string& cmInstallCommandArguments::GetPermissions() const
bool cmInstallCommandArguments::GetOptional() const
{
- if (this->Optional.IsEnabled()) {
+ if (this->Optional) {
return true;
}
if (this->GenericArguments != nullptr) {
@@ -103,7 +103,7 @@ bool cmInstallCommandArguments::GetOptional() const
bool cmInstallCommandArguments::GetExcludeFromAll() const
{
- if (this->ExcludeFromAll.IsEnabled()) {
+ if (this->ExcludeFromAll) {
return true;
}
if (this->GenericArguments != nullptr) {
@@ -114,7 +114,7 @@ bool cmInstallCommandArguments::GetExcludeFromAll() const
bool cmInstallCommandArguments::GetNamelinkOnly() const
{
- if (this->NamelinkOnly.IsEnabled()) {
+ if (this->NamelinkOnly) {
return true;
}
if (this->GenericArguments != nullptr) {
@@ -125,7 +125,7 @@ bool cmInstallCommandArguments::GetNamelinkOnly() const
bool cmInstallCommandArguments::GetNamelinkSkip() const
{
- if (this->NamelinkSkip.IsEnabled()) {
+ if (this->NamelinkSkip) {
return true;
}
if (this->GenericArguments != nullptr) {
@@ -136,7 +136,7 @@ bool cmInstallCommandArguments::GetNamelinkSkip() const
bool cmInstallCommandArguments::HasNamelinkComponent() const
{
- if (!this->NamelinkComponent.GetString().empty()) {
+ if (!this->NamelinkComponent.empty()) {
return true;
}
if (this->GenericArguments != nullptr) {
@@ -147,19 +147,19 @@ bool cmInstallCommandArguments::HasNamelinkComponent() const
const std::string& cmInstallCommandArguments::GetType() const
{
- return this->Type.GetString();
+ return this->Type;
}
const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
const
{
- if (!this->Configurations.GetVector().empty()) {
- return this->Configurations.GetVector();
+ if (!this->Configurations.empty()) {
+ return this->Configurations;
}
if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetConfigurations();
}
- return this->Configurations.GetVector();
+ return this->Configurations;
}
bool cmInstallCommandArguments::Finalize()
@@ -167,21 +167,15 @@ bool cmInstallCommandArguments::Finalize()
if (!this->CheckPermissions()) {
return false;
}
- this->DestinationString = this->Destination.GetString();
+ this->DestinationString = this->Destination;
cmSystemTools::ConvertToUnixSlashes(this->DestinationString);
return true;
}
-void cmInstallCommandArguments::Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs)
-{
- this->Parser.Parse(args, unconsumedArgs);
-}
-
bool cmInstallCommandArguments::CheckPermissions()
{
this->PermissionsString.clear();
- for (std::string const& perm : this->Permissions.GetVector()) {
+ for (std::string const& perm : this->Permissions) {
if (!cmInstallCommandArguments::CheckPermissions(
perm, this->PermissionsString)) {
return false;
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index 9c0d417..5d2ee0a 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -8,9 +8,9 @@
#include <string>
#include <vector>
-#include "cmCommandArgumentsHelper.h"
+#include "cmArgumentParser.h"
-class cmInstallCommandArguments
+class cmInstallCommandArguments : public cmArgumentParser<void>
{
public:
cmInstallCommandArguments(std::string defaultComponent);
@@ -18,8 +18,6 @@ public:
{
this->GenericArguments = args;
}
- void Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs);
// Compute destination path.and check permissions
bool Finalize();
@@ -37,30 +35,25 @@ public:
bool HasNamelinkComponent() const;
const std::string& GetType() const;
- // once HandleDirectoryMode() is also switched to using
- // cmInstallCommandArguments then these two functions can become non-static
- // private member functions without arguments
static bool CheckPermissions(const std::string& onePerm, std::string& perm);
- cmCommandArgumentsHelper Parser;
- cmCommandArgumentGroup ArgumentGroup;
private:
- cmCAString Destination;
- cmCAString Component;
- cmCAString NamelinkComponent;
- cmCAEnabler ExcludeFromAll;
- cmCAString Rename;
- cmCAStringVector Permissions;
- cmCAStringVector Configurations;
- cmCAEnabler Optional;
- cmCAEnabler NamelinkOnly;
- cmCAEnabler NamelinkSkip;
- cmCAString Type;
+ std::string Destination;
+ std::string Component;
+ std::string NamelinkComponent;
+ bool ExcludeFromAll = false;
+ std::string Rename;
+ std::vector<std::string> Permissions;
+ std::vector<std::string> Configurations;
+ bool Optional = false;
+ bool NamelinkOnly = false;
+ bool NamelinkSkip = false;
+ std::string Type;
std::string DestinationString;
std::string PermissionsString;
- cmInstallCommandArguments* GenericArguments;
+ cmInstallCommandArguments* GenericArguments = nullptr;
static const char* PermissionsTable[];
static const std::string EmptyString;
std::string DefaultComponentName;
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index 47b9785..73a37cb 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -202,7 +202,7 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
os << indentNN << "file(GLOB OLD_CONFIG_FILES \"" << installedDir
<< this->EFGen->GetConfigImportFileGlob() << "\")\n";
os << indentNN << "if(OLD_CONFIG_FILES)\n";
- os << indentNNN << "message(STATUS \"Old export file \\\"" << installedFile
+ os << indentNNN << R"(message(STATUS "Old export file \")" << installedFile
<< "\\\" will be replaced. Removing files [${OLD_CONFIG_FILES}].\")\n";
os << indentNNN << "file(REMOVE ${OLD_CONFIG_FILES})\n";
os << indentNN << "endif()\n";
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index bb4eb3e..2ffca30 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -142,7 +142,7 @@ void cmInstallGenerator::AddInstallRule(
std::string cmInstallGenerator::CreateComponentTest(const char* component,
bool exclude_from_all)
{
- std::string result = "\"x${CMAKE_INSTALL_COMPONENT}x\" STREQUAL \"x";
+ std::string result = R"("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "x)";
result += component;
result += "x\"";
if (!exclude_from_all) {
diff --git a/Source/cmInstallTargetsCommand.cxx b/Source/cmInstallTargetsCommand.cxx
index d721ca0..7e67d4e 100644
--- a/Source/cmInstallTargetsCommand.cxx
+++ b/Source/cmInstallTargetsCommand.cxx
@@ -40,8 +40,8 @@ bool cmInstallTargetsCommand::InitialPass(std::vector<std::string> const& args,
} else {
cmTargets::iterator ti = tgts.find(*s);
if (ti != tgts.end()) {
- ti->second.SetInstallPath(args[0].c_str());
- ti->second.SetRuntimeInstallPath(runtime_dir.c_str());
+ ti->second.SetInstallPath(args[0]);
+ ti->second.SetRuntimeInstallPath(runtime_dir);
ti->second.SetHaveInstallRule(true);
} else {
std::string str = "Cannot find target: \"" + *s + "\" to install.";
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index cd71518..69751b6 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -33,7 +33,7 @@ public:
this->info.CAPI = &cmStaticCAPI;
}
- ///! clean up any memory allocated by the plugin
+ //! clean up any memory allocated by the plugin
~cmLoadedCommand() override;
/**
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index a14fd7d..67763d4 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -457,7 +457,7 @@ void cmLocalGenerator::GenerateInstallRules()
<< "if(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
<< " set(CMAKE_INSTALL_PREFIX \"" << prefix << "\")" << std::endl
<< "endif()" << std::endl
- << "string(REGEX REPLACE \"/$\" \"\" CMAKE_INSTALL_PREFIX "
+ << R"(string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX )"
<< "\"${CMAKE_INSTALL_PREFIX}\")" << std::endl
<< std::endl;
@@ -934,10 +934,8 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
// Implicit include directories
std::vector<std::string> implicitDirs;
std::set<std::string> implicitSet;
- // Checks if this is not an implicit include directory
- auto notImplicit = [&implicitSet](std::string const& dir) {
- return (implicitSet.find(dir) == implicitSet.end());
- };
+ // Include directories to be excluded as if they were implicit.
+ std::set<std::string> implicitExclude;
{
// Raw list of implicit include directories
// Start with "standard" directories that we unconditionally add below.
@@ -975,7 +973,8 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
[](std::string const& d) {
return cmHasLiteralSuffix(d, "/usr/include");
}) != impDirVec.end()) {
- impDirVec.emplace_back("/usr/include");
+ // Only exclude this hard coded path for backwards compatibility.
+ implicitExclude.emplace("/usr/include");
}
for (std::string const& i : impDirVec) {
@@ -985,6 +984,12 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
}
}
+ // Checks if this is not an excluded (implicit) include directory.
+ auto notExcluded = [&implicitSet, &implicitExclude](std::string const& dir) {
+ return ((implicitSet.find(dir) == implicitSet.end()) &&
+ (implicitExclude.find(dir) == implicitExclude.end()));
+ };
+
// Get the target-specific include directories.
std::vector<BT<std::string>> userDirs =
target->GetIncludeDirectories(config, lang);
@@ -1001,7 +1006,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
cmSystemTools::ComparePath(udr.Value, topBinaryDir) ||
cmSystemTools::IsSubDirectory(udr.Value, topSourceDir) ||
cmSystemTools::IsSubDirectory(udr.Value, topBinaryDir)) {
- if (notImplicit(udr.Value)) {
+ if (notExcluded(udr.Value)) {
emitBT(udr);
}
}
@@ -1010,7 +1015,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
// Emit remaining non implicit user direcories.
for (BT<std::string> const& udr : userDirs) {
- if (notImplicit(udr.Value)) {
+ if (notExcluded(udr.Value)) {
emitBT(udr);
}
}
@@ -1029,7 +1034,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
if (!stripImplicitDirs) {
// Append implicit directories that were requested by the user only
for (BT<std::string> const& udr : userDirs) {
- if (!notImplicit(udr.Value)) {
+ if (implicitSet.find(udr.Value) != implicitSet.end()) {
emitBT(udr);
}
}
@@ -1253,6 +1258,10 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target,
// Add language-specific flags.
this->AddLanguageFlags(flags, target, lang, config);
+ if (target->IsIPOEnabled(lang, config)) {
+ this->AppendFeatureOptions(flags, lang, "IPO");
+ }
+
this->AddArchitectureFlags(flags, target, lang, config);
if (lang == "Fortran") {
@@ -1510,9 +1519,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
flagsVar += "_FLAGS";
this->AddConfigVariableFlags(flags, flagsVar, config);
- if (target->IsIPOEnabled(lang, config)) {
- this->AppendFeatureOptions(flags, lang, "IPO");
- }
+ // Placeholder for possible future per-target flags.
+ static_cast<void>(target);
}
void cmLocalGenerator::AddLanguageFlagsForLinking(
@@ -1529,6 +1537,10 @@ void cmLocalGenerator::AddLanguageFlagsForLinking(
}
this->AddLanguageFlags(flags, target, lang, config);
+
+ if (target->IsIPOEnabled(lang, config)) {
+ this->AppendFeatureOptions(flags, lang, "IPO");
+ }
}
cmGeneratorTarget* cmLocalGenerator::FindGeneratorTargetToUse(
@@ -2261,7 +2273,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
def += define.substr(0, eq);
if (eq != std::string::npos) {
def += "=";
- def += this->EscapeForShell(define.c_str() + eq + 1, true);
+ def += this->EscapeForShell(define.substr(eq + 1), true);
}
}
definesString += itemSeparator;
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index de12190..67e3c58 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -76,13 +76,13 @@ public:
bool IsRootMakefile() const;
- ///! Get the makefile for this generator
+ //! Get the makefile for this generator
cmMakefile* GetMakefile() { return this->Makefile; }
- ///! Get the makefile for this generator, const version
+ //! Get the makefile for this generator, const version
const cmMakefile* GetMakefile() const { return this->Makefile; }
- ///! Get the GlobalGenerator this is associated with
+ //! Get the GlobalGenerator this is associated with
cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; }
const cmGlobalGenerator* GetGlobalGenerator() const
{
@@ -118,7 +118,7 @@ public:
void AddCompilerRequirementFlag(std::string& flags,
cmGeneratorTarget const* target,
const std::string& lang);
- ///! Append flags to a string.
+ //! Append flags to a string.
virtual void AppendFlags(std::string& flags,
const std::string& newFlags) const;
virtual void AppendFlags(std::string& flags, const char* newFlags) const;
@@ -131,7 +131,7 @@ public:
cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
- ///! Get the include flags for the current makefile and language
+ //! Get the include flags for the current makefile and language
std::string GetIncludeFlags(const std::vector<std::string>& includes,
cmGeneratorTarget* target,
const std::string& lang,
@@ -403,7 +403,7 @@ public:
const std::string& prop);
protected:
- ///! put all the libraries for a target on into the given stream
+ //! put all the libraries for a target on into the given stream
void OutputLinkLibraries(cmComputeLinkInformation* pcli,
cmLinkLineComputer* linkLineComputer,
std::string& linkLibraries,
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index f3d5a94..bece12e 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -11,6 +11,7 @@
#include <utility>
#include "cmAlgorithms.h"
+#include "cmCustomCommand.h" // IWYU pragma: keep
#include "cmCustomCommandGenerator.h"
#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
@@ -1312,7 +1313,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
// The build.make file may have explicit dependencies for the object
// files but these will not affect the scanning process so they need
// not be considered.
- std::map<std::string, cmDepends::DependencyVector> validDependencies;
+ cmDepends::DependencyMap validDependencies;
bool needRescanDependencies = false;
if (!needRescanDirInfo) {
cmDependsC checker;
@@ -1352,8 +1353,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
bool cmLocalUnixMakefileGenerator3::ScanDependencies(
std::string const& targetDir, std::string const& dependFile,
- std::string const& internalDependFile,
- std::map<std::string, cmDepends::DependencyVector>& validDeps)
+ std::string const& internalDependFile, cmDepends::DependencyMap& validDeps)
{
// Read the directory information file.
cmMakefile* mf = this->Makefile;
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index ba882da..7a0ea98 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -143,8 +143,7 @@ public:
// File pairs for implicit dependency scanning. The key of the map
// is the depender and the value is the explicit dependee.
- struct ImplicitDependFileMap
- : public std::map<std::string, cmDepends::DependencyVector>
+ struct ImplicitDependFileMap : public cmDepends::DependencyMap
{
};
struct ImplicitDependLanguageMap
@@ -230,10 +229,10 @@ protected:
const char* filename = nullptr);
// Helper methods for dependency updates.
- bool ScanDependencies(
- std::string const& targetDir, std::string const& dependFile,
- std::string const& internalDependFile,
- std::map<std::string, cmDepends::DependencyVector>& validDeps);
+ bool ScanDependencies(std::string const& targetDir,
+ std::string const& dependFile,
+ std::string const& internalDependFile,
+ cmDepends::DependencyMap& validDeps);
void CheckMultipleOutputs(bool verbose);
private:
diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h
index a4150b9..5c6400e 100644
--- a/Source/cmLocalVisualStudio10Generator.h
+++ b/Source/cmLocalVisualStudio10Generator.h
@@ -21,7 +21,7 @@ class cmMakefile;
class cmLocalVisualStudio10Generator : public cmLocalVisualStudio7Generator
{
public:
- ///! Set cache only and recurse to false by default.
+ //! Set cache only and recurse to false by default.
cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalVisualStudio10Generator();
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index a497308..7ba3471 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudio7Generator.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalVisualStudio7Generator.h"
@@ -661,14 +662,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
langForClCompile = linkLanguage;
if (langForClCompile == "C" || langForClCompile == "CXX" ||
langForClCompile == "Fortran") {
- std::string baseFlagVar = "CMAKE_";
- baseFlagVar += langForClCompile;
- baseFlagVar += "_FLAGS";
- flags = this->Makefile->GetRequiredDefinition(baseFlagVar);
- std::string flagVar =
- baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
- flags += " ";
- flags += this->Makefile->GetRequiredDefinition(flagVar);
+ this->AddLanguageFlags(flags, target, langForClCompile, configName);
}
// set the correct language
if (linkLanguage == "C") {
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index b093e6f..ce8eceb 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -43,7 +43,7 @@ public:
class cmLocalVisualStudio7Generator : public cmLocalVisualStudioGenerator
{
public:
- ///! Set cache only and recurse to false by default.
+ //! Set cache only and recurse to false by default.
cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalVisualStudio7Generator();
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 660729c..f3f2042 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudioGenerator.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index 5c22dcf..42de20b 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -24,7 +24,7 @@ class cmSourceFile;
class cmLocalXCodeGenerator : public cmLocalGenerator
{
public:
- ///! Set cache only and recurse to false by default.
+ //! Set cache only and recurse to false by default.
cmLocalXCodeGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
~cmLocalXCodeGenerator() override;
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 88b4c2f..8cc14f3 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -257,7 +257,7 @@ public:
* can be used in CMake to refer to lists, directories, etc.
*/
void AddDefinition(const std::string& name, const char* value);
- ///! Add a definition to this makefile and the global cmake cache.
+ //! Add a definition to this makefile and the global cmake cache.
void AddCacheDefinition(const std::string& name, const char* value,
const char* doc, cmStateEnums::CacheEntryType type,
bool force = false);
@@ -272,7 +272,7 @@ public:
* for cache entries, and will only affect the current makefile.
*/
void RemoveDefinition(const std::string& name);
- ///! Remove a definition from the cache.
+ //! Remove a definition from the cache.
void RemoveCacheDefinition(const std::string& name);
/**
@@ -548,7 +548,7 @@ public:
{
return this->ListFiles;
}
- ///! When the file changes cmake will be re-run from the build system.
+ //! When the file changes cmake will be re-run from the build system.
void AddCMakeDependFile(const std::string& file)
{
this->ListFiles.push_back(file);
@@ -626,7 +626,7 @@ public:
bool ExecuteCommand(const cmListFileFunction& lff,
cmExecutionStatus& status);
- ///! Enable support for named language, if nil then all languages are
+ //! Enable support for named language, if nil then all languages are
/// enabled.
void EnableLanguage(std::vector<std::string> const& languages,
bool optional);
@@ -641,7 +641,7 @@ public:
cmVariableWatch* GetVariableWatch() const;
#endif
- ///! Display progress or status message.
+ //! Display progress or status message.
void DisplayStatus(const std::string&, float) const;
/**
@@ -677,7 +677,7 @@ public:
*/
cmSourceFile* GetSourceFileWithOutput(const std::string& outName) const;
- ///! Add a new cmTest to the list of tests for this makefile.
+ //! Add a new cmTest to the list of tests for this makefile.
cmTest* CreateTest(const std::string& testName);
/** Get a cmTest pointer for a given test name, if the name is
@@ -701,7 +701,7 @@ public:
std::string GetModulesFile(const std::string& name, bool& system) const;
- ///! Set/Get a property of this directory
+ //! Set/Get a property of this directory
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
@@ -710,7 +710,7 @@ public:
bool GetPropertyAsBool(const std::string& prop) const;
std::vector<std::string> GetPropertyKeys() const;
- ///! Initialize a makefile from its parent
+ //! Initialize a makefile from its parent
void InitializeFromParent(cmMakefile* parent);
void AddInstallGenerator(cmInstallGenerator* g)
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index b38d410..3300fef 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -12,6 +12,7 @@
#include <utility>
#include "cmAlgorithms.h"
+#include "cmCustomCommand.h" // IWYU pragma: keep
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
@@ -32,8 +33,6 @@
#include "cmStateTypes.h"
#include "cmSystemTools.h"
-class cmCustomCommand;
-
cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
cmGeneratorTarget* target)
: cmNinjaTargetGenerator(target)
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index 6438c7b..deca767 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -27,7 +27,7 @@ public:
std::string ConvertDirectorySeparatorsForShell(
const std::string& source) const;
- ///! for existing files convert to output path and short path if spaces
+ //! for existing files convert to output path and short path if spaces
std::string ConvertToOutputForExisting(const std::string& remote,
OutputFormat format = SHELL) const;
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index ab8d103..5213432 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -8,10 +8,12 @@
#include <utility>
#include "cmAlgorithms.h"
+#include "cmArgumentParser.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmRange.h"
#include "cmSystemTools.h"
+#include "cm_string_view.hxx"
class cmExecutionStatus;
@@ -28,42 +30,43 @@ static std::string EscapeArg(const std::string& arg)
return escapedArg;
}
-namespace {
-enum insideValues
+static std::string JoinList(std::vector<std::string> const& arg, bool escape)
{
- NONE,
- SINGLE,
- MULTI
-};
+ return escape ? cmJoin(cmMakeRange(arg).transform(EscapeArg), ";")
+ : cmJoin(cmMakeRange(arg), ";");
+}
+
+namespace {
typedef std::map<std::string, bool> options_map;
typedef std::map<std::string, std::string> single_map;
typedef std::map<std::string, std::vector<std::string>> multi_map;
typedef std::set<std::string> options_set;
-}
-// function to be called every time, a new key word was parsed or all
-// parameters where parsed.
-static void DetectKeywordsMissingValues(insideValues currentState,
- const std::string& currentArgName,
- int& argumentsFound,
- options_set& keywordsMissingValues)
+struct UserArgumentParser : public cmArgumentParser<void>
{
- if (currentState == SINGLE ||
- (currentState == MULTI && argumentsFound == 0)) {
- keywordsMissingValues.insert(currentArgName);
+ template <typename T, typename H>
+ void Bind(std::vector<std::string> const& names,
+ std::map<std::string, T>& ref, H duplicateKey)
+ {
+ for (std::string const& key : names) {
+ auto const it = ref.emplace(key, T{}).first;
+ bool const inserted = this->cmArgumentParser<void>::Bind(
+ cm::string_view(it->first), it->second);
+ if (!inserted) {
+ duplicateKey(key);
+ }
+ }
}
+};
- argumentsFound = 0;
-}
+} // namespace
-static void PassParsedArguments(const std::string& prefix,
- cmMakefile& makefile,
- const options_map& options,
- const single_map& singleValArgs,
- const multi_map& multiValArgs,
- const std::vector<std::string>& unparsed,
- const options_set& keywordsMissingValues)
+static void PassParsedArguments(
+ const std::string& prefix, cmMakefile& makefile, const options_map& options,
+ const single_map& singleValArgs, const multi_map& multiValArgs,
+ const std::vector<std::string>& unparsed,
+ const options_set& keywordsMissingValues, bool parseFromArgV)
{
for (auto const& iter : options) {
makefile.AddDefinition(prefix + iter.first,
@@ -81,7 +84,7 @@ static void PassParsedArguments(const std::string& prefix,
for (auto const& iter : multiValArgs) {
if (!iter.second.empty()) {
makefile.AddDefinition(prefix + iter.first,
- cmJoin(cmMakeRange(iter.second), ";").c_str());
+ JoinList(iter.second, parseFromArgV).c_str());
} else {
makefile.RemoveDefinition(prefix + iter.first);
}
@@ -89,7 +92,7 @@ static void PassParsedArguments(const std::string& prefix,
if (!unparsed.empty()) {
makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS",
- cmJoin(cmMakeRange(unparsed), ";").c_str());
+ JoinList(unparsed, parseFromArgV).c_str());
} else {
makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
}
@@ -141,6 +144,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
// the first argument is the prefix
const std::string prefix = (*argIter++) + "_";
+ UserArgumentParser parser;
+
// define the result maps holding key/value pairs for
// options, single values and multi values
options_map options;
@@ -150,45 +155,25 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
// anything else is put into a vector of unparsed strings
std::vector<std::string> unparsed;
- // remember already defined keywords
- std::set<std::string> used_keywords;
- const std::string dup_warning = "keyword defined more than once: ";
+ auto const duplicateKey = [this](std::string const& key) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::WARNING, "keyword defined more than once: " + key);
+ };
// the second argument is a (cmake) list of options without argument
std::vector<std::string> list;
cmSystemTools::ExpandListArgument(*argIter++, list);
- for (std::string const& iter : list) {
- if (!used_keywords.insert(iter).second) {
- this->GetMakefile()->IssueMessage(MessageType::WARNING,
- dup_warning + iter);
- }
- options[iter]; // default initialize
- }
+ parser.Bind(list, options, duplicateKey);
// the third argument is a (cmake) list of single argument options
list.clear();
cmSystemTools::ExpandListArgument(*argIter++, list);
- for (std::string const& iter : list) {
- if (!used_keywords.insert(iter).second) {
- this->GetMakefile()->IssueMessage(MessageType::WARNING,
- dup_warning + iter);
- }
- singleValArgs[iter]; // default initialize
- }
+ parser.Bind(list, singleValArgs, duplicateKey);
// the fourth argument is a (cmake) list of multi argument options
list.clear();
cmSystemTools::ExpandListArgument(*argIter++, list);
- for (std::string const& iter : list) {
- if (!used_keywords.insert(iter).second) {
- this->GetMakefile()->IssueMessage(MessageType::WARNING,
- dup_warning + iter);
- }
- multiValArgs[iter]; // default initialize
- }
-
- insideValues insideValues = NONE;
- std::string currentArgName;
+ parser.Bind(list, multiValArgs, duplicateKey);
list.clear();
if (!parseFromArgV) {
@@ -223,68 +208,14 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
}
}
- options_set keywordsMissingValues;
- int multiArgumentsFound = 0;
-
- // iterate over the arguments list and fill in the values where applicable
- for (std::string const& arg : list) {
- const options_map::iterator optIter = options.find(arg);
- if (optIter != options.end()) {
- DetectKeywordsMissingValues(insideValues, currentArgName,
- multiArgumentsFound, keywordsMissingValues);
- insideValues = NONE;
- optIter->second = true;
- continue;
- }
-
- const single_map::iterator singleIter = singleValArgs.find(arg);
- if (singleIter != singleValArgs.end()) {
- DetectKeywordsMissingValues(insideValues, currentArgName,
- multiArgumentsFound, keywordsMissingValues);
- insideValues = SINGLE;
- currentArgName = arg;
- continue;
- }
-
- const multi_map::iterator multiIter = multiValArgs.find(arg);
- if (multiIter != multiValArgs.end()) {
- DetectKeywordsMissingValues(insideValues, currentArgName,
- multiArgumentsFound, keywordsMissingValues);
- insideValues = MULTI;
- currentArgName = arg;
- continue;
- }
-
- switch (insideValues) {
- case SINGLE:
- singleValArgs[currentArgName] = arg;
- insideValues = NONE;
- break;
- case MULTI:
- ++multiArgumentsFound;
- if (parseFromArgV) {
- multiValArgs[currentArgName].push_back(EscapeArg(arg));
- } else {
- multiValArgs[currentArgName].push_back(arg);
- }
- break;
- default:
- multiArgumentsFound = 0;
-
- if (parseFromArgV) {
- unparsed.push_back(EscapeArg(arg));
- } else {
- unparsed.push_back(arg);
- }
- break;
- }
- }
+ std::vector<std::string> keywordsMissingValues;
- DetectKeywordsMissingValues(insideValues, currentArgName,
- multiArgumentsFound, keywordsMissingValues);
+ parser.Parse(list, &unparsed, &keywordsMissingValues);
- PassParsedArguments(prefix, *this->Makefile, options, singleValArgs,
- multiValArgs, unparsed, keywordsMissingValues);
+ PassParsedArguments(
+ prefix, *this->Makefile, options, singleValArgs, multiValArgs, unparsed,
+ options_set(keywordsMissingValues.begin(), keywordsMissingValues.end()),
+ parseFromArgV);
return true;
}
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 0a234c5..ec40136 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -145,7 +145,7 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
} else {
std::ostringstream e;
e << defaultVar << " has value \"" << defaultValue
- << "\" but must be \"OLD\", \"NEW\", or \"\" (empty).";
+ << R"(" but must be "OLD", "NEW", or "" (empty).)";
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
@@ -299,7 +299,7 @@ bool cmPolicies::GetPolicyID(const char* id, cmPolicies::PolicyID& pid)
return stringToId(id, pid);
}
-///! return a warning string for a given policy
+//! return a warning string for a given policy
std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id)
{
std::ostringstream msg;
@@ -333,7 +333,7 @@ std::string cmPolicies::GetPolicyDeprecatedWarning(cmPolicies::PolicyID id)
return msg.str();
}
-///! return an error string for when a required policy is unspecified
+//! return an error string for when a required policy is unspecified
std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
{
std::ostringstream error;
@@ -359,7 +359,7 @@ std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
return error.str();
}
-///! Get the default status for a policy
+//! Get the default status for a policy
cmPolicies::PolicyStatus cmPolicies::GetPolicyStatus(
cmPolicies::PolicyID /*unused*/)
{
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 7677186..02a6295 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -332,27 +332,27 @@ public:
CMPCOUNT
};
- ///! convert a string policy ID into a number
+ //! convert a string policy ID into a number
static bool GetPolicyID(const char* id, /* out */ cmPolicies::PolicyID& pid);
- ///! Get the default status for a policy
+ //! Get the default status for a policy
static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
- ///! Set a policy level for this listfile
+ //! Set a policy level for this listfile
static bool ApplyPolicyVersion(cmMakefile* mf,
std::string const& version_min,
std::string const& version_max);
static bool ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
unsigned int minorVer, unsigned int patchVer);
- ///! return a warning string for a given policy
+ //! return a warning string for a given policy
static std::string GetPolicyWarning(cmPolicies::PolicyID id);
static std::string GetPolicyDeprecatedWarning(cmPolicies::PolicyID id);
- ///! return an error string for when a required policy is unspecified
+ //! return an error string for when a required policy is unspecified
static std::string GetRequiredPolicyError(cmPolicies::PolicyID id);
- ///! return an error string for when a required policy is unspecified
+ //! return an error string for when a required policy is unspecified
static std::string GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id);
/** Represent a set of policy values. */
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 2fe9fe8..8615ecc 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -25,6 +25,10 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
+ if (!this->IncludeByVariable("CMAKE_PROJECT_INCLUDE_BEFORE")) {
+ return false;
+ }
+
std::string const& projectName = args[0];
this->Makefile->SetProjectName(projectName);
@@ -214,7 +218,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
}
cmsys::RegularExpression vx(
- "^([0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[0-9]+)?)?)?)?$");
+ R"(^([0-9]+(\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?)?)?$)");
if (!vx.find(version)) {
std::string e = "VERSION \"" + version + "\" format invalid.";
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
@@ -319,21 +323,41 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
languages.emplace_back("CXX");
}
this->Makefile->EnableLanguage(languages, false);
- std::string extraInclude = "CMAKE_PROJECT_" + projectName + "_INCLUDE";
- const char* include = this->Makefile->GetDefinition(extraInclude);
- if (include) {
- bool readit = this->Makefile->ReadDependentFile(include);
- if (!readit && !cmSystemTools::GetFatalErrorOccured()) {
- std::string m = "could not find file:\n"
- " ";
- m += include;
- this->SetError(m);
- return false;
- }
+
+ if (!this->IncludeByVariable("CMAKE_PROJECT_INCLUDE")) {
+ return false;
}
+
+ if (!this->IncludeByVariable("CMAKE_PROJECT_" + projectName + "_INCLUDE")) {
+ return false;
+ }
+
return true;
}
+bool cmProjectCommand::IncludeByVariable(const std::string& variable)
+{
+ const char* include = this->Makefile->GetDefinition(variable);
+ if (!include) {
+ return true;
+ }
+
+ const bool readit = this->Makefile->ReadDependentFile(include);
+ if (readit) {
+ return true;
+ }
+
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return true;
+ }
+
+ std::string m = "could not find file:\n"
+ " ";
+ m += include;
+ this->SetError(m);
+ return false;
+}
+
void cmProjectCommand::TopLevelCMakeVarCondSet(const char* const name,
const char* const value)
{
diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h
index 365d448..f1d03e7 100644
--- a/Source/cmProjectCommand.h
+++ b/Source/cmProjectCommand.h
@@ -36,6 +36,7 @@ public:
cmExecutionStatus& status) override;
private:
+ bool IncludeByVariable(const std::string& variable);
void TopLevelCMakeVarCondSet(const char* name, const char* value);
};
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 87ef112..9918c35 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -1,9 +1,12 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQtAutoGen.h"
+
#include "cmAlgorithms.h"
+#include "cmDuration.h"
+#include "cmProcessOutput.h"
#include "cmSystemTools.h"
-
+#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
@@ -73,44 +76,44 @@ void MergeOptions(std::vector<std::string>& baseOpts,
unsigned int const cmQtAutoGen::ParallelMax = 64;
std::string const cmQtAutoGen::ListSep = "<<<S>>>";
-std::string const cmQtAutoGen::GenAutoGen = "AutoGen";
-std::string const cmQtAutoGen::GenAutoMoc = "AutoMoc";
-std::string const cmQtAutoGen::GenAutoUic = "AutoUic";
-std::string const cmQtAutoGen::GenAutoRcc = "AutoRcc";
-
-std::string const cmQtAutoGen::GenAUTOGEN = "AUTOGEN";
-std::string const cmQtAutoGen::GenAUTOMOC = "AUTOMOC";
-std::string const cmQtAutoGen::GenAUTOUIC = "AUTOUIC";
-std::string const cmQtAutoGen::GenAUTORCC = "AUTORCC";
-
std::string const& cmQtAutoGen::GeneratorName(GenT genType)
{
+ static const std::string AutoGen("AutoGen");
+ static const std::string AutoMoc("AutoMoc");
+ static const std::string AutoUic("AutoUic");
+ static const std::string AutoRcc("AutoRcc");
+
switch (genType) {
case GenT::GEN:
- return GenAutoGen;
+ return AutoGen;
case GenT::MOC:
- return GenAutoMoc;
+ return AutoMoc;
case GenT::UIC:
- return GenAutoUic;
+ return AutoUic;
case GenT::RCC:
- return GenAutoRcc;
+ return AutoRcc;
}
- return GenAutoGen;
+ return AutoGen;
}
std::string const& cmQtAutoGen::GeneratorNameUpper(GenT genType)
{
+ static const std::string AUTOGEN("AUTOGEN");
+ static const std::string AUTOMOC("AUTOMOC");
+ static const std::string AUTOUIC("AUTOUIC");
+ static const std::string AUTORCC("AUTORCC");
+
switch (genType) {
case GenT::GEN:
- return GenAUTOGEN;
+ return AUTOGEN;
case GenT::MOC:
- return GenAUTOMOC;
+ return AUTOMOC;
case GenT::UIC:
- return GenAUTOUIC;
+ return AUTOUIC;
case GenT::RCC:
- return GenAUTORCC;
+ return AUTORCC;
}
- return GenAUTOGEN;
+ return AUTOGEN;
}
std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc)
@@ -118,13 +121,13 @@ std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc)
std::string res;
std::vector<std::string> lst;
if (moc) {
- lst.emplace_back(GenAUTOMOC);
+ lst.emplace_back("AUTOMOC");
}
if (uic) {
- lst.emplace_back(GenAUTOUIC);
+ lst.emplace_back("AUTOUIC");
}
if (rcc) {
- lst.emplace_back(GenAUTORCC);
+ lst.emplace_back("AUTORCC");
}
switch (lst.size()) {
case 1:
@@ -237,8 +240,8 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
}
-void cmQtAutoGen::RccListParseContent(std::string const& content,
- std::vector<std::string>& files)
+static void RccListParseContent(std::string const& content,
+ std::vector<std::string>& files)
{
cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
@@ -255,10 +258,10 @@ void cmQtAutoGen::RccListParseContent(std::string const& content,
}
}
-bool cmQtAutoGen::RccListParseOutput(std::string const& rccStdOut,
- std::string const& rccStdErr,
- std::vector<std::string>& files,
- std::string& error)
+static bool RccListParseOutput(std::string const& rccStdOut,
+ std::string const& rccStdErr,
+ std::vector<std::string>& files,
+ std::string& error)
{
// Lambda to strip CR characters
auto StripCR = [](std::string& line) {
@@ -305,11 +308,104 @@ bool cmQtAutoGen::RccListParseOutput(std::string const& rccStdOut,
return true;
}
-void cmQtAutoGen::RccListConvertFullPath(std::string const& qrcFileDir,
- std::vector<std::string>& files)
+cmQtAutoGen::RccLister::RccLister() = default;
+
+cmQtAutoGen::RccLister::RccLister(std::string rccExecutable,
+ std::vector<std::string> listOptions)
+ : RccExcutable_(std::move(rccExecutable))
+ , ListOptions_(std::move(listOptions))
{
+}
+
+bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
+ std::vector<std::string>& files,
+ std::string& error, bool verbose) const
+{
+ error.clear();
+
+ if (!cmSystemTools::FileExists(qrcFile, true)) {
+ error = "The resource file ";
+ error += Quoted(qrcFile);
+ error += " does not exist.";
+ return false;
+ }
+
+ // Run rcc list command in the directory of the qrc file with the pathless
+ // qrc file name argument. This way rcc prints relative paths.
+ // This avoids issues on Windows when the qrc file is in a path that
+ // contains non-ASCII characters.
+ std::string const fileDir = cmSystemTools::GetFilenamePath(qrcFile);
+
+ if (!this->RccExcutable_.empty() &&
+ cmSystemTools::FileExists(this->RccExcutable_, true) &&
+ !this->ListOptions_.empty()) {
+
+ bool result = false;
+ int retVal = 0;
+ std::string rccStdOut;
+ std::string rccStdErr;
+ {
+ std::vector<std::string> cmd;
+ cmd.emplace_back(this->RccExcutable_);
+ cmd.insert(cmd.end(), this->ListOptions_.begin(),
+ this->ListOptions_.end());
+ cmd.emplace_back(cmSystemTools::GetFilenameName(qrcFile));
+
+ // Log command
+ if (verbose) {
+ std::string msg = "Running command:\n";
+ msg += QuotedCommand(cmd);
+ msg += '\n';
+ cmSystemTools::Stdout(msg);
+ }
+
+ result = cmSystemTools::RunSingleCommand(
+ cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
+ }
+ if (!result || retVal) {
+ error = "The rcc list process failed for ";
+ error += Quoted(qrcFile);
+ error += "\n";
+ if (!rccStdOut.empty()) {
+ error += rccStdOut;
+ error += "\n";
+ }
+ if (!rccStdErr.empty()) {
+ error += rccStdErr;
+ error += "\n";
+ }
+ return false;
+ }
+ if (!RccListParseOutput(rccStdOut, rccStdErr, files, error)) {
+ return false;
+ }
+ } else {
+ // We can't use rcc for the file listing.
+ // Read the qrc file content into string and parse it.
+ {
+ std::string qrcContents;
+ {
+ cmsys::ifstream ifs(qrcFile.c_str());
+ if (ifs) {
+ std::ostringstream osst;
+ osst << ifs.rdbuf();
+ qrcContents = osst.str();
+ } else {
+ error = "The resource file ";
+ error += Quoted(qrcFile);
+ error += " is not readable\n";
+ return false;
+ }
+ }
+ // Parse string content
+ RccListParseContent(qrcContents, files);
+ }
+ }
+
+ // Convert relative paths to absolute paths
for (std::string& entry : files) {
- std::string tmp = cmSystemTools::CollapseFullPath(entry, qrcFileDir);
- entry = std::move(tmp);
+ entry = cmSystemTools::CollapseFullPath(entry, fileDir);
}
+ return true;
}
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index 6cc8df1..3a346b5 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -51,15 +51,6 @@ public:
/// @brief Nested lists separator
static std::string const ListSep;
- // Generator names
- static std::string const GenAutoGen;
- static std::string const GenAutoMoc;
- static std::string const GenAutoUic;
- static std::string const GenAutoRcc;
- static std::string const GenAUTOGEN;
- static std::string const GenAUTOMOC;
- static std::string const GenAUTOUIC;
- static std::string const GenAUTORCC;
/// @brief Maximum number of parallel threads/processes in a generator
static unsigned int const ParallelMax;
@@ -94,21 +85,44 @@ public:
std::vector<std::string> const& newOpts,
bool isQt5);
- /// @brief Parses the content of a qrc file
- ///
- /// Use when rcc does not support the "--list" option
- static void RccListParseContent(std::string const& content,
- std::vector<std::string>& files);
-
- /// @brief Parses the output of the "rcc --list ..." command
- static bool RccListParseOutput(std::string const& rccStdOut,
- std::string const& rccStdErr,
- std::vector<std::string>& files,
- std::string& error);
-
- /// @brief Converts relative qrc entry paths to full paths
- static void RccListConvertFullPath(std::string const& qrcFileDir,
- std::vector<std::string>& files);
+ /** @class RccLister
+ * @brief Lists files in qrc resource files
+ */
+ class RccLister
+ {
+ public:
+ RccLister();
+ RccLister(std::string rccExecutable, std::vector<std::string> listOptions);
+
+ //! The rcc executable
+ std::string const& RccExcutable() const { return RccExcutable_; }
+ void SetRccExecutable(std::string const& rccExecutable)
+ {
+ RccExcutable_ = rccExecutable;
+ }
+
+ //! The rcc executable list options
+ std::vector<std::string> const& ListOptions() const
+ {
+ return ListOptions_;
+ }
+ void SetListOptions(std::vector<std::string> const& listOptions)
+ {
+ ListOptions_ = listOptions;
+ }
+
+ /**
+ * @brief Lists a files in the qrcFile
+ * @arg files The file names are appended to this list
+ * @arg error contains the error message when the function fails
+ */
+ bool list(std::string const& qrcFile, std::vector<std::string>& files,
+ std::string& error, bool verbose = false) const;
+
+ private:
+ std::string RccExcutable_;
+ std::vector<std::string> ListOptions_;
+ };
};
#endif
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index 7bd0e52..59e17d7 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -20,6 +20,24 @@
#include <memory>
#include <utility>
+cmQtAutoGenGlobalInitializer::Keywords::Keywords()
+ : AUTOMOC("AUTOMOC")
+ , AUTOUIC("AUTOUIC")
+ , AUTORCC("AUTORCC")
+ , AUTOMOC_EXECUTABLE("AUTOMOC_EXECUTABLE")
+ , AUTOUIC_EXECUTABLE("AUTOUIC_EXECUTABLE")
+ , AUTORCC_EXECUTABLE("AUTORCC_EXECUTABLE")
+ , SKIP_AUTOGEN("SKIP_AUTOGEN")
+ , SKIP_AUTOMOC("SKIP_AUTOMOC")
+ , SKIP_AUTOUIC("SKIP_AUTOUIC")
+ , SKIP_AUTORCC("SKIP_AUTORCC")
+ , AUTOUIC_OPTIONS("AUTOUIC_OPTIONS")
+ , AUTORCC_OPTIONS("AUTORCC_OPTIONS")
+ , qrc("qrc")
+ , ui("ui")
+{
+}
+
cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
std::vector<cmLocalGenerator*> const& localGenerators)
{
@@ -74,16 +92,16 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
continue;
}
- bool const moc = target->GetPropertyAsBool(cmQtAutoGen::GenAUTOMOC);
- bool const uic = target->GetPropertyAsBool(cmQtAutoGen::GenAUTOUIC);
- bool const rcc = target->GetPropertyAsBool(cmQtAutoGen::GenAUTORCC);
+ bool const moc = target->GetPropertyAsBool(kw().AUTOMOC);
+ bool const uic = target->GetPropertyAsBool(kw().AUTOUIC);
+ bool const rcc = target->GetPropertyAsBool(kw().AUTORCC);
if (moc || uic || rcc) {
std::string const mocExec =
- target->GetSafeProperty("AUTOMOC_EXECUTABLE");
+ target->GetSafeProperty(kw().AUTOMOC_EXECUTABLE);
std::string const uicExec =
- target->GetSafeProperty("AUTOUIC_EXECUTABLE");
+ target->GetSafeProperty(kw().AUTOUIC_EXECUTABLE);
std::string const rccExec =
- target->GetSafeProperty("AUTORCC_EXECUTABLE");
+ target->GetSafeProperty(kw().AUTORCC_EXECUTABLE);
// We support Qt4, Qt5 and Qt6
auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target);
diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h
index 74184a0..77429b7 100644
--- a/Source/cmQtAutoGenGlobalInitializer.h
+++ b/Source/cmQtAutoGenGlobalInitializer.h
@@ -18,10 +18,39 @@ class cmQtAutoGenInitializer;
class cmQtAutoGenGlobalInitializer
{
public:
+ /// @brief Collection of QtAutogen related keywords
+ class Keywords
+ {
+ public:
+ Keywords();
+
+ std::string AUTOMOC;
+ std::string AUTOUIC;
+ std::string AUTORCC;
+
+ std::string AUTOMOC_EXECUTABLE;
+ std::string AUTOUIC_EXECUTABLE;
+ std::string AUTORCC_EXECUTABLE;
+
+ std::string SKIP_AUTOGEN;
+ std::string SKIP_AUTOMOC;
+ std::string SKIP_AUTOUIC;
+ std::string SKIP_AUTORCC;
+
+ std::string AUTOUIC_OPTIONS;
+ std::string AUTORCC_OPTIONS;
+
+ std::string qrc;
+ std::string ui;
+ };
+
+public:
cmQtAutoGenGlobalInitializer(
std::vector<cmLocalGenerator*> const& localGenerators);
~cmQtAutoGenGlobalInitializer();
+ Keywords const& kw() const { return Keywords_; };
+
bool generate();
private:
@@ -48,6 +77,7 @@ private:
std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_;
std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_;
std::unordered_map<std::string, std::string> ExecutableTestOutputs_;
+ Keywords const Keywords_;
};
#endif
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index ef8fe73..be96f1a 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -7,7 +7,6 @@
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
-#include "cmDuration.h"
#include "cmFilePathChecksum.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -19,7 +18,6 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProcessOutput.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmSourceGroup.h"
@@ -28,7 +26,6 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
-#include "cmsys/FStream.hxx"
#include "cmsys/SystemInformation.hxx"
#include <algorithm>
@@ -36,7 +33,6 @@
#include <deque>
#include <map>
#include <set>
-#include <sstream>
#include <string>
#include <utility>
#include <vector>
@@ -606,28 +602,19 @@ bool cmQtAutoGenInitializer::InitRcc()
bool cmQtAutoGenInitializer::InitScanFiles()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
+ auto const& kw = this->GlobalInitializer->kw();
- // String constants
- std::string const SKIP_AUTOGEN_str = "SKIP_AUTOGEN";
- std::string const SKIP_AUTOMOC_str = "SKIP_AUTOMOC";
- std::string const SKIP_AUTOUIC_str = "SKIP_AUTOUIC";
- std::string const SKIP_AUTORCC_str = "SKIP_AUTORCC";
- std::string const AUTOUIC_OPTIONS_str = "AUTOUIC_OPTIONS";
- std::string const AUTORCC_OPTIONS_str = "AUTORCC_OPTIONS";
- std::string const qrc_str = "qrc";
- std::string const ui_str = "ui";
-
- auto makeMUFile = [&](cmSourceFile* sf, std::string const& fullPath,
- bool muIt) -> MUFileHandle {
+ auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath,
+ bool muIt) -> MUFileHandle {
MUFileHandle muf = cm::make_unique<MUFile>();
muf->RealPath = cmSystemTools::GetRealPath(fullPath);
muf->SF = sf;
muf->Generated = sf->GetIsGenerated();
- bool const skipAutogen = sf->GetPropertyAsBool(SKIP_AUTOGEN_str);
+ bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
muf->SkipMoc = this->Moc.Enabled &&
- (skipAutogen || sf->GetPropertyAsBool(SKIP_AUTOMOC_str));
+ (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOMOC));
muf->SkipUic = this->Uic.Enabled &&
- (skipAutogen || sf->GetPropertyAsBool(SKIP_AUTOUIC_str));
+ (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));
if (muIt) {
muf->MocIt = this->Moc.Enabled && !muf->SkipMoc;
muf->UicIt = this->Uic.Enabled && !muf->SkipUic;
@@ -678,8 +665,8 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Register rcc enabled files
if (this->Rcc.Enabled) {
- if ((ext == qrc_str) && !sf->GetPropertyAsBool(SKIP_AUTOGEN_str) &&
- !sf->GetPropertyAsBool(SKIP_AUTORCC_str)) {
+ if ((ext == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
+ !sf->GetPropertyAsBool(kw.SKIP_AUTORCC)) {
// Register qrc file
Qrc qrc;
qrc.QrcFile = cmSystemTools::GetRealPath(fullPath);
@@ -688,7 +675,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
qrc.Generated = sf->GetIsGenerated();
// RCC options
{
- std::string const opts = sf->GetSafeProperty(AUTORCC_OPTIONS_str);
+ std::string const opts = sf->GetSafeProperty(kw.AUTORCC_OPTIONS);
if (!opts.empty()) {
cmSystemTools::ExpandListArgument(opts, qrc.Options);
}
@@ -798,15 +785,15 @@ bool cmQtAutoGenInitializer::InitScanFiles()
this->AutogenTarget.Sources.emplace(sf, std::move(muf));
}
}
- } else if (this->Uic.Enabled && (ext == ui_str)) {
+ } else if (this->Uic.Enabled && (ext == kw.ui)) {
// .ui file
std::string realPath = cmSystemTools::GetRealPath(fullPath);
- bool const skipAutogen = sf->GetPropertyAsBool(SKIP_AUTOGEN_str);
+ bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
bool const skipUic =
- (skipAutogen || sf->GetPropertyAsBool(SKIP_AUTOUIC_str));
+ (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));
if (!skipUic) {
// Check if the .ui file has uic options
- std::string const uicOpts = sf->GetSafeProperty(AUTOUIC_OPTIONS_str);
+ std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
if (!uicOpts.empty()) {
this->Uic.FileFiles.push_back(std::move(realPath));
std::vector<std::string> optsVec;
@@ -834,11 +821,11 @@ bool cmQtAutoGenInitializer::InitScanFiles()
msg += '\n';
std::string property;
if (this->Moc.Enabled && this->Uic.Enabled) {
- property = "SKIP_AUTOGEN";
+ property = kw.SKIP_AUTOGEN;
} else if (this->Moc.Enabled) {
- property = "SKIP_AUTOMOC";
+ property = kw.SKIP_AUTOMOC;
} else if (this->Uic.Enabled) {
- property = "SKIP_AUTOUIC";
+ property = kw.SKIP_AUTOUIC;
}
msg += "For compatibility, CMake is excluding the GENERATED source "
"file(s):\n";
@@ -866,7 +853,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Target rcc options
std::vector<std::string> optionsTarget;
cmSystemTools::ExpandListArgument(
- this->Target->GetSafeProperty("AUTORCC_OPTIONS"), optionsTarget);
+ this->Target->GetSafeProperty(kw.AUTORCC_OPTIONS), optionsTarget);
// Check if file name is unique
for (Qrc& qrc : this->Rcc.Qrcs) {
@@ -944,7 +931,8 @@ bool cmQtAutoGenInitializer::InitScanFiles()
for (Qrc& qrc : this->Rcc.Qrcs) {
if (!qrc.Generated) {
std::string error;
- if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) {
+ RccLister const lister(this->Rcc.Executable, this->Rcc.ListOptions);
+ if (!lister.list(qrc.QrcFile, qrc.Resources, error)) {
cmSystemTools::Error(error);
return false;
}
@@ -1639,86 +1627,3 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
return true;
}
-
-/// @brief Reads the resource files list from from a .qrc file
-/// @arg fileName Must be the absolute path of the .qrc file
-/// @return True if the rcc file was successfully read
-bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName,
- std::vector<std::string>& files,
- std::string& error)
-{
- if (!cmSystemTools::FileExists(fileName)) {
- error = "rcc resource file does not exist:\n ";
- error += Quoted(fileName);
- error += "\n";
- return false;
- }
- if (this->Rcc.ExecutableExists && !this->Rcc.ListOptions.empty()) {
- // Use rcc for file listing
- if (this->Rcc.Executable.empty()) {
- error = "rcc executable not available";
- return false;
- }
-
- // Run rcc list command in the directory of the qrc file with the
- // pathless
- // qrc file name argument. This way rcc prints relative paths.
- // This avoids issues on Windows when the qrc file is in a path that
- // contains non-ASCII characters.
- std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);
- std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);
-
- bool result = false;
- int retVal = 0;
- std::string rccStdOut;
- std::string rccStdErr;
- {
- std::vector<std::string> cmd;
- cmd.push_back(this->Rcc.Executable);
- cmd.insert(cmd.end(), this->Rcc.ListOptions.begin(),
- this->Rcc.ListOptions.end());
- cmd.push_back(fileNameName);
- result = cmSystemTools::RunSingleCommand(
- cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
- cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
- }
- if (!result || retVal) {
- error = "rcc list process failed for:\n ";
- error += Quoted(fileName);
- error += "\n";
- error += rccStdOut;
- error += "\n";
- error += rccStdErr;
- error += "\n";
- return false;
- }
- if (!RccListParseOutput(rccStdOut, rccStdErr, files, error)) {
- return false;
- }
- } else {
- // We can't use rcc for the file listing.
- // Read the qrc file content into string and parse it.
- {
- std::string qrcContents;
- {
- cmsys::ifstream ifs(fileName.c_str());
- if (ifs) {
- std::ostringstream osst;
- osst << ifs.rdbuf();
- qrcContents = osst.str();
- } else {
- error = "rcc file not readable:\n ";
- error += Quoted(fileName);
- error += "\n";
- return false;
- }
- }
- // Parse string content
- RccListParseContent(qrcContents, files);
- }
- }
-
- // Convert relative paths to absolute paths
- RccListConvertFullPath(cmSystemTools::GetFilenamePath(fileName), files);
- return true;
-}
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index 1f4087f..7ff33c3 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -62,7 +62,6 @@ public:
bool Enabled = false;
// Generator type/name
GenT Gen;
- std::string const& GenName;
std::string const& GenNameUpper;
// Executable
std::string ExecutableTargetName;
@@ -71,11 +70,9 @@ public:
bool ExecutableExists = false;
/// @brief Constructor
- GenVarsT(GenT gen, std::string const& genName,
- std::string const& genNameUpper)
+ GenVarsT(GenT gen)
: Gen(gen)
- , GenName(genName)
- , GenNameUpper(genNameUpper){};
+ , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
};
/// @brief Writes a CMake info file
@@ -152,10 +149,6 @@ private:
bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
bool ignoreMissingTarget, std::string* output) const;
- bool RccListInputs(std::string const& fileName,
- std::vector<std::string>& files,
- std::string& errorMessage);
-
private:
cmQtAutoGenGlobalInitializer* GlobalInitializer;
cmGeneratorTarget* Target;
@@ -213,8 +206,7 @@ private:
/// @brief Constructor
MocT()
- : GenVarsT(cmQtAutoGen::GenT::MOC, cmQtAutoGen::GenAutoMoc,
- cmQtAutoGen::GenAUTOMOC){};
+ : GenVarsT(GenT::MOC){};
} Moc;
/// @brief Uic only variables
@@ -229,8 +221,7 @@ private:
/// @brief Constructor
UicT()
- : GenVarsT(cmQtAutoGen::GenT::UIC, cmQtAutoGen::GenAutoUic,
- cmQtAutoGen::GenAUTOUIC){};
+ : GenVarsT(GenT::UIC){};
} Uic;
/// @brief Rcc only variables
@@ -242,8 +233,7 @@ private:
/// @brief Constructor
RccT()
- : GenVarsT(cmQtAutoGen::GenT::RCC, cmQtAutoGen::GenAutoRcc,
- cmQtAutoGen::GenAUTORCC){};
+ : GenVarsT(GenT::RCC){};
} Rcc;
};
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index a1abd3f..6fbea82 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -14,10 +14,33 @@
#include "cmSystemTools.h"
#include "cmake.h"
-#include <algorithm>
-#include <utility>
+cmQtAutoGenerator::Logger::Logger()
+{
+ // Initialize logger
+ {
+ std::string verbose;
+ if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) {
+ unsigned long iVerbose = 0;
+ if (cmSystemTools::StringToULong(verbose.c_str(), &iVerbose)) {
+ SetVerbosity(static_cast<unsigned int>(iVerbose));
+ } else {
+ // Non numeric verbosity
+ SetVerbose(cmSystemTools::IsOn(verbose));
+ }
+ }
+ }
+ {
+ std::string colorEnv;
+ cmSystemTools::GetEnv("COLOR", colorEnv);
+ if (!colorEnv.empty()) {
+ SetColorOutput(cmSystemTools::IsOn(colorEnv));
+ } else {
+ SetColorOutput(true);
+ }
+ }
+}
-// -- Class methods
+cmQtAutoGenerator::Logger::~Logger() = default;
void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value)
{
@@ -151,6 +174,91 @@ void cmQtAutoGenerator::Logger::ErrorCommand(
}
}
+bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename)
+{
+ bool success = true;
+ std::string const dirName = cmSystemTools::GetFilenamePath(filename);
+ if (!dirName.empty()) {
+ success = cmSystemTools::MakeDirectory(dirName);
+ }
+ return success;
+}
+
+bool cmQtAutoGenerator::FileRead(std::string& content,
+ std::string const& filename,
+ std::string* error)
+{
+ content.clear();
+ if (!cmSystemTools::FileExists(filename, true)) {
+ if (error != nullptr) {
+ error->append("Not a file.");
+ }
+ return false;
+ }
+
+ unsigned long const length = cmSystemTools::FileLength(filename);
+ cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
+
+ // Use lambda to save destructor calls of ifs
+ return [&ifs, length, &content, error]() -> bool {
+ if (!ifs) {
+ if (error != nullptr) {
+ error->append("Opening the file for reading failed.");
+ }
+ return false;
+ }
+ content.reserve(length);
+ typedef std::istreambuf_iterator<char> IsIt;
+ content.assign(IsIt{ ifs }, IsIt{});
+ if (!ifs) {
+ content.clear();
+ if (error != nullptr) {
+ error->append("Reading from the file failed.");
+ }
+ return false;
+ }
+ return true;
+ }();
+}
+
+bool cmQtAutoGenerator::FileWrite(std::string const& filename,
+ std::string const& content,
+ std::string* error)
+{
+ // Make sure the parent directory exists
+ if (!cmQtAutoGenerator::MakeParentDirectory(filename)) {
+ if (error != nullptr) {
+ error->assign("Could not create parent directory.");
+ }
+ return false;
+ }
+ cmsys::ofstream ofs;
+ ofs.open(filename.c_str(),
+ (std::ios::out | std::ios::binary | std::ios::trunc));
+
+ // Use lambda to save destructor calls of ofs
+ return [&ofs, &content, error]() -> bool {
+ if (!ofs) {
+ if (error != nullptr) {
+ error->assign("Opening file for writing failed.");
+ }
+ return false;
+ }
+ ofs << content;
+ if (!ofs.good()) {
+ if (error != nullptr) {
+ error->assign("File writing failed.");
+ }
+ return false;
+ }
+ return true;
+ }();
+}
+
+cmQtAutoGenerator::FileSystem::FileSystem() = default;
+
+cmQtAutoGenerator::FileSystem::~FileSystem() = default;
+
std::string cmQtAutoGenerator::FileSystem::GetRealPath(
std::string const& filename)
{
@@ -266,91 +374,16 @@ bool cmQtAutoGenerator::FileSystem::FileRead(std::string& content,
std::string const& filename,
std::string* error)
{
- bool success = false;
- if (FileExists(filename, true)) {
- unsigned long const length = FileLength(filename);
- {
- std::lock_guard<std::mutex> lock(Mutex_);
- cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
- if (ifs) {
- content.reserve(length);
- content.assign(std::istreambuf_iterator<char>{ ifs },
- std::istreambuf_iterator<char>{});
- if (ifs) {
- success = true;
- } else {
- content.clear();
- if (error != nullptr) {
- error->append("Reading from the file failed.");
- }
- }
- } else if (error != nullptr) {
- error->append("Opening the file for reading failed.");
- }
- }
- } else if (error != nullptr) {
- error->append(
- "The file does not exist, is not readable or is a directory.");
- }
- return success;
-}
-
-bool cmQtAutoGenerator::FileSystem::FileRead(GenT genType,
- std::string& content,
- std::string const& filename)
-{
- std::string error;
- if (!FileRead(content, filename, &error)) {
- Log()->ErrorFile(genType, filename, error);
- return false;
- }
- return true;
+ std::lock_guard<std::mutex> lock(Mutex_);
+ return cmQtAutoGenerator::FileRead(content, filename, error);
}
bool cmQtAutoGenerator::FileSystem::FileWrite(std::string const& filename,
std::string const& content,
std::string* error)
{
- bool success = false;
- // Make sure the parent directory exists
- if (MakeParentDirectory(filename)) {
- std::lock_guard<std::mutex> lock(Mutex_);
- cmsys::ofstream outfile;
- outfile.open(filename.c_str(),
- (std::ios::out | std::ios::binary | std::ios::trunc));
- if (outfile) {
- outfile << content;
- // Check for write errors
- if (outfile.good()) {
- success = true;
- } else {
- if (error != nullptr) {
- error->assign("File writing failed");
- }
- }
- } else {
- if (error != nullptr) {
- error->assign("Opening file for writing failed");
- }
- }
- } else {
- if (error != nullptr) {
- error->assign("Could not create parent directory");
- }
- }
- return success;
-}
-
-bool cmQtAutoGenerator::FileSystem::FileWrite(GenT genType,
- std::string const& filename,
- std::string const& content)
-{
- std::string error;
- if (!FileWrite(filename, content, &error)) {
- Log()->ErrorFile(genType, filename, error);
- return false;
- }
- return true;
+ std::lock_guard<std::mutex> lock(Mutex_);
+ return cmQtAutoGenerator::FileWrite(filename, content, error);
}
bool cmQtAutoGenerator::FileSystem::FileDiffers(std::string const& filename,
@@ -385,294 +418,16 @@ bool cmQtAutoGenerator::FileSystem::MakeDirectory(std::string const& dirname)
return cmSystemTools::MakeDirectory(dirname);
}
-bool cmQtAutoGenerator::FileSystem::MakeDirectory(GenT genType,
- std::string const& dirname)
-{
- if (!MakeDirectory(dirname)) {
- Log()->ErrorFile(genType, dirname, "Could not create directory");
- return false;
- }
- return true;
-}
-
bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
std::string const& filename)
{
- bool success = true;
- std::string const dirName = cmSystemTools::GetFilenamePath(filename);
- if (!dirName.empty()) {
- success = MakeDirectory(dirName);
- }
- return success;
-}
-
-bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
- GenT genType, std::string const& filename)
-{
- if (!MakeParentDirectory(filename)) {
- Log()->ErrorFile(genType, filename, "Could not create parent directory");
- return false;
- }
- return true;
-}
-
-int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::init(uv_loop_t* uv_loop,
- ReadOnlyProcessT* process)
-{
- Process_ = process;
- Target_ = nullptr;
- return UVPipe_.init(*uv_loop, 0, this);
-}
-
-int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::startRead(std::string* target)
-{
- Target_ = target;
- return uv_read_start(uv_stream(), &PipeT::UVAlloc, &PipeT::UVData);
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::reset()
-{
- Process_ = nullptr;
- Target_ = nullptr;
- UVPipe_.reset();
- Buffer_.clear();
- Buffer_.shrink_to_fit();
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVAlloc(uv_handle_t* handle,
- size_t suggestedSize,
- uv_buf_t* buf)
-{
- auto& pipe = *reinterpret_cast<PipeT*>(handle->data);
- pipe.Buffer_.resize(suggestedSize);
- buf->base = pipe.Buffer_.data();
- buf->len = pipe.Buffer_.size();
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVData(uv_stream_t* stream,
- ssize_t nread,
- const uv_buf_t* buf)
-{
- auto& pipe = *reinterpret_cast<PipeT*>(stream->data);
- if (nread > 0) {
- // Append data to merged output
- if ((buf->base != nullptr) && (pipe.Target_ != nullptr)) {
- pipe.Target_->append(buf->base, nread);
- }
- } else if (nread < 0) {
- // EOF or error
- auto* proc = pipe.Process_;
- // Check it this an unusual error
- if (nread != UV_EOF) {
- if (!proc->Result()->error()) {
- proc->Result()->ErrorMessage =
- "libuv reading from pipe failed with error code ";
- proc->Result()->ErrorMessage += std::to_string(nread);
- }
- }
- // Clear libuv pipe handle and try to finish
- pipe.reset();
- proc->UVTryFinish();
- }
-}
-
-void cmQtAutoGenerator::ProcessResultT::reset()
-{
- ExitStatus = 0;
- TermSignal = 0;
- if (!StdOut.empty()) {
- StdOut.clear();
- StdOut.shrink_to_fit();
- }
- if (!StdErr.empty()) {
- StdErr.clear();
- StdErr.shrink_to_fit();
- }
- if (!ErrorMessage.empty()) {
- ErrorMessage.clear();
- ErrorMessage.shrink_to_fit();
- }
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::setup(
- ProcessResultT* result, bool mergedOutput,
- std::vector<std::string> const& command, std::string const& workingDirectory)
-{
- Setup_.WorkingDirectory = workingDirectory;
- Setup_.Command = command;
- Setup_.Result = result;
- Setup_.MergedOutput = mergedOutput;
-}
-
-bool cmQtAutoGenerator::ReadOnlyProcessT::start(
- uv_loop_t* uv_loop, std::function<void()>&& finishedCallback)
-{
- if (IsStarted() || (Result() == nullptr)) {
- return false;
- }
-
- // Reset result before the start
- Result()->reset();
-
- // Fill command string pointers
- if (!Setup().Command.empty()) {
- CommandPtr_.reserve(Setup().Command.size() + 1);
- for (std::string const& arg : Setup().Command) {
- CommandPtr_.push_back(arg.c_str());
- }
- CommandPtr_.push_back(nullptr);
- } else {
- Result()->ErrorMessage = "Empty command";
- }
-
- if (!Result()->error()) {
- if (UVPipeOut_.init(uv_loop, this) != 0) {
- Result()->ErrorMessage = "libuv stdout pipe initialization failed";
- }
- }
- if (!Result()->error()) {
- if (UVPipeErr_.init(uv_loop, this) != 0) {
- Result()->ErrorMessage = "libuv stderr pipe initialization failed";
- }
- }
- if (!Result()->error()) {
- // -- Setup process stdio options
- // stdin
- UVOptionsStdIO_[0].flags = UV_IGNORE;
- UVOptionsStdIO_[0].data.stream = nullptr;
- // stdout
- UVOptionsStdIO_[1].flags =
- static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
- UVOptionsStdIO_[1].data.stream = UVPipeOut_.uv_stream();
- // stderr
- UVOptionsStdIO_[2].flags =
- static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
- UVOptionsStdIO_[2].data.stream = UVPipeErr_.uv_stream();
-
- // -- Setup process options
- std::fill_n(reinterpret_cast<char*>(&UVOptions_), sizeof(UVOptions_), 0);
- UVOptions_.exit_cb = &ReadOnlyProcessT::UVExit;
- UVOptions_.file = CommandPtr_[0];
- UVOptions_.args = const_cast<char**>(CommandPtr_.data());
- UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
- UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
- UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
- UVOptions_.stdio = UVOptionsStdIO_.data();
-
- // -- Spawn process
- if (UVProcess_.spawn(*uv_loop, UVOptions_, this) != 0) {
- Result()->ErrorMessage = "libuv process spawn failed";
- }
- }
- // -- Start reading from stdio streams
- if (!Result()->error()) {
- if (UVPipeOut_.startRead(&Result()->StdOut) != 0) {
- Result()->ErrorMessage = "libuv start reading from stdout pipe failed";
- }
- }
- if (!Result()->error()) {
- if (UVPipeErr_.startRead(Setup_.MergedOutput ? &Result()->StdOut
- : &Result()->StdErr) != 0) {
- Result()->ErrorMessage = "libuv start reading from stderr pipe failed";
- }
- }
-
- if (!Result()->error()) {
- IsStarted_ = true;
- FinishedCallback_ = std::move(finishedCallback);
- } else {
- // Clear libuv handles and finish
- UVProcess_.reset();
- UVPipeOut_.reset();
- UVPipeErr_.reset();
- CommandPtr_.clear();
- }
-
- return IsStarted();
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::UVExit(uv_process_t* handle,
- int64_t exitStatus,
- int termSignal)
-{
- auto& proc = *reinterpret_cast<ReadOnlyProcessT*>(handle->data);
- if (proc.IsStarted() && !proc.IsFinished()) {
- // Set error message on demand
- proc.Result()->ExitStatus = exitStatus;
- proc.Result()->TermSignal = termSignal;
- if (!proc.Result()->error()) {
- if (termSignal != 0) {
- proc.Result()->ErrorMessage = "Process was terminated by signal ";
- proc.Result()->ErrorMessage +=
- std::to_string(proc.Result()->TermSignal);
- } else if (exitStatus != 0) {
- proc.Result()->ErrorMessage = "Process failed with return value ";
- proc.Result()->ErrorMessage +=
- std::to_string(proc.Result()->ExitStatus);
- }
- }
-
- // Reset process handle and try to finish
- proc.UVProcess_.reset();
- proc.UVTryFinish();
- }
-}
-
-void cmQtAutoGenerator::ReadOnlyProcessT::UVTryFinish()
-{
- // There still might be data in the pipes after the process has finished.
- // Therefore check if the process is finished AND all pipes are closed
- // before signaling the worker thread to continue.
- if (UVProcess_.get() == nullptr) {
- if (UVPipeOut_.uv_pipe() == nullptr) {
- if (UVPipeErr_.uv_pipe() == nullptr) {
- IsFinished_ = true;
- FinishedCallback_();
- }
- }
- }
+ std::lock_guard<std::mutex> lock(Mutex_);
+ return cmQtAutoGenerator::MakeParentDirectory(filename);
}
-cmQtAutoGenerator::cmQtAutoGenerator()
- : FileSys_(&Logger_)
-{
- // Initialize logger
- {
- std::string verbose;
- if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) {
- unsigned long iVerbose = 0;
- if (cmSystemTools::StringToULong(verbose.c_str(), &iVerbose)) {
- Logger_.SetVerbosity(static_cast<unsigned int>(iVerbose));
- } else {
- // Non numeric verbosity
- Logger_.SetVerbose(cmSystemTools::IsOn(verbose));
- }
- }
- }
- {
- std::string colorEnv;
- cmSystemTools::GetEnv("COLOR", colorEnv);
- if (!colorEnv.empty()) {
- Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv));
- } else {
- Logger_.SetColorOutput(true);
- }
- }
-
- // Initialize libuv loop
- uv_disable_stdio_inheritance();
-#ifdef CMAKE_UV_SIGNAL_HACK
- UVHackRAII_ = cm::make_unique<cmUVSignalHackRAII>();
-#endif
- UVLoop_ = cm::make_unique<uv_loop_t>();
- uv_loop_init(UVLoop());
-}
+cmQtAutoGenerator::cmQtAutoGenerator() = default;
-cmQtAutoGenerator::~cmQtAutoGenerator()
-{
- // Close libuv loop
- uv_loop_close(UVLoop());
-}
+cmQtAutoGenerator::~cmQtAutoGenerator() = default;
bool cmQtAutoGenerator::Run(std::string const& infoFile,
std::string const& config)
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index b55bebc..437fa20 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -7,15 +7,8 @@
#include "cmFilePathChecksum.h"
#include "cmQtAutoGen.h"
-#include "cmUVHandlePtr.h"
-#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
-#include "cm_uv.h"
-#include <array>
-#include <functional>
#include <mutex>
-#include <stddef.h>
-#include <stdint.h>
#include <string>
#include <vector>
@@ -31,12 +24,16 @@ public:
class Logger
{
public:
+ // -- Construction
+ Logger();
+ ~Logger();
// -- Verbosity
unsigned int Verbosity() const { return this->Verbosity_; }
void SetVerbosity(unsigned int value) { this->Verbosity_ = value; }
void RaiseVerbosity(std::string const& value);
bool Verbose() const { return (this->Verbosity_ != 0); }
void SetVerbose(bool value) { this->Verbosity_ = value ? 1 : 0; }
+ // -- Color output
bool ColorOutput() const { return this->ColorOutput_; }
void SetColorOutput(bool value);
// -- Log info
@@ -62,17 +59,20 @@ public:
bool ColorOutput_ = false;
};
+ // -- File system methods
+ static bool MakeParentDirectory(std::string const& filename);
+ static bool FileRead(std::string& content, std::string const& filename,
+ std::string* error = nullptr);
+ static bool FileWrite(std::string const& filename,
+ std::string const& content,
+ std::string* error = nullptr);
+
/// @brief Thread safe file system interface
class FileSystem
{
public:
- FileSystem(Logger* log)
- : Log_(log)
- {
- }
-
- /// @brief Logger
- Logger* Log() const { return Log_; }
+ FileSystem();
+ ~FileSystem();
// -- Paths
/// @brief Wrapper for cmSystemTools::GetRealPath
@@ -113,15 +113,9 @@ public:
bool FileRead(std::string& content, std::string const& filename,
std::string* error = nullptr);
- /// @brief Error logging version
- bool FileRead(GenT genType, std::string& content,
- std::string const& filename);
bool FileWrite(std::string const& filename, std::string const& content,
std::string* error = nullptr);
- /// @brief Error logging version
- bool FileWrite(GenT genType, std::string const& filename,
- std::string const& content);
bool FileDiffers(std::string const& filename, std::string const& content);
@@ -130,113 +124,11 @@ public:
// -- Directory access
bool MakeDirectory(std::string const& dirname);
- /// @brief Error logging version
- bool MakeDirectory(GenT genType, std::string const& dirname);
-
bool MakeParentDirectory(std::string const& filename);
- /// @brief Error logging version
- bool MakeParentDirectory(GenT genType, std::string const& filename);
private:
std::mutex Mutex_;
cmFilePathChecksum FilePathChecksum_;
- Logger* Log_;
- };
-
- /// @brief Return value and output of an external process
- struct ProcessResultT
- {
- void reset();
- bool error() const
- {
- return (ExitStatus != 0) || (TermSignal != 0) || !ErrorMessage.empty();
- }
-
- std::int64_t ExitStatus = 0;
- int TermSignal = 0;
- std::string StdOut;
- std::string StdErr;
- std::string ErrorMessage;
- };
-
- /// @brief External process management class
- struct ReadOnlyProcessT
- {
- // -- Types
-
- /// @brief libuv pipe buffer class
- class PipeT
- {
- public:
- int init(uv_loop_t* uv_loop, ReadOnlyProcessT* process);
- int startRead(std::string* target);
- void reset();
-
- // -- Libuv casts
- uv_pipe_t* uv_pipe() { return UVPipe_.get(); }
- uv_stream_t* uv_stream()
- {
- return reinterpret_cast<uv_stream_t*>(uv_pipe());
- }
- uv_handle_t* uv_handle()
- {
- return reinterpret_cast<uv_handle_t*>(uv_pipe());
- }
-
- // -- Libuv callbacks
- static void UVAlloc(uv_handle_t* handle, size_t suggestedSize,
- uv_buf_t* buf);
- static void UVData(uv_stream_t* stream, ssize_t nread,
- const uv_buf_t* buf);
-
- private:
- ReadOnlyProcessT* Process_ = nullptr;
- std::string* Target_ = nullptr;
- std::vector<char> Buffer_;
- cm::uv_pipe_ptr UVPipe_;
- };
-
- /// @brief Process settings
- struct SetupT
- {
- std::string WorkingDirectory;
- std::vector<std::string> Command;
- ProcessResultT* Result = nullptr;
- bool MergedOutput = false;
- };
-
- // -- Const accessors
- const SetupT& Setup() const { return Setup_; }
- ProcessResultT* Result() const { return Setup_.Result; }
- bool IsStarted() const { return IsStarted_; }
- bool IsFinished() const { return IsFinished_; }
-
- // -- Runtime
- void setup(ProcessResultT* result, bool mergedOutput,
- std::vector<std::string> const& command,
- std::string const& workingDirectory = std::string());
- bool start(uv_loop_t* uv_loop, std::function<void()>&& finishedCallback);
-
- private:
- // -- Friends
- friend class PipeT;
- // -- Libuv callbacks
- static void UVExit(uv_process_t* handle, int64_t exitStatus,
- int termSignal);
- void UVTryFinish();
-
- // -- Setup
- SetupT Setup_;
- // -- Runtime
- bool IsStarted_ = false;
- bool IsFinished_ = false;
- std::function<void()> FinishedCallback_;
- std::vector<const char*> CommandPtr_;
- std::array<uv_stdio_container_t, 3> UVOptionsStdIO_;
- uv_process_options_t UVOptions_;
- cm::uv_process_ptr UVProcess_;
- PipeT UVPipeOut_;
- PipeT UVPipeErr_;
};
public:
@@ -250,18 +142,10 @@ public:
// -- Run
bool Run(std::string const& infoFile, std::string const& config);
- // -- Accessors
- // Logging
- Logger& Log() { return Logger_; }
- // File System
- FileSystem& FileSys() { return FileSys_; }
// InfoFile
std::string const& InfoFile() const { return InfoFile_; }
std::string const& InfoDir() const { return InfoDir_; }
std::string const& InfoConfig() const { return InfoConfig_; }
- // libuv loop
- uv_loop_t* UVLoop() { return UVLoop_.get(); }
- cm::uv_async_ptr& UVRequest() { return UVRequest_; }
// -- Utility
static std::string SettingsFind(std::string const& content, const char* key);
@@ -272,19 +156,10 @@ protected:
virtual bool Process() = 0;
private:
- // -- Logging
- Logger Logger_;
- FileSystem FileSys_;
// -- Info settings
std::string InfoFile_;
std::string InfoDir_;
std::string InfoConfig_;
-// -- libuv loop
-#ifdef CMAKE_UV_SIGNAL_HACK
- std::unique_ptr<cmUVSignalHackRAII> UVHackRAII_;
-#endif
- std::unique_ptr<uv_loop_t> UVLoop_;
- cm::uv_async_ptr UVRequest_;
};
#endif
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
deleted file mode 100644
index 5deb532..0000000
--- a/Source/cmQtAutoGeneratorRcc.cxx
+++ /dev/null
@@ -1,666 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGeneratorRcc.h"
-#include "cmQtAutoGen.h"
-
-#include "cmAlgorithms.h"
-#include "cmCryptoHash.h"
-#include "cmFileLockResult.h"
-#include "cmMakefile.h"
-#include "cmSystemTools.h"
-#include "cmUVHandlePtr.h"
-
-// -- Class methods
-
-cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
-{
- // Initialize libuv asynchronous iteration request
- UVRequest().init(*UVLoop(), &cmQtAutoGeneratorRcc::UVPollStage, this);
-}
-
-cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc() = default;
-
-bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
-{
- // -- Utility lambdas
- auto InfoGet = [makefile](std::string const& key) {
- return makefile->GetSafeDefinition(key);
- };
- auto InfoGetList =
- [makefile](std::string const& key) -> std::vector<std::string> {
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
- return list;
- };
- auto InfoGetConfig = [makefile,
- this](std::string const& key) -> std::string {
- const char* valueConf = nullptr;
- {
- std::string keyConf = key;
- keyConf += '_';
- keyConf += InfoConfig();
- valueConf = makefile->GetDefinition(keyConf);
- }
- if (valueConf == nullptr) {
- return makefile->GetSafeDefinition(key);
- }
- return std::string(valueConf);
- };
- auto InfoGetConfigList =
- [&InfoGetConfig](std::string const& key) -> std::vector<std::string> {
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
- return list;
- };
-
- // -- Read info file
- if (!makefile->ReadListFile(InfoFile())) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "File processing failed");
- return false;
- }
-
- // - Configurations
- Log().RaiseVerbosity(InfoGet("ARCC_VERBOSITY"));
- MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
-
- // - Directories
- AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
- if (AutogenBuildDir_.empty()) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "Build directory empty");
- return false;
- }
-
- IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
- if (IncludeDir_.empty()) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "Include directory empty");
- return false;
- }
-
- // - Rcc executable
- RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
- RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
-
- // - Job
- LockFile_ = InfoGet("ARCC_LOCK_FILE");
- QrcFile_ = InfoGet("ARCC_SOURCE");
- QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
- QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
- RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
- RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
- Options_ = InfoGetConfigList("ARCC_OPTIONS");
- Inputs_ = InfoGetList("ARCC_INPUTS");
-
- // - Settings file
- SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
-
- // - Validity checks
- if (LockFile_.empty()) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "Lock file name missing");
- return false;
- }
- if (SettingsFile_.empty()) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "Settings file name missing");
- return false;
- }
- if (AutogenBuildDir_.empty()) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "Autogen build directory missing");
- return false;
- }
- if (RccExecutable_.empty()) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "rcc executable missing");
- return false;
- }
- if (QrcFile_.empty()) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "rcc input file missing");
- return false;
- }
- if (RccFileName_.empty()) {
- Log().ErrorFile(GenT::RCC, InfoFile(), "rcc output file missing");
- return false;
- }
-
- // Init derived information
- // ------------------------
-
- RccFilePublic_ = AutogenBuildDir_;
- RccFilePublic_ += '/';
- RccFilePublic_ += RccPathChecksum_;
- RccFilePublic_ += '/';
- RccFilePublic_ += RccFileName_;
-
- // Compute rcc output file name
- if (IsMultiConfig()) {
- RccFileOutput_ = IncludeDir_;
- RccFileOutput_ += '/';
- RccFileOutput_ += MultiConfigOutput();
- } else {
- RccFileOutput_ = RccFilePublic_;
- }
-
- return true;
-}
-
-bool cmQtAutoGeneratorRcc::Process()
-{
- // Run libuv event loop
- UVRequest().send();
- if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) {
- if (Error_) {
- return false;
- }
- } else {
- return false;
- }
- return true;
-}
-
-void cmQtAutoGeneratorRcc::UVPollStage(uv_async_t* handle)
-{
- reinterpret_cast<cmQtAutoGeneratorRcc*>(handle->data)->PollStage();
-}
-
-void cmQtAutoGeneratorRcc::PollStage()
-{
- switch (Stage_) {
- // -- Initialize
- case StageT::SETTINGS_READ:
- if (SettingsFileRead()) {
- SetStage(StageT::TEST_QRC_RCC_FILES);
- } else {
- SetStage(StageT::FINISH);
- }
- break;
-
- // -- Change detection
- case StageT::TEST_QRC_RCC_FILES:
- if (TestQrcRccFiles()) {
- SetStage(StageT::GENERATE);
- } else {
- SetStage(StageT::TEST_RESOURCES_READ);
- }
- break;
- case StageT::TEST_RESOURCES_READ:
- if (TestResourcesRead()) {
- SetStage(StageT::TEST_RESOURCES);
- }
- break;
- case StageT::TEST_RESOURCES:
- if (TestResources()) {
- SetStage(StageT::GENERATE);
- } else {
- SetStage(StageT::TEST_INFO_FILE);
- }
- break;
- case StageT::TEST_INFO_FILE:
- TestInfoFile();
- SetStage(StageT::GENERATE_WRAPPER);
- break;
-
- // -- Generation
- case StageT::GENERATE:
- GenerateParentDir();
- SetStage(StageT::GENERATE_RCC);
- break;
- case StageT::GENERATE_RCC:
- if (GenerateRcc()) {
- SetStage(StageT::GENERATE_WRAPPER);
- }
- break;
- case StageT::GENERATE_WRAPPER:
- GenerateWrapper();
- SetStage(StageT::SETTINGS_WRITE);
- break;
-
- // -- Finalize
- case StageT::SETTINGS_WRITE:
- SettingsFileWrite();
- SetStage(StageT::FINISH);
- break;
- case StageT::FINISH:
- // Clear all libuv handles
- UVRequest().reset();
- // Set highest END stage manually
- Stage_ = StageT::END;
- break;
- case StageT::END:
- break;
- }
-}
-
-void cmQtAutoGeneratorRcc::SetStage(StageT stage)
-{
- if (Error_) {
- stage = StageT::FINISH;
- }
- // Only allow to increase the stage
- if (Stage_ < stage) {
- Stage_ = stage;
- UVRequest().send();
- }
-}
-
-std::string cmQtAutoGeneratorRcc::MultiConfigOutput() const
-{
- static std::string const suffix = "_CMAKE_";
- std::string res;
- res += RccPathChecksum_;
- res += '/';
- res += AppendFilenameSuffix(RccFileName_, suffix);
- return res;
-}
-
-bool cmQtAutoGeneratorRcc::SettingsFileRead()
-{
- // Compose current settings strings
- {
- cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
- std::string const sep(" ~~~ ");
- {
- std::string str;
- str += RccExecutable_;
- str += sep;
- str += cmJoin(RccListOptions_, ";");
- str += sep;
- str += QrcFile_;
- str += sep;
- str += RccPathChecksum_;
- str += sep;
- str += RccFileName_;
- str += sep;
- str += cmJoin(Options_, ";");
- str += sep;
- str += cmJoin(Inputs_, ";");
- str += sep;
- SettingsString_ = crypt.HashString(str);
- }
- }
-
- // Make sure the settings file exists
- if (!FileSys().FileExists(SettingsFile_, true)) {
- // Touch the settings file to make sure it exists
- FileSys().Touch(SettingsFile_, true);
- }
-
- // Lock the lock file
- {
- // Make sure the lock file exists
- if (!FileSys().FileExists(LockFile_, true)) {
- if (!FileSys().Touch(LockFile_, true)) {
- Log().ErrorFile(GenT::RCC, LockFile_, "Lock file creation failed");
- Error_ = true;
- return false;
- }
- }
- // Lock the lock file
- cmFileLockResult lockResult =
- LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1));
- if (!lockResult.IsOk()) {
- Log().ErrorFile(GenT::RCC, LockFile_,
- "File lock failed: " + lockResult.GetOutputMessage());
- Error_ = true;
- return false;
- }
- }
-
- // Read old settings
- {
- std::string content;
- if (FileSys().FileRead(content, SettingsFile_)) {
- SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
- // In case any setting changed clear the old settings file.
- // This triggers a full rebuild on the next run if the current
- // build is aborted before writing the current settings in the end.
- if (SettingsChanged_) {
- FileSys().FileWrite(GenT::RCC, SettingsFile_, "");
- }
- } else {
- SettingsChanged_ = true;
- }
- }
-
- return true;
-}
-
-void cmQtAutoGeneratorRcc::SettingsFileWrite()
-{
- // Only write if any setting changed
- if (SettingsChanged_) {
- if (Log().Verbose()) {
- Log().Info(GenT::RCC, "Writing settings file " + Quoted(SettingsFile_));
- }
- // Write settings file
- std::string content = "rcc:";
- content += SettingsString_;
- content += '\n';
- if (!FileSys().FileWrite(GenT::RCC, SettingsFile_, content)) {
- Log().ErrorFile(GenT::RCC, SettingsFile_,
- "Settings file writing failed");
- // Remove old settings file to trigger a full rebuild on the next run
- FileSys().FileRemove(SettingsFile_);
- Error_ = true;
- }
- }
-
- // Unlock the lock file
- LockFileLock_.Release();
-}
-
-bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
-{
- // Do basic checks if rcc generation is required
-
- // Test if the rcc output file exists
- if (!FileSys().FileExists(RccFileOutput_)) {
- if (Log().Verbose()) {
- std::string reason = "Generating ";
- reason += Quoted(RccFileOutput_);
- reason += " from its source file ";
- reason += Quoted(QrcFile_);
- reason += " because it doesn't exist";
- Log().Info(GenT::RCC, reason);
- }
- Generate_ = true;
- return Generate_;
- }
-
- // Test if the settings changed
- if (SettingsChanged_) {
- if (Log().Verbose()) {
- std::string reason = "Generating ";
- reason += Quoted(RccFileOutput_);
- reason += " from ";
- reason += Quoted(QrcFile_);
- reason += " because the RCC settings changed";
- Log().Info(GenT::RCC, reason);
- }
- Generate_ = true;
- return Generate_;
- }
-
- // Test if the rcc output file is older than the .qrc file
- {
- bool isOlder = false;
- {
- std::string error;
- isOlder = FileSys().FileIsOlderThan(RccFileOutput_, QrcFile_, &error);
- if (!error.empty()) {
- Log().ErrorFile(GenT::RCC, QrcFile_, error);
- Error_ = true;
- }
- }
- if (isOlder) {
- if (Log().Verbose()) {
- std::string reason = "Generating ";
- reason += Quoted(RccFileOutput_);
- reason += " because it is older than ";
- reason += Quoted(QrcFile_);
- Log().Info(GenT::RCC, reason);
- }
- Generate_ = true;
- }
- }
-
- return Generate_;
-}
-
-bool cmQtAutoGeneratorRcc::TestResourcesRead()
-{
- if (!Inputs_.empty()) {
- // Inputs are known already
- return true;
- }
-
- if (!RccListOptions_.empty()) {
- // Start a rcc list process and parse the output
- if (Process_) {
- // Process is running already
- if (Process_->IsFinished()) {
- // Process is finished
- if (!ProcessResult_.error()) {
- // Process success
- std::string parseError;
- if (!RccListParseOutput(ProcessResult_.StdOut, ProcessResult_.StdErr,
- Inputs_, parseError)) {
- Log().ErrorFile(GenT::RCC, QrcFile_, parseError);
- Error_ = true;
- }
- } else {
- Log().ErrorFile(GenT::RCC, QrcFile_, ProcessResult_.ErrorMessage);
- Error_ = true;
- }
- // Clean up
- Process_.reset();
- ProcessResult_.reset();
- } else {
- // Process is not finished, yet.
- return false;
- }
- } else {
- // Start a new process
- // rcc prints relative entry paths when started in the directory of the
- // qrc file with a pathless qrc file name argument.
- // This is important because on Windows absolute paths returned by rcc
- // might contain bad multibyte characters when the qrc file path
- // contains non-ASCII pcharacters.
- std::vector<std::string> cmd;
- cmd.push_back(RccExecutable_);
- cmd.insert(cmd.end(), RccListOptions_.begin(), RccListOptions_.end());
- cmd.push_back(QrcFileName_);
- // We're done here if the process fails to start
- return !StartProcess(QrcFileDir_, cmd, false);
- }
- } else {
- // rcc does not support the --list command.
- // Read the qrc file content and parse it.
- std::string qrcContent;
- if (FileSys().FileRead(GenT::RCC, qrcContent, QrcFile_)) {
- RccListParseContent(qrcContent, Inputs_);
- }
- }
-
- if (!Inputs_.empty()) {
- // Convert relative paths to absolute paths
- RccListConvertFullPath(QrcFileDir_, Inputs_);
- }
-
- return true;
-}
-
-bool cmQtAutoGeneratorRcc::TestResources()
-{
- if (Inputs_.empty()) {
- return true;
- }
- {
- std::string error;
- for (std::string const& resFile : Inputs_) {
- // Check if the resource file exists
- if (!FileSys().FileExists(resFile)) {
- error = "Could not find the resource file\n ";
- error += Quoted(resFile);
- error += '\n';
- Log().ErrorFile(GenT::RCC, QrcFile_, error);
- Error_ = true;
- break;
- }
- // Check if the resource file is newer than the build file
- if (FileSys().FileIsOlderThan(RccFileOutput_, resFile, &error)) {
- if (Log().Verbose()) {
- std::string reason = "Generating ";
- reason += Quoted(RccFileOutput_);
- reason += " from ";
- reason += Quoted(QrcFile_);
- reason += " because it is older than ";
- reason += Quoted(resFile);
- Log().Info(GenT::RCC, reason);
- }
- Generate_ = true;
- break;
- }
- // Print error and break on demand
- if (!error.empty()) {
- Log().ErrorFile(GenT::RCC, QrcFile_, error);
- Error_ = true;
- break;
- }
- }
- }
-
- return Generate_;
-}
-
-void cmQtAutoGeneratorRcc::TestInfoFile()
-{
- // Test if the rcc output file is older than the info file
- {
- bool isOlder = false;
- {
- std::string error;
- isOlder = FileSys().FileIsOlderThan(RccFileOutput_, InfoFile(), &error);
- if (!error.empty()) {
- Log().ErrorFile(GenT::RCC, QrcFile_, error);
- Error_ = true;
- }
- }
- if (isOlder) {
- if (Log().Verbose()) {
- std::string reason = "Touching ";
- reason += Quoted(RccFileOutput_);
- reason += " because it is older than ";
- reason += Quoted(InfoFile());
- Log().Info(GenT::RCC, reason);
- }
- // Touch build file
- FileSys().Touch(RccFileOutput_);
- BuildFileChanged_ = true;
- }
- }
-}
-
-void cmQtAutoGeneratorRcc::GenerateParentDir()
-{
- // Make sure the parent directory exists
- if (!FileSys().MakeParentDirectory(GenT::RCC, RccFileOutput_)) {
- Error_ = true;
- }
-}
-
-/**
- * @return True when finished
- */
-bool cmQtAutoGeneratorRcc::GenerateRcc()
-{
- if (!Generate_) {
- // Nothing to do
- return true;
- }
-
- if (Process_) {
- // Process is running already
- if (Process_->IsFinished()) {
- // Process is finished
- if (!ProcessResult_.error()) {
- // Rcc process success
- // Print rcc output
- if (!ProcessResult_.StdOut.empty()) {
- Log().Info(GenT::RCC, ProcessResult_.StdOut);
- }
- BuildFileChanged_ = true;
- } else {
- // Rcc process failed
- {
- std::string emsg = "The rcc process failed to compile\n ";
- emsg += Quoted(QrcFile_);
- emsg += "\ninto\n ";
- emsg += Quoted(RccFileOutput_);
- if (ProcessResult_.error()) {
- emsg += "\n";
- emsg += ProcessResult_.ErrorMessage;
- }
- Log().ErrorCommand(GenT::RCC, emsg, Process_->Setup().Command,
- ProcessResult_.StdOut);
- }
- FileSys().FileRemove(RccFileOutput_);
- Error_ = true;
- }
- // Clean up
- Process_.reset();
- ProcessResult_.reset();
- } else {
- // Process is not finished, yet.
- return false;
- }
- } else {
- // Start a rcc process
- std::vector<std::string> cmd;
- cmd.push_back(RccExecutable_);
- cmd.insert(cmd.end(), Options_.begin(), Options_.end());
- cmd.emplace_back("-o");
- cmd.push_back(RccFileOutput_);
- cmd.push_back(QrcFile_);
- // We're done here if the process fails to start
- return !StartProcess(AutogenBuildDir_, cmd, true);
- }
-
- return true;
-}
-
-void cmQtAutoGeneratorRcc::GenerateWrapper()
-{
- // Generate a wrapper source file on demand
- if (IsMultiConfig()) {
- // Wrapper file content
- std::string content;
- content += "// This is an autogenerated configuration wrapper file.\n";
- content += "// Changes will be overwritten.\n";
- content += "#include <";
- content += MultiConfigOutput();
- content += ">\n";
-
- // Write content to file
- if (FileSys().FileDiffers(RccFilePublic_, content)) {
- // Write new wrapper file
- if (Log().Verbose()) {
- Log().Info(GenT::RCC, "Generating RCC wrapper file " + RccFilePublic_);
- }
- if (!FileSys().FileWrite(GenT::RCC, RccFilePublic_, content)) {
- Log().ErrorFile(GenT::RCC, RccFilePublic_,
- "RCC wrapper file writing failed");
- Error_ = true;
- }
- } else if (BuildFileChanged_) {
- // Just touch the wrapper file
- if (Log().Verbose()) {
- Log().Info(GenT::RCC, "Touching RCC wrapper file " + RccFilePublic_);
- }
- FileSys().Touch(RccFilePublic_);
- }
- }
-}
-
-bool cmQtAutoGeneratorRcc::StartProcess(
- std::string const& workingDirectory, std::vector<std::string> const& command,
- bool mergedOutput)
-{
- // Log command
- if (Log().Verbose()) {
- std::string msg = "Running command:\n";
- msg += QuotedCommand(command);
- msg += '\n';
- Log().Info(GenT::RCC, msg);
- }
-
- // Create process handler
- Process_ = cm::make_unique<ReadOnlyProcessT>();
- Process_->setup(&ProcessResult_, mergedOutput, command, workingDirectory);
- // Start process
- if (!Process_->start(UVLoop(), [this] { UVRequest().send(); })) {
- Log().ErrorFile(GenT::RCC, QrcFile_, ProcessResult_.ErrorMessage);
- Error_ = true;
- // Clean up
- Process_.reset();
- ProcessResult_.reset();
- return false;
- }
- return true;
-}
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index cb6f7ea..75c5d8a 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -1,10 +1,10 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGeneratorMocUic.h"
+#include "cmQtAutoMocUic.h"
#include <algorithm>
#include <array>
-#include <cstddef>
+#include <deque>
#include <list>
#include <memory>
#include <set>
@@ -24,7 +24,7 @@
// -- Class methods
-std::string cmQtAutoGeneratorMocUic::BaseSettingsT::AbsoluteBuildPath(
+std::string cmQtAutoMocUic::BaseSettingsT::AbsoluteBuildPath(
std::string const& relativePath) const
{
return FileSys->CollapseFullPath(relativePath, AutogenBuildDir);
@@ -35,7 +35,7 @@ std::string cmQtAutoGeneratorMocUic::BaseSettingsT::AbsoluteBuildPath(
* appending different header extensions
* @return True on success
*/
-bool cmQtAutoGeneratorMocUic::BaseSettingsT::FindHeader(
+bool cmQtAutoMocUic::BaseSettingsT::FindHeader(
std::string& header, std::string const& testBasePath) const
{
for (std::string const& ext : HeaderExtensions) {
@@ -50,8 +50,7 @@ bool cmQtAutoGeneratorMocUic::BaseSettingsT::FindHeader(
return false;
}
-bool cmQtAutoGeneratorMocUic::MocSettingsT::skipped(
- std::string const& fileName) const
+bool cmQtAutoMocUic::MocSettingsT::skipped(std::string const& fileName) const
{
return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
}
@@ -60,7 +59,7 @@ bool cmQtAutoGeneratorMocUic::MocSettingsT::skipped(
* @brief Returns the first relevant Qt macro name found in the given C++ code
* @return The name of the Qt macro or an empty string
*/
-std::string cmQtAutoGeneratorMocUic::MocSettingsT::FindMacro(
+std::string cmQtAutoMocUic::MocSettingsT::FindMacro(
std::string const& content) const
{
for (KeyExpT const& filter : MacroFilters) {
@@ -77,7 +76,7 @@ std::string cmQtAutoGeneratorMocUic::MocSettingsT::FindMacro(
return std::string();
}
-std::string cmQtAutoGeneratorMocUic::MocSettingsT::MacrosString() const
+std::string cmQtAutoMocUic::MocSettingsT::MacrosString() const
{
std::string res;
const auto itB = MacroFilters.cbegin();
@@ -99,7 +98,7 @@ std::string cmQtAutoGeneratorMocUic::MocSettingsT::MacrosString() const
return res;
}
-std::string cmQtAutoGeneratorMocUic::MocSettingsT::FindIncludedFile(
+std::string cmQtAutoMocUic::MocSettingsT::FindIncludedFile(
std::string const& sourcePath, std::string const& includeString) const
{
// Search in vicinity of the source
@@ -123,7 +122,7 @@ std::string cmQtAutoGeneratorMocUic::MocSettingsT::FindIncludedFile(
return std::string();
}
-void cmQtAutoGeneratorMocUic::MocSettingsT::FindDependencies(
+void cmQtAutoMocUic::MocSettingsT::FindDependencies(
std::string const& content, std::set<std::string>& depends) const
{
if (!DependFilters.empty() && !content.empty()) {
@@ -147,17 +146,124 @@ void cmQtAutoGeneratorMocUic::MocSettingsT::FindDependencies(
}
}
-bool cmQtAutoGeneratorMocUic::UicSettingsT::skipped(
- std::string const& fileName) const
+bool cmQtAutoMocUic::UicSettingsT::skipped(std::string const& fileName) const
{
return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
}
-void cmQtAutoGeneratorMocUic::JobParseT::Process(WorkerT& wrk)
+void cmQtAutoMocUic::JobT::LogError(GenT genType,
+ std::string const& message) const
+{
+ Gen()->AbortError();
+ Gen()->Log().Error(genType, message);
+}
+
+void cmQtAutoMocUic::JobT::LogFileError(GenT genType,
+ std::string const& filename,
+ std::string const& message) const
+{
+ Gen()->AbortError();
+ Gen()->Log().ErrorFile(genType, filename, message);
+}
+
+void cmQtAutoMocUic::JobT::LogCommandError(
+ GenT genType, std::string const& message,
+ std::vector<std::string> const& command, std::string const& output) const
+{
+ Gen()->AbortError();
+ Gen()->Log().ErrorCommand(genType, message, command, output);
+}
+
+bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
+ cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command)
+{
+ // Log command
+ if (Log().Verbose()) {
+ std::string msg = "Running command:\n";
+ msg += QuotedCommand(command);
+ msg += '\n';
+ Log().Info(genType, msg);
+ }
+ return cmWorkerPool::JobT::RunProcess(result, command,
+ Gen()->Base().AutogenBuildDir);
+}
+
+void cmQtAutoMocUic::JobMocPredefsT::Process()
+{
+ // (Re)generate moc_predefs.h on demand
+ bool generate(false);
+ bool fileExists(FileSys().FileExists(Gen()->Moc().PredefsFileAbs));
+ if (!fileExists) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(Gen()->Moc().PredefsFileRel);
+ reason += " because it doesn't exist";
+ Log().Info(GenT::MOC, reason);
+ }
+ generate = true;
+ } else if (Gen()->Moc().SettingsChanged) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(Gen()->Moc().PredefsFileRel);
+ reason += " because the settings changed.";
+ Log().Info(GenT::MOC, reason);
+ }
+ generate = true;
+ }
+ if (generate) {
+ cmWorkerPool::ProcessResultT result;
+ {
+ // Compose command
+ std::vector<std::string> cmd = Gen()->Moc().PredefsCmd;
+ // Add includes
+ cmd.insert(cmd.end(), Gen()->Moc().Includes.begin(),
+ Gen()->Moc().Includes.end());
+ // Add definitions
+ for (std::string const& def : Gen()->Moc().Definitions) {
+ cmd.push_back("-D" + def);
+ }
+ // Execute command
+ if (!RunProcess(GenT::MOC, result, cmd)) {
+ std::string emsg = "The content generation command for ";
+ emsg += Quoted(Gen()->Moc().PredefsFileRel);
+ emsg += " failed.\n";
+ emsg += result.ErrorMessage;
+ LogCommandError(GenT::MOC, emsg, cmd, result.StdOut);
+ }
+ }
+
+ // (Re)write predefs file only on demand
+ if (!result.error()) {
+ if (!fileExists ||
+ FileSys().FileDiffers(Gen()->Moc().PredefsFileAbs, result.StdOut)) {
+ if (FileSys().FileWrite(Gen()->Moc().PredefsFileAbs, result.StdOut)) {
+ // Success
+ } else {
+ std::string emsg = "Writing ";
+ emsg += Quoted(Gen()->Moc().PredefsFileRel);
+ emsg += " failed.";
+ LogFileError(GenT::MOC, Gen()->Moc().PredefsFileAbs, emsg);
+ }
+ } else {
+ // Touch to update the time stamp
+ if (Log().Verbose()) {
+ std::string msg = "Touching ";
+ msg += Quoted(Gen()->Moc().PredefsFileRel);
+ msg += ".";
+ Log().Info(GenT::MOC, msg);
+ }
+ FileSys().Touch(Gen()->Moc().PredefsFileAbs);
+ }
+ }
+ }
+}
+
+void cmQtAutoMocUic::JobParseT::Process()
{
if (AutoMoc && Header) {
// Don't parse header for moc if the file is included by a source already
- if (wrk.Gen().ParallelMocIncluded(FileName)) {
+ if (Gen()->ParallelMocIncluded(FileName)) {
AutoMoc = false;
}
}
@@ -165,35 +271,32 @@ void cmQtAutoGeneratorMocUic::JobParseT::Process(WorkerT& wrk)
if (AutoMoc || AutoUic) {
std::string error;
MetaT meta;
- if (wrk.FileSys().FileRead(meta.Content, FileName, &error)) {
+ if (FileSys().FileRead(meta.Content, FileName, &error)) {
if (!meta.Content.empty()) {
- meta.FileDir = wrk.FileSys().SubDirPrefix(FileName);
- meta.FileBase =
- wrk.FileSys().GetFilenameWithoutLastExtension(FileName);
+ meta.FileDir = FileSys().SubDirPrefix(FileName);
+ meta.FileBase = FileSys().GetFilenameWithoutLastExtension(FileName);
bool success = true;
if (AutoMoc) {
if (Header) {
- success = ParseMocHeader(wrk, meta);
+ success = ParseMocHeader(meta);
} else {
- success = ParseMocSource(wrk, meta);
+ success = ParseMocSource(meta);
}
}
if (AutoUic && success) {
- ParseUic(wrk, meta);
+ ParseUic(meta);
}
} else {
- wrk.LogFileWarning(GenT::GEN, FileName, "The source file is empty");
+ Log().WarningFile(GenT::GEN, FileName, "The source file is empty");
}
} else {
- wrk.LogFileError(GenT::GEN, FileName,
- "Could not read the file: " + error);
+ LogFileError(GenT::GEN, FileName, "Could not read the file: " + error);
}
}
}
-bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
- MetaT const& meta)
+bool cmQtAutoMocUic::JobParseT::ParseMocSource(MetaT const& meta)
{
struct JobPre
{
@@ -211,7 +314,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
};
// Check if this source file contains a relevant macro
- std::string const ownMacro = wrk.Moc().FindMacro(meta.Content);
+ std::string const ownMacro = Gen()->Moc().FindMacro(meta.Content);
// Extract moc includes from file
std::deque<MocInclude> mocIncsUsc;
@@ -220,11 +323,11 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
if (meta.Content.find("moc") != std::string::npos) {
const char* contentChars = meta.Content.c_str();
cmsys::RegularExpressionMatch match;
- while (wrk.Moc().RegExpInclude.find(contentChars, match)) {
+ while (Gen()->Moc().RegExpInclude.find(contentChars, match)) {
std::string incString = match.match(2);
- std::string incDir(wrk.FileSys().SubDirPrefix(incString));
+ std::string incDir(FileSys().SubDirPrefix(incString));
std::string incBase =
- wrk.FileSys().GetFilenameWithoutLastExtension(incString);
+ FileSys().GetFilenameWithoutLastExtension(incString);
if (cmHasLiteralPrefix(incBase, "moc_")) {
// moc_<BASE>.cxx
// Remove the moc_ part from the base name
@@ -253,10 +356,10 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
// Process moc_<BASE>.cxx includes
for (const MocInclude& mocInc : mocIncsUsc) {
std::string const header =
- MocFindIncludedHeader(wrk, meta.FileDir, mocInc.Dir + mocInc.Base);
+ MocFindIncludedHeader(meta.FileDir, mocInc.Dir + mocInc.Base);
if (!header.empty()) {
// Check if header is skipped
- if (wrk.Moc().skipped(header)) {
+ if (Gen()->Moc().skipped(header)) {
continue;
}
// Register moc job
@@ -271,9 +374,9 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
std::string emsg = "The file includes the moc file ";
emsg += Quoted(mocInc.Inc);
emsg += ", but the header ";
- emsg += Quoted(MocStringHeaders(wrk, mocInc.Base));
+ emsg += Quoted(MocStringHeaders(mocInc.Base));
emsg += " could not be found.";
- wrk.LogFileError(GenT::MOC, FileName, emsg);
+ LogFileError(GenT::MOC, FileName, emsg);
}
return false;
}
@@ -282,7 +385,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
// Process <BASE>.moc includes
for (const MocInclude& mocInc : mocIncsDot) {
const bool ownMoc = (mocInc.Base == meta.FileBase);
- if (wrk.Moc().RelaxedMode) {
+ if (Gen()->Moc().RelaxedMode) {
// Relaxed mode
if (!ownMacro.empty() && ownMoc) {
// Add self
@@ -292,10 +395,10 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
// In relaxed mode try to find a header instead but issue a warning.
// This is for KDE4 compatibility
std::string const header =
- MocFindIncludedHeader(wrk, meta.FileDir, mocInc.Dir + mocInc.Base);
+ MocFindIncludedHeader(meta.FileDir, mocInc.Dir + mocInc.Base);
if (!header.empty()) {
// Check if header is skipped
- if (wrk.Moc().skipped(header)) {
+ if (Gen()->Moc().skipped(header)) {
continue;
}
// Register moc job
@@ -305,14 +408,14 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
std::string emsg = "The file includes the moc file ";
emsg += Quoted(mocInc.Inc);
emsg += ", but does not contain a ";
- emsg += wrk.Moc().MacrosString();
+ emsg += Gen()->Moc().MacrosString();
emsg += " macro.\nRunning moc on\n ";
emsg += Quoted(header);
emsg += "!\nBetter include ";
emsg += Quoted("moc_" + mocInc.Base + ".cpp");
emsg += " for a compatibility with strict mode.\n"
"(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
- wrk.LogFileWarning(GenT::MOC, FileName, emsg);
+ Log().WarningFile(GenT::MOC, FileName, emsg);
} else {
std::string emsg = "The file includes the moc file ";
emsg += Quoted(mocInc.Inc);
@@ -324,7 +427,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
emsg += Quoted("moc_" + mocInc.Base + ".cpp");
emsg += " for compatibility with strict mode.\n"
"(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
- wrk.LogFileWarning(GenT::MOC, FileName, emsg);
+ Log().WarningFile(GenT::MOC, FileName, emsg);
}
}
} else {
@@ -334,9 +437,9 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
emsg += ", which seems to be the moc file from a different "
"source file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a "
"matching header ";
- emsg += Quoted(MocStringHeaders(wrk, mocInc.Base));
+ emsg += Quoted(MocStringHeaders(mocInc.Base));
emsg += " could not be found.";
- wrk.LogFileError(GenT::MOC, FileName, emsg);
+ LogFileError(GenT::MOC, FileName, emsg);
}
return false;
}
@@ -352,9 +455,9 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
std::string emsg = "The file includes the moc file ";
emsg += Quoted(mocInc.Inc);
emsg += ", but does not contain a ";
- emsg += wrk.Moc().MacrosString();
+ emsg += Gen()->Moc().MacrosString();
emsg += " macro.";
- wrk.LogFileWarning(GenT::MOC, FileName, emsg);
+ Log().WarningFile(GenT::MOC, FileName, emsg);
}
} else {
// Don't allow <BASE>.moc include other than self in strict mode
@@ -365,7 +468,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
"source file.\nThis is not supported. Include ";
emsg += Quoted(meta.FileBase + ".moc");
emsg += " to run moc on this source file.";
- wrk.LogFileError(GenT::MOC, FileName, emsg);
+ LogFileError(GenT::MOC, FileName, emsg);
}
return false;
}
@@ -379,7 +482,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
// foo.cpp instead of foo.h, because otherwise it won't build.
// But warn, since this is not how it is supposed to be used.
// This is for KDE4 compatibility.
- if (wrk.Moc().RelaxedMode && ownMocUscIncluded) {
+ if (Gen()->Moc().RelaxedMode && ownMocUscIncluded) {
JobPre uscJobPre;
// Remove underscore job request
{
@@ -408,7 +511,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
emsg += Quoted(meta.FileBase + ".moc");
emsg += " for compatibility with strict mode.\n"
"(CMAKE_AUTOMOC_RELAXED_MODE warning)";
- wrk.LogFileWarning(GenT::MOC, FileName, emsg);
+ Log().WarningFile(GenT::MOC, FileName, emsg);
}
// Add own source job
jobs.emplace_back(
@@ -423,7 +526,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
emsg += "!\nConsider to\n - add #include \"";
emsg += meta.FileBase;
emsg += ".moc\"\n - enable SKIP_AUTOMOC for this file";
- wrk.LogFileError(GenT::MOC, FileName, emsg);
+ LogFileError(GenT::MOC, FileName, emsg);
}
return false;
}
@@ -431,76 +534,80 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
// Convert pre jobs to actual jobs
for (JobPre& jobPre : jobs) {
- JobHandleT jobHandle = cm::make_unique<JobMocT>(
+ cmWorkerPool::JobHandleT jobHandle = cm::make_unique<JobMocT>(
std::move(jobPre.SourceFile), FileName, std::move(jobPre.IncludeString));
if (jobPre.self) {
// Read dependencies from this source
- static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
+ JobMocT& jobMoc = static_cast<JobMocT&>(*jobHandle);
+ Gen()->Moc().FindDependencies(meta.Content, jobMoc.Depends);
+ jobMoc.DependsValid = true;
}
- if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) {
+ if (!Gen()->ParallelJobPushMoc(std::move(jobHandle))) {
return false;
}
}
return true;
}
-bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocHeader(WorkerT& wrk,
- MetaT const& meta)
+bool cmQtAutoMocUic::JobParseT::ParseMocHeader(MetaT const& meta)
{
bool success = true;
- std::string const macroName = wrk.Moc().FindMacro(meta.Content);
+ std::string const macroName = Gen()->Moc().FindMacro(meta.Content);
if (!macroName.empty()) {
- JobHandleT jobHandle = cm::make_unique<JobMocT>(
+ cmWorkerPool::JobHandleT jobHandle = cm::make_unique<JobMocT>(
std::string(FileName), std::string(), std::string());
// Read dependencies from this source
- static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
- success = wrk.Gen().ParallelJobPushMoc(jobHandle);
+ {
+ JobMocT& jobMoc = static_cast<JobMocT&>(*jobHandle);
+ Gen()->Moc().FindDependencies(meta.Content, jobMoc.Depends);
+ jobMoc.DependsValid = true;
+ }
+ success = Gen()->ParallelJobPushMoc(std::move(jobHandle));
}
return success;
}
-std::string cmQtAutoGeneratorMocUic::JobParseT::MocStringHeaders(
- WorkerT& wrk, std::string const& fileBase) const
+std::string cmQtAutoMocUic::JobParseT::MocStringHeaders(
+ std::string const& fileBase) const
{
std::string res = fileBase;
res += ".{";
- res += cmJoin(wrk.Base().HeaderExtensions, ",");
+ res += cmJoin(Gen()->Base().HeaderExtensions, ",");
res += "}";
return res;
}
-std::string cmQtAutoGeneratorMocUic::JobParseT::MocFindIncludedHeader(
- WorkerT& wrk, std::string const& includerDir, std::string const& includeBase)
+std::string cmQtAutoMocUic::JobParseT::MocFindIncludedHeader(
+ std::string const& includerDir, std::string const& includeBase)
{
std::string header;
// Search in vicinity of the source
- if (!wrk.Base().FindHeader(header, includerDir + includeBase)) {
+ if (!Gen()->Base().FindHeader(header, includerDir + includeBase)) {
// Search in include directories
- for (std::string const& path : wrk.Moc().IncludePaths) {
+ for (std::string const& path : Gen()->Moc().IncludePaths) {
std::string fullPath = path;
fullPath.push_back('/');
fullPath += includeBase;
- if (wrk.Base().FindHeader(header, fullPath)) {
+ if (Gen()->Base().FindHeader(header, fullPath)) {
break;
}
}
}
// Sanitize
if (!header.empty()) {
- header = wrk.FileSys().GetRealPath(header);
+ header = FileSys().GetRealPath(header);
}
return header;
}
-bool cmQtAutoGeneratorMocUic::JobParseT::ParseUic(WorkerT& wrk,
- MetaT const& meta)
+bool cmQtAutoMocUic::JobParseT::ParseUic(MetaT const& meta)
{
bool success = true;
if (meta.Content.find("ui_") != std::string::npos) {
const char* contentChars = meta.Content.c_str();
cmsys::RegularExpressionMatch match;
- while (wrk.Uic().RegExpInclude.find(contentChars, match)) {
- if (!ParseUicInclude(wrk, meta, match.match(2))) {
+ while (Gen()->Uic().RegExpInclude.find(contentChars, match)) {
+ if (!ParseUicInclude(meta, match.match(2))) {
success = false;
break;
}
@@ -510,16 +617,16 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseUic(WorkerT& wrk,
return success;
}
-bool cmQtAutoGeneratorMocUic::JobParseT::ParseUicInclude(
- WorkerT& wrk, MetaT const& meta, std::string&& includeString)
+bool cmQtAutoMocUic::JobParseT::ParseUicInclude(MetaT const& meta,
+ std::string&& includeString)
{
bool success = false;
- std::string uiInputFile = UicFindIncludedFile(wrk, meta, includeString);
+ std::string uiInputFile = UicFindIncludedFile(meta, includeString);
if (!uiInputFile.empty()) {
- if (!wrk.Uic().skipped(uiInputFile)) {
- JobHandleT jobHandle = cm::make_unique<JobUicT>(
+ if (!Gen()->Uic().skipped(uiInputFile)) {
+ cmWorkerPool::JobHandleT jobHandle = cm::make_unique<JobUicT>(
std::move(uiInputFile), FileName, std::move(includeString));
- success = wrk.Gen().ParallelJobPushUic(jobHandle);
+ success = Gen()->ParallelJobPushUic(std::move(jobHandle));
} else {
// A skipped file is successful
success = true;
@@ -528,17 +635,17 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseUicInclude(
return success;
}
-std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile(
- WorkerT& wrk, MetaT const& meta, std::string const& includeString)
+std::string cmQtAutoMocUic::JobParseT::UicFindIncludedFile(
+ MetaT const& meta, std::string const& includeString)
{
std::string res;
std::string searchFile =
- wrk.FileSys().GetFilenameWithoutLastExtension(includeString).substr(3);
+ FileSys().GetFilenameWithoutLastExtension(includeString).substr(3);
searchFile += ".ui";
// Collect search paths list
std::deque<std::string> testFiles;
{
- std::string const searchPath = wrk.FileSys().SubDirPrefix(includeString);
+ std::string const searchPath = FileSys().SubDirPrefix(includeString);
std::string searchFileFull;
if (!searchPath.empty()) {
@@ -554,12 +661,12 @@ std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile(
}
}
// AUTOUIC search paths
- if (!wrk.Uic().SearchPaths.empty()) {
- for (std::string const& sPath : wrk.Uic().SearchPaths) {
+ if (!Gen()->Uic().SearchPaths.empty()) {
+ for (std::string const& sPath : Gen()->Uic().SearchPaths) {
testFiles.push_back((sPath + "/").append(searchFile));
}
if (!searchPath.empty()) {
- for (std::string const& sPath : wrk.Uic().SearchPaths) {
+ for (std::string const& sPath : Gen()->Uic().SearchPaths) {
testFiles.push_back((sPath + "/").append(searchFileFull));
}
}
@@ -568,8 +675,8 @@ std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile(
// Search for the .ui file!
for (std::string const& testFile : testFiles) {
- if (wrk.FileSys().FileExists(testFile)) {
- res = wrk.FileSys().GetRealPath(testFile);
+ if (FileSys().FileExists(testFile)) {
+ res = FileSys().GetRealPath(testFile);
break;
}
}
@@ -584,160 +691,140 @@ std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile(
emsg += Quoted(testFile);
emsg += "\n";
}
- wrk.LogFileError(GenT::UIC, FileName, emsg);
+ LogFileError(GenT::UIC, FileName, emsg);
}
return res;
}
-void cmQtAutoGeneratorMocUic::JobMocPredefsT::Process(WorkerT& wrk)
+void cmQtAutoMocUic::JobPostParseT::Process()
{
- // (Re)generate moc_predefs.h on demand
- bool generate(false);
- bool fileExists(wrk.FileSys().FileExists(wrk.Moc().PredefsFileAbs));
- if (!fileExists) {
- if (wrk.Log().Verbose()) {
- std::string reason = "Generating ";
- reason += Quoted(wrk.Moc().PredefsFileRel);
- reason += " because it doesn't exist";
- wrk.LogInfo(GenT::MOC, reason);
- }
- generate = true;
- } else if (wrk.Moc().SettingsChanged) {
- if (wrk.Log().Verbose()) {
- std::string reason = "Generating ";
- reason += Quoted(wrk.Moc().PredefsFileRel);
- reason += " because the settings changed.";
- wrk.LogInfo(GenT::MOC, reason);
- }
- generate = true;
+ if (Gen()->Moc().Enabled) {
+ // Add mocs compilations fence job
+ Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
}
- if (generate) {
- ProcessResultT result;
- {
- // Compose command
- std::vector<std::string> cmd = wrk.Moc().PredefsCmd;
- // Add includes
- cmd.insert(cmd.end(), wrk.Moc().Includes.begin(),
- wrk.Moc().Includes.end());
- // Add definitions
- for (std::string const& def : wrk.Moc().Definitions) {
- cmd.push_back("-D" + def);
- }
- // Execute command
- if (!wrk.RunProcess(GenT::MOC, result, cmd)) {
- std::string emsg = "The content generation command for ";
- emsg += Quoted(wrk.Moc().PredefsFileRel);
- emsg += " failed.\n";
- emsg += result.ErrorMessage;
- wrk.LogCommandError(GenT::MOC, emsg, cmd, result.StdOut);
- }
+ // Add finish job
+ Gen()->WorkerPool().EmplaceJob<JobFinishT>();
+}
+
+void cmQtAutoMocUic::JobMocsCompilationT::Process()
+{
+ // Compose mocs compilation file content
+ std::string content =
+ "// This file is autogenerated. Changes will be overwritten.\n";
+ if (Gen()->MocAutoFiles().empty()) {
+ // Placeholder content
+ content += "// No files found that require moc or the moc files are "
+ "included\n";
+ content += "enum some_compilers { need_more_than_nothing };\n";
+ } else {
+ // Valid content
+ char const sbeg = Gen()->Base().MultiConfig ? '<' : '"';
+ char const send = Gen()->Base().MultiConfig ? '>' : '"';
+ for (std::string const& mocfile : Gen()->MocAutoFiles()) {
+ content += "#include ";
+ content += sbeg;
+ content += mocfile;
+ content += send;
+ content += '\n';
}
+ }
- // (Re)write predefs file only on demand
- if (!result.error()) {
- if (!fileExists ||
- wrk.FileSys().FileDiffers(wrk.Moc().PredefsFileAbs, result.StdOut)) {
- if (wrk.FileSys().FileWrite(GenT::MOC, wrk.Moc().PredefsFileAbs,
- result.StdOut)) {
- // Success
- } else {
- std::string emsg = "Writing ";
- emsg += Quoted(wrk.Moc().PredefsFileRel);
- emsg += " failed.";
- wrk.LogFileError(GenT::MOC, wrk.Moc().PredefsFileAbs, emsg);
- }
- } else {
- // Touch to update the time stamp
- if (wrk.Log().Verbose()) {
- std::string msg = "Touching ";
- msg += Quoted(wrk.Moc().PredefsFileRel);
- msg += ".";
- wrk.LogInfo(GenT::MOC, msg);
- }
- wrk.FileSys().Touch(wrk.Moc().PredefsFileAbs);
- }
+ std::string const& compAbs = Gen()->Moc().CompFileAbs;
+ if (FileSys().FileDiffers(compAbs, content)) {
+ // Actually write mocs compilation file
+ if (Log().Verbose()) {
+ Log().Info(GenT::MOC, "Generating MOC compilation " + compAbs);
+ }
+ if (!FileSys().FileWrite(compAbs, content)) {
+ LogFileError(GenT::MOC, compAbs,
+ "mocs compilation file writing failed.");
}
+ } else if (Gen()->MocAutoFileUpdated()) {
+ // Only touch mocs compilation file
+ if (Log().Verbose()) {
+ Log().Info(GenT::MOC, "Touching mocs compilation " + compAbs);
+ }
+ FileSys().Touch(compAbs);
}
}
-void cmQtAutoGeneratorMocUic::JobMocT::FindDependencies(
- WorkerT& wrk, std::string const& content)
+void cmQtAutoMocUic::JobMocT::FindDependencies(std::string const& content)
{
- wrk.Moc().FindDependencies(content, Depends);
+ Gen()->Moc().FindDependencies(content, Depends);
DependsValid = true;
}
-void cmQtAutoGeneratorMocUic::JobMocT::Process(WorkerT& wrk)
+void cmQtAutoMocUic::JobMocT::Process()
{
// Compute build file name
if (!IncludeString.empty()) {
- BuildFile = wrk.Base().AutogenIncludeDir;
+ BuildFile = Gen()->Base().AutogenIncludeDir;
BuildFile += '/';
BuildFile += IncludeString;
} else {
// Relative build path
- std::string relPath = wrk.FileSys().GetFilePathChecksum(SourceFile);
+ std::string relPath = FileSys().GetFilePathChecksum(SourceFile);
relPath += "/moc_";
- relPath += wrk.FileSys().GetFilenameWithoutLastExtension(SourceFile);
+ relPath += FileSys().GetFilenameWithoutLastExtension(SourceFile);
// Register relative file path with duplication check
- relPath = wrk.Gen().ParallelMocAutoRegister(relPath);
+ relPath = Gen()->ParallelMocAutoRegister(relPath);
// Absolute build path
- if (wrk.Base().MultiConfig) {
- BuildFile = wrk.Base().AutogenIncludeDir;
+ if (Gen()->Base().MultiConfig) {
+ BuildFile = Gen()->Base().AutogenIncludeDir;
BuildFile += '/';
BuildFile += relPath;
} else {
- BuildFile = wrk.Base().AbsoluteBuildPath(relPath);
+ BuildFile = Gen()->Base().AbsoluteBuildPath(relPath);
}
}
- if (UpdateRequired(wrk)) {
- GenerateMoc(wrk);
+ if (UpdateRequired()) {
+ GenerateMoc();
}
}
-bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
+bool cmQtAutoMocUic::JobMocT::UpdateRequired()
{
- bool const verbose = wrk.Gen().Log().Verbose();
+ bool const verbose = Log().Verbose();
// Test if the build file exists
- if (!wrk.FileSys().FileExists(BuildFile)) {
+ if (!FileSys().FileExists(BuildFile)) {
if (verbose) {
std::string reason = "Generating ";
reason += Quoted(BuildFile);
reason += " from its source file ";
reason += Quoted(SourceFile);
reason += " because it doesn't exist";
- wrk.LogInfo(GenT::MOC, reason);
+ Log().Info(GenT::MOC, reason);
}
return true;
}
// Test if any setting changed
- if (wrk.Moc().SettingsChanged) {
+ if (Gen()->Moc().SettingsChanged) {
if (verbose) {
std::string reason = "Generating ";
reason += Quoted(BuildFile);
reason += " from ";
reason += Quoted(SourceFile);
reason += " because the MOC settings changed";
- wrk.LogInfo(GenT::MOC, reason);
+ Log().Info(GenT::MOC, reason);
}
return true;
}
// Test if the moc_predefs file is newer
- if (!wrk.Moc().PredefsFileAbs.empty()) {
+ if (!Gen()->Moc().PredefsFileAbs.empty()) {
bool isOlder = false;
{
std::string error;
- isOlder = wrk.FileSys().FileIsOlderThan(
- BuildFile, wrk.Moc().PredefsFileAbs, &error);
+ isOlder = FileSys().FileIsOlderThan(BuildFile,
+ Gen()->Moc().PredefsFileAbs, &error);
if (!isOlder && !error.empty()) {
- wrk.LogError(GenT::MOC, error);
+ LogError(GenT::MOC, error);
return false;
}
}
@@ -746,8 +833,8 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
std::string reason = "Generating ";
reason += Quoted(BuildFile);
reason += " because it's older than: ";
- reason += Quoted(wrk.Moc().PredefsFileAbs);
- wrk.LogInfo(GenT::MOC, reason);
+ reason += Quoted(Gen()->Moc().PredefsFileAbs);
+ Log().Info(GenT::MOC, reason);
}
return true;
}
@@ -758,9 +845,9 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
bool isOlder = false;
{
std::string error;
- isOlder = wrk.FileSys().FileIsOlderThan(BuildFile, SourceFile, &error);
+ isOlder = FileSys().FileIsOlderThan(BuildFile, SourceFile, &error);
if (!isOlder && !error.empty()) {
- wrk.LogError(GenT::MOC, error);
+ LogError(GenT::MOC, error);
return false;
}
}
@@ -770,7 +857,7 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
reason += Quoted(BuildFile);
reason += " because it's older than its source file ";
reason += Quoted(SourceFile);
- wrk.LogInfo(GenT::MOC, reason);
+ Log().Info(GenT::MOC, reason);
}
return true;
}
@@ -783,7 +870,7 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
std::string content;
{
std::string error;
- if (!wrk.FileSys().FileRead(content, SourceFile, &error)) {
+ if (!FileSys().FileRead(content, SourceFile, &error)) {
std::string emsg = "Could not read file\n ";
emsg += Quoted(SourceFile);
emsg += "\nrequired by moc include ";
@@ -792,20 +879,20 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
emsg += Quoted(IncluderFile);
emsg += ".\n";
emsg += error;
- wrk.LogError(GenT::MOC, emsg);
+ LogError(GenT::MOC, emsg);
return false;
}
}
- FindDependencies(wrk, content);
+ FindDependencies(content);
}
// Check dependency timestamps
std::string error;
- std::string sourceDir = wrk.FileSys().SubDirPrefix(SourceFile);
+ std::string sourceDir = FileSys().SubDirPrefix(SourceFile);
for (std::string const& depFileRel : Depends) {
std::string depFileAbs =
- wrk.Moc().FindIncludedFile(sourceDir, depFileRel);
+ Gen()->Moc().FindIncludedFile(sourceDir, depFileRel);
if (!depFileAbs.empty()) {
- if (wrk.FileSys().FileIsOlderThan(BuildFile, depFileAbs, &error)) {
+ if (FileSys().FileIsOlderThan(BuildFile, depFileAbs, &error)) {
if (verbose) {
std::string reason = "Generating ";
reason += Quoted(BuildFile);
@@ -813,18 +900,18 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
reason += Quoted(SourceFile);
reason += " because it is older than it's dependency file ";
reason += Quoted(depFileAbs);
- wrk.LogInfo(GenT::MOC, reason);
+ Log().Info(GenT::MOC, reason);
}
return true;
}
if (!error.empty()) {
- wrk.LogError(GenT::MOC, error);
+ LogError(GenT::MOC, error);
return false;
}
} else {
std::string message = "Could not find dependency file ";
message += Quoted(depFileRel);
- wrk.LogFileWarning(GenT::MOC, SourceFile, message);
+ Log().WarningFile(GenT::MOC, SourceFile, message);
}
}
}
@@ -832,36 +919,40 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
return false;
}
-void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk)
+void cmQtAutoMocUic::JobMocT::GenerateMoc()
{
// Make sure the parent directory exists
- if (wrk.FileSys().MakeParentDirectory(GenT::MOC, BuildFile)) {
+ if (!FileSys().MakeParentDirectory(BuildFile)) {
+ LogFileError(GenT::MOC, BuildFile, "Could not create parent directory.");
+ return;
+ }
+ {
// Compose moc command
std::vector<std::string> cmd;
- cmd.push_back(wrk.Moc().Executable);
+ cmd.push_back(Gen()->Moc().Executable);
// Add options
- cmd.insert(cmd.end(), wrk.Moc().AllOptions.begin(),
- wrk.Moc().AllOptions.end());
+ cmd.insert(cmd.end(), Gen()->Moc().AllOptions.begin(),
+ Gen()->Moc().AllOptions.end());
// Add predefs include
- if (!wrk.Moc().PredefsFileAbs.empty()) {
+ if (!Gen()->Moc().PredefsFileAbs.empty()) {
cmd.emplace_back("--include");
- cmd.push_back(wrk.Moc().PredefsFileAbs);
+ cmd.push_back(Gen()->Moc().PredefsFileAbs);
}
cmd.emplace_back("-o");
cmd.push_back(BuildFile);
cmd.push_back(SourceFile);
// Execute moc command
- ProcessResultT result;
- if (wrk.RunProcess(GenT::MOC, result, cmd)) {
+ cmWorkerPool::ProcessResultT result;
+ if (RunProcess(GenT::MOC, result, cmd)) {
// Moc command success
// Print moc output
if (!result.StdOut.empty()) {
- wrk.LogInfo(GenT::MOC, result.StdOut);
+ Log().Info(GenT::MOC, result.StdOut);
}
// Notify the generator that a not included file changed (on demand)
if (IncludeString.empty()) {
- wrk.Gen().ParallelMocAutoUpdated();
+ Gen()->ParallelMocAutoUpdated();
}
} else {
// Moc command failed
@@ -872,51 +963,51 @@ void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk)
emsg += Quoted(BuildFile);
emsg += ".\n";
emsg += result.ErrorMessage;
- wrk.LogCommandError(GenT::MOC, emsg, cmd, result.StdOut);
+ LogCommandError(GenT::MOC, emsg, cmd, result.StdOut);
}
- wrk.FileSys().FileRemove(BuildFile);
+ FileSys().FileRemove(BuildFile);
}
}
}
-void cmQtAutoGeneratorMocUic::JobUicT::Process(WorkerT& wrk)
+void cmQtAutoMocUic::JobUicT::Process()
{
// Compute build file name
- BuildFile = wrk.Base().AutogenIncludeDir;
+ BuildFile = Gen()->Base().AutogenIncludeDir;
BuildFile += '/';
BuildFile += IncludeString;
- if (UpdateRequired(wrk)) {
- GenerateUic(wrk);
+ if (UpdateRequired()) {
+ GenerateUic();
}
}
-bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk)
+bool cmQtAutoMocUic::JobUicT::UpdateRequired()
{
- bool const verbose = wrk.Gen().Log().Verbose();
+ bool const verbose = Log().Verbose();
// Test if the build file exists
- if (!wrk.FileSys().FileExists(BuildFile)) {
+ if (!FileSys().FileExists(BuildFile)) {
if (verbose) {
std::string reason = "Generating ";
reason += Quoted(BuildFile);
reason += " from its source file ";
reason += Quoted(SourceFile);
reason += " because it doesn't exist";
- wrk.LogInfo(GenT::UIC, reason);
+ Log().Info(GenT::UIC, reason);
}
return true;
}
// Test if the uic settings changed
- if (wrk.Uic().SettingsChanged) {
+ if (Gen()->Uic().SettingsChanged) {
if (verbose) {
std::string reason = "Generating ";
reason += Quoted(BuildFile);
reason += " from ";
reason += Quoted(SourceFile);
reason += " because the UIC settings changed";
- wrk.LogInfo(GenT::UIC, reason);
+ Log().Info(GenT::UIC, reason);
}
return true;
}
@@ -926,9 +1017,9 @@ bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk)
bool isOlder = false;
{
std::string error;
- isOlder = wrk.FileSys().FileIsOlderThan(BuildFile, SourceFile, &error);
+ isOlder = FileSys().FileIsOlderThan(BuildFile, SourceFile, &error);
if (!isOlder && !error.empty()) {
- wrk.LogError(GenT::UIC, error);
+ LogError(GenT::UIC, error);
return false;
}
}
@@ -938,7 +1029,7 @@ bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk)
reason += Quoted(BuildFile);
reason += " because it's older than its source file ";
reason += Quoted(SourceFile);
- wrk.LogInfo(GenT::UIC, reason);
+ Log().Info(GenT::UIC, reason);
}
return true;
}
@@ -947,32 +1038,36 @@ bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk)
return false;
}
-void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk)
+void cmQtAutoMocUic::JobUicT::GenerateUic()
{
// Make sure the parent directory exists
- if (wrk.FileSys().MakeParentDirectory(GenT::UIC, BuildFile)) {
+ if (!FileSys().MakeParentDirectory(BuildFile)) {
+ LogFileError(GenT::UIC, BuildFile, "Could not create parent directory.");
+ return;
+ }
+ {
// Compose uic command
std::vector<std::string> cmd;
- cmd.push_back(wrk.Uic().Executable);
+ cmd.push_back(Gen()->Uic().Executable);
{
- std::vector<std::string> allOpts = wrk.Uic().TargetOptions;
- auto optionIt = wrk.Uic().Options.find(SourceFile);
- if (optionIt != wrk.Uic().Options.end()) {
+ std::vector<std::string> allOpts = Gen()->Uic().TargetOptions;
+ auto optionIt = Gen()->Uic().Options.find(SourceFile);
+ if (optionIt != Gen()->Uic().Options.end()) {
UicMergeOptions(allOpts, optionIt->second,
- (wrk.Base().QtVersionMajor == 5));
+ (Gen()->Base().QtVersionMajor == 5));
}
cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
}
cmd.emplace_back("-o");
- cmd.push_back(BuildFile);
- cmd.push_back(SourceFile);
+ cmd.emplace_back(BuildFile);
+ cmd.emplace_back(SourceFile);
- ProcessResultT result;
- if (wrk.RunProcess(GenT::UIC, result, cmd)) {
+ cmWorkerPool::ProcessResultT result;
+ if (RunProcess(GenT::UIC, result, cmd)) {
// Uic command success
// Print uic output
if (!result.StdOut.empty()) {
- wrk.LogInfo(GenT::UIC, result.StdOut);
+ Log().Info(GenT::UIC, result.StdOut);
}
} else {
// Uic command failed
@@ -985,143 +1080,19 @@ void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk)
emsg += Quoted(IncluderFile);
emsg += ".\n";
emsg += result.ErrorMessage;
- wrk.LogCommandError(GenT::UIC, emsg, cmd, result.StdOut);
+ LogCommandError(GenT::UIC, emsg, cmd, result.StdOut);
}
- wrk.FileSys().FileRemove(BuildFile);
+ FileSys().FileRemove(BuildFile);
}
}
}
-cmQtAutoGeneratorMocUic::WorkerT::WorkerT(cmQtAutoGeneratorMocUic* gen,
- uv_loop_t* uvLoop)
- : Gen_(gen)
-{
- // Initialize uv asynchronous callback for process starting
- ProcessRequest_.init(*uvLoop, &WorkerT::UVProcessStart, this);
- // Start thread
- Thread_ = std::thread(&WorkerT::Loop, this);
-}
-
-cmQtAutoGeneratorMocUic::WorkerT::~WorkerT()
-{
- // Join thread
- if (Thread_.joinable()) {
- Thread_.join();
- }
-}
-
-void cmQtAutoGeneratorMocUic::WorkerT::LogInfo(
- GenT genType, std::string const& message) const
-{
- Log().Info(genType, message);
-}
-
-void cmQtAutoGeneratorMocUic::WorkerT::LogWarning(
- GenT genType, std::string const& message) const
-{
- Log().Warning(genType, message);
-}
-
-void cmQtAutoGeneratorMocUic::WorkerT::LogFileWarning(
- GenT genType, std::string const& filename, std::string const& message) const
+void cmQtAutoMocUic::JobFinishT::Process()
{
- Log().WarningFile(genType, filename, message);
-}
-
-void cmQtAutoGeneratorMocUic::WorkerT::LogError(
- GenT genType, std::string const& message) const
-{
- Gen().ParallelRegisterJobError();
- Log().Error(genType, message);
-}
-
-void cmQtAutoGeneratorMocUic::WorkerT::LogFileError(
- GenT genType, std::string const& filename, std::string const& message) const
-{
- Gen().ParallelRegisterJobError();
- Log().ErrorFile(genType, filename, message);
-}
-
-void cmQtAutoGeneratorMocUic::WorkerT::LogCommandError(
- GenT genType, std::string const& message,
- std::vector<std::string> const& command, std::string const& output) const
-{
- Gen().ParallelRegisterJobError();
- Log().ErrorCommand(genType, message, command, output);
-}
-
-bool cmQtAutoGeneratorMocUic::WorkerT::RunProcess(
- GenT genType, ProcessResultT& result,
- std::vector<std::string> const& command)
-{
- if (command.empty()) {
- return false;
- }
-
- // Create process instance
- {
- std::lock_guard<std::mutex> lock(ProcessMutex_);
- Process_ = cm::make_unique<ReadOnlyProcessT>();
- Process_->setup(&result, true, command, Gen().Base().AutogenBuildDir);
- }
-
- // Send asynchronous process start request to libuv loop
- ProcessRequest_.send();
-
- // Log command
- if (this->Log().Verbose()) {
- std::string msg = "Running command:\n";
- msg += QuotedCommand(command);
- msg += '\n';
- this->LogInfo(genType, msg);
- }
-
- // Wait until the process has been finished and destroyed
- {
- std::unique_lock<std::mutex> ulock(ProcessMutex_);
- while (Process_) {
- ProcessCondition_.wait(ulock);
- }
- }
- return !result.error();
+ Gen()->AbortSuccess();
}
-void cmQtAutoGeneratorMocUic::WorkerT::Loop()
-{
- while (true) {
- Gen().WorkerSwapJob(JobHandle_);
- if (JobHandle_) {
- JobHandle_->Process(*this);
- } else {
- break;
- }
- }
-}
-
-void cmQtAutoGeneratorMocUic::WorkerT::UVProcessStart(uv_async_t* handle)
-{
- auto& wrk = *reinterpret_cast<WorkerT*>(handle->data);
- {
- std::lock_guard<std::mutex> lock(wrk.ProcessMutex_);
- if (wrk.Process_ && !wrk.Process_->IsStarted()) {
- wrk.Process_->start(handle->loop, [&wrk] { wrk.UVProcessFinished(); });
- }
- }
-}
-
-void cmQtAutoGeneratorMocUic::WorkerT::UVProcessFinished()
-{
- {
- std::lock_guard<std::mutex> lock(ProcessMutex_);
- if (Process_ && Process_->IsFinished()) {
- Process_.reset();
- }
- }
- // Notify idling thread
- ProcessCondition_.notify_one();
-}
-
-cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
+cmQtAutoMocUic::cmQtAutoMocUic()
: Base_(&FileSys())
, Moc_(&FileSys())
{
@@ -1131,14 +1102,11 @@ cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
"[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
Uic_.RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
"[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
-
- // Initialize libuv asynchronous iteration request
- UVRequest().init(*UVLoop(), &cmQtAutoGeneratorMocUic::UVPollStage, this);
}
-cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic() = default;
+cmQtAutoMocUic::~cmQtAutoMocUic() = default;
-bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
+bool cmQtAutoMocUic::Init(cmMakefile* makefile)
{
// -- Meta
Base_.HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
@@ -1336,7 +1304,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
Moc_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
// Install moc predefs job
if (!Moc().PredefsCmd.empty()) {
- JobQueues_.MocPredefs.emplace_back(cm::make_unique<JobMocPredefsT>());
+ WorkerPool().EmplaceJob<JobMocPredefsT>();
}
}
@@ -1372,46 +1340,48 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
}
// - Headers and sources
+ // Add sources
{
- auto addHeader = [this](std::string&& hdr, bool moc, bool uic) {
- this->JobQueues_.Headers.emplace_back(
- cm::make_unique<JobParseT>(std::move(hdr), moc, uic, true));
- };
auto addSource = [this](std::string&& src, bool moc, bool uic) {
- this->JobQueues_.Sources.emplace_back(
- cm::make_unique<JobParseT>(std::move(src), moc, uic, false));
+ WorkerPool().EmplaceJob<JobParseT>(std::move(src), moc, uic, false);
};
-
- // Add headers
- for (std::string& hdr : InfoGetList("AM_HEADERS")) {
- addHeader(std::move(hdr), true, true);
+ for (std::string& src : InfoGetList("AM_SOURCES")) {
+ addSource(std::move(src), true, true);
}
if (Moc().Enabled) {
- for (std::string& hdr : InfoGetList("AM_MOC_HEADERS")) {
- addHeader(std::move(hdr), true, false);
+ for (std::string& src : InfoGetList("AM_MOC_SOURCES")) {
+ addSource(std::move(src), true, false);
}
}
if (Uic().Enabled) {
- for (std::string& hdr : InfoGetList("AM_UIC_HEADERS")) {
- addHeader(std::move(hdr), false, true);
+ for (std::string& src : InfoGetList("AM_UIC_SOURCES")) {
+ addSource(std::move(src), false, true);
}
}
-
- // Add sources
- for (std::string& src : InfoGetList("AM_SOURCES")) {
- addSource(std::move(src), true, true);
+ }
+ // Add Fence job
+ WorkerPool().EmplaceJob<JobFenceT>();
+ // Add headers
+ {
+ auto addHeader = [this](std::string&& hdr, bool moc, bool uic) {
+ WorkerPool().EmplaceJob<JobParseT>(std::move(hdr), moc, uic, true);
+ };
+ for (std::string& hdr : InfoGetList("AM_HEADERS")) {
+ addHeader(std::move(hdr), true, true);
}
if (Moc().Enabled) {
- for (std::string& src : InfoGetList("AM_MOC_SOURCES")) {
- addSource(std::move(src), true, false);
+ for (std::string& hdr : InfoGetList("AM_MOC_HEADERS")) {
+ addHeader(std::move(hdr), true, false);
}
}
if (Uic().Enabled) {
- for (std::string& src : InfoGetList("AM_UIC_SOURCES")) {
- addSource(std::move(src), false, true);
+ for (std::string& hdr : InfoGetList("AM_UIC_HEADERS")) {
+ addHeader(std::move(hdr), false, true);
}
}
}
+ // Addpost parse fence job
+ WorkerPool().EmplaceJob<JobPostParseT>();
// Init derived information
// ------------------------
@@ -1506,98 +1476,25 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
return true;
}
-bool cmQtAutoGeneratorMocUic::Process()
+bool cmQtAutoMocUic::Process()
{
- // Run libuv event loop
- UVRequest().send();
- if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) {
- if (JobError_) {
- return false;
- }
- } else {
+ SettingsFileRead();
+ if (!CreateDirectories()) {
return false;
}
- return true;
-}
-void cmQtAutoGeneratorMocUic::UVPollStage(uv_async_t* handle)
-{
- reinterpret_cast<cmQtAutoGeneratorMocUic*>(handle->data)->PollStage();
-}
-
-void cmQtAutoGeneratorMocUic::PollStage()
-{
- switch (Stage_) {
- case StageT::SETTINGS_READ:
- SettingsFileRead();
- SetStage(StageT::CREATE_DIRECTORIES);
- break;
- case StageT::CREATE_DIRECTORIES:
- CreateDirectories();
- SetStage(StageT::PARSE_SOURCES);
- break;
- case StageT::PARSE_SOURCES:
- if (ThreadsStartJobs(JobQueues_.Sources)) {
- SetStage(StageT::PARSE_HEADERS);
- }
- break;
- case StageT::PARSE_HEADERS:
- if (ThreadsStartJobs(JobQueues_.Headers)) {
- SetStage(StageT::MOC_PREDEFS);
- }
- break;
- case StageT::MOC_PREDEFS:
- if (ThreadsStartJobs(JobQueues_.MocPredefs)) {
- SetStage(StageT::MOC_PROCESS);
- }
- break;
- case StageT::MOC_PROCESS:
- if (ThreadsStartJobs(JobQueues_.Moc)) {
- SetStage(StageT::MOCS_COMPILATION);
- }
- break;
- case StageT::MOCS_COMPILATION:
- if (ThreadsJobsDone()) {
- MocGenerateCompilation();
- SetStage(StageT::UIC_PROCESS);
- }
- break;
- case StageT::UIC_PROCESS:
- if (ThreadsStartJobs(JobQueues_.Uic)) {
- SetStage(StageT::SETTINGS_WRITE);
- }
- break;
- case StageT::SETTINGS_WRITE:
- SettingsFileWrite();
- SetStage(StageT::FINISH);
- break;
- case StageT::FINISH:
- if (ThreadsJobsDone()) {
- // Clear all libuv handles
- ThreadsStop();
- UVRequest().reset();
- // Set highest END stage manually
- Stage_ = StageT::END;
- }
- break;
- case StageT::END:
- break;
+ if (!WorkerPool_.Process(Base().NumThreads, this)) {
+ return false;
}
-}
-void cmQtAutoGeneratorMocUic::SetStage(StageT stage)
-{
if (JobError_) {
- stage = StageT::FINISH;
- }
- // Only allow to increase the stage
- if (Stage_ < stage) {
- Stage_ = stage;
- UVRequest().send();
+ return false;
}
+
+ return SettingsFileWrite();
}
-void cmQtAutoGeneratorMocUic::SettingsFileRead()
+void cmQtAutoMocUic::SettingsFileRead()
{
// Compose current settings strings
{
@@ -1663,11 +1560,10 @@ void cmQtAutoGeneratorMocUic::SettingsFileRead()
}
}
-void cmQtAutoGeneratorMocUic::SettingsFileWrite()
+bool cmQtAutoMocUic::SettingsFileWrite()
{
- std::lock_guard<std::mutex> jobsLock(JobsMutex_);
// Only write if any setting changed
- if (!JobError_ && (Moc().SettingsChanged || Uic().SettingsChanged)) {
+ if (Moc().SettingsChanged || Uic().SettingsChanged) {
if (Log().Verbose()) {
Log().Info(GenT::GEN, "Writing settings file " + Quoted(SettingsFile_));
}
@@ -1687,258 +1583,148 @@ void cmQtAutoGeneratorMocUic::SettingsFileWrite()
SettingAppend("uic", SettingsStringUic_);
}
// Write settings file
- if (!FileSys().FileWrite(GenT::GEN, SettingsFile_, content)) {
+ std::string error;
+ if (!FileSys().FileWrite(SettingsFile_, content, &error)) {
Log().ErrorFile(GenT::GEN, SettingsFile_,
- "Settings file writing failed");
+ "Settings file writing failed. " + error);
// Remove old settings file to trigger a full rebuild on the next run
FileSys().FileRemove(SettingsFile_);
- RegisterJobError();
+ return false;
}
}
+ return true;
}
-void cmQtAutoGeneratorMocUic::CreateDirectories()
+bool cmQtAutoMocUic::CreateDirectories()
{
// Create AUTOGEN include directory
- if (!FileSys().MakeDirectory(GenT::GEN, Base().AutogenIncludeDir)) {
- RegisterJobError();
+ if (!FileSys().MakeDirectory(Base().AutogenIncludeDir)) {
+ Log().ErrorFile(GenT::GEN, Base().AutogenIncludeDir,
+ "Could not create directory.");
+ return false;
}
+ return true;
}
-bool cmQtAutoGeneratorMocUic::ThreadsStartJobs(JobQueueT& queue)
+// Private method that requires cmQtAutoMocUic::JobsMutex_ to be
+// locked
+void cmQtAutoMocUic::Abort(bool error)
{
- bool done = false;
- std::size_t queueSize = queue.size();
-
- // Change the active queue
- {
- std::lock_guard<std::mutex> jobsLock(JobsMutex_);
- // Check if there are still unfinished jobs from the previous queue
- if (JobsRemain_ == 0) {
- if (!JobThreadsAbort_) {
- JobQueue_.swap(queue);
- JobsRemain_ = queueSize;
- } else {
- // Abort requested
- queue.clear();
- queueSize = 0;
- }
- done = true;
- }
+ if (error) {
+ JobError_.store(true);
}
+ WorkerPool_.Abort();
+}
- if (done && (queueSize != 0)) {
- // Start new threads on demand
- if (Workers_.empty()) {
- Workers_.resize(Base().NumThreads);
- for (auto& item : Workers_) {
- item = cm::make_unique<WorkerT>(this, UVLoop());
+bool cmQtAutoMocUic::ParallelJobPushMoc(cmWorkerPool::JobHandleT&& jobHandle)
+{
+ JobMocT const& mocJob(static_cast<JobMocT&>(*jobHandle));
+ // Do additional tests if this is an included moc job
+ if (!mocJob.IncludeString.empty()) {
+ std::lock_guard<std::mutex> guard(MocMetaMutex_);
+ // Register included moc file
+ MocIncludedFiles_.emplace(mocJob.SourceFile);
+
+ // Check if the same moc file would be generated from a different
+ // source file.
+ auto const range = MocIncludes_.equal_range(mocJob.IncludeString);
+ for (auto it = range.first; it != range.second; ++it) {
+ if (it->second[0] == mocJob.SourceFile) {
+ // The output file already gets generated
+ return true;
}
- } else {
- // Notify threads
- if (queueSize == 1) {
- JobsConditionRead_.notify_one();
- } else {
- JobsConditionRead_.notify_all();
+ {
+ // The output file already gets generated - from a different source
+ // file!
+ std::string error = "The two source files\n ";
+ error += Quoted(mocJob.IncluderFile);
+ error += " and\n ";
+ error += Quoted(it->second[1]);
+ error += "\ncontain the same moc include string ";
+ error += Quoted(mocJob.IncludeString);
+ error += "\nbut the moc file would be generated from different "
+ "source files\n ";
+ error += Quoted(mocJob.SourceFile);
+ error += " and\n ";
+ error += Quoted(it->second[0]);
+ error += ".\nConsider to\n"
+ "- not include the \"moc_<NAME>.cpp\" file\n"
+ "- add a directory prefix to a \"<NAME>.moc\" include "
+ "(e.g \"sub/<NAME>.moc\")\n"
+ "- rename the source file(s)\n";
+ Log().Error(GenT::MOC, error);
+ AbortError();
+ return false;
}
}
- }
- return done;
-}
-
-void cmQtAutoGeneratorMocUic::ThreadsStop()
-{
- if (!Workers_.empty()) {
- // Clear all jobs
- {
- std::lock_guard<std::mutex> jobsLock(JobsMutex_);
- JobThreadsAbort_ = true;
- JobsRemain_ -= JobQueue_.size();
- JobQueue_.clear();
-
- JobQueues_.Sources.clear();
- JobQueues_.Headers.clear();
- JobQueues_.MocPredefs.clear();
- JobQueues_.Moc.clear();
- JobQueues_.Uic.clear();
- }
- // Wake threads
- JobsConditionRead_.notify_all();
- // Join and clear threads
- Workers_.clear();
+ // We're still here so register this job
+ MocIncludes_.emplace_hint(range.first, mocJob.IncludeString,
+ std::array<std::string, 2>{
+ { mocJob.SourceFile, mocJob.IncluderFile } });
}
+ return WorkerPool_.PushJob(std::move(jobHandle));
}
-bool cmQtAutoGeneratorMocUic::ThreadsJobsDone()
-{
- std::lock_guard<std::mutex> jobsLock(JobsMutex_);
- return (JobsRemain_ == 0);
-}
-
-void cmQtAutoGeneratorMocUic::WorkerSwapJob(JobHandleT& jobHandle)
+bool cmQtAutoMocUic::ParallelJobPushUic(cmWorkerPool::JobHandleT&& jobHandle)
{
- bool const jobProcessed(jobHandle);
- if (jobProcessed) {
- jobHandle.reset();
- }
+ const JobUicT& uicJob(static_cast<JobUicT&>(*jobHandle));
{
- std::unique_lock<std::mutex> jobsLock(JobsMutex_);
- // Reduce the remaining job count and notify the libuv loop
- // when all jobs are done
- if (jobProcessed) {
- --JobsRemain_;
- if (JobsRemain_ == 0) {
- UVRequest().send();
+ std::lock_guard<std::mutex> guard(UicMetaMutex_);
+ // Check if the same uic file would be generated from a different
+ // source file.
+ auto const range = UicIncludes_.equal_range(uicJob.IncludeString);
+ for (auto it = range.first; it != range.second; ++it) {
+ if (it->second[0] == uicJob.SourceFile) {
+ // The output file already gets generated
+ return true;
}
- }
- // Wait for new jobs
- while (!JobThreadsAbort_ && JobQueue_.empty()) {
- JobsConditionRead_.wait(jobsLock);
- }
- // Try to pick up a new job handle
- if (!JobThreadsAbort_ && !JobQueue_.empty()) {
- jobHandle = std::move(JobQueue_.front());
- JobQueue_.pop_front();
- }
- }
-}
-
-void cmQtAutoGeneratorMocUic::ParallelRegisterJobError()
-{
- std::lock_guard<std::mutex> jobsLock(JobsMutex_);
- RegisterJobError();
-}
-
-// Private method that requires cmQtAutoGeneratorMocUic::JobsMutex_ to be
-// locked
-void cmQtAutoGeneratorMocUic::RegisterJobError()
-{
- JobError_ = true;
- if (!JobThreadsAbort_) {
- JobThreadsAbort_ = true;
- // Clear remaining jobs
- if (JobsRemain_ != 0) {
- JobsRemain_ -= JobQueue_.size();
- JobQueue_.clear();
- }
- }
-}
-
-bool cmQtAutoGeneratorMocUic::ParallelJobPushMoc(JobHandleT& jobHandle)
-{
- std::lock_guard<std::mutex> jobsLock(JobsMutex_);
- if (!JobThreadsAbort_) {
- bool pushJobHandle = true;
- // Do additional tests if this is an included moc job
- const JobMocT& mocJob(static_cast<JobMocT&>(*jobHandle));
- if (!mocJob.IncludeString.empty()) {
- // Register included moc file and look for collisions
- MocIncludedFiles_.emplace(mocJob.SourceFile);
- if (!MocIncludedStrings_.emplace(mocJob.IncludeString).second) {
- // Another source file includes the same moc file!
- for (const JobHandleT& otherHandle : JobQueues_.Moc) {
- const JobMocT& otherJob(static_cast<JobMocT&>(*otherHandle));
- if (otherJob.IncludeString == mocJob.IncludeString) {
- // Check if the same moc file would be generated from different
- // source files which is an error.
- if (otherJob.SourceFile != mocJob.SourceFile) {
- // Include string collision
- std::string error = "The two source files\n ";
- error += Quoted(mocJob.IncluderFile);
- error += " and\n ";
- error += Quoted(otherJob.IncluderFile);
- error += "\ncontain the same moc include string ";
- error += Quoted(mocJob.IncludeString);
- error += "\nbut the moc file would be generated from different "
- "source files\n ";
- error += Quoted(mocJob.SourceFile);
- error += " and\n ";
- error += Quoted(otherJob.SourceFile);
- error += ".\nConsider to\n"
- "- not include the \"moc_<NAME>.cpp\" file\n"
- "- add a directory prefix to a \"<NAME>.moc\" include "
- "(e.g \"sub/<NAME>.moc\")\n"
- "- rename the source file(s)\n";
- Log().Error(GenT::MOC, error);
- RegisterJobError();
- }
- // Do not push this job in since the included moc file already
- // gets generated by an other job.
- pushJobHandle = false;
- break;
- }
- }
+ {
+ // The output file already gets generated - from a different .ui
+ // file!
+ std::string error = "The two source files\n ";
+ error += Quoted(uicJob.IncluderFile);
+ error += " and\n ";
+ error += Quoted(it->second[1]);
+ error += "\ncontain the same uic include string ";
+ error += Quoted(uicJob.IncludeString);
+ error += "\nbut the uic file would be generated from different "
+ "source files\n ";
+ error += Quoted(uicJob.SourceFile);
+ error += " and\n ";
+ error += Quoted(it->second[0]);
+ error +=
+ ".\nConsider to\n"
+ "- add a directory prefix to a \"ui_<NAME>.h\" include "
+ "(e.g \"sub/ui_<NAME>.h\")\n"
+ "- rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" "
+ "include(s)\n";
+ Log().Error(GenT::UIC, error);
+ AbortError();
+ return false;
}
}
- // Push job on demand
- if (pushJobHandle) {
- JobQueues_.Moc.emplace_back(std::move(jobHandle));
- }
- }
- return !JobError_;
-}
-bool cmQtAutoGeneratorMocUic::ParallelJobPushUic(JobHandleT& jobHandle)
-{
- std::lock_guard<std::mutex> jobsLock(JobsMutex_);
- if (!JobThreadsAbort_) {
- bool pushJobHandle = true;
- // Look for include collisions.
- const JobUicT& uicJob(static_cast<JobUicT&>(*jobHandle));
- for (const JobHandleT& otherHandle : JobQueues_.Uic) {
- const JobUicT& otherJob(static_cast<JobUicT&>(*otherHandle));
- if (otherJob.IncludeString == uicJob.IncludeString) {
- // Check if the same uic file would be generated from different
- // source files which would be an error.
- if (otherJob.SourceFile != uicJob.SourceFile) {
- // Include string collision
- std::string error = "The two source files\n ";
- error += Quoted(uicJob.IncluderFile);
- error += " and\n ";
- error += Quoted(otherJob.IncluderFile);
- error += "\ncontain the same uic include string ";
- error += Quoted(uicJob.IncludeString);
- error += "\nbut the uic file would be generated from different "
- "source files\n ";
- error += Quoted(uicJob.SourceFile);
- error += " and\n ";
- error += Quoted(otherJob.SourceFile);
- error +=
- ".\nConsider to\n"
- "- add a directory prefix to a \"ui_<NAME>.h\" include "
- "(e.g \"sub/ui_<NAME>.h\")\n"
- "- rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" "
- "include(s)\n";
- Log().Error(GenT::UIC, error);
- RegisterJobError();
- }
- // Do not push this job in since the uic file already
- // gets generated by an other job.
- pushJobHandle = false;
- break;
- }
- }
- if (pushJobHandle) {
- JobQueues_.Uic.emplace_back(std::move(jobHandle));
- }
+ // We're still here so register this job
+ UicIncludes_.emplace_hint(range.first, uicJob.IncludeString,
+ std::array<std::string, 2>{
+ { uicJob.SourceFile, uicJob.IncluderFile } });
}
- return !JobError_;
+ return WorkerPool_.PushJob(std::move(jobHandle));
}
-bool cmQtAutoGeneratorMocUic::ParallelMocIncluded(
- std::string const& sourceFile)
+bool cmQtAutoMocUic::ParallelMocIncluded(std::string const& sourceFile)
{
- std::lock_guard<std::mutex> mocLock(JobsMutex_);
+ std::lock_guard<std::mutex> guard(MocMetaMutex_);
return (MocIncludedFiles_.find(sourceFile) != MocIncludedFiles_.end());
}
-std::string cmQtAutoGeneratorMocUic::ParallelMocAutoRegister(
+std::string cmQtAutoMocUic::ParallelMocAutoRegister(
std::string const& baseName)
{
std::string res;
{
- std::lock_guard<std::mutex> mocLock(JobsMutex_);
+ std::lock_guard<std::mutex> mocLock(MocMetaMutex_);
res = baseName;
res += ".cpp";
if (MocAutoFiles_.find(res) == MocAutoFiles_.end()) {
@@ -1959,62 +1745,3 @@ std::string cmQtAutoGeneratorMocUic::ParallelMocAutoRegister(
}
return res;
}
-
-void cmQtAutoGeneratorMocUic::ParallelMocAutoUpdated()
-{
- std::lock_guard<std::mutex> mocLock(JobsMutex_);
- MocAutoFileUpdated_ = true;
-}
-
-void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
-{
- std::lock_guard<std::mutex> mocLock(JobsMutex_);
- if (!JobError_ && Moc().Enabled) {
- // Write mocs compilation build file
- {
- // Compose mocs compilation file content
- std::string content =
- "// This file is autogenerated. Changes will be overwritten.\n";
- if (MocAutoFiles_.empty()) {
- // Placeholder content
- content += "// No files found that require moc or the moc files are "
- "included\n";
- content += "enum some_compilers { need_more_than_nothing };\n";
- } else {
- // Valid content
- char const sbeg = Base().MultiConfig ? '<' : '"';
- char const send = Base().MultiConfig ? '>' : '"';
- for (std::string const& mocfile : MocAutoFiles_) {
- content += "#include ";
- content += sbeg;
- content += mocfile;
- content += send;
- content += '\n';
- }
- }
-
- std::string const& compAbs = Moc().CompFileAbs;
- if (FileSys().FileDiffers(compAbs, content)) {
- // Actually write mocs compilation file
- if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Generating MOC compilation " + compAbs);
- }
- if (!FileSys().FileWrite(GenT::MOC, compAbs, content)) {
- Log().ErrorFile(GenT::MOC, compAbs,
- "mocs compilation file writing failed");
- RegisterJobError();
- return;
- }
- } else if (MocAutoFileUpdated_) {
- // Only touch mocs compilation file
- if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Touching mocs compilation " + compAbs);
- }
- FileSys().Touch(compAbs);
- }
- }
- // Write mocs compilation wrapper file
- if (Base().MultiConfig) {
- }
- }
-}
diff --git a/Source/cmQtAutoGeneratorMocUic.h b/Source/cmQtAutoMocUic.h
index e48d7f3..3902abb 100644
--- a/Source/cmQtAutoGeneratorMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -1,25 +1,22 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmQtAutoGeneratorMocUic_h
-#define cmQtAutoGeneratorMocUic_h
+#ifndef cmQtAutoMocUic_h
+#define cmQtAutoMocUic_h
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
-#include "cmUVHandlePtr.h"
-#include "cm_uv.h"
+#include "cmWorkerPool.h"
#include "cmsys/RegularExpression.hxx"
-#include <condition_variable>
-#include <cstddef>
-#include <deque>
+#include <array>
+#include <atomic>
#include <map>
#include <memory> // IWYU pragma: keep
#include <mutex>
#include <set>
#include <string>
-#include <thread>
#include <unordered_set>
#include <utility>
#include <vector>
@@ -27,18 +24,18 @@
class cmMakefile;
// @brief AUTOMOC and AUTOUIC generator
-class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
+class cmQtAutoMocUic : public cmQtAutoGenerator
{
public:
- cmQtAutoGeneratorMocUic();
- ~cmQtAutoGeneratorMocUic() override;
+ cmQtAutoMocUic();
+ ~cmQtAutoMocUic() override;
- cmQtAutoGeneratorMocUic(cmQtAutoGeneratorMocUic const&) = delete;
- cmQtAutoGeneratorMocUic& operator=(cmQtAutoGeneratorMocUic const&) = delete;
+ cmQtAutoMocUic(cmQtAutoMocUic const&) = delete;
+ cmQtAutoMocUic& operator=(cmQtAutoMocUic const&) = delete;
public:
// -- Types
- class WorkerT;
+ typedef std::multimap<std::string, std::array<std::string, 2>> IncludesMap;
/// @brief Search key plus regular expression pair
///
@@ -172,31 +169,71 @@ public:
cmsys::RegularExpression RegExpInclude;
};
- /// @brief Abstract job class for threaded processing
+ /// @brief Abstract job class for concurrent job processing
///
- class JobT
+ class JobT : public cmWorkerPool::JobT
{
- public:
- JobT() = default;
- virtual ~JobT() = default;
+ protected:
+ /**
+ * @brief Protected default constructor
+ */
+ JobT(bool fence = false)
+ : cmWorkerPool::JobT(fence)
+ {
+ }
+
+ //! Get the generator. Only valid during Process() call!
+ cmQtAutoMocUic* Gen() const
+ {
+ return static_cast<cmQtAutoMocUic*>(UserData());
+ };
+
+ //! Get the file system interface. Only valid during Process() call!
+ FileSystem& FileSys() { return Gen()->FileSys(); }
+ //! Get the logger. Only valid during Process() call!
+ Logger& Log() { return Gen()->Log(); }
- JobT(JobT const&) = delete;
- JobT& operator=(JobT const&) = delete;
+ // -- Error logging with automatic abort
+ void LogError(GenT genType, std::string const& message) const;
+ void LogFileError(GenT genType, std::string const& filename,
+ std::string const& message) const;
+ void LogCommandError(GenT genType, std::string const& message,
+ std::vector<std::string> const& command,
+ std::string const& output) const;
- // -- Abstract processing interface
- virtual void Process(WorkerT& wrk) = 0;
+ /**
+ * @brief Run an external process. Use only during Process() call!
+ */
+ bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command);
};
- // Job management types
- typedef std::unique_ptr<JobT> JobHandleT;
- typedef std::deque<JobHandleT> JobQueueT;
+ /// @brief Fence job utility class
+ ///
+ class JobFenceT : public JobT
+ {
+ public:
+ JobFenceT()
+ : JobT(true)
+ {
+ }
+ void Process() override{};
+ };
- /// @brief Parse source job
+ /// @brief Generate moc_predefs.h
+ ///
+ class JobMocPredefsT : public JobT
+ {
+ private:
+ void Process() override;
+ };
+
+ /// @brief Parses a source file
///
class JobParseT : public JobT
{
public:
- JobParseT(std::string&& fileName, bool moc, bool uic, bool header = false)
+ JobParseT(std::string fileName, bool moc, bool uic, bool header = false)
: FileName(std::move(fileName))
, AutoMoc(moc)
, AutoUic(uic)
@@ -212,18 +249,15 @@ public:
std::string FileBase;
};
- void Process(WorkerT& wrk) override;
- bool ParseMocSource(WorkerT& wrk, MetaT const& meta);
- bool ParseMocHeader(WorkerT& wrk, MetaT const& meta);
- std::string MocStringHeaders(WorkerT& wrk,
- std::string const& fileBase) const;
- std::string MocFindIncludedHeader(WorkerT& wrk,
- std::string const& includerDir,
+ void Process() override;
+ bool ParseMocSource(MetaT const& meta);
+ bool ParseMocHeader(MetaT const& meta);
+ std::string MocStringHeaders(std::string const& fileBase) const;
+ std::string MocFindIncludedHeader(std::string const& includerDir,
std::string const& includeBase);
- bool ParseUic(WorkerT& wrk, MetaT const& meta);
- bool ParseUicInclude(WorkerT& wrk, MetaT const& meta,
- std::string&& includeString);
- std::string UicFindIncludedFile(WorkerT& wrk, MetaT const& meta,
+ bool ParseUic(MetaT const& meta);
+ bool ParseUicInclude(MetaT const& meta, std::string&& includeString);
+ std::string UicFindIncludedFile(MetaT const& meta,
std::string const& includeString);
private:
@@ -233,12 +267,20 @@ public:
bool Header = false;
};
- /// @brief Generate moc_predefs
+ /// @brief Generates additional jobs after all files have been parsed
///
- class JobMocPredefsT : public JobT
+ class JobPostParseT : public JobFenceT
{
private:
- void Process(WorkerT& wrk) override;
+ void Process() override;
+ };
+
+ /// @brief Generate mocs_compilation.cpp
+ ///
+ class JobMocsCompilationT : public JobFenceT
+ {
+ private:
+ void Process() override;
};
/// @brief Moc a file job
@@ -246,20 +288,20 @@ public:
class JobMocT : public JobT
{
public:
- JobMocT(std::string&& sourceFile, std::string includerFile,
- std::string&& includeString)
+ JobMocT(std::string sourceFile, std::string includerFile,
+ std::string includeString)
: SourceFile(std::move(sourceFile))
, IncluderFile(std::move(includerFile))
, IncludeString(std::move(includeString))
{
}
- void FindDependencies(WorkerT& wrk, std::string const& content);
+ void FindDependencies(std::string const& content);
private:
- void Process(WorkerT& wrk) override;
- bool UpdateRequired(WorkerT& wrk);
- void GenerateMoc(WorkerT& wrk);
+ void Process() override;
+ bool UpdateRequired();
+ void GenerateMoc();
public:
std::string SourceFile;
@@ -275,8 +317,8 @@ public:
class JobUicT : public JobT
{
public:
- JobUicT(std::string&& sourceFile, std::string includerFile,
- std::string&& includeString)
+ JobUicT(std::string sourceFile, std::string includerFile,
+ std::string includeString)
: SourceFile(std::move(sourceFile))
, IncluderFile(std::move(includerFile))
, IncludeString(std::move(includeString))
@@ -284,9 +326,9 @@ public:
}
private:
- void Process(WorkerT& wrk) override;
- bool UpdateRequired(WorkerT& wrk);
- void GenerateUic(WorkerT& wrk);
+ void Process() override;
+ bool UpdateRequired();
+ void GenerateUic();
public:
std::string SourceFile;
@@ -295,80 +337,12 @@ public:
std::string BuildFile;
};
- /// @brief Worker Thread
+ /// @brief The last job
///
- class WorkerT
+ class JobFinishT : public JobFenceT
{
- public:
- WorkerT(cmQtAutoGeneratorMocUic* gen, uv_loop_t* uvLoop);
- ~WorkerT();
-
- WorkerT(WorkerT const&) = delete;
- WorkerT& operator=(WorkerT const&) = delete;
-
- // -- Const accessors
- cmQtAutoGeneratorMocUic& Gen() const { return *Gen_; }
- Logger& Log() const { return Gen_->Log(); }
- FileSystem& FileSys() const { return Gen_->FileSys(); }
- const BaseSettingsT& Base() const { return Gen_->Base(); }
- const MocSettingsT& Moc() const { return Gen_->Moc(); }
- const UicSettingsT& Uic() const { return Gen_->Uic(); }
-
- // -- Log info
- void LogInfo(GenT genType, std::string const& message) const;
- // -- Log warning
- void LogWarning(GenT genType, std::string const& message) const;
- void LogFileWarning(GenT genType, std::string const& filename,
- std::string const& message) const;
- // -- Log error
- void LogError(GenT genType, std::string const& message) const;
- void LogFileError(GenT genType, std::string const& filename,
- std::string const& message) const;
- void LogCommandError(GenT genType, std::string const& message,
- std::vector<std::string> const& command,
- std::string const& output) const;
-
- // -- External processes
- /// @brief Verbose logging version
- bool RunProcess(GenT genType, ProcessResultT& result,
- std::vector<std::string> const& command);
-
- private:
- /// @brief Thread main loop
- void Loop();
-
- // -- Libuv callbacks
- static void UVProcessStart(uv_async_t* handle);
- void UVProcessFinished();
-
private:
- // -- Generator
- cmQtAutoGeneratorMocUic* Gen_;
- // -- Job handle
- JobHandleT JobHandle_;
- // -- Process management
- std::mutex ProcessMutex_;
- cm::uv_async_ptr ProcessRequest_;
- std::condition_variable ProcessCondition_;
- std::unique_ptr<ReadOnlyProcessT> Process_;
- // -- System thread
- std::thread Thread_;
- };
-
- /// @brief Processing stage
- enum class StageT
- {
- SETTINGS_READ,
- CREATE_DIRECTORIES,
- PARSE_SOURCES,
- PARSE_HEADERS,
- MOC_PREDEFS,
- MOC_PROCESS,
- MOCS_COMPILATION,
- UIC_PROCESS,
- SETTINGS_WRITE,
- FINISH,
- END
+ void Process() override;
};
// -- Const settings interface
@@ -376,69 +350,64 @@ public:
const MocSettingsT& Moc() const { return this->Moc_; }
const UicSettingsT& Uic() const { return this->Uic_; }
- // -- Worker thread interface
- void WorkerSwapJob(JobHandleT& jobHandle);
// -- Parallel job processing interface
- void ParallelRegisterJobError();
- bool ParallelJobPushMoc(JobHandleT& jobHandle);
- bool ParallelJobPushUic(JobHandleT& jobHandle);
- bool ParallelMocIncluded(std::string const& sourceFile);
+ cmWorkerPool& WorkerPool() { return WorkerPool_; }
+ void AbortError() { Abort(true); }
+ void AbortSuccess() { Abort(false); }
+ bool ParallelJobPushMoc(cmWorkerPool::JobHandleT&& jobHandle);
+ bool ParallelJobPushUic(cmWorkerPool::JobHandleT&& jobHandle);
+
+ // -- Mocs compilation include file updated flag
+ void ParallelMocAutoUpdated() { MocAutoFileUpdated_.store(true); }
+ bool MocAutoFileUpdated() const { return MocAutoFileUpdated_.load(); }
+
+ // -- Mocs compilation file register
std::string ParallelMocAutoRegister(std::string const& baseName);
- void ParallelMocAutoUpdated();
+ bool ParallelMocIncluded(std::string const& sourceFile);
+ std::set<std::string> const& MocAutoFiles() const
+ {
+ return this->MocAutoFiles_;
+ }
private:
+ // -- Utility accessors
+ Logger& Log() { return Logger_; }
+ FileSystem& FileSys() { return FileSys_; }
// -- Abstract processing interface
bool Init(cmMakefile* makefile) override;
bool Process() override;
- // -- Process stage
- static void UVPollStage(uv_async_t* handle);
- void PollStage();
- void SetStage(StageT stage);
// -- Settings file
void SettingsFileRead();
- void SettingsFileWrite();
+ bool SettingsFileWrite();
// -- Thread processing
- bool ThreadsStartJobs(JobQueueT& queue);
- bool ThreadsJobsDone();
- void ThreadsStop();
- void RegisterJobError();
+ void Abort(bool error);
// -- Generation
- void CreateDirectories();
- void MocGenerateCompilation();
+ bool CreateDirectories();
private:
+ // -- Utility
+ Logger Logger_;
+ FileSystem FileSys_;
// -- Settings
BaseSettingsT Base_;
MocSettingsT Moc_;
UicSettingsT Uic_;
- // -- Progress
- StageT Stage_ = StageT::SETTINGS_READ;
- // -- Job queues
- std::mutex JobsMutex_;
- struct
- {
- JobQueueT Sources;
- JobQueueT Headers;
- JobQueueT MocPredefs;
- JobQueueT Moc;
- JobQueueT Uic;
- } JobQueues_;
- JobQueueT JobQueue_;
- std::size_t volatile JobsRemain_ = 0;
- bool volatile JobError_ = false;
- bool volatile JobThreadsAbort_ = false;
- std::condition_variable JobsConditionRead_;
// -- Moc meta
- std::set<std::string> MocIncludedStrings_;
+ std::mutex MocMetaMutex_;
std::set<std::string> MocIncludedFiles_;
+ IncludesMap MocIncludes_;
std::set<std::string> MocAutoFiles_;
- bool volatile MocAutoFileUpdated_ = false;
+ std::atomic<bool> MocAutoFileUpdated_ = ATOMIC_VAR_INIT(false);
+ // -- Uic meta
+ std::mutex UicMetaMutex_;
+ IncludesMap UicIncludes_;
// -- Settings file
std::string SettingsFile_;
std::string SettingsStringMoc_;
std::string SettingsStringUic_;
- // -- Threads and loops
- std::vector<std::unique_ptr<WorkerT>> Workers_;
+ // -- Thread pool and job queue
+ std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
+ cmWorkerPool WorkerPool_;
};
#endif
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
new file mode 100644
index 0000000..e58324d
--- /dev/null
+++ b/Source/cmQtAutoRcc.cxx
@@ -0,0 +1,516 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoRcc.h"
+#include "cmQtAutoGen.h"
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmDuration.h"
+#include "cmFileLockResult.h"
+#include "cmMakefile.h"
+#include "cmProcessOutput.h"
+#include "cmSystemTools.h"
+
+// -- Class methods
+
+cmQtAutoRcc::cmQtAutoRcc() = default;
+
+cmQtAutoRcc::~cmQtAutoRcc() = default;
+
+bool cmQtAutoRcc::Init(cmMakefile* makefile)
+{
+ // -- Utility lambdas
+ auto InfoGet = [makefile](std::string const& key) {
+ return makefile->GetSafeDefinition(key);
+ };
+ auto InfoGetList =
+ [makefile](std::string const& key) -> std::vector<std::string> {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
+ return list;
+ };
+ auto InfoGetConfig = [makefile,
+ this](std::string const& key) -> std::string {
+ const char* valueConf = nullptr;
+ {
+ std::string keyConf = key;
+ keyConf += '_';
+ keyConf += InfoConfig();
+ valueConf = makefile->GetDefinition(keyConf);
+ }
+ if (valueConf == nullptr) {
+ return makefile->GetSafeDefinition(key);
+ }
+ return std::string(valueConf);
+ };
+ auto InfoGetConfigList =
+ [&InfoGetConfig](std::string const& key) -> std::vector<std::string> {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
+ return list;
+ };
+
+ // -- Read info file
+ if (!makefile->ReadListFile(InfoFile())) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "File processing failed.");
+ return false;
+ }
+
+ // - Configurations
+ Log().RaiseVerbosity(InfoGet("ARCC_VERBOSITY"));
+ MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
+
+ // - Directories
+ AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
+ if (AutogenBuildDir_.empty()) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "Build directory empty.");
+ return false;
+ }
+
+ IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
+ if (IncludeDir_.empty()) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "Include directory empty.");
+ return false;
+ }
+
+ // - Rcc executable
+ RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
+ RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
+
+ // - Job
+ LockFile_ = InfoGet("ARCC_LOCK_FILE");
+ QrcFile_ = InfoGet("ARCC_SOURCE");
+ QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
+ QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
+ RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
+ RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
+ Options_ = InfoGetConfigList("ARCC_OPTIONS");
+ Inputs_ = InfoGetList("ARCC_INPUTS");
+
+ // - Settings file
+ SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
+
+ // - Validity checks
+ if (LockFile_.empty()) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "Lock file name missing.");
+ return false;
+ }
+ if (SettingsFile_.empty()) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "Settings file name missing.");
+ return false;
+ }
+ if (AutogenBuildDir_.empty()) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "Autogen build directory missing.");
+ return false;
+ }
+ if (RccExecutable_.empty()) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "rcc executable missing.");
+ return false;
+ }
+ if (QrcFile_.empty()) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "rcc input file missing.");
+ return false;
+ }
+ if (RccFileName_.empty()) {
+ Log().ErrorFile(GenT::RCC, InfoFile(), "rcc output file missing.");
+ return false;
+ }
+
+ // Init derived information
+ // ------------------------
+
+ RccFilePublic_ = AutogenBuildDir_;
+ RccFilePublic_ += '/';
+ RccFilePublic_ += RccPathChecksum_;
+ RccFilePublic_ += '/';
+ RccFilePublic_ += RccFileName_;
+
+ // Compute rcc output file name
+ if (IsMultiConfig()) {
+ RccFileOutput_ = IncludeDir_;
+ RccFileOutput_ += '/';
+ RccFileOutput_ += MultiConfigOutput();
+ } else {
+ RccFileOutput_ = RccFilePublic_;
+ }
+
+ return true;
+}
+
+bool cmQtAutoRcc::Process()
+{
+ if (!SettingsFileRead()) {
+ return false;
+ }
+
+ // Test if the rcc output needs to be regenerated
+ bool generate = false;
+ if (!TestQrcRccFiles(generate)) {
+ return false;
+ }
+ if (!generate && !TestResources(generate)) {
+ return false;
+ }
+ // Generate on demand
+ if (generate) {
+ if (!GenerateRcc()) {
+ return false;
+ }
+ } else {
+ // Test if the info file is newer than the output file
+ if (!TestInfoFile()) {
+ return false;
+ }
+ }
+
+ if (!GenerateWrapper()) {
+ return false;
+ }
+
+ return SettingsFileWrite();
+}
+
+std::string cmQtAutoRcc::MultiConfigOutput() const
+{
+ static std::string const suffix = "_CMAKE_";
+ std::string res;
+ res += RccPathChecksum_;
+ res += '/';
+ res += AppendFilenameSuffix(RccFileName_, suffix);
+ return res;
+}
+
+bool cmQtAutoRcc::SettingsFileRead()
+{
+ // Compose current settings strings
+ {
+ cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
+ std::string const sep(" ~~~ ");
+ {
+ std::string str;
+ str += RccExecutable_;
+ str += sep;
+ str += cmJoin(RccListOptions_, ";");
+ str += sep;
+ str += QrcFile_;
+ str += sep;
+ str += RccPathChecksum_;
+ str += sep;
+ str += RccFileName_;
+ str += sep;
+ str += cmJoin(Options_, ";");
+ str += sep;
+ str += cmJoin(Inputs_, ";");
+ str += sep;
+ SettingsString_ = crypt.HashString(str);
+ }
+ }
+
+ // Make sure the settings file exists
+ if (!cmSystemTools::FileExists(SettingsFile_, true)) {
+ // Touch the settings file to make sure it exists
+ if (!cmSystemTools::Touch(SettingsFile_, true)) {
+ Log().ErrorFile(GenT::RCC, SettingsFile_,
+ "Settings file creation failed.");
+ return false;
+ }
+ }
+
+ // Lock the lock file
+ {
+ // Make sure the lock file exists
+ if (!cmSystemTools::FileExists(LockFile_, true)) {
+ if (!cmSystemTools::Touch(LockFile_, true)) {
+ Log().ErrorFile(GenT::RCC, LockFile_, "Lock file creation failed.");
+ return false;
+ }
+ }
+ // Lock the lock file
+ cmFileLockResult lockResult =
+ LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1));
+ if (!lockResult.IsOk()) {
+ Log().ErrorFile(GenT::RCC, LockFile_,
+ "File lock failed: " + lockResult.GetOutputMessage());
+ return false;
+ }
+ }
+
+ // Read old settings
+ {
+ std::string content;
+ if (FileRead(content, SettingsFile_)) {
+ SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
+ // In case any setting changed clear the old settings file.
+ // This triggers a full rebuild on the next run if the current
+ // build is aborted before writing the current settings in the end.
+ if (SettingsChanged_) {
+ std::string error;
+ if (!FileWrite(SettingsFile_, "", &error)) {
+ Log().ErrorFile(GenT::RCC, SettingsFile_,
+ "Settings file clearing failed. " + error);
+ return false;
+ }
+ }
+ } else {
+ SettingsChanged_ = true;
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoRcc::SettingsFileWrite()
+{
+ // Only write if any setting changed
+ if (SettingsChanged_) {
+ if (Log().Verbose()) {
+ Log().Info(GenT::RCC, "Writing settings file " + Quoted(SettingsFile_));
+ }
+ // Write settings file
+ std::string content = "rcc:";
+ content += SettingsString_;
+ content += '\n';
+ std::string error;
+ if (!FileWrite(SettingsFile_, content, &error)) {
+ Log().ErrorFile(GenT::RCC, SettingsFile_,
+ "Settings file writing failed. " + error);
+ // Remove old settings file to trigger a full rebuild on the next run
+ cmSystemTools::RemoveFile(SettingsFile_);
+ return false;
+ }
+ }
+
+ // Unlock the lock file
+ LockFileLock_.Release();
+ return true;
+}
+
+/// Do basic checks if rcc generation is required
+bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
+{
+ // Test if the rcc input file exists
+ if (!QrcFileTime_.Load(QrcFile_)) {
+ std::string error;
+ error = "The resources file ";
+ error += Quoted(QrcFile_);
+ error += " does not exist";
+ Log().ErrorFile(GenT::RCC, QrcFile_, error);
+ return false;
+ }
+
+ // Test if the rcc output file exists
+ if (!RccFileTime_.Load(RccFileOutput_)) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(RccFileOutput_);
+ reason += " from its source file ";
+ reason += Quoted(QrcFile_);
+ reason += " because it doesn't exist";
+ Log().Info(GenT::RCC, reason);
+ }
+ generate = true;
+ return true;
+ }
+
+ // Test if the settings changed
+ if (SettingsChanged_) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(RccFileOutput_);
+ reason += " from ";
+ reason += Quoted(QrcFile_);
+ reason += " because the RCC settings changed";
+ Log().Info(GenT::RCC, reason);
+ }
+ generate = true;
+ return true;
+ }
+
+ // Test if the rcc output file is older than the .qrc file
+ if (RccFileTime_.Older(QrcFileTime_)) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(RccFileOutput_);
+ reason += " because it is older than ";
+ reason += Quoted(QrcFile_);
+ Log().Info(GenT::RCC, reason);
+ }
+ generate = true;
+ return true;
+ }
+
+ return true;
+}
+
+bool cmQtAutoRcc::TestResources(bool& generate)
+{
+ // Read resource files list
+ if (Inputs_.empty()) {
+ std::string error;
+ RccLister const lister(RccExecutable_, RccListOptions_);
+ if (!lister.list(QrcFile_, Inputs_, error, Log().Verbose())) {
+ Log().ErrorFile(GenT::RCC, QrcFile_, error);
+ return false;
+ }
+ }
+
+ for (std::string const& resFile : Inputs_) {
+ // Check if the resource file exists
+ cmFileTime fileTime;
+ if (!fileTime.Load(resFile)) {
+ std::string error;
+ error = "Could not find the resource file\n ";
+ error += Quoted(resFile);
+ error += '\n';
+ Log().ErrorFile(GenT::RCC, QrcFile_, error);
+ return false;
+ }
+ // Check if the resource file is newer than the build file
+ if (RccFileTime_.Older(fileTime)) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(RccFileOutput_);
+ reason += " from ";
+ reason += Quoted(QrcFile_);
+ reason += " because it is older than ";
+ reason += Quoted(resFile);
+ Log().Info(GenT::RCC, reason);
+ }
+ generate = true;
+ break;
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoRcc::TestInfoFile()
+{
+ // Test if the rcc output file is older than the info file
+
+ cmFileTime infoFileTime;
+ if (!infoFileTime.Load(InfoFile())) {
+ std::string error;
+ error = "Could not find the info file ";
+ error += Quoted(InfoFile());
+ error += '\n';
+ Log().ErrorFile(GenT::RCC, QrcFile_, error);
+ return false;
+ }
+ if (RccFileTime_.Older(infoFileTime)) {
+ if (Log().Verbose()) {
+ std::string reason = "Touching ";
+ reason += Quoted(RccFileOutput_);
+ reason += " because it is older than ";
+ reason += Quoted(InfoFile());
+ Log().Info(GenT::RCC, reason);
+ }
+ // Touch build file
+ if (!cmSystemTools::Touch(RccFileOutput_, false)) {
+ Log().ErrorFile(GenT::RCC, RccFileOutput_, "Build file touch failed");
+ return false;
+ }
+ BuildFileChanged_ = true;
+ }
+
+ return true;
+}
+
+bool cmQtAutoRcc::GenerateRcc()
+{
+ // Make parent directory
+ if (!MakeParentDirectory(RccFileOutput_)) {
+ Log().ErrorFile(GenT::RCC, RccFileOutput_,
+ "Could not create parent directory");
+ return false;
+ }
+
+ // Start a rcc process
+ std::vector<std::string> cmd;
+ cmd.push_back(RccExecutable_);
+ cmd.insert(cmd.end(), Options_.begin(), Options_.end());
+ cmd.emplace_back("-o");
+ cmd.push_back(RccFileOutput_);
+ cmd.push_back(QrcFile_);
+
+ // Log command
+ if (Log().Verbose()) {
+ std::string msg = "Running command:\n";
+ msg += QuotedCommand(cmd);
+ msg += '\n';
+ cmSystemTools::Stdout(msg);
+ }
+
+ std::string rccStdOut;
+ std::string rccStdErr;
+ int retVal = 0;
+ bool result = cmSystemTools::RunSingleCommand(
+ cmd, &rccStdOut, &rccStdErr, &retVal, AutogenBuildDir_.c_str(),
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
+ if (!result || (retVal != 0)) {
+ // rcc process failed
+ {
+ std::string err = "The rcc process failed to compile\n ";
+ err += Quoted(QrcFile_);
+ err += "\ninto\n ";
+ err += Quoted(RccFileOutput_);
+ Log().ErrorCommand(GenT::RCC, err, cmd, rccStdOut + rccStdErr);
+ }
+ cmSystemTools::RemoveFile(RccFileOutput_);
+ return false;
+ }
+
+ // rcc process success
+ // Print rcc output
+ if (!rccStdOut.empty()) {
+ Log().Info(GenT::RCC, rccStdOut);
+ }
+ BuildFileChanged_ = true;
+
+ return true;
+}
+
+bool cmQtAutoRcc::GenerateWrapper()
+{
+ // Generate a wrapper source file on demand
+ if (IsMultiConfig()) {
+ // Wrapper file content
+ std::string content;
+ content += "// This is an autogenerated configuration wrapper file.\n";
+ content += "// Changes will be overwritten.\n";
+ content += "#include <";
+ content += MultiConfigOutput();
+ content += ">\n";
+
+ // Compare with existing file content
+ bool fileDiffers = true;
+ {
+ std::string oldContents;
+ if (FileRead(oldContents, RccFilePublic_)) {
+ fileDiffers = (oldContents != content);
+ }
+ }
+ if (fileDiffers) {
+ // Write new wrapper file
+ if (Log().Verbose()) {
+ Log().Info(GenT::RCC, "Generating RCC wrapper file " + RccFilePublic_);
+ }
+ std::string error;
+ if (!FileWrite(RccFilePublic_, content, &error)) {
+ Log().ErrorFile(GenT::RCC, RccFilePublic_,
+ "RCC wrapper file writing failed. " + error);
+ return false;
+ }
+ } else if (BuildFileChanged_) {
+ // Just touch the wrapper file
+ if (Log().Verbose()) {
+ Log().Info(GenT::RCC, "Touching RCC wrapper file " + RccFilePublic_);
+ }
+ if (!cmSystemTools::Touch(RccFilePublic_, false)) {
+ Log().ErrorFile(GenT::RCC, RccFilePublic_,
+ "RCC wrapper file touch failed.");
+ return false;
+ }
+ }
+ }
+ return true;
+}
diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoRcc.h
index 1ec1c4a..8dc9179 100644
--- a/Source/cmQtAutoGeneratorRcc.h
+++ b/Source/cmQtAutoRcc.h
@@ -1,13 +1,13 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmQtAutoGeneratorRcc_h
-#define cmQtAutoGeneratorRcc_h
+#ifndef cmQtAutoRcc_h
+#define cmQtAutoRcc_h
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmFileLock.h"
+#include "cmFileTime.h"
#include "cmQtAutoGenerator.h"
-#include "cm_uv.h"
#include <string>
#include <vector>
@@ -15,62 +15,38 @@
class cmMakefile;
// @brief AUTORCC generator
-class cmQtAutoGeneratorRcc : public cmQtAutoGenerator
+class cmQtAutoRcc : public cmQtAutoGenerator
{
public:
- cmQtAutoGeneratorRcc();
- ~cmQtAutoGeneratorRcc() override;
+ cmQtAutoRcc();
+ ~cmQtAutoRcc() override;
- cmQtAutoGeneratorRcc(cmQtAutoGeneratorRcc const&) = delete;
- cmQtAutoGeneratorRcc& operator=(cmQtAutoGeneratorRcc const&) = delete;
+ cmQtAutoRcc(cmQtAutoRcc const&) = delete;
+ cmQtAutoRcc& operator=(cmQtAutoRcc const&) = delete;
private:
- // -- Types
-
- /// @brief Processing stage
- enum class StageT : unsigned char
- {
- SETTINGS_READ,
- TEST_QRC_RCC_FILES,
- TEST_RESOURCES_READ,
- TEST_RESOURCES,
- TEST_INFO_FILE,
- GENERATE,
- GENERATE_RCC,
- GENERATE_WRAPPER,
- SETTINGS_WRITE,
- FINISH,
- END
- };
+ // -- Utility
+ Logger& Log() { return Logger_; }
+ bool IsMultiConfig() const { return MultiConfig_; }
+ std::string MultiConfigOutput() const;
// -- Abstract processing interface
bool Init(cmMakefile* makefile) override;
bool Process() override;
- // -- Process stage
- static void UVPollStage(uv_async_t* handle);
- void PollStage();
- void SetStage(StageT stage);
// -- Settings file
bool SettingsFileRead();
- void SettingsFileWrite();
+ bool SettingsFileWrite();
// -- Tests
- bool TestQrcRccFiles();
- bool TestResourcesRead();
- bool TestResources();
- void TestInfoFile();
+ bool TestQrcRccFiles(bool& generate);
+ bool TestResources(bool& generate);
+ bool TestInfoFile();
// -- Generation
- void GenerateParentDir();
bool GenerateRcc();
- void GenerateWrapper();
-
- // -- Utility
- bool IsMultiConfig() const { return MultiConfig_; }
- std::string MultiConfigOutput() const;
- bool StartProcess(std::string const& workingDirectory,
- std::vector<std::string> const& command,
- bool mergedOutput);
+ bool GenerateWrapper();
private:
+ // -- Logging
+ Logger Logger_;
// -- Config settings
bool MultiConfig_ = false;
// -- Directories
@@ -85,23 +61,18 @@ private:
std::string QrcFile_;
std::string QrcFileName_;
std::string QrcFileDir_;
+ cmFileTime QrcFileTime_;
std::string RccPathChecksum_;
std::string RccFileName_;
std::string RccFileOutput_;
std::string RccFilePublic_;
+ cmFileTime RccFileTime_;
std::vector<std::string> Options_;
std::vector<std::string> Inputs_;
- // -- Subprocess
- ProcessResultT ProcessResult_;
- std::unique_ptr<ReadOnlyProcessT> Process_;
// -- Settings file
std::string SettingsFile_;
std::string SettingsString_;
bool SettingsChanged_ = false;
- // -- libuv loop
- StageT Stage_ = StageT::SETTINGS_READ;
- bool Error_ = false;
- bool Generate_ = false;
bool BuildFileChanged_ = false;
};
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index 5917e27..2064275 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -33,7 +33,7 @@ cmRST::cmRST(std::ostream& os, std::string docroot)
, TocTreeDirective("^.. toctree::[ \t]*(.*)$")
, ProductionListDirective("^.. productionlist::[ \t]*(.*)$")
, NoteDirective("^.. note::[ \t]*(.*)$")
- , ModuleRST("^#\\[(=*)\\[\\.rst:$")
+ , ModuleRST(R"(^#\[(=*)\[\.rst:$)")
, CMakeRole("(:cmake)?:("
"command|cpack_gen|generator|variable|envvar|module|policy|"
"prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
@@ -457,6 +457,12 @@ void cmRST::UnindentLines(std::vector<std::string>& lines)
size_t trailingEmpty =
std::distance(rit, cmFindNot(cmReverseRange(lines), std::string()));
+ if ((leadingEmpty + trailingEmpty) >= lines.size()) {
+ // All lines are empty. The markup block is empty. Leave only one.
+ lines.resize(1);
+ return;
+ }
+
std::vector<std::string>::iterator contentEnd = cmRotate(
lines.begin(), lines.begin() + leadingEmpty, lines.end() - trailingEmpty);
lines.erase(contentEnd, lines.end());
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 0d8f1cc..e9343c7 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -335,7 +335,7 @@ bool cmSetPropertyCommand::HandleCacheMode()
!cmSystemTools::IsOff(this->PropertyValue)) {
std::ostringstream e;
e << "given non-boolean value \"" << this->PropertyValue
- << "\" for CACHE property \"ADVANCED\". ";
+ << R"(" for CACHE property "ADVANCED". )";
this->SetError(e.str());
return false;
}
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index d579018..edad4c7 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -44,13 +44,13 @@ public:
cmCustomCommand const* GetCustomCommand() const;
void SetCustomCommand(cmCustomCommand* cc);
- ///! Set/Get a property of this source file
+ //! Set/Get a property of this source file
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
- ///! Might return a nullptr if the property is not set or invalid
+ //! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
- ///! Always returns a valid pointer
+ //! Always returns a valid pointer
const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
@@ -58,7 +58,7 @@ public:
command like get_property or get_source_file_property. */
const char* GetPropertyForUser(const std::string& prop);
- ///! Checks is the GENERATED property is set and true
+ //! Checks is the GENERATED property is set and true
/// @return Equivalent to GetPropertyAsBool("GENERATED")
bool GetIsGenerated() const { return this->IsGenerated; }
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index 34ded38..2bc4c39 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -77,6 +77,7 @@ std::vector<std::string> prepareFilesPathsForTree(
const std::string& currentSourceDir)
{
std::vector<std::string> prepared;
+ prepared.reserve(filesPaths.size());
for (auto const& filePath : filesPaths) {
prepared.push_back(prepareFilePathForTree(filePath, currentSourceDir));
diff --git a/Source/cmState.h b/Source/cmState.h
index 190eafc..6abe71c 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -107,7 +107,7 @@ public:
void RemoveCacheEntryProperty(std::string const& key,
std::string const& propertyName);
- ///! Break up a line like VAR:type="value" into var, type and value
+ //! Break up a line like VAR:type="value" into var, type and value
static bool ParseCacheEntry(const std::string& entry, std::string& var,
std::string& value,
cmStateEnums::CacheEntryType& type);
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 252d985..998f904 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -1,9 +1,13 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#define _SCL_SECURE_NO_WARNINGS
+
#include "cmStringCommand.h"
#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
#include <ctype.h>
+#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdio.h>
@@ -13,6 +17,7 @@
#include "cmCryptoHash.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmRange.h"
#include "cmStringReplaceHelper.h"
#include "cmSystemTools.h"
@@ -79,6 +84,9 @@ bool cmStringCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "STRIP") {
return this->HandleStripCommand(args);
}
+ if (subCommand == "REPEAT") {
+ return this->HandleRepeatCommand(args);
+ }
if (subCommand == "RANDOM") {
return this->HandleRandomCommand(args);
}
@@ -709,6 +717,59 @@ bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args)
return true;
}
+bool cmStringCommand::HandleRepeatCommand(std::vector<std::string> const& args)
+{
+ // `string(REPEAT "<str>" <times> OUTPUT_VARIABLE)`
+ enum ArgPos : std::size_t
+ {
+ SUB_COMMAND,
+ VALUE,
+ TIMES,
+ OUTPUT_VARIABLE,
+ TOTAL_ARGS
+ };
+
+ if (args.size() != ArgPos::TOTAL_ARGS) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "sub-command REPEAT requires three arguments.");
+ return true;
+ }
+
+ unsigned long times;
+ if (!cmSystemTools::StringToULong(args[ArgPos::TIMES].c_str(), &times)) {
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "repeat count is not a positive number.");
+ return true;
+ }
+
+ const auto& stringValue = args[ArgPos::VALUE];
+ const auto& variableName = args[ArgPos::OUTPUT_VARIABLE];
+ const auto inStringLength = stringValue.size();
+
+ std::string result;
+ switch (inStringLength) {
+ case 0u:
+ // Nothing to do for zero length input strings
+ break;
+ case 1u:
+ // NOTE If the string to repeat consists of the only character,
+ // use the appropriate constructor.
+ result = std::string(times, stringValue[0]);
+ break;
+ default:
+ result = std::string(inStringLength * times, char{});
+ for (auto i = 0u; i < times; ++i) {
+ std::copy(cm::cbegin(stringValue), cm::cend(stringValue),
+ &result[i * inStringLength]);
+ }
+ break;
+ }
+
+ this->Makefile->AddDefinition(variableName, result.c_str());
+ return true;
+}
+
bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
{
if (args.size() < 2 || args.size() == 3 || args.size() == 5) {
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index cbff73e..acde605 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -51,6 +51,7 @@ protected:
bool HandleConcatCommand(std::vector<std::string> const& args);
bool HandleJoinCommand(std::vector<std::string> const& args);
bool HandleStripCommand(std::vector<std::string> const& args);
+ bool HandleRepeatCommand(std::vector<std::string> const& args);
bool HandleRandomCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
bool HandleTimestampCommand(std::vector<std::string> const& args);
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index d201061..212608d 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -3023,6 +3023,12 @@ bool cmSystemTools::StringToULong(const char* str, unsigned long* value)
{
errno = 0;
char* endp;
+ while (isspace(*str)) {
+ ++str;
+ }
+ if (*str == '-') {
+ return false;
+ }
*value = strtoul(str, &endp, 10);
return (*endp == '\0') && (endp != str) && (errno == 0);
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 0b75025..a8b2d37 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -45,7 +45,7 @@ public:
static void ExpandRegistryValues(std::string& source,
KeyWOW64 view = KeyWOW64_Default);
- ///! Escape quotes in a string.
+ //! Escape quotes in a string.
static std::string EscapeQuotes(const std::string& str);
/** Map help document name to file name. */
@@ -78,11 +78,11 @@ public:
using OutputCallback = std::function<void(std::string const&)>;
- ///! Send a string to stdout
+ //! Send a string to stdout
static void Stdout(const std::string& s);
static void SetStdoutCallback(OutputCallback f);
- ///! Send a string to stderr
+ //! Send a string to stderr
static void Stderr(const std::string& s);
static void SetStderrCallback(OutputCallback f);
@@ -90,25 +90,25 @@ public:
static void SetInterruptCallback(InterruptCallback f);
static bool GetInterruptFlag();
- ///! Return true if there was an error at any point.
+ //! Return true if there was an error at any point.
static bool GetErrorOccuredFlag()
{
return cmSystemTools::s_ErrorOccured ||
cmSystemTools::s_FatalErrorOccured || GetInterruptFlag();
}
- ///! If this is set to true, cmake stops processing commands.
+ //! If this is set to true, cmake stops processing commands.
static void SetFatalErrorOccured()
{
cmSystemTools::s_FatalErrorOccured = true;
}
static void SetErrorOccured() { cmSystemTools::s_ErrorOccured = true; }
- ///! Return true if there was an error at any point.
+ //! Return true if there was an error at any point.
static bool GetFatalErrorOccured()
{
return cmSystemTools::s_FatalErrorOccured || GetInterruptFlag();
}
- ///! Set the error occurred flag and fatal error back to false
+ //! Set the error occurred flag and fatal error back to false
static void ResetErrorOccuredFlag()
{
cmSystemTools::s_FatalErrorOccured = false;
@@ -138,9 +138,9 @@ public:
static bool IsOff(const char* val);
static bool IsOff(const std::string& val);
- ///! Return true if value is NOTFOUND or ends in -NOTFOUND.
+ //! Return true if value is NOTFOUND or ends in -NOTFOUND.
static bool IsNOTFOUND(const char* value);
- ///! Return true if the path is a framework
+ //! Return true if the path is a framework
static bool IsPathToFramework(const std::string& value);
static bool DoesFileExistWithExtensions(
@@ -177,14 +177,14 @@ public:
static bool RenameFile(const std::string& oldname,
const std::string& newname);
- ///! Compute the hash of a file
+ //! Compute the hash of a file
static std::string ComputeFileHash(const std::string& source,
cmCryptoHash::Algo algo);
/** Compute the md5sum of a string. */
static std::string ComputeStringMD5(const std::string& input);
- ///! Get the SHA thumbprint for a certificate file
+ //! Get the SHA thumbprint for a certificate file
static std::string ComputeCertificateThumbprint(const std::string& source);
/**
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index c6a69be..dc9b6d2 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -13,6 +13,7 @@
#include <unordered_set>
#include "cmAlgorithms.h"
+#include "cmCustomCommand.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -21,6 +22,7 @@
#include "cmMessageType.h"
#include "cmMessenger.h"
#include "cmProperty.h"
+#include "cmPropertyMap.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
@@ -32,7 +34,7 @@
#include "cmTargetPropertyComputer.h"
#include "cmake.h"
-///! Append all elements from the second container to the first container
+//! Append all elements from the second container to the first container
template <class C, class R>
static inline void CApp(C& container, R const& range)
{
@@ -164,6 +166,26 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>(
class cmTargetInternals
{
public:
+ cmStateEnums::TargetType TargetType;
+ cmMakefile* Makefile;
+ cmPolicies::PolicyMap PolicyMap;
+ std::string Name;
+ std::string InstallPath;
+ std::string RuntimeInstallPath;
+ cmPropertyMap Properties;
+ bool IsGeneratorProvided;
+ bool HaveInstallRule;
+ bool DLLPlatform;
+ bool IsAndroid;
+ bool IsImportedTarget;
+ bool ImportedGloballyVisible;
+ bool BuildInterfaceIncludesAppended;
+ std::set<BT<std::string>> Utilities;
+ std::vector<cmCustomCommand> PreBuildCommands;
+ std::vector<cmCustomCommand> PreLinkCommands;
+ std::vector<cmCustomCommand> PostBuildCommands;
+ std::set<std::string> SystemIncludeDirectories;
+ cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
std::vector<std::string> IncludeDirectoriesEntries;
std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
std::vector<std::string> CompileOptionsEntries;
@@ -180,138 +202,156 @@ public:
std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
std::vector<std::string> LinkImplementationPropertyEntries;
std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
+ std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
+ TLLCommands;
+ cmListFileBacktrace Backtrace;
+
+public:
+ bool CheckImportedLibName(std::string const& prop,
+ std::string const& value) const;
+
+ std::string ProcessSourceItemCMP0049(const std::string& s);
};
cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
Visibility vis, cmMakefile* mf)
+ : impl(cm::make_unique<cmTargetInternals>())
{
assert(mf);
- this->IsGeneratorProvided = false;
- this->Name = name;
- this->TargetTypeValue = type;
- this->Makefile = mf;
- this->HaveInstallRule = false;
- this->DLLPlatform = false;
- this->IsAndroid = false;
- this->IsImportedTarget =
+ impl->TargetType = type;
+ impl->Makefile = mf;
+ impl->Name = name;
+ impl->IsGeneratorProvided = false;
+ impl->HaveInstallRule = false;
+ impl->DLLPlatform = false;
+ impl->IsAndroid = false;
+ impl->IsImportedTarget =
(vis == VisibilityImported || vis == VisibilityImportedGlobally);
- this->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
- this->BuildInterfaceIncludesAppended = false;
+ impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
+ impl->BuildInterfaceIncludesAppended = false;
// Check whether this is a DLL platform.
- this->DLLPlatform =
- !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
+ impl->DLLPlatform =
+ !impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
// Check whether we are targeting an Android platform.
- this->IsAndroid =
- (this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android");
+ impl->IsAndroid =
+ (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android");
+
+ std::string gKey;
+ gKey.reserve(128);
+ gKey += "CMAKE_";
+ auto InitProperty = [this, mf, &gKey](const std::string& property,
+ const char* default_value) {
+ // Replace everything after "CMAKE_"
+ gKey.replace(gKey.begin() + 6, gKey.end(), property);
+ if (const char* value = mf->GetDefinition(gKey)) {
+ this->SetProperty(property, value);
+ } else if (default_value) {
+ this->SetProperty(property, default_value);
+ }
+ };
// Setup default property values.
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("ANDROID_API", nullptr);
- this->SetPropertyDefault("ANDROID_API_MIN", nullptr);
- this->SetPropertyDefault("ANDROID_ARCH", nullptr);
- this->SetPropertyDefault("ANDROID_STL_TYPE", nullptr);
- this->SetPropertyDefault("ANDROID_SKIP_ANT_STEP", nullptr);
- this->SetPropertyDefault("ANDROID_PROCESS_MAX", nullptr);
- this->SetPropertyDefault("ANDROID_PROGUARD", nullptr);
- this->SetPropertyDefault("ANDROID_PROGUARD_CONFIG_PATH", nullptr);
- this->SetPropertyDefault("ANDROID_SECURE_PROPS_PATH", nullptr);
- this->SetPropertyDefault("ANDROID_NATIVE_LIB_DIRECTORIES", nullptr);
- this->SetPropertyDefault("ANDROID_NATIVE_LIB_DEPENDENCIES", nullptr);
- this->SetPropertyDefault("ANDROID_JAVA_SOURCE_DIR", nullptr);
- this->SetPropertyDefault("ANDROID_JAR_DIRECTORIES", nullptr);
- this->SetPropertyDefault("ANDROID_JAR_DEPENDENCIES", nullptr);
- 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");
- this->SetPropertyDefault("INTERPROCEDURAL_OPTIMIZATION", nullptr);
- this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
- this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
- this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", nullptr);
- this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", nullptr);
- this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", nullptr);
- this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", nullptr);
- this->SetPropertyDefault("COMPILE_PDB_OUTPUT_DIRECTORY", nullptr);
- this->SetPropertyDefault("Fortran_FORMAT", nullptr);
- this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", nullptr);
- this->SetPropertyDefault("Fortran_COMPILER_LAUNCHER", nullptr);
- this->SetPropertyDefault("GNUtoMS", nullptr);
- this->SetPropertyDefault("OSX_ARCHITECTURES", nullptr);
- this->SetPropertyDefault("IOS_INSTALL_COMBINED", nullptr);
- 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);
- this->SetPropertyDefault("AUTOMOC_MACRO_NAMES", nullptr);
- this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", nullptr);
- this->SetPropertyDefault("AUTOUIC_OPTIONS", nullptr);
- this->SetPropertyDefault("AUTOUIC_SEARCH_PATHS", nullptr);
- this->SetPropertyDefault("AUTORCC_OPTIONS", nullptr);
- this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", nullptr);
- this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", nullptr);
- this->SetPropertyDefault("WIN32_EXECUTABLE", nullptr);
- this->SetPropertyDefault("MACOSX_BUNDLE", nullptr);
- this->SetPropertyDefault("MACOSX_RPATH", nullptr);
- this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", nullptr);
- this->SetPropertyDefault("BUILD_WITH_INSTALL_NAME_DIR", nullptr);
- this->SetPropertyDefault("C_CLANG_TIDY", nullptr);
- this->SetPropertyDefault("C_COMPILER_LAUNCHER", nullptr);
- this->SetPropertyDefault("C_CPPLINT", nullptr);
- this->SetPropertyDefault("C_CPPCHECK", nullptr);
- this->SetPropertyDefault("C_INCLUDE_WHAT_YOU_USE", nullptr);
- this->SetPropertyDefault("LINK_WHAT_YOU_USE", nullptr);
- this->SetPropertyDefault("C_STANDARD", nullptr);
- this->SetPropertyDefault("C_STANDARD_REQUIRED", nullptr);
- this->SetPropertyDefault("C_EXTENSIONS", nullptr);
- this->SetPropertyDefault("CXX_CLANG_TIDY", nullptr);
- this->SetPropertyDefault("CXX_COMPILER_LAUNCHER", nullptr);
- this->SetPropertyDefault("CXX_CPPLINT", nullptr);
- this->SetPropertyDefault("CXX_CPPCHECK", nullptr);
- this->SetPropertyDefault("CXX_INCLUDE_WHAT_YOU_USE", nullptr);
- this->SetPropertyDefault("CXX_STANDARD", nullptr);
- this->SetPropertyDefault("CXX_STANDARD_REQUIRED", nullptr);
- this->SetPropertyDefault("CXX_EXTENSIONS", nullptr);
- this->SetPropertyDefault("CUDA_STANDARD", nullptr);
- this->SetPropertyDefault("CUDA_STANDARD_REQUIRED", nullptr);
- this->SetPropertyDefault("CUDA_EXTENSIONS", nullptr);
- this->SetPropertyDefault("CUDA_COMPILER_LAUNCHER", nullptr);
- this->SetPropertyDefault("CUDA_SEPARABLE_COMPILATION", nullptr);
- this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr);
- this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr);
- this->SetPropertyDefault("FOLDER", nullptr);
+ InitProperty("ANDROID_API", nullptr);
+ InitProperty("ANDROID_API_MIN", nullptr);
+ InitProperty("ANDROID_ARCH", nullptr);
+ InitProperty("ANDROID_STL_TYPE", nullptr);
+ InitProperty("ANDROID_SKIP_ANT_STEP", nullptr);
+ InitProperty("ANDROID_PROCESS_MAX", nullptr);
+ InitProperty("ANDROID_PROGUARD", nullptr);
+ InitProperty("ANDROID_PROGUARD_CONFIG_PATH", nullptr);
+ InitProperty("ANDROID_SECURE_PROPS_PATH", nullptr);
+ InitProperty("ANDROID_NATIVE_LIB_DIRECTORIES", nullptr);
+ InitProperty("ANDROID_NATIVE_LIB_DEPENDENCIES", nullptr);
+ InitProperty("ANDROID_JAVA_SOURCE_DIR", nullptr);
+ InitProperty("ANDROID_JAR_DIRECTORIES", nullptr);
+ InitProperty("ANDROID_JAR_DEPENDENCIES", nullptr);
+ InitProperty("ANDROID_ASSETS_DIRECTORIES", nullptr);
+ InitProperty("ANDROID_ANT_ADDITIONAL_OPTIONS", nullptr);
+ InitProperty("BUILD_RPATH", nullptr);
+ InitProperty("BUILD_RPATH_USE_ORIGIN", nullptr);
+ InitProperty("INSTALL_NAME_DIR", nullptr);
+ InitProperty("INSTALL_RPATH", "");
+ InitProperty("INSTALL_RPATH_USE_LINK_PATH", "OFF");
+ InitProperty("INTERPROCEDURAL_OPTIMIZATION", nullptr);
+ InitProperty("SKIP_BUILD_RPATH", "OFF");
+ InitProperty("BUILD_WITH_INSTALL_RPATH", "OFF");
+ InitProperty("ARCHIVE_OUTPUT_DIRECTORY", nullptr);
+ InitProperty("LIBRARY_OUTPUT_DIRECTORY", nullptr);
+ InitProperty("RUNTIME_OUTPUT_DIRECTORY", nullptr);
+ InitProperty("PDB_OUTPUT_DIRECTORY", nullptr);
+ InitProperty("COMPILE_PDB_OUTPUT_DIRECTORY", nullptr);
+ InitProperty("Fortran_FORMAT", nullptr);
+ InitProperty("Fortran_MODULE_DIRECTORY", nullptr);
+ InitProperty("Fortran_COMPILER_LAUNCHER", nullptr);
+ InitProperty("GNUtoMS", nullptr);
+ InitProperty("OSX_ARCHITECTURES", nullptr);
+ InitProperty("IOS_INSTALL_COMBINED", nullptr);
+ InitProperty("AUTOMOC", nullptr);
+ InitProperty("AUTOUIC", nullptr);
+ InitProperty("AUTORCC", nullptr);
+ InitProperty("AUTOGEN_ORIGIN_DEPENDS", nullptr);
+ InitProperty("AUTOGEN_PARALLEL", nullptr);
+ InitProperty("AUTOMOC_COMPILER_PREDEFINES", nullptr);
+ InitProperty("AUTOMOC_DEPEND_FILTERS", nullptr);
+ InitProperty("AUTOMOC_MACRO_NAMES", nullptr);
+ InitProperty("AUTOMOC_MOC_OPTIONS", nullptr);
+ InitProperty("AUTOUIC_OPTIONS", nullptr);
+ InitProperty("AUTOUIC_SEARCH_PATHS", nullptr);
+ InitProperty("AUTORCC_OPTIONS", nullptr);
+ InitProperty("LINK_DEPENDS_NO_SHARED", nullptr);
+ InitProperty("LINK_INTERFACE_LIBRARIES", nullptr);
+ InitProperty("WIN32_EXECUTABLE", nullptr);
+ InitProperty("MACOSX_BUNDLE", nullptr);
+ InitProperty("MACOSX_RPATH", nullptr);
+ InitProperty("NO_SYSTEM_FROM_IMPORTED", nullptr);
+ InitProperty("BUILD_WITH_INSTALL_NAME_DIR", nullptr);
+ InitProperty("C_CLANG_TIDY", nullptr);
+ InitProperty("C_COMPILER_LAUNCHER", nullptr);
+ InitProperty("C_CPPLINT", nullptr);
+ InitProperty("C_CPPCHECK", nullptr);
+ InitProperty("C_INCLUDE_WHAT_YOU_USE", nullptr);
+ InitProperty("LINK_WHAT_YOU_USE", nullptr);
+ InitProperty("C_STANDARD", nullptr);
+ InitProperty("C_STANDARD_REQUIRED", nullptr);
+ InitProperty("C_EXTENSIONS", nullptr);
+ InitProperty("CXX_CLANG_TIDY", nullptr);
+ InitProperty("CXX_COMPILER_LAUNCHER", nullptr);
+ InitProperty("CXX_CPPLINT", nullptr);
+ InitProperty("CXX_CPPCHECK", nullptr);
+ InitProperty("CXX_INCLUDE_WHAT_YOU_USE", nullptr);
+ InitProperty("CXX_STANDARD", nullptr);
+ InitProperty("CXX_STANDARD_REQUIRED", nullptr);
+ InitProperty("CXX_EXTENSIONS", nullptr);
+ InitProperty("CUDA_STANDARD", nullptr);
+ InitProperty("CUDA_STANDARD_REQUIRED", nullptr);
+ InitProperty("CUDA_EXTENSIONS", nullptr);
+ InitProperty("CUDA_COMPILER_LAUNCHER", nullptr);
+ InitProperty("CUDA_SEPARABLE_COMPILATION", nullptr);
+ InitProperty("LINK_SEARCH_START_STATIC", nullptr);
+ InitProperty("LINK_SEARCH_END_STATIC", nullptr);
+ InitProperty("FOLDER", nullptr);
#ifdef __APPLE__
if (this->GetGlobalGenerator()->IsXcode()) {
- this->SetPropertyDefault("XCODE_GENERATE_SCHEME", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_ADDRESS_SANITIZER", nullptr);
- this->SetPropertyDefault(
- "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_THREAD_SANITIZER", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_THREAD_SANITIZER_STOP", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER",
- nullptr);
- this->SetPropertyDefault(
- "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER",
- nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP",
- nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_MALLOC_SCRIBBLE", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_MALLOC_GUARD_EDGES", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_GUARD_MALLOC", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_ZOMBIE_OBJECTS", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_MALLOC_STACK", nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE",
- nullptr);
- this->SetPropertyDefault("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS", nullptr);
+ InitProperty("XCODE_GENERATE_SCHEME", nullptr);
+ InitProperty("XCODE_SCHEME_ADDRESS_SANITIZER", nullptr);
+ InitProperty("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN", nullptr);
+ InitProperty("XCODE_SCHEME_THREAD_SANITIZER", nullptr);
+ InitProperty("XCODE_SCHEME_THREAD_SANITIZER_STOP", nullptr);
+ InitProperty("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER", nullptr);
+ InitProperty("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP", nullptr);
+ InitProperty("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER", nullptr);
+ InitProperty("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP", nullptr);
+ InitProperty("XCODE_SCHEME_MALLOC_SCRIBBLE", nullptr);
+ InitProperty("XCODE_SCHEME_MALLOC_GUARD_EDGES", nullptr);
+ InitProperty("XCODE_SCHEME_GUARD_MALLOC", nullptr);
+ InitProperty("XCODE_SCHEME_ZOMBIE_OBJECTS", nullptr);
+ InitProperty("XCODE_SCHEME_MALLOC_STACK", nullptr);
+ InitProperty("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE", nullptr);
+ InitProperty("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS", nullptr);
}
#endif
}
@@ -333,13 +373,13 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
for (auto const& prop : configProps) {
// Interface libraries have no output locations, so honor only
// the configuration map.
- if (this->TargetTypeValue == cmStateEnums::INTERFACE_LIBRARY &&
+ if (impl->TargetType == cmStateEnums::INTERFACE_LIBRARY &&
strcmp(prop, "MAP_IMPORTED_CONFIG_") != 0) {
continue;
}
std::string property = prop;
property += configUpper;
- this->SetPropertyDefault(property, nullptr);
+ InitProperty(property, nullptr);
}
// Initialize per-configuration name postfix property from the
@@ -347,93 +387,92 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
// compatibility with previous CMake versions in which executables
// did not support this variable. Projects may still specify the
// property directly.
- if (this->TargetTypeValue != cmStateEnums::EXECUTABLE &&
- this->TargetTypeValue != cmStateEnums::INTERFACE_LIBRARY) {
+ if (impl->TargetType != cmStateEnums::EXECUTABLE &&
+ impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
std::string property = cmSystemTools::UpperCase(configName);
property += "_POSTFIX";
- this->SetPropertyDefault(property, nullptr);
+ InitProperty(property, nullptr);
}
}
}
// Save the backtrace of target construction.
- this->Backtrace = this->Makefile->GetBacktrace();
+ impl->Backtrace = impl->Makefile->GetBacktrace();
if (!this->IsImported()) {
// Initialize the INCLUDE_DIRECTORIES property based on the current value
// of the same directory property:
- CApp(this->Internal->IncludeDirectoriesEntries,
- this->Makefile->GetIncludeDirectoriesEntries());
- CApp(this->Internal->IncludeDirectoriesBacktraces,
- this->Makefile->GetIncludeDirectoriesBacktraces());
+ CApp(impl->IncludeDirectoriesEntries,
+ impl->Makefile->GetIncludeDirectoriesEntries());
+ CApp(impl->IncludeDirectoriesBacktraces,
+ impl->Makefile->GetIncludeDirectoriesBacktraces());
{
- auto const& sysInc = this->Makefile->GetSystemIncludeDirectories();
- this->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end());
+ auto const& sysInc = impl->Makefile->GetSystemIncludeDirectories();
+ impl->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end());
}
- CApp(this->Internal->CompileOptionsEntries,
- this->Makefile->GetCompileOptionsEntries());
- CApp(this->Internal->CompileOptionsBacktraces,
- this->Makefile->GetCompileOptionsBacktraces());
+ CApp(impl->CompileOptionsEntries,
+ impl->Makefile->GetCompileOptionsEntries());
+ CApp(impl->CompileOptionsBacktraces,
+ impl->Makefile->GetCompileOptionsBacktraces());
- CApp(this->Internal->LinkOptionsEntries,
- this->Makefile->GetLinkOptionsEntries());
- CApp(this->Internal->LinkOptionsBacktraces,
- this->Makefile->GetLinkOptionsBacktraces());
+ CApp(impl->LinkOptionsEntries, impl->Makefile->GetLinkOptionsEntries());
+ CApp(impl->LinkOptionsBacktraces,
+ impl->Makefile->GetLinkOptionsBacktraces());
- CApp(this->Internal->LinkDirectoriesEntries,
- this->Makefile->GetLinkDirectoriesEntries());
- CApp(this->Internal->LinkDirectoriesBacktraces,
- this->Makefile->GetLinkDirectoriesBacktraces());
+ CApp(impl->LinkDirectoriesEntries,
+ impl->Makefile->GetLinkDirectoriesEntries());
+ CApp(impl->LinkDirectoriesBacktraces,
+ impl->Makefile->GetLinkDirectoriesBacktraces());
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("C_VISIBILITY_PRESET", nullptr);
- this->SetPropertyDefault("CXX_VISIBILITY_PRESET", nullptr);
- this->SetPropertyDefault("CUDA_VISIBILITY_PRESET", nullptr);
- this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", nullptr);
+ InitProperty("C_VISIBILITY_PRESET", nullptr);
+ InitProperty("CXX_VISIBILITY_PRESET", nullptr);
+ InitProperty("CUDA_VISIBILITY_PRESET", nullptr);
+ InitProperty("VISIBILITY_INLINES_HIDDEN", nullptr);
}
- if (this->TargetTypeValue == cmStateEnums::EXECUTABLE) {
- this->SetPropertyDefault("ANDROID_GUI", nullptr);
- this->SetPropertyDefault("CROSSCOMPILING_EMULATOR", nullptr);
- this->SetPropertyDefault("ENABLE_EXPORTS", nullptr);
+ if (impl->TargetType == cmStateEnums::EXECUTABLE) {
+ InitProperty("ANDROID_GUI", nullptr);
+ InitProperty("CROSSCOMPILING_EMULATOR", nullptr);
+ InitProperty("ENABLE_EXPORTS", nullptr);
}
- if (this->TargetTypeValue == cmStateEnums::SHARED_LIBRARY ||
- this->TargetTypeValue == cmStateEnums::MODULE_LIBRARY) {
+ if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
+ impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
}
- if (this->TargetTypeValue == cmStateEnums::SHARED_LIBRARY ||
- this->TargetTypeValue == cmStateEnums::EXECUTABLE) {
- this->SetPropertyDefault("WINDOWS_EXPORT_ALL_SYMBOLS", nullptr);
+ if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
+ impl->TargetType == cmStateEnums::EXECUTABLE) {
+ InitProperty("WINDOWS_EXPORT_ALL_SYMBOLS", nullptr);
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", nullptr);
+ InitProperty("POSITION_INDEPENDENT_CODE", nullptr);
}
// Record current policies for later use.
- this->Makefile->RecordPolicies(this->PolicyMap);
+ impl->Makefile->RecordPolicies(impl->PolicyMap);
- if (this->TargetTypeValue == cmStateEnums::INTERFACE_LIBRARY) {
+ if (impl->TargetType == cmStateEnums::INTERFACE_LIBRARY) {
// This policy is checked in a few conditions. The properties relevant
// to the policy are always ignored for cmStateEnums::INTERFACE_LIBRARY
// targets,
// so ensure that the conditions don't lead to nonsense.
- this->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
+ impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("JOB_POOL_COMPILE", nullptr);
- this->SetPropertyDefault("JOB_POOL_LINK", nullptr);
+ InitProperty("JOB_POOL_COMPILE", nullptr);
+ InitProperty("JOB_POOL_LINK", nullptr);
}
- if (this->TargetTypeValue <= cmStateEnums::UTILITY) {
- this->SetPropertyDefault("DOTNET_TARGET_FRAMEWORK_VERSION", nullptr);
+ if (impl->TargetType <= cmStateEnums::UTILITY) {
+ InitProperty("DOTNET_TARGET_FRAMEWORK_VERSION", nullptr);
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
@@ -454,7 +493,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
if (assignment != std::string::npos) {
const std::string propName = vsGlobal + i.substr(0, assignment);
const std::string propValue = i.substr(assignment + 1);
- this->SetPropertyDefault(propName, propValue.c_str());
+ InitProperty(propName, propValue.c_str());
}
}
}
@@ -462,20 +501,56 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
}
}
+cmTarget::cmTarget(cmTarget&&) noexcept = default;
+cmTarget::~cmTarget() = default;
+
+cmTarget& cmTarget::operator=(cmTarget&&) noexcept = default;
+
+cmStateEnums::TargetType cmTarget::GetType() const
+{
+ return impl->TargetType;
+}
+
+cmMakefile* cmTarget::GetMakefile() const
+{
+ return impl->Makefile;
+}
+
+cmPolicies::PolicyMap const& cmTarget::GetPolicyMap() const
+{
+ return impl->PolicyMap;
+}
+
+const std::string& cmTarget::GetName() const
+{
+ return impl->Name;
+}
+
+cmPolicies::PolicyStatus cmTarget::GetPolicyStatus(
+ cmPolicies::PolicyID policy) const
+{
+ return impl->PolicyMap.Get(policy);
+}
+
cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
{
- return this->GetMakefile()->GetGlobalGenerator();
+ return impl->Makefile->GetGlobalGenerator();
+}
+
+void cmTarget::AddUtility(std::string const& name, cmMakefile* mf)
+{
+ impl->Utilities.insert(
+ BT<std::string>(name, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
}
-void cmTarget::AddUtility(std::string const& u, cmMakefile* mf)
+std::set<BT<std::string>> const& cmTarget::GetUtilities() const
{
- BT<std::string> util(u, mf ? mf->GetBacktrace() : cmListFileBacktrace());
- this->Utilities.insert(util);
+ return impl->Utilities;
}
cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
- return this->Backtrace;
+ return impl->Backtrace;
}
bool cmTarget::IsExecutableWithExports() const
@@ -484,34 +559,57 @@ bool cmTarget::IsExecutableWithExports() const
this->GetPropertyAsBool("ENABLE_EXPORTS"));
}
-bool cmTarget::HasImportLibrary() const
-{
- return (this->DLLPlatform &&
- (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
- this->IsExecutableWithExports()));
-}
-
bool cmTarget::IsFrameworkOnApple() const
{
return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
- this->Makefile->IsOn("APPLE") &&
+ impl->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("FRAMEWORK"));
}
bool cmTarget::IsAppBundleOnApple() const
{
return (this->GetType() == cmStateEnums::EXECUTABLE &&
- this->Makefile->IsOn("APPLE") &&
+ impl->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("MACOSX_BUNDLE"));
}
+std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const
+{
+ return impl->PreBuildCommands;
+}
+
+void cmTarget::AddPreBuildCommand(cmCustomCommand const& cmd)
+{
+ impl->PreBuildCommands.push_back(cmd);
+}
+
+std::vector<cmCustomCommand> const& cmTarget::GetPreLinkCommands() const
+{
+ return impl->PreLinkCommands;
+}
+
+void cmTarget::AddPreLinkCommand(cmCustomCommand const& cmd)
+{
+ impl->PreLinkCommands.push_back(cmd);
+}
+
+std::vector<cmCustomCommand> const& cmTarget::GetPostBuildCommands() const
+{
+ return impl->PostBuildCommands;
+}
+
+void cmTarget::AddPostBuildCommand(cmCustomCommand const& cmd)
+{
+ impl->PostBuildCommands.push_back(cmd);
+}
+
void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
if (!srcs.empty()) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.push_back(cmJoin(srcs, ";"));
- this->Internal->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.push_back(cmJoin(srcs, ";"));
+ impl->SourceBacktraces.push_back(lfbt);
}
}
@@ -522,25 +620,25 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
for (auto filename : srcs) {
if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) {
if (!filename.empty()) {
- filename = this->ProcessSourceItemCMP0049(filename);
+ filename = impl->ProcessSourceItemCMP0049(filename);
if (filename.empty()) {
return;
}
}
- this->Makefile->GetOrCreateSource(filename);
+ impl->Makefile->GetOrCreateSource(filename);
}
srcFiles += sep;
srcFiles += filename;
sep = ";";
}
if (!srcFiles.empty()) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.push_back(std::move(srcFiles));
- this->Internal->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.push_back(std::move(srcFiles));
+ impl->SourceBacktraces.push_back(lfbt);
}
}
-std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
+std::string cmTargetInternals::ProcessSourceItemCMP0049(const std::string& s)
{
std::string src = s;
@@ -565,7 +663,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
}
if (!noMessage) {
e << "Legacy variable expansion in source file \"" << s
- << "\" expanded to \"" << src << "\" in target \"" << this->GetName()
+ << "\" expanded to \"" << src << "\" in target \"" << this->Name
<< "\". This behavior will be removed in a "
"future version of CMake.";
this->Makefile->IssueMessage(messageType, e.str());
@@ -579,7 +677,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s)
{
- std::string src = this->ProcessSourceItemCMP0049(s);
+ std::string src = impl->ProcessSourceItemCMP0049(s);
if (!s.empty() && src.empty()) {
return nullptr;
}
@@ -643,26 +741,22 @@ public:
cmSourceFile* cmTarget::AddSource(const std::string& src, bool before)
{
- cmSourceFileLocation sfl(this->Makefile, src,
+ cmSourceFileLocation sfl(impl->Makefile, src,
cmSourceFileLocationKind::Known);
- if (std::find_if(this->Internal->SourceEntries.begin(),
- this->Internal->SourceEntries.end(),
+ if (std::find_if(impl->SourceEntries.begin(), impl->SourceEntries.end(),
TargetPropertyEntryFinder(sfl)) ==
- this->Internal->SourceEntries.end()) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.insert(
- before ? this->Internal->SourceEntries.begin()
- : this->Internal->SourceEntries.end(),
- src);
- this->Internal->SourceBacktraces.insert(
- before ? this->Internal->SourceBacktraces.begin()
- : this->Internal->SourceBacktraces.end(),
- lfbt);
+ impl->SourceEntries.end()) {
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.insert(
+ before ? impl->SourceEntries.begin() : impl->SourceEntries.end(), src);
+ impl->SourceBacktraces.insert(before ? impl->SourceBacktraces.begin()
+ : impl->SourceBacktraces.end(),
+ lfbt);
}
if (cmGeneratorExpression::Find(src) != std::string::npos) {
return nullptr;
}
- return this->Makefile->GetOrCreateSource(src, false,
+ return impl->Makefile->GetOrCreateSource(src, false,
cmSourceFileLocationKind::Known);
}
@@ -682,7 +776,7 @@ std::string cmTarget::GetDebugGeneratorExpressions(
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> debugConfigs =
- this->Makefile->GetCMakeInstance()->GetDebugConfigs();
+ impl->Makefile->GetCMakeInstance()->GetDebugConfigs();
std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";
@@ -708,13 +802,13 @@ bool cmTarget::PushTLLCommandTrace(TLLSignature signature,
cmListFileContext const& lfc)
{
bool ret = true;
- if (!this->TLLCommands.empty()) {
- if (this->TLLCommands.back().first != signature) {
+ if (!impl->TLLCommands.empty()) {
+ if (impl->TLLCommands.back().first != signature) {
ret = false;
}
}
- if (this->TLLCommands.empty() || this->TLLCommands.back().second != lfc) {
- this->TLLCommands.emplace_back(signature, lfc);
+ if (impl->TLLCommands.empty() || impl->TLLCommands.back().second != lfc) {
+ impl->TLLCommands.emplace_back(signature, lfc);
}
return ret;
}
@@ -724,18 +818,63 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
const char* sigString =
(sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain");
s << "The uses of the " << sigString << " signature are here:\n";
- cmStateDirectory cmDir =
- this->GetMakefile()->GetStateSnapshot().GetDirectory();
- for (auto const& cmd : this->TLLCommands) {
+ cmStateDirectory cmDir = impl->Makefile->GetStateSnapshot().GetDirectory();
+ for (auto const& cmd : impl->TLLCommands) {
if (cmd.first == sig) {
cmListFileContext lfc = cmd.second;
lfc.FilePath = cmDir.ConvertToRelPathIfNotContained(
- this->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
+ impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
s << " * " << lfc << std::endl;
}
}
}
+std::string const& cmTarget::GetInstallPath() const
+{
+ return impl->InstallPath;
+}
+
+void cmTarget::SetInstallPath(std::string const& name)
+{
+ impl->InstallPath = name;
+}
+
+std::string const& cmTarget::GetRuntimeInstallPath() const
+{
+ return impl->RuntimeInstallPath;
+}
+
+void cmTarget::SetRuntimeInstallPath(std::string const& name)
+{
+ impl->RuntimeInstallPath = name;
+}
+
+bool cmTarget::GetHaveInstallRule() const
+{
+ return impl->HaveInstallRule;
+}
+
+void cmTarget::SetHaveInstallRule(bool hir)
+{
+ impl->HaveInstallRule = hir;
+}
+
+bool cmTarget::GetIsGeneratorProvided() const
+{
+ return impl->IsGeneratorProvided;
+}
+
+void cmTarget::SetIsGeneratorProvided(bool igp)
+{
+ impl->IsGeneratorProvided = igp;
+}
+
+cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries()
+ const
+{
+ return impl->OriginalLinkLibraries;
+}
+
void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
cmTargetLinkLibraryType llt)
{
@@ -763,11 +902,11 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
(tgt &&
(tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
- (this->Name == lib)) {
+ (impl->Name == lib)) {
return;
}
- this->OriginalLinkLibraries.emplace_back(lib, llt);
+ impl->OriginalLinkLibraries.emplace_back(lib, llt);
// Add the explicit dependency information for libraries. This is
// simply a set of libraries separated by ";". There should always
@@ -777,11 +916,11 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
// may be purposefully duplicated to handle recursive dependencies,
// and we removing one instance will break the link line. Duplicates
// will be appropriately eliminated at emit time.
- if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
- this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY &&
+ if (impl->TargetType >= cmStateEnums::STATIC_LIBRARY &&
+ impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
(this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
- std::string targetEntry = this->Name;
+ std::string targetEntry = impl->Name;
targetEntry += "_LIB_DEPENDS";
std::string dependencies;
const char* old_val = mf.GetDefinition(targetEntry);
@@ -809,94 +948,99 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
void cmTarget::AddSystemIncludeDirectories(const std::set<std::string>& incs)
{
- this->SystemIncludeDirectories.insert(incs.begin(), incs.end());
+ impl->SystemIncludeDirectories.insert(incs.begin(), incs.end());
+}
+
+std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const
+{
+ return impl->SystemIncludeDirectories;
}
cmStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
- return cmMakeRange(this->Internal->IncludeDirectoriesEntries);
+ return cmMakeRange(impl->IncludeDirectoriesEntries);
}
cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const
{
- return cmMakeRange(this->Internal->IncludeDirectoriesBacktraces);
+ return cmMakeRange(impl->IncludeDirectoriesBacktraces);
}
cmStringRange cmTarget::GetCompileOptionsEntries() const
{
- return cmMakeRange(this->Internal->CompileOptionsEntries);
+ return cmMakeRange(impl->CompileOptionsEntries);
}
cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const
{
- return cmMakeRange(this->Internal->CompileOptionsBacktraces);
+ return cmMakeRange(impl->CompileOptionsBacktraces);
}
cmStringRange cmTarget::GetCompileFeaturesEntries() const
{
- return cmMakeRange(this->Internal->CompileFeaturesEntries);
+ return cmMakeRange(impl->CompileFeaturesEntries);
}
cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const
{
- return cmMakeRange(this->Internal->CompileFeaturesBacktraces);
+ return cmMakeRange(impl->CompileFeaturesBacktraces);
}
cmStringRange cmTarget::GetCompileDefinitionsEntries() const
{
- return cmMakeRange(this->Internal->CompileDefinitionsEntries);
+ return cmMakeRange(impl->CompileDefinitionsEntries);
}
cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const
{
- return cmMakeRange(this->Internal->CompileDefinitionsBacktraces);
+ return cmMakeRange(impl->CompileDefinitionsBacktraces);
}
cmStringRange cmTarget::GetSourceEntries() const
{
- return cmMakeRange(this->Internal->SourceEntries);
+ return cmMakeRange(impl->SourceEntries);
}
cmBacktraceRange cmTarget::GetSourceBacktraces() const
{
- return cmMakeRange(this->Internal->SourceBacktraces);
+ return cmMakeRange(impl->SourceBacktraces);
}
cmStringRange cmTarget::GetLinkOptionsEntries() const
{
- return cmMakeRange(this->Internal->LinkOptionsEntries);
+ return cmMakeRange(impl->LinkOptionsEntries);
}
cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const
{
- return cmMakeRange(this->Internal->LinkOptionsBacktraces);
+ return cmMakeRange(impl->LinkOptionsBacktraces);
}
cmStringRange cmTarget::GetLinkDirectoriesEntries() const
{
- return cmMakeRange(this->Internal->LinkDirectoriesEntries);
+ return cmMakeRange(impl->LinkDirectoriesEntries);
}
cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const
{
- return cmMakeRange(this->Internal->LinkDirectoriesBacktraces);
+ return cmMakeRange(impl->LinkDirectoriesBacktraces);
}
cmStringRange cmTarget::GetLinkImplementationEntries() const
{
- return cmMakeRange(this->Internal->LinkImplementationPropertyEntries);
+ return cmMakeRange(impl->LinkImplementationPropertyEntries);
}
cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const
{
- return cmMakeRange(this->Internal->LinkImplementationPropertyBacktraces);
+ return cmMakeRange(impl->LinkImplementationPropertyBacktraces);
}
void cmTarget::SetProperty(const std::string& prop, const char* value)
{
if (!cmTargetPropertyComputer::PassesWhitelist(
- this->GetType(), prop, this->Makefile->GetMessenger(),
- this->Makefile->GetBacktrace())) {
+ this->GetType(), prop, impl->Makefile->GetMessenger(),
+ impl->Makefile->GetBacktrace())) {
return;
}
#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
@@ -918,133 +1062,133 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
std::ostringstream e;
e << "MANUALLY_ADDED_DEPENDENCIES property is read-only\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propNAME) {
std::ostringstream e;
e << "NAME property is read-only\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propTYPE) {
std::ostringstream e;
e << "TYPE property is read-only\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propEXPORT_NAME && this->IsImported()) {
std::ostringstream e;
e << "EXPORT_NAME property can't be set on imported targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propSOURCES && this->IsImported()) {
std::ostringstream e;
- e << "SOURCES property can't be set on imported targets (\"" << this->Name
+ e << "SOURCES property can't be set on imported targets (\"" << impl->Name
<< "\")\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propIMPORTED_GLOBAL && !this->IsImported()) {
std::ostringstream e;
e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propINCLUDE_DIRECTORIES) {
- this->Internal->IncludeDirectoriesEntries.clear();
- this->Internal->IncludeDirectoriesBacktraces.clear();
+ impl->IncludeDirectoriesEntries.clear();
+ impl->IncludeDirectoriesBacktraces.clear();
if (value) {
- this->Internal->IncludeDirectoriesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt);
+ impl->IncludeDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->IncludeDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == propCOMPILE_OPTIONS) {
- this->Internal->CompileOptionsEntries.clear();
- this->Internal->CompileOptionsBacktraces.clear();
+ impl->CompileOptionsEntries.clear();
+ impl->CompileOptionsBacktraces.clear();
if (value) {
- this->Internal->CompileOptionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileOptionsBacktraces.push_back(lfbt);
+ impl->CompileOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileOptionsBacktraces.push_back(lfbt);
}
} else if (prop == propCOMPILE_FEATURES) {
- this->Internal->CompileFeaturesEntries.clear();
- this->Internal->CompileFeaturesBacktraces.clear();
+ impl->CompileFeaturesEntries.clear();
+ impl->CompileFeaturesBacktraces.clear();
if (value) {
- this->Internal->CompileFeaturesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileFeaturesBacktraces.push_back(lfbt);
+ impl->CompileFeaturesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileFeaturesBacktraces.push_back(lfbt);
}
} else if (prop == propCOMPILE_DEFINITIONS) {
- this->Internal->CompileDefinitionsEntries.clear();
- this->Internal->CompileDefinitionsBacktraces.clear();
+ impl->CompileDefinitionsEntries.clear();
+ impl->CompileDefinitionsBacktraces.clear();
if (value) {
- this->Internal->CompileDefinitionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
+ impl->CompileDefinitionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileDefinitionsBacktraces.push_back(lfbt);
}
} else if (prop == propLINK_OPTIONS) {
- this->Internal->LinkOptionsEntries.clear();
- this->Internal->LinkOptionsBacktraces.clear();
+ impl->LinkOptionsEntries.clear();
+ impl->LinkOptionsBacktraces.clear();
if (value) {
- this->Internal->LinkOptionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->LinkOptionsBacktraces.push_back(lfbt);
+ impl->LinkOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkOptionsBacktraces.push_back(lfbt);
}
} else if (prop == propLINK_DIRECTORIES) {
- this->Internal->LinkDirectoriesEntries.clear();
- this->Internal->LinkDirectoriesBacktraces.clear();
+ impl->LinkDirectoriesEntries.clear();
+ impl->LinkDirectoriesBacktraces.clear();
if (value) {
- this->Internal->LinkDirectoriesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->LinkDirectoriesBacktraces.push_back(lfbt);
+ impl->LinkDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == propLINK_LIBRARIES) {
- this->Internal->LinkImplementationPropertyEntries.clear();
- this->Internal->LinkImplementationPropertyBacktraces.clear();
+ impl->LinkImplementationPropertyEntries.clear();
+ impl->LinkImplementationPropertyBacktraces.clear();
if (value) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->LinkImplementationPropertyEntries.emplace_back(value);
- this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkImplementationPropertyEntries.emplace_back(value);
+ impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
}
} else if (prop == propSOURCES) {
- this->Internal->SourceEntries.clear();
- this->Internal->SourceBacktraces.clear();
+ impl->SourceEntries.clear();
+ impl->SourceBacktraces.clear();
if (value) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.emplace_back(value);
- this->Internal->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.emplace_back(value);
+ impl->SourceBacktraces.push_back(lfbt);
}
} else if (prop == propIMPORTED_GLOBAL) {
if (!cmSystemTools::IsOn(value)) {
std::ostringstream e;
e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
/* no need to change anything if value does not change */
- if (!this->ImportedGloballyVisible) {
- this->ImportedGloballyVisible = true;
+ if (!impl->ImportedGloballyVisible) {
+ impl->ImportedGloballyVisible = true;
this->GetGlobalGenerator()->IndexTarget(this);
}
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
- !this->CheckImportedLibName(prop, value ? value : "")) {
+ !impl->CheckImportedLibName(prop, value ? value : "")) {
/* error was reported by check method */
} else if (prop == propCUDA_PTX_COMPILATION &&
this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT "
"targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
} else {
- this->Properties.SetProperty(prop, value);
+ impl->Properties.SetProperty(prop, value);
}
}
@@ -1052,89 +1196,89 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
bool asString)
{
if (!cmTargetPropertyComputer::PassesWhitelist(
- this->GetType(), prop, this->Makefile->GetMessenger(),
- this->Makefile->GetBacktrace())) {
+ this->GetType(), prop, impl->Makefile->GetMessenger(),
+ impl->Makefile->GetBacktrace())) {
return;
}
if (prop == "NAME") {
std::ostringstream e;
e << "NAME property is read-only\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "EXPORT_NAME" && this->IsImported()) {
std::ostringstream e;
e << "EXPORT_NAME property can't be set on imported targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "SOURCES" && this->IsImported()) {
std::ostringstream e;
- e << "SOURCES property can't be set on imported targets (\"" << this->Name
+ e << "SOURCES property can't be set on imported targets (\"" << impl->Name
<< "\")\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "IMPORTED_GLOBAL") {
std::ostringstream e;
e << "IMPORTED_GLOBAL property can't be appended, only set on imported "
"targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "INCLUDE_DIRECTORIES") {
if (value && *value) {
- this->Internal->IncludeDirectoriesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt);
+ impl->IncludeDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->IncludeDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_OPTIONS") {
if (value && *value) {
- this->Internal->CompileOptionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileOptionsBacktraces.push_back(lfbt);
+ impl->CompileOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileOptionsBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_FEATURES") {
if (value && *value) {
- this->Internal->CompileFeaturesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileFeaturesBacktraces.push_back(lfbt);
+ impl->CompileFeaturesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileFeaturesBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_DEFINITIONS") {
if (value && *value) {
- this->Internal->CompileDefinitionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
+ impl->CompileDefinitionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileDefinitionsBacktraces.push_back(lfbt);
}
} else if (prop == "LINK_OPTIONS") {
if (value && *value) {
- this->Internal->LinkOptionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->LinkOptionsBacktraces.push_back(lfbt);
+ impl->LinkOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkOptionsBacktraces.push_back(lfbt);
}
} else if (prop == "LINK_DIRECTORIES") {
if (value && *value) {
- this->Internal->LinkDirectoriesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->LinkDirectoriesBacktraces.push_back(lfbt);
+ impl->LinkDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == "LINK_LIBRARIES") {
if (value && *value) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->LinkImplementationPropertyEntries.emplace_back(value);
- this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkImplementationPropertyEntries.emplace_back(value);
+ impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
}
} else if (prop == "SOURCES") {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.emplace_back(value);
- this->Internal->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.emplace_back(value);
+ impl->SourceBacktraces.push_back(lfbt);
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
prop + " property may not be APPENDed.");
} else {
- this->Properties.AppendProperty(prop, value, asString);
+ impl->Properties.AppendProperty(prop, value, asString);
}
}
@@ -1147,17 +1291,17 @@ void cmTarget::AppendBuildInterfaceIncludes()
!this->IsExecutableWithExports()) {
return;
}
- if (this->BuildInterfaceIncludesAppended) {
+ if (impl->BuildInterfaceIncludesAppended) {
return;
}
- this->BuildInterfaceIncludesAppended = true;
+ impl->BuildInterfaceIncludesAppended = true;
- if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
- std::string dirs = this->Makefile->GetCurrentBinaryDirectory();
+ if (impl->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
+ std::string dirs = impl->Makefile->GetCurrentBinaryDirectory();
if (!dirs.empty()) {
dirs += ';';
}
- dirs += this->Makefile->GetCurrentSourceDirectory();
+ dirs += impl->Makefile->GetCurrentSourceDirectory();
if (!dirs.empty()) {
this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
("$<BUILD_INTERFACE:" + dirs + ">").c_str());
@@ -1169,67 +1313,66 @@ void cmTarget::InsertInclude(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
std::vector<std::string>::iterator position = before
- ? this->Internal->IncludeDirectoriesEntries.begin()
- : this->Internal->IncludeDirectoriesEntries.end();
+ ? impl->IncludeDirectoriesEntries.begin()
+ : impl->IncludeDirectoriesEntries.end();
std::vector<cmListFileBacktrace>::iterator btPosition = before
- ? this->Internal->IncludeDirectoriesBacktraces.begin()
- : this->Internal->IncludeDirectoriesBacktraces.end();
+ ? impl->IncludeDirectoriesBacktraces.begin()
+ : impl->IncludeDirectoriesBacktraces.end();
- this->Internal->IncludeDirectoriesEntries.insert(position, entry);
- this->Internal->IncludeDirectoriesBacktraces.insert(btPosition, bt);
+ impl->IncludeDirectoriesEntries.insert(position, entry);
+ impl->IncludeDirectoriesBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertCompileOption(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
std::vector<std::string>::iterator position = before
- ? this->Internal->CompileOptionsEntries.begin()
- : this->Internal->CompileOptionsEntries.end();
+ ? impl->CompileOptionsEntries.begin()
+ : impl->CompileOptionsEntries.end();
std::vector<cmListFileBacktrace>::iterator btPosition = before
- ? this->Internal->CompileOptionsBacktraces.begin()
- : this->Internal->CompileOptionsBacktraces.end();
+ ? impl->CompileOptionsBacktraces.begin()
+ : impl->CompileOptionsBacktraces.end();
- this->Internal->CompileOptionsEntries.insert(position, entry);
- this->Internal->CompileOptionsBacktraces.insert(btPosition, bt);
+ impl->CompileOptionsEntries.insert(position, entry);
+ impl->CompileOptionsBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertCompileDefinition(std::string const& entry,
cmListFileBacktrace const& bt)
{
- this->Internal->CompileDefinitionsEntries.push_back(entry);
- this->Internal->CompileDefinitionsBacktraces.push_back(bt);
+ impl->CompileDefinitionsEntries.push_back(entry);
+ impl->CompileDefinitionsBacktraces.push_back(bt);
}
void cmTarget::InsertLinkOption(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
- std::vector<std::string>::iterator position = before
- ? this->Internal->LinkOptionsEntries.begin()
- : this->Internal->LinkOptionsEntries.end();
+ std::vector<std::string>::iterator position =
+ before ? impl->LinkOptionsEntries.begin() : impl->LinkOptionsEntries.end();
std::vector<cmListFileBacktrace>::iterator btPosition = before
- ? this->Internal->LinkOptionsBacktraces.begin()
- : this->Internal->LinkOptionsBacktraces.end();
+ ? impl->LinkOptionsBacktraces.begin()
+ : impl->LinkOptionsBacktraces.end();
- this->Internal->LinkOptionsEntries.insert(position, entry);
- this->Internal->LinkOptionsBacktraces.insert(btPosition, bt);
+ impl->LinkOptionsEntries.insert(position, entry);
+ impl->LinkOptionsBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertLinkDirectory(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
std::vector<std::string>::iterator position = before
- ? this->Internal->LinkDirectoriesEntries.begin()
- : this->Internal->LinkDirectoriesEntries.end();
+ ? impl->LinkDirectoriesEntries.begin()
+ : impl->LinkDirectoriesEntries.end();
std::vector<cmListFileBacktrace>::iterator btPosition = before
- ? this->Internal->LinkDirectoriesBacktraces.begin()
- : this->Internal->LinkDirectoriesBacktraces.end();
+ ? impl->LinkDirectoriesBacktraces.begin()
+ : impl->LinkDirectoriesBacktraces.end();
- this->Internal->LinkDirectoriesEntries.insert(position, entry);
- this->Internal->LinkDirectoriesBacktraces.insert(btPosition, bt);
+ impl->LinkDirectoriesEntries.insert(position, entry);
+ impl->LinkDirectoriesBacktraces.insert(btPosition, bt);
}
static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
@@ -1380,12 +1523,12 @@ const char* cmTarget::GetProperty(const std::string& prop) const
}
if (specialProps.count(prop)) {
if (prop == propLINK_LIBRARIES) {
- if (this->Internal->LinkImplementationPropertyEntries.empty()) {
+ if (impl->LinkImplementationPropertyEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->LinkImplementationPropertyEntries, ";");
+ output = cmJoin(impl->LinkImplementationPropertyEntries, ";");
return output.c_str();
}
// the type property returns what type the target is
@@ -1393,67 +1536,67 @@ const char* cmTarget::GetProperty(const std::string& prop) const
return cmState::GetTargetTypeName(this->GetType());
}
if (prop == propINCLUDE_DIRECTORIES) {
- if (this->Internal->IncludeDirectoriesEntries.empty()) {
+ if (impl->IncludeDirectoriesEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->IncludeDirectoriesEntries, ";");
+ output = cmJoin(impl->IncludeDirectoriesEntries, ";");
return output.c_str();
}
if (prop == propCOMPILE_FEATURES) {
- if (this->Internal->CompileFeaturesEntries.empty()) {
+ if (impl->CompileFeaturesEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->CompileFeaturesEntries, ";");
+ output = cmJoin(impl->CompileFeaturesEntries, ";");
return output.c_str();
}
if (prop == propCOMPILE_OPTIONS) {
- if (this->Internal->CompileOptionsEntries.empty()) {
+ if (impl->CompileOptionsEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->CompileOptionsEntries, ";");
+ output = cmJoin(impl->CompileOptionsEntries, ";");
return output.c_str();
}
if (prop == propCOMPILE_DEFINITIONS) {
- if (this->Internal->CompileDefinitionsEntries.empty()) {
+ if (impl->CompileDefinitionsEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->CompileDefinitionsEntries, ";");
+ output = cmJoin(impl->CompileDefinitionsEntries, ";");
return output.c_str();
}
if (prop == propLINK_OPTIONS) {
- if (this->Internal->LinkOptionsEntries.empty()) {
+ if (impl->LinkOptionsEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->LinkOptionsEntries, ";");
+ output = cmJoin(impl->LinkOptionsEntries, ";");
return output.c_str();
}
if (prop == propLINK_DIRECTORIES) {
- if (this->Internal->LinkDirectoriesEntries.empty()) {
+ if (impl->LinkDirectoriesEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->LinkDirectoriesEntries, ";");
+ output = cmJoin(impl->LinkDirectoriesEntries, ";");
return output.c_str();
}
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
- if (this->Utilities.empty()) {
+ if (impl->Utilities.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(this->Utilities, ";");
+ output = cmJoin(impl->Utilities, ";");
return output.c_str();
}
if (prop == propIMPORTED) {
@@ -1466,27 +1609,25 @@ const char* cmTarget::GetProperty(const std::string& prop) const
return this->GetName().c_str();
}
if (prop == propBINARY_DIR) {
- return this->GetMakefile()
- ->GetStateSnapshot()
+ return impl->Makefile->GetStateSnapshot()
.GetDirectory()
.GetCurrentBinary()
.c_str();
}
if (prop == propSOURCE_DIR) {
- return this->GetMakefile()
- ->GetStateSnapshot()
+ return impl->Makefile->GetStateSnapshot()
.GetDirectory()
.GetCurrentSource()
.c_str();
}
}
- const char* retVal = this->Properties.GetPropertyValue(prop);
+ const char* retVal = impl->Properties.GetPropertyValue(prop);
if (!retVal) {
- const bool chain = this->GetMakefile()->GetState()->IsPropertyChained(
- prop, cmProperty::TARGET);
+ const bool chain =
+ impl->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TARGET);
if (chain) {
- return this->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
+ return impl->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
prop, chain);
}
}
@@ -1507,6 +1648,21 @@ bool cmTarget::GetPropertyAsBool(const std::string& prop) const
return cmSystemTools::IsOn(this->GetProperty(prop));
}
+cmPropertyMap const& cmTarget::GetProperties() const
+{
+ return impl->Properties;
+}
+
+bool cmTarget::IsImported() const
+{
+ return impl->IsImportedTarget;
+}
+
+bool cmTarget::IsImportedGloballyVisible() const
+{
+ return impl->ImportedGloballyVisible;
+}
+
const char* cmTarget::GetSuffixVariableInternal(
cmStateEnums::ArtifactType artifact) const
{
@@ -1534,7 +1690,7 @@ const char* cmTarget::GetSuffixVariableInternal(
case cmStateEnums::RuntimeBinaryArtifact:
// Android GUI application packages store the native
// binary as a shared library.
- return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+ return (impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
? "CMAKE_SHARED_LIBRARY_SUFFIX"
: "CMAKE_EXECUTABLE_SUFFIX");
case cmStateEnums::ImportLibraryArtifact:
@@ -1574,7 +1730,7 @@ const char* cmTarget::GetPrefixVariableInternal(
case cmStateEnums::RuntimeBinaryArtifact:
// Android GUI application packages store the native
// binary as a shared library.
- return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+ return (impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
? "CMAKE_SHARED_LIBRARY_PREFIX"
: "");
case cmStateEnums::ImportLibraryArtifact:
@@ -1648,25 +1804,11 @@ std::string cmTarget::ImportedGetFullPath(
return result;
}
-void cmTarget::SetPropertyDefault(const std::string& property,
- const char* default_value)
-{
- // Compute the name of the variable holding the default value.
- std::string var = "CMAKE_";
- var += property;
-
- if (const char* value = this->Makefile->GetDefinition(var)) {
- this->SetProperty(property, value);
- } else if (default_value) {
- this->SetProperty(property, default_value);
- }
-}
-
-bool cmTarget::CheckImportedLibName(std::string const& prop,
- std::string const& value) const
+bool cmTargetInternals::CheckImportedLibName(std::string const& prop,
+ std::string const& value) const
{
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY ||
- !this->IsImported()) {
+ if (this->TargetType != cmStateEnums::INTERFACE_LIBRARY ||
+ !this->IsImportedTarget) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
prop +
@@ -1726,7 +1868,9 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
// If we needed to find one of the mapped configurations but did not
// On a DLL platform there may be only IMPORTED_IMPLIB for a shared
// library or an executable with exports.
- bool allowImp = this->HasImportLibrary();
+ bool allowImp = (impl->DLLPlatform &&
+ (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->IsExecutableWithExports()));
// If a mapping was found, check its configurations.
for (std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
@@ -1829,37 +1973,3 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
return true;
}
-
-cmTargetInternalPointer::cmTargetInternalPointer()
-{
- this->Pointer = new cmTargetInternals;
-}
-
-cmTargetInternalPointer::cmTargetInternalPointer(
- cmTargetInternalPointer const& r)
-{
- // Ideally cmTarget instances should never be copied. However until
- // we can make a sweep to remove that, this copy constructor avoids
- // allowing the resources (Internals) to be copied.
- this->Pointer = new cmTargetInternals(*r.Pointer);
-}
-
-cmTargetInternalPointer::~cmTargetInternalPointer()
-{
- delete this->Pointer;
-}
-
-cmTargetInternalPointer& cmTargetInternalPointer::operator=(
- cmTargetInternalPointer const& r)
-{
- if (this == &r) {
- return *this;
- } // avoid warning on HP about self check
- // Ideally cmTarget instances should never be copied. However until
- // we can make a sweep to remove that, this copy constructor avoids
- // allowing the resources (Internals) to be copied.
- cmTargetInternals* oldPointer = this->Pointer;
- this->Pointer = new cmTargetInternals(*r.Pointer);
- delete oldPointer;
- return *this;
-}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 24b3742..0ac5ca7 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <memory> // IWYU pragma: keep
#include <set>
#include <string>
#include <unordered_map>
@@ -13,38 +14,23 @@
#include <vector>
#include "cmAlgorithms.h"
-#include "cmCustomCommand.h"
#include "cmListFileCache.h"
#include "cmPolicies.h"
-#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmTargetLinkLibraryType.h"
+class cmCustomCommand;
class cmGlobalGenerator;
class cmMakefile;
class cmMessenger;
+class cmPropertyMap;
class cmSourceFile;
class cmTargetInternals;
-class cmTargetInternalPointer
-{
-public:
- cmTargetInternalPointer();
- cmTargetInternalPointer(cmTargetInternalPointer const& r);
- ~cmTargetInternalPointer();
- cmTargetInternalPointer& operator=(cmTargetInternalPointer const& r);
- cmTargetInternals* operator->() const { return this->Pointer; }
- cmTargetInternals* Get() const { return this->Pointer; }
-
-private:
- cmTargetInternals* Pointer;
-};
-
/** \class cmTarget
* \brief Represent a library or executable target loaded from a makefile.
*
- * cmTarget represents a target loaded from
- * a makefile.
+ * cmTarget represents a target loaded from a makefile.
*/
class cmTarget
{
@@ -56,9 +42,6 @@ public:
VisibilityImportedGlobally
};
- cmTarget(std::string const& name, cmStateEnums::TargetType type,
- Visibility vis, cmMakefile* mf);
-
enum CustomCommandType
{
PRE_BUILD,
@@ -66,77 +49,68 @@ public:
POST_BUILD
};
- /**
- * Return the type of target.
- */
- cmStateEnums::TargetType GetType() const { return this->TargetTypeValue; }
+ cmTarget(std::string const& name, cmStateEnums::TargetType type,
+ Visibility vis, cmMakefile* mf);
+
+ cmTarget(cmTarget const&) = delete;
+ cmTarget(cmTarget&&) noexcept;
+ ~cmTarget();
+
+ cmTarget& operator=(cmTarget const&) = delete;
+ cmTarget& operator=(cmTarget&&) noexcept;
+
+ //! Return the type of target.
+ cmStateEnums::TargetType GetType() const;
+
+ //! Get the cmMakefile that owns this target.
+ cmMakefile* GetMakefile() const;
+ //! Return the global generator.
cmGlobalGenerator* GetGlobalGenerator() const;
- ///! Set/Get the name of the target
- const std::string& GetName() const { return this->Name; }
+ //! Set/Get the name of the target
+ const std::string& GetName() const;
- /** Get the cmMakefile that owns this target. */
- cmMakefile* GetMakefile() const { return this->Makefile; }
+ //! Get the policy map
+ cmPolicies::PolicyMap const& GetPolicyMap() const;
+
+ //! Get policy status
+ cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID policy) const;
#define DECLARE_TARGET_POLICY(POLICY) \
cmPolicies::PolicyStatus GetPolicyStatus##POLICY() const \
{ \
- return this->PolicyMap.Get(cmPolicies::POLICY); \
+ return this->GetPolicyStatus(cmPolicies::POLICY); \
}
CM_FOR_EACH_TARGET_POLICY(DECLARE_TARGET_POLICY)
#undef DECLARE_TARGET_POLICY
- /**
- * Get the list of the custom commands for this target
- */
- std::vector<cmCustomCommand> const& GetPreBuildCommands() const
- {
- return this->PreBuildCommands;
- }
- std::vector<cmCustomCommand> const& GetPreLinkCommands() const
- {
- return this->PreLinkCommands;
- }
- std::vector<cmCustomCommand> const& GetPostBuildCommands() const
- {
- return this->PostBuildCommands;
- }
- void AddPreBuildCommand(cmCustomCommand const& cmd)
- {
- this->PreBuildCommands.push_back(cmd);
- }
- void AddPreLinkCommand(cmCustomCommand const& cmd)
- {
- this->PreLinkCommands.push_back(cmd);
- }
- void AddPostBuildCommand(cmCustomCommand const& cmd)
- {
- this->PostBuildCommands.push_back(cmd);
- }
+ //! Get the list of the PRE_BUILD custom commands for this target
+ std::vector<cmCustomCommand> const& GetPreBuildCommands() const;
+ void AddPreBuildCommand(cmCustomCommand const& cmd);
- /**
- * Add sources to the target.
- */
+ //! Get the list of the PRE_LINK custom commands for this target
+ std::vector<cmCustomCommand> const& GetPreLinkCommands() const;
+ void AddPreLinkCommand(cmCustomCommand const& cmd);
+
+ //! Get the list of the POST_BUILD custom commands for this target
+ std::vector<cmCustomCommand> const& GetPostBuildCommands() const;
+ void AddPostBuildCommand(cmCustomCommand const& cmd);
+
+ //! Add sources to the target.
void AddSources(std::vector<std::string> const& srcs);
void AddTracedSources(std::vector<std::string> const& srcs);
cmSourceFile* AddSourceCMP0049(const std::string& src);
cmSourceFile* AddSource(const std::string& src, bool before = false);
- //* how we identify a library, by name and type
+ //! how we identify a library, by name and type
typedef std::pair<std::string, cmTargetLinkLibraryType> LibraryID;
-
typedef std::vector<LibraryID> LinkLibraryVectorType;
- const LinkLibraryVectorType& GetOriginalLinkLibraries() const
- {
- return this->OriginalLinkLibraries;
- }
+ LinkLibraryVectorType const& GetOriginalLinkLibraries() const;
- /**
- * Clear the dependency information recorded for this target, if any.
- */
+ //! Clear the dependency information recorded for this target, if any.
void ClearDependencyInformation(cmMakefile& mf);
void AddLinkLibrary(cmMakefile& mf, const std::string& lib,
@@ -157,83 +131,69 @@ public:
* Set the path where this target should be installed. This is relative to
* INSTALL_PREFIX
*/
- std::string GetInstallPath() const { return this->InstallPath; }
- void SetInstallPath(const char* name) { this->InstallPath = name; }
+ std::string const& GetInstallPath() const;
+ void SetInstallPath(std::string const& name);
/**
* Set the path where this target (if it has a runtime part) should be
* installed. This is relative to INSTALL_PREFIX
*/
- std::string GetRuntimeInstallPath() const
- {
- return this->RuntimeInstallPath;
- }
- void SetRuntimeInstallPath(const char* name)
- {
- this->RuntimeInstallPath = name;
- }
+ std::string const& GetRuntimeInstallPath() const;
+ void SetRuntimeInstallPath(std::string const& name);
/**
* Get/Set whether there is an install rule for this target.
*/
- bool GetHaveInstallRule() const { return this->HaveInstallRule; }
- void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; }
+ bool GetHaveInstallRule() const;
+ void SetHaveInstallRule(bool hir);
/**
* Get/Set whether this target was auto-created by a generator.
*/
- bool GetIsGeneratorProvided() const { return this->IsGeneratorProvided; }
- void SetIsGeneratorProvided(bool igp) { this->IsGeneratorProvided = igp; }
+ bool GetIsGeneratorProvided() const;
+ void SetIsGeneratorProvided(bool igp);
- /** Add a utility on which this project depends. A utility is an executable
+ /**
+ * Add a utility on which this project depends. A utility is an executable
* 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(std::string const& u, cmMakefile* mf = nullptr);
- ///! Get the utilities used by this target
- std::set<BT<std::string>> const& GetUtilities() const
- {
- return this->Utilities;
- }
+ void AddUtility(std::string const& name, cmMakefile* mf = nullptr);
+ //! Get the utilities used by this target
+ std::set<BT<std::string>> const& GetUtilities() const;
- ///! Set/Get a property of this target file
+ //! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
- ///! Might return a nullptr if the property is not set or invalid
+ //! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
- ///! Always returns a valid pointer
+ //! Always returns a valid pointer
const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
void CheckProperty(const std::string& prop, cmMakefile* context) const;
const char* GetComputedProperty(const std::string& prop,
cmMessenger* messenger,
cmListFileBacktrace const& context) const;
+ //! Get all properties
+ cmPropertyMap const& GetProperties() const;
- bool IsImported() const { return this->IsImportedTarget; }
- bool IsImportedGloballyVisible() const
- {
- return this->ImportedGloballyVisible;
- }
-
- // Get the properties
- cmPropertyMap const& GetProperties() const { return this->Properties; }
+ bool IsImported() const;
+ bool IsImportedGloballyVisible() const;
bool GetMappedConfig(std::string const& desired_config, const char** loc,
const char** imp, std::string& suffix) const;
- /** Return whether this target is an executable with symbol exports
- enabled. */
+ //! Return whether this target is an executable with symbol exports enabled.
bool IsExecutableWithExports() const;
- /** Return whether this target is a shared library Framework on
- Apple. */
+ //! Return whether this target is a shared library Framework on Apple.
bool IsFrameworkOnApple() const;
- /** Return whether this target is an executable Bundle on Apple. */
+ //! Return whether this target is an executable Bundle on Apple.
bool IsAppBundleOnApple() const;
- /** Get a backtrace from the creation of the target. */
+ //! Get a backtrace from the creation of the target.
cmListFileBacktrace const& GetBacktrace() const;
void InsertInclude(std::string const& entry, cmListFileBacktrace const& bt,
@@ -252,11 +212,8 @@ public:
std::string GetDebugGeneratorExpressions(const std::string& value,
cmTargetLinkLibraryType llt) const;
- void AddSystemIncludeDirectories(const std::set<std::string>& incs);
- std::set<std::string> const& GetSystemIncludeDirectories() const
- {
- return this->SystemIncludeDirectories;
- }
+ void AddSystemIncludeDirectories(std::set<std::string> const& incs);
+ std::set<std::string> const& GetSystemIncludeDirectories() const;
cmStringRange GetIncludeDirectoriesEntries() const;
cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
@@ -282,63 +239,25 @@ public:
cmStringRange GetLinkImplementationEntries() const;
cmBacktraceRange GetLinkImplementationBacktraces() const;
+ std::string ImportedGetFullPath(const std::string& config,
+ cmStateEnums::ArtifactType artifact) const;
+
struct StrictTargetComparison
{
bool operator()(cmTarget const* t1, cmTarget const* t2) const;
};
- std::string ImportedGetFullPath(const std::string& config,
- cmStateEnums::ArtifactType artifact) const;
-
private:
+ // Internal representation details.
+ friend class cmGeneratorTarget;
+
const char* GetSuffixVariableInternal(
cmStateEnums::ArtifactType artifact) const;
const char* GetPrefixVariableInternal(
cmStateEnums::ArtifactType artifact) const;
- // Use a makefile variable to set a default for the given property.
- // If the variable is not defined use the given default instead.
- void SetPropertyDefault(const std::string& property,
- const char* default_value);
-
- bool CheckImportedLibName(std::string const& prop,
- std::string const& value) const;
-
private:
- bool IsGeneratorProvided;
- cmPropertyMap Properties;
- std::set<std::string> SystemIncludeDirectories;
- std::set<BT<std::string>> Utilities;
- cmPolicies::PolicyMap PolicyMap;
- std::string Name;
- std::string InstallPath;
- std::string RuntimeInstallPath;
- std::vector<cmCustomCommand> PreBuildCommands;
- std::vector<cmCustomCommand> PreLinkCommands;
- std::vector<cmCustomCommand> PostBuildCommands;
- std::vector<std::pair<TLLSignature, cmListFileContext>> TLLCommands;
- LinkLibraryVectorType OriginalLinkLibraries;
- cmMakefile* Makefile;
- cmTargetInternalPointer Internal;
- cmStateEnums::TargetType TargetTypeValue;
- bool HaveInstallRule;
- bool DLLPlatform;
- bool IsAndroid;
- bool IsImportedTarget;
- bool ImportedGloballyVisible;
- bool BuildInterfaceIncludesAppended;
-
- std::string ProcessSourceItemCMP0049(const std::string& s);
-
- /** Return whether or not the target has a DLL import library. */
- bool HasImportLibrary() const;
-
- // Internal representation details.
- friend class cmTargetInternals;
- friend class cmGeneratorTarget;
- friend class cmTargetTraceDependencies;
-
- cmListFileBacktrace Backtrace;
+ std::unique_ptr<cmTargetInternals> impl;
};
typedef std::unordered_map<std::string, cmTarget> cmTargets;
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
index d2c3496..994fcf7 100644
--- a/Source/cmTargetPropertyComputer.cxx
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -67,6 +67,8 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
builtIns.insert("IMPORTED_GLOBAL");
builtIns.insert("MANUALLY_ADDED_DEPENDENCIES");
builtIns.insert("NAME");
+ builtIns.insert("PRIVATE_HEADER");
+ builtIns.insert("PUBLIC_HEADER");
builtIns.insert("TYPE");
}
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index 97e4fba..efbf95f 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -81,7 +81,7 @@ private:
context)) {
return nullptr;
}
- const char* configName = prop.c_str() + 9;
+ std::string configName = prop.substr(9);
return ComputeLocation(tgt, configName);
}
diff --git a/Source/cmTest.h b/Source/cmTest.h
index d4839d1..88dc730 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -26,14 +26,14 @@ public:
cmTest(cmMakefile* mf);
~cmTest();
- ///! Set the test name
+ //! Set the test name
void SetName(const std::string& name);
std::string GetName() const { return this->Name; }
void SetCommand(std::vector<std::string> const& command);
std::vector<std::string> const& GetCommand() const { return this->Command; }
- ///! Set/Get a property of this source file
+ //! Set/Get a property of this source file
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx
index e4a1b5f..88e415a 100644
--- a/Source/cmUseMangledMesaCommand.cxx
+++ b/Source/cmUseMangledMesaCommand.cxx
@@ -78,7 +78,7 @@ void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(const char* source,
cmsys::RegularExpression includeLine(
"^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]");
// regular expression for gl/ or GL/ in a file (match(1) of above)
- cmsys::RegularExpression glDirLine("(gl|GL)(/|\\\\)([^<\"]+)");
+ cmsys::RegularExpression glDirLine(R"((gl|GL)(/|\\)([^<"]+))");
// regular expression for gl GL or xmesa in a file (match(1) of above)
cmsys::RegularExpression glLine("(gl|GL|xmesa)");
while (cmSystemTools::GetLineFromStream(fin, inLine)) {
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 6ec47c2..c60706d 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -4,6 +4,7 @@
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
@@ -1448,10 +1449,10 @@ std::string cmVisualStudio10TargetGenerator::ConvertPath(
static void ConvertToWindowsSlash(std::string& s)
{
// first convert all of the slashes
- std::string::size_type pos = 0;
- while ((pos = s.find('/', pos)) != std::string::npos) {
- s[pos] = '\\';
- pos++;
+ for (auto& ch : s) {
+ if (ch == '/') {
+ ch = '\\';
+ }
}
}
@@ -1467,7 +1468,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
this->GeneratorTarget->GetAllConfigSources();
- std::set<cmSourceGroup*> groupsUsed;
+ std::set<cmSourceGroup const*> groupsUsed;
for (cmGeneratorTarget::AllConfigSource const& si : sources) {
std::string const& source = si.Source->GetFullPath();
cmSourceGroup* sourceGroup =
@@ -1552,13 +1553,13 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
{
Elem e1(e0, "ItemGroup");
e1.SetHasElements();
- std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(),
- groupsUsed.end());
+ std::vector<cmSourceGroup const*> groupsVec(groupsUsed.begin(),
+ groupsUsed.end());
std::sort(groupsVec.begin(), groupsVec.end(),
- [](cmSourceGroup* l, cmSourceGroup* r) {
+ [](cmSourceGroup const* l, cmSourceGroup const* r) {
return l->GetFullName() < r->GetFullName();
});
- for (cmSourceGroup* sg : groupsVec) {
+ for (cmSourceGroup const* sg : groupsVec) {
std::string const& name = sg->GetFullName();
if (!name.empty()) {
std::string guidName = "SG_Filter_" + name;
@@ -1590,7 +1591,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
// Add to groupsUsed empty source groups that have non-empty children.
void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
- std::set<cmSourceGroup*>& groupsUsed,
+ std::set<cmSourceGroup const*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups)
{
for (cmSourceGroup const& current : allGroups) {
@@ -1601,17 +1602,15 @@ void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
this->AddMissingSourceGroups(groupsUsed, children);
- cmSourceGroup* current_ptr = const_cast<cmSourceGroup*>(&current);
- if (groupsUsed.find(current_ptr) != groupsUsed.end()) {
+ if (groupsUsed.count(&current) > 0) {
continue; // group has already been added to set
}
// check if it least one of the group's descendants is not empty
// (at least one child must already have been added)
- std::vector<cmSourceGroup>::const_iterator child_it = children.begin();
+ auto child_it = children.begin();
while (child_it != children.end()) {
- cmSourceGroup* child_ptr = const_cast<cmSourceGroup*>(&(*child_it));
- if (groupsUsed.find(child_ptr) != groupsUsed.end()) {
+ if (groupsUsed.count(&(*child_it)) > 0) {
break; // found a child that was already added => add current group too
}
child_it++;
@@ -1621,7 +1620,7 @@ void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
continue; // no descendants have source files => ignore this group
}
- groupsUsed.insert(current_ptr);
+ groupsUsed.insert(&current);
}
}
@@ -2548,24 +2547,17 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
} else {
std::set<std::string> languages;
this->GeneratorTarget->GetLanguages(languages, configName);
- for (const char* const* l = cm::cbegin(clLangs); l != cm::cend(clLangs);
- ++l) {
- if (languages.find(*l) != languages.end()) {
- langForClCompile = *l;
+ for (const char* l : clLangs) {
+ if (languages.count(l)) {
+ langForClCompile = l;
break;
}
}
}
this->LangForClCompile = langForClCompile;
if (!langForClCompile.empty()) {
- std::string baseFlagVar = "CMAKE_";
- baseFlagVar += langForClCompile;
- baseFlagVar += "_FLAGS";
- flags = this->Makefile->GetRequiredDefinition(baseFlagVar);
- std::string flagVar =
- baseFlagVar + "_" + cmSystemTools::UpperCase(configName);
- flags += " ";
- flags += this->Makefile->GetRequiredDefinition(flagVar);
+ this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
+ langForClCompile, configName);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
langForClCompile, configName);
}
@@ -4082,10 +4074,7 @@ bool cmVisualStudio10TargetGenerator::IsResxHeader(
{
std::set<std::string> expectedResxHeaders;
this->GeneratorTarget->GetExpectedResxHeaders(expectedResxHeaders, "");
-
- std::set<std::string>::const_iterator it =
- expectedResxHeaders.find(headerFile);
- return it != expectedResxHeaders.end();
+ return expectedResxHeaders.count(headerFile) > 0;
}
bool cmVisualStudio10TargetGenerator::IsXamlHeader(
@@ -4093,10 +4082,7 @@ bool cmVisualStudio10TargetGenerator::IsXamlHeader(
{
std::set<std::string> expectedXamlHeaders;
this->GeneratorTarget->GetExpectedXamlHeaders(expectedXamlHeaders, "");
-
- std::set<std::string>::const_iterator it =
- expectedXamlHeaders.find(headerFile);
- return it != expectedXamlHeaders.end();
+ return expectedXamlHeaders.count(headerFile) > 0;
}
bool cmVisualStudio10TargetGenerator::IsXamlSource(
@@ -4104,10 +4090,7 @@ bool cmVisualStudio10TargetGenerator::IsXamlSource(
{
std::set<std::string> expectedXamlSources;
this->GeneratorTarget->GetExpectedXamlSources(expectedXamlSources, "");
-
- std::set<std::string>::const_iterator it =
- expectedXamlSources.find(sourceFile);
- return it != expectedXamlSources.end();
+ return expectedXamlSources.count(sourceFile) > 0;
}
void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
@@ -4678,10 +4661,8 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties(
Elem& e2, const std::map<std::string, std::string>& tags)
{
- if (!tags.empty()) {
- for (const auto& i : tags) {
- e2.Element(i.first.c_str(), i.second);
- }
+ for (const auto& i : tags) {
+ e2.Element(i.first.c_str(), i.second);
}
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index b5b7a4a..1dea8e9 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -166,7 +166,7 @@ private:
void WriteGroupSources(Elem& e0, std::string const& name,
ToolSources const& sources,
std::vector<cmSourceGroup>&);
- void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
+ void AddMissingSourceGroups(std::set<cmSourceGroup const*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
bool IsResxHeader(const std::string& headerFile);
bool IsXamlHeader(const std::string& headerFile);
diff --git a/Source/cmWorkerPool.cxx b/Source/cmWorkerPool.cxx
new file mode 100644
index 0000000..464182c
--- /dev/null
+++ b/Source/cmWorkerPool.cxx
@@ -0,0 +1,770 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWorkerPool.h"
+
+#include "cmRange.h"
+#include "cmUVHandlePtr.h"
+#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
+#include "cm_uv.h"
+
+#include <algorithm>
+#include <array>
+#include <condition_variable>
+#include <deque>
+#include <functional>
+#include <mutex>
+#include <stddef.h>
+#include <thread>
+
+/**
+ * @brief libuv pipe buffer class
+ */
+class cmUVPipeBuffer
+{
+public:
+ typedef cmRange<char const*> DataRange;
+ typedef std::function<void(DataRange)> DataFunction;
+ /// On error the ssize_t argument is a non zero libuv error code
+ typedef std::function<void(ssize_t)> EndFunction;
+
+public:
+ /**
+ * Reset to construction state
+ */
+ void reset();
+
+ /**
+ * Initializes uv_pipe(), uv_stream() and uv_handle()
+ * @return true on success
+ */
+ bool init(uv_loop_t* uv_loop);
+
+ /**
+ * Start reading
+ * @return true on success
+ */
+ bool startRead(DataFunction dataFunction, EndFunction endFunction);
+
+ //! libuv pipe
+ uv_pipe_t* uv_pipe() const { return UVPipe_.get(); }
+ //! uv_pipe() casted to libuv stream
+ uv_stream_t* uv_stream() const { return static_cast<uv_stream_t*>(UVPipe_); }
+ //! uv_pipe() casted to libuv handle
+ uv_handle_t* uv_handle() { return static_cast<uv_handle_t*>(UVPipe_); }
+
+private:
+ // -- Libuv callbacks
+ static void UVAlloc(uv_handle_t* handle, size_t suggestedSize,
+ uv_buf_t* buf);
+ static void UVData(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
+
+private:
+ cm::uv_pipe_ptr UVPipe_;
+ std::vector<char> Buffer_;
+ DataFunction DataFunction_;
+ EndFunction EndFunction_;
+};
+
+void cmUVPipeBuffer::reset()
+{
+ if (UVPipe_.get() != nullptr) {
+ EndFunction_ = nullptr;
+ DataFunction_ = nullptr;
+ Buffer_.clear();
+ Buffer_.shrink_to_fit();
+ UVPipe_.reset();
+ }
+}
+
+bool cmUVPipeBuffer::init(uv_loop_t* uv_loop)
+{
+ reset();
+ if (uv_loop == nullptr) {
+ return false;
+ }
+ int ret = UVPipe_.init(*uv_loop, 0, this);
+ return (ret == 0);
+}
+
+bool cmUVPipeBuffer::startRead(DataFunction dataFunction,
+ EndFunction endFunction)
+{
+ if (UVPipe_.get() == nullptr) {
+ return false;
+ }
+ if (!dataFunction || !endFunction) {
+ return false;
+ }
+ DataFunction_ = std::move(dataFunction);
+ EndFunction_ = std::move(endFunction);
+ int ret = uv_read_start(uv_stream(), &cmUVPipeBuffer::UVAlloc,
+ &cmUVPipeBuffer::UVData);
+ return (ret == 0);
+}
+
+void cmUVPipeBuffer::UVAlloc(uv_handle_t* handle, size_t suggestedSize,
+ uv_buf_t* buf)
+{
+ auto& pipe = *reinterpret_cast<cmUVPipeBuffer*>(handle->data);
+ pipe.Buffer_.resize(suggestedSize);
+ buf->base = pipe.Buffer_.data();
+ buf->len = static_cast<unsigned long>(pipe.Buffer_.size());
+}
+
+void cmUVPipeBuffer::UVData(uv_stream_t* stream, ssize_t nread,
+ const uv_buf_t* buf)
+{
+ auto& pipe = *reinterpret_cast<cmUVPipeBuffer*>(stream->data);
+ if (nread > 0) {
+ if (buf->base != nullptr) {
+ // Call data function
+ pipe.DataFunction_(DataRange(buf->base, buf->base + nread));
+ }
+ } else if (nread < 0) {
+ // Save the end function on the stack before resetting the pipe
+ EndFunction efunc;
+ efunc.swap(pipe.EndFunction_);
+ // Reset pipe before calling the end function
+ pipe.reset();
+ // Call end function
+ efunc((nread == UV_EOF) ? 0 : nread);
+ }
+}
+
+/**
+ * @brief External process management class
+ */
+class cmUVReadOnlyProcess
+{
+public:
+ // -- Types
+ //! @brief Process settings
+ struct SetupT
+ {
+ std::string WorkingDirectory;
+ std::vector<std::string> Command;
+ cmWorkerPool::ProcessResultT* Result = nullptr;
+ bool MergedOutput = false;
+ };
+
+public:
+ // -- Const accessors
+ SetupT const& Setup() const { return Setup_; }
+ cmWorkerPool::ProcessResultT* Result() const { return Setup_.Result; }
+ bool IsStarted() const { return IsStarted_; }
+ bool IsFinished() const { return IsFinished_; }
+
+ // -- Runtime
+ void setup(cmWorkerPool::ProcessResultT* result, bool mergedOutput,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory = std::string());
+ bool start(uv_loop_t* uv_loop, std::function<void()> finishedCallback);
+
+private:
+ // -- Libuv callbacks
+ static void UVExit(uv_process_t* handle, int64_t exitStatus, int termSignal);
+ void UVPipeOutData(cmUVPipeBuffer::DataRange data);
+ void UVPipeOutEnd(ssize_t error);
+ void UVPipeErrData(cmUVPipeBuffer::DataRange data);
+ void UVPipeErrEnd(ssize_t error);
+ void UVTryFinish();
+
+private:
+ // -- Setup
+ SetupT Setup_;
+ // -- Runtime
+ bool IsStarted_ = false;
+ bool IsFinished_ = false;
+ std::function<void()> FinishedCallback_;
+ std::vector<const char*> CommandPtr_;
+ std::array<uv_stdio_container_t, 3> UVOptionsStdIO_;
+ uv_process_options_t UVOptions_;
+ cm::uv_process_ptr UVProcess_;
+ cmUVPipeBuffer UVPipeOut_;
+ cmUVPipeBuffer UVPipeErr_;
+};
+
+void cmUVReadOnlyProcess::setup(cmWorkerPool::ProcessResultT* result,
+ bool mergedOutput,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory)
+{
+ Setup_.WorkingDirectory = workingDirectory;
+ Setup_.Command = command;
+ Setup_.Result = result;
+ Setup_.MergedOutput = mergedOutput;
+}
+
+bool cmUVReadOnlyProcess::start(uv_loop_t* uv_loop,
+ std::function<void()> finishedCallback)
+{
+ if (IsStarted() || (Result() == nullptr)) {
+ return false;
+ }
+
+ // Reset result before the start
+ Result()->reset();
+
+ // Fill command string pointers
+ if (!Setup().Command.empty()) {
+ CommandPtr_.reserve(Setup().Command.size() + 1);
+ for (std::string const& arg : Setup().Command) {
+ CommandPtr_.push_back(arg.c_str());
+ }
+ CommandPtr_.push_back(nullptr);
+ } else {
+ Result()->ErrorMessage = "Empty command";
+ }
+
+ if (!Result()->error()) {
+ if (!UVPipeOut_.init(uv_loop)) {
+ Result()->ErrorMessage = "libuv stdout pipe initialization failed";
+ }
+ }
+ if (!Result()->error()) {
+ if (!UVPipeErr_.init(uv_loop)) {
+ Result()->ErrorMessage = "libuv stderr pipe initialization failed";
+ }
+ }
+ if (!Result()->error()) {
+ // -- Setup process stdio options
+ // stdin
+ UVOptionsStdIO_[0].flags = UV_IGNORE;
+ UVOptionsStdIO_[0].data.stream = nullptr;
+ // stdout
+ UVOptionsStdIO_[1].flags =
+ static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
+ UVOptionsStdIO_[1].data.stream = UVPipeOut_.uv_stream();
+ // stderr
+ UVOptionsStdIO_[2].flags =
+ static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
+ UVOptionsStdIO_[2].data.stream = UVPipeErr_.uv_stream();
+
+ // -- Setup process options
+ std::fill_n(reinterpret_cast<char*>(&UVOptions_), sizeof(UVOptions_), 0);
+ UVOptions_.exit_cb = &cmUVReadOnlyProcess::UVExit;
+ UVOptions_.file = CommandPtr_[0];
+ UVOptions_.args = const_cast<char**>(CommandPtr_.data());
+ UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
+ UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
+ UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
+ UVOptions_.stdio = UVOptionsStdIO_.data();
+
+ // -- Spawn process
+ int uvErrorCode = UVProcess_.spawn(*uv_loop, UVOptions_, this);
+ if (uvErrorCode != 0) {
+ Result()->ErrorMessage = "libuv process spawn failed";
+ if (const char* uvErr = uv_strerror(uvErrorCode)) {
+ Result()->ErrorMessage += ": ";
+ Result()->ErrorMessage += uvErr;
+ }
+ }
+ }
+ // -- Start reading from stdio streams
+ if (!Result()->error()) {
+ if (!UVPipeOut_.startRead(
+ [this](cmUVPipeBuffer::DataRange range) {
+ this->UVPipeOutData(range);
+ },
+ [this](ssize_t error) { this->UVPipeOutEnd(error); })) {
+ Result()->ErrorMessage = "libuv start reading from stdout pipe failed";
+ }
+ }
+ if (!Result()->error()) {
+ if (!UVPipeErr_.startRead(
+ [this](cmUVPipeBuffer::DataRange range) {
+ this->UVPipeErrData(range);
+ },
+ [this](ssize_t error) { this->UVPipeErrEnd(error); })) {
+ Result()->ErrorMessage = "libuv start reading from stderr pipe failed";
+ }
+ }
+
+ if (!Result()->error()) {
+ IsStarted_ = true;
+ FinishedCallback_ = std::move(finishedCallback);
+ } else {
+ // Clear libuv handles and finish
+ UVProcess_.reset();
+ UVPipeOut_.reset();
+ UVPipeErr_.reset();
+ CommandPtr_.clear();
+ }
+
+ return IsStarted();
+}
+
+void cmUVReadOnlyProcess::UVExit(uv_process_t* handle, int64_t exitStatus,
+ int termSignal)
+{
+ auto& proc = *reinterpret_cast<cmUVReadOnlyProcess*>(handle->data);
+ if (proc.IsStarted() && !proc.IsFinished()) {
+ // Set error message on demand
+ proc.Result()->ExitStatus = exitStatus;
+ proc.Result()->TermSignal = termSignal;
+ if (!proc.Result()->error()) {
+ if (termSignal != 0) {
+ proc.Result()->ErrorMessage = "Process was terminated by signal ";
+ proc.Result()->ErrorMessage +=
+ std::to_string(proc.Result()->TermSignal);
+ } else if (exitStatus != 0) {
+ proc.Result()->ErrorMessage = "Process failed with return value ";
+ proc.Result()->ErrorMessage +=
+ std::to_string(proc.Result()->ExitStatus);
+ }
+ }
+
+ // Reset process handle
+ proc.UVProcess_.reset();
+ // Try finish
+ proc.UVTryFinish();
+ }
+}
+
+void cmUVReadOnlyProcess::UVPipeOutData(cmUVPipeBuffer::DataRange data)
+{
+ Result()->StdOut.append(data.begin(), data.end());
+}
+
+void cmUVReadOnlyProcess::UVPipeOutEnd(ssize_t error)
+{
+ // Process pipe error
+ if ((error != 0) && !Result()->error()) {
+ Result()->ErrorMessage =
+ "Reading from stdout pipe failed with libuv error code ";
+ Result()->ErrorMessage += std::to_string(error);
+ }
+ // Try finish
+ UVTryFinish();
+}
+
+void cmUVReadOnlyProcess::UVPipeErrData(cmUVPipeBuffer::DataRange data)
+{
+ std::string* str =
+ Setup_.MergedOutput ? &Result()->StdOut : &Result()->StdErr;
+ str->append(data.begin(), data.end());
+}
+
+void cmUVReadOnlyProcess::UVPipeErrEnd(ssize_t error)
+{
+ // Process pipe error
+ if ((error != 0) && !Result()->error()) {
+ Result()->ErrorMessage =
+ "Reading from stderr pipe failed with libuv error code ";
+ Result()->ErrorMessage += std::to_string(error);
+ }
+ // Try finish
+ UVTryFinish();
+}
+
+void cmUVReadOnlyProcess::UVTryFinish()
+{
+ // There still might be data in the pipes after the process has finished.
+ // Therefore check if the process is finished AND all pipes are closed
+ // before signaling the worker thread to continue.
+ if ((UVProcess_.get() != nullptr) || (UVPipeOut_.uv_pipe() != nullptr) ||
+ (UVPipeErr_.uv_pipe() != nullptr)) {
+ return;
+ }
+ IsFinished_ = true;
+ FinishedCallback_();
+}
+
+/**
+ * @brief Private worker pool internals
+ */
+class cmWorkerPoolInternal
+{
+public:
+ // -- Types
+
+ /**
+ * @brief Worker thread
+ */
+ class WorkerT
+ {
+ public:
+ WorkerT(unsigned int index);
+ ~WorkerT();
+
+ WorkerT(WorkerT const&) = delete;
+ WorkerT& operator=(WorkerT const&) = delete;
+
+ /**
+ * Start the thread
+ */
+ void Start(cmWorkerPoolInternal* internal);
+
+ /**
+ * @brief Run an external process
+ */
+ bool RunProcess(cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory);
+
+ // -- Accessors
+ unsigned int Index() const { return Index_; }
+ cmWorkerPool::JobHandleT& JobHandle() { return JobHandle_; }
+
+ private:
+ // -- Libuv callbacks
+ static void UVProcessStart(uv_async_t* handle);
+ void UVProcessFinished();
+
+ private:
+ //! @brief Job handle
+ cmWorkerPool::JobHandleT JobHandle_;
+ //! @brief Worker index
+ unsigned int Index_;
+ // -- Process management
+ struct
+ {
+ std::mutex Mutex;
+ cm::uv_async_ptr Request;
+ std::condition_variable Condition;
+ std::unique_ptr<cmUVReadOnlyProcess> ROP;
+ } Proc_;
+ // -- System thread
+ std::thread Thread_;
+ };
+
+public:
+ // -- Constructors
+ cmWorkerPoolInternal(cmWorkerPool* pool);
+ ~cmWorkerPoolInternal();
+
+ /**
+ * @brief Runs the libuv loop
+ */
+ bool Process();
+
+ /**
+ * @brief Clear queue and abort threads
+ */
+ void Abort();
+
+ /**
+ * @brief Push a job to the queue and notify a worker
+ */
+ bool PushJob(cmWorkerPool::JobHandleT&& jobHandle);
+
+ /**
+ * @brief Worker thread main loop method
+ */
+ void Work(WorkerT* worker);
+
+ // -- Request slots
+ static void UVSlotBegin(uv_async_t* handle);
+ static void UVSlotEnd(uv_async_t* handle);
+
+public:
+ // -- UV loop
+#ifdef CMAKE_UV_SIGNAL_HACK
+ std::unique_ptr<cmUVSignalHackRAII> UVHackRAII;
+#endif
+ std::unique_ptr<uv_loop_t> UVLoop;
+ cm::uv_async_ptr UVRequestBegin;
+ cm::uv_async_ptr UVRequestEnd;
+
+ // -- Thread pool and job queue
+ std::mutex Mutex;
+ bool Aborting = false;
+ bool FenceProcessing = false;
+ unsigned int WorkersRunning = 0;
+ unsigned int WorkersIdle = 0;
+ unsigned int JobsProcessing = 0;
+ std::deque<cmWorkerPool::JobHandleT> Queue;
+ std::condition_variable Condition;
+ std::vector<std::unique_ptr<WorkerT>> Workers;
+
+ // -- References
+ cmWorkerPool* Pool = nullptr;
+};
+
+cmWorkerPoolInternal::WorkerT::WorkerT(unsigned int index)
+ : Index_(index)
+{
+}
+
+cmWorkerPoolInternal::WorkerT::~WorkerT()
+{
+ if (Thread_.joinable()) {
+ Thread_.join();
+ }
+}
+
+void cmWorkerPoolInternal::WorkerT::Start(cmWorkerPoolInternal* internal)
+{
+ Proc_.Request.init(*(internal->UVLoop), &WorkerT::UVProcessStart, this);
+ Thread_ = std::thread(&cmWorkerPoolInternal::Work, internal, this);
+}
+
+bool cmWorkerPoolInternal::WorkerT::RunProcess(
+ cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command, std::string const& workingDirectory)
+{
+ if (command.empty()) {
+ return false;
+ }
+ // Create process instance
+ {
+ std::lock_guard<std::mutex> lock(Proc_.Mutex);
+ Proc_.ROP = cm::make_unique<cmUVReadOnlyProcess>();
+ Proc_.ROP->setup(&result, true, command, workingDirectory);
+ }
+ // Send asynchronous process start request to libuv loop
+ Proc_.Request.send();
+ // Wait until the process has been finished and destroyed
+ {
+ std::unique_lock<std::mutex> ulock(Proc_.Mutex);
+ while (Proc_.ROP) {
+ Proc_.Condition.wait(ulock);
+ }
+ }
+ return !result.error();
+}
+
+void cmWorkerPoolInternal::WorkerT::UVProcessStart(uv_async_t* handle)
+{
+ auto* wrk = reinterpret_cast<WorkerT*>(handle->data);
+ bool startFailed = false;
+ {
+ auto& Proc = wrk->Proc_;
+ std::lock_guard<std::mutex> lock(Proc.Mutex);
+ if (Proc.ROP && !Proc.ROP->IsStarted()) {
+ startFailed =
+ !Proc.ROP->start(handle->loop, [wrk] { wrk->UVProcessFinished(); });
+ }
+ }
+ // Clean up if starting of the process failed
+ if (startFailed) {
+ wrk->UVProcessFinished();
+ }
+}
+
+void cmWorkerPoolInternal::WorkerT::UVProcessFinished()
+{
+ {
+ std::lock_guard<std::mutex> lock(Proc_.Mutex);
+ if (Proc_.ROP && (Proc_.ROP->IsFinished() || !Proc_.ROP->IsStarted())) {
+ Proc_.ROP.reset();
+ }
+ }
+ // Notify idling thread
+ Proc_.Condition.notify_one();
+}
+
+void cmWorkerPool::ProcessResultT::reset()
+{
+ ExitStatus = 0;
+ TermSignal = 0;
+ if (!StdOut.empty()) {
+ StdOut.clear();
+ StdOut.shrink_to_fit();
+ }
+ if (!StdErr.empty()) {
+ StdErr.clear();
+ StdErr.shrink_to_fit();
+ }
+ if (!ErrorMessage.empty()) {
+ ErrorMessage.clear();
+ ErrorMessage.shrink_to_fit();
+ }
+}
+
+cmWorkerPoolInternal::cmWorkerPoolInternal(cmWorkerPool* pool)
+ : Pool(pool)
+{
+ // Initialize libuv loop
+ uv_disable_stdio_inheritance();
+#ifdef CMAKE_UV_SIGNAL_HACK
+ UVHackRAII = cm::make_unique<cmUVSignalHackRAII>();
+#endif
+ UVLoop = cm::make_unique<uv_loop_t>();
+ uv_loop_init(UVLoop.get());
+}
+
+cmWorkerPoolInternal::~cmWorkerPoolInternal()
+{
+ uv_loop_close(UVLoop.get());
+}
+
+bool cmWorkerPoolInternal::Process()
+{
+ // Reset state
+ Aborting = false;
+ // Initialize libuv asynchronous request
+ UVRequestBegin.init(*UVLoop, &cmWorkerPoolInternal::UVSlotBegin, this);
+ UVRequestEnd.init(*UVLoop, &cmWorkerPoolInternal::UVSlotEnd, this);
+ // Send begin request
+ UVRequestBegin.send();
+ // Run libuv loop
+ return (uv_run(UVLoop.get(), UV_RUN_DEFAULT) == 0);
+}
+
+void cmWorkerPoolInternal::Abort()
+{
+ bool firstCall = false;
+ // Clear all jobs and set abort flag
+ {
+ std::lock_guard<std::mutex> guard(Mutex);
+ if (!Aborting) {
+ // Register abort and clear queue
+ Aborting = true;
+ Queue.clear();
+ firstCall = true;
+ }
+ }
+ if (firstCall) {
+ // Wake threads
+ Condition.notify_all();
+ }
+}
+
+inline bool cmWorkerPoolInternal::PushJob(cmWorkerPool::JobHandleT&& jobHandle)
+{
+ std::lock_guard<std::mutex> guard(Mutex);
+ if (Aborting) {
+ return false;
+ }
+
+ // Append the job to the queue
+ Queue.emplace_back(std::move(jobHandle));
+
+ // Notify an idle worker if there's one
+ if (WorkersIdle != 0) {
+ Condition.notify_one();
+ }
+
+ return true;
+}
+
+void cmWorkerPoolInternal::UVSlotBegin(uv_async_t* handle)
+{
+ auto& gint = *reinterpret_cast<cmWorkerPoolInternal*>(handle->data);
+ // Create worker threads
+ {
+ unsigned int const num = gint.Pool->ThreadCount();
+ // Create workers
+ gint.Workers.reserve(num);
+ for (unsigned int ii = 0; ii != num; ++ii) {
+ gint.Workers.emplace_back(cm::make_unique<WorkerT>(ii));
+ }
+ // Start workers
+ for (auto& wrk : gint.Workers) {
+ wrk->Start(&gint);
+ }
+ }
+ // Destroy begin request
+ gint.UVRequestBegin.reset();
+}
+
+void cmWorkerPoolInternal::UVSlotEnd(uv_async_t* handle)
+{
+ auto& gint = *reinterpret_cast<cmWorkerPoolInternal*>(handle->data);
+ // Join and destroy worker threads
+ gint.Workers.clear();
+ // Destroy end request
+ gint.UVRequestEnd.reset();
+}
+
+void cmWorkerPoolInternal::Work(WorkerT* worker)
+{
+ std::unique_lock<std::mutex> uLock(Mutex);
+ // Increment running workers count
+ ++WorkersRunning;
+ // Enter worker main loop
+ while (true) {
+ // Abort on request
+ if (Aborting) {
+ break;
+ }
+ // Wait for new jobs
+ if (Queue.empty()) {
+ ++WorkersIdle;
+ Condition.wait(uLock);
+ --WorkersIdle;
+ continue;
+ }
+
+ // Check for fence jobs
+ if (FenceProcessing || Queue.front()->IsFence()) {
+ if (JobsProcessing != 0) {
+ Condition.wait(uLock);
+ continue;
+ }
+ // No jobs get processed. Set the fence job processing flag.
+ FenceProcessing = true;
+ }
+
+ // Pop next job from queue
+ worker->JobHandle() = std::move(Queue.front());
+ Queue.pop_front();
+
+ // Unlocked scope for job processing
+ ++JobsProcessing;
+ {
+ uLock.unlock();
+ worker->JobHandle()->Work(Pool, worker->Index()); // Process job
+ worker->JobHandle().reset(); // Destroy job
+ uLock.lock();
+ }
+ --JobsProcessing;
+
+ // Was this a fence job?
+ if (FenceProcessing) {
+ FenceProcessing = false;
+ Condition.notify_all();
+ }
+ }
+
+ // Decrement running workers count
+ if (--WorkersRunning == 0) {
+ // Last worker thread about to finish. Send libuv event.
+ UVRequestEnd.send();
+ }
+}
+
+cmWorkerPool::JobT::~JobT() = default;
+
+bool cmWorkerPool::JobT::RunProcess(ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory)
+{
+ // Get worker by index
+ auto* wrk = Pool_->Int_->Workers.at(WorkerIndex_).get();
+ return wrk->RunProcess(result, command, workingDirectory);
+}
+
+cmWorkerPool::cmWorkerPool()
+ : Int_(cm::make_unique<cmWorkerPoolInternal>(this))
+{
+}
+
+cmWorkerPool::~cmWorkerPool() = default;
+
+bool cmWorkerPool::Process(unsigned int threadCount, void* userData)
+{
+ // Setup user data
+ UserData_ = userData;
+ ThreadCount_ = (threadCount > 0) ? threadCount : 1u;
+
+ // Run libuv loop
+ bool success = Int_->Process();
+
+ // Clear user data
+ UserData_ = nullptr;
+ ThreadCount_ = 0;
+
+ return success;
+}
+
+bool cmWorkerPool::PushJob(JobHandleT&& jobHandle)
+{
+ return Int_->PushJob(std::move(jobHandle));
+}
+
+void cmWorkerPool::Abort()
+{
+ Int_->Abort();
+}
diff --git a/Source/cmWorkerPool.h b/Source/cmWorkerPool.h
new file mode 100644
index 0000000..71c7d84
--- /dev/null
+++ b/Source/cmWorkerPool.h
@@ -0,0 +1,219 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmWorkerPool_h
+#define cmWorkerPool_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmAlgorithms.h" // IWYU pragma: keep
+
+#include <memory> // IWYU pragma: keep
+#include <stdint.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+// -- Types
+class cmWorkerPoolInternal;
+
+/** @class cmWorkerPool
+ * @brief Thread pool with job queue
+ */
+class cmWorkerPool
+{
+public:
+ /**
+ * Return value and output of an external process.
+ */
+ struct ProcessResultT
+ {
+ void reset();
+ bool error() const
+ {
+ return (ExitStatus != 0) || (TermSignal != 0) || !ErrorMessage.empty();
+ }
+
+ std::int64_t ExitStatus = 0;
+ int TermSignal = 0;
+ std::string StdOut;
+ std::string StdErr;
+ std::string ErrorMessage;
+ };
+
+ /**
+ * Abstract job class for concurrent job processing.
+ */
+ class JobT
+ {
+ public:
+ JobT(JobT const&) = delete;
+ JobT& operator=(JobT const&) = delete;
+
+ /**
+ * @brief Virtual destructor.
+ */
+ virtual ~JobT();
+
+ /**
+ * @brief Fence job flag
+ *
+ * Fence jobs require that:
+ * - all jobs before in the queue have been processed
+ * - no jobs later in the queue will be processed before this job was
+ * processed
+ */
+ bool IsFence() const { return Fence_; }
+
+ protected:
+ /**
+ * @brief Protected default constructor
+ */
+ JobT(bool fence = false)
+ : Fence_(fence)
+ {
+ }
+
+ /**
+ * Abstract processing interface that must be implement in derived classes.
+ */
+ virtual void Process() = 0;
+
+ /**
+ * Get the worker pool.
+ * Only valid during the JobT::Process() call!
+ */
+ cmWorkerPool* Pool() const { return Pool_; }
+
+ /**
+ * Get the user data.
+ * Only valid during the JobT::Process() call!
+ */
+ void* UserData() const { return Pool_->UserData(); };
+
+ /**
+ * Get the worker index.
+ * This is the index of the thread processing this job and is in the range
+ * [0..ThreadCount).
+ * Concurrently processing jobs will never have the same WorkerIndex().
+ * Only valid during the JobT::Process() call!
+ */
+ unsigned int WorkerIndex() const { return WorkerIndex_; }
+
+ /**
+ * Run an external read only process.
+ * Use only during JobT::Process() call!
+ */
+ bool RunProcess(ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory);
+
+ private:
+ //! Needs access to Work()
+ friend class cmWorkerPoolInternal;
+ //! Worker thread entry method.
+ void Work(cmWorkerPool* pool, unsigned int workerIndex)
+ {
+ Pool_ = pool;
+ WorkerIndex_ = workerIndex;
+ this->Process();
+ }
+
+ private:
+ cmWorkerPool* Pool_ = nullptr;
+ unsigned int WorkerIndex_ = 0;
+ bool Fence_ = false;
+ };
+
+ /**
+ * @brief Job handle type
+ */
+ typedef std::unique_ptr<JobT> JobHandleT;
+
+ /**
+ * @brief Fence job base class
+ */
+ class JobFenceT : public JobT
+ {
+ public:
+ JobFenceT()
+ : JobT(true)
+ {
+ }
+ //! Does nothing
+ void Process() override{};
+ };
+
+ /**
+ * @brief Fence job that aborts the worker pool.
+ * This class is useful as the last job in the job queue.
+ */
+ class JobEndT : JobFenceT
+ {
+ public:
+ //! Does nothing
+ void Process() override { Pool()->Abort(); }
+ };
+
+public:
+ // -- Methods
+ cmWorkerPool();
+ ~cmWorkerPool();
+
+ /**
+ * @brief Blocking function that starts threads to process all Jobs in
+ * the queue.
+ *
+ * This method blocks until a job calls the Abort() method.
+ * @arg threadCount Number of threads to process jobs.
+ * @arg userData Common user data pointer available in all Jobs.
+ */
+ bool Process(unsigned int threadCount, void* userData = nullptr);
+
+ /**
+ * Number of worker threads passed to Process().
+ * Only valid during Process().
+ */
+ unsigned int ThreadCount() const { return ThreadCount_; }
+
+ /**
+ * User data reference passed to Process().
+ * Only valid during Process().
+ */
+ void* UserData() const { return UserData_; }
+
+ // -- Job processing interface
+
+ /**
+ * @brief Clears the job queue and aborts all worker threads.
+ *
+ * This method is thread safe and can be called from inside a job.
+ */
+ void Abort();
+
+ /**
+ * @brief Push job to the queue.
+ *
+ * This method is thread safe and can be called from inside a job or before
+ * Process().
+ */
+ bool PushJob(JobHandleT&& jobHandle);
+
+ /**
+ * @brief Push job to the queue
+ *
+ * This method is thread safe and can be called from inside a job or before
+ * Process().
+ */
+ template <class T, typename... Args>
+ bool EmplaceJob(Args&&... args)
+ {
+ return PushJob(cm::make_unique<T>(std::forward<Args>(args)...));
+ }
+
+private:
+ void* UserData_ = nullptr;
+ unsigned int ThreadCount_ = 0;
+ std::unique_ptr<cmWorkerPoolInternal> Int_;
+};
+
+#endif
diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx
index 9d2a3c4..f1ce608 100644
--- a/Source/cmXMLWriter.cxx
+++ b/Source/cmXMLWriter.cxx
@@ -23,7 +23,7 @@ cmXMLWriter::~cmXMLWriter()
void cmXMLWriter::StartDocument(const char* encoding)
{
- this->Output << "<?xml version=\"1.0\" encoding=\"" << encoding << "\"?>";
+ this->Output << R"(<?xml version="1.0" encoding=")" << encoding << "\"?>";
}
void cmXMLWriter::EndDocument()
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 8c1a359..fc24ac0 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -710,6 +710,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
this->GraphVizFile = path;
if (this->GraphVizFile.empty()) {
cmSystemTools::Error("No file specified for --graphviz");
+ return;
}
} else if (arg.find("--debug-trycompile", 0) == 0) {
std::cout << "debug trycompile on\n";
@@ -797,9 +798,9 @@ void cmake::SetArgs(const std::vector<std::string>& args)
cmSystemTools::Error("Could not create named generator " + value +
kdevError);
this->PrintGeneratorList();
- } else {
- this->SetGlobalGenerator(gen);
+ return;
}
+ this->SetGlobalGenerator(gen);
}
// no option assume it is the path to the source or an existing build
else {
diff --git a/Source/cmake.h b/Source/cmake.h
index 8d22f34..8b4b396 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -162,7 +162,7 @@ public:
int Configure();
int ActualConfigure();
- ///! Break up a line like VAR:type="value" into var, type and value
+ //! Break up a line like VAR:type="value" into var, type and value
static bool ParseCacheEntry(const std::string& entry, std::string& var,
std::string& value,
cmStateEnums::CacheEntryType& type);
@@ -176,40 +176,40 @@ public:
bool DeleteCache(const std::string& path);
void PreLoadCMakeFiles();
- ///! Create a GlobalGenerator
+ //! Create a GlobalGenerator
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name);
- ///! Return the global generator assigned to this instance of cmake
+ //! Return the global generator assigned to this instance of cmake
cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; }
- ///! Return the global generator assigned to this instance of cmake, const
+ //! Return the global generator assigned to this instance of cmake, const
const cmGlobalGenerator* GetGlobalGenerator() const
{
return this->GlobalGenerator;
}
- ///! Return the full path to where the CMakeCache.txt file should be.
+ //! Return the full path to where the CMakeCache.txt file should be.
static std::string FindCacheFile(const std::string& binaryDir);
- ///! Return the global generator assigned to this instance of cmake
+ //! Return the global generator assigned to this instance of cmake
void SetGlobalGenerator(cmGlobalGenerator*);
- ///! Get the names of the current registered generators
+ //! Get the names of the current registered generators
void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators,
bool includeNamesWithPlatform = true) const;
- ///! Set the name of the selected generator-specific instance.
+ //! Set the name of the selected generator-specific instance.
void SetGeneratorInstance(std::string const& instance)
{
this->GeneratorInstance = instance;
}
- ///! Set the name of the selected generator-specific platform.
+ //! Set the name of the selected generator-specific platform.
void SetGeneratorPlatform(std::string const& ts)
{
this->GeneratorPlatform = ts;
}
- ///! Set the name of the selected generator-specific toolset.
+ //! Set the name of the selected generator-specific toolset.
void SetGeneratorToolset(std::string const& ts)
{
this->GeneratorToolset = ts;
@@ -244,7 +244,7 @@ public:
* Given a variable name, return its value (as a string).
*/
const char* GetCacheDefinition(const std::string&) const;
- ///! Add an entry into the cache
+ //! Add an entry into the cache
void AddCacheEntry(const std::string& key, const char* value,
const char* helpString, int type);
@@ -263,14 +263,14 @@ public:
*/
int GetSystemInformation(std::vector<std::string>&);
- ///! Parse command line arguments
+ //! Parse command line arguments
void SetArgs(const std::vector<std::string>& args);
- ///! Is this cmake running as a result of a TRY_COMPILE command
+ //! Is this cmake running as a result of a TRY_COMPILE command
bool GetIsInTryCompile() const;
void SetIsInTryCompile(bool b);
- ///! Parse command line arguments that might set cache values
+ //! Parse command line arguments that might set cache values
bool SetCacheArgs(const std::vector<std::string>&);
using ProgressCallbackType = std::function<void(const std::string&, float)>;
@@ -283,24 +283,24 @@ public:
*/
void SetProgressCallback(ProgressCallbackType f);
- ///! this is called by generators to update the progress
+ //! this is called by generators to update the progress
void UpdateProgress(const std::string& msg, float prog);
#if defined(CMAKE_BUILD_WITH_CMAKE)
- ///! Get the variable watch object
+ //! Get the variable watch object
cmVariableWatch* GetVariableWatch() { return this->VariableWatch; }
#endif
std::vector<cmDocumentationEntry> GetGeneratorsDocumentation();
- ///! Set/Get a property of this target file
+ //! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
const char* GetProperty(const std::string& prop);
bool GetPropertyAsBool(const std::string& prop);
- ///! Get or create an cmInstalledFile instance and return a pointer to it
+ //! Get or create an cmInstalledFile instance and return a pointer to it
cmInstalledFile* GetOrCreateInstalledFile(cmMakefile* mf,
const std::string& name);
@@ -311,13 +311,13 @@ public:
return this->InstalledFiles;
}
- ///! Do all the checks before running configure
+ //! Do all the checks before running configure
int DoPreConfigureChecks();
void SetWorkingMode(WorkingMode mode) { this->CurrentWorkingMode = mode; }
WorkingMode GetWorkingMode() { return this->CurrentWorkingMode; }
- ///! Debug the try compile stuff by not deleting the files
+ //! Debug the try compile stuff by not deleting the files
bool GetDebugTryCompile() { return this->DebugTryCompile; }
void DebugTryCompileOn() { this->DebugTryCompile = true; }
@@ -423,13 +423,13 @@ public:
MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
- ///! run the --build option
+ //! run the --build option
int Build(int jobs, const std::string& dir,
const std::vector<std::string>& targets, const std::string& config,
const std::vector<std::string>& nativeOptions, bool clean,
bool verbose);
- ///! run the --open option
+ //! run the --open option
bool Open(const std::string& dir, bool dryRun);
void UnwatchUnusedCli(const std::string& var);
@@ -462,12 +462,12 @@ protected:
std::string GeneratorPlatform;
std::string GeneratorToolset;
- ///! read in a cmake list file to initialize the cache
+ //! read in a cmake list file to initialize the cache
void ReadListFile(const std::vector<std::string>& args,
const std::string& path);
bool FindPackage(const std::vector<std::string>& args);
- ///! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file.
+ //! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file.
/// If it is set, truncate it to 50kb
void TruncateOutputLog(const char* fname);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 8d63971..3c75957 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -7,8 +7,8 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmQtAutoGeneratorMocUic.h"
-#include "cmQtAutoGeneratorRcc.h"
+#include "cmQtAutoMocUic.h"
+#include "cmQtAutoRcc.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -368,7 +368,7 @@ struct CoCompileJob
};
// called when args[0] == "__run_co_compile"
-int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
+int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args)
{
std::vector<CoCompileJob> jobs;
std::string sourceFile; // store --source=
@@ -381,8 +381,7 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
std::vector<std::string> orig_cmd;
bool doing_options = true;
- for (std::string::size_type i = 2; i < args.size(); ++i) {
- std::string const& arg = args[i];
+ for (std::string const& arg : cmMakeRange(args).advance(2)) {
// if the arg is -- then the rest of the args after
// go into orig_cmd
if (arg == "--") {
@@ -466,7 +465,7 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
return ret;
}
-int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
+int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
{
// IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
if (args.size() > 1) {
@@ -482,9 +481,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 (!cmsys::SystemTools::CopyFileAlways(args[cc], args.back())) {
- std::cerr << "Error copying file \"" << args[cc] << "\" to \""
+ for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
+ if (!cmsys::SystemTools::CopyFileAlways(arg, args.back())) {
+ std::cerr << "Error copying file \"" << arg << "\" to \""
<< args.back() << "\".\n";
return_value = true;
}
@@ -504,9 +503,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::CopyFileIfDifferent(args[cc], args.back())) {
- std::cerr << "Error copying file (if different) from \"" << args[cc]
+ for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
+ if (!cmSystemTools::CopyFileIfDifferent(arg, args.back())) {
+ std::cerr << "Error copying file (if different) from \"" << arg
<< "\" to \"" << args.back() << "\".\n";
return_value = true;
}
@@ -518,10 +517,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
if (args[1] == "copy_directory" && args.size() > 3) {
// 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.back())) {
- std::cerr << "Error copying directory from \"" << args[cc]
- << "\" to \"" << args.back() << "\".\n";
+ for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
+ if (!cmSystemTools::CopyADirectory(arg, args.back())) {
+ std::cerr << "Error copying directory from \"" << arg << "\" to \""
+ << args.back() << "\".\n";
return_value = true;
}
}
@@ -614,13 +613,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
}
if (args[1] == "env") {
- std::vector<std::string>::const_iterator ai = args.begin() + 2;
- std::vector<std::string>::const_iterator ae = args.end();
+ auto ai = args.cbegin() + 2;
+ auto ae = args.cend();
for (; ai != ae; ++ai) {
std::string const& a = *ai;
if (cmHasLiteralPrefix(a, "--unset=")) {
// Unset environment variable.
- cmSystemTools::UnPutEnv(a.c_str() + 8);
+ cmSystemTools::UnPutEnv(a.substr(8));
} else if (!a.empty() && a[0] == '-') {
// Environment variable and command names cannot start in '-',
// so this must be an unknown option.
@@ -654,10 +653,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
#if defined(CMAKE_BUILD_WITH_CMAKE)
if (args[1] == "environment") {
- std::vector<std::string> env = cmSystemTools::GetEnvironmentVariables();
- std::vector<std::string>::iterator it;
- for (it = env.begin(); it != env.end(); ++it) {
- std::cout << *it << std::endl;
+ for (auto const& env : cmSystemTools::GetEnvironmentVariables()) {
+ std::cout << env << std::endl;
}
return 0;
}
@@ -666,9 +663,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
if (args[1] == "make_directory" && args.size() > 2) {
// If error occurs we want to continue copying next files.
bool return_value = false;
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- if (!cmSystemTools::MakeDirectory(args[cc])) {
- std::cerr << "Error creating directory \"" << args[cc] << "\".\n";
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (!cmSystemTools::MakeDirectory(arg)) {
+ std::cerr << "Error creating directory \"" << arg << "\".\n";
return_value = true;
}
}
@@ -687,14 +684,14 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Remove file
if (args[1] == "remove" && args.size() > 2) {
bool force = false;
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- if (args[cc] == "\\-f" || args[cc] == "-f") {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (arg == "\\-f" || arg == "-f") {
force = true;
} else {
// Complain if the file could not be removed, still exists,
// and the -f option was not given.
- if (!cmSystemTools::RemoveFile(args[cc]) && !force &&
- cmSystemTools::FileExists(args[cc])) {
+ if (!cmSystemTools::RemoveFile(arg) && !force &&
+ cmSystemTools::FileExists(arg)) {
return 1;
}
}
@@ -704,10 +701,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Touch file
if (args[1] == "touch" && args.size() > 2) {
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- if (!cmSystemTools::Touch(args[cc], true)) {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (!cmSystemTools::Touch(arg, true)) {
std::cerr << "cmake -E touch: failed to update \"";
- std::cerr << args[cc] << "\".\n";
+ std::cerr << arg << "\".\n";
return 1;
}
}
@@ -716,10 +713,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Touch file
if (args[1] == "touch_nocreate" && args.size() > 2) {
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- if (!cmSystemTools::Touch(args[cc], false)) {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (!cmSystemTools::Touch(arg, false)) {
std::cerr << "cmake -E touch_nocreate: failed to update \"";
- std::cerr << args[cc] << "\".\n";
+ std::cerr << arg << "\".\n";
return 1;
}
}
@@ -744,15 +741,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Sleep command
if (args[1] == "sleep" && args.size() > 2) {
double total = 0;
- for (size_t i = 2; i < args.size(); ++i) {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
double num = 0.0;
char unit;
char extra;
- int n = sscanf(args[i].c_str(), "%lg%c%c", &num, &unit, &extra);
+ int n = sscanf(arg.c_str(), "%lg%c%c", &num, &unit, &extra);
if ((n == 1 || (n == 2 && unit == 's')) && num >= 0) {
total += num;
} else {
- std::cerr << "Unknown sleep time format \"" << args[i] << "\".\n";
+ std::cerr << "Unknown sleep time format \"" << arg << "\".\n";
return 1;
}
}
@@ -1021,13 +1018,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
#ifdef CMAKE_BUILD_WITH_CMAKE
if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
- cmQtAutoGeneratorMocUic autoGen;
+ cmQtAutoMocUic autoGen;
std::string const& infoDir = args[2];
std::string const& config = args[3];
return autoGen.Run(infoDir, config) ? 0 : 1;
}
if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
- cmQtAutoGeneratorRcc autoGen;
+ cmQtAutoRcc autoGen;
std::string const& infoFile = args[2];
std::string config;
if (args.size() > 3) {
@@ -1047,8 +1044,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
std::string mtime;
std::string format;
bool doing_options = true;
- for (std::string::size_type cc = 4; cc < args.size(); cc++) {
- std::string const& arg = args[cc];
+ for (auto const& arg : cmMakeRange(args).advance(4)) {
if (doing_options && cmHasLiteralPrefix(arg, "--")) {
if (arg == "--") {
doing_options = false;
@@ -1180,17 +1176,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
bool isDebug = false;
std::string pipe;
- for (size_t i = 2; i < args.size(); ++i) {
- const std::string& a = args[i];
-
- if (a == "--experimental") {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (arg == "--experimental") {
supportExperimental = true;
- } else if (a == "--debug") {
+ } else if (arg == "--debug") {
pipe.clear();
isDebug = true;
- } else if (a.substr(0, pipePrefix.size()) == pipePrefix) {
+ } else if (arg.substr(0, pipePrefix.size()) == pipePrefix) {
isDebug = false;
- pipe = a.substr(pipePrefix.size());
+ pipe = arg.substr(pipePrefix.size());
if (pipe.empty()) {
cmSystemTools::Error("No pipe given after --pipe=");
return 2;
@@ -1262,15 +1256,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
-int cmcmd::HashSumFile(std::vector<std::string>& args, cmCryptoHash::Algo algo)
+int cmcmd::HashSumFile(std::vector<std::string> const& args,
+ cmCryptoHash::Algo algo)
{
if (args.size() < 3) {
return -1;
}
int retval = 0;
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- const char* filename = args[cc].c_str();
+ for (auto const& filename : cmMakeRange(args).advance(2)) {
// Cannot compute sum of a directory
if (cmSystemTools::FileIsDirectory(filename)) {
std::cerr << "Error: " << filename << " is a directory" << std::endl;
@@ -1289,7 +1283,7 @@ int cmcmd::HashSumFile(std::vector<std::string>& args, cmCryptoHash::Algo algo)
return retval;
}
-int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
+int cmcmd::SymlinkLibrary(std::vector<std::string> const& args)
{
int result = 0;
std::string realName = args[2];
@@ -1313,7 +1307,7 @@ int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
return result;
}
-int cmcmd::SymlinkExecutable(std::vector<std::string>& args)
+int cmcmd::SymlinkExecutable(std::vector<std::string> const& args)
{
int result = 0;
std::string const& realName = args[2];
@@ -1387,7 +1381,7 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num)
}
}
-int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
+int cmcmd::ExecuteEchoColor(std::vector<std::string> const& args)
{
// The arguments are
// args[0] == <cmake-executable>
@@ -1397,55 +1391,54 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
int color = cmsysTerminal_Color_Normal;
bool newline = true;
std::string progressDir;
- for (unsigned int i = 2; i < args.size(); ++i) {
- if (args[i].find("--switch=") == 0) {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (arg.find("--switch=") == 0) {
// Enable or disable color based on the switch value.
- std::string value = args[i].substr(9);
+ std::string value = arg.substr(9);
if (!value.empty()) {
enabled = cmSystemTools::IsOn(value);
}
- } else if (cmHasLiteralPrefix(args[i], "--progress-dir=")) {
- progressDir = args[i].substr(15);
- } else if (cmHasLiteralPrefix(args[i], "--progress-num=")) {
+ } else if (cmHasLiteralPrefix(arg, "--progress-dir=")) {
+ progressDir = arg.substr(15);
+ } else if (cmHasLiteralPrefix(arg, "--progress-num=")) {
if (!progressDir.empty()) {
- std::string const& progressNum = args[i].substr(15);
+ std::string const& progressNum = arg.substr(15);
cmcmdProgressReport(progressDir, progressNum);
}
- } else if (args[i] == "--normal") {
+ } else if (arg == "--normal") {
color = cmsysTerminal_Color_Normal;
- } else if (args[i] == "--black") {
+ } else if (arg == "--black") {
color = cmsysTerminal_Color_ForegroundBlack;
- } else if (args[i] == "--red") {
+ } else if (arg == "--red") {
color = cmsysTerminal_Color_ForegroundRed;
- } else if (args[i] == "--green") {
+ } else if (arg == "--green") {
color = cmsysTerminal_Color_ForegroundGreen;
- } else if (args[i] == "--yellow") {
+ } else if (arg == "--yellow") {
color = cmsysTerminal_Color_ForegroundYellow;
- } else if (args[i] == "--blue") {
+ } else if (arg == "--blue") {
color = cmsysTerminal_Color_ForegroundBlue;
- } else if (args[i] == "--magenta") {
+ } else if (arg == "--magenta") {
color = cmsysTerminal_Color_ForegroundMagenta;
- } else if (args[i] == "--cyan") {
+ } else if (arg == "--cyan") {
color = cmsysTerminal_Color_ForegroundCyan;
- } else if (args[i] == "--white") {
+ } else if (arg == "--white") {
color = cmsysTerminal_Color_ForegroundWhite;
- } else if (args[i] == "--bold") {
+ } else if (arg == "--bold") {
color |= cmsysTerminal_Color_ForegroundBold;
- } else if (args[i] == "--no-newline") {
+ } else if (arg == "--no-newline") {
newline = false;
- } else if (args[i] == "--newline") {
+ } else if (arg == "--newline") {
newline = true;
} else {
// Color is enabled. Print with the current color.
- cmSystemTools::MakefileColorEcho(color, args[i].c_str(), newline,
- enabled);
+ cmSystemTools::MakefileColorEcho(color, arg.c_str(), newline, enabled);
}
}
return 0;
}
-int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
+int cmcmd::ExecuteLinkScript(std::vector<std::string> const& args)
{
// The arguments are
// args[0] == <cmake-executable>
@@ -1658,9 +1651,9 @@ std::ostream& operator<<(std::ostream& stream,
return stream;
}
-static bool RunCommand(const char* comment, std::vector<std::string>& command,
- bool verbose, NumberFormat exitFormat,
- int* retCodeOut = nullptr,
+static bool RunCommand(const char* comment,
+ std::vector<std::string> const& command, bool verbose,
+ NumberFormat exitFormat, int* retCodeOut = nullptr,
bool (*retCodeOkay)(int) = nullptr)
{
if (verbose) {
diff --git a/Source/cmcmd.h b/Source/cmcmd.h
index d1e03d0..69a7ecb 100644
--- a/Source/cmcmd.h
+++ b/Source/cmcmd.h
@@ -16,18 +16,18 @@ public:
* Execute commands during the build process. Supports options such
* as echo, remove file etc.
*/
- static int ExecuteCMakeCommand(std::vector<std::string>&);
+ static int ExecuteCMakeCommand(std::vector<std::string> const&);
protected:
- static int HandleCoCompileCommands(std::vector<std::string>& args);
- static int HashSumFile(std::vector<std::string>& args,
+ static int HandleCoCompileCommands(std::vector<std::string> const& args);
+ static int HashSumFile(std::vector<std::string> const& args,
cmCryptoHash::Algo algo);
- static int SymlinkLibrary(std::vector<std::string>& args);
- static int SymlinkExecutable(std::vector<std::string>& args);
+ static int SymlinkLibrary(std::vector<std::string> const& args);
+ static int SymlinkExecutable(std::vector<std::string> const& args);
static bool SymlinkInternal(std::string const& file,
std::string const& link);
- static int ExecuteEchoColor(std::vector<std::string>& args);
- static int ExecuteLinkScript(std::vector<std::string>& args);
+ static int ExecuteEchoColor(std::vector<std::string> const& args);
+ static int ExecuteLinkScript(std::vector<std::string> const& args);
static int WindowsCEEnvironment(const char* version,
const std::string& name);
static int VisualStudioLink(std::vector<std::string> const& args, int type);
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 8577506..db4ef90 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -172,6 +172,9 @@ ENDIF()
IF(KWSYS_USE_Directory)
SET(KWSYS_USE_Encoding 1)
ENDIF()
+IF(KWSYS_USE_DynamicLoader)
+ SET(KWSYS_USE_Encoding 1)
+ENDIF()
IF(KWSYS_USE_FStream)
SET(KWSYS_USE_Encoding 1)
ENDIF()
@@ -1096,6 +1099,20 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
ADD_LIBRARY(${KWSYS_NAMESPACE}TestDynload MODULE testDynload.c)
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestDynload PROPERTY LABELS ${KWSYS_LABELS_LIB})
ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestDynload ${KWSYS_TARGET_INTERFACE})
+
+ if (WIN32)
+ # Windows tests supported flags.
+ add_library(${KWSYS_NAMESPACE}TestDynloadImpl SHARED testDynloadImpl.c)
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY LABELS ${KWSYS_LABELS_LIB})
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY DEFINE_SYMBOL BUILDING_TestDynloadImpl)
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dynloaddir")
+ add_dependencies(${KWSYS_NAMESPACE}TestDynloadImpl ${KWSYS_TARGET_INTERFACE})
+ add_library(${KWSYS_NAMESPACE}TestDynloadUse MODULE testDynloadUse.c)
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadUse PROPERTY LABELS ${KWSYS_LABELS_LIB})
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadUse PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dynloaddir")
+ add_dependencies(${KWSYS_NAMESPACE}TestDynloadUse ${KWSYS_TARGET_INTERFACE})
+ target_link_libraries(${KWSYS_NAMESPACE}TestDynloadUse PRIVATE ${KWSYS_NAMESPACE}TestDynloadImpl)
+ endif ()
ENDIF()
CREATE_TEST_SOURCELIST(
KWSYS_CXX_TEST_SRCS ${KWSYS_NAMESPACE}TestsCxx.cxx
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index a85690f..b93a215 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -1,9 +1,14 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#if defined(_WIN32)
+# define NOMINMAX // hide min,max to not conflict with <limits>
+#endif
+
#include "kwsysPrivate.h"
#include KWSYS_HEADER(DynamicLoader.hxx)
#include KWSYS_HEADER(Configure.hxx)
+#include KWSYS_HEADER(Encoding.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
@@ -25,6 +30,28 @@
// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.
+#define CHECK_OPEN_FLAGS(var, supported, ret) \
+ do { \
+ /* Check for unknown flags. */ \
+ if ((var & AllOpenFlags) != var) { \
+ return ret; \
+ } \
+ \
+ /* Check for unsupported flags. */ \
+ if ((var & (supported)) != var) { \
+ return ret; \
+ } \
+ } while (0)
+
+namespace KWSYS_NAMESPACE {
+
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
+{
+ return DynamicLoader::OpenLibrary(libname, 0);
+}
+}
+
#if !KWSYS_SUPPORTS_SHARED_LIBS
// Implementation for environments without dynamic libs
# include <string.h> // for strerror()
@@ -32,7 +59,7 @@
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
return 0;
}
@@ -67,8 +94,10 @@ const char* DynamicLoader::LastError()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, 0);
+
return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L);
}
@@ -130,8 +159,10 @@ const char* DynamicLoader::LastError()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, 0);
+
NSObjectFileImageReturnCode rc;
NSObjectFileImage image = 0;
@@ -185,19 +216,22 @@ const char* DynamicLoader::LastError()
// Implementation for Windows win32 code but not cygwin
# include <windows.h>
+# include <stdio.h>
+
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
- DynamicLoader::LibraryHandle lh;
- int length = MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, NULL, 0);
- wchar_t* wchars = new wchar_t[length + 1];
- wchars[0] = '\0';
- MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, wchars, length);
- lh = LoadLibraryW(wchars);
- delete[] wchars;
- return lh;
+ CHECK_OPEN_FLAGS(flags, SearchBesideLibrary, NULL);
+
+ DWORD llFlags = 0;
+ if (flags & SearchBesideLibrary) {
+ llFlags |= LOAD_WITH_ALTERED_SEARCH_PATH;
+ }
+
+ return LoadLibraryExW(Encoding::ToWindowsExtendedPath(libname).c_str(), NULL,
+ llFlags);
}
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
@@ -247,24 +281,38 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
# endif
}
+# define DYNLOAD_ERROR_BUFFER_SIZE 1024
+
const char* DynamicLoader::LastError()
{
- LPVOID lpMsgBuf = NULL;
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR)&lpMsgBuf, 0, NULL);
+ wchar_t lpMsgBuf[DYNLOAD_ERROR_BUFFER_SIZE + 1];
+
+ DWORD error = GetLastError();
+ DWORD length = FormatMessageW(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ lpMsgBuf, DYNLOAD_ERROR_BUFFER_SIZE, NULL);
+
+ static char str[DYNLOAD_ERROR_BUFFER_SIZE + 1];
+
+ if (length < 1) {
+ /* FormatMessage failed. Use a default message. */
+ _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
+ "DynamicLoader encountered error 0x%X. "
+ "FormatMessage failed with error 0x%X",
+ error, GetLastError());
+ return str;
+ }
- if (!lpMsgBuf) {
- return NULL;
+ if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, str,
+ DYNLOAD_ERROR_BUFFER_SIZE, NULL, NULL)) {
+ /* WideCharToMultiByte failed. Use a default message. */
+ _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
+ "DynamicLoader encountered error 0x%X. "
+ "WideCharToMultiByte failed with error 0x%X",
+ error, GetLastError());
}
- static char* str = 0;
- delete[] str;
- str = strcpy(new char[strlen((char*)lpMsgBuf) + 1], (char*)lpMsgBuf);
- // Free the buffer.
- LocalFree(lpMsgBuf);
return str;
}
@@ -282,8 +330,10 @@ namespace KWSYS_NAMESPACE {
static image_id last_dynamic_err = B_OK;
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, 0);
+
// image_id's are integers, errors are negative. Add one just in case we
// get a valid image_id of zero (is that even possible?).
image_id rc = load_add_on(libname.c_str());
@@ -360,8 +410,10 @@ const char* DynamicLoader::LastError()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, NULL);
+
char* name = (char*)calloc(1, libname.size() + 1);
dld_init(program_invocation_name);
strncpy(name, libname.c_str(), libname.size());
@@ -404,8 +456,10 @@ const char* DynamicLoader::LastError()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, NULL);
+
return dlopen(libname.c_str(), RTLD_LAZY);
}
diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in
index 08f2790..539c742 100644
--- a/Source/kwsys/DynamicLoader.hxx.in
+++ b/Source/kwsys/DynamicLoader.hxx.in
@@ -66,10 +66,23 @@ public:
// Return type from DynamicLoader::GetSymbolAddress.
typedef void (*SymbolPointer)();
+ enum OpenFlags
+ {
+ // Search for dependent libraries beside the library being loaded.
+ //
+ // This is currently only supported on Windows.
+ SearchBesideLibrary = 0x00000001,
+
+ AllOpenFlags = SearchBesideLibrary
+ };
+
/** Load a dynamic library into the current process.
* The returned LibraryHandle can be used to access the symbols in the
- * library. */
+ * library. The optional second argument is a set of flags to use when
+ * opening the library. If unrecognized or unsupported flags are specified,
+ * the library is not opened. */
static LibraryHandle OpenLibrary(const std::string&);
+ static LibraryHandle OpenLibrary(const std::string&, int);
/** Attempt to detach a dynamic library from the
* process. A value of true is returned if it is successful. */
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index b736ed4..87da80e 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -2436,10 +2436,6 @@ static bool CloneFileContent(const std::string& source,
bool SystemTools::CopyFileAlways(const std::string& source,
const std::string& destination)
{
- // If files are the same do not copy
- if (SystemTools::SameFile(source, destination)) {
- return true;
- }
mode_t perm = 0;
bool perms = SystemTools::GetPermissions(source, perm);
std::string real_destination = destination;
@@ -2460,6 +2456,10 @@ bool SystemTools::CopyFileAlways(const std::string& source,
} else {
destination_dir = SystemTools::GetFilenamePath(destination);
}
+ // If files are the same do not copy
+ if (SystemTools::SameFile(source, real_destination)) {
+ return true;
+ }
// Create destination directory
diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx
index ce87117..eff2ed7 100644
--- a/Source/kwsys/testDynamicLoader.cxx
+++ b/Source/kwsys/testDynamicLoader.cxx
@@ -21,11 +21,15 @@
// left on disk.
#include <testSystemTools.h>
-static std::string GetLibName(const char* lname)
+static std::string GetLibName(const char* lname, const char* subdir = NULL)
{
// Construct proper name of lib
std::string slname;
slname = EXECUTABLE_OUTPUT_PATH;
+ if (subdir) {
+ slname += "/";
+ slname += subdir;
+ }
#ifdef CMAKE_INTDIR
slname += "/";
slname += CMAKE_INTDIR;
@@ -45,26 +49,29 @@ static std::string GetLibName(const char* lname)
* r3: should CloseLibrary succeed ?
*/
static int TestDynamicLoader(const char* libname, const char* symbol, int r1,
- int r2, int r3)
+ int r2, int r3, int flags = 0)
{
std::cerr << "Testing: " << libname << std::endl;
kwsys::DynamicLoader::LibraryHandle l =
- kwsys::DynamicLoader::OpenLibrary(libname);
+ kwsys::DynamicLoader::OpenLibrary(libname, flags);
// If result is incompatible with expectation just fails (xor):
if ((r1 && !l) || (!r1 && l)) {
- std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
+ std::cerr << "OpenLibrary: " << kwsys::DynamicLoader::LastError()
+ << std::endl;
return 1;
}
kwsys::DynamicLoader::SymbolPointer f =
kwsys::DynamicLoader::GetSymbolAddress(l, symbol);
if ((r2 && !f) || (!r2 && f)) {
- std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
+ std::cerr << "GetSymbolAddress: " << kwsys::DynamicLoader::LastError()
+ << std::endl;
return 1;
}
#ifndef __APPLE__
int s = kwsys::DynamicLoader::CloseLibrary(l);
if ((r3 && !s) || (!r3 && s)) {
- std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
+ std::cerr << "CloseLibrary: " << kwsys::DynamicLoader::LastError()
+ << std::endl;
return 1;
}
#else
@@ -113,5 +120,14 @@ int testDynamicLoader(int argc, char* argv[])
res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderData", 1, 1, 1);
res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderData", 1, 0, 1);
+#ifdef _WIN32
+ libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynloadUse", "dynloaddir");
+ res += TestDynamicLoader(libname.c_str(), "dummy", 0, 0, 0);
+ res += TestDynamicLoader(libname.c_str(), "TestLoad", 1, 1, 1,
+ kwsys::DynamicLoader::SearchBesideLibrary);
+ res += TestDynamicLoader(libname.c_str(), "_TestLoad", 1, 0, 1,
+ kwsys::DynamicLoader::SearchBesideLibrary);
+#endif
+
return res;
}
diff --git a/Source/kwsys/testDynloadImpl.c b/Source/kwsys/testDynloadImpl.c
new file mode 100644
index 0000000..2b9069b
--- /dev/null
+++ b/Source/kwsys/testDynloadImpl.c
@@ -0,0 +1,10 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+
+#include "testDynloadImpl.h"
+
+int TestDynamicLoaderImplData = 0;
+
+void TestDynamicLoaderImplSymbolPointer()
+{
+}
diff --git a/Source/kwsys/testDynloadImpl.h b/Source/kwsys/testDynloadImpl.h
new file mode 100644
index 0000000..d0c9dfb
--- /dev/null
+++ b/Source/kwsys/testDynloadImpl.h
@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#ifdef _WIN32
+# ifdef BUILDING_TestDynloadImpl
+# define DLIMPL_EXPORT __declspec(dllexport)
+# else
+# define DLIMPL_EXPORT __declspec(dllimport)
+# endif
+#else
+# define DLIMPL_EXPORT
+#endif
+
+DLIMPL_EXPORT int TestDynamicLoaderImplData;
+
+DLIMPL_EXPORT void TestDynamicLoaderImplSymbolPointer();
diff --git a/Source/kwsys/testDynloadUse.c b/Source/kwsys/testDynloadUse.c
new file mode 100644
index 0000000..5402add
--- /dev/null
+++ b/Source/kwsys/testDynloadUse.c
@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#include "testDynloadImpl.h"
+
+#ifdef _WIN32
+# define DL_EXPORT __declspec(dllexport)
+#else
+# define DL_EXPORT
+#endif
+
+DL_EXPORT int TestLoad()
+{
+ TestDynamicLoaderImplSymbolPointer();
+ return TestDynamicLoaderImplData;
+}