diff options
Diffstat (limited to 'Source')
281 files changed, 8724 insertions, 4966 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index b1f7b29e58..ff313d66d1 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -289,6 +289,8 @@ set(SRCS cmGeneratorExpression.h cmGeneratorTarget.cxx cmGeneratorTarget.h + cmLinkItemGraphVisitor.cxx + cmLinkItemGraphVisitor.h cmGetPipes.cxx cmGetPipes.h cmGlobalCommonGenerator.cxx @@ -691,6 +693,8 @@ set(SRCS cmDuration.h cmDuration.cxx + + bindexplib.cxx ) SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS @@ -713,7 +717,6 @@ if (WIN32) set(SRCS ${SRCS} cmCallVisualStudioMacro.cxx cmCallVisualStudioMacro.h - bindexplib.cxx ) if(NOT UNIX) @@ -1193,6 +1196,11 @@ if(WIN32) endforeach() endif() +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET ${_tools} PROPERTY JOB_POOL_LINK "link-bin") + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "link-bin=${CMake_JOB_POOL_LINK_BIN}") +endif() + # Install tools foreach(_tool ${_tools}) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 17eda0d10b..985303c5da 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 16) -set(CMake_VERSION_PATCH 2) +set(CMake_VERSION_PATCH 20200114) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 953022764f..712eb779cd 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -125,7 +125,7 @@ int cmCPackGenerator::PrepareNames() cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl); const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); - if (descFileName) { + if (descFileName && !this->GetOption("CPACK_PACKAGE_DESCRIPTION")) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: " << descFileName << std::endl); if (!cmSystemTools::FileExists(descFileName)) { @@ -149,7 +149,12 @@ int cmCPackGenerator::PrepareNames() while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) { ostr << cmXMLSafe(line) << std::endl; } - this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str()); + this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str()); + const char* defFileName = + this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE"); + if (defFileName && !strcmp(defFileName, descFileName)) { + this->SetOption("CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE", "ON"); + } } if (!this->GetOption("CPACK_PACKAGE_DESCRIPTION")) { cmCPackLogger( @@ -616,9 +621,9 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( buildConfigs.emplace_back(); } - std::unique_ptr<cmGlobalGenerator> globalGenerator( + std::unique_ptr<cmGlobalGenerator> globalGenerator = this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator( - cmakeGenerator)); + cmakeGenerator); if (!globalGenerator) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Specified package generator not found. " diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 9bf72dfb88..363f536822 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -128,22 +128,26 @@ int cmCPackNSISGenerator::PackageFiles() this->IsSet("CPACK_NSIS_MUI_UNIICON")) { std::string installerIconCode; if (this->IsSet("CPACK_NSIS_MUI_ICON")) { - installerIconCode += "!define MUI_ICON \""; - installerIconCode += this->GetOption("CPACK_NSIS_MUI_ICON"); - installerIconCode += "\"\n"; + installerIconCode += cmStrCat( + "!define MUI_ICON \"", this->GetOption("CPACK_NSIS_MUI_ICON"), "\"\n"); } if (this->IsSet("CPACK_NSIS_MUI_UNIICON")) { - installerIconCode += "!define MUI_UNICON \""; - installerIconCode += this->GetOption("CPACK_NSIS_MUI_UNIICON"); - installerIconCode += "\"\n"; + installerIconCode += + cmStrCat("!define MUI_UNICON \"", + this->GetOption("CPACK_NSIS_MUI_UNIICON"), "\"\n"); } this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_ICON_CODE", installerIconCode.c_str()); } - if (this->IsSet("CPACK_PACKAGE_ICON")) { - std::string installerIconCode = - cmStrCat("!define MUI_HEADERIMAGE_BITMAP \"", - this->GetOption("CPACK_PACKAGE_ICON"), "\"\n"); + std::string installerHeaderImage; + if (this->IsSet("CPACK_NSIS_MUI_HEADERIMAGE")) { + installerHeaderImage = this->GetOption("CPACK_NSIS_MUI_HEADERIMAGE"); + } else if (this->IsSet("CPACK_PACKAGE_ICON")) { + installerHeaderImage = this->GetOption("CPACK_PACKAGE_ICON"); + } + if (!installerHeaderImage.empty()) { + std::string installerIconCode = cmStrCat( + "!define MUI_HEADERIMAGE_BITMAP \"", installerHeaderImage, "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE", installerIconCode.c_str()); } @@ -173,6 +177,32 @@ int cmCPackNSISGenerator::PackageFiles() installerRunCode.c_str()); } + if (this->IsSet("CPACK_NSIS_WELCOME_TITLE")) { + std::string welcomeTitleCode = + cmStrCat("!define MUI_WELCOMEPAGE_TITLE \"", + this->GetOption("CPACK_NSIS_WELCOME_TITLE"), "\""); + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_WELCOME_TITLE_CODE", + welcomeTitleCode.c_str()); + } + + if (this->IsSet("CPACK_NSIS_WELCOME_TITLE_3LINES")) { + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_WELCOME_TITLE_3LINES_CODE", + "!define MUI_WELCOMEPAGE_TITLE_3LINES"); + } + + if (this->IsSet("CPACK_NSIS_FINISH_TITLE")) { + std::string finishTitleCode = + cmStrCat("!define MUI_FINISHPAGE_TITLE \"", + this->GetOption("CPACK_NSIS_FINISH_TITLE"), "\""); + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_FINISH_TITLE_CODE", + finishTitleCode.c_str()); + } + + if (this->IsSet("CPACK_NSIS_FINISH_TITLE_3LINES")) { + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_FINISH_TITLE_3LINES_CODE", + "!define MUI_FINISHPAGE_TITLE_3LINES"); + } + // Setup all of the component sections if (this->Components.empty()) { this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", ""); diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index dae5ec9d4b..ac3d64d9ae 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -46,7 +46,66 @@ std::string cmCPackPKGGenerator::GetPackageName( return component.ArchiveFile + ".pkg"; } -void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) +void cmCPackPKGGenerator::CreateBackground(const char* themeName, + const char* metapackageFile, + cm::string_view genName, + cmXMLWriter& xout) +{ + std::string paramSuffix = + (themeName == nullptr) ? "" : cmSystemTools::UpperCase(themeName); + std::string opt = (themeName == nullptr) + ? cmStrCat("CPACK_", genName, "_BACKGROUND") + : cmStrCat("CPACK_", genName, "_BACKGROUND_", paramSuffix); + const char* bgFileName = this->GetOption(opt); + if (bgFileName == nullptr) { + return; + } + + std::string bgFilePath = cmStrCat(metapackageFile, "/Contents/", bgFileName); + + if (!cmSystemTools::FileExists(bgFilePath)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Background image doesn't exist in the resource directory: " + << bgFileName << std::endl); + return; + } + + if (themeName == nullptr) { + xout.StartElement("background"); + } else { + xout.StartElement(cmStrCat("background-", themeName)); + } + + xout.Attribute("file", bgFileName); + + const char* param = this->GetOption(cmStrCat(opt, "_ALIGNMENT")); + if (param != nullptr) { + xout.Attribute("alignment", param); + } + + param = this->GetOption(cmStrCat(opt, "_SCALING")); + if (param != nullptr) { + xout.Attribute("scaling", param); + } + + // Apple docs say that you must provide either mime-type or uti + // attribute for the background, but I've seen examples that + // doesn't have them, so don't make them mandatory. + param = this->GetOption(cmStrCat(opt, "_MIME_TYPE")); + if (param != nullptr) { + xout.Attribute("mime-type", param); + } + + param = this->GetOption(cmStrCat(opt, "_UTI")); + if (param != nullptr) { + xout.Attribute("uti", param); + } + + xout.EndElement(); +} + +void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile, + const char* genName) { std::string distributionTemplate = this->FindTemplate("CPack.distribution.dist.in"); @@ -102,6 +161,11 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) CreateChoice(PostFlightComponent, xout); } + // default background + this->CreateBackground(nullptr, metapackageFile, genName, xout); + // Dark Aqua + this->CreateBackground("darkAqua", metapackageFile, genName, xout); + this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str()); // Create the distribution.dist file in the metapackage to turn it diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h index 69286ffde6..be730abddf 100644 --- a/Source/CPack/cmCPackPKGGenerator.h +++ b/Source/CPack/cmCPackPKGGenerator.h @@ -9,6 +9,8 @@ #include <sstream> #include <string> +#include <cm/string_view> + #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" @@ -57,7 +59,7 @@ protected: // inter-component dependencies. metapackageFile is the name of the // metapackage for the distribution. Only valid for a // component-based install. - void WriteDistributionFile(const char* metapackageFile); + void WriteDistributionFile(const char* metapackageFile, const char* genName); // Subroutine of WriteDistributionFile that writes out the // dependency attributes for inter-component dependencies. @@ -85,6 +87,10 @@ protected: /// installer GUI. void CreateChoice(const cmCPackComponent& component, cmXMLWriter& xout); + /// Creates a background in the distribution XML. + void CreateBackground(const char* themeName, const char* metapackageFile, + cm::string_view genName, cmXMLWriter& xout); + // The PostFlight component when creating a metapackage cmCPackComponent PostFlightComponent; }; diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index c5ba726d50..12ea97b47f 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -279,7 +279,7 @@ int cmCPackPackageMakerGenerator::PackageFiles() } else { // We have built the package in place. Generate the // distribution.dist file to describe it for the installer. - WriteDistributionFile(packageDirFileName.c_str()); + WriteDistributionFile(packageDirFileName.c_str(), "PACKAGEMAKER"); } std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index dae268c5ce..a3e55de5c2 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -81,7 +81,7 @@ int cmCPackProductBuildGenerator::PackageFiles() } // combine package(s) into a distribution - WriteDistributionFile(packageDirFileName.c_str()); + WriteDistributionFile(packageDirFileName.c_str(), "PRODUCTBUILD"); std::ostringstream pkgCmd; std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 58956522f4..dc316233c9 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -115,7 +115,6 @@ int main(int argc, char const* const* argv) argc = args.argc(); argv = args.argv(); - cmSystemTools::EnableMSVCDebugHook(); cmSystemTools::InitializeLibUV(); cmSystemTools::FindCMakeResources(argv[0]); cmCPackLog log; @@ -314,7 +313,7 @@ int main(int argc, char const* const* argv) else { // get a default value (current working directory) cpackProjectDirectory = cmsys::SystemTools::GetCurrentWorkingDirectory(); - // use default value iff no value has been provided by the config file + // use default value if no value has been provided by the config file if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) { globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory); @@ -324,6 +323,12 @@ int main(int argc, char const* const* argv) globalMF.AddDefinition(cd.first, cd.second); } + // Force CPACK_PACKAGE_DIRECTORY as absolute path + cpackProjectDirectory = globalMF.GetDefinition("CPACK_PACKAGE_DIRECTORY"); + cpackProjectDirectory = + cmSystemTools::CollapseFullPath(cpackProjectDirectory); + globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory); + const char* cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH"); if (cpackModulesPath) { globalMF.AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath); diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index 8640c46f84..c87fb83b31 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -8,11 +8,12 @@ #include <ostream> #include <vector> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" #include "cm_expat.h" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" @@ -245,7 +246,7 @@ private: void CharacterDataHandler(const char* data, int length) override { - cmAppend(this->CData, data, data + length); + cm::append(this->CData, data, data + length); } void EndElement(const std::string& name) override diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 2ad661cf04..5e29386c76 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -215,11 +215,11 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) if (this->BuildNoCMake) { // Make the generator available for the Build call below. - cmGlobalGenerator* gen = cm.CreateGlobalGenerator(this->BuildGenerator); - cm.SetGlobalGenerator(gen); + cm.SetGlobalGenerator(cm.CreateGlobalGenerator(this->BuildGenerator)); if (!this->BuildGeneratorPlatform.empty()) { - cmMakefile mf(gen, cm.GetCurrentSnapshot()); - if (!gen->SetGeneratorPlatform(this->BuildGeneratorPlatform, &mf)) { + cmMakefile mf(cm.GetGlobalGenerator(), cm.GetCurrentSnapshot()); + if (!cm.GetGlobalGenerator()->SetGeneratorPlatform( + this->BuildGeneratorPlatform, &mf)) { return 1; } } diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 18df2141ec..d1b7701ec6 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -29,13 +29,7 @@ void cmCTestBuildCommand::BindArguments() this->Bind("PROJECT_NAME"_s, this->ProjectName); } -cmCTestBuildCommand::~cmCTestBuildCommand() -{ - if (this->GlobalGenerator) { - delete this->GlobalGenerator; - this->GlobalGenerator = nullptr; - } -} +cmCTestBuildCommand::~cmCTestBuildCommand() = default; cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() { @@ -79,8 +73,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() } if (this->GlobalGenerator) { if (this->GlobalGenerator->GetName() != cmakeGeneratorName) { - delete this->GlobalGenerator; - this->GlobalGenerator = nullptr; + this->GlobalGenerator.reset(); } } if (!this->GlobalGenerator) { diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h index da00a43c64..0f82817589 100644 --- a/Source/CTest/cmCTestBuildCommand.h +++ b/Source/CTest/cmCTestBuildCommand.h @@ -48,7 +48,7 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - cmGlobalGenerator* GlobalGenerator = nullptr; + std::unique_ptr<cmGlobalGenerator> GlobalGenerator; protected: cmCTestBuildHandler* Handler; diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 9cb5449d96..03a3fd306b 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -7,11 +7,12 @@ #include <set> #include <utility> +#include <cmext/algorithm> + #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" #include "cmsys/Process.h" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmDuration.h" #include "cmFileTimeCache.h" @@ -969,7 +970,7 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length, if (it != queue->end()) { // Create a contiguous array for the line this->CurrentProcessingLine.clear(); - cmAppend(this->CurrentProcessingLine, queue->begin(), it); + cm::append(this->CurrentProcessingLine, queue->begin(), it); this->CurrentProcessingLine.push_back(0); const char* line = this->CurrentProcessingLine.data(); diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index f2f42b4f2d..3854710819 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -69,12 +69,11 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() bool multiConfig = false; bool cmakeBuildTypeInOptions = false; - cmGlobalGenerator* gg = - this->Makefile->GetCMakeInstance()->CreateGlobalGenerator( - cmakeGeneratorName); + auto gg = this->Makefile->GetCMakeInstance()->CreateGlobalGenerator( + cmakeGeneratorName); if (gg) { multiConfig = gg->IsMultiConfig(); - delete gg; + gg.reset(); } std::string cmakeConfigureCommand = diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 4cd783fd6b..2c8f119378 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -12,12 +12,13 @@ #include <sstream> #include <utility> +#include <cmext/algorithm> + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" @@ -819,7 +820,7 @@ int cmCTestCoverageHandler::HandleJacocoCoverage( std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory"); std::string binCoverageFile = binaryDir + "/*jacoco.xml"; g2.FindFiles(binCoverageFile); - cmAppend(files, g2.GetFiles()); + cm::append(files, g2.GetFiles()); if (!files.empty()) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, @@ -1462,7 +1463,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage( " looking for LCOV files in: " << daGlob << std::endl, this->Quiet); gl.FindFiles(daGlob); // Keep a list of all LCOV files - cmAppend(lcovFiles, gl.GetFiles()); + cm::append(lcovFiles, gl.GetFiles()); for (std::string const& file : lcovFiles) { lcovFile = file; @@ -1599,10 +1600,10 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files) " globbing for coverage in: " << lm.first << std::endl, this->Quiet); std::string daGlob = cmStrCat(lm.first, "/*.da"); gl.FindFiles(daGlob); - cmAppend(files, gl.GetFiles()); + cm::append(files, gl.GetFiles()); daGlob = cmStrCat(lm.first, "/*.gcda"); gl.FindFiles(daGlob); - cmAppend(files, gl.GetFiles()); + cm::append(files, gl.GetFiles()); } } @@ -1638,7 +1639,7 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) "Error while finding files matching " << daGlob << std::endl); return false; } - cmAppend(files, gl.GetFiles()); + cm::append(files, gl.GetFiles()); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Now searching in: " << daGlob << std::endl, this->Quiet); return true; diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx index ccac832f06..3ad474980c 100644 --- a/Source/CTest/cmCTestCurl.cxx +++ b/Source/CTest/cmCTestCurl.cxx @@ -5,7 +5,8 @@ #include <cstdio> #include <ostream> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmCTest.h" #include "cmCurl.h" #include "cmStringAlgorithms.h" @@ -46,14 +47,14 @@ size_t curlWriteMemoryCallback(void* ptr, size_t size, size_t nmemb, { int realsize = static_cast<int>(size * nmemb); const char* chPtr = static_cast<char*>(ptr); - cmAppend(*static_cast<std::vector<char>*>(data), chPtr, chPtr + realsize); + cm::append(*static_cast<std::vector<char>*>(data), chPtr, chPtr + realsize); return realsize; } size_t curlDebugCallback(CURL* /*unused*/, curl_infotype /*unused*/, char* chPtr, size_t size, void* data) { - cmAppend(*static_cast<std::vector<char>*>(data), chPtr, chPtr + size); + cm::append(*static_cast<std::vector<char>*>(data), chPtr, chPtr + size); return size; } } diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx index 3265498c08..5f4581eff7 100644 --- a/Source/CTest/cmCTestHG.cxx +++ b/Source/CTest/cmCTestHG.cxx @@ -5,9 +5,10 @@ #include <ostream> #include <vector> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" @@ -204,7 +205,7 @@ private: void CharacterDataHandler(const char* data, int length) override { - cmAppend(this->CData, data, data + length); + cm::append(this->CData, data, data + length); } void EndElement(const std::string& name) override diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index a5ec1ae81e..c1ecaf125d 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -2,9 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestMemCheckHandler.h" +#include <algorithm> #include <chrono> #include <cstring> #include <iostream> +#include <iterator> #include <sstream> #include <utility> @@ -12,6 +14,7 @@ #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" +#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmDuration.h" #include "cmSystemTools.h" @@ -162,12 +165,13 @@ int cmCTestMemCheckHandler::PostProcessHandler() void cmCTestMemCheckHandler::GenerateTestCommand( std::vector<std::string>& args, int test) { - std::string index; - std::ostringstream stream; + std::string index = std::to_string(test); std::string memcheckcommand = cmSystemTools::ConvertToOutputPath(this->MemoryTester); - stream << test; - index = stream.str(); + + std::vector<std::string> dirs; + bool nextArgIsDir = false; + for (std::string arg : this->MemoryTesterDynamicOptions) { std::string::size_type pos = arg.find("??"); if (pos != std::string::npos) { @@ -177,6 +181,16 @@ void cmCTestMemCheckHandler::GenerateTestCommand( memcheckcommand += " \""; memcheckcommand += arg; memcheckcommand += "\""; + + if (nextArgIsDir) { + nextArgIsDir = false; + dirs.push_back(arg); + } + + if (this->MemoryTesterStyle == cmCTestMemCheckHandler::DRMEMORY && + (arg == "-logdir" || arg == "-symcache_dir")) { + nextArgIsDir = true; + } } // Create a copy of the memory tester environment variable. // This is used for memory testing programs that pass options @@ -208,6 +222,11 @@ void cmCTestMemCheckHandler::GenerateTestCommand( memcheckcommand += " " + memTesterEnvironmentVariable; args.push_back(memTesterEnvironmentVariable); } + + for (std::string const& dir : dirs) { + cmSystemTools::MakeDirectory(dir); + } + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Memory check command: " << memcheckcommand << std::endl, this->Quiet); @@ -300,6 +319,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) case cmCTestMemCheckHandler::VALGRIND: xml.Attribute("Checker", "Valgrind"); break; + case cmCTestMemCheckHandler::DRMEMORY: + xml.Attribute("Checker", "DrMemory"); + break; case cmCTestMemCheckHandler::PURIFY: xml.Attribute("Checker", "Purify"); break; @@ -387,11 +409,11 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) } cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "MemCheck log files can be found here: " - "( * corresponds to test number)" + "(<#> corresponds to test number)" << std::endl, this->Quiet); std::string output = this->MemoryTesterOutputFile; - cmSystemTools::ReplaceString(output, "??", "*"); + cmSystemTools::ReplaceString(output, "??", "<#>"); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, output << std::endl, this->Quiet); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, @@ -437,6 +459,10 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() if (testerName.find("valgrind") != std::string::npos || this->CTest->GetCTestConfiguration("MemoryCheckType") == "Valgrind") { this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; + } else if (testerName.find("drmemory") != std::string::npos || + this->CTest->GetCTestConfiguration("MemoryCheckType") == + "DrMemory") { + this->MemoryTesterStyle = cmCTestMemCheckHandler::DRMEMORY; } else if (testerName.find("purify") != std::string::npos) { this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; } else if (testerName.find("BC") != std::string::npos) { @@ -453,6 +479,10 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTester = this->CTest->GetCTestConfiguration("ValgrindCommand"); this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; } else if (cmSystemTools::FileExists( + this->CTest->GetCTestConfiguration("DrMemoryCommand"))) { + this->MemoryTester = this->CTest->GetCTestConfiguration("DrMemoryCommand"); + this->MemoryTesterStyle = cmCTestMemCheckHandler::DRMEMORY; + } else if (cmSystemTools::FileExists( this->CTest->GetCTestConfiguration("BoundsCheckerCommand"))) { this->MemoryTester = this->CTest->GetCTestConfiguration("BoundsCheckerCommand"); @@ -498,6 +528,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; } else if (checkType == "Valgrind") { this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; + } else if (checkType == "DrMemory") { + this->MemoryTesterStyle = cmCTestMemCheckHandler::DRMEMORY; } } if (this->MemoryTester.empty()) { @@ -519,6 +551,10 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() .empty()) { memoryTesterOptions = this->CTest->GetCTestConfiguration("ValgrindCommandOptions"); + } else if (!this->CTest->GetCTestConfiguration("DrMemoryCommandOptions") + .empty()) { + memoryTesterOptions = + this->CTest->GetCTestConfiguration("DrMemoryCommandOptions"); } this->MemoryTesterOptions = cmSystemTools::ParseArguments(memoryTesterOptions); @@ -554,6 +590,64 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterOutputFile); break; } + case cmCTestMemCheckHandler::DRMEMORY: { + std::string tempDrMemoryDir = + this->CTest->GetBinaryDir() + "/Testing/Temporary/DrMemory"; + + if (!cmContains(this->MemoryTesterOptions, "-quiet")) { + this->MemoryTesterOptions.emplace_back("-quiet"); + } + + if (!cmContains(this->MemoryTesterOptions, "-batch")) { + this->MemoryTesterOptions.emplace_back("-batch"); + } + + this->MemoryTesterDynamicOptions.emplace_back("-logdir"); + auto logdirOption = + std::find(this->MemoryTesterOptions.begin(), + this->MemoryTesterOptions.end(), "-logdir"); + if (logdirOption == this->MemoryTesterOptions.end()) { + // No logdir found in memory tester options + std::string drMemoryLogDir = tempDrMemoryDir + "/??"; + this->MemoryTesterDynamicOptions.push_back(drMemoryLogDir); + this->MemoryTesterOutputFile = drMemoryLogDir; + } else { + // Use logdir found in memory tester options + auto logdirLocation = std::next(logdirOption); + this->MemoryTesterOutputFile = *logdirLocation; + this->MemoryTesterDynamicOptions.push_back(*logdirLocation); + this->MemoryTesterOptions.erase(logdirOption, logdirLocation + 1); + } + this->MemoryTesterOutputFile += "/*/results.txt"; + + if (std::find(this->MemoryTesterOptions.begin(), + this->MemoryTesterOptions.end(), + "-symcache_dir") == this->MemoryTesterOptions.end()) { + this->MemoryTesterDynamicOptions.emplace_back("-symcache_dir"); + std::string drMemoryCacheDir = tempDrMemoryDir + "/cache"; + this->MemoryTesterDynamicOptions.push_back(drMemoryCacheDir); + } + + if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile") + .empty()) { + if (!cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile"))) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot find memory checker suppression file: " + << this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile") + << std::endl); + return false; + } + this->MemoryTesterOptions.emplace_back("-suppress"); + this->MemoryTesterOptions.push_back( + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")); + } + + this->MemoryTesterOptions.emplace_back("--"); + + break; + } case cmCTestMemCheckHandler::PURIFY: { std::string outputFile; #ifdef _WIN32 @@ -667,6 +761,8 @@ bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, switch (this->MemoryTesterStyle) { case cmCTestMemCheckHandler::VALGRIND: return this->ProcessMemCheckValgrindOutput(str, log, results); + case cmCTestMemCheckHandler::DRMEMORY: + return this->ProcessMemCheckDrMemoryOutput(str, log, results); case cmCTestMemCheckHandler::PURIFY: return this->ProcessMemCheckPurifyOutput(str, log, results); case cmCTestMemCheckHandler::ADDRESS_SANITIZER: @@ -932,6 +1028,47 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( return defects == 0; } +bool cmCTestMemCheckHandler::ProcessMemCheckDrMemoryOutput( + const std::string& str, std::string& log, std::vector<int>& results) +{ + std::vector<std::string> lines; + cmsys::SystemTools::Split(str, lines); + + cmsys::RegularExpression drMemoryError("^Error #[0-9]+"); + + cmsys::RegularExpression unaddressableAccess("UNADDRESSABLE ACCESS"); + cmsys::RegularExpression uninitializedRead("UNINITIALIZED READ"); + cmsys::RegularExpression invalidHeapArgument("INVALID HEAP ARGUMENT"); + cmsys::RegularExpression leak("LEAK"); + cmsys::RegularExpression handleLeak("HANDLE LEAK"); + + int defects = 0; + + std::ostringstream ostr; + for (const auto& l : lines) { + ostr << l << std::endl; + if (drMemoryError.find(l)) { + defects++; + if (unaddressableAccess.find(l)) { + results[cmCTestMemCheckHandler::UMR]++; + } else if (uninitializedRead.find(l)) { + results[cmCTestMemCheckHandler::UMR]++; + } else if (leak.find(l)) { + results[cmCTestMemCheckHandler::MLK]++; + } else if (handleLeak.find(l)) { + results[cmCTestMemCheckHandler::MLK]++; + } else if (invalidHeapArgument.find(l)) { + results[cmCTestMemCheckHandler::FMM]++; + } + } + } + + log = ostr.str(); + + this->DefectCount += defects; + return defects == 0; +} + bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( const std::string& str, std::string& log, std::vector<int>& results) { @@ -991,6 +1128,8 @@ void cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res, int test) this->Quiet); if (this->MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER) { this->PostProcessBoundsCheckerTest(res, test); + } else if (this->MemoryTesterStyle == cmCTestMemCheckHandler::DRMEMORY) { + this->PostProcessDrMemoryTest(res, test); } else { std::vector<std::string> files; this->TestOutputFileNames(test, files); @@ -1045,6 +1184,37 @@ void cmCTestMemCheckHandler::PostProcessBoundsCheckerTest( this->Quiet); } +void cmCTestMemCheckHandler::PostProcessDrMemoryTest( + cmCTestTestHandler::cmCTestTestResult& res, int test) +{ + std::string drMemoryLogDir = this->MemoryTesterOutputFile.substr( + 0, this->MemoryTesterOutputFile.find("/*/results.txt")); + + // replace placeholder of test + std::string::size_type pos = drMemoryLogDir.find("??"); + if (pos != std::string::npos) { + drMemoryLogDir.replace(pos, 2, std::to_string(test)); + } + + cmsys::Glob g; + g.FindFiles(drMemoryLogDir + "/resfile.*"); + const std::vector<std::string>& files = g.GetFiles(); + + for (const std::string& f : files) { + cmsys::ifstream ifs(f.c_str()); + if (!ifs) { + std::string log = "Cannot read memory tester output file: " + f; + cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl); + return; + } + std::string resultFileLocation; + cmSystemTools::GetLineFromStream(ifs, resultFileLocation); + this->AppendMemTesterOutput(res, resultFileLocation); + ifs.close(); + cmSystemTools::RemoveFile(f); + } +} + void cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res, std::string const& ofile) { diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index eda65f7b98..52667f8cfe 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -43,6 +43,7 @@ private: UNKNOWN = 0, VALGRIND, PURIFY, + DRMEMORY, BOUNDS_CHECKER, // checkers after here do not use the standard error list ADDRESS_SANITIZER, @@ -132,6 +133,8 @@ private: std::vector<int>& results); bool ProcessMemCheckValgrindOutput(const std::string& str, std::string& log, std::vector<int>& results); + bool ProcessMemCheckDrMemoryOutput(const std::string& str, std::string& log, + std::vector<int>& results); bool ProcessMemCheckPurifyOutput(const std::string& str, std::string& log, std::vector<int>& results); bool ProcessMemCheckSanitizerOutput(const std::string& str, std::string& log, @@ -142,6 +145,7 @@ private: void PostProcessTest(cmCTestTestResult& res, int test); void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test); + void PostProcessDrMemoryTest(cmCTestTestResult& res, int test); //! append MemoryTesterOutputFile to the test log void AppendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res, diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 02d396ebdc..37679b97f7 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -19,6 +19,8 @@ #include <utility> #include <vector> +#include <cmext/algorithm> + #include "cmsys/FStream.hxx" #include "cmsys/SystemInformation.hxx" @@ -171,9 +173,9 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) this->RunningCount += GetProcessorsUsed(test); cmCTestRunTest* testRun = new cmCTestRunTest(*this); - if (this->CTest->GetRepeatUntilFail()) { - testRun->SetRunUntilFailOn(); - testRun->SetNumberOfRuns(this->CTest->GetTestRepeat()); + if (this->RepeatMode != cmCTest::Repeat::Never) { + testRun->SetRepeatMode(this->RepeatMode); + testRun->SetNumberOfRuns(this->RepeatCount); } testRun->SetIndex(test); testRun->SetTestProperties(this->Properties[test]); @@ -788,7 +790,7 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList() // Sort tests within each level by COST and append them to the cost list. for (TestSet const& currentSet : cmReverseRange(priorityStack)) { TestList sortedCopy; - cmAppend(sortedCopy, currentSet); + cm::append(sortedCopy, currentSet); std::stable_sort(sortedCopy.begin(), sortedCopy.end(), TestComparator(this)); @@ -1154,7 +1156,7 @@ static Json::Value DumpCTestInfo( const std::vector<std::string>& args = testRun.GetArguments(); if (!args.empty()) { commandAndArgs.reserve(args.size() + 1); - cmAppend(commandAndArgs, args); + cm::append(commandAndArgs, args); } testInfo["command"] = DumpToJsonArray(commandAndArgs); } diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 1db4bfdd1b..483740138e 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -14,11 +14,11 @@ #include "cm_uv.h" +#include "cmCTest.h" #include "cmCTestResourceAllocator.h" #include "cmCTestTestHandler.h" #include "cmUVHandlePtr.h" -class cmCTest; struct cmCTestBinPackerAllocation; class cmCTestResourceSpec; class cmCTestRunTest; @@ -85,6 +85,12 @@ public: cmCTestTestHandler* GetTestHandler() { return this->TestHandler; } + void SetRepeatMode(cmCTest::Repeat mode, int count) + { + this->RepeatMode = mode; + this->RepeatCount = count; + } + void SetQuiet(bool b) { this->Quiet = b; } void InitResourceAllocator(const cmCTestResourceSpec& spec) @@ -179,6 +185,8 @@ protected: cmCTestTestHandler* TestHandler; cmCTest* CTest; bool HasCycles; + cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; + int RepeatCount = 1; bool Quiet; bool SerialTestRunning; }; diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index e2063e1786..1375be406c 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -7,9 +7,10 @@ #include <ostream> #include <utility> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" @@ -326,7 +327,7 @@ void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions) // The CTEST_P4_OPTIONS variable adds additional Perforce command line // options before the main command std::string opts = this->CTest->GetCTestConfiguration("P4Options"); - cmAppend(P4Options, cmSystemTools::ParseArguments(opts)); + cm::append(P4Options, cmSystemTools::ParseArguments(opts)); } CommandOptions.clear(); diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx index 237a745c9f..8f91efb454 100644 --- a/Source/CTest/cmCTestResourceSpec.cxx +++ b/Source/CTest/cmCTestResourceSpec.cxx @@ -16,21 +16,22 @@ static const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" }; static const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" }; -bool cmCTestResourceSpec::ReadFromJSONFile(const std::string& filename) +cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile( + const std::string& filename) { cmsys::ifstream fin(filename.c_str()); if (!fin) { - return false; + return ReadFileResult::FILE_NOT_FOUND; } Json::Value root; Json::CharReaderBuilder builder; if (!Json::parseFromStream(builder, fin, &root, nullptr)) { - return false; + return ReadFileResult::JSON_PARSE_ERROR; } if (!root.isObject()) { - return false; + return ReadFileResult::INVALID_ROOT; } int majorVersion = 1; @@ -39,42 +40,42 @@ bool cmCTestResourceSpec::ReadFromJSONFile(const std::string& filename) auto const& version = root["version"]; if (version.isObject()) { if (!version.isMember("major") || !version.isMember("minor")) { - return false; + return ReadFileResult::INVALID_VERSION; } auto const& major = version["major"]; auto const& minor = version["minor"]; if (!major.isInt() || !minor.isInt()) { - return false; + return ReadFileResult::INVALID_VERSION; } majorVersion = major.asInt(); minorVersion = minor.asInt(); } else { - return false; + return ReadFileResult::INVALID_VERSION; } } else { - return false; + return ReadFileResult::NO_VERSION; } if (majorVersion != 1 || minorVersion != 0) { - return false; + return ReadFileResult::UNSUPPORTED_VERSION; } auto const& local = root["local"]; if (!local.isArray()) { - return false; + return ReadFileResult::INVALID_SOCKET_SPEC; } if (local.size() > 1) { - return false; + return ReadFileResult::INVALID_SOCKET_SPEC; } if (local.empty()) { this->LocalSocket.Resources.clear(); - return true; + return ReadFileResult::READ_OK; } auto const& localSocket = local[0]; if (!localSocket.isObject()) { - return false; + return ReadFileResult::INVALID_SOCKET_SPEC; } std::map<std::string, std::vector<cmCTestResourceSpec::Resource>> resources; cmsys::RegularExpressionMatch match; @@ -88,21 +89,21 @@ bool cmCTestResourceSpec::ReadFromJSONFile(const std::string& filename) cmCTestResourceSpec::Resource resource; if (!item.isMember("id")) { - return false; + return ReadFileResult::INVALID_RESOURCE; } auto const& id = item["id"]; if (!id.isString()) { - return false; + return ReadFileResult::INVALID_RESOURCE; } resource.Id = id.asString(); if (!IdRegex.find(resource.Id.c_str(), match)) { - return false; + return ReadFileResult::INVALID_RESOURCE; } if (item.isMember("slots")) { auto const& capacity = item["slots"]; if (!capacity.isConvertibleTo(Json::uintValue)) { - return false; + return ReadFileResult::INVALID_RESOURCE; } resource.Capacity = capacity.asUInt(); } else { @@ -111,17 +112,55 @@ bool cmCTestResourceSpec::ReadFromJSONFile(const std::string& filename) r.push_back(resource); } else { - return false; + return ReadFileResult::INVALID_RESOURCE; } } } else { - return false; + return ReadFileResult::INVALID_RESOURCE_TYPE; } } } this->LocalSocket.Resources = std::move(resources); - return true; + return ReadFileResult::READ_OK; +} + +const char* cmCTestResourceSpec::ResultToString(ReadFileResult result) +{ + switch (result) { + case ReadFileResult::READ_OK: + return "OK"; + + case ReadFileResult::FILE_NOT_FOUND: + return "File not found"; + + case ReadFileResult::JSON_PARSE_ERROR: + return "JSON parse error"; + + case ReadFileResult::INVALID_ROOT: + return "Invalid root object"; + + case ReadFileResult::NO_VERSION: + return "No version specified"; + + case ReadFileResult::INVALID_VERSION: + return "Invalid version object"; + + case ReadFileResult::UNSUPPORTED_VERSION: + return "Unsupported version"; + + case ReadFileResult::INVALID_SOCKET_SPEC: + return "Invalid socket object"; + + case ReadFileResult::INVALID_RESOURCE_TYPE: + return "Invalid resource type object"; + + case ReadFileResult::INVALID_RESOURCE: + return "Invalid resource object"; + + default: + return "Unknown"; + } } bool cmCTestResourceSpec::operator==(const cmCTestResourceSpec& other) const diff --git a/Source/CTest/cmCTestResourceSpec.h b/Source/CTest/cmCTestResourceSpec.h index 4646db84cd..cb242c0507 100644 --- a/Source/CTest/cmCTestResourceSpec.h +++ b/Source/CTest/cmCTestResourceSpec.h @@ -31,7 +31,22 @@ public: Socket LocalSocket; - bool ReadFromJSONFile(const std::string& filename); + enum class ReadFileResult + { + READ_OK, + FILE_NOT_FOUND, + JSON_PARSE_ERROR, + INVALID_ROOT, + NO_VERSION, + INVALID_VERSION, + UNSUPPORTED_VERSION, + INVALID_SOCKET_SPEC, // Can't be INVALID_SOCKET due to a Windows macro + INVALID_RESOURCE_TYPE, + INVALID_RESOURCE, + }; + + ReadFileResult ReadFromJSONFile(const std::string& filename); + static const char* ResultToString(ReadFileResult result); bool operator==(const cmCTestResourceSpec& other) const; bool operator!=(const cmCTestResourceSpec& other) const; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 3091050f38..cc5de43a9d 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -34,9 +34,6 @@ cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler) this->TestResult.Status = cmCTestTestHandler::NOT_RUN; this->TestResult.TestCount = 0; this->TestResult.Properties = nullptr; - this->NumberOfRunsLeft = 1; // default to 1 run of the test - this->RunUntilFail = false; // default to run the test once - this->RunAgain = false; // default to not having to run again } void cmCTestRunTest::CheckOutput(std::string const& line) @@ -310,7 +307,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) } // If the test does not need to rerun push the current TestResult onto the // TestHandler vector - if (!this->NeedsToRerun()) { + if (!this->NeedsToRepeat()) { this->TestHandler->TestResults.push_back(this->TestResult); } this->TestProcess.reset(); @@ -336,17 +333,21 @@ bool cmCTestRunTest::StartAgain(size_t completed) return true; } -bool cmCTestRunTest::NeedsToRerun() +bool cmCTestRunTest::NeedsToRepeat() { this->NumberOfRunsLeft--; if (this->NumberOfRunsLeft == 0) { return false; } // if number of runs left is not 0, and we are running until - // we find a failed test, then return true so the test can be + // we find a failed (or passed) test, then return true so the test can be // restarted - if (this->RunUntilFail && - this->TestResult.Status == cmCTestTestHandler::COMPLETED) { + if ((this->RepeatMode == cmCTest::Repeat::UntilFail && + this->TestResult.Status == cmCTestTestHandler::COMPLETED) || + (this->RepeatMode == cmCTest::Repeat::UntilPass && + this->TestResult.Status != cmCTestTestHandler::COMPLETED) || + (this->RepeatMode == cmCTest::Repeat::AfterTimeout && + this->TestResult.Status == cmCTestTestHandler::TIMEOUT)) { this->RunAgain = true; return true; } @@ -746,7 +747,12 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) // then it will never print out the completed / total, same would // got for run until pass. Trick is when this is called we don't // yet know if we are passing or failing. - if (this->NumberOfRunsLeft == 1 || this->CTest->GetTestProgressOutput()) { + bool const progressOnLast = + (this->RepeatMode != cmCTest::Repeat::UntilPass && + this->RepeatMode != cmCTest::Repeat::AfterTimeout); + if ((progressOnLast && this->NumberOfRunsLeft == 1) || + (!progressOnLast && this->NumberOfRunsLeft == this->NumberOfRunsTotal) || + this->CTest->GetTestProgressOutput()) { outputStream << std::setw(getNumWidth(total)) << completed << "/"; outputStream << std::setw(getNumWidth(total)) << total << " "; } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index f781c7ab0d..7eeaebd8dc 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -13,13 +13,12 @@ #include <stddef.h> +#include "cmCTest.h" #include "cmCTestMultiProcessHandler.h" #include "cmCTestTestHandler.h" #include "cmDuration.h" #include "cmProcess.h" -class cmCTest; - /** \class cmRunTest * \brief represents a single test to be run * @@ -30,8 +29,13 @@ class cmCTestRunTest public: explicit cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler); - void SetNumberOfRuns(int n) { this->NumberOfRunsLeft = n; } - void SetRunUntilFailOn() { this->RunUntilFail = true; } + void SetNumberOfRuns(int n) + { + this->NumberOfRunsLeft = n; + this->NumberOfRunsTotal = n; + } + + void SetRepeatMode(cmCTest::Repeat r) { this->RepeatMode = r; } void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties* prop) { this->TestProperties = prop; @@ -98,7 +102,7 @@ public: } private: - bool NeedsToRerun(); + bool NeedsToRepeat(); void DartProcessing(); void ExeNotFound(std::string exe); bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout, @@ -132,9 +136,10 @@ private: std::vector<std::map< std::string, std::vector<cmCTestMultiProcessHandler::ResourceAllocation>>> AllocatedResources; - bool RunUntilFail; - int NumberOfRunsLeft; - bool RunAgain; + cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; + int NumberOfRunsLeft = 1; // default to 1 run of the test + int NumberOfRunsTotal = 1; // default to 1 run of the test + bool RunAgain = false; // default to not having to run again size_t TotalNumberOfTests; }; diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 34395c9fe0..44dfab2e60 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -7,9 +7,10 @@ #include <map> #include <ostream> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" @@ -271,7 +272,7 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters, std::vector<char const*> args; args.push_back(this->CommandLineTool.c_str()); - cmAppend(args, parameters); + cm::append(args, parameters); args.push_back("--non-interactive"); std::string userOptions = this->CTest->GetCTestConfiguration("SVNOptions"); @@ -344,7 +345,7 @@ private: void CharacterDataHandler(const char* data, int length) override { - cmAppend(this->CData, data, data + length); + cm::append(this->CData, data, data + length); } void EndElement(const std::string& name) override diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 60facbdf53..7803e3764a 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -340,6 +340,13 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) this->SetRunCurrentScript(true); this->UpdateElapsedTime(); + // set the CTEST_CONFIGURATION_TYPE variable to the current value of the + // the -C argument on the command line. + if (!this->CTest->GetConfigType().empty()) { + this->Makefile->AddDefinition("CTEST_CONFIGURATION_TYPE", + this->CTest->GetConfigType()); + } + // add the script arg if defined if (!script_arg.empty()) { this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg); diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 46b00b1685..acb75b2edd 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -7,6 +7,7 @@ #include <utility> #include <cm/memory> +#include <cm/vector> #include "cm_static_string_view.hxx" @@ -174,7 +175,7 @@ void cmCTestSubmitCommand::CheckArguments( this->PartsMentioned = !this->Parts.empty() || cmContains(keywords, "PARTS"); this->FilesMentioned = !this->Files.empty() || cmContains(keywords, "FILES"); - cmEraseIf(this->Parts, [this](std::string const& arg) -> bool { + cm::erase_if(this->Parts, [this](std::string const& arg) -> bool { cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str()); if (p == cmCTest::PartCount) { std::ostringstream e; @@ -185,7 +186,7 @@ void cmCTestSubmitCommand::CheckArguments( return false; }); - cmEraseIf(this->Files, [this](std::string const& arg) -> bool { + cm::erase_if(this->Files, [this](std::string const& arg) -> bool { if (!cmSystemTools::FileExists(arg)) { std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 2ac5af691a..a8f201a8a8 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -7,6 +7,8 @@ #include <cstdlib> #include <sstream> +#include <cmext/algorithm> + #include "cm_curl.h" #include "cm_jsoncpp_reader.h" #include "cm_jsoncpp_value.h" @@ -65,7 +67,7 @@ private: void CharacterDataHandler(const char* data, int length) override { - cmAppend(this->CurrentValue, data, data + length); + cm::append(this->CurrentValue, data, data + length); } void EndElement(const std::string& name) override @@ -96,8 +98,8 @@ static size_t cmCTestSubmitHandlerWriteMemoryCallback(void* ptr, size_t size, { int realsize = static_cast<int>(size * nmemb); const char* chPtr = static_cast<char*>(ptr); - cmAppend(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, - chPtr + realsize); + cm::append(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, + chPtr + realsize); return realsize; } @@ -106,8 +108,8 @@ static size_t cmCTestSubmitHandlerCurlDebugCallback(CURL* /*unused*/, char* chPtr, size_t size, void* data) { - cmAppend(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, - chPtr + size); + cm::append(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, + chPtr + size); return size; } @@ -768,7 +770,7 @@ int cmCTestSubmitHandler::ProcessHandler() if (!this->Files.empty()) { // Submit the explicitly selected files: - cmAppend(files, this->Files); + cm::append(files, this->Files); } // Add to the list of files to submit from any selected, existing parts: @@ -814,7 +816,7 @@ int cmCTestSubmitHandler::ProcessHandler() } // Submit files from this part. - cmAppend(files, this->CTest->GetSubmitFiles(p)); + cm::append(files, this->CTest->GetSubmitFiles(p)); } // Make sure files are unique, but preserve order. diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 9784214053..0f9b6958df 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -29,6 +29,7 @@ void cmCTestTestCommand::BindArguments() this->Bind("EXCLUDE_FIXTURE_SETUP"_s, this->ExcludeFixtureSetup); this->Bind("EXCLUDE_FIXTURE_CLEANUP"_s, this->ExcludeFixtureCleanup); this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel); + this->Bind("REPEAT"_s, this->Repeat); this->Bind("SCHEDULE_RANDOM"_s, this->ScheduleRandom); this->Bind("STOP_TIME"_s, this->StopTime); this->Bind("TEST_LOAD"_s, this->TestLoad); @@ -85,6 +86,9 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() if (!this->ParallelLevel.empty()) { handler->SetOption("ParallelLevel", this->ParallelLevel.c_str()); } + if (!this->Repeat.empty()) { + handler->SetOption("Repeat", this->Repeat.c_str()); + } if (!this->ScheduleRandom.empty()) { handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str()); } diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index 4019694b2e..2345afbcfe 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -55,6 +55,7 @@ protected: std::string ExcludeFixtureSetup; std::string ExcludeFixtureCleanup; std::string ParallelLevel; + std::string Repeat; std::string ScheduleRandom; std::string StopTime; std::string TestLoad; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 8e3ac22639..e70bc5a76d 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -471,6 +471,30 @@ bool cmCTestTestHandler::ProcessOptions() if (cmIsOn(this->GetOption("ScheduleRandom"))) { this->CTest->SetScheduleType("Random"); } + if (const char* repeat = this->GetOption("Repeat")) { + cmsys::RegularExpression repeatRegex( + "^(UNTIL_FAIL|UNTIL_PASS|AFTER_TIMEOUT):([0-9]+)$"); + if (repeatRegex.find(repeat)) { + std::string const& count = repeatRegex.match(2); + unsigned long n = 1; + cmStrToULong(count, &n); // regex guarantees success + this->RepeatCount = static_cast<int>(n); + if (this->RepeatCount > 1) { + std::string const& mode = repeatRegex.match(1); + if (mode == "UNTIL_FAIL") { + this->RepeatMode = cmCTest::Repeat::UntilFail; + } else if (mode == "UNTIL_PASS") { + this->RepeatMode = cmCTest::Repeat::UntilPass; + } else if (mode == "AFTER_TIMEOUT") { + this->RepeatMode = cmCTest::Repeat::AfterTimeout; + } + } + } else { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Repeat option invalid value: " << repeat << std::endl); + return false; + } + } if (this->GetOption("ParallelLevel")) { this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel"))); } @@ -513,9 +537,13 @@ bool cmCTestTestHandler::ProcessOptions() val = this->GetOption("ResourceSpecFile"); if (val) { this->UseResourceSpec = true; - if (!this->ResourceSpec.ReadFromJSONFile(val)) { + auto result = this->ResourceSpec.ReadFromJSONFile(val); + if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) { cmCTestLog(this->CTest, ERROR_MESSAGE, - "Could not read resource spec file: " << val << std::endl); + "Could not read/parse resource spec file " + << val << ": " + << cmCTestResourceSpec::ResultToString(result) + << std::endl); return false; } } @@ -1231,6 +1259,12 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, parallel->SetCTest(this->CTest); parallel->SetParallelLevel(this->CTest->GetParallelLevel()); parallel->SetTestHandler(this); + if (this->RepeatMode != cmCTest::Repeat::Never) { + parallel->SetRepeatMode(this->RepeatMode, this->RepeatCount); + } else { + parallel->SetRepeatMode(this->CTest->GetRepeatMode(), + this->CTest->GetRepeatCount()); + } parallel->SetQuiet(this->Quiet); if (this->TestLoad > 0) { parallel->SetTestLoad(this->TestLoad); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index eab75d0eb8..55237f9b3a 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -18,12 +18,12 @@ #include "cmsys/RegularExpression.hxx" +#include "cmCTest.h" #include "cmCTestGenericHandler.h" #include "cmCTestResourceSpec.h" #include "cmDuration.h" #include "cmListFileCache.h" -class cmCTest; class cmMakefile; class cmXMLWriter; @@ -353,6 +353,8 @@ private: std::ostream* LogFile; + cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; + int RepeatCount = 1; bool RerunFailed; }; diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx index d0e3848a08..eaef1ca6af 100644 --- a/Source/CTest/cmCTestUploadCommand.cxx +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -4,11 +4,11 @@ #include <set> #include <sstream> -#include <vector> + +#include <cm/vector> #include "cm_static_string_view.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestUploadHandler.h" #include "cmMakefile.h" @@ -24,7 +24,7 @@ void cmCTestUploadCommand::BindArguments() void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&) { - cmEraseIf(this->Files, [this](std::string const& arg) -> bool { + cm::erase_if(this->Files, [this](std::string const& arg) -> bool { if (!cmSystemTools::FileExists(arg)) { std::ostringstream e; e << "File \"" << arg << "\" does not exist. Cannot submit " diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 87f7147bc9..2ec9622dca 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -6,9 +6,10 @@ #include <iostream> #include <string> +#include <cmext/algorithm> + #include "cmsys/Process.h" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestRunTest.h" #include "cmCTestTestHandler.h" @@ -218,7 +219,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) if (nread > 0) { std::string strdata; this->Conv.DecodeText(buf->base, static_cast<size_t>(nread), strdata); - cmAppend(this->Output, strdata); + cm::append(this->Output, strdata); while (this->Output.GetLine(line)) { this->Runner.CheckOutput(line); diff --git a/Source/Checks/Curses.cmake b/Source/Checks/Curses.cmake index 2942b666ae..d35dd2a6e1 100644 --- a/Source/Checks/Curses.cmake +++ b/Source/Checks/Curses.cmake @@ -1,4 +1,7 @@ -message(STATUS "Checking for curses support") +include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) +cm_message_checks_compat( + "Checking for curses support" __checkStart __checkPass __checkFail) +message(${__checkStart}) # Try compiling a simple project using curses. # Pass in any cache entries that the user may have set. @@ -31,11 +34,11 @@ set(CMakeCheckCurses_COMPILED "${CMakeCheckCurses_COMPILED}") unset(CMakeCheckCurses_COMPILED CACHE) if(CMakeCheckCurses_COMPILED) - message(STATUS "Checking for curses support - Success") + message(${__checkPass} "Success") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Checking for curses support passed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n") else() - message(STATUS "Checking for curses support - Failed") + message(${__checkFail} "Failed") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Checking for curses support failed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n") endif() diff --git a/Source/Checks/cm_c11_thread_local.cmake b/Source/Checks/cm_c11_thread_local.cmake index 6b8d10b2bd..2263be3bad 100644 --- a/Source/Checks/cm_c11_thread_local.cmake +++ b/Source/Checks/cm_c11_thread_local.cmake @@ -1,7 +1,11 @@ set(CMake_C11_THREAD_LOCAL_BROKEN 0) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION) if(NOT DEFINED CMake_C11_THREAD_LOCAL_WORKS) - message(STATUS "Checking if compiler supports C11 _Thread_local") + include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) + cm_message_checks_compat( + "Checking if compiler supports C11 _Thread_local" + __checkStart __checkPass __checkFail) + message(${__checkStart}) try_compile(CMake_C11_THREAD_LOCAL_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/cm_c11_thread_local.c @@ -12,14 +16,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION) set_property(CACHE CMake_C11_THREAD_LOCAL_WORKS PROPERTY VALUE 0) endif() if(CMake_C11_THREAD_LOCAL_WORKS) - message(STATUS "Checking if compiler supports C11 _Thread_local - yes") + message(${__checkPass} "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if compiler supports C11 _Thread_local passed with the following output:\n" "${OUTPUT}\n" "\n" ) else() - message(STATUS "Checking if compiler supports C11 _Thread_local - no") + message(${__checkFail} "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler supports C11 _Thread_local failed with the following output:\n" "${OUTPUT}\n" diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake index 38606b9c90..e5656bf4ed 100644 --- a/Source/Checks/cm_cxx14_check.cmake +++ b/Source/Checks/cm_cxx14_check.cmake @@ -1,10 +1,14 @@ set(CMake_CXX14_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel") if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION) set(CMake_CXX14_WORKS 0) endif() if(NOT DEFINED CMake_CXX14_WORKS) - message(STATUS "Checking if compiler supports needed C++14 constructs") + include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) + cm_message_checks_compat( + "Checking if compiler supports needed C++14 constructs" + __checkStart __checkPass __checkFail) + message(${__checkStart}) try_compile(CMake_CXX14_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/cm_cxx14_check.cpp @@ -15,14 +19,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") set_property(CACHE CMake_CXX14_WORKS PROPERTY VALUE 0) endif() if(CMake_CXX14_WORKS) - message(STATUS "Checking if compiler supports needed C++14 constructs - yes") + message(${__checkPass} "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if compiler supports needed C++14 constructs passed with the following output:\n" "${OUTPUT}\n" "\n" ) else() - message(STATUS "Checking if compiler supports needed C++14 constructs - no") + message(${__checkFail} "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler supports needed C++14 constructs failed with the following output:\n" "${OUTPUT}\n" diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake index 4da2fd7cac..dba3eaf3b3 100644 --- a/Source/Checks/cm_cxx17_check.cmake +++ b/Source/Checks/cm_cxx17_check.cmake @@ -1,10 +1,14 @@ set(CMake_CXX17_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel") if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION) set(CMake_CXX17_WORKS 0) endif() if(NOT DEFINED CMake_CXX17_WORKS) - message(STATUS "Checking if compiler supports needed C++17 constructs") + include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) + cm_message_checks_compat( + "Checking if compiler supports needed C++17 constructs" + __checkStart __checkPass __checkFail) + message(${__checkStart}) try_compile(CMake_CXX17_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/cm_cxx17_check.cpp @@ -15,14 +19,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") set_property(CACHE CMake_CXX17_WORKS PROPERTY VALUE 0) endif() if(CMake_CXX17_WORKS) - message(STATUS "Checking if compiler supports needed C++17 constructs - yes") + message(${__checkPass} "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if compiler supports needed C++17 constructs passed with the following output:\n" "${OUTPUT}\n" "\n" ) else() - message(STATUS "Checking if compiler supports needed C++17 constructs - no") + message(${__checkFail} "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler supports needed C++17 constructs failed with the following output:\n" "${OUTPUT}\n" diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp index 29863b136b..abbe22cf6f 100644 --- a/Source/Checks/cm_cxx17_check.cpp +++ b/Source/Checks/cm_cxx17_check.cpp @@ -8,6 +8,13 @@ # include <comdef.h> #endif +template <typename T, + typename std::invoke_result<decltype(&T::get), T>::type = nullptr> +typename T::pointer get_ptr(T& item) +{ + return item.get(); +} + int main() { int a[] = { 0, 1, 2 }; @@ -20,6 +27,9 @@ int main() std::unique_ptr<int> u(new int(0)); + // Intel compiler do not handle correctly 'decltype' inside 'invoke_result' + get_ptr(u); + #ifdef _MSC_VER // clang-cl has problems instantiating this constructor in C++17 mode // error: indirection requires pointer operand ('const _GUID' invalid) diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index fb68ed78c9..3b00dfb13e 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -1,8 +1,12 @@ +include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) function(cm_check_cxx_feature name) string(TOUPPER ${name} FEATURE) if(NOT DEFINED CMake_HAVE_CXX_${FEATURE}) - message(STATUS "Checking if compiler supports C++ ${name}") + cm_message_checks_compat( + "Checking if compiler supports C++ ${name}" + __checkStart __checkPass __checkFail) + message(${__checkStart}) if(CMAKE_CXX_STANDARD) set(maybe_cxx_standard -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}) else() @@ -26,19 +30,21 @@ function(cm_check_cxx_feature name) string(REGEX REPLACE "[^\n]*warning:[^\n]*sprintf\\(\\) is often misused, please use snprintf[^\n]*" "" check_output "${check_output}") # Filter out xcodebuild warnings. string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}") + # Filter out ld warnings. + string(REGEX REPLACE "[^\n]*ld: warning: [^\n]*" "" check_output "${check_output}") # If using the feature causes warnings, treat it as broken/unavailable. if(check_output MATCHES "(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]") set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE) endif() if(CMake_HAVE_CXX_${FEATURE}) - message(STATUS "Checking if compiler supports C++ ${name} - yes") + message(${__checkPass} "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if compiler supports C++ ${name} passed with the following output:\n" "${OUTPUT}\n" "\n" ) else() - message(STATUS "Checking if compiler supports C++ ${name} - no") + message(${__checkFail} "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler supports C++ ${name} failed with the following output:\n" "${OUTPUT}\n" diff --git a/Source/Checks/cm_message_checks_compat.cmake b/Source/Checks/cm_message_checks_compat.cmake new file mode 100644 index 0000000000..024c397a8b --- /dev/null +++ b/Source/Checks/cm_message_checks_compat.cmake @@ -0,0 +1,13 @@ +# Supporting using the CHECK_... message modes if available +# and fall back to the older behavior if not +macro(cm_message_checks_compat description startVar passVar failVar) + if(CMAKE_VERSION VERSION_GREATER 3.16.2019) + set(${startVar} CHECK_START "${description}") + set(${passVar} CHECK_PASS) + set(${failVar} CHECK_FAIL) + else() + set(${startVar} STATUS "${description}") + set(${passVar} STATUS "${description} - ") + set(${failVar} STATUS "${description} - ") + endif() +endmacro() diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt index 7009717511..c24ee76216 100644 --- a/Source/CursesDialog/CMakeLists.txt +++ b/Source/CursesDialog/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(ccmake ccmake.cxx cmCursesBoolWidget.cxx cmCursesCacheEntryComposite.cxx + cmCursesColor.cxx cmCursesDummyWidget.cxx cmCursesFilePathWidget.cxx cmCursesForm.cxx @@ -17,21 +18,45 @@ add_executable(ccmake cmCursesWidget.cxx ) target_include_directories(ccmake PRIVATE ${CURSES_INCLUDE_PATH}) +set(CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_PATH}) target_link_libraries(ccmake CMakeLib) if(CMAKE_USE_SYSTEM_FORM) find_path(CURSES_FORM_INCLUDE_DIR NAMES form.h HINTS ${CURSES_INCLUDE_PATH} ${CURSES_INCLUDE_PATH}/ncurses) if(CURSES_FORM_INCLUDE_DIR) target_include_directories(ccmake PRIVATE ${CURSES_FORM_INCLUDE_DIR}) + list(APPEND CMAKE_REQUIRED_INCLUDES ${CURSES_FORM_INCLUDE_DIR}) endif() target_link_libraries(ccmake ${CURSES_FORM_LIBRARY} ${CURSES_LIBRARY} ) + set(CMAKE_REQUIRED_LIBRARIES + ${CURSES_FORM_LIBRARY} + ${CURSES_LIBRARY} + ) if(CURSES_EXTRA_LIBRARY) target_link_libraries(ccmake ${CURSES_EXTRA_LIBRARY}) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${CURSES_EXTRA_LIBRARY}) endif() else() target_link_libraries(ccmake cmForm) + get_target_property(cmFormIncludeDirs cmForm INTERFACE_INCLUDE_DIRECTORIES) + list(APPEND CMAKE_REQUIRED_INCLUDES ${cmFormIncludeDirs}) + get_target_property(cmFormLibraries cmForm INTERFACE_LINK_LIBRARIES) + set(CMAKE_REQUIRED_LIBRARIES ${cmFormLibraries}) +endif() + +include(CheckSymbolExists) +check_symbol_exists(use_default_colors + "form.h" + HAVE_CURSES_USE_DEFAULT_COLORS) +if(HAVE_CURSES_USE_DEFAULT_COLORS) + set_source_files_properties(cmCursesColor.cxx + PROPERTIES COMPILE_DEFINITIONS HAVE_CURSES_USE_DEFAULT_COLORS) +endif() + +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET ccmake PROPERTY JOB_POOL_LINK "link-bin") endif() CMake_OPTIONAL_COMPONENT(ccmake) diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 9e9dfbd195..01fce85454 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -9,6 +9,7 @@ #include "cmsys/Encoding.hxx" +#include "cmCursesColor.h" #include "cmCursesForm.h" #include "cmCursesMainForm.h" #include "cmCursesStandardIncludes.h" @@ -126,6 +127,7 @@ int main(int argc, char const* const* argv) noecho(); /* Echo off */ cbreak(); /* nl- or cr not needed */ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ + cmCursesColor::InitColors(); signal(SIGWINCH, onsig); @@ -153,10 +155,28 @@ int main(int argc, char const* const* argv) return 1; } + /* + * The message is stored in a list by the form which will be + * joined by '\n' before display. + * Removing any trailing '\n' avoid extra empty lines in the final results + */ + auto cleanMessage = [](const std::string& message) -> std::string { + auto msg = message; + if (!msg.empty() && msg.back() == '\n') { + msg.pop_back(); + } + return msg; + }; cmSystemTools::SetMessageCallback( - [myform](const std::string& message, const char* title) { - myform->AddError(message, title); + [&](const std::string& message, const char* title) { + myform->AddError(cleanMessage(message), title); }); + cmSystemTools::SetStderrCallback([&](const std::string& message) { + myform->AddError(cleanMessage(message), ""); + }); + cmSystemTools::SetStdoutCallback([&](const std::string& message) { + myform->UpdateProgress(cleanMessage(message), -1); + }); cmCursesForm::CurrentForm = myform; diff --git a/Source/CursesDialog/cmCursesBoolWidget.cxx b/Source/CursesDialog/cmCursesBoolWidget.cxx index 97b0811288..c4dbed8350 100644 --- a/Source/CursesDialog/cmCursesBoolWidget.cxx +++ b/Source/CursesDialog/cmCursesBoolWidget.cxx @@ -4,6 +4,7 @@ #include <string> +#include "cmCursesColor.h" #include "cmCursesWidget.h" #include "cmStateTypes.h" @@ -12,8 +13,10 @@ cmCursesBoolWidget::cmCursesBoolWidget(int width, int height, int left, : cmCursesWidget(width, height, left, top) { this->Type = cmStateEnums::BOOL; - set_field_fore(this->Field, A_NORMAL); - set_field_back(this->Field, A_STANDOUT); + if (!cmCursesColor::HasColors()) { + set_field_fore(this->Field, A_NORMAL); + set_field_back(this->Field, A_STANDOUT); + } field_opts_off(this->Field, O_STATIC); this->SetValueAsBool(false); } @@ -42,8 +45,16 @@ void cmCursesBoolWidget::SetValueAsBool(bool value) { if (value) { this->SetValue("ON"); + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::BoolOn)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::BoolOn)); + } } else { this->SetValue("OFF"); + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::BoolOff)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::BoolOff)); + } } } diff --git a/Source/CursesDialog/cmCursesColor.cxx b/Source/CursesDialog/cmCursesColor.cxx new file mode 100644 index 0000000000..641d48ccec --- /dev/null +++ b/Source/CursesDialog/cmCursesColor.cxx @@ -0,0 +1,29 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCursesColor.h" + +#include "cmCursesStandardIncludes.h" + +bool cmCursesColor::HasColors() +{ +#ifdef HAVE_CURSES_USE_DEFAULT_COLORS + return has_colors(); +#else + return false; +#endif +} + +void cmCursesColor::InitColors() +{ +#ifdef HAVE_CURSES_USE_DEFAULT_COLORS + if (HasColors()) { + start_color(); + use_default_colors(); + init_pair(cmCursesColor::BoolOff, COLOR_RED, -1); + init_pair(cmCursesColor::BoolOn, COLOR_GREEN, -1); + init_pair(cmCursesColor::String, COLOR_BLUE, -1); + init_pair(cmCursesColor::Path, COLOR_YELLOW, -1); + init_pair(cmCursesColor::Options, COLOR_MAGENTA, -1); + } +#endif +} diff --git a/Source/CursesDialog/cmCursesColor.h b/Source/CursesDialog/cmCursesColor.h new file mode 100644 index 0000000000..78ca52cbb1 --- /dev/null +++ b/Source/CursesDialog/cmCursesColor.h @@ -0,0 +1,24 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCursesColor_h +#define cmCursesColor_h + +class cmCursesColor +{ +public: + enum Color + { + // Default color is pair 0 + BoolOff = 1, + BoolOn, + String, + Path, + Options + }; + + static bool HasColors(); + + static void InitColors(); +}; + +#endif // cmCursesColor_h diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index e2d8d06b49..806e663e9e 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -8,6 +8,7 @@ #include "cmCursesForm.h" #include "cmCursesMainForm.h" #include "cmCursesStandardIncludes.h" +#include "cmStringAlgorithms.h" #include "cmVersion.h" inline int ctrl(int z) @@ -16,14 +17,12 @@ inline int ctrl(int z) } cmCursesLongMessageForm::cmCursesLongMessageForm( - std::vector<std::string> const& messages, const char* title) + std::vector<std::string> const& messages, const char* title, + ScrollBehavior scrollBehavior) + : Scrolling(scrollBehavior) { // Append all messages into on big string - for (std::string const& message : messages) { - this->Messages += message; - // Add one blank line after each message - this->Messages += "\n\n"; - } + this->Messages = cmJoin(messages, "\n"); this->Title = title; this->Fields[0] = nullptr; this->Fields[1] = nullptr; @@ -48,7 +47,7 @@ void cmCursesLongMessageForm::UpdateStatusBar() size = cmCursesMainForm::MAX_WIDTH - 1; } strncpy(bar, this->Title.c_str(), size); - for (size_t i = size - 1; i < cmCursesMainForm::MAX_WIDTH; i++) { + for (size_t i = size; i < cmCursesMainForm::MAX_WIDTH; i++) { bar[i] = ' '; } int width; @@ -89,7 +88,7 @@ void cmCursesLongMessageForm::PrintKeys() return; } char firstLine[512]; - sprintf(firstLine, "Press [e] to exit help"); + sprintf(firstLine, "Press [e] to exit screen"); char fmt_s[] = "%s"; curses_move(y - 2, 0); @@ -112,8 +111,6 @@ void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/, const char* msg = this->Messages.c_str(); - curses_clear(); - if (this->Fields[0]) { free_field(this->Fields[0]); this->Fields[0] = nullptr; @@ -136,10 +133,13 @@ void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/, } i++; } - form_driver(this->Form, REQ_BEG_FIELD); + if (this->Scrolling == ScrollBehavior::ScrollDown) { + form_driver(this->Form, REQ_END_FIELD); + } else { + form_driver(this->Form, REQ_BEG_FIELD); + } this->UpdateStatusBar(); - this->PrintKeys(); touchwin(stdscr); refresh(); } @@ -153,6 +153,7 @@ void cmCursesLongMessageForm::HandleInput() char debugMessage[128]; for (;;) { + this->PrintKeys(); int key = getch(); sprintf(debugMessage, "Message widget handling input, key: %d", key); @@ -173,7 +174,6 @@ void cmCursesLongMessageForm::HandleInput() } this->UpdateStatusBar(); - this->PrintKeys(); touchwin(stdscr); wrefresh(stdscr); } diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h index 42f9c710b7..88efe62173 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.h +++ b/Source/CursesDialog/cmCursesLongMessageForm.h @@ -14,8 +14,14 @@ class cmCursesLongMessageForm : public cmCursesForm { public: + enum class ScrollBehavior + { + NoScroll, + ScrollDown + }; + cmCursesLongMessageForm(std::vector<std::string> const& messages, - const char* title); + const char* title, ScrollBehavior scrollBehavior); ~cmCursesLongMessageForm() override; cmCursesLongMessageForm(cmCursesLongMessageForm const&) = delete; @@ -43,6 +49,7 @@ public: protected: std::string Messages; std::string Title; + ScrollBehavior Scrolling; FIELD* Fields[2]; }; diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 6b71e8a10a..2c92835159 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -34,6 +34,7 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args, : Args(std::move(args)) , InitialWidth(initWidth) { + this->HasNonStatusOutputs = false; this->NumberOfPages = 0; this->AdvancedMode = false; this->NumberOfVisibleEntries = 0; @@ -321,25 +322,25 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */) } else { if (this->OkToGenerate) { sprintf(firstLine, - "Press [c] to configure Press [g] to generate and exit"); + " [l] Show log output [c] Configure" + " [g] Generate "); } else { sprintf(firstLine, - "Press [c] to configure "); + " [l] Show log output [c] Configure" + " "); } { const char* toggleKeyInstruction = - "Press [t] to toggle advanced mode (Currently %s)"; + " [t] Toggle advanced mode (currently %s)"; sprintf(thirdLine, toggleKeyInstruction, - this->AdvancedMode ? "On" : "Off"); + this->AdvancedMode ? "on" : "off"); } sprintf(secondLine, - "Press [h] for help " - "Press [q] to quit without generating"); + " [h] Help [q] Quit without generating"); } curses_move(y - 4, 0); - char fmt[512] = - "Press [enter] to edit option Press [d] to delete an entry"; + char fmt[512] = "Keys: [enter] Edit an entry [d] Delete an entry"; if (process) { memset(fmt, ' ', 57); } @@ -364,7 +365,7 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */) // Print the key of the current entry and the CMake version // on the status bar. Designed for a width of 80 chars. -void cmCursesMainForm::UpdateStatusBar(const char* message) +void cmCursesMainForm::UpdateStatusBar(cm::optional<std::string> message) { int x; int y; @@ -385,119 +386,91 @@ void cmCursesMainForm::UpdateStatusBar(const char* message) return; } - // Get the key of the current entry - FIELD* cur = current_field(this->Form); - int findex = field_index(cur); - cmCursesWidget* lbl = nullptr; - if (findex >= 0) { - lbl = reinterpret_cast<cmCursesWidget*>( - field_userptr(this->Fields[findex - 2])); - } - char help[128] = ""; - const char* curField = ""; - if (lbl) { - curField = lbl->GetValue(); + // Find the current label index + // Field are grouped by 3, the label should be 2 less than the current index + using size_type = decltype(this->Fields)::size_type; + size_type currentLabelIndex = field_index(current_field(this->Form)) - 2; + + // Use the status message if any, otherwise join the key and help string + std::string bar; + if (message) { + bar = *message; + } else { + // Get the key of the current entry + cmCursesWidget* labelWidget = reinterpret_cast<cmCursesWidget*>( + field_userptr(this->Fields[currentLabelIndex])); + std::string labelValue = labelWidget->GetValue(); + bar = labelValue + ": "; // Get the help string of the current entry // and add it to the help string - const char* existingValue = - this->CMakeInstance->GetState()->GetCacheEntryValue(curField); + auto cmakeState = this->CMakeInstance->GetState(); + const char* existingValue = cmakeState->GetCacheEntryValue(labelValue); if (existingValue) { - const char* hs = this->CMakeInstance->GetState()->GetCacheEntryProperty( - curField, "HELPSTRING"); - if (hs) { - strncpy(help, hs, 127); - help[127] = '\0'; - } else { - help[0] = 0; + auto help = cmakeState->GetCacheEntryProperty(labelValue, "HELPSTRING"); + if (help) { + bar += help; } - } else { - sprintf(help, " "); } } + // Pad with spaces to erase any previous text, + // or truncate as necessary to fit the screen + bar.resize(x, ' '); + curses_move(y - 5, 0); + attron(A_STANDOUT); + char fmt_s[] = "%s"; + printw(fmt_s, bar.c_str()); + attroff(A_STANDOUT); - // Join the key, help string and pad with spaces - // (or truncate) as necessary - char bar[cmCursesMainForm::MAX_WIDTH]; - size_t curFieldLen = strlen(curField); - size_t helpLen = strlen(help); - - size_t width = std::min<size_t>(x, cmCursesMainForm::MAX_WIDTH); - - if (message) { - curField = message; - curFieldLen = strlen(message); - strncpy(bar, curField, width); - if (curFieldLen < width) { - memset(bar + curFieldLen, ' ', width - curFieldLen); - } - } else { - strncpy(bar, curField, width); - if (curFieldLen < width) { - bar[curFieldLen] = ':'; - bar[curFieldLen + 1] = ' '; - strncpy(bar + curFieldLen + 2, help, width - curFieldLen - 2); - if (curFieldLen + helpLen + 2 < width) { - memset(bar + curFieldLen + helpLen + 2, ' ', - width - (curFieldLen + helpLen + 2)); - } - } + // Highlight the current label, reset others + // Fields are grouped by 3, the first one being the label + // so start at 0 and move up by 3 avoiding the last null entry + for (size_type index = 0; index < this->Fields.size() - 1; index += 3) { + bool currentLabel = index == currentLabelIndex; + set_field_fore(this->Fields[index], currentLabel ? A_STANDOUT : A_NORMAL); } - bar[width] = '\0'; - - // Display CMake version info on the next line + // Display CMake version under the status bar // We want to display this on the right - char version[cmCursesMainForm::MAX_WIDTH]; - char vertmp[128]; - sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion()); - size_t sideSpace = (width - strlen(vertmp)); - memset(version, ' ', sideSpace); - sprintf(version + sideSpace, "%s", vertmp); - version[width] = '\0'; - - // Now print both lines - char fmt_s[] = "%s"; - curses_move(y - 5, 0); - attron(A_STANDOUT); - printw(fmt_s, bar); - attroff(A_STANDOUT); - curses_move(y - 4, 0); - printw(fmt_s, version); + std::string version = "CMake Version "; + version += cmVersion::GetCMakeVersion(); + version.resize(std::min<std::string::size_type>(x, version.size())); + curses_move(y - 4, x - static_cast<int>(version.size())); + printw(fmt_s, version.c_str()); + pos_form_cursor(this->Form); } void cmCursesMainForm::UpdateProgress(const std::string& msg, float prog) { - char tmp[1024]; - const char* cmsg = tmp; if (prog >= 0) { - sprintf(tmp, "%s %i%%", msg.c_str(), static_cast<int>(100 * prog)); + constexpr int progressBarWidth = 40; + int progressBarCompleted = static_cast<int>(progressBarWidth * prog); + int percentCompleted = static_cast<int>(100 * prog); + this->LastProgress = (percentCompleted < 100 ? " " : ""); + this->LastProgress += (percentCompleted < 10 ? " " : ""); + this->LastProgress += std::to_string(percentCompleted) + "% ["; + this->LastProgress.append(progressBarCompleted, '#'); + this->LastProgress.append(progressBarWidth - progressBarCompleted, ' '); + this->LastProgress += "] " + msg + "..."; } else { - cmsg = msg.c_str(); + this->Outputs.emplace_back(msg); } - this->UpdateStatusBar(cmsg); - this->PrintKeys(1); - curses_move(1, 1); - touchwin(stdscr); - refresh(); + + this->DisplayOutputs(); } int cmCursesMainForm::Configure(int noconfigure) { - int xi; - int yi; - getmaxyx(stdscr, yi, xi); - - curses_move(1, 1); - this->UpdateStatusBar("Configuring, please wait..."); - this->PrintKeys(1); - touchwin(stdscr); - refresh(); - this->CMakeInstance->SetProgressCallback( - [this](const std::string& msg, float prog) { - this->UpdateProgress(msg, prog); - }); + this->ResetOutputs(); + + if (noconfigure == 0) { + this->UpdateProgress("Configuring", 0); + this->CMakeInstance->SetProgressCallback( + [this](const std::string& msg, float prog) { + this->UpdateProgress(msg, prog); + }); + } // always save the current gui values to disk this->FillCacheManagerFromUI(); @@ -505,9 +478,6 @@ int cmCursesMainForm::Configure(int noconfigure) this->CMakeInstance->GetHomeOutputDirectory()); this->LoadCache(nullptr); - // Get rid of previous errors - this->Errors = std::vector<std::string>(); - // run the generate process this->OkToGenerate = true; int retVal; @@ -524,7 +494,7 @@ int cmCursesMainForm::Configure(int noconfigure) keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ - if (retVal != 0 || !this->Errors.empty()) { + if (retVal != 0 || this->HasNonStatusOutputs) { // see if there was an error if (cmSystemTools::GetErrorOccuredFlag()) { this->OkToGenerate = false; @@ -532,11 +502,13 @@ int cmCursesMainForm::Configure(int noconfigure) int xx; int yy; getmaxyx(stdscr, yy, xx); - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->Errors, - cmSystemTools::GetErrorOccuredFlag() - ? "Errors occurred during the last pass." - : "CMake produced the following output."); + const char* title = "Configure produced the following output"; + if (cmSystemTools::GetErrorOccuredFlag()) { + title = "Configure failed with the following output"; + } + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->Outputs, title, + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); // reset error condition cmSystemTools::ResetErrorOccuredFlag(); CurrentForm = msgs; @@ -547,11 +519,13 @@ int cmCursesMainForm::Configure(int noconfigure) if (retVal == -2) { return retVal; } - CurrentForm = this; - this->Render(1, 1, xx, yy); } this->InitializeUI(); + CurrentForm = this; + int xi; + int yi; + getmaxyx(stdscr, yi, xi); this->Render(1, 1, xi, yi); return 0; @@ -559,30 +533,21 @@ int cmCursesMainForm::Configure(int noconfigure) int cmCursesMainForm::Generate() { - int xi; - int yi; - getmaxyx(stdscr, yi, xi); + this->ResetOutputs(); - curses_move(1, 1); - this->UpdateStatusBar("Generating, please wait..."); - this->PrintKeys(1); - touchwin(stdscr); - refresh(); + this->UpdateProgress("Generating", 0); this->CMakeInstance->SetProgressCallback( [this](const std::string& msg, float prog) { this->UpdateProgress(msg, prog); }); - // Get rid of previous errors - this->Errors = std::vector<std::string>(); - // run the generate process int retVal = this->CMakeInstance->Generate(); this->CMakeInstance->SetProgressCallback(nullptr); keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ - if (retVal != 0 || !this->Errors.empty()) { + if (retVal != 0 || this->HasNonStatusOutputs) { // see if there was an error if (cmSystemTools::GetErrorOccuredFlag()) { this->OkToGenerate = false; @@ -592,12 +557,13 @@ int cmCursesMainForm::Generate() int xx; int yy; getmaxyx(stdscr, yy, xx); - const char* title = "Messages during last pass."; + const char* title = "Generate produced the following output"; if (cmSystemTools::GetErrorOccuredFlag()) { - title = "Errors occurred during the last pass."; + title = "Generate failed with the following output"; } - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->Errors, title); + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->Outputs, title, + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); CurrentForm = msgs; msgs->Render(1, 1, xx, yy); msgs->HandleInput(); @@ -606,11 +572,13 @@ int cmCursesMainForm::Generate() if (retVal == -2) { return retVal; } - CurrentForm = this; - this->Render(1, 1, xx, yy); } this->InitializeUI(); + CurrentForm = this; + int xi; + int yi; + getmaxyx(stdscr, yi, xi); this->Render(1, 1, xi, yi); return 0; @@ -619,7 +587,9 @@ int cmCursesMainForm::Generate() void cmCursesMainForm::AddError(const std::string& message, const char* /*unused*/) { - this->Errors.emplace_back(message); + this->Outputs.emplace_back(message); + this->HasNonStatusOutputs = true; + this->DisplayOutputs(); } void cmCursesMainForm::RemoveEntry(const char* value) @@ -704,7 +674,7 @@ void cmCursesMainForm::HandleInput() this->PrintKeys(); if (this->SearchMode) { std::string searchstr = "Search: " + this->SearchString; - this->UpdateStatusBar(searchstr.c_str()); + this->UpdateStatusBar(searchstr); this->PrintKeys(1); curses_move(y - 5, static_cast<unsigned int>(searchstr.size())); // curses_move(1,1); @@ -848,8 +818,9 @@ void cmCursesMainForm::HandleInput() this->HelpMessage[1] = ""; } - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->HelpMessage, "Help."); + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->HelpMessage, "Help", + cmCursesLongMessageForm::ScrollBehavior::NoScroll); CurrentForm = msgs; msgs->Render(1, 1, x, y); msgs->HandleInput(); @@ -861,7 +832,8 @@ void cmCursesMainForm::HandleInput() else if (key == 'l') { getmaxyx(stdscr, y, x); cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( - this->Errors, "Errors occurred during the last pass."); + this->Outputs, "CMake produced the following output", + cmCursesLongMessageForm::ScrollBehavior::NoScroll); CurrentForm = msgs; msgs->Render(1, 1, x, y); msgs->HandleInput(); @@ -1007,15 +979,6 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr) } else { form_driver(this->Form, REQ_NEXT_FIELD); } - /* - char buffer[1024]; - sprintf(buffer, "Line: %d != %d / %d\n", findex, idx, - this->NumberOfVisibleEntries); - touchwin(stdscr); - refresh(); - this->UpdateStatusBar( buffer ); - usleep(100000); - */ cur = current_field(this->Form); findex = field_index(cur); if (findex == start_index) { @@ -1024,6 +987,28 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr) } } +void cmCursesMainForm::ResetOutputs() +{ + this->LogForm.reset(); + this->Outputs.clear(); + this->HasNonStatusOutputs = false; + this->LastProgress.clear(); +} + +void cmCursesMainForm::DisplayOutputs() +{ + int xi; + int yi; + getmaxyx(stdscr, yi, xi); + + auto newLogForm = new cmCursesLongMessageForm( + this->Outputs, this->LastProgress.c_str(), + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); + CurrentForm = newLogForm; + this->LogForm.reset(newLogForm); + this->LogForm->Render(1, 1, xi, yi); +} + const char* cmCursesMainForm::s_ConstHelpMessage = "CMake is used to configure and generate build files for software projects. " "The basic steps for configuring a project with ccmake are as follows:\n\n" @@ -1080,7 +1065,7 @@ const char* cmCursesMainForm::s_ConstHelpMessage = " c : process the configuration files with the current options\n" " g : generate build files and exit, only available when there are no " "new options and no errors have been detected during last configuration.\n" - " l : shows last errors\n" + " l : shows cmake output\n" " d : delete an option\n" " t : toggles advanced mode. In normal mode, only the most important " "options are shown. In advanced mode, all options are shown. We recommend " diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h index b8769b7cf4..b7c204d64e 100644 --- a/Source/CursesDialog/cmCursesMainForm.h +++ b/Source/CursesDialog/cmCursesMainForm.h @@ -10,12 +10,15 @@ #include <string> #include <vector> +#include <cm/optional> + #include "cmCursesCacheEntryComposite.h" #include "cmCursesForm.h" #include "cmCursesStandardIncludes.h" #include "cmStateTypes.h" class cmake; +class cmCursesLongMessageForm; /** \class cmCursesMainForm * \brief The main page of ccmake @@ -66,8 +69,8 @@ public: * exception is during a resize. The optional argument specifies the * string to be displayed in the status bar. */ - void UpdateStatusBar() override { this->UpdateStatusBar(nullptr); } - virtual void UpdateStatusBar(const char* message); + void UpdateStatusBar() override { this->UpdateStatusBar(cm::nullopt); } + void UpdateStatusBar(cm::optional<std::string> message); /** * Display current commands and their keys on the toolbar. This @@ -122,10 +125,24 @@ protected: // Jump to the cache entry whose name matches the string. void JumpToCacheEntry(const char* str); + // Clear and reset the output log and state + void ResetOutputs(); + + // Display the current progress and output + void DisplayOutputs(); + // Copies of cache entries stored in the user interface std::vector<cmCursesCacheEntryComposite> Entries; - // Errors produced during last run of cmake - std::vector<std::string> Errors; + + // The form used to display logs during processing + std::unique_ptr<cmCursesLongMessageForm> LogForm; + // Output produced by the last pass + std::vector<std::string> Outputs; + // Did the last pass produced outputs of interest (errors, warnings, ...) + bool HasNonStatusOutputs; + // Last progress bar + std::string LastProgress; + // Command line arguments to be passed to cmake each time // it is run std::vector<std::string> Args; diff --git a/Source/CursesDialog/cmCursesOptionsWidget.cxx b/Source/CursesDialog/cmCursesOptionsWidget.cxx index eb773ad0fb..a15241faed 100644 --- a/Source/CursesDialog/cmCursesOptionsWidget.cxx +++ b/Source/CursesDialog/cmCursesOptionsWidget.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCursesOptionsWidget.h" +#include "cmCursesColor.h" #include "cmCursesWidget.h" #include "cmStateTypes.h" @@ -15,8 +16,13 @@ cmCursesOptionsWidget::cmCursesOptionsWidget(int width, int height, int left, // there is no option type, and string type causes ccmake to cast // the widget into a string widget at some point. BOOL is safe for // now. - set_field_fore(this->Field, A_NORMAL); - set_field_back(this->Field, A_STANDOUT); + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::Options)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::Options)); + } else { + set_field_fore(this->Field, A_NORMAL); + set_field_back(this->Field, A_STANDOUT); + } field_opts_off(this->Field, O_STATIC); } diff --git a/Source/CursesDialog/cmCursesPathWidget.cxx b/Source/CursesDialog/cmCursesPathWidget.cxx index bb3808e89c..8ed42dee75 100644 --- a/Source/CursesDialog/cmCursesPathWidget.cxx +++ b/Source/CursesDialog/cmCursesPathWidget.cxx @@ -4,6 +4,7 @@ #include <vector> +#include "cmCursesColor.h" #include "cmCursesMainForm.h" #include "cmCursesStringWidget.h" #include "cmStateTypes.h" @@ -16,6 +17,13 @@ cmCursesPathWidget::cmCursesPathWidget(int width, int height, int left, this->Type = cmStateEnums::PATH; this->Cycle = false; this->CurrentIndex = 0; + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::Path)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::Path)); + } else { + set_field_fore(this->Field, A_NORMAL); + set_field_back(this->Field, A_STANDOUT); + } } void cmCursesPathWidget::OnType(int& key, cmCursesMainForm* fm, WINDOW* w) diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx index 6296af20ba..c62947836c 100644 --- a/Source/CursesDialog/cmCursesStringWidget.cxx +++ b/Source/CursesDialog/cmCursesStringWidget.cxx @@ -4,6 +4,7 @@ #include <cstdio> +#include "cmCursesColor.h" #include "cmCursesForm.h" #include "cmCursesMainForm.h" #include "cmCursesStandardIncludes.h" @@ -21,8 +22,13 @@ cmCursesStringWidget::cmCursesStringWidget(int width, int height, int left, { this->InEdit = false; this->Type = cmStateEnums::STRING; - set_field_fore(this->Field, A_NORMAL); - set_field_back(this->Field, A_STANDOUT); + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::String)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::String)); + } else { + set_field_fore(this->Field, A_NORMAL); + set_field_back(this->Field, A_STANDOUT); + } field_opts_off(this->Field, O_STATIC); } diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx index ae7fb42ea8..34dc8ecfea 100644 --- a/Source/LexerParser/cmCommandArgumentParser.cxx +++ b/Source/LexerParser/cmCommandArgumentParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison implementation for Yacc-like parsers in C @@ -48,7 +48,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.3.2" +#define YYBISON_VERSION "3.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ /* First part of user prologue. */ -#line 1 "cmCommandArgumentParser.y" /* yacc.c:337 */ +#line 1 "cmCommandArgumentParser.y" /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -134,7 +134,8 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 138 "cmCommandArgumentParser.cxx" /* yacc.c:337 */ +#line 138 "cmCommandArgumentParser.cxx" + # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus @@ -155,8 +156,8 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # define YYERROR_VERBOSE 1 #endif -/* In a future release of Bison, this section will be replaced - by #include "cmCommandArgumentParserTokens.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED # define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -310,6 +311,8 @@ typedef short yytype_int16; #endif +#define YY_ASSERT(E) ((void) (0 && (E))) + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -700,7 +703,9 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy if (yytype < YYNTOKENS) YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1138,6 +1143,8 @@ yynewstate: | yynewstate -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) @@ -1200,8 +1207,6 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) YYACCEPT; @@ -1269,7 +1274,6 @@ yybackup: YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; @@ -1304,193 +1308,194 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 99 "cmCommandArgumentParser.y" /* yacc.c:1652 */ + case 2: +#line 99 "cmCommandArgumentParser.y" { (yyval.str) = 0; yyGetParser->SetResult((yyvsp[0].str)); } -#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1318 "cmCommandArgumentParser.cxx" break; case 3: -#line 105 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 105 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1326 "cmCommandArgumentParser.cxx" break; case 4: -#line 108 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 108 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1334 "cmCommandArgumentParser.cxx" break; case 5: -#line 113 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 113 "cmCommandArgumentParser.y" { (yyval.str) = 0; } -#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1342 "cmCommandArgumentParser.cxx" break; case 6: -#line 116 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 116 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1350 "cmCommandArgumentParser.cxx" break; case 7: -#line 121 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 121 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1358 "cmCommandArgumentParser.cxx" break; case 8: -#line 124 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 124 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1366 "cmCommandArgumentParser.cxx" break; case 9: -#line 129 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 129 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1374 "cmCommandArgumentParser.cxx" break; case 10: -#line 132 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 132 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1382 "cmCommandArgumentParser.cxx" break; case 11: -#line 135 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 135 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1390 "cmCommandArgumentParser.cxx" break; case 12: -#line 138 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 138 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1398 "cmCommandArgumentParser.cxx" break; case 13: -#line 141 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 141 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1406 "cmCommandArgumentParser.cxx" break; case 14: -#line 144 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 144 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1414 "cmCommandArgumentParser.cxx" break; case 15: -#line 149 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 149 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1422 "cmCommandArgumentParser.cxx" break; case 16: -#line 152 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 152 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1430 "cmCommandArgumentParser.cxx" break; case 17: -#line 155 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 155 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); } -#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1438 "cmCommandArgumentParser.cxx" break; case 18: -#line 158 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 158 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } -#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1446 "cmCommandArgumentParser.cxx" break; case 19: -#line 163 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 163 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1454 "cmCommandArgumentParser.cxx" break; case 20: -#line 166 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 166 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[-1].str); } -#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1462 "cmCommandArgumentParser.cxx" break; case 21: -#line 171 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 171 "cmCommandArgumentParser.y" { (yyval.str) = 0; } -#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1470 "cmCommandArgumentParser.cxx" break; case 22: -#line 174 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 174 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1478 "cmCommandArgumentParser.cxx" break; case 23: -#line 179 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 179 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1486 "cmCommandArgumentParser.cxx" break; case 24: -#line 182 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 182 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1490 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1494 "cmCommandArgumentParser.cxx" break; -#line 1494 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1498 "cmCommandArgumentParser.cxx" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1723,7 +1728,7 @@ yyreturn: #endif return yyresult; } -#line 187 "cmCommandArgumentParser.y" /* yacc.c:1918 */ +#line 187 "cmCommandArgumentParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h index 56c9794f9f..033b8994d1 100644 --- a/Source/LexerParser/cmCommandArgumentParserTokens.h +++ b/Source/LexerParser/cmCommandArgumentParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index 6c1fb2cb37..b15082ddb2 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison implementation for Yacc-like parsers in C @@ -48,7 +48,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.3.2" +#define YYBISON_VERSION "3.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ /* First part of user prologue. */ -#line 1 "cmDependsJavaParser.y" /* yacc.c:337 */ +#line 1 "cmDependsJavaParser.y" /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -123,7 +123,8 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 127 "cmDependsJavaParser.cxx" /* yacc.c:337 */ +#line 127 "cmDependsJavaParser.cxx" + # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus @@ -144,8 +145,8 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # define YYERROR_VERBOSE 1 #endif -/* In a future release of Bison, this section will be replaced - by #include "cmDependsJavaParserTokens.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED # define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -481,6 +482,8 @@ typedef short yytype_int16; #endif +#define YY_ASSERT(E) ((void) (0 && (E))) + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -1685,7 +1688,9 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy if (yytype < YYNTOKENS) YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -2123,6 +2128,8 @@ yynewstate: | yynewstate -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) @@ -2185,8 +2192,6 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) YYACCEPT; @@ -2254,7 +2259,6 @@ yybackup: YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; @@ -2289,215 +2293,215 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 183 "cmDependsJavaParser.y" /* yacc.c:1652 */ + case 2: +#line 183 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2305 "cmDependsJavaParser.cxx" break; case 3: -#line 192 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 192 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2312 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2316 "cmDependsJavaParser.cxx" break; case 4: -#line 200 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 200 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2323 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2327 "cmDependsJavaParser.cxx" break; case 5: -#line 208 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 208 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2334 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2338 "cmDependsJavaParser.cxx" break; case 6: -#line 216 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 216 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2345 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2349 "cmDependsJavaParser.cxx" break; case 7: -#line 224 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 224 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2356 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2360 "cmDependsJavaParser.cxx" break; case 8: -#line 232 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 232 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2367 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2371 "cmDependsJavaParser.cxx" break; case 9: -#line 241 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 241 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2378 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2382 "cmDependsJavaParser.cxx" break; case 10: -#line 249 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 249 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2389 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2393 "cmDependsJavaParser.cxx" break; case 11: -#line 258 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 258 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2400 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2404 "cmDependsJavaParser.cxx" break; case 12: -#line 266 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 266 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2415 "cmDependsJavaParser.cxx" break; case 13: -#line 275 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 275 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2423 "cmDependsJavaParser.cxx" break; case 14: -#line 280 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 280 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2431 "cmDependsJavaParser.cxx" break; case 15: -#line 285 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 285 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2439 "cmDependsJavaParser.cxx" break; case 16: -#line 290 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 290 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2447 "cmDependsJavaParser.cxx" break; case 17: -#line 295 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 295 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2455 "cmDependsJavaParser.cxx" break; case 18: -#line 300 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 300 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2463 "cmDependsJavaParser.cxx" break; case 19: -#line 305 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 305 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2471 "cmDependsJavaParser.cxx" break; case 20: -#line 310 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 310 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2475 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2479 "cmDependsJavaParser.cxx" break; case 21: -#line 316 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 316 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2486 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2490 "cmDependsJavaParser.cxx" break; case 22: -#line 324 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 324 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2497 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2501 "cmDependsJavaParser.cxx" break; case 23: -#line 333 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 333 "cmDependsJavaParser.y" { jpElementStart(1); jpStoreClass((yyvsp[0].str)); @@ -2505,44 +2509,44 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2509 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2513 "cmDependsJavaParser.cxx" break; case 24: -#line 343 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 343 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2520 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2524 "cmDependsJavaParser.cxx" break; case 25: -#line 352 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 352 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2531 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2535 "cmDependsJavaParser.cxx" break; case 26: -#line 361 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 361 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2542 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2546 "cmDependsJavaParser.cxx" break; case 27: -#line 369 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 369 "cmDependsJavaParser.y" { jpElementStart(2); jpStoreClass((yyvsp[-1].str)); @@ -2550,56 +2554,56 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2554 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2558 "cmDependsJavaParser.cxx" break; case 28: -#line 379 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 379 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2563 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2567 "cmDependsJavaParser.cxx" break; case 29: -#line 385 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 385 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2572 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2576 "cmDependsJavaParser.cxx" break; case 30: -#line 392 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 392 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2581 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2585 "cmDependsJavaParser.cxx" break; case 31: -#line 399 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 399 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2590 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2594 "cmDependsJavaParser.cxx" break; case 32: -#line 405 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 405 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = (yyvsp[0].str); } -#line 2599 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2603 "cmDependsJavaParser.cxx" break; case 33: -#line 412 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 412 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->AddClassFound((yyvsp[-2].str)); @@ -2607,11 +2611,11 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine()); } -#line 2611 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2615 "cmDependsJavaParser.cxx" break; case 34: -#line 421 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 421 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2620,11 +2624,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2624 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2628 "cmDependsJavaParser.cxx" break; case 35: -#line 431 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 431 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2633,118 +2637,118 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2637 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2641 "cmDependsJavaParser.cxx" break; case 36: -#line 441 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 441 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2648 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2652 "cmDependsJavaParser.cxx" break; case 37: -#line 450 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 450 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2659 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2663 "cmDependsJavaParser.cxx" break; case 38: -#line 458 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 458 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2670 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2674 "cmDependsJavaParser.cxx" break; case 39: -#line 467 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 467 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2681 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2685 "cmDependsJavaParser.cxx" break; case 40: -#line 475 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 475 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2691 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2695 "cmDependsJavaParser.cxx" break; case 41: -#line 482 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 482 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2702 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2706 "cmDependsJavaParser.cxx" break; case 42: -#line 490 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 490 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2712 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2716 "cmDependsJavaParser.cxx" break; case 43: -#line 497 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 497 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2723 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2727 "cmDependsJavaParser.cxx" break; case 44: -#line 505 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 505 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2733 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2737 "cmDependsJavaParser.cxx" break; case 45: -#line 512 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 512 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2744 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2748 "cmDependsJavaParser.cxx" break; case 46: -#line 521 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 521 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->SetCurrentPackage((yyvsp[-1].str)); @@ -2754,33 +2758,33 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2758 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2762 "cmDependsJavaParser.cxx" break; case 47: -#line 533 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 533 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2769 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2773 "cmDependsJavaParser.cxx" break; case 48: -#line 541 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 541 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2780 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2784 "cmDependsJavaParser.cxx" break; case 49: -#line 550 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 550 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->AddPackagesImport((yyvsp[-1].str)); @@ -2790,11 +2794,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2794 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2798 "cmDependsJavaParser.cxx" break; case 50: -#line 562 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 562 "cmDependsJavaParser.y" { jpElementStart(5); std::string str = (yyvsp[-3].str); @@ -2805,77 +2809,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2809 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2813 "cmDependsJavaParser.cxx" break; case 51: -#line 575 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 575 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2820 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2824 "cmDependsJavaParser.cxx" break; case 52: -#line 583 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 583 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2831 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2835 "cmDependsJavaParser.cxx" break; case 53: -#line 591 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 591 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2842 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2846 "cmDependsJavaParser.cxx" break; case 54: -#line 600 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 600 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2853 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2857 "cmDependsJavaParser.cxx" break; case 55: -#line 608 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 608 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2864 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2868 "cmDependsJavaParser.cxx" break; case 67: -#line 623 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 623 "cmDependsJavaParser.y" { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 2875 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2879 "cmDependsJavaParser.cxx" break; case 68: -#line 633 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 633 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -2883,11 +2887,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2887 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2891 "cmDependsJavaParser.cxx" break; case 69: -#line 642 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 642 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(2); @@ -2895,11 +2899,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2899 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2903 "cmDependsJavaParser.cxx" break; case 70: -#line 651 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 651 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -2907,11 +2911,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2911 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2915 "cmDependsJavaParser.cxx" break; case 71: -#line 660 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 660 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -2919,226 +2923,226 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2923 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2927 "cmDependsJavaParser.cxx" break; case 72: -#line 669 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 669 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2933 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2937 "cmDependsJavaParser.cxx" break; case 73: -#line 676 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 676 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2944 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2948 "cmDependsJavaParser.cxx" break; case 74: -#line 685 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 685 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2955 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2959 "cmDependsJavaParser.cxx" break; case 75: -#line 694 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 694 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2966 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2970 "cmDependsJavaParser.cxx" break; case 76: -#line 703 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 703 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2977 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2981 "cmDependsJavaParser.cxx" break; case 77: -#line 711 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 711 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2988 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2992 "cmDependsJavaParser.cxx" break; case 78: -#line 720 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 720 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2999 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3003 "cmDependsJavaParser.cxx" break; case 79: -#line 728 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 728 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3009 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3013 "cmDependsJavaParser.cxx" break; case 80: -#line 735 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 735 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3020 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3024 "cmDependsJavaParser.cxx" break; case 81: -#line 744 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 744 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3031 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3035 "cmDependsJavaParser.cxx" break; case 82: -#line 752 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 752 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3042 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3046 "cmDependsJavaParser.cxx" break; case 83: -#line 760 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 760 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3053 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3057 "cmDependsJavaParser.cxx" break; case 84: -#line 768 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 768 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3064 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3068 "cmDependsJavaParser.cxx" break; case 85: -#line 777 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 777 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3075 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3079 "cmDependsJavaParser.cxx" break; case 86: -#line 785 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 785 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3090 "cmDependsJavaParser.cxx" break; case 87: -#line 794 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 794 "cmDependsJavaParser.y" { jpElementStart(4); } -#line 3094 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3098 "cmDependsJavaParser.cxx" break; case 88: -#line 800 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 800 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3105 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3109 "cmDependsJavaParser.cxx" break; case 89: -#line 808 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 808 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3116 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3120 "cmDependsJavaParser.cxx" break; case 90: -#line 817 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 817 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3127 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3131 "cmDependsJavaParser.cxx" break; case 91: -#line 825 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 825 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3138 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3142 "cmDependsJavaParser.cxx" break; case 92: -#line 834 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 834 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -3146,77 +3150,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3150 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3154 "cmDependsJavaParser.cxx" break; case 93: -#line 843 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 843 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3161 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3165 "cmDependsJavaParser.cxx" break; case 94: -#line 852 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 852 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3172 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3176 "cmDependsJavaParser.cxx" break; case 95: -#line 860 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 860 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3183 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3187 "cmDependsJavaParser.cxx" break; case 96: -#line 869 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 869 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3194 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3198 "cmDependsJavaParser.cxx" break; case 97: -#line 877 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 877 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3205 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3209 "cmDependsJavaParser.cxx" break; case 98: -#line 885 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 885 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3216 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3220 "cmDependsJavaParser.cxx" break; case 99: -#line 894 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 894 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3224,11 +3228,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3228 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3232 "cmDependsJavaParser.cxx" break; case 100: -#line 903 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 903 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3236,22 +3240,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3240 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3244 "cmDependsJavaParser.cxx" break; case 101: -#line 912 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 912 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3251 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3255 "cmDependsJavaParser.cxx" break; case 102: -#line 920 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 920 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3259,11 +3263,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3263 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3267 "cmDependsJavaParser.cxx" break; case 103: -#line 930 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 930 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3272,40 +3276,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3276 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3280 "cmDependsJavaParser.cxx" break; case 104: -#line 940 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 940 "cmDependsJavaParser.y" { jpElementStart(3); } -#line 3285 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3289 "cmDependsJavaParser.cxx" break; case 105: -#line 946 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 946 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3296 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3300 "cmDependsJavaParser.cxx" break; case 107: -#line 957 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 957 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 3305 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3309 "cmDependsJavaParser.cxx" break; case 108: -#line 963 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 963 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3313,11 +3317,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3317 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3321 "cmDependsJavaParser.cxx" break; case 109: -#line 973 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 973 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3325,11 +3329,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3329 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3333 "cmDependsJavaParser.cxx" break; case 110: -#line 983 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 983 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3337,20 +3341,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3341 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3345 "cmDependsJavaParser.cxx" break; case 111: -#line 993 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 993 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 3350 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3354 "cmDependsJavaParser.cxx" break; case 112: -#line 999 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 999 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3358,11 +3362,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3362 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3366 "cmDependsJavaParser.cxx" break; case 113: -#line 1009 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1009 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3370,11 +3374,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3374 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3378 "cmDependsJavaParser.cxx" break; case 114: -#line 1019 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1019 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3382,11 +3386,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3386 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3390 "cmDependsJavaParser.cxx" break; case 115: -#line 1029 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1029 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3394,11 +3398,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3398 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3402 "cmDependsJavaParser.cxx" break; case 116: -#line 1038 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1038 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3406,11 +3410,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3410 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3414 "cmDependsJavaParser.cxx" break; case 117: -#line 1048 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1048 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3419,11 +3423,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3423 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3427 "cmDependsJavaParser.cxx" break; case 118: -#line 1059 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1059 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3431,22 +3435,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3435 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3439 "cmDependsJavaParser.cxx" break; case 119: -#line 1068 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1068 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3446 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3450 "cmDependsJavaParser.cxx" break; case 120: -#line 1076 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1076 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3454,11 +3458,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3458 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3462 "cmDependsJavaParser.cxx" break; case 121: -#line 1086 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1086 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3466,11 +3470,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3470 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3474 "cmDependsJavaParser.cxx" break; case 122: -#line 1095 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1095 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3478,22 +3482,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3482 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3486 "cmDependsJavaParser.cxx" break; case 123: -#line 1105 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1105 "cmDependsJavaParser.y" { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3493 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3497 "cmDependsJavaParser.cxx" break; case 124: -#line 1114 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1114 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3501,21 +3505,21 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3505 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3509 "cmDependsJavaParser.cxx" break; case 125: -#line 1123 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1123 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3515 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3519 "cmDependsJavaParser.cxx" break; case 126: -#line 1130 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1130 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3523,11 +3527,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3527 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3531 "cmDependsJavaParser.cxx" break; case 127: -#line 1140 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1140 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3535,11 +3539,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3539 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3543 "cmDependsJavaParser.cxx" break; case 128: -#line 1149 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1149 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3547,11 +3551,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3551 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3555 "cmDependsJavaParser.cxx" break; case 129: -#line 1159 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1159 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3559,33 +3563,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3563 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3567 "cmDependsJavaParser.cxx" break; case 130: -#line 1168 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1168 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3574 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3578 "cmDependsJavaParser.cxx" break; case 131: -#line 1176 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1176 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3585 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3589 "cmDependsJavaParser.cxx" break; case 132: -#line 1185 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1185 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3593,11 +3597,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3597 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3601 "cmDependsJavaParser.cxx" break; case 133: -#line 1194 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1194 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3605,11 +3609,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3609 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3613 "cmDependsJavaParser.cxx" break; case 134: -#line 1203 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1203 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3617,22 +3621,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3621 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3625 "cmDependsJavaParser.cxx" break; case 135: -#line 1212 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1212 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3632 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3636 "cmDependsJavaParser.cxx" break; case 136: -#line 1220 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1220 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3640,22 +3644,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3644 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3648 "cmDependsJavaParser.cxx" break; case 137: -#line 1229 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1229 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3655 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3659 "cmDependsJavaParser.cxx" break; case 138: -#line 1238 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1238 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3663,11 +3667,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3667 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3671 "cmDependsJavaParser.cxx" break; case 139: -#line 1248 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1248 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3675,11 +3679,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3679 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3683 "cmDependsJavaParser.cxx" break; case 140: -#line 1258 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1258 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3687,11 +3691,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3691 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3695 "cmDependsJavaParser.cxx" break; case 141: -#line 1267 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1267 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3699,11 +3703,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3703 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3707 "cmDependsJavaParser.cxx" break; case 142: -#line 1277 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1277 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3711,22 +3715,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3715 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3719 "cmDependsJavaParser.cxx" break; case 143: -#line 1286 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1286 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3726 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3730 "cmDependsJavaParser.cxx" break; case 144: -#line 1294 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1294 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3734,11 +3738,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3738 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3742 "cmDependsJavaParser.cxx" break; case 145: -#line 1303 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1303 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3746,11 +3750,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3750 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3754 "cmDependsJavaParser.cxx" break; case 146: -#line 1313 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1313 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3758,11 +3762,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3762 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3766 "cmDependsJavaParser.cxx" break; case 147: -#line 1322 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1322 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3770,33 +3774,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3774 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3778 "cmDependsJavaParser.cxx" break; case 148: -#line 1332 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1332 "cmDependsJavaParser.y" { jpElementStart(4); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3785 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3789 "cmDependsJavaParser.cxx" break; case 149: -#line 1340 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1340 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3796 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3800 "cmDependsJavaParser.cxx" break; case 150: -#line 1348 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1348 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3804,11 +3808,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3808 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3812 "cmDependsJavaParser.cxx" break; case 151: -#line 1358 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1358 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3816,11 +3820,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3820 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3824 "cmDependsJavaParser.cxx" break; case 152: -#line 1367 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1367 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -3828,11 +3832,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3832 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3836 "cmDependsJavaParser.cxx" break; case 153: -#line 1377 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1377 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3840,11 +3844,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3844 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3848 "cmDependsJavaParser.cxx" break; case 154: -#line 1386 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1386 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3852,11 +3856,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3856 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3860 "cmDependsJavaParser.cxx" break; case 155: -#line 1395 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1395 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3864,11 +3868,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3868 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3872 "cmDependsJavaParser.cxx" break; case 156: -#line 1405 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1405 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -3876,11 +3880,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3880 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3884 "cmDependsJavaParser.cxx" break; case 157: -#line 1415 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1415 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(3); @@ -3888,11 +3892,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3892 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3896 "cmDependsJavaParser.cxx" break; case 158: -#line 1424 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1424 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -3900,11 +3904,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3904 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3908 "cmDependsJavaParser.cxx" break; case 159: -#line 1434 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1434 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3912,11 +3916,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3916 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3920 "cmDependsJavaParser.cxx" break; case 160: -#line 1443 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1443 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3924,11 +3928,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3928 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3932 "cmDependsJavaParser.cxx" break; case 161: -#line 1452 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1452 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3936,11 +3940,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3940 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3944 "cmDependsJavaParser.cxx" break; case 162: -#line 1461 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1461 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3948,11 +3952,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3952 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3956 "cmDependsJavaParser.cxx" break; case 163: -#line 1470 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1470 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3960,11 +3964,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3964 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3968 "cmDependsJavaParser.cxx" break; case 164: -#line 1479 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1479 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3972,11 +3976,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3976 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3980 "cmDependsJavaParser.cxx" break; case 165: -#line 1489 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1489 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3984,11 +3988,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3988 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3992 "cmDependsJavaParser.cxx" break; case 166: -#line 1498 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1498 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3996,11 +4000,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4000 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4004 "cmDependsJavaParser.cxx" break; case 167: -#line 1507 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1507 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4008,11 +4012,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4012 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4016 "cmDependsJavaParser.cxx" break; case 168: -#line 1516 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1516 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4020,11 +4024,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4024 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4028 "cmDependsJavaParser.cxx" break; case 169: -#line 1525 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1525 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4032,11 +4036,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4036 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4040 "cmDependsJavaParser.cxx" break; case 170: -#line 1535 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1535 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4044,11 +4048,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4048 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4052 "cmDependsJavaParser.cxx" break; case 171: -#line 1544 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1544 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4056,11 +4060,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4060 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4064 "cmDependsJavaParser.cxx" break; case 172: -#line 1553 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1553 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4068,11 +4072,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4072 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4076 "cmDependsJavaParser.cxx" break; case 173: -#line 1562 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1562 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4080,11 +4084,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4084 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4088 "cmDependsJavaParser.cxx" break; case 174: -#line 1571 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1571 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4092,11 +4096,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4096 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4100 "cmDependsJavaParser.cxx" break; case 175: -#line 1580 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1580 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4104,11 +4108,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4108 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4112 "cmDependsJavaParser.cxx" break; case 176: -#line 1589 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1589 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4116,11 +4120,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4120 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4124 "cmDependsJavaParser.cxx" break; case 177: -#line 1598 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1598 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4128,11 +4132,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4132 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4136 "cmDependsJavaParser.cxx" break; case 178: -#line 1607 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1607 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4140,11 +4144,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4144 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4148 "cmDependsJavaParser.cxx" break; case 179: -#line 1616 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1616 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4152,11 +4156,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4156 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4160 "cmDependsJavaParser.cxx" break; case 180: -#line 1625 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1625 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4164,11 +4168,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4168 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4172 "cmDependsJavaParser.cxx" break; case 181: -#line 1634 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1634 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4176,11 +4180,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4180 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4184 "cmDependsJavaParser.cxx" break; case 182: -#line 1644 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1644 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4188,11 +4192,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4192 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4196 "cmDependsJavaParser.cxx" break; case 183: -#line 1654 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1654 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); @@ -4201,11 +4205,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4205 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4209 "cmDependsJavaParser.cxx" break; case 184: -#line 1665 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1665 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4213,11 +4217,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4217 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4221 "cmDependsJavaParser.cxx" break; case 185: -#line 1675 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1675 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4225,11 +4229,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4229 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4233 "cmDependsJavaParser.cxx" break; case 186: -#line 1685 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1685 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4237,11 +4241,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4241 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4245 "cmDependsJavaParser.cxx" break; case 187: -#line 1694 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1694 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4249,11 +4253,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4253 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4257 "cmDependsJavaParser.cxx" break; case 188: -#line 1703 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1703 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4261,11 +4265,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4265 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4269 "cmDependsJavaParser.cxx" break; case 189: -#line 1712 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1712 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4273,11 +4277,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4277 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4281 "cmDependsJavaParser.cxx" break; case 190: -#line 1721 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1721 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4285,11 +4289,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4289 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4293 "cmDependsJavaParser.cxx" break; case 191: -#line 1730 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1730 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4297,11 +4301,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4305 "cmDependsJavaParser.cxx" break; case 192: -#line 1739 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1739 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4309,11 +4313,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4313 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4317 "cmDependsJavaParser.cxx" break; case 193: -#line 1749 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1749 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4321,11 +4325,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4325 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4329 "cmDependsJavaParser.cxx" break; case 194: -#line 1759 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1759 "cmDependsJavaParser.y" { jpElementStart(7); jpCheckEmpty(7); @@ -4333,11 +4337,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4337 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4341 "cmDependsJavaParser.cxx" break; case 195: -#line 1769 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1769 "cmDependsJavaParser.y" { jpElementStart(7); jpCheckEmpty(7); @@ -4345,40 +4349,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4349 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4353 "cmDependsJavaParser.cxx" break; case 196: -#line 1779 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1779 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4358 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4362 "cmDependsJavaParser.cxx" break; case 197: -#line 1786 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1786 "cmDependsJavaParser.y" { jpElementStart(4); } -#line 4367 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4371 "cmDependsJavaParser.cxx" break; case 198: -#line 1792 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1792 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4378 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4382 "cmDependsJavaParser.cxx" break; case 199: -#line 1800 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1800 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4386,22 +4390,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4390 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4394 "cmDependsJavaParser.cxx" break; case 200: -#line 1809 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1809 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4401 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4405 "cmDependsJavaParser.cxx" break; case 201: -#line 1817 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1817 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4409,11 +4413,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4413 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4417 "cmDependsJavaParser.cxx" break; case 202: -#line 1827 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1827 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4421,11 +4425,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4425 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4429 "cmDependsJavaParser.cxx" break; case 203: -#line 1837 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1837 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4433,11 +4437,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4437 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4441 "cmDependsJavaParser.cxx" break; case 204: -#line 1846 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1846 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4445,11 +4449,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4449 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4453 "cmDependsJavaParser.cxx" break; case 205: -#line 1856 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1856 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4457,11 +4461,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4461 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4465 "cmDependsJavaParser.cxx" break; case 206: -#line 1865 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1865 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4469,58 +4473,58 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4473 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4477 "cmDependsJavaParser.cxx" break; case 207: -#line 1875 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1875 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4482 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4486 "cmDependsJavaParser.cxx" break; case 208: -#line 1882 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1882 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4491 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4495 "cmDependsJavaParser.cxx" break; case 209: -#line 1889 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1889 "cmDependsJavaParser.y" { jpElementStart(7); } -#line 4500 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4504 "cmDependsJavaParser.cxx" break; case 210: -#line 1897 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1897 "cmDependsJavaParser.y" { jpElementStart(9); } -#line 4509 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4513 "cmDependsJavaParser.cxx" break; case 211: -#line 1903 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1903 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4520 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4524 "cmDependsJavaParser.cxx" break; case 212: -#line 1911 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1911 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4528,22 +4532,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4532 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4536 "cmDependsJavaParser.cxx" break; case 213: -#line 1920 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1920 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4543 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4547 "cmDependsJavaParser.cxx" break; case 214: -#line 1928 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1928 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4551,33 +4555,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4555 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4559 "cmDependsJavaParser.cxx" break; case 215: -#line 1939 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1939 "cmDependsJavaParser.y" { jpElementStart(9); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4566 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4570 "cmDependsJavaParser.cxx" break; case 216: -#line 1947 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1947 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4577 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4581 "cmDependsJavaParser.cxx" break; case 217: -#line 1955 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1955 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4585,11 +4589,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4589 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4593 "cmDependsJavaParser.cxx" break; case 218: -#line 1965 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1965 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4597,11 +4601,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4601 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4605 "cmDependsJavaParser.cxx" break; case 219: -#line 1974 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1974 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4609,11 +4613,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4613 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4617 "cmDependsJavaParser.cxx" break; case 220: -#line 1984 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1984 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4621,11 +4625,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4625 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4629 "cmDependsJavaParser.cxx" break; case 221: -#line 1994 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1994 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4633,11 +4637,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4637 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4641 "cmDependsJavaParser.cxx" break; case 222: -#line 2003 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2003 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4645,11 +4649,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4649 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4653 "cmDependsJavaParser.cxx" break; case 223: -#line 2013 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2013 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4657,11 +4661,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4661 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4665 "cmDependsJavaParser.cxx" break; case 224: -#line 2022 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2022 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4669,11 +4673,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4673 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4677 "cmDependsJavaParser.cxx" break; case 225: -#line 2032 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2032 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4682,31 +4686,31 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4686 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4690 "cmDependsJavaParser.cxx" break; case 226: -#line 2042 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2042 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4697 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4701 "cmDependsJavaParser.cxx" break; case 227: -#line 2050 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2050 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 4706 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4710 "cmDependsJavaParser.cxx" break; case 228: -#line 2057 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2057 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4715,11 +4719,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4719 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4723 "cmDependsJavaParser.cxx" break; case 229: -#line 2068 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2068 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4727,11 +4731,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4731 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4735 "cmDependsJavaParser.cxx" break; case 230: -#line 2078 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2078 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4739,11 +4743,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4743 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4747 "cmDependsJavaParser.cxx" break; case 231: -#line 2088 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2088 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4751,11 +4755,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4755 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4759 "cmDependsJavaParser.cxx" break; case 232: -#line 2098 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2098 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4763,11 +4767,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4767 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4771 "cmDependsJavaParser.cxx" break; case 233: -#line 2107 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2107 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -4775,22 +4779,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4779 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4783 "cmDependsJavaParser.cxx" break; case 234: -#line 2116 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2116 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4790 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4794 "cmDependsJavaParser.cxx" break; case 235: -#line 2124 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2124 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4798,11 +4802,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4802 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4806 "cmDependsJavaParser.cxx" break; case 236: -#line 2134 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2134 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4810,11 +4814,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4814 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4818 "cmDependsJavaParser.cxx" break; case 237: -#line 2143 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2143 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4822,20 +4826,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4826 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4830 "cmDependsJavaParser.cxx" break; case 238: -#line 2153 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2153 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4835 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4839 "cmDependsJavaParser.cxx" break; case 239: -#line 2160 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2160 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4843,11 +4847,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4847 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4851 "cmDependsJavaParser.cxx" break; case 240: -#line 2170 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2170 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4855,11 +4859,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4859 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4863 "cmDependsJavaParser.cxx" break; case 241: -#line 2179 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2179 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4867,11 +4871,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4871 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4875 "cmDependsJavaParser.cxx" break; case 242: -#line 2189 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2189 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4879,20 +4883,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4883 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4887 "cmDependsJavaParser.cxx" break; case 243: -#line 2198 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2198 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 4892 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4896 "cmDependsJavaParser.cxx" break; case 244: -#line 2204 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2204 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4900,11 +4904,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4904 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4908 "cmDependsJavaParser.cxx" break; case 245: -#line 2213 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2213 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4912,11 +4916,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4916 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4920 "cmDependsJavaParser.cxx" break; case 246: -#line 2222 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2222 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4924,11 +4928,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4928 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4932 "cmDependsJavaParser.cxx" break; case 247: -#line 2231 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2231 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4936,11 +4940,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4940 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4944 "cmDependsJavaParser.cxx" break; case 248: -#line 2240 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2240 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4948,11 +4952,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4952 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4956 "cmDependsJavaParser.cxx" break; case 249: -#line 2250 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2250 "cmDependsJavaParser.y" { jpElementStart(6); jpCheckEmpty(6); @@ -4960,22 +4964,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4964 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4968 "cmDependsJavaParser.cxx" break; case 250: -#line 2259 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2259 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4975 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4979 "cmDependsJavaParser.cxx" break; case 251: -#line 2267 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2267 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4983,22 +4987,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4987 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4991 "cmDependsJavaParser.cxx" break; case 252: -#line 2276 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2276 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4998 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5002 "cmDependsJavaParser.cxx" break; case 253: -#line 2284 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2284 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5006,11 +5010,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5010 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5014 "cmDependsJavaParser.cxx" break; case 254: -#line 2294 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2294 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5018,11 +5022,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5022 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5026 "cmDependsJavaParser.cxx" break; case 255: -#line 2303 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2303 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5030,11 +5034,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5034 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5038 "cmDependsJavaParser.cxx" break; case 256: -#line 2313 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2313 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5042,11 +5046,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5046 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5050 "cmDependsJavaParser.cxx" break; case 257: -#line 2322 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2322 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5054,11 +5058,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5058 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5062 "cmDependsJavaParser.cxx" break; case 258: -#line 2331 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2331 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5066,11 +5070,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5070 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5074 "cmDependsJavaParser.cxx" break; case 259: -#line 2340 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2340 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5078,22 +5082,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5082 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5086 "cmDependsJavaParser.cxx" break; case 260: -#line 2349 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2349 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 5093 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5097 "cmDependsJavaParser.cxx" break; case 261: -#line 2357 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2357 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5101,11 +5105,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5105 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5109 "cmDependsJavaParser.cxx" break; case 262: -#line 2367 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2367 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5113,11 +5117,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5117 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5121 "cmDependsJavaParser.cxx" break; case 263: -#line 2376 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2376 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5125,11 +5129,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5129 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5133 "cmDependsJavaParser.cxx" break; case 264: -#line 2386 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2386 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5137,29 +5141,29 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5141 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5145 "cmDependsJavaParser.cxx" break; case 265: -#line 2396 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2396 "cmDependsJavaParser.y" { jpElementStart(2); } -#line 5150 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5154 "cmDependsJavaParser.cxx" break; case 266: -#line 2402 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2402 "cmDependsJavaParser.y" { jpElementStart(3); } -#line 5159 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5163 "cmDependsJavaParser.cxx" break; case 267: -#line 2409 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2409 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5168,11 +5172,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5172 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5176 "cmDependsJavaParser.cxx" break; case 268: -#line 2419 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2419 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5181,11 +5185,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5185 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5189 "cmDependsJavaParser.cxx" break; case 269: -#line 2429 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2429 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5194,11 +5198,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5198 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5202 "cmDependsJavaParser.cxx" break; case 270: -#line 2439 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2439 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5207,11 +5211,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5211 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5215 "cmDependsJavaParser.cxx" break; case 271: -#line 2450 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2450 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5220,11 +5224,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5224 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5228 "cmDependsJavaParser.cxx" break; case 272: -#line 2460 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2460 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-5].str))); @@ -5234,11 +5238,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5238 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5242 "cmDependsJavaParser.cxx" break; case 273: -#line 2471 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2471 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5247,11 +5251,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5251 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5255 "cmDependsJavaParser.cxx" break; case 274: -#line 2481 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2481 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5260,11 +5264,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5264 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5268 "cmDependsJavaParser.cxx" break; case 275: -#line 2492 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2492 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5273,11 +5277,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5277 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5281 "cmDependsJavaParser.cxx" break; case 276: -#line 2502 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2502 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5285,11 +5289,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5289 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5293 "cmDependsJavaParser.cxx" break; case 277: -#line 2512 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2512 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5297,11 +5301,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5305 "cmDependsJavaParser.cxx" break; case 278: -#line 2521 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2521 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5309,11 +5313,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5313 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5317 "cmDependsJavaParser.cxx" break; case 279: -#line 2530 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2530 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5321,11 +5325,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5325 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5329 "cmDependsJavaParser.cxx" break; case 280: -#line 2539 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2539 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5333,11 +5337,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5337 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5341 "cmDependsJavaParser.cxx" break; case 281: -#line 2548 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2548 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5345,11 +5349,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5349 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5353 "cmDependsJavaParser.cxx" break; case 282: -#line 2558 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2558 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5357,11 +5361,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5361 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5365 "cmDependsJavaParser.cxx" break; case 283: -#line 2568 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2568 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5369,11 +5373,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5373 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5377 "cmDependsJavaParser.cxx" break; case 284: -#line 2578 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2578 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5381,11 +5385,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5385 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5389 "cmDependsJavaParser.cxx" break; case 285: -#line 2587 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2587 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5393,11 +5397,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5397 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5401 "cmDependsJavaParser.cxx" break; case 286: -#line 2596 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2596 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5405,11 +5409,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5409 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5413 "cmDependsJavaParser.cxx" break; case 287: -#line 2605 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2605 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5417,11 +5421,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5421 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5425 "cmDependsJavaParser.cxx" break; case 288: -#line 2614 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2614 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5429,11 +5433,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5433 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5437 "cmDependsJavaParser.cxx" break; case 289: -#line 2624 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2624 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5441,11 +5445,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5445 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5449 "cmDependsJavaParser.cxx" break; case 290: -#line 2634 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2634 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5453,11 +5457,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5457 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5461 "cmDependsJavaParser.cxx" break; case 291: -#line 2644 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2644 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5465,11 +5469,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5469 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5473 "cmDependsJavaParser.cxx" break; case 292: -#line 2653 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2653 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5477,11 +5481,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5481 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5485 "cmDependsJavaParser.cxx" break; case 293: -#line 2662 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2662 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5489,11 +5493,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5493 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5497 "cmDependsJavaParser.cxx" break; case 294: -#line 2671 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2671 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5501,11 +5505,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5505 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5509 "cmDependsJavaParser.cxx" break; case 295: -#line 2681 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2681 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -5513,11 +5517,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5517 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5521 "cmDependsJavaParser.cxx" break; case 296: -#line 2690 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2690 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5525,20 +5529,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5529 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5533 "cmDependsJavaParser.cxx" break; case 297: -#line 2699 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2699 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 5538 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5542 "cmDependsJavaParser.cxx" break; case 298: -#line 2706 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2706 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5546,11 +5550,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5550 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5554 "cmDependsJavaParser.cxx" break; case 299: -#line 2715 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2715 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5558,11 +5562,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5562 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5566 "cmDependsJavaParser.cxx" break; case 300: -#line 2724 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2724 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5570,11 +5574,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5574 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5578 "cmDependsJavaParser.cxx" break; case 301: -#line 2733 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2733 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5582,11 +5586,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5586 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5590 "cmDependsJavaParser.cxx" break; case 302: -#line 2743 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2743 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5594,11 +5598,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5598 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5602 "cmDependsJavaParser.cxx" break; case 303: -#line 2752 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2752 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5606,11 +5610,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5610 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5614 "cmDependsJavaParser.cxx" break; case 304: -#line 2761 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2761 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5618,11 +5622,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5622 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5626 "cmDependsJavaParser.cxx" break; case 305: -#line 2771 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2771 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5630,11 +5634,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5634 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5638 "cmDependsJavaParser.cxx" break; case 306: -#line 2780 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2780 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5642,11 +5646,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5646 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5650 "cmDependsJavaParser.cxx" break; case 307: -#line 2789 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2789 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5654,11 +5658,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5658 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5662 "cmDependsJavaParser.cxx" break; case 308: -#line 2798 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2798 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5666,11 +5670,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5670 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5674 "cmDependsJavaParser.cxx" break; case 309: -#line 2808 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2808 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5678,11 +5682,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5682 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5686 "cmDependsJavaParser.cxx" break; case 310: -#line 2817 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2817 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5690,11 +5694,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5694 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5698 "cmDependsJavaParser.cxx" break; case 311: -#line 2826 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2826 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5702,11 +5706,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5706 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5710 "cmDependsJavaParser.cxx" break; case 312: -#line 2835 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2835 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5714,11 +5718,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5718 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5722 "cmDependsJavaParser.cxx" break; case 313: -#line 2844 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2844 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5726,11 +5730,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5730 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5734 "cmDependsJavaParser.cxx" break; case 314: -#line 2853 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2853 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5738,11 +5742,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5742 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5746 "cmDependsJavaParser.cxx" break; case 315: -#line 2863 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2863 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5750,11 +5754,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5754 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5758 "cmDependsJavaParser.cxx" break; case 316: -#line 2872 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2872 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5762,11 +5766,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5766 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5770 "cmDependsJavaParser.cxx" break; case 317: -#line 2881 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2881 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5774,11 +5778,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5778 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5782 "cmDependsJavaParser.cxx" break; case 318: -#line 2891 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2891 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5786,11 +5790,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5790 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5794 "cmDependsJavaParser.cxx" break; case 319: -#line 2900 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2900 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5798,11 +5802,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5802 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5806 "cmDependsJavaParser.cxx" break; case 320: -#line 2910 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2910 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5810,11 +5814,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5814 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5818 "cmDependsJavaParser.cxx" break; case 321: -#line 2919 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2919 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5822,11 +5826,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5826 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5830 "cmDependsJavaParser.cxx" break; case 322: -#line 2929 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2929 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5834,11 +5838,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5838 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5842 "cmDependsJavaParser.cxx" break; case 323: -#line 2938 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2938 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5846,11 +5850,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5850 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5854 "cmDependsJavaParser.cxx" break; case 324: -#line 2948 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2948 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5858,11 +5862,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5862 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5866 "cmDependsJavaParser.cxx" break; case 325: -#line 2957 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2957 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5870,11 +5874,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5874 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5878 "cmDependsJavaParser.cxx" break; case 326: -#line 2967 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2967 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5882,11 +5886,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5886 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5890 "cmDependsJavaParser.cxx" break; case 327: -#line 2976 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2976 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5894,11 +5898,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5898 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5902 "cmDependsJavaParser.cxx" break; case 328: -#line 2986 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2986 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5906,11 +5910,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5910 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5914 "cmDependsJavaParser.cxx" break; case 329: -#line 2995 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2995 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -5918,11 +5922,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5922 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5926 "cmDependsJavaParser.cxx" break; case 330: -#line 3005 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3005 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5930,11 +5934,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5934 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5938 "cmDependsJavaParser.cxx" break; case 331: -#line 3014 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3014 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5942,11 +5946,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5946 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5950 "cmDependsJavaParser.cxx" break; case 332: -#line 3024 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3024 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5954,11 +5958,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5958 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5962 "cmDependsJavaParser.cxx" break; case 333: -#line 3034 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3034 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5967,11 +5971,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5971 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5975 "cmDependsJavaParser.cxx" break; case 334: -#line 3044 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3044 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5979,11 +5983,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5983 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5987 "cmDependsJavaParser.cxx" break; case 335: -#line 3053 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3053 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5991,11 +5995,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5995 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5999 "cmDependsJavaParser.cxx" break; case 336: -#line 3063 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3063 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6003,11 +6007,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6007 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6011 "cmDependsJavaParser.cxx" break; case 337: -#line 3072 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3072 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6015,11 +6019,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6019 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6023 "cmDependsJavaParser.cxx" break; case 338: -#line 3081 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3081 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6027,11 +6031,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6031 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6035 "cmDependsJavaParser.cxx" break; case 339: -#line 3090 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3090 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6039,11 +6043,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6043 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6047 "cmDependsJavaParser.cxx" break; case 340: -#line 3099 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3099 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6051,11 +6055,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6055 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6059 "cmDependsJavaParser.cxx" break; case 341: -#line 3108 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3108 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6063,11 +6067,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6067 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6071 "cmDependsJavaParser.cxx" break; case 342: -#line 3117 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3117 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6075,11 +6079,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6079 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6083 "cmDependsJavaParser.cxx" break; case 343: -#line 3126 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3126 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6087,11 +6091,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6091 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6095 "cmDependsJavaParser.cxx" break; case 344: -#line 3135 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3135 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6099,11 +6103,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6103 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6107 "cmDependsJavaParser.cxx" break; case 345: -#line 3144 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3144 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6111,11 +6115,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6115 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6119 "cmDependsJavaParser.cxx" break; case 346: -#line 3153 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3153 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6123,11 +6127,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6127 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6131 "cmDependsJavaParser.cxx" break; case 347: -#line 3162 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3162 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6135,11 +6139,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6139 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6143 "cmDependsJavaParser.cxx" break; case 348: -#line 3172 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3172 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6147,11 +6151,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6151 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6155 "cmDependsJavaParser.cxx" break; case 349: -#line 3182 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3182 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6159,11 +6163,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6163 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6167 "cmDependsJavaParser.cxx" break; case 350: -#line 3192 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3192 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6171,11 +6175,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6175 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6179 "cmDependsJavaParser.cxx" break; case 351: -#line 3201 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3201 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -6184,11 +6188,12 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6188 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6192 "cmDependsJavaParser.cxx" break; -#line 6192 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6196 "cmDependsJavaParser.cxx" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -6421,7 +6426,7 @@ yyreturn: #endif return yyresult; } -#line 3210 "cmDependsJavaParser.y" /* yacc.c:1918 */ +#line 3210 "cmDependsJavaParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h index 6bbc0848d4..e0dfa01cc5 100644 --- a/Source/LexerParser/cmDependsJavaParserTokens.h +++ b/Source/LexerParser/cmDependsJavaParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx index 8416e7249c..562b35bf71 100644 --- a/Source/LexerParser/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison implementation for Yacc-like parsers in C @@ -48,7 +48,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.3.2" +#define YYBISON_VERSION "3.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ /* First part of user prologue. */ -#line 1 "cmExprParser.y" /* yacc.c:337 */ +#line 1 "cmExprParser.y" /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -116,7 +116,8 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 120 "cmExprParser.cxx" /* yacc.c:337 */ +#line 120 "cmExprParser.cxx" + # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus @@ -137,8 +138,8 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # define YYERROR_VERBOSE 1 #endif -/* In a future release of Bison, this section will be replaced - by #include "cmExprParserTokens.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED # define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -296,6 +297,8 @@ typedef short yytype_int16; #endif +#define YY_ASSERT(E) ((void) (0 && (E))) + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -688,7 +691,9 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy if (yytype < YYNTOKENS) YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1126,6 +1131,8 @@ yynewstate: | yynewstate -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) @@ -1188,8 +1195,6 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) YYACCEPT; @@ -1257,7 +1262,6 @@ yybackup: YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; @@ -1292,195 +1296,196 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 77 "cmExprParser.y" /* yacc.c:1652 */ + case 2: +#line 77 "cmExprParser.y" { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1301 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1305 "cmExprParser.cxx" break; case 3: -#line 82 "cmExprParser.y" /* yacc.c:1652 */ +#line 82 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1309 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1313 "cmExprParser.cxx" break; case 4: -#line 85 "cmExprParser.y" /* yacc.c:1652 */ +#line 85 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1317 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1321 "cmExprParser.cxx" break; case 5: -#line 90 "cmExprParser.y" /* yacc.c:1652 */ +#line 90 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1325 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1329 "cmExprParser.cxx" break; case 6: -#line 93 "cmExprParser.y" /* yacc.c:1652 */ +#line 93 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1333 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1337 "cmExprParser.cxx" break; case 7: -#line 98 "cmExprParser.y" /* yacc.c:1652 */ +#line 98 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1341 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1345 "cmExprParser.cxx" break; case 8: -#line 101 "cmExprParser.y" /* yacc.c:1652 */ +#line 101 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1349 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1353 "cmExprParser.cxx" break; case 9: -#line 106 "cmExprParser.y" /* yacc.c:1652 */ +#line 106 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1357 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1361 "cmExprParser.cxx" break; case 10: -#line 109 "cmExprParser.y" /* yacc.c:1652 */ +#line 109 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1365 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1369 "cmExprParser.cxx" break; case 11: -#line 112 "cmExprParser.y" /* yacc.c:1652 */ +#line 112 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1373 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1377 "cmExprParser.cxx" break; case 12: -#line 117 "cmExprParser.y" /* yacc.c:1652 */ +#line 117 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1381 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1385 "cmExprParser.cxx" break; case 13: -#line 120 "cmExprParser.y" /* yacc.c:1652 */ +#line 120 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1389 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1393 "cmExprParser.cxx" break; case 14: -#line 123 "cmExprParser.y" /* yacc.c:1652 */ +#line 123 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1397 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1401 "cmExprParser.cxx" break; case 15: -#line 128 "cmExprParser.y" /* yacc.c:1652 */ +#line 128 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1405 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1409 "cmExprParser.cxx" break; case 16: -#line 131 "cmExprParser.y" /* yacc.c:1652 */ +#line 131 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1413 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1417 "cmExprParser.cxx" break; case 17: -#line 134 "cmExprParser.y" /* yacc.c:1652 */ +#line 134 "cmExprParser.y" { if (yyvsp[0].Number == 0) { throw std::overflow_error("divide by zero"); } (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1424 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1428 "cmExprParser.cxx" break; case 18: -#line 140 "cmExprParser.y" /* yacc.c:1652 */ +#line 140 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1432 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1436 "cmExprParser.cxx" break; case 19: -#line 145 "cmExprParser.y" /* yacc.c:1652 */ +#line 145 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1440 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1444 "cmExprParser.cxx" break; case 20: -#line 148 "cmExprParser.y" /* yacc.c:1652 */ +#line 148 "cmExprParser.y" { (yyval.Number) = + (yyvsp[0].Number); } -#line 1448 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1452 "cmExprParser.cxx" break; case 21: -#line 151 "cmExprParser.y" /* yacc.c:1652 */ +#line 151 "cmExprParser.y" { (yyval.Number) = - (yyvsp[0].Number); } -#line 1456 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1460 "cmExprParser.cxx" break; case 22: -#line 154 "cmExprParser.y" /* yacc.c:1652 */ +#line 154 "cmExprParser.y" { (yyval.Number) = ~ (yyvsp[0].Number); } -#line 1464 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1468 "cmExprParser.cxx" break; case 23: -#line 159 "cmExprParser.y" /* yacc.c:1652 */ +#line 159 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1472 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1476 "cmExprParser.cxx" break; case 24: -#line 162 "cmExprParser.y" /* yacc.c:1652 */ +#line 162 "cmExprParser.y" { (yyval.Number) = (yyvsp[-1].Number); } -#line 1480 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1484 "cmExprParser.cxx" break; -#line 1484 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1488 "cmExprParser.cxx" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1713,7 +1718,7 @@ yyreturn: #endif return yyresult; } -#line 167 "cmExprParser.y" /* yacc.c:1918 */ +#line 167 "cmExprParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h index 5ffd7c5100..e30a832572 100644 --- a/Source/LexerParser/cmExprParserTokens.h +++ b/Source/LexerParser/cmExprParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 2ca79276d8..2494aadcc7 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison implementation for Yacc-like parsers in C @@ -48,7 +48,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.3.2" +#define YYBISON_VERSION "3.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ /* First part of user prologue. */ -#line 1 "cmFortranParser.y" /* yacc.c:337 */ +#line 1 "cmFortranParser.y" /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -135,7 +135,8 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 139 "cmFortranParser.cxx" /* yacc.c:337 */ +#line 139 "cmFortranParser.cxx" + # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus @@ -156,8 +157,8 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # define YYERROR_VERBOSE 1 #endif -/* In a future release of Bison, this section will be replaced - by #include "cmFortranParserTokens.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED # define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -255,16 +256,15 @@ extern int cmFortran_yydebug; /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - union YYSTYPE { -#line 73 "cmFortranParser.y" /* yacc.c:352 */ +#line 73 "cmFortranParser.y" char* string; -#line 266 "cmFortranParser.cxx" /* yacc.c:352 */ -}; +#line 266 "cmFortranParser.cxx" +}; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 @@ -378,6 +378,8 @@ typedef short yytype_int16; #endif +#define YY_ASSERT(E) ((void) (0 && (E))) + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -509,16 +511,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 593 +#define YYLAST 594 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 41 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 14 /* YYNRULES -- Number of rules. */ -#define YYNRULES 63 +#define YYNRULES 64 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 126 +#define YYNSTATES 127 #define YYUNDEFTOK 2 #define YYMAXUTOK 295 @@ -574,7 +576,7 @@ static const yytype_uint8 yyrline[] = 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246 + 243, 244, 245, 246, 247 }; #endif @@ -626,16 +628,16 @@ static const yytype_int16 yypact[] = -39, 21, -39, 1, -39, -20, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -24, -18, 20, -8, - -3, 39, -39, 15, 16, 18, 19, 33, -39, -39, + -3, 40, -39, 15, 16, 17, 19, 34, -39, -39, -39, -39, -39, -39, 59, -39, -39, -39, -39, -39, - 35, 36, 37, -39, -39, -39, -39, -39, -39, 76, - 114, 129, 167, 182, -39, -39, -39, -39, -39, -39, + 36, 37, 38, -39, -39, -39, -39, -39, -39, 77, + 115, 130, 168, 183, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, 220, 235, 273, 288, -21, 26, -39, 326, - 341, 379, 394, 432, 447, -39, -39, -39, -39, -39, - -39, -39, -39, -39, 38, 40, 41, 485, -39, -39, - -39, -39, -39, -39, 45, -39, -39, -39, 43, 500, - 538, -39, -39, -39, 553, -39 + -39, -39, -39, 221, 236, 274, 289, -21, 26, -39, + 327, 342, 380, 395, 433, 448, -39, -39, -39, -39, + -39, -39, -39, -39, -39, 39, 41, 42, 486, -39, + -39, -39, -39, -39, -39, 18, -39, -39, -39, 43, + 501, 539, -39, -39, -39, 554, -39 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -649,13 +651,13 @@ static const yytype_uint8 yydefact[] = 0, 0, 3, 0, 0, 0, 0, 0, 46, 46, 46, 46, 26, 46, 0, 46, 46, 4, 46, 46, 0, 0, 0, 46, 46, 46, 46, 46, 46, 0, - 0, 0, 0, 0, 15, 57, 56, 62, 58, 59, - 60, 61, 63, 55, 48, 49, 50, 51, 52, 53, - 54, 47, 0, 0, 0, 0, 0, 0, 46, 0, - 0, 0, 0, 0, 0, 21, 22, 23, 24, 14, - 10, 13, 9, 6, 0, 0, 0, 0, 5, 16, - 17, 18, 19, 20, 0, 46, 46, 11, 0, 0, - 0, 46, 7, 12, 0, 8 + 0, 0, 0, 0, 15, 57, 56, 64, 62, 58, + 59, 60, 61, 63, 55, 48, 49, 50, 51, 52, + 53, 54, 47, 0, 0, 0, 0, 0, 0, 46, + 0, 0, 0, 0, 0, 0, 21, 22, 23, 24, + 14, 10, 13, 9, 6, 0, 0, 0, 0, 5, + 16, 17, 18, 19, 20, 0, 46, 46, 11, 0, + 0, 0, 46, 7, 12, 0, 8 }; /* YYPGOTO[NTERM-NUM]. */ @@ -669,7 +671,7 @@ static const yytype_int8 yypgoto[] = static const yytype_int8 yydefgoto[] = { -1, 1, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 44, 81 + 40, 41, 44, 82 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -677,66 +679,66 @@ static const yytype_int8 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint8 yytable[] = { - 59, 60, 61, 62, 42, 63, 104, 82, 83, 105, - 84, 85, 43, 45, 46, 89, 90, 91, 92, 93, - 94, 2, 3, 47, 4, 49, 50, 5, 6, 7, + 59, 60, 61, 62, 42, 63, 105, 83, 84, 106, + 85, 86, 43, 45, 46, 90, 91, 92, 93, 94, + 95, 2, 3, 47, 4, 49, 50, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 54, 0, 55, - 107, 56, 57, 48, 106, 25, 26, 27, 28, 29, - 30, 31, 64, 65, 66, 51, 58, 52, 86, 87, - 88, 114, 53, 115, 116, 118, 121, 119, 120, 95, - 65, 66, 0, 124, 0, 67, 68, 69, 70, 71, - 72, 73, 74, 0, 75, 76, 77, 78, 79, 80, - 0, 0, 67, 68, 69, 70, 71, 72, 73, 74, - 0, 75, 76, 77, 78, 79, 80, 96, 65, 66, + 18, 19, 20, 21, 22, 23, 24, 54, 119, 55, + 56, 108, 57, 48, 107, 25, 26, 27, 28, 29, + 30, 31, 64, 65, 66, 67, 51, 58, 52, 87, + 88, 89, 115, 53, 116, 117, 122, 0, 120, 121, + 96, 65, 66, 67, 125, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, + 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, + 75, 0, 76, 77, 78, 79, 80, 81, 97, 65, + 66, 67, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 98, 65, 66, 67, 0, 0, 0, + 0, 68, 69, 70, 71, 72, 73, 74, 75, 0, + 76, 77, 78, 79, 80, 81, 68, 69, 70, 71, + 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, + 81, 99, 65, 66, 67, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 100, 65, 66, 67, + 0, 0, 0, 0, 68, 69, 70, 71, 72, 73, + 74, 75, 0, 76, 77, 78, 79, 80, 81, 68, + 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, + 78, 79, 80, 81, 101, 65, 66, 67, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, + 65, 66, 67, 0, 0, 0, 0, 68, 69, 70, + 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, + 80, 81, 68, 69, 70, 71, 72, 73, 74, 75, + 0, 76, 77, 78, 79, 80, 81, 103, 65, 66, + 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 104, 65, 66, 67, 0, 0, 0, 0, + 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, + 77, 78, 79, 80, 81, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, + 109, 65, 66, 67, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 110, 65, 66, 67, 0, + 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, + 75, 0, 76, 77, 78, 79, 80, 81, 68, 69, + 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, + 79, 80, 81, 111, 65, 66, 67, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 112, 65, + 66, 67, 0, 0, 0, 0, 68, 69, 70, 71, + 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, + 81, 68, 69, 70, 71, 72, 73, 74, 75, 0, + 76, 77, 78, 79, 80, 81, 113, 65, 66, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 97, 65, 66, 0, 0, 0, 0, 0, - 67, 68, 69, 70, 71, 72, 73, 74, 0, 75, - 76, 77, 78, 79, 80, 67, 68, 69, 70, 71, - 72, 73, 74, 0, 75, 76, 77, 78, 79, 80, - 98, 65, 66, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 99, 65, 66, 0, 0, - 0, 0, 0, 67, 68, 69, 70, 71, 72, 73, - 74, 0, 75, 76, 77, 78, 79, 80, 67, 68, - 69, 70, 71, 72, 73, 74, 0, 75, 76, 77, - 78, 79, 80, 100, 65, 66, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 101, 65, - 66, 0, 0, 0, 0, 0, 67, 68, 69, 70, - 71, 72, 73, 74, 0, 75, 76, 77, 78, 79, - 80, 67, 68, 69, 70, 71, 72, 73, 74, 0, - 75, 76, 77, 78, 79, 80, 102, 65, 66, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 103, 65, 66, 0, 0, 0, 0, 0, 67, - 68, 69, 70, 71, 72, 73, 74, 0, 75, 76, - 77, 78, 79, 80, 67, 68, 69, 70, 71, 72, - 73, 74, 0, 75, 76, 77, 78, 79, 80, 108, - 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 109, 65, 66, 0, 0, 0, - 0, 0, 67, 68, 69, 70, 71, 72, 73, 74, - 0, 75, 76, 77, 78, 79, 80, 67, 68, 69, - 70, 71, 72, 73, 74, 0, 75, 76, 77, 78, - 79, 80, 110, 65, 66, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 111, 65, 66, - 0, 0, 0, 0, 0, 67, 68, 69, 70, 71, - 72, 73, 74, 0, 75, 76, 77, 78, 79, 80, - 67, 68, 69, 70, 71, 72, 73, 74, 0, 75, - 76, 77, 78, 79, 80, 112, 65, 66, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 113, 65, 66, 0, 0, 0, 0, 0, 67, 68, - 69, 70, 71, 72, 73, 74, 0, 75, 76, 77, - 78, 79, 80, 67, 68, 69, 70, 71, 72, 73, - 74, 0, 75, 76, 77, 78, 79, 80, 117, 65, - 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 122, 65, 66, 0, 0, 0, 0, - 0, 67, 68, 69, 70, 71, 72, 73, 74, 0, - 75, 76, 77, 78, 79, 80, 67, 68, 69, 70, - 71, 72, 73, 74, 0, 75, 76, 77, 78, 79, - 80, 123, 65, 66, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 125, 65, 66, 0, - 0, 0, 0, 0, 67, 68, 69, 70, 71, 72, - 73, 74, 0, 75, 76, 77, 78, 79, 80, 67, - 68, 69, 70, 71, 72, 73, 74, 0, 75, 76, - 77, 78, 79, 80 + 0, 114, 65, 66, 67, 0, 0, 0, 0, 68, + 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, + 78, 79, 80, 81, 68, 69, 70, 71, 72, 73, + 74, 75, 0, 76, 77, 78, 79, 80, 81, 118, + 65, 66, 67, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 123, 65, 66, 67, 0, 0, + 0, 0, 68, 69, 70, 71, 72, 73, 74, 75, + 0, 76, 77, 78, 79, 80, 81, 68, 69, 70, + 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, + 80, 81, 124, 65, 66, 67, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 126, 65, 66, + 67, 0, 0, 0, 0, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, + 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, + 77, 78, 79, 80, 81 }; static const yytype_int8 yycheck[] = @@ -745,62 +747,62 @@ static const yytype_int8 yycheck[] = 48, 49, 32, 37, 32, 53, 54, 55, 56, 57, 58, 0, 1, 3, 3, 33, 29, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 32, -1, 33, - 88, 33, 33, 33, 28, 34, 35, 36, 37, 38, - 39, 40, 3, 4, 5, 26, 33, 28, 33, 33, - 33, 33, 33, 33, 33, 30, 33, 115, 116, 3, - 4, 5, -1, 121, -1, 26, 27, 28, 29, 30, + 19, 20, 21, 22, 23, 24, 25, 32, 30, 33, + 33, 89, 33, 33, 28, 34, 35, 36, 37, 38, + 39, 40, 3, 4, 5, 6, 26, 33, 28, 33, + 33, 33, 33, 33, 33, 33, 33, -1, 116, 117, + 3, 4, 5, 6, 122, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, - -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, + -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, + 33, -1, 35, 36, 37, 38, 39, 40, 3, 4, + 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, + 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, + 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, + 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, + -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, + 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, + 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, + 37, 38, 39, 40, 3, 4, 5, 6, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, + 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, + 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 3, 4, 5, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 3, 4, 5, -1, -1, -1, -1, -1, + 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, - 3, 4, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3, 4, 5, -1, -1, + 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, - 38, 39, 40, 3, 4, 5, -1, -1, -1, -1, + 38, 39, 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, - 5, -1, -1, -1, -1, -1, 26, 27, 28, 29, + 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, - 35, 36, 37, 38, 39, 40, 3, 4, 5, -1, + 35, 36, 37, 38, 39, 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3, 4, 5, -1, -1, -1, -1, -1, 26, + -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 3, - 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 3, 4, 5, -1, -1, -1, + 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, - 39, 40, 3, 4, 5, -1, -1, -1, -1, -1, + 39, 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, - -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, + 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, - 36, 37, 38, 39, 40, 3, 4, 5, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, 4, 5, -1, -1, -1, -1, -1, 26, 27, - 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, - 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, - 33, -1, 35, 36, 37, 38, 39, 40, 3, 4, - 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 3, 4, 5, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, - 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, - 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, - 40, 3, 4, 5, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, - -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, - 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, - 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, - 37, 38, 39, 40 + 36, 37, 38, 39, 40 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -813,13 +815,13 @@ static const yytype_uint8 yystos[] = 39, 40, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 3, 32, 53, 37, 32, 3, 33, 33, 29, 26, 28, 33, 32, 33, 33, 33, 33, 53, - 53, 53, 53, 53, 3, 4, 5, 26, 27, 28, - 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, - 40, 54, 53, 53, 53, 53, 33, 33, 33, 53, - 53, 53, 53, 53, 53, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 27, 30, 28, 53, 3, 3, - 3, 3, 3, 3, 33, 33, 33, 3, 30, 53, - 53, 33, 3, 3, 53, 3 + 53, 53, 53, 53, 3, 4, 5, 6, 26, 27, + 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, + 39, 40, 54, 53, 53, 53, 53, 33, 33, 33, + 53, 53, 53, 53, 53, 53, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 27, 30, 28, 53, 3, + 3, 3, 3, 3, 3, 33, 33, 33, 3, 30, + 53, 53, 33, 3, 3, 53, 3 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ @@ -831,7 +833,7 @@ static const yytype_uint8 yyr1[] = 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54 + 54, 54, 54, 54, 54 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -843,7 +845,7 @@ static const yytype_uint8 yyr2[] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1 + 1, 1, 1, 1, 1 }; @@ -930,7 +932,9 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy if (yytype < YYNTOKENS) YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1368,6 +1372,8 @@ yynewstate: | yynewstate -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) @@ -1430,8 +1436,6 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) YYACCEPT; @@ -1499,7 +1503,6 @@ yybackup: YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; @@ -1534,27 +1537,27 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 4: -#line 104 "cmFortranParser.y" /* yacc.c:1652 */ + case 4: +#line 104 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1544 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1547 "cmFortranParser.cxx" break; case 5: -#line 108 "cmFortranParser.y" /* yacc.c:1652 */ +#line 108 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1554 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1557 "cmFortranParser.cxx" break; case 6: -#line 113 "cmFortranParser.y" /* yacc.c:1652 */ +#line 113 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1564,22 +1567,22 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1568 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1571 "cmFortranParser.cxx" break; case 7: -#line 122 "cmFortranParser.y" /* yacc.c:1652 */ +#line 122 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1579 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1582 "cmFortranParser.cxx" break; case 8: -#line 128 "cmFortranParser.y" /* yacc.c:1652 */ +#line 128 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); @@ -1587,40 +1590,40 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1591 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1594 "cmFortranParser.cxx" break; case 9: -#line 135 "cmFortranParser.y" /* yacc.c:1652 */ +#line 135 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1601 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1604 "cmFortranParser.cxx" break; case 10: -#line 140 "cmFortranParser.y" /* yacc.c:1652 */ +#line 140 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1610 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1613 "cmFortranParser.cxx" break; case 11: -#line 144 "cmFortranParser.y" /* yacc.c:1652 */ +#line 144 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1620 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1623 "cmFortranParser.cxx" break; case 12: -#line 149 "cmFortranParser.y" /* yacc.c:1652 */ +#line 149 "cmFortranParser.y" { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1629,139 +1632,140 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1633 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1636 "cmFortranParser.cxx" break; case 13: -#line 157 "cmFortranParser.y" /* yacc.c:1652 */ +#line 157 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1643 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1646 "cmFortranParser.cxx" break; case 14: -#line 162 "cmFortranParser.y" /* yacc.c:1652 */ +#line 162 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1653 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1656 "cmFortranParser.cxx" break; case 15: -#line 167 "cmFortranParser.y" /* yacc.c:1652 */ +#line 167 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1663 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1666 "cmFortranParser.cxx" break; case 16: -#line 172 "cmFortranParser.y" /* yacc.c:1652 */ +#line 172 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1673 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1676 "cmFortranParser.cxx" break; case 17: -#line 177 "cmFortranParser.y" /* yacc.c:1652 */ +#line 177 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1683 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1686 "cmFortranParser.cxx" break; case 18: -#line 182 "cmFortranParser.y" /* yacc.c:1652 */ +#line 182 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1693 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1696 "cmFortranParser.cxx" break; case 19: -#line 187 "cmFortranParser.y" /* yacc.c:1652 */ +#line 187 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1703 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1706 "cmFortranParser.cxx" break; case 20: -#line 192 "cmFortranParser.y" /* yacc.c:1652 */ +#line 192 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1713 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1716 "cmFortranParser.cxx" break; case 21: -#line 197 "cmFortranParser.y" /* yacc.c:1652 */ +#line 197 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1722 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1725 "cmFortranParser.cxx" break; case 22: -#line 201 "cmFortranParser.y" /* yacc.c:1652 */ +#line 201 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1731 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1734 "cmFortranParser.cxx" break; case 23: -#line 205 "cmFortranParser.y" /* yacc.c:1652 */ +#line 205 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1740 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1743 "cmFortranParser.cxx" break; case 24: -#line 209 "cmFortranParser.y" /* yacc.c:1652 */ +#line 209 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1749 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1752 "cmFortranParser.cxx" break; case 48: -#line 231 "cmFortranParser.y" /* yacc.c:1652 */ +#line 231 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1755 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1758 "cmFortranParser.cxx" break; case 55: -#line 238 "cmFortranParser.y" /* yacc.c:1652 */ +#line 238 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1761 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1764 "cmFortranParser.cxx" break; -#line 1765 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1768 "cmFortranParser.cxx" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1994,6 +1998,6 @@ yyreturn: #endif return yyresult; } -#line 249 "cmFortranParser.y" /* yacc.c:1918 */ +#line 250 "cmFortranParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index 87f3e0a16e..1b54dd9f7d 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -244,6 +244,7 @@ misc_code: | RPAREN | COMMA | UNTERMINATED_STRING +| CPP_LINE_DIRECTIVE ; %% diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h index 0da4c1c43e..f66a15cf87 100644 --- a/Source/LexerParser/cmFortranParserTokens.h +++ b/Source/LexerParser/cmFortranParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C @@ -131,16 +131,15 @@ extern int cmFortran_yydebug; /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - union YYSTYPE { -#line 73 "cmFortranParser.y" /* yacc.c:1921 */ +#line 73 "cmFortranParser.y" char* string; -#line 142 "cmFortranParserTokens.h" /* yacc.c:1921 */ -}; +#line 141 "cmFortranParserTokens.h" +}; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index cb89d19fd9..98dd0e212b 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -178,6 +178,10 @@ if(WIN32) target_sources(cmake-gui PRIVATE $<TARGET_OBJECTS:CMakeVersion>) endif() +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET cmake-gui PROPERTY JOB_POOL_LINK "link-bin") +endif() + # cmake-gui has not been updated for `include-what-you-use`. # Block the tool until this is done. set_target_properties(cmake-gui PROPERTIES diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index b608fcbfc6..3b5dc042f1 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -6,6 +6,7 @@ #include <QDir> #include "cmExternalMakefileProjectGenerator.h" +#include "cmGlobalGenerator.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index b85cc33590..0b2750d854 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -64,32 +64,36 @@ */ #include "bindexplib.h" -#include <iostream> +#include <cstddef> #include <sstream> #include <vector> -#include <windows.h> +#ifdef _WIN32 +# include <windows.h> + +# include "cmsys/Encoding.hxx" +#endif -#include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" #include "cmSystemTools.h" -#ifndef IMAGE_FILE_MACHINE_ARM -# define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian -#endif +#ifdef _WIN32 +# ifndef IMAGE_FILE_MACHINE_ARM +# define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian +# endif -#ifndef IMAGE_FILE_MACHINE_THUMB -# define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian -#endif +# ifndef IMAGE_FILE_MACHINE_THUMB +# define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian +# endif -#ifndef IMAGE_FILE_MACHINE_ARMNT -# define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian -#endif +# ifndef IMAGE_FILE_MACHINE_ARMNT +# define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian +# endif -#ifndef IMAGE_FILE_MACHINE_ARM64 -# define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian -#endif +# ifndef IMAGE_FILE_MACHINE_ARM64 +# define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian +# endif typedef struct cmANON_OBJECT_HEADER_BIGOBJ { @@ -306,6 +310,7 @@ private: SymbolTableType* SymbolTable; bool IsI386; }; +#endif bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, std::set<std::string>& symbols, @@ -315,15 +320,15 @@ bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, // break up command line into a vector std::vector<std::string> command; command.push_back(nmPath); - command.push_back("--no-weak"); - command.push_back("--defined-only"); - command.push_back("--format=posix"); - command.push_back(filename); + command.emplace_back("--no-weak"); + command.emplace_back("--defined-only"); + command.emplace_back("--format=posix"); + command.emplace_back(filename); // run the command int exit_code = 0; - cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code, "", - cmSystemTools::OUTPUT_NONE); + cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code, + nullptr, cmSystemTools::OUTPUT_NONE); if (exit_code != 0) { fprintf(stderr, "llvm-nm returned an error: %s\n", output.c_str()); @@ -336,7 +341,7 @@ bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, if (line.empty()) { // last line continue; } - size_t sym_end = line.find(" "); + size_t sym_end = line.find(' '); if (sym_end == std::string::npos) { fprintf(stderr, "Couldn't parse llvm-nm output line: %s\n", line.c_str()); @@ -366,6 +371,9 @@ bool DumpFile(std::string const& nmPath, const char* filename, std::set<std::string>& symbols, std::set<std::string>& dataSymbols) { +#ifndef _WIN32 + return DumpFileWithLlvmNm(nmPath, filename, symbols, dataSymbols); +#else HANDLE hFile; HANDLE hFileMapping; LPVOID lpFileBase; @@ -446,6 +454,7 @@ bool DumpFile(std::string const& nmPath, const char* filename, CloseHandle(hFileMapping); CloseHandle(hFile); return true; +#endif } bool bindexplib::AddObjectFile(const char* filename) diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 6e04ce5829..995088c55c 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -261,9 +261,9 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, case doing_target: target = copy; break; - case doing_depends: { + case doing_depends: depends.push_back(copy); - } break; + break; case doing_outputs: outputs.push_back(filename); break; @@ -343,7 +343,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, // Target is empty, use the output. mf.AddCustomCommandToOutput( output, byproducts, depends, main_dependency, implicit_depends, - commandLines, comment, working.c_str(), false, escapeOldStyle, + commandLines, comment, working.c_str(), nullptr, false, escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool); } else if (!byproducts.empty()) { status.SetError("BYPRODUCTS may not be specified with SOURCE signatures"); diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index e27b126dd8..aa98d8949a 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -6,7 +6,6 @@ #include "cmCheckCustomOutputs.h" #include "cmCustomCommandLines.h" -#include "cmCustomCommandTypes.h" #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -215,9 +214,9 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args, // Add the utility target to the makefile. bool escapeOldStyle = !verbatim; cmTarget* target = mf.AddUtilityCommand( - targetName, cmCommandOrigin::Project, excludeFromAll, - working_directory.c_str(), byproducts, depends, commandLines, - escapeOldStyle, comment, uses_terminal, command_expand_lists, job_pool); + targetName, excludeFromAll, working_directory.c_str(), byproducts, depends, + commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists, + job_pool); // Add additional user-specified source files to the target. target->AddSources(sources); diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 0439c518c0..f443fc664a 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -2,7 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddLibraryCommand.h" -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -309,7 +310,7 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, return true; } - cmAppend(srclists, s, args.end()); + cm::append(srclists, s, args.end()); mf.AddLibrary(libName, type, srclists, excludeFromAll); diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index e0d27eedf9..3b0a223607 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -8,6 +8,7 @@ #include <algorithm> #include <functional> #include <iterator> +#include <memory> #include <unordered_set> #include <utility> #include <vector> @@ -36,12 +37,6 @@ FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last) return first; } -template <typename Container, typename Predicate> -void cmEraseIf(Container& cont, Predicate pred) -{ - cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); -} - template <typename Range, typename Key> auto cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<2>) -> decltype(range.exists(key)) @@ -144,18 +139,6 @@ void cmDeleteAll(Range const& r) ContainerAlgorithms::DefaultDeleter<Range>()); } -template <typename T, typename Range> -void cmAppend(std::vector<T>& v, Range const& r) -{ - v.insert(v.end(), r.begin(), r.end()); -} - -template <typename T, typename InputIt> -void cmAppend(std::vector<T>& v, InputIt first, InputIt last) -{ - v.insert(v.end(), first, last); -} - template <typename Range> typename Range::const_iterator cmRemoveN(Range& r, size_t n) { diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 177bca889a..b5c7e9693a 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -221,10 +221,10 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName, // Pass the call to the makefile instance. std::vector<std::string> no_byproducts; - mf->AddUtilityCommand(utilityName, cmCommandOrigin::Project, - (all ? false : true), nullptr, no_byproducts, depends2, - commandLines); + mf->AddUtilityCommand(utilityName, (all ? false : true), nullptr, + no_byproducts, depends2, commandLines); } + void CCONV cmAddCustomCommand(void* arg, const char* source, const char* command, int numArgs, const char** args, int numDepends, diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h index 6a9514869c..19626f0b87 100644 --- a/Source/cmCPluginAPI.h +++ b/Source/cmCPluginAPI.h @@ -36,7 +36,7 @@ typedef struct of functions are utility functions that are specific to the plugin API =========================================================================*/ /* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how - information is passed from the InitialPass to FInalPass for commands + information is passed from the InitialPass to FinalPass for commands that need a FinalPass and need information from the InitialPass */ void*(CCONV* GetClientData)(void* info); /* return the summed size in characters of all the arguments */ @@ -44,7 +44,7 @@ typedef struct /* free all the memory associated with an argc, argv pair */ void(CCONV* FreeArguments)(int argc, char** argv); /* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how - information is passed from the InitialPass to FInalPass for commands + information is passed from the InitialPass to FinalPass for commands that need a FinalPass and need information from the InitialPass */ void(CCONV* SetClientData)(void* info, void* cd); /* when an error occurs, call this function to set the error string */ diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 6eae26e4c7..22a6e3869e 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -21,6 +21,7 @@ #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/Process.h" +#include "cmsys/RegularExpression.hxx" #include "cmsys/SystemInformation.hxx" #include "cm_curl.h" @@ -32,8 +33,8 @@ #endif #include <cm/memory> +#include <cmext/algorithm> -#include "cmAlgorithms.h" #include "cmCTestBuildAndTestHandler.h" #include "cmCTestBuildHandler.h" #include "cmCTestConfigureHandler.h" @@ -83,8 +84,8 @@ struct cmCTest::Private std::string Name; }; - int RepeatTests = 1; // default to run each test once - bool RepeatUntilFail = false; + int RepeatCount = 1; // default to run each test once + cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; std::string ConfigType; std::string ScheduleType; std::chrono::system_clock::time_point StopTime; @@ -1279,7 +1280,7 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { processOutput.DecodeText(data, length, strdata); if (output) { - cmAppend(tempOutput, data, data + length); + cm::append(tempOutput, data, data + length); } cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(strdata.c_str(), strdata.size())); @@ -1839,11 +1840,16 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, this->SetParallelLevel(plevel); this->Impl->ParallelLevelSetInCli = true; } + if (this->CheckArgument(arg, "--repeat-until-fail")) { if (i >= args.size() - 1) { errormsg = "'--repeat-until-fail' requires an argument"; return false; } + if (this->Impl->RepeatMode != cmCTest::Repeat::Never) { + errormsg = "At most one '--repeat' option may be used."; + return false; + } i++; long repeat = 1; if (!cmStrToLong(args[i], &repeat)) { @@ -1851,9 +1857,42 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, "'--repeat-until-fail' given non-integer value '" + args[i] + "'"; return false; } - this->Impl->RepeatTests = static_cast<int>(repeat); + this->Impl->RepeatCount = static_cast<int>(repeat); if (repeat > 1) { - this->Impl->RepeatUntilFail = true; + this->Impl->RepeatMode = cmCTest::Repeat::UntilFail; + } + } + + if (this->CheckArgument(arg, "--repeat")) { + if (i >= args.size() - 1) { + errormsg = "'--repeat' requires an argument"; + return false; + } + if (this->Impl->RepeatMode != cmCTest::Repeat::Never) { + errormsg = "At most one '--repeat' option may be used."; + return false; + } + i++; + cmsys::RegularExpression repeatRegex( + "^(until-fail|until-pass|after-timeout):([0-9]+)$"); + if (repeatRegex.find(args[i])) { + std::string const& count = repeatRegex.match(2); + unsigned long n = 1; + cmStrToULong(count, &n); // regex guarantees success + this->Impl->RepeatCount = static_cast<int>(n); + if (this->Impl->RepeatCount > 1) { + std::string const& mode = repeatRegex.match(1); + if (mode == "until-fail") { + this->Impl->RepeatMode = cmCTest::Repeat::UntilFail; + } else if (mode == "until-pass") { + this->Impl->RepeatMode = cmCTest::Repeat::UntilPass; + } else if (mode == "after-timeout") { + this->Impl->RepeatMode = cmCTest::Repeat::AfterTimeout; + } + } + } else { + errormsg = "'--repeat' given invalid value '" + args[i] + "'"; + return false; } } @@ -2204,7 +2243,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) bool SRArgumentSpecified = false; // copy the command line - cmAppend(this->Impl->InitialCommandLineArguments, args); + cm::append(this->Impl->InitialCommandLineArguments, args); // process the command line arguments for (size_t i = 1; i < args.size(); ++i) { @@ -2847,14 +2886,14 @@ const std::map<std::string, std::string>& cmCTest::GetDefinitions() const return this->Impl->Definitions; } -int cmCTest::GetTestRepeat() const +int cmCTest::GetRepeatCount() const { - return this->Impl->RepeatTests; + return this->Impl->RepeatCount; } -bool cmCTest::GetRepeatUntilFail() const +cmCTest::Repeat cmCTest::GetRepeatMode() const { - return this->Impl->RepeatUntilFail; + return this->Impl->RepeatMode; } void cmCTest::SetBuildID(const std::string& id) @@ -2964,10 +3003,10 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args, res = cmsysProcess_WaitForData(cp, &data, &length, nullptr); switch (res) { case cmsysProcess_Pipe_STDOUT: - cmAppend(tempOutput, data, data + length); + cm::append(tempOutput, data, data + length); break; case cmsysProcess_Pipe_STDERR: - cmAppend(tempError, data, data + length); + cm::append(tempError, data, data + length); break; default: done = true; diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 82a6f4cbd3..e0ae1000b0 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -431,10 +431,16 @@ public: const std::map<std::string, std::string>& GetDefinitions() const; /** Return the number of times a test should be run */ - int GetTestRepeat() const; + int GetRepeatCount() const; - /** Return true if test should run until fail */ - bool GetRepeatUntilFail() const; + enum class Repeat + { + Never, + UntilFail, + UntilPass, + AfterTimeout, + }; + Repeat GetRepeatMode() const; void GenerateSubprojectsOutput(cmXMLWriter& xml); std::vector<std::string> GetLabelsForSubprojects(); diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index d627465c76..265941abb3 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -190,7 +190,7 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey, if (entryKey.size() > plen && *(end - plen) == '-' && strcmp(end - plen + 1, *p) == 0) { std::string key = entryKey.substr(0, entryKey.size() - plen); - cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->GetCacheIterator(key); if (it.IsAtEnd()) { // Create an entry and store the property. CacheEntry& ne = this->Cache[key]; @@ -497,9 +497,15 @@ cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry( return nullptr; } -cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(const char* key) +cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator( + const std::string& key) { - return { *this, key }; + return { *this, key.c_str() }; +} + +cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator() +{ + return { *this, nullptr }; } const std::string* cmCacheManager::GetInitializedCacheValue( @@ -617,7 +623,7 @@ const char* cmCacheManager::CacheEntry::GetProperty( const std::string& prop) const { if (prop == "TYPE") { - return cmState::CacheEntryTypeToString(this->Type); + return cmState::CacheEntryTypeToString(this->Type).c_str(); } if (prop == "VALUE") { return this->Value.c_str(); @@ -638,20 +644,21 @@ void cmCacheManager::CacheEntry::SetProperty(const std::string& prop, } void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop, - const char* value, + const std::string& value, bool asString) { if (prop == "TYPE") { - this->Type = cmState::StringToCacheEntryType(value ? value : "STRING"); + this->Type = cmState::StringToCacheEntryType(!value.empty() ? value.c_str() + : "STRING"); } else if (prop == "VALUE") { - if (value) { - if (!this->Value.empty() && *value && !asString) { + if (!value.empty()) { + if (!this->Value.empty() && !asString) { this->Value += ";"; } this->Value += value; } } else { - this->Properties.AppendProperty(prop, value, asString); + this->Properties.AppendProperty(prop, value.c_str(), asString); } } @@ -673,7 +680,7 @@ void cmCacheManager::CacheIterator::SetProperty(const std::string& p, } void cmCacheManager::CacheIterator::AppendProperty(const std::string& p, - const char* v, + const std::string& v, bool asString) { if (!this->IsAtEnd()) { diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index faa60c5287..d8be991cd9 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -39,7 +39,7 @@ private: std::vector<std::string> GetPropertyList() const; const char* GetProperty(const std::string&) const; void SetProperty(const std::string& property, const char* value); - void AppendProperty(const std::string& property, const char* value, + void AppendProperty(const std::string& property, const std::string& value, bool asString = false); bool Initialized = false; }; @@ -58,10 +58,10 @@ public: bool GetPropertyAsBool(const std::string&) const; bool PropertyExists(const std::string&) const; void SetProperty(const std::string& property, const char* value); - void AppendProperty(const std::string& property, const char* value, + void AppendProperty(const std::string& property, const std::string& value, bool asString = false); void SetProperty(const std::string& property, bool value); - const char* GetValue() const { return this->GetEntry().Value.c_str(); } + const std::string& GetValue() const { return this->GetEntry().Value; } bool GetValueAsBool() const; void SetValue(const char*); cmStateEnums::CacheEntryType GetType() const @@ -111,7 +111,8 @@ public: void PrintCache(std::ostream&) const; //! Get the iterator for an entry with a given key. - cmCacheManager::CacheIterator GetCacheIterator(const char* key = nullptr); + cmCacheManager::CacheIterator GetCacheIterator(const std::string& key); + cmCacheManager::CacheIterator GetCacheIterator(); //! Remove an entry from the cache void RemoveCacheEntry(const std::string& key); @@ -124,52 +125,52 @@ public: const char* GetCacheEntryValue(const std::string& key) { - cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->GetCacheIterator(key); if (it.IsAtEnd()) { return nullptr; } - return it.GetValue(); + return it.GetValue().c_str(); } const char* GetCacheEntryProperty(std::string const& key, std::string const& propName) { - return this->GetCacheIterator(key.c_str()).GetProperty(propName); + return this->GetCacheIterator(key).GetProperty(propName); } cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) { - return this->GetCacheIterator(key.c_str()).GetType(); + return this->GetCacheIterator(key).GetType(); } bool GetCacheEntryPropertyAsBool(std::string const& key, std::string const& propName) { - return this->GetCacheIterator(key.c_str()).GetPropertyAsBool(propName); + return this->GetCacheIterator(key).GetPropertyAsBool(propName); } void SetCacheEntryProperty(std::string const& key, std::string const& propName, std::string const& value) { - this->GetCacheIterator(key.c_str()).SetProperty(propName, value.c_str()); + this->GetCacheIterator(key).SetProperty(propName, value.c_str()); } void SetCacheEntryBoolProperty(std::string const& key, std::string const& propName, bool value) { - this->GetCacheIterator(key.c_str()).SetProperty(propName, value); + this->GetCacheIterator(key).SetProperty(propName, value); } void SetCacheEntryValue(std::string const& key, std::string const& value) { - this->GetCacheIterator(key.c_str()).SetValue(value.c_str()); + this->GetCacheIterator(key).SetValue(value.c_str()); } void RemoveCacheEntryProperty(std::string const& key, std::string const& propName) { - this->GetCacheIterator(key.c_str()).SetProperty(propName, nullptr); + this->GetCacheIterator(key).SetProperty(propName, nullptr); } void AppendCacheEntryProperty(std::string const& key, @@ -177,8 +178,7 @@ public: std::string const& value, bool asString = false) { - this->GetCacheIterator(key.c_str()) - .AppendProperty(propName, value.c_str(), asString); + this->GetCacheIterator(key).AppendProperty(propName, value, asString); } std::vector<std::string> GetCacheEntryKeys() diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 6f19697bc0..896b6a98de 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -198,6 +198,7 @@ void GetScriptingCommands(cmState* state) #if !defined(CMAKE_BOOTSTRAP) state->AddBuiltinCommand("cmake_host_system_information", cmCMakeHostSystemInformationCommand); + state->AddBuiltinCommand("load_cache", cmLoadCacheCommand); state->AddBuiltinCommand("remove", cmRemoveCommand); state->AddBuiltinCommand("variable_watch", cmVariableWatchCommand); state->AddBuiltinCommand("write_file", cmWriteFileCommand); @@ -279,7 +280,6 @@ void GetProjectCommands(cmState* state) state->AddBuiltinCommand("link_libraries", cmLinkLibrariesCommand); state->AddBuiltinCommand("target_link_directories", cmTargetLinkDirectoriesCommand); - state->AddBuiltinCommand("load_cache", cmLoadCacheCommand); state->AddBuiltinCommand("qt_wrap_cpp", cmQTWrapCPPCommand); state->AddBuiltinCommand("qt_wrap_ui", cmQTWrapUICommand); state->AddBuiltinCommand("remove_definitions", cmRemoveDefinitionsCommand); @@ -339,7 +339,6 @@ void GetProjectCommandsInScriptMode(cmState* state) CM_UNEXPECTED_PROJECT_COMMAND("install"); CM_UNEXPECTED_PROJECT_COMMAND("link_directories"); CM_UNEXPECTED_PROJECT_COMMAND("link_libraries"); - CM_UNEXPECTED_PROJECT_COMMAND("load_cache"); CM_UNEXPECTED_PROJECT_COMMAND("project"); CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_cpp"); CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_ui"); diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 19a096bdf7..9106e70595 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -25,27 +25,29 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator)) , GlobalCommonGenerator(static_cast<cmGlobalCommonGenerator*>( gt->LocalGenerator->GetGlobalGenerator())) - , ConfigName(LocalCommonGenerator->GetConfigName()) + , ConfigNames(LocalCommonGenerator->GetConfigNames()) { } cmCommonTargetGenerator::~cmCommonTargetGenerator() = default; -std::string const& cmCommonTargetGenerator::GetConfigName() const +std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const { - return this->ConfigName; + return this->ConfigNames; } -const char* cmCommonTargetGenerator::GetFeature(const std::string& feature) +const char* cmCommonTargetGenerator::GetFeature(const std::string& feature, + const std::string& config) { - return this->GeneratorTarget->GetFeature(feature, this->ConfigName); + return this->GeneratorTarget->GetFeature(feature, config); } void cmCommonTargetGenerator::AddModuleDefinitionFlag( - cmLinkLineComputer* linkLineComputer, std::string& flags) + cmLinkLineComputer* linkLineComputer, std::string& flags, + const std::string& config) { cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + this->GeneratorTarget->GetModuleDefinitionInfo(config); if (!mdi || mdi->DefFile.empty()) { return; } @@ -94,57 +96,60 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags( } } -std::string cmCommonTargetGenerator::GetFlags(const std::string& l) +std::string cmCommonTargetGenerator::GetFlags(const std::string& l, + const std::string& config) { - auto i = this->FlagsByLanguage.find(l); - if (i == this->FlagsByLanguage.end()) { + auto i = this->Configs[config].FlagsByLanguage.find(l); + if (i == this->Configs[config].FlagsByLanguage.end()) { std::string flags; - this->LocalCommonGenerator->GetTargetCompileFlags( - this->GeneratorTarget, this->ConfigName, l, flags); + this->LocalCommonGenerator->GetTargetCompileFlags(this->GeneratorTarget, + config, l, flags); ByLanguageMap::value_type entry(l, flags); - i = this->FlagsByLanguage.insert(entry).first; + i = this->Configs[config].FlagsByLanguage.insert(entry).first; } return i->second; } -std::string cmCommonTargetGenerator::GetDefines(const std::string& l) +std::string cmCommonTargetGenerator::GetDefines(const std::string& l, + const std::string& config) { - auto i = this->DefinesByLanguage.find(l); - if (i == this->DefinesByLanguage.end()) { + auto i = this->Configs[config].DefinesByLanguage.find(l); + if (i == this->Configs[config].DefinesByLanguage.end()) { std::set<std::string> defines; - this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, - this->ConfigName, l, defines); + this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, config, + l, defines); std::string definesString; this->LocalCommonGenerator->JoinDefines(defines, definesString, l); ByLanguageMap::value_type entry(l, definesString); - i = this->DefinesByLanguage.insert(entry).first; + i = this->Configs[config].DefinesByLanguage.insert(entry).first; } return i->second; } -std::string cmCommonTargetGenerator::GetIncludes(std::string const& l) +std::string cmCommonTargetGenerator::GetIncludes(std::string const& l, + const std::string& config) { - auto i = this->IncludesByLanguage.find(l); - if (i == this->IncludesByLanguage.end()) { + auto i = this->Configs[config].IncludesByLanguage.find(l); + if (i == this->Configs[config].IncludesByLanguage.end()) { std::string includes; - this->AddIncludeFlags(includes, l); + this->AddIncludeFlags(includes, l, config); ByLanguageMap::value_type entry(l, includes); - i = this->IncludesByLanguage.insert(entry).first; + i = this->Configs[config].IncludesByLanguage.insert(entry).first; } return i->second; } -std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories() - const +std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories( + const std::string& config) const { std::vector<std::string> dirs; std::set<cmGeneratorTarget const*> emitted; if (cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->ConfigName)) { + this->GeneratorTarget->GetLinkInformation(config)) { cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); for (auto const& item : items) { cmGeneratorTarget const* linkee = item.Target; @@ -165,19 +170,24 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories() return dirs; } -std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const +std::string cmCommonTargetGenerator::ComputeTargetCompilePDB( + const std::string& config) const { std::string compilePdbPath; if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) { return compilePdbPath; } - compilePdbPath = - this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName()); + compilePdbPath = this->GeneratorTarget->GetCompilePDBPath(config); if (compilePdbPath.empty()) { // Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`. // A trailing slash tells the toolchain to add its default file name. - compilePdbPath = this->GeneratorTarget->GetSupportDirectory() + "/"; + compilePdbPath = this->GeneratorTarget->GetSupportDirectory(); + if (this->GlobalCommonGenerator->IsMultiConfig()) { + compilePdbPath += "/"; + compilePdbPath += config; + } + compilePdbPath += "/"; if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) { // Match VS default for static libs: `$(IntDir)$(ProjectName).pdb`. compilePdbPath += this->GeneratorTarget->GetName(); @@ -188,10 +198,10 @@ std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const return compilePdbPath; } -std::string cmCommonTargetGenerator::GetManifests() +std::string cmCommonTargetGenerator::GetManifests(const std::string& config) { std::vector<cmSourceFile const*> manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, config); std::vector<std::string> manifests; manifests.reserve(manifest_srcs.size()); diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 17792d6ac3..2796470e5f 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -25,42 +25,50 @@ public: cmCommonTargetGenerator(cmGeneratorTarget* gt); virtual ~cmCommonTargetGenerator(); - std::string const& GetConfigName() const; + std::vector<std::string> const& GetConfigNames() const; protected: // Feature query methods. - const char* GetFeature(const std::string& feature); + const char* GetFeature(const std::string& feature, + const std::string& config); // Helper to add flag for windows .def file. void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer, - std::string& flags); + std::string& flags, const std::string& config); cmGeneratorTarget* GeneratorTarget; cmMakefile* Makefile; cmLocalCommonGenerator* LocalCommonGenerator; cmGlobalCommonGenerator* GlobalCommonGenerator; - std::string ConfigName; + std::vector<std::string> ConfigNames; void AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source); - virtual void AddIncludeFlags(std::string& flags, - std::string const& lang) = 0; + virtual void AddIncludeFlags(std::string& flags, std::string const& lang, + const std::string& config) = 0; void AppendOSXVerFlag(std::string& flags, const std::string& lang, const char* name, bool so); - using ByLanguageMap = std::map<std::string, std::string>; - std::string GetFlags(const std::string& l); - ByLanguageMap FlagsByLanguage; - std::string GetDefines(const std::string& l); - ByLanguageMap DefinesByLanguage; - std::string GetIncludes(std::string const& l); - ByLanguageMap IncludesByLanguage; - std::string GetManifests(); + std::string GetFlags(const std::string& l, const std::string& config); + std::string GetDefines(const std::string& l, const std::string& config); + std::string GetIncludes(std::string const& l, const std::string& config); + std::string GetManifests(const std::string& config); + + std::vector<std::string> GetLinkedTargetDirectories( + const std::string& config) const; + std::string ComputeTargetCompilePDB(const std::string& config) const; - std::vector<std::string> GetLinkedTargetDirectories() const; - std::string ComputeTargetCompilePDB() const; +private: + using ByLanguageMap = std::map<std::string, std::string>; + struct ByConfig + { + ByLanguageMap FlagsByLanguage; + ByLanguageMap DefinesByLanguage; + ByLanguageMap IncludesByLanguage; + }; + std::map<std::string, ByConfig> Configs; }; #endif diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 645189ad52..47c821b022 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -7,12 +7,11 @@ #include <map> #include <memory> +#include <queue> #include <set> #include <string> #include <vector> -#include <queue> - #include "cmGraphAdjacencyList.h" #include "cmLinkItem.h" #include "cmTargetLinkLibraryType.h" diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 162bab2987..58ec53a713 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -4,6 +4,7 @@ #include <cassert> #include <cstdio> +#include <memory> #include <sstream> #include <utility> @@ -157,15 +158,12 @@ void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t, void cmComputeTargetDepends::CollectTargets() { // Collect all targets from all generators. - std::vector<cmLocalGenerator*> const& lgens = - this->GlobalGenerator->GetLocalGenerators(); - for (cmLocalGenerator* lgen : lgens) { - const std::vector<cmGeneratorTarget*>& targets = - lgen->GetGeneratorTargets(); - for (cmGeneratorTarget const* ti : targets) { + auto const& lgens = this->GlobalGenerator->GetLocalGenerators(); + for (const auto& lgen : lgens) { + for (const auto& ti : lgen->GetGeneratorTargets()) { int index = static_cast<int>(this->Targets.size()); - this->TargetIndex[ti] = index; - this->Targets.push_back(ti); + this->TargetIndex[ti.get()] = index; + this->Targets.push_back(ti.get()); } } } diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 003e60d572..fda687fd3b 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -9,6 +9,8 @@ #include <sstream> #include <utility> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" #include "cmAlgorithms.h" @@ -396,7 +398,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, // copy to the list structure auto argP1 = arg; argP1++; - cmAppend(newArgs2, argP1, argClose); + cm::append(newArgs2, argP1, argClose); newArgs2.pop_back(); // now recursively invoke IsTrue to handle the values inside the // parenthetical expression diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 5711cae493..da04396b16 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -51,6 +51,8 @@ static std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES"; static std::string const kCMAKE_OSX_DEPLOYMENT_TARGET = "CMAKE_OSX_DEPLOYMENT_TARGET"; static std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT"; +static std::string const kCMAKE_APPLE_ARCH_SYSROOTS = + "CMAKE_APPLE_ARCH_SYSROOTS"; static std::string const kCMAKE_POSITION_INDEPENDENT_CODE = "CMAKE_POSITION_INDEPENDENT_CODE"; static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT"; @@ -723,6 +725,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, vars.insert(kCMAKE_OSX_ARCHITECTURES); vars.insert(kCMAKE_OSX_DEPLOYMENT_TARGET); vars.insert(kCMAKE_OSX_SYSROOT); + vars.insert(kCMAKE_APPLE_ARCH_SYSROOTS); vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE); vars.insert(kCMAKE_SYSROOT); vars.insert(kCMAKE_SYSROOT_COMPILE); @@ -1042,7 +1045,9 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir) if (deletedFiles.insert(fileName).second) { std::string const fullPath = std::string(binDir).append("/").append(fileName); - if (cmSystemTools::FileIsDirectory(fullPath)) { + if (cmSystemTools::FileIsSymlink(fullPath)) { + cmSystemTools::RemoveFile(fullPath); + } else if (cmSystemTools::FileIsDirectory(fullPath)) { this->CleanupFiles(fullPath); cmSystemTools::RemoveADirectory(fullPath); } else { diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx index 09d269b208..0dd8722cf9 100644 --- a/Source/cmCustomCommand.cxx +++ b/Source/cmCustomCommand.cxx @@ -4,27 +4,23 @@ #include <utility> -#include "cmAlgorithms.h" -#include "cmMakefile.h" +#include <cmext/algorithm> -cmCustomCommand::cmCustomCommand(cmMakefile const* mf, - std::vector<std::string> outputs, +cmCustomCommand::cmCustomCommand(std::vector<std::string> outputs, std::vector<std::string> byproducts, std::vector<std::string> depends, cmCustomCommandLines commandLines, - const char* comment, + cmListFileBacktrace lfbt, const char* comment, const char* workingDirectory) : Outputs(std::move(outputs)) , Byproducts(std::move(byproducts)) , Depends(std::move(depends)) , CommandLines(std::move(commandLines)) + , Backtrace(std::move(lfbt)) , Comment(comment ? comment : "") , WorkingDirectory(workingDirectory ? workingDirectory : "") , HaveComment(comment != nullptr) { - if (mf) { - this->Backtrace = mf->GetBacktrace(); - } } const std::vector<std::string>& cmCustomCommand::GetOutputs() const @@ -55,12 +51,12 @@ const char* cmCustomCommand::GetComment() const void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines) { - cmAppend(this->CommandLines, commandLines); + cm::append(this->CommandLines, commandLines); } void cmCustomCommand::AppendDepends(const std::vector<std::string>& depends) { - cmAppend(this->Depends, depends); + cm::append(this->Depends, depends); } bool cmCustomCommand::GetEscapeOldStyle() const @@ -100,7 +96,7 @@ void cmCustomCommand::SetImplicitDepends(cmImplicitDependsList const& l) void cmCustomCommand::AppendImplicitDepends(cmImplicitDependsList const& l) { - cmAppend(this->ImplicitDepends, l); + cm::append(this->ImplicitDepends, l); } bool cmCustomCommand::GetUsesTerminal() const diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index 4689aceea0..d300fa569d 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -12,8 +12,6 @@ #include "cmCustomCommandLines.h" #include "cmListFileCache.h" -class cmMakefile; - class cmImplicitDependsList : public std::vector<std::pair<std::string, std::string>> { @@ -28,11 +26,11 @@ class cmCustomCommand { public: /** Main constructor specifies all information for the command. */ - cmCustomCommand(cmMakefile const* mf, std::vector<std::string> outputs, + cmCustomCommand(std::vector<std::string> outputs, std::vector<std::string> byproducts, std::vector<std::string> depends, - cmCustomCommandLines commandLines, const char* comment, - const char* workingDirectory); + cmCustomCommandLines commandLines, cmListFileBacktrace lfbt, + const char* comment, const char* workingDirectory); /** Get the output file produced by the command. */ const std::vector<std::string>& GetOutputs() const; diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index c1f412df88..c5682530dc 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -6,6 +6,8 @@ #include <memory> #include <utility> +#include <cmext/algorithm> + #include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" @@ -28,11 +30,14 @@ void AppendPaths(const std::vector<std::string>& inputs, cmExpandedList(cge->Evaluate(lg, config)); for (std::string& it : result) { cmSystemTools::ConvertToUnixSlashes(it); + if (cmContains(it, '/') && !cmSystemTools::FileIsFullPath(it)) { + it = cmStrCat(lg->GetMakefile()->GetCurrentBinaryDirectory(), '/', it); + } if (cmSystemTools::FileIsFullPath(it)) { it = cmSystemTools::CollapseFullPath(it); } } - cmAppend(output, result); + cm::append(output, result); } } } @@ -56,7 +61,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(clarg); std::string parsed_arg = cge->Evaluate(this->LG, this->Config); if (this->CC.GetCommandExpandLists()) { - cmAppend(argv, cmExpandedList(parsed_arg)); + cm::append(argv, cmExpandedList(parsed_arg)); } else { argv.push_back(std::move(parsed_arg)); } @@ -201,7 +206,9 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, if (this->OldStyle) { cmd += escapeForShellOldStyle(emulator[j]); } else { - cmd += this->LG->EscapeForShell(emulator[j], this->MakeVars); + cmd += + this->LG->EscapeForShell(emulator[j], this->MakeVars, false, false, + this->MakeVars && this->LG->IsNinjaMulti()); } } @@ -222,7 +229,9 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, if (this->OldStyle) { cmd += escapeForShellOldStyle(arg); } else { - cmd += this->LG->EscapeForShell(arg, this->MakeVars); + cmd += + this->LG->EscapeForShell(arg, this->MakeVars, false, false, + this->MakeVars && this->LG->IsNinjaMulti()); } } } diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index 3bb6e36a37..868c94ae94 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -7,12 +7,11 @@ #include <iosfwd> #include <map> +#include <queue> #include <set> #include <string> #include <vector> -#include <queue> - #include "cmsys/RegularExpression.hxx" #include "cmDepends.h" diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h index 15cada6de3..641263de78 100644 --- a/Source/cmDocumentationSection.h +++ b/Source/cmDocumentationSection.h @@ -8,7 +8,8 @@ #include <string> #include <vector> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmDocumentationEntry.h" // Low-level interface for custom documents: @@ -47,7 +48,7 @@ public: } void Append(const std::vector<cmDocumentationEntry>& entries) { - cmAppend(this->Entries, entries); + cm::append(this->Entries, entries); } /** Append an entry to this section using NULL terminated chars */ diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 5976b2f78b..202b205042 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -10,13 +10,12 @@ #include <vector> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cm_kwiml.h" -#include "cmAlgorithms.h" - // Include the ELF format information system header. #if defined(__OpenBSD__) # include <elf_abi.h> @@ -578,7 +577,7 @@ std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries( } char* pdyn = reinterpret_cast<char*>(&dyn); - cmAppend(result, pdyn, pdyn + sizeof(ELF_Dyn)); + cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn)); } return result; diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 80e4bcd636..5be5bcecfa 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -9,11 +9,12 @@ #include <memory> #include <vector> +#include <cmext/algorithm> + #include "cmsys/Process.h" #include "cm_static_string_view.hxx" -#include "cmAlgorithms.h" #include "cmArgumentParser.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" @@ -402,6 +403,6 @@ void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data, --length; } #endif - cmAppend(output, data, data + length); + cm::append(output, data, data + length); } } diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 7e9a98738d..d22bd48621 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -8,6 +8,7 @@ #include <sstream> #include <utility> +#include "cmAlgorithms.h" #include "cmExportSet.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -300,11 +301,10 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg, std::vector<std::string> exportFiles; std::string ns; - std::map<std::string, cmExportBuildFileGenerator*>& exportSets = - gg->GetBuildExportSets(); + auto& exportSets = gg->GetBuildExportSets(); for (auto const& exp : exportSets) { - const cmExportBuildFileGenerator* exportSet = exp.second; + const auto& exportSet = exp.second; std::vector<std::string> targets; exportSet->GetTargets(targets); if (cmContains(targets, name)) { diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 11fbd02d68..66e8cbb424 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -10,7 +10,8 @@ #include <utility> #include <vector> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExportFileGenerator.h" #include "cmStateTypes.h" @@ -41,7 +42,7 @@ public: void GetTargets(std::vector<std::string>& targets) const; void AppendTargets(std::vector<std::string> const& targets) { - cmAppend(this->Targets, targets); + cm::append(this->Targets, targets); } void SetExportSet(cmExportSet*); diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 2a6bf5df7d..b7cc193e9c 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -6,6 +6,8 @@ #include <sstream> #include <utility> +#include <cm/memory> + #include "cmsys/RegularExpression.hxx" #include "cm_static_string_view.hxx" @@ -182,11 +184,11 @@ bool cmExportCommand(std::vector<std::string> const& args, } // Setup export file generation. - cmExportBuildFileGenerator* ebfg = nullptr; + std::unique_ptr<cmExportBuildFileGenerator> ebfg = nullptr; if (android) { - ebfg = new cmExportBuildAndroidMKGenerator; + ebfg = cm::make_unique<cmExportBuildAndroidMKGenerator>(); } else { - ebfg = new cmExportBuildFileGenerator; + ebfg = cm::make_unique<cmExportBuildFileGenerator>(); } ebfg->SetExportFile(fname.c_str()); ebfg->SetNamespace(arguments.Namespace); @@ -196,7 +198,7 @@ bool cmExportCommand(std::vector<std::string> const& args, } else { ebfg->SetTargets(targets); } - mf.AddExportBuildFileGenerator(ebfg); + mf.AddExportBuildFileGenerator(ebfg.get()); ebfg->SetExportOld(arguments.ExportOld); // Compute the set of configurations exported. @@ -209,9 +211,9 @@ bool cmExportCommand(std::vector<std::string> const& args, ebfg->AddConfiguration(ct); } if (exportSet != nullptr) { - gg->AddBuildExportExportSet(ebfg); + gg->AddBuildExportExportSet(std::move(ebfg)); } else { - gg->AddBuildExportSet(ebfg); + gg->AddBuildExportSet(std::move(ebfg)); } return true; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index aeef602bf6..7a4b8875cd 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -1062,6 +1062,12 @@ void cmExportFileGenerator::GenerateImportTargetCode( if (target->IsCFBundleOnApple()) { os << "set_property(TARGET " << targetName << " PROPERTY BUNDLE 1)\n"; } + + // generate DEPRECATION + if (target->IsDeprecated()) { + os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION " + << cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n"; + } os << "\n"; } diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index 2d732c1db9..9702e0e7c0 100644 --- a/Source/cmExportInstallAndroidMKGenerator.cxx +++ b/Source/cmExportInstallAndroidMKGenerator.cxx @@ -49,7 +49,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode( if (te->ArchiveGenerator) { dest = te->ArchiveGenerator->GetDestination(""); } - te->Target->Target->SetProperty("__dest", dest.c_str()); + te->Target->Target->SetProperty("__dest", dest); } } diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 6d29c9994f..987ec9ea7b 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -258,15 +258,7 @@ void cmExportInstallFileGenerator::LoadConfigFiles(std::ostream& os) void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input) { - std::string::size_type pos = 0; - std::string::size_type lastPos = pos; - - while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != - std::string::npos) { - std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1; - input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}"); - lastPos = endPos; - } + cmGeneratorExpression::ReplaceInstallPrefix(input, "${_IMPORT_PREFIX}"); } bool cmExportInstallFileGenerator::GenerateImportFileConfig( @@ -525,13 +517,14 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget( } std::string cmExportInstallFileGenerator::InstallNameDir( - cmGeneratorTarget* target, const std::string& /*config*/) + cmGeneratorTarget* target, const std::string& config) { std::string install_name_dir; cmMakefile* mf = target->Target->GetMakefile(); if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { - install_name_dir = target->GetInstallNameDirForInstallTree(); + install_name_dir = + target->GetInstallNameDirForInstallTree(config, "${_IMPORT_PREFIX}"); } return install_name_dir; diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index 89093e95fa..6011ba4b0f 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -12,6 +12,7 @@ #include "cmExecutionStatus.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -20,6 +21,8 @@ #include "cmTargetLinkLibraryType.h" #include "cmake.h" +class cmListFileBacktrace; + static void FinalAction(cmMakefile& makefile, std::string const& filename, bool append) { @@ -46,11 +49,11 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename, // the project. cmake* cm = makefile.GetCMakeInstance(); cmGlobalGenerator* global = cm->GetGlobalGenerator(); - const std::vector<cmMakefile*>& locals = global->GetMakefiles(); + const auto& locals = global->GetMakefiles(); std::map<std::string, std::string> libDepsOld; std::map<std::string, std::string> libDepsNew; std::map<std::string, std::string> libTypes; - for (cmMakefile* local : locals) { + for (const auto& local : locals) { for (auto const& tgt : local->GetTargets()) { // Get the current target. cmTarget const& target = tgt.second; @@ -150,9 +153,9 @@ bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args, std::string const& filename = args[0]; bool const append = args.size() > 1 && args[1] == "APPEND"; - status.GetMakefile().AddFinalAction( - [filename, append](cmMakefile& makefile) { - FinalAction(makefile, filename, append); + status.GetMakefile().AddGeneratorAction( + [filename, append](cmLocalGenerator& lg, const cmListFileBacktrace&) { + FinalAction(*lg.GetMakefile(), filename, append); }); return true; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index fafa51b7b3..3df6a5c9a2 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -70,7 +70,8 @@ std::string cmExportTryCompileFileGenerator::FindTargets( std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE, - cmTarget::VisibilityNormal, tgt->Target->GetMakefile()); + cmTarget::VisibilityNormal, tgt->Target->GetMakefile(), + true); cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator()); diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h index a472a06914..2b8d505a34 100644 --- a/Source/cmExternalMakefileProjectGenerator.h +++ b/Source/cmExternalMakefileProjectGenerator.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <string> #include <vector> @@ -78,7 +79,7 @@ public: std::vector<std::string> GetSupportedGlobalGenerators() const; std::vector<std::string> Aliases; - virtual cmExternalMakefileProjectGenerator* + virtual std::unique_ptr<cmExternalMakefileProjectGenerator> CreateExternalMakefileProjectGenerator() const = 0; void AddSupportedGlobalGenerator(const std::string& base); @@ -100,10 +101,10 @@ public: { } - cmExternalMakefileProjectGenerator* CreateExternalMakefileProjectGenerator() - const override + std::unique_ptr<cmExternalMakefileProjectGenerator> + CreateExternalMakefileProjectGenerator() const override { - T* p = new T; + std::unique_ptr<cmExternalMakefileProjectGenerator> p(new T); p->SetName(GetName()); return p; } diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 5a5d959104..b710467c56 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -3,10 +3,13 @@ #include "cmExtraCodeBlocksGenerator.h" #include <map> +#include <memory> #include <ostream> #include <set> #include <utility> +#include <cmext/algorithm> + #include "cmAlgorithms.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -209,7 +212,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // Collect all files std::vector<std::string> listFiles; for (cmLocalGenerator* lg : it.second) { - cmAppend(listFiles, lg->GetMakefile()->GetListFiles()); + cm::append(listFiles, lg->GetMakefile()->GetListFiles()); } // Convert @@ -283,8 +286,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // add all executable and library targets and some of the GLOBAL // and UTILITY targets for (cmLocalGenerator* lg : lgs) { - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = lg->GetGeneratorTargets(); + for (const auto& target : targets) { std::string targetName = target->GetName(); switch (target->GetType()) { case cmStateEnums::GLOBAL_TARGET: { @@ -315,7 +318,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: case cmStateEnums::OBJECT_LIBRARY: { - cmGeneratorTarget* gt = target; + cmGeneratorTarget* gt = target.get(); this->AppendTarget(xml, targetName, gt, make, lg, compiler, makeArgs); std::string fastTarget = cmStrCat(targetName, "/fast"); @@ -341,8 +344,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( for (cmLocalGenerator* lg : lgs) { cmMakefile* makefile = lg->GetMakefile(); - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = lg->GetGeneratorTargets(); + for (const auto& target : targets) { switch (target->GetType()) { case cmStateEnums::EXECUTABLE: case cmStateEnums::STATIC_LIBRARY: @@ -352,13 +355,12 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( case cmStateEnums::UTILITY: // can have sources since 2.6.3 { std::vector<cmSourceFile*> sources; - cmGeneratorTarget* gt = target; - gt->GetSourceFiles(sources, - makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); + target->GetSourceFiles( + sources, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (cmSourceFile* s : sources) { // don't add source files from UTILITY target which have the // GENERATED property set: - if (gt->GetType() == cmStateEnums::UTILITY && + if (target->GetType() == cmStateEnums::UTILITY && s->GetIsGenerated()) { continue; } @@ -391,7 +393,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( } CbpUnit& cbpUnit = allFiles[fullPath]; - cbpUnit.Targets.push_back(target); + cbpUnit.Targets.push_back(target.get()); } } default: // intended fallthrough @@ -558,19 +560,19 @@ void cmExtraCodeBlocksGenerator::AppendTarget( { std::vector<std::string> includes; lg->GetIncludeDirectories(includes, target, "C", buildType); - cmAppend(allIncludeDirs, includes); + cm::append(allIncludeDirs, includes); } std::string systemIncludeDirs = makefile->GetSafeDefinition( "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); if (!systemIncludeDirs.empty()) { - cmAppend(allIncludeDirs, cmExpandedList(systemIncludeDirs)); + cm::append(allIncludeDirs, cmExpandedList(systemIncludeDirs)); } systemIncludeDirs = makefile->GetSafeDefinition( "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); if (!systemIncludeDirs.empty()) { - cmAppend(allIncludeDirs, cmExpandedList(systemIncludeDirs)); + cm::append(allIncludeDirs, cmExpandedList(systemIncludeDirs)); } auto end = cmRemoveDuplicates(allIncludeDirs); diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index c7b74570f7..de40c77d53 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -4,6 +4,7 @@ #include <cstring> #include <map> +#include <memory> #include <set> #include <sstream> #include <utility> @@ -116,10 +117,9 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget( { std::vector<std::string> retval; // for each target in the workspace create a codelite project - const std::vector<cmLocalGenerator*>& lgs = - this->GlobalGenerator->GetLocalGenerators(); - for (cmLocalGenerator* lg : lgs) { - for (cmGeneratorTarget* lt : lg->GetGeneratorTargets()) { + const auto& lgs = this->GlobalGenerator->GetLocalGenerators(); + for (const auto& lg : lgs) { + for (const auto& lt : lg->GetGeneratorTargets()) { cmStateEnums::TargetType type = lt->GetType(); std::string const& outputDir = lg->GetCurrentBinaryDirectory(); std::string targetName = lt->GetName(); @@ -142,7 +142,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget( xml->Attribute("Active", "No"); xml->EndElement(); - CreateNewProjectFile(lt, filename); + CreateNewProjectFile(lt.get(), filename); break; default: break; @@ -269,9 +269,9 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile( for (cmLocalGenerator* lg : lgs) { cmMakefile* makefile = lg->GetMakefile(); - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { - projectType = CollectSourceFiles(makefile, target, cFiles, otherFiles); + for (const auto& target : lg->GetGeneratorTargets()) { + projectType = + CollectSourceFiles(makefile, target.get(), cFiles, otherFiles); } } @@ -634,7 +634,10 @@ std::string cmExtraCodeLiteGenerator::GetBuildCommand( if (generator == "NMake Makefiles" || generator == "Ninja") { ss << make; } else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") { - ss << make << " -f$(ProjectPath)/Makefile -j " << this->CpuCount; + ss << make << " -f$(ProjectPath)/Makefile"; + if (this->CpuCount > 0) { + ss << " -j " << this->CpuCount; + } } if (!targetName.empty()) { ss << " " << targetName; diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index b286acf0c8..78cabce178 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -6,6 +6,7 @@ #include <cassert> #include <cstdio> #include <map> +#include <memory> #include <sstream> #include <utility> @@ -98,7 +99,7 @@ void cmExtraEclipseCDT4Generator::EnableLanguage( void cmExtraEclipseCDT4Generator::Generate() { - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; const cmMakefile* mf = lg->GetMakefile(); std::string eclipseVersion = mf->GetSafeDefinition("CMAKE_ECLIPSE_VERSION"); @@ -175,7 +176,7 @@ void cmExtraEclipseCDT4Generator::Generate() void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile() { - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; cmMakefile* mf = lg->GetMakefile(); const std::string filename = @@ -198,7 +199,7 @@ void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() assert(this->HomeDirectory != this->HomeOutputDirectory); // set up the project name: <project>-Source@<baseSourcePathName> - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; std::string name = cmExtraEclipseCDT4Generator::GenerateProjectName( lg->GetProjectName(), "Source", cmExtraEclipseCDT4Generator::GetPathBasename(this->HomeDirectory)); @@ -231,9 +232,9 @@ void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, const char* envVar, - cmLocalGenerator* lg) + cmLocalGenerator& lg) { - cmMakefile* mf = lg->GetMakefile(); + cmMakefile* mf = lg.GetMakefile(); // get the variables from the environment and from the cache and then // figure out which one to use: @@ -243,7 +244,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar); const std::string* cacheValue = - lg->GetState()->GetInitializedCacheValue(cacheEntryName); + lg.GetState()->GetInitializedCacheValue(cacheEntryName); // now we have both, decide which one to use std::string valueToUse; @@ -256,7 +257,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, valueToUse = envVarValue; mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), cacheEntryName.c_str(), cmStateEnums::STRING, true); - mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory()); + mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); } else if (!envVarSet && cacheValue != nullptr) { // It is already in the cache, but not in the env, so use it from the cache valueToUse = *cacheValue; @@ -272,7 +273,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), cacheEntryName.c_str(), cmStateEnums::STRING, true); - mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory()); + mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); } } @@ -283,7 +284,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, void cmExtraEclipseCDT4Generator::CreateProjectFile() { - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; cmMakefile* mf = lg->GetMakefile(); const std::string filename = this->HomeOutputDirectory + "/.project"; @@ -350,15 +351,15 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() // set vsvars32.bat environment available at CMake time, // but not necessarily when eclipse is open if (compilerId == "MSVC") { - AddEnvVar(environment, "PATH", lg); - AddEnvVar(environment, "INCLUDE", lg); - AddEnvVar(environment, "LIB", lg); - AddEnvVar(environment, "LIBPATH", lg); + AddEnvVar(environment, "PATH", *lg); + AddEnvVar(environment, "INCLUDE", *lg); + AddEnvVar(environment, "LIB", *lg); + AddEnvVar(environment, "LIBPATH", *lg); } else if (compilerId == "Intel") { // if the env.var is set, use this one and put it in the cache // if the env.var is not set, but the value is in the cache, // use it from the cache: - AddEnvVar(environment, "INTEL_LICENSE_FILE", lg); + AddEnvVar(environment, "INTEL_LICENSE_FILE", *lg); } AppendDictionary(xml, "org.eclipse.cdt.make.core.environment", environment.str()); @@ -494,11 +495,11 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml) cmExtraEclipseCDT4Generator::AppendLinkedResource( xml, linkName, "virtual:/virtual", VirtualFolder); - for (cmLocalGenerator* lg : this->GlobalGenerator->GetLocalGenerators()) { + for (const auto& lg : this->GlobalGenerator->GetLocalGenerators()) { cmMakefile* makefile = lg->GetMakefile(); - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); + const auto& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + for (const auto& target : targets) { std::string linkName2 = cmStrCat(linkName, '/'); switch (target->GetType()) { case cmStateEnums::EXECUTABLE: @@ -519,10 +520,9 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml) std::vector<cmSourceGroup> sourceGroups = makefile->GetSourceGroups(); // get the files from the source lists then add them to the groups - cmGeneratorTarget* gt = const_cast<cmGeneratorTarget*>(target); std::vector<cmSourceFile*> files; - gt->GetSourceFiles(files, - makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); + target->GetSourceFiles( + files, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (cmSourceFile* sf : files) { // Add the file to the list of sources. std::string const& source = sf->ResolveFullPath(); @@ -606,7 +606,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const { std::set<std::string> emmited; - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; const cmMakefile* mf = lg->GetMakefile(); const std::string filename = this->HomeOutputDirectory + "/.cproject"; @@ -752,7 +752,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // add pre-processor definitions to allow eclipse to gray out sections emmited.clear(); - for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) { + for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { if (const char* cdefs = lgen->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) { @@ -859,16 +859,15 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // include dirs emmited.clear(); - for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) { - const std::vector<cmGeneratorTarget*>& targets = - lgen->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { + const auto& targets = lgen->GetGeneratorTargets(); + for (const auto& target : targets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } std::vector<std::string> includeDirs; std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE"); - lgen->GetIncludeDirectories(includeDirs, target, "C", config); + lgen->GetIncludeDirectories(includeDirs, target.get(), "C", config); this->AppendIncludeDirectories(xml, includeDirs, emmited); } } @@ -915,16 +914,15 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // add all executable and library targets and some of the GLOBAL // and UTILITY targets - for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) { - const std::vector<cmGeneratorTarget*>& targets = - lgen->GetGeneratorTargets(); + for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { + const auto& targets = lgen->GetGeneratorTargets(); std::string subdir = lgen->MaybeConvertToRelativePath( this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory()); if (subdir == ".") { subdir.clear(); } - for (cmGeneratorTarget* target : targets) { + for (const auto& target : targets) { std::string targetName = target->GetName(); switch (target->GetType()) { case cmStateEnums::GLOBAL_TARGET: { @@ -975,8 +973,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const std::string cleanArgs = cmStrCat("-E chdir \"", lgen->GetCurrentBinaryDirectory(), "\" \"", cmSystemTools::GetCMakeCommand(), "\" -P \""); - cmGeneratorTarget* gt = target; - cleanArgs += lgen->GetTargetDirectory(gt); + cleanArgs += lgen->GetTargetDirectory(target.get()); cleanArgs += "/cmake_clean.cmake\""; cmExtraEclipseCDT4Generator::AppendTarget( xml, "Clean", cmSystemTools::GetCMakeCommand(), cleanArgs, diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h index ff4c59eeb0..a7aa549ddb 100644 --- a/Source/cmExtraEclipseCDT4Generator.h +++ b/Source/cmExtraEclipseCDT4Generator.h @@ -86,7 +86,7 @@ private: std::set<std::string>& emittedDirs); static void AddEnvVar(std::ostream& out, const char* envVar, - cmLocalGenerator* lg); + cmLocalGenerator& lg); void WriteGroups(std::vector<cmSourceGroup> const& sourceGroups, std::string& linkName, cmXMLWriter& xml); diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index e8c9dd0020..e46342076e 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -3,6 +3,7 @@ #include "cmExtraKateGenerator.h" #include <cstring> +#include <memory> #include <ostream> #include <set> #include <vector> @@ -40,21 +41,21 @@ cmExternalMakefileProjectGeneratorFactory* cmExtraKateGenerator::GetFactory() void cmExtraKateGenerator::Generate() { - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; const cmMakefile* mf = lg->GetMakefile(); this->ProjectName = this->GenerateProjectName( lg->GetProjectName(), mf->GetSafeDefinition("CMAKE_BUILD_TYPE"), this->GetPathBasename(lg->GetBinaryDirectory())); this->UseNinja = (this->GlobalGenerator->GetName() == "Ninja"); - this->CreateKateProjectFile(lg); - this->CreateDummyKateProjectFile(lg); + this->CreateKateProjectFile(*lg); + this->CreateDummyKateProjectFile(*lg); } void cmExtraKateGenerator::CreateKateProjectFile( - const cmLocalGenerator* lg) const + const cmLocalGenerator& lg) const { - std::string filename = cmStrCat(lg->GetBinaryDirectory(), "/.kateproject"); + std::string filename = cmStrCat(lg.GetBinaryDirectory(), "/.kateproject"); cmGeneratedFileStream fout(filename); if (!fout) { return; @@ -64,21 +65,21 @@ void cmExtraKateGenerator::CreateKateProjectFile( fout << "{\n" "\t\"name\": \"" << this->ProjectName << "\",\n" - "\t\"directory\": \"" << lg->GetSourceDirectory() << "\",\n" + "\t\"directory\": \"" << lg.GetSourceDirectory() << "\",\n" "\t\"files\": [ { " << this->GenerateFilesString(lg) << "} ],\n"; /* clang-format on */ this->WriteTargets(lg, fout); fout << "}\n"; } -void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg, +void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg, cmGeneratedFileStream& fout) const { - cmMakefile const* mf = lg->GetMakefile(); + cmMakefile const* mf = lg.GetMakefile(); const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); const std::string& makeArgs = mf->GetSafeDefinition("CMAKE_KATE_MAKE_ARGUMENTS"); - std::string const& homeOutputDir = lg->GetBinaryDirectory(); + std::string const& homeOutputDir = lg.GetBinaryDirectory(); /* clang-format off */ fout << @@ -109,14 +110,12 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg, // add all executable and library targets and some of the GLOBAL // and UTILITY targets - for (cmLocalGenerator* localGen : - this->GlobalGenerator->GetLocalGenerators()) { - const std::vector<cmGeneratorTarget*>& targets = - localGen->GetGeneratorTargets(); + for (const auto& localGen : this->GlobalGenerator->GetLocalGenerators()) { + const auto& targets = localGen->GetGeneratorTargets(); std::string currentDir = localGen->GetCurrentBinaryDirectory(); bool topLevel = (currentDir == localGen->GetBinaryDirectory()); - for (cmGeneratorTarget* target : targets) { + for (const auto& target : targets) { std::string const& targetName = target->GetName(); switch (target->GetType()) { case cmStateEnums::GLOBAL_TARGET: { @@ -205,10 +204,10 @@ void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout, } void cmExtraKateGenerator::CreateDummyKateProjectFile( - const cmLocalGenerator* lg) const + const cmLocalGenerator& lg) const { std::string filename = - cmStrCat(lg->GetBinaryDirectory(), '/', this->ProjectName, ".kateproject"); + cmStrCat(lg.GetBinaryDirectory(), '/', this->ProjectName, ".kateproject"); cmGeneratedFileStream fout(filename); if (!fout) { return; @@ -219,26 +218,25 @@ void cmExtraKateGenerator::CreateDummyKateProjectFile( } std::string cmExtraKateGenerator::GenerateFilesString( - const cmLocalGenerator* lg) const + const cmLocalGenerator& lg) const { - std::string s = cmStrCat(lg->GetSourceDirectory(), "/.git"); + std::string s = cmStrCat(lg.GetSourceDirectory(), "/.git"); if (cmSystemTools::FileExists(s)) { return "\"git\": 1 "; } - s = cmStrCat(lg->GetSourceDirectory(), "/.svn"); + s = cmStrCat(lg.GetSourceDirectory(), "/.svn"); if (cmSystemTools::FileExists(s)) { return "\"svn\": 1 "; } - s = cmStrCat(lg->GetSourceDirectory(), '/'); + s = cmStrCat(lg.GetSourceDirectory(), '/'); std::set<std::string> files; std::string tmp; - const std::vector<cmLocalGenerator*>& lgs = - this->GlobalGenerator->GetLocalGenerators(); + const auto& lgs = this->GlobalGenerator->GetLocalGenerators(); - for (cmLocalGenerator* lgen : lgs) { + for (const auto& lgen : lgs) { cmMakefile* makefile = lgen->GetMakefile(); const std::vector<std::string>& listFiles = makefile->GetListFiles(); for (std::string const& listFile : listFiles) { diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h index be1376aa2f..1fb81b482d 100644 --- a/Source/cmExtraKateGenerator.h +++ b/Source/cmExtraKateGenerator.h @@ -25,16 +25,16 @@ public: void Generate() override; private: - void CreateKateProjectFile(const cmLocalGenerator* lg) const; - void CreateDummyKateProjectFile(const cmLocalGenerator* lg) const; - void WriteTargets(const cmLocalGenerator* lg, + void CreateKateProjectFile(const cmLocalGenerator& lg) const; + void CreateDummyKateProjectFile(const cmLocalGenerator& lg) const; + void WriteTargets(const cmLocalGenerator& lg, cmGeneratedFileStream& fout) const; void AppendTarget(cmGeneratedFileStream& fout, const std::string& target, const std::string& make, const std::string& makeArgs, const std::string& path, const std::string& homeOutputDir) const; - std::string GenerateFilesString(const cmLocalGenerator* lg) const; + std::string GenerateFilesString(const cmLocalGenerator& lg) const; std::string GetPathBasename(const std::string& path) const; std::string GenerateProjectName(const std::string& name, const std::string& type, diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 495324cbf3..603fea38da 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -3,6 +3,7 @@ #include "cmExtraSublimeTextGenerator.h" #include <cstring> +#include <memory> #include <set> #include <sstream> #include <utility> @@ -182,8 +183,8 @@ void cmExtraSublimeTextGenerator::AppendAllTargets( // and UTILITY targets for (cmLocalGenerator* lg : lgs) { cmMakefile* makefile = lg->GetMakefile(); - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = lg->GetGeneratorTargets(); + for (const auto& target : targets) { std::string targetName = target->GetName(); switch (target->GetType()) { case cmStateEnums::GLOBAL_TARGET: { @@ -216,11 +217,11 @@ void cmExtraSublimeTextGenerator::AppendAllTargets( case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: case cmStateEnums::OBJECT_LIBRARY: { - this->AppendTarget(fout, targetName, lg, target, make.c_str(), + this->AppendTarget(fout, targetName, lg, target.get(), make.c_str(), makefile, compiler.c_str(), sourceFileFlags, false); std::string fastTarget = cmStrCat(targetName, "/fast"); - this->AppendTarget(fout, fastTarget, lg, target, make.c_str(), + this->AppendTarget(fout, fastTarget, lg, target.get(), make.c_str(), makefile, compiler.c_str(), sourceFileFlags, false); } break; diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 11844e47d6..d88617a01b 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -6,15 +6,20 @@ #include "cmCustomCommandLines.h" #include "cmExecutionStatus.h" +#include "cmListFileCache.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmake.h" class cmTarget; -static void FinalAction(cmMakefile& makefile, std::string const& name) +static void FinalAction(cmMakefile& makefile, std::string const& name, + const cmListFileBacktrace& lfbt) { // people should add the srcs to the target themselves, but the old command // didn't support that, so check and see if they added the files in and if @@ -26,7 +31,8 @@ static void FinalAction(cmMakefile& makefile, std::string const& name) ". The problem was found while processing the source directory: ", makefile.GetCurrentSourceDirectory(), ". This FLTK_WRAP_UI call will be ignored."); - cmSystemTools::Message(msg, "Warning"); + makefile.GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_ERROR, msg, + lfbt); } } @@ -116,7 +122,9 @@ bool cmFLTKWrapUICommand(std::vector<std::string> const& args, std::string const varName = target + "_FLTK_UI_SRCS"; mf.AddDefinition(varName, sourceListValue); - mf.AddFinalAction( - [target](cmMakefile& makefile) { FinalAction(makefile, target); }); + mf.AddGeneratorAction( + [target](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) { + FinalAction(*lg.GetMakefile(), target, lfbt); + }); return true; } diff --git a/Source/cmFileAPICMakeFiles.cxx b/Source/cmFileAPICMakeFiles.cxx index f419997710..44ba96c253 100644 --- a/Source/cmFileAPICMakeFiles.cxx +++ b/Source/cmFileAPICMakeFiles.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFileAPICMakeFiles.h" +#include <memory> #include <string> #include <vector> @@ -67,7 +68,7 @@ Json::Value CMakeFiles::DumpInputs() cmGlobalGenerator* gg = this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); - for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) { + for (const auto& lg : gg->GetLocalGenerators()) { cmMakefile const* mf = lg->GetMakefile(); for (std::string const& file : mf->GetListFiles()) { inputs.append(this->DumpInput(file)); diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index d7993c7d9f..d13e8ec191 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -15,9 +15,10 @@ #include <utility> #include <vector> +#include <cmext/algorithm> + #include "cm_jsoncpp_value.h" -#include "cmAlgorithms.h" #include "cmCryptoHash.h" #include "cmFileAPI.h" #include "cmGeneratorExpression.h" @@ -426,7 +427,7 @@ Json::Value Codemodel::DumpConfigurations() Json::Value configurations = Json::arrayValue; cmGlobalGenerator* gg = this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); - auto makefiles = gg->GetMakefiles(); + const auto& makefiles = gg->GetMakefiles(); if (!makefiles.empty()) { std::vector<std::string> const& configs = makefiles[0]->GetGeneratorConfigs(); @@ -469,17 +470,17 @@ void CodemodelConfig::ProcessDirectories() { cmGlobalGenerator* gg = this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); - std::vector<cmLocalGenerator*> const& localGens = gg->GetLocalGenerators(); + auto const& localGens = gg->GetLocalGenerators(); // Add directories in forward order to process parents before children. this->Directories.reserve(localGens.size()); - for (cmLocalGenerator* lg : localGens) { + for (const auto& lg : localGens) { auto directoryIndex = static_cast<Json::ArrayIndex>(this->Directories.size()); this->Directories.emplace_back(); Directory& d = this->Directories[directoryIndex]; d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory(); - d.LocalGenerator = lg; + d.LocalGenerator = lg.get(); this->DirectoryMap[d.Snapshot] = directoryIndex; d.ProjectIndex = this->AddProject(d.Snapshot); @@ -554,8 +555,8 @@ Json::Value CodemodelConfig::DumpTargets() std::vector<cmGeneratorTarget*> targetList; cmGlobalGenerator* gg = this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); - for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) { - cmAppend(targetList, lg->GetGeneratorTargets()); + for (const auto& lg : gg->GetLocalGenerators()) { + cm::append(targetList, lg->GetGeneratorTargets()); } std::sort(targetList.begin(), targetList.end(), [](cmGeneratorTarget* l, cmGeneratorTarget* r) { diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index d55b959e8e..1fdfa87ea3 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -15,6 +15,7 @@ #include <vector> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" @@ -24,7 +25,6 @@ #include "cm_static_string_view.hxx" #include "cm_sys_stat.h" -#include "cmAlgorithms.h" #include "cmArgumentParser.h" #include "cmCryptoHash.h" #include "cmExecutionStatus.h" @@ -783,7 +783,7 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse, } std::vector<std::string>& foundFiles = g.GetFiles(); - cmAppend(files, foundFiles); + cm::append(files, foundFiles); if (configureDepends) { std::sort(foundFiles.begin(), foundFiles.end()); @@ -1394,8 +1394,8 @@ size_t cmWriteToMemoryCallback(void* ptr, size_t size, size_t nmemb, { int realsize = static_cast<int>(size * nmemb); const char* chPtr = static_cast<char*>(ptr); - cmAppend(*static_cast<cmFileCommandVectorOfChar*>(data), chPtr, - chPtr + realsize); + cm::append(*static_cast<cmFileCommandVectorOfChar*>(data), chPtr, + chPtr + realsize); return realsize; } @@ -1408,7 +1408,7 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr, case CURLINFO_TEXT: case CURLINFO_HEADER_IN: case CURLINFO_HEADER_OUT: - cmAppend(vec, chPtr, chPtr + size); + cm::append(vec, chPtr, chPtr + size); break; case CURLINFO_DATA_IN: case CURLINFO_DATA_OUT: @@ -1418,7 +1418,7 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr, int n = sprintf(buf, "[%" KWIML_INT_PRIu64 " bytes data]\n", static_cast<KWIML_INT_uint64_t>(size)); if (n > 0) { - cmAppend(vec, buf, buf + n); + cm::append(vec, buf, buf + n); } } break; default: diff --git a/Source/cmFileLock.cxx b/Source/cmFileLock.cxx index e90f57140e..6010233cad 100644 --- a/Source/cmFileLock.cxx +++ b/Source/cmFileLock.cxx @@ -3,11 +3,23 @@ #include "cmFileLock.h" #include <cassert> +#include <utility> #include "cmFileLockResult.h" // Common implementation +cmFileLock::cmFileLock(cmFileLock&& other) noexcept +{ + this->File = other.File; +#if defined(_WIN32) + other.File = INVALID_HANDLE_VALUE; +#else + other.File = -1; +#endif + this->Filename = std::move(other.Filename); +} + cmFileLock::~cmFileLock() { if (!this->Filename.empty()) { @@ -17,6 +29,19 @@ cmFileLock::~cmFileLock() } } +cmFileLock& cmFileLock::operator=(cmFileLock&& other) noexcept +{ + this->File = other.File; +#if defined(_WIN32) + other.File = INVALID_HANDLE_VALUE; +#else + other.File = -1; +#endif + this->Filename = std::move(other.Filename); + + return *this; +} + cmFileLockResult cmFileLock::Lock(const std::string& filename, unsigned long timeout) { diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h index 2130d65dbe..5fe068e8f1 100644 --- a/Source/cmFileLock.h +++ b/Source/cmFileLock.h @@ -26,7 +26,9 @@ public: ~cmFileLock(); cmFileLock(cmFileLock const&) = delete; + cmFileLock(cmFileLock&&) noexcept; cmFileLock& operator=(cmFileLock const&) = delete; + cmFileLock& operator=(cmFileLock&&) noexcept; /** * @brief Lock the file. diff --git a/Source/cmFileLockPool.cxx b/Source/cmFileLockPool.cxx index 8db2db2103..e1f6e948a9 100644 --- a/Source/cmFileLockPool.cxx +++ b/Source/cmFileLockPool.cxx @@ -3,40 +3,34 @@ #include "cmFileLockPool.h" #include <cassert> +#include <utility> -#include "cmAlgorithms.h" #include "cmFileLock.h" #include "cmFileLockResult.h" cmFileLockPool::cmFileLockPool() = default; -cmFileLockPool::~cmFileLockPool() -{ - cmDeleteAll(this->FunctionScopes); - cmDeleteAll(this->FileScopes); -} +cmFileLockPool::~cmFileLockPool() = default; void cmFileLockPool::PushFunctionScope() { - this->FunctionScopes.push_back(new ScopePool()); + this->FunctionScopes.push_back(ScopePool()); } void cmFileLockPool::PopFunctionScope() { assert(!this->FunctionScopes.empty()); - delete this->FunctionScopes.back(); this->FunctionScopes.pop_back(); } void cmFileLockPool::PushFileScope() { - this->FileScopes.push_back(new ScopePool()); + this->FileScopes.push_back(ScopePool()); } void cmFileLockPool::PopFileScope() { assert(!this->FileScopes.empty()); - delete this->FileScopes.back(); this->FileScopes.pop_back(); } @@ -49,7 +43,7 @@ cmFileLockResult cmFileLockPool::LockFunctionScope(const std::string& filename, if (this->FunctionScopes.empty()) { return cmFileLockResult::MakeNoFunction(); } - return this->FunctionScopes.back()->Lock(filename, timeoutSec); + return this->FunctionScopes.back().Lock(filename, timeoutSec); } cmFileLockResult cmFileLockPool::LockFileScope(const std::string& filename, @@ -59,7 +53,7 @@ cmFileLockResult cmFileLockPool::LockFileScope(const std::string& filename, return cmFileLockResult::MakeAlreadyLocked(); } assert(!this->FileScopes.empty()); - return this->FileScopes.back()->Lock(filename, timeoutSec); + return this->FileScopes.back().Lock(filename, timeoutSec); } cmFileLockResult cmFileLockPool::LockProcessScope(const std::string& filename, @@ -74,14 +68,14 @@ cmFileLockResult cmFileLockPool::LockProcessScope(const std::string& filename, cmFileLockResult cmFileLockPool::Release(const std::string& filename) { for (auto& funcScope : this->FunctionScopes) { - const cmFileLockResult result = funcScope->Release(filename); + const cmFileLockResult result = funcScope.Release(filename); if (!result.IsOk()) { return result; } } for (auto& fileScope : this->FileScopes) { - const cmFileLockResult result = fileScope->Release(filename); + const cmFileLockResult result = fileScope.Release(filename); if (!result.IsOk()) { return result; } @@ -93,14 +87,14 @@ cmFileLockResult cmFileLockPool::Release(const std::string& filename) bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const { for (auto const& funcScope : this->FunctionScopes) { - const bool result = funcScope->IsAlreadyLocked(filename); + const bool result = funcScope.IsAlreadyLocked(filename); if (result) { return true; } } for (auto const& fileScope : this->FileScopes) { - const bool result = fileScope->IsAlreadyLocked(filename); + const bool result = fileScope.IsAlreadyLocked(filename); if (result) { return true; } @@ -111,21 +105,29 @@ bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const cmFileLockPool::ScopePool::ScopePool() = default; -cmFileLockPool::ScopePool::~ScopePool() +cmFileLockPool::ScopePool::~ScopePool() = default; + +cmFileLockPool::ScopePool::ScopePool(ScopePool&&) noexcept = default; + +cmFileLockPool::ScopePool& cmFileLockPool::ScopePool::operator=( + ScopePool&& other) noexcept { - cmDeleteAll(this->Locks); + if (this != &other) { + this->Locks = std::move(other.Locks); + } + + return *this; } cmFileLockResult cmFileLockPool::ScopePool::Lock(const std::string& filename, unsigned long timeoutSec) { - cmFileLock* lock = new cmFileLock(); - const cmFileLockResult result = lock->Lock(filename, timeoutSec); + cmFileLock lock; + const cmFileLockResult result = lock.Lock(filename, timeoutSec); if (result.IsOk()) { - this->Locks.push_back(lock); + this->Locks.push_back(std::move(lock)); return cmFileLockResult::MakeOk(); } - delete lock; return result; } @@ -133,8 +135,8 @@ cmFileLockResult cmFileLockPool::ScopePool::Release( const std::string& filename) { for (auto& lock : this->Locks) { - if (lock->IsLocked(filename)) { - return lock->Release(); + if (lock.IsLocked(filename)) { + return lock.Release(); } } return cmFileLockResult::MakeOk(); @@ -144,7 +146,7 @@ bool cmFileLockPool::ScopePool::IsAlreadyLocked( const std::string& filename) const { for (auto const& lock : this->Locks) { - if (lock->IsLocked(filename)) { + if (lock.IsLocked(filename)) { return true; } } diff --git a/Source/cmFileLockPool.h b/Source/cmFileLockPool.h index dae68dd011..d45c82cc41 100644 --- a/Source/cmFileLockPool.h +++ b/Source/cmFileLockPool.h @@ -8,7 +8,8 @@ #include <string> #include <vector> -class cmFileLock; +#include "cmFileLock.h" + class cmFileLockResult; class cmFileLockPool @@ -64,7 +65,9 @@ private: ~ScopePool(); ScopePool(ScopePool const&) = delete; + ScopePool(ScopePool&&) noexcept; ScopePool& operator=(ScopePool const&) = delete; + ScopePool& operator=(ScopePool&&) noexcept; cmFileLockResult Lock(const std::string& filename, unsigned long timeoutSec); @@ -72,17 +75,12 @@ private: bool IsAlreadyLocked(const std::string& filename) const; private: - using List = std::vector<cmFileLock*>; - using It = List::iterator; - using CIt = List::const_iterator; + using List = std::vector<cmFileLock>; List Locks; }; - using List = std::vector<ScopePool*>; - - using It = List::iterator; - using CIt = List::const_iterator; + using List = std::vector<ScopePool>; List FunctionScopes; List FileScopes; diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx index ac8a37eee0..8cfdb2ddd8 100644 --- a/Source/cmFileMonitor.cxx +++ b/Source/cmFileMonitor.cxx @@ -7,9 +7,9 @@ #include <unordered_map> #include <utility> -#include "cmsys/SystemTools.hxx" +#include <cm/memory> -#include "cmAlgorithms.h" +#include "cmsys/SystemTools.hxx" namespace { void on_directory_change(uv_fs_event_t* handle, const char* filename, @@ -37,12 +37,12 @@ public: class cmVirtualDirectoryWatcher : public cmIBaseWatcher { public: - ~cmVirtualDirectoryWatcher() override { cmDeleteAll(this->Children); } + ~cmVirtualDirectoryWatcher() override = default; cmIBaseWatcher* Find(const std::string& ps) { const auto i = this->Children.find(ps); - return (i == this->Children.end()) ? nullptr : i->second; + return (i == this->Children.end()) ? nullptr : i->second.get(); } void Trigger(const std::string& pathSegment, int events, @@ -96,11 +96,7 @@ public: return result; } - void Reset() - { - cmDeleteAll(this->Children); - this->Children.clear(); - } + void Reset() { this->Children.clear(); } void AddChildWatcher(const std::string& ps, cmIBaseWatcher* watcher) { @@ -108,11 +104,12 @@ public: assert(this->Children.find(ps) == this->Children.end()); assert(watcher); - this->Children.emplace(std::make_pair(ps, watcher)); + this->Children.emplace(ps, std::unique_ptr<cmIBaseWatcher>(watcher)); } private: - std::unordered_map<std::string, cmIBaseWatcher*> Children; // owned! + std::unordered_map<std::string, std::unique_ptr<cmIBaseWatcher>> + Children; // owned! }; // Root of all the different (on windows!) root directories: @@ -295,14 +292,11 @@ void on_fs_close(uv_handle_t* handle) } // namespace cmFileMonitor::cmFileMonitor(uv_loop_t* l) - : Root(new cmRootWatcher(l)) + : Root(cm::make_unique<cmRootWatcher>(l)) { } -cmFileMonitor::~cmFileMonitor() -{ - delete this->Root; -} +cmFileMonitor::~cmFileMonitor() = default; void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths, Callback const& cb) @@ -316,7 +310,7 @@ void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths, if (segmentCount < 2) { // Expect at least rootdir and filename continue; } - cmVirtualDirectoryWatcher* currentWatcher = this->Root; + cmVirtualDirectoryWatcher* currentWatcher = this->Root.get(); for (size_t i = 0; i < segmentCount; ++i) { assert(currentWatcher); @@ -334,11 +328,12 @@ void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths, cmIBaseWatcher* nextWatcher = currentWatcher->Find(currentSegment); if (!nextWatcher) { if (rootSegment) { // Root part - assert(currentWatcher == this->Root); - nextWatcher = new cmRootDirectoryWatcher(this->Root, currentSegment); + assert(currentWatcher == this->Root.get()); + nextWatcher = + new cmRootDirectoryWatcher(this->Root.get(), currentSegment); assert(currentWatcher->Find(currentSegment) == nextWatcher); } else if (fileSegment) { // File part - assert(currentWatcher != this->Root); + assert(currentWatcher != this->Root.get()); nextWatcher = new cmFileWatcher( dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher), currentSegment, cb); diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h index 7ffc9294ef..b510a2cd24 100644 --- a/Source/cmFileMonitor.h +++ b/Source/cmFileMonitor.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <functional> +#include <memory> #include <string> #include <vector> @@ -30,5 +31,5 @@ public: std::vector<std::string> WatchedDirectories() const; private: - cmRootWatcher* Root; + std::unique_ptr<cmRootWatcher> Root; }; diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 7d741182d2..bec99bb7ee 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -4,10 +4,11 @@ #include <cstddef> #include <deque> -#include <iostream> #include <map> +#include <utility> + +#include <cmext/algorithm> -#include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmRange.h" #include "cmSearchPath.h" @@ -116,17 +117,19 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) this->NoDefaultPath = true; } else if (this->CheckCommonArgument(args[j])) { doing = DoingNone; + } else { // Some common arguments were accidentally supported by CMake // 2.4 and 2.6.0 in the short-hand form of the command, so we // must support it even though it is not documented. - } else if (doing == DoingNames) { - this->Names.push_back(args[j]); - } else if (doing == DoingPaths) { - this->UserGuessArgs.push_back(args[j]); - } else if (doing == DoingHints) { - this->UserHintsArgs.push_back(args[j]); - } else if (doing == DoingPathSuffixes) { - this->AddPathSuffix(args[j]); + if (doing == DoingNames) { + this->Names.push_back(args[j]); + } else if (doing == DoingPaths) { + this->UserGuessArgs.push_back(args[j]); + } else if (doing == DoingHints) { + this->UserHintsArgs.push_back(args[j]); + } else if (doing == DoingPathSuffixes) { + this->AddPathSuffix(args[j]); + } } } @@ -153,7 +156,7 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) std::vector<std::string> shortArgs = this->Names; this->Names.clear(); // clear out any values in Names this->Names.push_back(shortArgs[0]); - cmAppend(this->UserGuessArgs, shortArgs.begin() + 1, shortArgs.end()); + cm::append(this->UserGuessArgs, shortArgs.begin() + 1, shortArgs.end()); } this->ExpandPaths(); @@ -288,33 +291,6 @@ void cmFindBase::FillUserGuessPath() paths.AddSuffixes(this->SearchPathSuffixes); } -void cmFindBase::PrintFindStuff() -{ - std::cerr << "SearchFrameworkLast: " << this->SearchFrameworkLast << "\n"; - std::cerr << "SearchFrameworkOnly: " << this->SearchFrameworkOnly << "\n"; - std::cerr << "SearchFrameworkFirst: " << this->SearchFrameworkFirst << "\n"; - std::cerr << "SearchAppBundleLast: " << this->SearchAppBundleLast << "\n"; - std::cerr << "SearchAppBundleOnly: " << this->SearchAppBundleOnly << "\n"; - std::cerr << "SearchAppBundleFirst: " << this->SearchAppBundleFirst << "\n"; - std::cerr << "VariableName " << this->VariableName << "\n"; - std::cerr << "VariableDocumentation " << this->VariableDocumentation << "\n"; - std::cerr << "NoDefaultPath " << this->NoDefaultPath << "\n"; - std::cerr << "NoCMakeEnvironmentPath " << this->NoCMakeEnvironmentPath - << "\n"; - std::cerr << "NoCMakePath " << this->NoCMakePath << "\n"; - std::cerr << "NoSystemEnvironmentPath " << this->NoSystemEnvironmentPath - << "\n"; - std::cerr << "NoCMakeSystemPath " << this->NoCMakeSystemPath << "\n"; - std::cerr << "EnvironmentPath " << this->EnvironmentPath << "\n"; - std::cerr << "CMakePathName " << this->CMakePathName << "\n"; - std::cerr << "Names " << cmJoin(this->Names, " ") << "\n"; - std::cerr << "\n"; - std::cerr << "SearchPathSuffixes "; - std::cerr << cmJoin(this->SearchPathSuffixes, "\n") << "\n"; - std::cerr << "SearchPaths\n"; - std::cerr << cmWrap("[", this->SearchPaths, "]", "\n") << "\n"; -} - bool cmFindBase::CheckForVariableInCache() { if (const char* cacheValue = @@ -343,3 +319,87 @@ bool cmFindBase::CheckForVariableInCache() } return false; } + +cmFindBaseDebugState::cmFindBaseDebugState(std::string commandName, + cmFindBase const* findBase) + : FindCommand(findBase) + , CommandName(std::move(commandName)) +{ +} + +cmFindBaseDebugState::~cmFindBaseDebugState() +{ + if (this->FindCommand->DebugMode) { + std::string buffer = + cmStrCat(this->CommandName, " called with the following settings:\n"); + buffer += cmStrCat(" VAR: ", this->FindCommand->VariableName, "\n"); + buffer += cmStrCat( + " NAMES: ", cmWrap("\"", this->FindCommand->Names, "\"", "\n "), + "\n"); + buffer += cmStrCat( + " Documentation: ", this->FindCommand->VariableDocumentation, "\n"); + buffer += " Framework\n"; + buffer += cmStrCat(" Only Search Frameworks: ", + this->FindCommand->SearchFrameworkOnly, "\n"); + + buffer += cmStrCat(" Search Frameworks Last: ", + this->FindCommand->SearchFrameworkLast, "\n"); + buffer += cmStrCat(" Search Frameworks First: ", + this->FindCommand->SearchFrameworkFirst, "\n"); + buffer += " AppBundle\n"; + buffer += cmStrCat(" Only Search AppBundle: ", + this->FindCommand->SearchAppBundleOnly, "\n"); + buffer += cmStrCat(" Search AppBundle Last: ", + this->FindCommand->SearchAppBundleLast, "\n"); + buffer += cmStrCat(" Search AppBundle First: ", + this->FindCommand->SearchAppBundleFirst, "\n"); + + if (this->FindCommand->NoDefaultPath) { + buffer += " NO_DEFAULT_PATH Enabled\n"; + } else { + buffer += cmStrCat( + " CMAKE_FIND_USE_CMAKE_PATH: ", !this->FindCommand->NoCMakePath, "\n", + " CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: ", + !this->FindCommand->NoCMakeEnvironmentPath, "\n", + " CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: ", + !this->FindCommand->NoSystemEnvironmentPath, "\n", + " CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: ", + !this->FindCommand->NoCMakeSystemPath, "\n"); + } + + buffer += + cmStrCat(this->CommandName, " considered the following locations:\n"); + for (auto const& state : this->FailedSearchLocations) { + std::string path = cmStrCat(" ", state.path); + if (!state.regexName.empty()) { + path = cmStrCat(path, "/", state.regexName); + } + buffer += cmStrCat(path, "\n"); + } + + if (!this->FoundSearchLocation.path.empty()) { + buffer += cmStrCat("The item was found at\n ", + this->FoundSearchLocation.path, "\n"); + } else { + buffer += "The item was not found.\n"; + } + + this->FindCommand->DebugMessage(buffer); + } +} + +void cmFindBaseDebugState::FoundAt(std::string const& path, + std::string regexName) +{ + if (this->FindCommand->DebugMode) { + this->FoundSearchLocation = DebugLibState{ std::move(regexName), path }; + } +} + +void cmFindBaseDebugState::FailedAt(std::string const& path, + std::string regexName) +{ + if (this->FindCommand->DebugMode) { + this->FailedSearchLocations.emplace_back(std::move(regexName), path); + } +} diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index f75db5ff3f..fce0b11896 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <string> +#include <utility> #include <vector> #include "cmFindCommon.h" @@ -31,7 +32,7 @@ public: virtual bool ParseArguments(std::vector<std::string> const& args); protected: - void PrintFindStuff(); + friend class cmFindBaseDebugState; void ExpandPaths(); // see if the VariableName is already set in the cache, @@ -63,4 +64,33 @@ private: void FillUserGuessPath(); }; +class cmFindBaseDebugState +{ +public: + explicit cmFindBaseDebugState(std::string name, cmFindBase const* findBase); + ~cmFindBaseDebugState(); + + void FoundAt(std::string const& path, std::string regexName = std::string()); + void FailedAt(std::string const& path, + std::string regexName = std::string()); + +private: + struct DebugLibState + { + DebugLibState() = default; + DebugLibState(std::string&& n, std::string p) + : regexName(n) + , path(std::move(p)) + { + } + std::string regexName; + std::string path; + }; + + cmFindBase const* FindCommand; + std::string CommandName; + std::vector<DebugLibState> FailedSearchLocations; + DebugLibState FoundSearchLocation; +}; + #endif diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index badec55a8a..82acfedad3 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -7,11 +7,14 @@ #include <cstring> #include <utility> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmake.h" cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL"); cmFindCommon::PathLabel cmFindCommon::PathLabel::PackageRoot( @@ -52,6 +55,8 @@ cmFindCommon::cmFindCommon(cmExecutionStatus& status) this->SearchAppBundleLast = false; this->InitializeSearchPathGroups(); + + this->DebugMode = false; } void cmFindCommon::SetError(std::string const& e) @@ -59,6 +64,19 @@ void cmFindCommon::SetError(std::string const& e) this->Status.SetError(e); } +void cmFindCommon::DebugMessage(std::string const& msg) const +{ + if (this->Makefile) { + this->Makefile->IssueMessage(MessageType::LOG, msg); + } +} + +bool cmFindCommon::ComputeIfDebugModeWanted() +{ + return this->Makefile->IsOn("CMAKE_FIND_DEBUG_MODE") || + this->Makefile->GetCMakeInstance()->GetDebugFindOutput(); +} + void cmFindCommon::InitializeSearchPathGroups() { std::vector<PathLabel>* labels; @@ -249,7 +267,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) // If searching both rooted and unrooted paths add the original // paths again. if (this->FindRootPathMode == RootPathModeBoth) { - cmAppend(paths, unrootedPaths); + cm::append(paths, unrootedPaths); } } diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index 8177eacd6e..916f3bc9ba 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -30,8 +30,11 @@ public: void SetError(std::string const& e); + bool DebugModeEnabled() const { return this->DebugMode; } + protected: friend class cmSearchPath; + friend class cmFindBaseDebugState; /** Used to define groups of path labels */ class PathGroup : public cmPathLabel @@ -96,6 +99,10 @@ protected: /** Compute the current default search modes based on global variables. */ void SelectDefaultSearchModes(); + /** The `InitialPass` functions of the child classes should set + this->DebugMode to the result of this. */ + bool ComputeIfDebugModeWanted(); + // Path arguments prior to path manipulation routines std::vector<std::string> UserHintsArgs; std::vector<std::string> UserGuessArgs; @@ -106,6 +113,8 @@ protected: bool CheckCommonArgument(std::string const& arg); void AddPathSuffix(std::string const& arg); + void DebugMessage(std::string const& msg) const; + bool DebugMode; bool NoDefaultPath; bool NoPackageRootPath; bool NoCMakePath; diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 20221b12e0..d5a4bde97e 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -29,6 +29,7 @@ cmFindLibraryCommand::cmFindLibraryCommand(cmExecutionStatus& status) // cmFindLibraryCommand bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn) { + this->DebugMode = ComputeIfDebugModeWanted(); this->VariableDocumentation = "Path to a library."; this->CMakePathName = "LIBRARY"; if (!this->ParseArguments(argsIn)) { @@ -92,6 +93,13 @@ void cmFindLibraryCommand::AddArchitecturePaths(const char* suffix) original.swap(this->SearchPaths); for (std::string const& o : original) { this->AddArchitecturePath(o, 0, suffix); + if (this->DebugMode) { + std::string msg = cmStrCat( + "find_library(", this->VariableName, ") removed original suffix ", o, + " from PATH_SUFFIXES while adding architecture paths for suffix '", + suffix, "'"); + this->DebugMessage(msg); + } } } @@ -153,11 +161,23 @@ void cmFindLibraryCommand::AddArchitecturePath( if (use_dirX) { dirX += "/"; + if (this->DebugMode) { + std::string msg = cmStrCat( + "find_library(", this->VariableName, ") added replacement path ", + dirX, " to PATH_SUFFIXES for architecture suffix '", suffix, "'"); + this->DebugMessage(msg); + } this->SearchPaths.push_back(std::move(dirX)); } if (use_dir) { this->SearchPaths.push_back(dir); + if (this->DebugMode) { + std::string msg = cmStrCat( + "find_library(", this->VariableName, ") added replacement path ", + dir, " to PATH_SUFFIXES for architecture suffix '", suffix, "'"); + this->DebugMessage(msg); + } } } } @@ -179,7 +199,7 @@ std::string cmFindLibraryCommand::FindLibrary() struct cmFindLibraryHelper { - cmFindLibraryHelper(cmMakefile* mf); + cmFindLibraryHelper(cmMakefile* mf, cmFindBase const* findBase); // Context information. cmMakefile* Makefile; @@ -198,6 +218,8 @@ struct cmFindLibraryHelper // Support for OpenBSD shared library naming: lib<name>.so.<major>.<minor> bool OpenBSD; + bool DebugMode; + // Current names under consideration. struct Name { @@ -227,10 +249,33 @@ struct cmFindLibraryHelper void SetName(std::string const& name); bool CheckDirectory(std::string const& path); bool CheckDirectoryForName(std::string const& path, Name& name); + + cmFindBaseDebugState DebugSearches; + + void DebugLibraryFailed(std::string const& name, std::string const& path) + { + if (this->DebugMode) { + auto regexName = + cmStrCat(this->PrefixRegexStr, name, this->SuffixRegexStr); + this->DebugSearches.FailedAt(path, regexName); + } + }; + + void DebugLibraryFound(std::string const& name, std::string const& path) + { + if (this->DebugMode) { + auto regexName = + cmStrCat(this->PrefixRegexStr, name, this->SuffixRegexStr); + this->DebugSearches.FoundAt(path, regexName); + } + }; }; -cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf) +cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf, + cmFindBase const* base) : Makefile(mf) + , DebugMode(base->DebugModeEnabled()) + , DebugSearches("find_library", base) { this->GG = this->Makefile->GetGlobalGenerator(); @@ -350,7 +395,12 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, // library or an import library). if (name.TryRaw) { this->TestPath = cmStrCat(path, name.Raw); - if (cmSystemTools::FileExists(this->TestPath, true)) { + + const bool exists = cmSystemTools::FileExists(this->TestPath, true); + if (!exists) { + this->DebugLibraryFailed(name.Raw, path); + } else { + this->DebugLibraryFound(name.Raw, path); this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath); cmSystemTools::ConvertToUnixSlashes(this->BestPath); return true; @@ -376,6 +426,8 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, if (name.Regex.find(testName)) { this->TestPath = cmStrCat(path, origName); if (!cmSystemTools::FileIsDirectory(this->TestPath)) { + this->DebugLibraryFound(name.Raw, dir); + // This is a matching file. Check if it is better than the // best name found so far. Earlier prefixes are preferred, // followed by earlier suffixes. For OpenBSD, shared library @@ -402,6 +454,12 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, } } + if (this->BestPath.empty()) { + this->DebugLibraryFailed(name.Raw, dir); + } else { + this->DebugLibraryFound(name.Raw, this->BestPath); + } + // Use the best candidate found in this directory, if any. return !this->BestPath.empty(); } @@ -417,7 +475,7 @@ std::string cmFindLibraryCommand::FindNormalLibrary() std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir() { // Search for all names in each directory. - cmFindLibraryHelper helper(this->Makefile); + cmFindLibraryHelper helper(this->Makefile, this); for (std::string const& n : this->Names) { helper.AddName(n); } @@ -434,7 +492,7 @@ std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir() std::string cmFindLibraryCommand::FindNormalLibraryDirsPerName() { // Search the entire path for each name. - cmFindLibraryHelper helper(this->Makefile); + cmFindLibraryHelper helper(this->Makefile, this); for (std::string const& n : this->Names) { // Switch to searching for this name. helper.SetName(n); diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 2b11b62a21..297c72b0f5 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -160,8 +160,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]); } - // Check for debug mode. - this->DebugMode = this->Makefile->IsOn("CMAKE_FIND_DEBUG_MODE"); + this->DebugMode = ComputeIfDebugModeWanted(); + this->DebugBuffer.clear(); // Lookup target architecture, if any. if (const char* arch = @@ -576,6 +576,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } this->AppendSuccessInformation(); + return loadedPackage; } @@ -695,8 +696,23 @@ void cmFindPackageCommand::RestoreFindDefinitions() bool cmFindPackageCommand::FindModule(bool& found) { std::string module = cmStrCat("Find", this->Name, ".cmake"); + bool system = false; - std::string mfile = this->Makefile->GetModulesFile(module, system); + std::string debugBuffer = + cmStrCat("find_package considered the following paths for ", this->Name, + ".cmake\n"); + std::string mfile = this->Makefile->GetModulesFile( + module, system, this->DebugMode, debugBuffer); + if (this->DebugMode) { + if (mfile.empty()) { + debugBuffer = cmStrCat(debugBuffer, "The file was not found."); + } else { + debugBuffer = + cmStrCat(debugBuffer, "The file was found at\n ", mfile, "\n"); + } + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } + if (!mfile.empty()) { if (system) { auto it = this->DeprecatedFindModules.find(this->Name); @@ -827,6 +843,11 @@ bool cmFindPackageCommand::HandlePackageMode( result = false; } + if (this->DebugMode) { + this->DebugMessage(this->DebugBuffer); + this->DebugBuffer.clear(); + } + // package not found if (result && !found) { // warn if package required or neither quiet nor in config mode @@ -987,6 +1008,11 @@ bool cmFindPackageCommand::FindConfig() // Look for the project's configuration file. bool found = false; + if (this->DebugMode) { + this->DebugBuffer = cmStrCat(this->DebugBuffer, + "find_package considered the following " + "locations for the Config module:\n"); + } // Search for frameworks. if (!found && (this->SearchFrameworkFirst || this->SearchFrameworkOnly)) { @@ -1013,6 +1039,16 @@ bool cmFindPackageCommand::FindConfig() found = this->FindAppBundleConfig(); } + if (this->DebugMode) { + if (found) { + this->DebugBuffer = cmStrCat( + this->DebugBuffer, "The file was found at\n ", this->FileFound, "\n"); + } else { + this->DebugBuffer = + cmStrCat(this->DebugBuffer, "The file was not found.\n"); + } + } + // Store the entry in the cache so it can be set by the user. std::string init; if (found) { @@ -1026,6 +1062,7 @@ bool cmFindPackageCommand::FindConfig() // We force the value since we do not get here if it was already set. this->Makefile->AddCacheDefinition(this->Variable, init.c_str(), help.c_str(), cmStateEnums::PATH, true); + return found; } @@ -1164,6 +1201,21 @@ void cmFindPackageCommand::AppendSuccessInformation() this->Makefile->FindPackageRootPathStack.pop_back(); } +inline std::size_t collectPathsForDebug(std::string& buffer, + cmSearchPath const& searchPath, + std::size_t startIndex = 0) +{ + const auto& paths = searchPath.GetPaths(); + if (paths.empty()) { + buffer += " none"; + return 0; + } + for (std::size_t i = startIndex; i < paths.size(); i++) { + buffer += " " + paths[i] + "\n"; + } + return paths.size(); +} + void cmFindPackageCommand::ComputePrefixes() { if (!this->NoDefaultPath) { @@ -1177,7 +1229,9 @@ void cmFindPackageCommand::ComputePrefixes() this->FillPrefixesCMakeEnvironment(); } } + this->FillPrefixesUserHints(); + if (!this->NoDefaultPath) { if (!this->NoSystemEnvironmentPath) { this->FillPrefixesSystemEnvironment(); @@ -1209,29 +1263,72 @@ void cmFindPackageCommand::FillPrefixesPackageRoot() paths.AddPath(path); } } + if (this->DebugMode) { + std::string debugBuffer = "<PackageName>_ROOT CMake variable " + "[CMAKE_FIND_USE_PACKAGE_ROOT_PATH].\n"; + collectPathsForDebug(debugBuffer, paths); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } void cmFindPackageCommand::FillPrefixesCMakeEnvironment() { cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment]; + std::string debugBuffer; + std::size_t debugOffset = 0; // Check the environment variable with the same name as the cache // entry. paths.AddEnvPath(this->Variable); + if (this->DebugMode) { + debugBuffer = cmStrCat("Env variable ", this->Variable, + " [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n"); + debugOffset = collectPathsForDebug(debugBuffer, paths); + } // And now the general CMake environment variables paths.AddEnvPath("CMAKE_PREFIX_PATH"); + if (this->DebugMode) { + debugBuffer = cmStrCat(debugBuffer, + "\nCMAKE_PREFIX_PATH env variable " + "[CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n"); + debugOffset = collectPathsForDebug(debugBuffer, paths, debugOffset); + } + paths.AddEnvPath("CMAKE_FRAMEWORK_PATH"); paths.AddEnvPath("CMAKE_APPBUNDLE_PATH"); + if (this->DebugMode) { + debugBuffer = + cmStrCat(debugBuffer, + "\nCMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH env " + "variables [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n"); + collectPathsForDebug(debugBuffer, paths, debugOffset); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } void cmFindPackageCommand::FillPrefixesCMakeVariable() { cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake]; + std::string debugBuffer; + std::size_t debugOffset = 0; paths.AddCMakePath("CMAKE_PREFIX_PATH"); + if (this->DebugMode) { + debugBuffer = "CMAKE_PREFIX_PATH variable [CMAKE_FIND_USE_CMAKE_PATH].\n"; + debugOffset = collectPathsForDebug(debugBuffer, paths); + } + paths.AddCMakePath("CMAKE_FRAMEWORK_PATH"); paths.AddCMakePath("CMAKE_APPBUNDLE_PATH"); + if (this->DebugMode) { + debugBuffer = + cmStrCat(debugBuffer, + "\nCMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH variables " + "[CMAKE_FIND_USE_CMAKE_PATH].\n"); + collectPathsForDebug(debugBuffer, paths, debugOffset); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } void cmFindPackageCommand::FillPrefixesSystemEnvironment() @@ -1251,6 +1348,12 @@ void cmFindPackageCommand::FillPrefixesSystemEnvironment() paths.AddPath(i); } } + if (this->DebugMode) { + std::string debugBuffer = "Standard system environment variables " + "[CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH].\n"; + collectPathsForDebug(debugBuffer, paths); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } void cmFindPackageCommand::FillPrefixesUserRegistry() @@ -1274,6 +1377,13 @@ void cmFindPackageCommand::FillPrefixesUserRegistry() this->LabeledPaths[PathLabel::UserRegistry]); } #endif + if (this->DebugMode) { + std::string debugBuffer = + "CMake User Package Registry [CMAKE_FIND_USE_PACKAGE_REGISTRY].\n"; + collectPathsForDebug(debugBuffer, + this->LabeledPaths[PathLabel::UserRegistry]); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } void cmFindPackageCommand::FillPrefixesSystemRegistry() @@ -1285,6 +1395,15 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry() #if defined(_WIN32) && !defined(__CYGWIN__) this->LoadPackageRegistryWinSystem(); #endif + + if (this->DebugMode) { + std::string debugBuffer = + "CMake System Package Registry " + "[CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY].\n"; + collectPathsForDebug(debugBuffer, + this->LabeledPaths[PathLabel::SystemRegistry]); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } #if defined(_WIN32) && !defined(__CYGWIN__) @@ -1457,6 +1576,13 @@ void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); + + if (this->DebugMode) { + std::string debugBuffer = "CMake variables defined in the Platform file " + "[CMAKE_FIND_USE_CMAKE_SYSTEM_PATH].\n"; + collectPathsForDebug(debugBuffer, paths); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } void cmFindPackageCommand::FillPrefixesUserGuess() @@ -1466,6 +1592,12 @@ void cmFindPackageCommand::FillPrefixesUserGuess() for (std::string const& p : this->UserGuessArgs) { paths.AddUserPath(p); } + if (this->DebugMode) { + std::string debugBuffer = + "Paths specified by the find_package PATHS option.\n"; + collectPathsForDebug(debugBuffer, paths); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } void cmFindPackageCommand::FillPrefixesUserHints() @@ -1475,6 +1607,12 @@ void cmFindPackageCommand::FillPrefixesUserHints() for (std::string const& p : this->UserHintsArgs) { paths.AddUserPath(p); } + if (this->DebugMode) { + std::string debugBuffer = + "Paths specified by the find_package HINTS option.\n"; + collectPathsForDebug(debugBuffer, paths); + this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n"); + } } bool cmFindPackageCommand::SearchDirectory(std::string const& dir) @@ -1519,7 +1657,7 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir, for (std::string const& c : this->Configs) { file = cmStrCat(dir, '/', c); if (this->DebugMode) { - fprintf(stderr, "Checking file [%s]\n", file.c_str()); + this->DebugBuffer = cmStrCat(this->DebugBuffer, " ", file, "\n"); } if (cmSystemTools::FileExists(file, true) && this->CheckVersion(file)) { // Allow resolving symlinks when the config file is found through a link @@ -2032,9 +2170,6 @@ private: bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) { assert(!prefix_in.empty() && prefix_in.back() == '/'); - if (this->DebugMode) { - fprintf(stderr, "Checking prefix [%s]\n", prefix_in.c_str()); - } // Skip this if the prefix does not exist. if (!cmSystemTools::FileIsDirectory(prefix_in)) { @@ -2188,9 +2323,6 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in) { assert(!prefix_in.empty() && prefix_in.back() == '/'); - if (this->DebugMode) { - fprintf(stderr, "Checking framework prefix [%s]\n", prefix_in.c_str()); - } // Strip the trailing slash because the path generator is about to // add one. @@ -2249,9 +2381,6 @@ bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in) bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in) { assert(!prefix_in.empty() && prefix_in.back() == '/'); - if (this->DebugMode) { - fprintf(stderr, "Checking bundle prefix [%s]\n", prefix_in.c_str()); - } // Strip the trailing slash because the path generator is about to // add one. diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 85fe7b6e51..ae9ade73e9 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -174,7 +174,6 @@ private: bool UseFindModules; bool NoUserRegistry; bool NoSystemRegistry; - bool DebugMode; bool UseLib32Paths; bool UseLib64Paths; bool UseLibx32Paths; @@ -184,6 +183,7 @@ private: std::vector<std::string> Names; std::vector<std::string> Configs; std::set<std::string> IgnoredPaths; + std::string DebugBuffer; /*! the selected sortOrder (None by default)*/ SortOrderType SortOrder; diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index f5e2631081..908f0c13c6 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -21,6 +21,7 @@ cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status) // cmFindPathCommand bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn) { + this->DebugMode = ComputeIfDebugModeWanted(); this->VariableDocumentation = "Path to a file."; this->CMakePathName = "INCLUDE"; if (!this->ParseArguments(argsIn)) { @@ -55,16 +56,19 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn) std::string cmFindPathCommand::FindHeader() { + std::string debug_name = this->IncludeFileInPath ? "find_file" : "find_path"; + cmFindBaseDebugState debug(debug_name, this); std::string header; if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) { - header = this->FindFrameworkHeader(); + header = this->FindFrameworkHeader(debug); } if (header.empty() && !this->SearchFrameworkOnly) { - header = this->FindNormalHeader(); + header = this->FindNormalHeader(debug); } if (header.empty() && this->SearchFrameworkLast) { - header = this->FindFrameworkHeader(); + header = this->FindFrameworkHeader(debug); } + return header; } @@ -116,28 +120,31 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file, return ""; } -std::string cmFindPathCommand::FindNormalHeader() +std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug) { std::string tryPath; for (std::string const& n : this->Names) { for (std::string const& sp : this->SearchPaths) { tryPath = cmStrCat(sp, n); if (cmSystemTools::FileExists(tryPath)) { + debug.FoundAt(tryPath); if (this->IncludeFileInPath) { return tryPath; } return sp; } + debug.FailedAt(tryPath); } } return ""; } -std::string cmFindPathCommand::FindFrameworkHeader() +std::string cmFindPathCommand::FindFrameworkHeader(cmFindBaseDebugState& debug) { for (std::string const& n : this->Names) { for (std::string const& sp : this->SearchPaths) { std::string fwPath = this->FindHeaderInFramework(n, sp); + fwPath.empty() ? debug.FailedAt(fwPath) : debug.FoundAt(fwPath); if (!fwPath.empty()) { return fwPath; } diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h index 8d1ea8b60e..18bfb7dd86 100644 --- a/Source/cmFindPathCommand.h +++ b/Source/cmFindPathCommand.h @@ -32,8 +32,8 @@ private: std::string FindHeaderInFramework(std::string const& file, std::string const& dir); std::string FindHeader(); - std::string FindNormalHeader(); - std::string FindFrameworkHeader(); + std::string FindNormalHeader(cmFindBaseDebugState& debug); + std::string FindFrameworkHeader(cmFindBaseDebugState& debug); }; bool cmFindPath(std::vector<std::string> const& args, diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index e0a3fbfcf5..3e4917262c 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -15,7 +15,9 @@ class cmExecutionStatus; struct cmFindProgramHelper { - cmFindProgramHelper() + cmFindProgramHelper(cmMakefile* makefile, cmFindBase const* base) + : DebugSearches("find_program", base) + , Makefile(makefile) { #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) // Consider platform-specific extensions. @@ -41,6 +43,10 @@ struct cmFindProgramHelper // Current full path under consideration. std::string TestPath; + // Debug state + cmFindBaseDebugState DebugSearches; + cmMakefile* Makefile; + void AddName(std::string const& name) { this->Names.push_back(name); } void SetName(std::string const& name) { @@ -78,8 +84,10 @@ struct cmFindProgramHelper this->TestNameExt = cmStrCat(name, ext); this->TestPath = cmSystemTools::CollapseFullPath(this->TestNameExt, path); - - if (cmSystemTools::FileExists(this->TestPath, true)) { + bool exists = cmSystemTools::FileExists(this->TestPath, true); + exists ? this->DebugSearches.FoundAt(this->TestPath) + : this->DebugSearches.FailedAt(this->TestPath); + if (exists) { this->BestPath = this->TestPath; return true; } @@ -97,6 +105,7 @@ cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status) // cmFindProgramCommand bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn) { + this->DebugMode = ComputeIfDebugModeWanted(); this->VariableDocumentation = "Path to a program."; this->CMakePathName = "PROGRAM"; // call cmFindBase::ParseArguments @@ -158,7 +167,7 @@ std::string cmFindProgramCommand::FindNormalProgram() std::string cmFindProgramCommand::FindNormalProgramNamesPerDir() { // Search for all names in each directory. - cmFindProgramHelper helper; + cmFindProgramHelper helper(this->Makefile, this); for (std::string const& n : this->Names) { helper.AddName(n); } @@ -181,7 +190,7 @@ std::string cmFindProgramCommand::FindNormalProgramNamesPerDir() std::string cmFindProgramCommand::FindNormalProgramDirsPerName() { // Search the entire path for each name. - cmFindProgramHelper helper; + cmFindProgramHelper helper(this->Makefile, this); for (std::string const& n : this->Names) { // Switch to searching for this name. helper.SetName(n); diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 44392baa75..ac48287892 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -2,8 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmForEachCommand.h" -#include <cstdio> +#include <algorithm> +#include <cassert> +#include <cstddef> +// NOTE The declaration of `std::abs` has moved to `cmath` since C++17 +// See https://en.cppreference.com/w/cpp/numeric/math/abs +// ALERT But IWYU used to lint `#include`s do not "understand" +// conditional compilation (i.e. `#if __cplusplus >= 201703L`) #include <cstdlib> +#include <iterator> +#include <map> #include <utility> #include <cm/memory> @@ -21,12 +29,10 @@ #include "cmSystemTools.h" namespace { -bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile); - class cmForEachFunctionBlocker : public cmFunctionBlocker { public: - cmForEachFunctionBlocker(cmMakefile* mf); + explicit cmForEachFunctionBlocker(cmMakefile* mf); ~cmForEachFunctionBlocker() override; cm::string_view StartCommandName() const override { return "foreach"_s; } @@ -38,10 +44,33 @@ public: bool Replay(std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus) override; + void SetIterationVarsCount(const std::size_t varsCount) + { + this->IterationVarsCount = varsCount; + } + void SetZipLists() { this->ZipLists = true; } + std::vector<std::string> Args; private: + struct InvokeResult + { + bool Restore; + bool Break; + }; + + bool ReplayItems(std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus); + + bool ReplayZipLists(std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus); + + InvokeResult invoke(std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus, cmMakefile& mf); + cmMakefile* Makefile; + std::size_t IterationVarsCount = 0u; + bool ZipLists = false; }; cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf) @@ -60,52 +89,272 @@ bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, { std::vector<std::string> expandedArguments; mf.ExpandArguments(lff.Arguments, expandedArguments); - return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; + return expandedArguments.empty() || + expandedArguments.front() == this->Args.front(); } bool cmForEachFunctionBlocker::Replay( std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus) { - cmMakefile& mf = inStatus.GetMakefile(); - // at end of for each execute recorded commands + return this->ZipLists ? this->ReplayZipLists(functions, inStatus) + : this->ReplayItems(functions, inStatus); +} + +bool cmForEachFunctionBlocker::ReplayItems( + std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus) +{ + assert("Unexpected number of iteration variables" && + this->IterationVarsCount == 1); + + auto& mf = inStatus.GetMakefile(); + + // At end of for each execute recorded commands // store the old value std::string oldDef; - if (mf.GetDefinition(this->Args[0])) { - oldDef = mf.GetDefinition(this->Args[0]); + if (mf.GetDefinition(this->Args.front())) { + oldDef = mf.GetDefinition(this->Args.front()); } + auto restore = false; for (std::string const& arg : cmMakeRange(this->Args).advance(1)) { - // set the variable to the loop value - mf.AddDefinition(this->Args[0], arg); + // Set the variable to the loop value + mf.AddDefinition(this->Args.front(), arg); // Invoke all the functions that were collected in the block. - for (cmListFileFunction const& func : functions) { - cmExecutionStatus status(mf); - mf.ExecuteCommand(func, status); - if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); + auto r = this->invoke(functions, inStatus, mf); + restore = r.Restore; + if (r.Break) { + break; + } + } + + if (restore) { + // restore the variable to its prior value + mf.AddDefinition(this->Args.front(), oldDef); + } + return true; +} + +bool cmForEachFunctionBlocker::ReplayZipLists( + std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus) +{ + assert("Unexpected number of iteration variables" && + this->IterationVarsCount >= 1); + + auto& mf = inStatus.GetMakefile(); + + // Expand the list of list-variables into a list of lists of strings + std::vector<std::vector<std::string>> values; + values.reserve(this->Args.size() - this->IterationVarsCount); + // Also track the longest list size + std::size_t maxItems = 0u; + for (auto const& var : + cmMakeRange(this->Args).advance(this->IterationVarsCount)) { + std::vector<std::string> items; + auto const& value = mf.GetSafeDefinition(var); + if (!value.empty()) { + cmExpandList(value, items, true); + } + maxItems = std::max(maxItems, items.size()); + values.emplace_back(std::move(items)); + } + + // Form the list of iteration variables + std::vector<std::string> iterationVars; + if (this->IterationVarsCount > 1) { + // If multiple iteration variables has given, + // just copy them to the `iterationVars` list. + iterationVars.reserve(values.size()); + std::copy(this->Args.begin(), + this->Args.begin() + this->IterationVarsCount, + std::back_inserter(iterationVars)); + } else { + // In case of the only iteration variable, + // generate names as `var_name_N`, + // where `N` is the count of lists to zip + iterationVars.resize(values.size()); + const auto iter_var_prefix = this->Args.front() + "_"; + auto i = 0u; + std::generate( + iterationVars.begin(), iterationVars.end(), + [&]() -> std::string { return iter_var_prefix + std::to_string(i++); }); + } + assert("Sanity check" && iterationVars.size() == values.size()); + + // Store old values for iteration variables + std::map<std::string, std::string> oldDefs; + for (auto i = 0u; i < values.size(); ++i) { + if (mf.GetDefinition(iterationVars[i])) { + oldDefs.emplace(iterationVars[i], mf.GetDefinition(iterationVars[i])); + } + } + + // Form a vector of current positions in all lists (Ok, vectors) of values + std::vector<decltype(values)::value_type::iterator> positions; + positions.reserve(values.size()); + std::transform( + values.begin(), values.end(), std::back_inserter(positions), + // Set the initial position to the beginning of every list + [](decltype(values)::value_type& list) { return list.begin(); }); + assert("Sanity check" && positions.size() == values.size()); + + auto restore = false; + // Iterate over all the lists simulateneously + for (auto i = 0u; i < maxItems; ++i) { + // Declare iteration variables + for (auto j = 0u; j < values.size(); ++j) { + // Define (or not) the iteration variable if the current position + // still not at the end... + if (positions[j] != values[j].end()) { + mf.AddDefinition(iterationVars[j], *positions[j]); + ++positions[j]; + } else { + mf.RemoveDefinition(iterationVars[j]); + } + } + // Invoke all the functions that were collected in the block. + auto r = this->invoke(functions, inStatus, mf); + restore = r.Restore; + if (r.Break) { + break; + } + } + + // Restore the variables to its prior value + if (restore) { + for (auto const& p : oldDefs) { + mf.AddDefinition(p.first, p.second); + } + } + return true; +} + +auto cmForEachFunctionBlocker::invoke( + std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus, cmMakefile& mf) -> InvokeResult +{ + InvokeResult result = { true, false }; + // Invoke all the functions that were collected in the block. + for (cmListFileFunction const& func : functions) { + cmExecutionStatus status(mf); + mf.ExecuteCommand(func, status); + if (status.GetReturnInvoked()) { + inStatus.SetReturnInvoked(); + result.Break = true; + break; + } + if (status.GetBreakInvoked()) { + result.Break = true; + break; + } + if (status.GetContinueInvoked()) { + break; + } + if (cmSystemTools::GetFatalErrorOccured()) { + result.Restore = false; + result.Break = true; + break; + } + } + return result; +} + +bool HandleInMode(std::vector<std::string> const& args, + std::vector<std::string>::const_iterator kwInIter, + cmMakefile& makefile) +{ + assert("A valid iterator expected" && kwInIter != args.end()); + + auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile); + + // Copy iteration variable names first + std::copy(args.begin(), kwInIter, std::back_inserter(fb->Args)); + // Remember the count of given iteration variable names + const auto varsCount = fb->Args.size(); + fb->SetIterationVarsCount(varsCount); + + enum Doing + { + DoingNone, + DoingLists, + DoingItems, + DoingZipLists + }; + Doing doing = DoingNone; + // Iterate over arguments past the "IN" keyword + for (std::string const& arg : cmMakeRange(++kwInIter, args.end())) { + if (arg == "LISTS") { + if (doing == DoingZipLists) { + makefile.IssueMessage(MessageType::FATAL_ERROR, + "ZIP_LISTS can not be used with LISTS or ITEMS"); return true; } - if (status.GetBreakInvoked()) { - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); + if (varsCount != 1u) { + makefile.IssueMessage( + MessageType::FATAL_ERROR, + "ITEMS or LISTS require exactly one iteration variable"); return true; } - if (status.GetContinueInvoked()) { - break; + doing = DoingLists; + + } else if (arg == "ITEMS") { + if (doing == DoingZipLists) { + makefile.IssueMessage(MessageType::FATAL_ERROR, + "ZIP_LISTS can not be used with LISTS or ITEMS"); + return true; } - if (cmSystemTools::GetFatalErrorOccured()) { + if (varsCount != 1u) { + makefile.IssueMessage( + MessageType::FATAL_ERROR, + "ITEMS or LISTS require exactly one iteration variable"); return true; } + doing = DoingItems; + + } else if (arg == "ZIP_LISTS") { + if (doing != DoingNone) { + makefile.IssueMessage(MessageType::FATAL_ERROR, + "ZIP_LISTS can not be used with LISTS or ITEMS"); + return true; + } + doing = DoingZipLists; + fb->SetZipLists(); + + } else if (doing == DoingLists) { + auto const& value = makefile.GetSafeDefinition(arg); + if (!value.empty()) { + cmExpandList(value, fb->Args, true); + } + + } else if (doing == DoingItems || doing == DoingZipLists) { + fb->Args.push_back(arg); + + } else { + makefile.IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("Unknown argument:\n", " ", arg, "\n")); + return true; } } - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); + // If `ZIP_LISTS` given and variables count more than 1, + // make sure the given lists count matches variables... + if (doing == DoingZipLists && varsCount > 1u && + (2u * varsCount) != fb->Args.size()) { + makefile.IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Expected ", std::to_string(varsCount), + " list variables, but given ", + std::to_string(fb->Args.size() - varsCount))); + return true; + } + + makefile.AddFunctionBlocker(std::move(fb)); + return true; } -} + +} // anonymous namespace bool cmForEachCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -114,8 +363,9 @@ bool cmForEachCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments"); return false; } - if (args.size() > 1 && args[1] == "IN") { - return HandleInMode(args, status.GetMakefile()); + auto kwInIter = std::find(args.begin(), args.end(), "IN"); + if (kwInIter != args.end()) { + return HandleInMode(args, kwInIter, status.GetMakefile()); } // create a function blocker @@ -126,16 +376,16 @@ bool cmForEachCommand(std::vector<std::string> const& args, int stop = 0; int step = 0; if (args.size() == 3) { - stop = atoi(args[2].c_str()); + stop = std::stoi(args[2]); } if (args.size() == 4) { - start = atoi(args[2].c_str()); - stop = atoi(args[3].c_str()); + start = std::stoi(args[2]); + stop = std::stoi(args[3]); } if (args.size() == 5) { - start = atoi(args[2].c_str()); - stop = atoi(args[3].c_str()); - step = atoi(args[4].c_str()); + start = std::stoi(args[2]); + stop = std::stoi(args[3]); + step = std::stoi(args[4]); } if (step == 0) { if (start > stop) { @@ -151,67 +401,33 @@ bool cmForEachCommand(std::vector<std::string> const& args, ", stop ", stop, ", step ", step)); return false; } - std::vector<std::string> range; - char buffer[100]; - range.push_back(args[0]); - int cc; - for (cc = start;; cc += step) { - if ((step > 0 && cc > stop) || (step < 0 && cc < stop)) { - break; - } - sprintf(buffer, "%d", cc); - range.emplace_back(buffer); - if (cc == stop) { - break; - } - } - fb->Args = range; + + // Calculate expected iterations count and reserve enough space + // in the `fb->Args` vector. The first item is the iteration variable + // name... + const std::size_t iter_cnt = 2u + + int(start < stop) * (stop - start) / std::abs(step) + + int(start > stop) * (start - stop) / std::abs(step); + fb->Args.resize(iter_cnt); + fb->Args.front() = args.front(); + auto cc = start; + auto generator = [&cc, step]() -> std::string { + auto result = std::to_string(cc); + cc += step; + return result; + }; + // Fill the `range` vector w/ generated string values + // (starting from 2nd position) + std::generate(++fb->Args.begin(), fb->Args.end(), generator); } else { fb->Args = args; } } else { fb->Args = args; } - status.GetMakefile().AddFunctionBlocker(std::move(fb)); - - return true; -} -namespace { -bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile) -{ - auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile); - fb->Args.push_back(args[0]); - - enum Doing - { - DoingNone, - DoingLists, - DoingItems - }; - Doing doing = DoingNone; - for (unsigned int i = 2; i < args.size(); ++i) { - if (doing == DoingItems) { - fb->Args.push_back(args[i]); - } else if (args[i] == "LISTS") { - doing = DoingLists; - } else if (args[i] == "ITEMS") { - doing = DoingItems; - } else if (doing == DoingLists) { - const char* value = makefile.GetDefinition(args[i]); - if (value && *value) { - cmExpandList(value, fb->Args, true); - } - } else { - makefile.IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Unknown argument:\n", " ", args[i], "\n")); - return true; - } - } - - makefile.AddFunctionBlocker(std::move(fb)); + fb->SetIterationVarsCount(1u); + status.GetMakefile().AddFunctionBlocker(std::move(fb)); return true; } -} diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index b3ddfe01f3..a4c907232c 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -2,15 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFunctionCommand.h" -#include <sstream> #include <utility> #include <cm/memory> #include <cm/string_view> +#include <cmext/algorithm> #include "cm_static_string_view.hxx" -#include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmFunctionBlocker.h" #include "cmListFileCache.h" @@ -19,8 +18,20 @@ #include "cmRange.h" #include "cmState.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" namespace { +std::string const ARGC = "ARGC"; +std::string const ARGN = "ARGN"; +std::string const ARGV = "ARGV"; +std::string const CMAKE_CURRENT_FUNCTION = "CMAKE_CURRENT_FUNCTION"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_FILE = + "CMAKE_CURRENT_FUNCTION_LIST_FILE"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_DIR = + "CMAKE_CURRENT_FUNCTION_LIST_DIR"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_LINE = + "CMAKE_CURRENT_FUNCTION_LIST_LINE"; + // define the class for function commands class cmFunctionHelperCommand { @@ -36,8 +47,8 @@ public: std::vector<cmListFileFunction> Functions; cmPolicies::PolicyMap Policies; std::string FilePath; + long Line; }; -} bool cmFunctionHelperCommand::operator()( std::vector<cmListFileArgument> const& args, @@ -52,9 +63,9 @@ bool cmFunctionHelperCommand::operator()( // make sure the number of arguments passed is at least the number // required by the signature if (expandedArgs.size() < this->Args.size() - 1) { - std::string errorMsg = cmStrCat( + auto const errorMsg = cmStrCat( "Function invoked with incorrect arguments for function named: ", - this->Args[0]); + this->Args.front()); inStatus.SetError(errorMsg); return false; } @@ -63,30 +74,40 @@ bool cmFunctionHelperCommand::operator()( this->Policies); // set the value of argc - makefile.AddDefinition("ARGC", std::to_string(expandedArgs.size())); - makefile.MarkVariableAsUsed("ARGC"); + makefile.AddDefinition(ARGC, std::to_string(expandedArgs.size())); + makefile.MarkVariableAsUsed(ARGC); // set the values for ARGV0 ARGV1 ... - for (unsigned int t = 0; t < expandedArgs.size(); ++t) { - std::ostringstream tmpStream; - tmpStream << "ARGV" << t; - makefile.AddDefinition(tmpStream.str(), expandedArgs[t]); - makefile.MarkVariableAsUsed(tmpStream.str()); + for (auto t = 0u; t < expandedArgs.size(); ++t) { + auto const value = cmStrCat(ARGV, std::to_string(t)); + makefile.AddDefinition(value, expandedArgs[t]); + makefile.MarkVariableAsUsed(value); } // define the formal arguments - for (unsigned int j = 1; j < this->Args.size(); ++j) { + for (auto j = 1u; j < this->Args.size(); ++j) { makefile.AddDefinition(this->Args[j], expandedArgs[j - 1]); } // define ARGV and ARGN - std::string argvDef = cmJoin(expandedArgs, ";"); - auto eit = expandedArgs.begin() + (this->Args.size() - 1); - std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";"); - makefile.AddDefinition("ARGV", argvDef); - makefile.MarkVariableAsUsed("ARGV"); - makefile.AddDefinition("ARGN", argnDef); - makefile.MarkVariableAsUsed("ARGN"); + auto const argvDef = cmJoin(expandedArgs, ";"); + auto const eit = expandedArgs.begin() + (this->Args.size() - 1); + auto const argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";"); + makefile.AddDefinition(ARGV, argvDef); + makefile.MarkVariableAsUsed(ARGV); + makefile.AddDefinition(ARGN, argnDef); + makefile.MarkVariableAsUsed(ARGN); + + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION, this->Args.front()); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_FILE, this->FilePath); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_FILE); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_DIR, + cmSystemTools::GetFilenamePath(this->FilePath)); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_DIR); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_LINE, + std::to_string(this->Line)); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_LINE); // Invoke all the functions that were collected in the block. // for each function @@ -100,7 +121,7 @@ bool cmFunctionHelperCommand::operator()( return false; } if (status.GetReturnInvoked()) { - return true; + break; } } @@ -129,7 +150,8 @@ bool cmFunctionFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, std::vector<std::string> expandedArguments; mf.ExpandArguments(lff.Arguments, expandedArguments, this->GetStartingContext().FilePath.c_str()); - return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; + return expandedArguments.empty() || + expandedArguments.front() == this->Args.front(); } bool cmFunctionFunctionBlocker::Replay( @@ -141,11 +163,14 @@ bool cmFunctionFunctionBlocker::Replay( f.Args = this->Args; f.Functions = std::move(functions); f.FilePath = this->GetStartingContext().FilePath; + f.Line = this->GetStartingContext().Line; mf.RecordPolicies(f.Policies); - mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); + mf.GetState()->AddScriptedCommand(this->Args.front(), std::move(f)); return true; } +} // anonymous namespace + bool cmFunctionCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -155,10 +180,9 @@ bool cmFunctionCommand(std::vector<std::string> const& args, } // create a function blocker - { - auto fb = cm::make_unique<cmFunctionFunctionBlocker>(); - cmAppend(fb->Args, args); - status.GetMakefile().AddFunctionBlocker(std::move(fb)); - } + auto fb = cm::make_unique<cmFunctionFunctionBlocker>(); + cm::append(fb->Args, args); + status.GetMakefile().AddFunctionBlocker(std::move(fb)); + return true; } diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index b7f7d1d9b6..81d1e46927 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -8,7 +8,6 @@ #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorExpressionEvaluator.h" @@ -22,6 +21,8 @@ cmGeneratorExpression::cmGeneratorExpression(cmListFileBacktrace backtrace) { } +cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() = default; + cmGeneratorExpression::~cmGeneratorExpression() = default; std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse( @@ -86,7 +87,7 @@ const std::string& cmCompiledGeneratorExpression::EvaluateWithContext( this->Output.clear(); - for (const cmGeneratorExpressionEvaluator* it : this->Evaluators) { + for (const auto& it : this->Evaluators) { this->Output += it->Evaluate(&context, dagChecker); this->SeenTargetProperties.insert(context.SeenTargetProperties.cbegin(), @@ -129,11 +130,6 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( } } -cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() -{ - cmDeleteAll(this->Evaluators); -} - std::string cmGeneratorExpression::StripEmptyListElements( const std::string& input) { @@ -385,6 +381,20 @@ bool cmGeneratorExpression::IsValidTargetName(const std::string& input) return targetNameValidator.find(input); } +void cmGeneratorExpression::ReplaceInstallPrefix( + std::string& input, const std::string& replacement) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + + while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != + std::string::npos) { + std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1; + input.replace(pos, endPos - pos, replacement); + lastPos = endPos; + } +} + void cmCompiledGeneratorExpression::GetMaxLanguageStandard( const cmGeneratorTarget* tgt, std::map<std::string, std::string>& mapping) { diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 4bd1c9f88a..c4be3a13bf 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -87,6 +87,9 @@ public: return input != nullptr && input[0] == '$' && input[1] == '<'; } + static void ReplaceInstallPrefix(std::string& input, + const std::string& replacement); + private: cmListFileBacktrace Backtrace; }; @@ -160,7 +163,7 @@ private: friend class cmGeneratorExpression; cmListFileBacktrace Backtrace; - std::vector<cmGeneratorExpressionEvaluator*> Evaluators; + std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>> Evaluators; const std::string Input; bool NeedsEvaluation; bool EvaluateForBuildsystem; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index e0ae170c08..4129a0c4fd 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -2,10 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGeneratorExpressionEvaluator.h" -#include <algorithm> #include <sstream> -#include "cmAlgorithms.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionNode.h" @@ -16,6 +14,8 @@ GeneratorExpressionContent::GeneratorExpressionContent( { } +GeneratorExpressionContent::~GeneratorExpressionContent() = default; + std::string GeneratorExpressionContent::GetOriginalExpression() const { return std::string(this->StartContent, this->ContentLength); @@ -25,14 +25,13 @@ std::string GeneratorExpressionContent::ProcessArbitraryContent( const cmGeneratorExpressionNode* node, const std::string& identifier, cmGeneratorExpressionContext* context, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator - pit) const + std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit) const { std::string result; const auto pend = this->ParamChildren.end(); for (; pit != pend; ++pit) { - for (cmGeneratorExpressionEvaluator* pExprEval : *pit) { + for (auto& pExprEval : *pit) { if (node->RequiresLiteralInput()) { if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) { reportError(context, this->GetOriginalExpression(), @@ -64,8 +63,7 @@ std::string GeneratorExpressionContent::Evaluate( { std::string identifier; { - for (cmGeneratorExpressionEvaluator* pExprEval : - this->IdentifierChildren) { + for (auto& pExprEval : this->IdentifierChildren) { identifier += pExprEval->Evaluate(context, dagChecker); if (context->HadError) { return std::string(); @@ -126,7 +124,7 @@ std::string GeneratorExpressionContent::EvaluateParameters( return std::string(); } std::string parameter; - for (cmGeneratorExpressionEvaluator* pExprEval : *pit) { + for (auto& pExprEval : *pit) { parameter += pExprEval->Evaluate(context, dagChecker); if (context->HadError) { return std::string(); @@ -174,10 +172,3 @@ std::string GeneratorExpressionContent::EvaluateParameters( } return std::string(); } - -GeneratorExpressionContent::~GeneratorExpressionContent() -{ - cmDeleteAll(this->IdentifierChildren); - std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(), - cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*>>); -} diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index b10bb5bda7..10496fd682 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <cstddef> +#include <memory> #include <string> #include <utility> #include <vector> @@ -36,6 +37,9 @@ struct cmGeneratorExpressionEvaluator cmGeneratorExpressionDAGChecker*) const = 0; }; +using cmGeneratorExpressionEvaluatorVector = + std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>>; + struct TextContent : public cmGeneratorExpressionEvaluator { TextContent(const char* start, size_t length) @@ -68,13 +72,13 @@ struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator { GeneratorExpressionContent(const char* startContent, size_t length); - void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier) + void SetIdentifier(cmGeneratorExpressionEvaluatorVector&& identifier) { this->IdentifierChildren = std::move(identifier); } void SetParameters( - std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters) + std::vector<cmGeneratorExpressionEvaluatorVector>&& parameters) { this->ParamChildren = std::move(parameters); } @@ -102,12 +106,12 @@ private: const cmGeneratorExpressionNode* node, const std::string& identifier, cmGeneratorExpressionContext* context, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator - pit) const; + std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit) + const; private: - std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren; - std::vector<std::vector<cmGeneratorExpressionEvaluator*>> ParamChildren; + cmGeneratorExpressionEvaluatorVector IdentifierChildren; + std::vector<cmGeneratorExpressionEvaluatorVector> ParamChildren; const char* StartContent; size_t ContentLength; }; diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index d6cc6ab1c6..c2c9ef7230 100644 --- a/Source/cmGeneratorExpressionParser.cxx +++ b/Source/cmGeneratorExpressionParser.cxx @@ -6,7 +6,10 @@ #include <cstddef> #include <utility> -#include "cmAlgorithms.h" +#include <cm/memory> +#include <cmext/algorithm> +#include <cmext/memory> + #include "cmGeneratorExpressionEvaluator.h" cmGeneratorExpressionParser::cmGeneratorExpressionParser( @@ -17,7 +20,7 @@ cmGeneratorExpressionParser::cmGeneratorExpressionParser( } void cmGeneratorExpressionParser::Parse( - std::vector<cmGeneratorExpressionEvaluator*>& result) + cmGeneratorExpressionEvaluatorVector& result) { it = this->Tokens.begin(); @@ -27,40 +30,38 @@ void cmGeneratorExpressionParser::Parse( } static void extendText( - std::vector<cmGeneratorExpressionEvaluator*>& result, + cmGeneratorExpressionEvaluatorVector& result, std::vector<cmGeneratorExpressionToken>::const_iterator it) { if (!result.empty() && (*(result.end() - 1))->GetType() == cmGeneratorExpressionEvaluator::Text) { - TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1)); - textContent->Extend(it->Length); + cm::static_reference_cast<TextContent>(*(result.end() - 1)) + .Extend(it->Length); } else { - TextContent* textContent = new TextContent(it->Content, it->Length); - result.push_back(textContent); + auto textContent = cm::make_unique<TextContent>(it->Content, it->Length); + result.push_back(std::move(textContent)); } } static void extendResult( - std::vector<cmGeneratorExpressionEvaluator*>& result, - const std::vector<cmGeneratorExpressionEvaluator*>& contents) + cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector& result, + cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector&& contents) { if (!result.empty() && (*(result.end() - 1))->GetType() == cmGeneratorExpressionEvaluator::Text && contents.front()->GetType() == cmGeneratorExpressionEvaluator::Text) { - TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1)); - textContent->Extend( - static_cast<TextContent*>(contents.front())->GetLength()); - delete contents.front(); - cmAppend(result, contents.begin() + 1, contents.end()); - } else { - cmAppend(result, contents); + cm::static_reference_cast<TextContent>(*(result.end() - 1)) + .Extend( + cm::static_reference_cast<TextContent>(contents.front()).GetLength()); + contents.erase(contents.begin()); } + cm::append(result, std::move(contents)); } void cmGeneratorExpressionParser::ParseGeneratorExpression( - std::vector<cmGeneratorExpressionEvaluator*>& result) + cmGeneratorExpressionEvaluatorVector& result) { assert(this->it != this->Tokens.end()); unsigned int nestedLevel = this->NestingLevel; @@ -68,7 +69,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( auto startToken = this->it - 1; - std::vector<cmGeneratorExpressionEvaluator*> identifier; + cmGeneratorExpressionEvaluatorVector identifier; while (this->it->TokenType != cmGeneratorExpressionToken::EndExpression && this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator) { if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) { @@ -87,18 +88,18 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( if (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::EndExpression) { - GeneratorExpressionContent* content = new GeneratorExpressionContent( + auto content = cm::make_unique<GeneratorExpressionContent>( startToken->Content, this->it->Content - startToken->Content + this->it->Length); assert(this->it != this->Tokens.end()); ++this->it; --this->NestingLevel; content->SetIdentifier(std::move(identifier)); - result.push_back(content); + result.push_back(std::move(content)); return; } - std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters; + std::vector<cmGeneratorExpressionEvaluatorVector> parameters; std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator> commaTokens; std::vector<cmGeneratorExpressionToken>::const_iterator colonToken; @@ -169,7 +170,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( // treat the '$<' as having been plain text, along with the // corresponding : and , tokens that might have been found. extendText(result, startToken); - extendResult(result, identifier); + extendResult(result, std::move(identifier)); if (!parameters.empty()) { extendText(result, colonToken); @@ -179,7 +180,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( assert(parameters.size() > commaTokens.size()); for (; pit != pend; ++pit, ++commaIt) { if (!pit->empty() && !emptyParamTermination) { - extendResult(result, *pit); + extendResult(result, std::move(*pit)); } if (commaIt != commaTokens.end()) { extendText(result, *commaIt); @@ -193,15 +194,15 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( size_t contentLength = ((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length; - GeneratorExpressionContent* content = - new GeneratorExpressionContent(startToken->Content, contentLength); + auto content = cm::make_unique<GeneratorExpressionContent>( + startToken->Content, contentLength); content->SetIdentifier(std::move(identifier)); content->SetParameters(std::move(parameters)); - result.push_back(content); + result.push_back(std::move(content)); } void cmGeneratorExpressionParser::ParseContent( - std::vector<cmGeneratorExpressionEvaluator*>& result) + cmGeneratorExpressionEvaluatorVector& result) { assert(this->it != this->Tokens.end()); switch (this->it->TokenType) { @@ -213,17 +214,16 @@ void cmGeneratorExpressionParser::ParseContent( // A comma in 'plain text' could have split text that should // otherwise be continuous. Extend the last text content instead of // creating a new one. - TextContent* textContent = - static_cast<TextContent*>(*(result.end() - 1)); - textContent->Extend(this->it->Length); + cm::static_reference_cast<TextContent>(*(result.end() - 1)) + .Extend(this->it->Length); assert(this->it != this->Tokens.end()); ++this->it; return; } } - cmGeneratorExpressionEvaluator* n = - new TextContent(this->it->Content, this->it->Length); - result.push_back(n); + auto n = + cm::make_unique<TextContent>(this->it->Content, this->it->Length); + result.push_back(std::move(n)); assert(this->it != this->Tokens.end()); ++this->it; return; diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h index e663496dae..1ba1654187 100644 --- a/Source/cmGeneratorExpressionParser.h +++ b/Source/cmGeneratorExpressionParser.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <vector> #include "cmGeneratorExpressionLexer.h" @@ -15,11 +16,14 @@ struct cmGeneratorExpressionParser { cmGeneratorExpressionParser(std::vector<cmGeneratorExpressionToken> tokens); - void Parse(std::vector<cmGeneratorExpressionEvaluator*>& result); + using cmGeneratorExpressionEvaluatorVector = + std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>>; + + void Parse(cmGeneratorExpressionEvaluatorVector& result); private: - void ParseContent(std::vector<cmGeneratorExpressionEvaluator*>&); - void ParseGeneratorExpression(std::vector<cmGeneratorExpressionEvaluator*>&); + void ParseContent(cmGeneratorExpressionEvaluatorVector&); + void ParseGeneratorExpression(cmGeneratorExpressionEvaluatorVector&); private: std::vector<cmGeneratorExpressionToken>::const_iterator it; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 171c3ed395..523083a768 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -10,15 +10,14 @@ #include <cstdlib> #include <cstring> #include <iterator> -#include <memory> +#include <queue> #include <sstream> #include <unordered_set> #include <utility> +#include <cm/memory> #include <cm/string_view> -#include <queue> - #include "cmsys/RegularExpression.hxx" #include "cmAlgorithms.h" @@ -162,7 +161,8 @@ private: cmListFileBacktrace Backtrace; }; -cmGeneratorTarget::TargetPropertyEntry* CreateTargetPropertyEntry( +std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry> +CreateTargetPropertyEntry( const std::string& propertyValue, cmListFileBacktrace backtrace = cmListFileBacktrace(), bool evaluateForBuildsystem = false) @@ -172,15 +172,18 @@ cmGeneratorTarget::TargetPropertyEntry* CreateTargetPropertyEntry( std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propertyValue); cge->SetEvaluateForBuildsystem(evaluateForBuildsystem); - return new TargetPropertyEntryGenex(std::move(cge)); + return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>( + cm::make_unique<TargetPropertyEntryGenex>(std::move(cge))); } - return new TargetPropertyEntryString(propertyValue, std::move(backtrace)); + return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>( + cm::make_unique<TargetPropertyEntryString>(propertyValue, + std::move(backtrace))); } void CreatePropertyGeneratorExpressions( cmStringRange entries, cmBacktraceRange backtraces, - std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items, + std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items, bool evaluateForBuildsystem = false) { auto btIt = backtraces.begin(); @@ -219,13 +222,13 @@ struct EvaluatedTargetPropertyEntry EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( cmGeneratorTarget const* thisTarget, std::string const& config, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, - cmGeneratorTarget::TargetPropertyEntry* entry) + cmGeneratorTarget::TargetPropertyEntry& entry) { - EvaluatedTargetPropertyEntry ee(entry->LinkImplItem, entry->GetBacktrace()); - cmExpandList(entry->Evaluate(thisTarget->GetLocalGenerator(), config, - thisTarget, dagChecker, lang), + EvaluatedTargetPropertyEntry ee(entry.LinkImplItem, entry.GetBacktrace()); + cmExpandList(entry.Evaluate(thisTarget->GetLocalGenerator(), config, + thisTarget, dagChecker, lang), ee.Values); - if (entry->GetHadContextSensitiveCondition()) { + if (entry.GetHadContextSensitiveCondition()) { ee.ContextDependent = true; } return ee; @@ -234,13 +237,14 @@ EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( std::vector<EvaluatedTargetPropertyEntry> EvaluateTargetPropertyEntries( cmGeneratorTarget const* thisTarget, std::string const& config, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<cmGeneratorTarget::TargetPropertyEntry*> const& in) + std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const& + in) { std::vector<EvaluatedTargetPropertyEntry> out; out.reserve(in.size()); - for (cmGeneratorTarget::TargetPropertyEntry* entry : in) { + for (auto& entry : in) { out.emplace_back(EvaluateTargetPropertyEntry(thisTarget, config, lang, - dagChecker, entry)); + dagChecker, *entry)); } return out; } @@ -304,23 +308,12 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) this->PolicyMap = t->GetPolicyMap(); } -cmGeneratorTarget::~cmGeneratorTarget() -{ - cmDeleteAll(this->IncludeDirectoriesEntries); - cmDeleteAll(this->CompileOptionsEntries); - cmDeleteAll(this->CompileFeaturesEntries); - cmDeleteAll(this->CompileDefinitionsEntries); - cmDeleteAll(this->LinkOptionsEntries); - cmDeleteAll(this->LinkDirectoriesEntries); - cmDeleteAll(this->PrecompileHeadersEntries); - cmDeleteAll(this->SourceEntries); - cmDeleteAll(this->LinkInformation); -} +cmGeneratorTarget::~cmGeneratorTarget() = default; const char* cmGeneratorTarget::GetSourcesProperty() const { std::vector<std::string> values; - for (TargetPropertyEntry* se : this->SourceEntries) { + for (auto& se : this->SourceEntries) { values.push_back(se->GetInput()); } static std::string value; @@ -655,6 +648,7 @@ void cmGeneratorTarget::ClearSourcesCache() this->KindedSourcesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; this->Objects.clear(); + this->VisitedConfigsForObjects.clear(); } void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before) @@ -744,7 +738,7 @@ void cmGeneratorTarget::GetObjectSources( { IMPLEMENT_VISIT(SourceKindObjectSource); - if (!this->Objects.empty()) { + if (this->VisitedConfigsForObjects.count(config)) { return; } @@ -753,16 +747,17 @@ void cmGeneratorTarget::GetObjectSources( } this->LocalGenerator->ComputeObjectFilenames(this->Objects, this); + this->VisitedConfigsForObjects.insert(config); } void cmGeneratorTarget::ComputeObjectMapping() { - if (!this->Objects.empty()) { + auto const& configs = this->Makefile->GetGeneratorConfigs(); + std::set<std::string> configSet(configs.begin(), configs.end()); + if (configSet == this->VisitedConfigsForObjects) { return; } - std::vector<std::string> const& configs = - this->Makefile->GetGeneratorConfigs(); for (std::string const& c : configs) { std::vector<cmSourceFile const*> sourceFiles; this->GetObjectSources(sourceFiles, c); @@ -1122,7 +1117,8 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const } bool cmGeneratorTarget::MaybeHaveInterfaceProperty( - std::string const& prop, cmGeneratorExpressionContext* context) const + std::string const& prop, cmGeneratorExpressionContext* context, + bool usage_requirements_only) const { std::string const key = prop + '@' + context->Config; auto i = this->MaybeInterfacePropertyExists.find(key); @@ -1141,7 +1137,7 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty( context->HeadTarget ? context->HeadTarget : this; if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries(context->Config, headTarget, - true)) { + usage_requirements_only)) { if (iface->HadHeadSensitiveCondition) { // With a different head target we may get to a library with // this interface property. @@ -1151,7 +1147,8 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty( // head target, so we can follow them. for (cmLinkItem const& lib : iface->Libraries) { if (lib.Target && - lib.Target->MaybeHaveInterfaceProperty(prop, context)) { + lib.Target->MaybeHaveInterfaceProperty( + prop, context, usage_requirements_only)) { maybeInterfaceProp = true; break; } @@ -1165,12 +1162,14 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty( std::string cmGeneratorTarget::EvaluateInterfaceProperty( std::string const& prop, cmGeneratorExpressionContext* context, - cmGeneratorExpressionDAGChecker* dagCheckerParent) const + cmGeneratorExpressionDAGChecker* dagCheckerParent, + bool usage_requirements_only) const { std::string result; // If the property does not appear transitively at all, we are done. - if (!this->MaybeHaveInterfaceProperty(prop, context)) { + if (!this->MaybeHaveInterfaceProperty(prop, context, + usage_requirements_only)) { return result; } @@ -1202,8 +1201,8 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( p, context->LG, context, headTarget, &dagChecker, this); } - if (cmLinkInterfaceLibraries const* iface = - this->GetLinkInterfaceLibraries(context->Config, headTarget, true)) { + if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries( + context->Config, headTarget, usage_requirements_only)) { for (cmLinkItem const& lib : iface->Libraries) { // Broken code can have a target in its own link interface. // Don't follow such link interface entries so as not to create a @@ -1217,8 +1216,8 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( context->EvaluateForBuildsystem, context->Backtrace, context->Language); std::string libResult = cmGeneratorExpression::StripEmptyListElements( - lib.Target->EvaluateInterfaceProperty(prop, &libContext, - &dagChecker)); + lib.Target->EvaluateInterfaceProperty(prop, &libContext, &dagChecker, + usage_requirements_only)); if (!libResult.empty()) { if (result.empty()) { result = std::move(libResult); @@ -1246,7 +1245,8 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget, std::string const& config, std::string const& prop, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<EvaluatedTargetPropertyEntry>& entries) + std::vector<EvaluatedTargetPropertyEntry>& entries, + bool usage_requirements_only = true) { if (cmLinkImplementationLibraries const* impl = headTarget->GetLinkImplementationLibraries(config)) { @@ -1259,9 +1259,9 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget, cmGeneratorExpressionContext context( headTarget->GetLocalGenerator(), config, false, headTarget, headTarget, true, lib.Backtrace, lang); - cmExpandList( - lib.Target->EvaluateInterfaceProperty(prop, &context, dagChecker), - ee.Values); + cmExpandList(lib.Target->EvaluateInterfaceProperty( + prop, &context, dagChecker, usage_requirements_only), + ee.Values); ee.ContextDependent = context.HadContextSensitiveCondition; entries.emplace_back(std::move(ee)); } @@ -1672,6 +1672,19 @@ void cmGeneratorTarget::ComputeAllConfigSources() const } } +std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const +{ + std::set<std::string> languages; + std::vector<AllConfigSource> const& sources = this->GetAllConfigSources(); + for (AllConfigSource const& si : sources) { + std::string const& lang = si.Source->GetOrDetermineLanguage(); + if (!lang.empty()) { + languages.emplace(lang); + } + } + return languages; +} + std::string cmGeneratorTarget::GetCompilePDBName( const std::string& config) const { @@ -2114,7 +2127,9 @@ std::string cmGeneratorTarget::GetInstallNameDirForBuildTree( // If building directly for installation then the build tree install_name // is the same as the install tree. if (this->MacOSXUseInstallNameDir()) { - return this->GetInstallNameDirForInstallTree(); + std::string installPrefix = + this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); + return this->GetInstallNameDirForInstallTree(config, installPrefix); } // Use the build tree directory for the target. @@ -2132,7 +2147,8 @@ std::string cmGeneratorTarget::GetInstallNameDirForBuildTree( return ""; } -std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const +std::string cmGeneratorTarget::GetInstallNameDirForInstallTree( + const std::string& config, const std::string& installPrefix) const { if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { std::string dir; @@ -2140,7 +2156,13 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) { if (install_name_dir && *install_name_dir) { - dir = cmStrCat(install_name_dir, '/'); + dir = install_name_dir; + cmGeneratorExpression::ReplaceInstallPrefix(dir, installPrefix); + dir = + cmGeneratorExpression::Evaluate(dir, this->LocalGenerator, config); + if (!dir.empty()) { + dir = cmStrCat(dir, '/'); + } } } if (!install_name_dir) { @@ -2492,11 +2514,11 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo( info.WindowsExportAllSymbols = this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") && this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"); -#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) +#if !defined(CMAKE_BOOTSTRAP) info.DefFileGenerated = info.WindowsExportAllSymbols || info.Sources.size() > 1; #else - // Our __create_def helper is only available on Windows. + // Our __create_def helper is not available during CMake bootstrap. info.DefFileGenerated = false; #endif if (info.DefFileGenerated) { @@ -3277,10 +3299,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( CM_FALLTHROUGH; } case cmPolicies::OLD: { - std::unique_ptr<TargetPropertyEntry> entry( - CreateTargetPropertyEntry(configProp)); + std::unique_ptr<TargetPropertyEntry> entry = + CreateTargetPropertyEntry(configProp); entries.emplace_back(EvaluateTargetPropertyEntry( - this, config, language, &dagChecker, entry.get())); + this, config, language, &dagChecker, *entry)); } break; case cmPolicies::NEW: case cmPolicies::REQUIRED_ALWAYS: @@ -3647,7 +3669,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( this->LinkOptionsEntries); AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language, - &dagChecker, entries); + &dagChecker, entries, + this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processOptions(this, entries, result, uniqueOptions, debugOptions, "link options", OptionsParse::Shell); @@ -3779,10 +3802,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { std::vector<std::string> options = cmExpandedList(linkOptions); for (const auto& option : options) { - std::unique_ptr<TargetPropertyEntry> entry( - CreateTargetPropertyEntry(option)); - entries.emplace_back(EvaluateTargetPropertyEntry( - this, config, language, &dagChecker, entry.get())); + std::unique_ptr<TargetPropertyEntry> entry = + CreateTargetPropertyEntry(option); + entries.emplace_back(EvaluateTargetPropertyEntry(this, config, language, + &dagChecker, *entry)); } } processOptions(this, entries, result, uniqueOptions, false, @@ -3902,7 +3925,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( this->LinkDirectoriesEntries); AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language, - &dagChecker, entries); + &dagChecker, entries, + this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processLinkDirectories(this, entries, result, uniqueDirectories, debugDirectories); @@ -3933,14 +3957,15 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) { std::vector<std::string> depends = cmExpandedList(linkDepends); for (const auto& depend : depends) { - std::unique_ptr<TargetPropertyEntry> entry( - CreateTargetPropertyEntry(depend)); - entries.emplace_back(EvaluateTargetPropertyEntry( - this, config, language, &dagChecker, entry.get())); + std::unique_ptr<TargetPropertyEntry> entry = + CreateTargetPropertyEntry(depend); + entries.emplace_back(EvaluateTargetPropertyEntry(this, config, language, + &dagChecker, *entry)); } } AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language, - &dagChecker, entries); + &dagChecker, entries, + this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processOptions(this, entries, result, uniqueOptions, false, "link depends", OptionsParse::None); @@ -4720,9 +4745,9 @@ std::string intersect(const std::set<std::string>& s1, } void cmGeneratorTarget::CheckPropertyCompatibility( - cmComputeLinkInformation* info, const std::string& config) const + cmComputeLinkInformation& info, const std::string& config) const { - const cmComputeLinkInformation::ItemVector& deps = info->GetItems(); + const cmComputeLinkInformation::ItemVector& deps = info.GetItems(); std::set<std::string> emittedBools; static const std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; @@ -5067,10 +5092,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, } std::string interfaceProperty = "INTERFACE_" + p; - std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter( - p == "POSITION_INDEPENDENT_CODE" ? new cmGeneratorExpressionInterpreter( - tgt->GetLocalGenerator(), config, tgt) - : nullptr); + std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter; + if (p == "POSITION_INDEPENDENT_CODE") { + genexInterpreter = cm::make_unique<cmGeneratorExpressionInterpreter>( + tgt->GetLocalGenerator(), config, tgt); + } for (cmGeneratorTarget const* theTarget : deps) { // An error should be reported if one dependency @@ -5217,22 +5243,19 @@ cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation( auto i = this->LinkInformation.find(key); if (i == this->LinkInformation.end()) { // Compute information for this configuration. - cmComputeLinkInformation* info = - new cmComputeLinkInformation(this, config); - if (!info || !info->Compute()) { - delete info; - info = nullptr; + auto info = cm::make_unique<cmComputeLinkInformation>(this, config); + if (info && !info->Compute()) { + info.reset(); } // Store the information for this configuration. - cmTargetLinkInformationMap::value_type entry(key, info); - i = this->LinkInformation.insert(entry).first; + i = this->LinkInformation.emplace(key, std::move(info)).first; - if (info) { - this->CheckPropertyCompatibility(info, config); + if (i->second) { + this->CheckPropertyCompatibility(*i->second, config); } } - return i->second; + return i->second.get(); } void cmGeneratorTarget::GetTargetVersion(int& major, int& minor) const @@ -6330,6 +6353,21 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const return lib; } +bool cmGeneratorTarget::IsDeprecated() const +{ + const char* deprecation = this->GetProperty("DEPRECATION"); + return deprecation && *deprecation; +} + +std::string cmGeneratorTarget::GetDeprecation() const +{ + // find DEPRECATION property + if (const char* deprecation = this->GetProperty("DEPRECATION")) { + return deprecation; + } + return std::string(); +} + void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages, const std::string& config) const { @@ -6379,8 +6417,7 @@ bool cmGeneratorTarget::IsCSharpOnly() const this->GetType() != cmStateEnums::EXECUTABLE) { return false; } - std::set<std::string> languages; - this->GetLanguages(languages, ""); + std::set<std::string> languages = this->GetAllConfigCompileLanguages(); // Consider an explicit linker language property, but *not* the // computed linker language that may depend on linked targets. const char* linkLang = this->GetProperty("LINKER_LANGUAGE"); @@ -6601,6 +6638,19 @@ cmLinkItem cmGeneratorTarget::ResolveLinkItem( return cmLinkItem(resolved.String, bt); } + // Check deprecation, issue message with `bt` backtrace. + if (resolved.Target->IsDeprecated()) { + std::ostringstream w; + /* clang-format off */ + w << + "The library that is being linked to, " << resolved.Target->GetName() << + ", is marked as being deprecated by the owner. The message provided by " + "the developer is: \n" << resolved.Target->GetDeprecation() << "\n"; + /* clang-format on */ + this->LocalGenerator->GetCMakeInstance()->IssueMessage( + MessageType::AUTHOR_WARNING, w.str(), bt); + } + // Skip targets that will not really be linked. This is probably a // name conflict between an external library and an executable // within the project. diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 493eafcf01..0a72cbea7a 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -7,6 +7,7 @@ #include <cstddef> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -125,7 +126,7 @@ public: struct AllConfigSource { - cmSourceFile const* Source; + cmSourceFile* Source; cmGeneratorTarget::SourceKind Kind; std::vector<size_t> Configs; }; @@ -134,6 +135,10 @@ public: per-source configurations assigned. */ std::vector<AllConfigSource> const& GetAllConfigSources() const; + /** Get all languages used to compile sources in any configuration. + This excludes the languages of objects from object libraries. */ + std::set<std::string> GetAllConfigCompileLanguages() const; + void GetObjectSources(std::vector<cmSourceFile const*>&, const std::string& config) const; const std::string& GetObjectName(cmSourceFile const* file); @@ -245,6 +250,13 @@ public: std::string GetAppBundleDirectory(const std::string& config, BundleDirectoryLevel level) const; + /** Return whether this target is marked as deprecated by the + maintainer */ + bool IsDeprecated() const; + + /** Returns the deprecation message provided by the maintainer */ + std::string GetDeprecation() const; + /** Return whether this target is an executable Bundle, a framework or CFBundle on Apple. */ bool IsBundleOnApple() const; @@ -274,7 +286,8 @@ public: /** Return the install name directory for the target in the * install tree. For example: "\@rpath/" or "\@loader_path/". */ - std::string GetInstallNameDirForInstallTree() const; + std::string GetInstallNameDirForInstallTree( + const std::string& config, const std::string& installPrefix) const; cmListFileBacktrace GetBacktrace() const; @@ -701,7 +714,8 @@ public: std::string EvaluateInterfaceProperty( std::string const& prop, cmGeneratorExpressionContext* context, - cmGeneratorExpressionDAGChecker* dagCheckerParent) const; + cmGeneratorExpressionDAGChecker* dagCheckerParent, + bool usage_requirements_only = true) const; bool HaveInstallTreeRPATH(const std::string& config) const; @@ -760,6 +774,7 @@ private: }; using SourceEntriesType = std::map<cmSourceFile const*, SourceEntry>; SourceEntriesType SourceDepends; + mutable std::set<std::string> VisitedConfigsForObjects; mutable std::map<cmSourceFile const*, std::string> Objects; std::set<cmSourceFile const*> ExplicitObjectName; mutable std::map<std::string, std::vector<std::string>> SystemIncludesCache; @@ -816,10 +831,10 @@ private: mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap; using cmTargetLinkInformationMap = - std::map<std::string, cmComputeLinkInformation*>; + std::map<std::string, std::unique_ptr<cmComputeLinkInformation>>; mutable cmTargetLinkInformationMap LinkInformation; - void CheckPropertyCompatibility(cmComputeLinkInformation* info, + void CheckPropertyCompatibility(cmComputeLinkInformation& info, const std::string& config) const; struct LinkImplClosure : public std::vector<cmGeneratorTarget const*> @@ -880,16 +895,20 @@ private: mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists; bool MaybeHaveInterfaceProperty(std::string const& prop, - cmGeneratorExpressionContext* context) const; - - std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; - std::vector<TargetPropertyEntry*> CompileOptionsEntries; - std::vector<TargetPropertyEntry*> CompileFeaturesEntries; - std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; - std::vector<TargetPropertyEntry*> LinkOptionsEntries; - std::vector<TargetPropertyEntry*> LinkDirectoriesEntries; - std::vector<TargetPropertyEntry*> PrecompileHeadersEntries; - std::vector<TargetPropertyEntry*> SourceEntries; + cmGeneratorExpressionContext* context, + bool usage_requirements_only) const; + + using TargetPropertyEntryVector = + std::vector<std::unique_ptr<TargetPropertyEntry>>; + + TargetPropertyEntryVector IncludeDirectoriesEntries; + TargetPropertyEntryVector CompileOptionsEntries; + TargetPropertyEntryVector CompileFeaturesEntries; + TargetPropertyEntryVector CompileDefinitionsEntries; + TargetPropertyEntryVector LinkOptionsEntries; + TargetPropertyEntryVector LinkDirectoriesEntries; + TargetPropertyEntryVector PrecompileHeadersEntries; + TargetPropertyEntryVector SourceEntries; mutable std::set<std::string> LinkImplicitNullProperties; mutable std::map<std::string, std::string> PchHeaders; mutable std::map<std::string, std::string> PchSources; diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 8e4352e29f..5e2248ed10 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -113,7 +113,7 @@ void cmGhsMultiTargetGenerator::Generate() // Tell the global generator the name of the project file this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", - this->Name.c_str()); + this->Name); this->GeneratorTarget->Target->SetProperty( "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); @@ -279,10 +279,10 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, std::string frameworkPath; std::string linkPath; - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->GetGlobalGenerator()->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); this->LocalGenerator->GetTargetFlags( linkLineComputer.get(), config, linkLibraries, flags, linkFlags, diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 51d681dee2..06943e7fff 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -2,6 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalBorlandMakefileGenerator.h" +#include <utility> + +#include <cm/memory> + #include "cmDocumentationEntry.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" @@ -35,15 +39,14 @@ void cmGlobalBorlandMakefileGenerator::EnableLanguage( } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalBorlandMakefileGenerator::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(cmMakefile* mf) { - cmLocalUnixMakefileGenerator3* lg = - new cmLocalUnixMakefileGenerator3(this, mf); + auto lg = cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf); lg->SetMakefileVariableSize(32); lg->SetMakeCommandEscapeTargetTwice(true); lg->SetBorlandMakeCurlyHack(true); - return lg; + return std::unique_ptr<cmLocalGenerator>(std::move(lg)); } void cmGlobalBorlandMakefileGenerator::GetDocumentation( diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index da04743ac0..9af0eac412 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -4,6 +4,7 @@ #define cmGlobalBorlandMakefileGenerator_h #include <iosfwd> +#include <memory> #include "cmGlobalNMakeMakefileGenerator.h" @@ -16,10 +17,10 @@ class cmGlobalBorlandMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalBorlandMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalBorlandMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalBorlandMakefileGenerator>()); } //! Get the name for the generator. @@ -33,7 +34,8 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); //! Create a local generator appropriate to this Global Generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index 9fa4467b2a..e04eef1b44 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalCommonGenerator.h" +#include <memory> #include <utility> #include "cmGeneratorTarget.h" @@ -24,15 +25,15 @@ std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget> cmGlobalCommonGenerator::ComputeDirectoryTargets() const { std::map<std::string, DirectoryTarget> dirTargets; - for (cmLocalGenerator* lg : this->LocalGenerators) { + for (const auto& lg : this->LocalGenerators) { std::string const& currentBinaryDir( lg->GetStateSnapshot().GetDirectory().GetCurrentBinary()); DirectoryTarget& dirTarget = dirTargets[currentBinaryDir]; - dirTarget.LG = lg; + dirTarget.LG = lg.get(); // The directory-level rule should depend on the target-level rules // for all targets in the directory. - for (auto gt : lg->GetGeneratorTargets()) { + for (const auto& gt : lg->GetGeneratorTargets()) { cmStateEnums::TargetType const type = gt->GetType(); if (type != cmStateEnums::EXECUTABLE && type != cmStateEnums::STATIC_LIBRARY && @@ -43,7 +44,7 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const continue; } DirectoryTarget::Target t; - t.GT = gt; + t.GT = gt.get(); if (const char* exclude = gt->GetProperty("EXCLUDE_FROM_ALL")) { if (cmIsOn(exclude)) { // This target has been explicitly excluded. diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 09fb87dd70..4cbcda026f 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -10,6 +10,9 @@ #include <initializer_list> #include <iterator> #include <sstream> +#include <utility> + +#include <cm/memory> #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" @@ -31,6 +34,7 @@ #include "cmGeneratorTarget.h" #include "cmInstallGenerator.h" #include "cmLinkLineComputer.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMSVC60LinkLineComputer.h" #include "cmMakefile.h" @@ -121,6 +125,7 @@ Json::Value cmGlobalGenerator::GetJson() const { Json::Value generator = Json::objectValue; generator["name"] = this->GetName(); + generator["multiConfig"] = this->IsMultiConfig(); return generator; } #endif @@ -165,7 +170,7 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p, return false; } -bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, +bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, bool, cmMakefile* mf) { if (ts.empty()) { @@ -256,16 +261,17 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, } } -void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen) +void cmGlobalGenerator::AddBuildExportSet( + std::unique_ptr<cmExportBuildFileGenerator> gen) { - this->BuildExportSets[gen->GetMainExportFileName()] = gen; + this->BuildExportSets[gen->GetMainExportFileName()] = std::move(gen); } void cmGlobalGenerator::AddBuildExportExportSet( - cmExportBuildFileGenerator* gen) + std::unique_ptr<cmExportBuildFileGenerator> gen) { - this->BuildExportSets[gen->GetMainExportFileName()] = gen; - this->BuildExportExportSets[gen->GetMainExportFileName()] = gen; + this->BuildExportExportSets[gen->GetMainExportFileName()] = gen.get(); + this->AddBuildExportSet(std::move(gen)); } bool cmGlobalGenerator::GenerateImportFile(const std::string& file) @@ -275,13 +281,11 @@ bool cmGlobalGenerator::GenerateImportFile(const std::string& file) bool result = it->second->GenerateImportFile(); if (!this->ConfigureDoneCMP0026AndCMP0024) { - for (cmMakefile* m : this->Makefiles) { - m->RemoveExportBuildFileGeneratorCMP0024(it->second); + for (const auto& m : this->Makefiles) { + m->RemoveExportBuildFileGeneratorCMP0024(it->second.get()); } } - delete it->second; - it->second = nullptr; this->BuildExportSets.erase(it); return result; } @@ -295,8 +299,8 @@ void cmGlobalGenerator::ForceLinkerLanguages() bool cmGlobalGenerator::CheckTargetsForMissingSources() const { bool failed = false; - for (cmLocalGenerator* localGen : this->LocalGenerators) { - for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) { + for (const auto& localGen : this->LocalGenerators) { + for (const auto& target : localGen->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || target->GetType() == cmStateEnums::TargetType::UTILITY || @@ -335,8 +339,8 @@ bool cmGlobalGenerator::CheckTargetsForType() const return false; } bool failed = false; - for (cmLocalGenerator* generator : this->LocalGenerators) { - for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) { + for (const auto& generator : this->LocalGenerators) { + for (const auto& target : generator->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::EXECUTABLE && target->GetPropertyAsBool("WIN32_EXECUTABLE")) { std::vector<std::string> const& configs = @@ -363,8 +367,8 @@ bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const return false; } bool failed = false; - for (cmLocalGenerator* generator : this->LocalGenerators) { - for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) { + for (const auto& generator : this->LocalGenerators) { + for (const auto& target : generator->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || target->GetType() == cmStateEnums::TargetType::UTILITY || @@ -650,7 +654,7 @@ void cmGlobalGenerator::EnableLanguage( // Tell the generator about the toolset, if any. std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"); - if (!this->SetGeneratorToolset(toolset, mf)) { + if (!this->SetGeneratorToolset(toolset, false, mf)) { cmSystemTools::SetFatalErrorOccured(); return; } @@ -1199,13 +1203,12 @@ void cmGlobalGenerator::ClearEnabledLanguages() void cmGlobalGenerator::CreateLocalGenerators() { this->LocalGeneratorSearchIndex.clear(); - cmDeleteAll(this->LocalGenerators); this->LocalGenerators.clear(); this->LocalGenerators.reserve(this->Makefiles.size()); - for (cmMakefile* m : this->Makefiles) { - cmLocalGenerator* lg = this->CreateLocalGenerator(m); - this->LocalGenerators.push_back(lg); - this->IndexLocalGenerator(lg); + for (const auto& m : this->Makefiles) { + auto lg = this->CreateLocalGenerator(m.get()); + this->IndexLocalGenerator(lg.get()); + this->LocalGenerators.push_back(std::move(lg)); } } @@ -1221,9 +1224,10 @@ void cmGlobalGenerator::Configure() snapshot.GetDirectory().SetCurrentBinary( this->CMakeInstance->GetHomeOutputDirectory()); - cmMakefile* dirMf = new cmMakefile(this, snapshot); + auto dirMfu = cm::make_unique<cmMakefile>(this, snapshot); + auto dirMf = dirMfu.get(); + this->Makefiles.push_back(std::move(dirMfu)); dirMf->SetRecursionDepth(this->RecursionDepth); - this->Makefiles.push_back(dirMf); this->IndexMakefile(dirMf); this->BinaryDirectories.insert( @@ -1241,11 +1245,11 @@ void cmGlobalGenerator::Configure() std::vector<GlobalTargetInfo> globalTargets; this->CreateDefaultGlobalTargets(globalTargets); - for (cmMakefile* mf : this->Makefiles) { + for (const auto& mf : this->Makefiles) { auto& targets = mf->GetTargets(); for (GlobalTargetInfo const& globalTarget : globalTargets) { targets.emplace(globalTarget.Name, - this->CreateGlobalTarget(globalTarget, mf)); + this->CreateGlobalTarget(globalTarget, mf.get())); } } } @@ -1258,10 +1262,6 @@ void cmGlobalGenerator::Configure() "number of local generators", cmStateEnums::INTERNAL); - // check for link libraries and include directories containing "NOTFOUND" - // and for infinite loops - this->CheckTargetProperties(); - if (this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) { std::ostringstream msg; if (cmSystemTools::GetErrorOccuredFlag()) { @@ -1284,6 +1284,10 @@ void cmGlobalGenerator::Configure() void cmGlobalGenerator::CreateGenerationObjects(TargetTypes targetTypes) { this->CreateLocalGenerators(); + // Commit side effects only if we are actually generating + if (this->GetConfigureDoneCMP0026()) { + this->CheckTargetProperties(); + } this->CreateGeneratorTargets(targetTypes); this->ComputeBuildFileGenerators(); } @@ -1294,8 +1298,11 @@ void cmGlobalGenerator::CreateImportedGenerationObjects( { this->CreateGenerationObjects(ImportedOnly); auto const mfit = - std::find(this->Makefiles.begin(), this->Makefiles.end(), mf); - cmLocalGenerator* lg = + std::find_if(this->Makefiles.begin(), this->Makefiles.end(), + [mf](const std::unique_ptr<cmMakefile>& item) { + return item.get() == mf; + }); + auto& lg = this->LocalGenerators[std::distance(this->Makefiles.begin(), mfit)]; for (std::string const& t : targets) { cmGeneratorTarget* gt = lg->FindGeneratorTargetToUse(t); @@ -1309,7 +1316,7 @@ cmExportBuildFileGenerator* cmGlobalGenerator::GetExportedTargetsFile( const std::string& filename) const { auto const it = this->BuildExportSets.find(filename); - return it == this->BuildExportSets.end() ? nullptr : it->second; + return it == this->BuildExportSets.end() ? nullptr : it->second.get(); } void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target) @@ -1348,7 +1355,7 @@ void cmGlobalGenerator::ComputeBuildFileGenerators() std::vector<cmExportBuildFileGenerator*> gens = this->Makefiles[i]->GetExportBuildFileGenerators(); for (cmExportBuildFileGenerator* g : gens) { - g->Compute(this->LocalGenerators[i]); + g->Compute(this->LocalGenerators[i].get()); } } } @@ -1387,7 +1394,7 @@ bool cmGlobalGenerator::Compute() } // Add generator specific helper commands - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->AddHelperCommands(); } @@ -1397,16 +1404,16 @@ bool cmGlobalGenerator::Compute() // on the original cmTarget instance. It accumulates features // across all configurations. Some refactoring is needed to // compute a per-config resulta purely during generation. - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { if (!localGen->ComputeTargetCompileFeatures()) { return false; } } - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { cmMakefile* mf = localGen->GetMakefile(); for (cmInstallGenerator* g : mf->GetInstallGenerators()) { - if (!g->Compute(localGen)) { + if (!g->Compute(localGen.get())) { return false; } } @@ -1416,7 +1423,7 @@ bool cmGlobalGenerator::Compute() // Trace the dependencies, after that no custom commands should be added // because their dependencies might not be handled correctly - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->TraceDependencies(); } @@ -1428,7 +1435,7 @@ bool cmGlobalGenerator::Compute() this->ForceLinkerLanguages(); // Compute the manifest of main targets generated. - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->ComputeTargetManifest(); } @@ -1445,7 +1452,7 @@ bool cmGlobalGenerator::Compute() return false; } - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->ComputeHomeRelativeOutputPath(); } @@ -1460,6 +1467,8 @@ void cmGlobalGenerator::Generate() this->ProcessEvaluationFiles(); + this->CMakeInstance->UpdateProgress("Generating", 0.1f); + // Generate project files for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { this->SetCurrentMakefile(this->LocalGenerators[i]->GetMakefile()); @@ -1471,8 +1480,9 @@ void cmGlobalGenerator::Generate() this->LocalGenerators[i]->GenerateTestFiles(); this->CMakeInstance->UpdateProgress( "Generating", - (static_cast<float>(i) + 1.0f) / - static_cast<float>(this->LocalGenerators.size())); + 0.1f + + 0.9f * (static_cast<float>(i) + 1.0f) / + static_cast<float>(this->LocalGenerators.size())); } this->SetCurrentMakefile(nullptr); @@ -1555,40 +1565,42 @@ bool cmGlobalGenerator::QtAutoGen() bool cmGlobalGenerator::AddAutomaticSources() { - for (cmLocalGenerator* lg : this->LocalGenerators) { + for (const auto& lg : this->LocalGenerators) { lg->CreateEvaluationFileOutputs(); - for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) { + for (const auto& gt : lg->GetGeneratorTargets()) { if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY || gt->GetType() == cmStateEnums::UTILITY || gt->GetType() == cmStateEnums::GLOBAL_TARGET) { continue; } - lg->AddUnityBuild(gt); - lg->AddPchDependencies(gt); + lg->AddUnityBuild(gt.get()); + lg->AddPchDependencies(gt.get()); } } // The above transformations may have changed the classification of sources. // Clear the source list and classification cache (KindedSources) of all // targets so that it will be recomputed correctly by the generators later // now that the above transformations are done for all targets. - for (cmLocalGenerator* lg : this->LocalGenerators) { - for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) { + for (const auto& lg : this->LocalGenerators) { + for (const auto& gt : lg->GetGeneratorTargets()) { gt->ClearSourcesCache(); } } return true; } -cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( +std::unique_ptr<cmLinkLineComputer> cmGlobalGenerator::CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const { - return new cmLinkLineComputer(outputConverter, stateDir); + return cm::make_unique<cmLinkLineComputer>(outputConverter, stateDir); } -cmLinkLineComputer* cmGlobalGenerator::CreateMSVC60LinkLineComputer( +std::unique_ptr<cmLinkLineComputer> +cmGlobalGenerator::CreateMSVC60LinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const { - return new cmMSVC60LinkLineComputer(outputConverter, stateDir); + return std::unique_ptr<cmLinkLineComputer>( + cm::make_unique<cmMSVC60LinkLineComputer>(outputConverter, stateDir)); } void cmGlobalGenerator::FinalizeTargetCompileInfo() @@ -1597,7 +1609,7 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() this->CMakeInstance->GetState()->GetEnabledLanguages(); // Construct per-target generator information. - for (cmMakefile* mf : this->Makefiles) { + for (const auto& mf : this->Makefiles) { const cmStringRange noconfig_compile_definitions = mf->GetCompileDefinitionsEntries(); const cmBacktraceRange noconfig_compile_definitions_bts = @@ -1661,8 +1673,7 @@ void cmGlobalGenerator::CreateGeneratorTargets( if (targetTypes == AllTargets) { for (auto& target : mf->GetTargets()) { cmTarget* t = &target.second; - cmGeneratorTarget* gt = new cmGeneratorTarget(t, lg); - lg->AddGeneratorTarget(gt); + lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(t, lg)); } } @@ -1675,31 +1686,28 @@ void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes) { std::map<cmTarget*, cmGeneratorTarget*> importedMap; for (unsigned int i = 0; i < this->Makefiles.size(); ++i) { - cmMakefile* mf = this->Makefiles[i]; + auto& mf = this->Makefiles[i]; for (cmTarget* ownedImpTgt : mf->GetOwnedImportedTargets()) { - cmLocalGenerator* lg = this->LocalGenerators[i]; - cmGeneratorTarget* gt = new cmGeneratorTarget(ownedImpTgt, lg); - lg->AddOwnedImportedGeneratorTarget(gt); - importedMap[ownedImpTgt] = gt; + cmLocalGenerator* lg = this->LocalGenerators[i].get(); + auto gt = cm::make_unique<cmGeneratorTarget>(ownedImpTgt, lg); + importedMap[ownedImpTgt] = gt.get(); + lg->AddOwnedImportedGeneratorTarget(std::move(gt)); } } // Construct per-target generator information. for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { - this->CreateGeneratorTargets(targetTypes, this->Makefiles[i], - this->LocalGenerators[i], importedMap); + this->CreateGeneratorTargets(targetTypes, this->Makefiles[i].get(), + this->LocalGenerators[i].get(), importedMap); } } void cmGlobalGenerator::ClearGeneratorMembers() { - cmDeleteAll(this->BuildExportSets); this->BuildExportSets.clear(); - cmDeleteAll(this->Makefiles); this->Makefiles.clear(); - cmDeleteAll(this->LocalGenerators); this->LocalGenerators.clear(); this->AliasTargets.clear(); @@ -1722,12 +1730,12 @@ void cmGlobalGenerator::ComputeTargetObjectDirectory( void cmGlobalGenerator::CheckTargetProperties() { + // check for link libraries and include directories containing "NOTFOUND" + // and for infinite loops std::map<std::string, std::string> notFoundMap; - // std::set<std::string> notFoundMap; - // after it is all done do a ConfigureFinalPass cmState* state = this->GetCMakeInstance()->GetState(); for (unsigned int i = 0; i < this->Makefiles.size(); ++i) { - this->Makefiles[i]->ConfigureFinalPass(); + this->Makefiles[i]->Generate(*this->LocalGenerators[i]); for (auto const& target : this->Makefiles[i]->GetTargets()) { if (target.second.GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; @@ -1771,11 +1779,6 @@ void cmGlobalGenerator::CheckTargetProperties() } } } - this->CMakeInstance->UpdateProgress( - "Configuring", - 0.9f + - 0.1f * (static_cast<float>(i) + 1.0f) / - static_cast<float>(this->Makefiles.size())); } if (!notFoundMap.empty()) { @@ -1999,10 +2002,10 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand( return makeCommand; } -void cmGlobalGenerator::AddMakefile(cmMakefile* mf) +void cmGlobalGenerator::AddMakefile(std::unique_ptr<cmMakefile> mf) { - this->Makefiles.push_back(mf); - this->IndexMakefile(mf); + this->IndexMakefile(mf.get()); + this->Makefiles.push_back(std::move(mf)); // update progress // estimate how many lg there will be @@ -2025,10 +2028,10 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf) } int numGen = atoi(numGenC->c_str()); - float prog = 0.9f * static_cast<float>(this->Makefiles.size()) / - static_cast<float>(numGen); - if (prog > 0.9f) { - prog = 0.9f; + float prog = + static_cast<float>(this->Makefiles.size()) / static_cast<float>(numGen); + if (prog > 1.0f) { + prog = 1.0f; } this->CMakeInstance->UpdateProgress("Configuring", prog); } @@ -2045,9 +2048,10 @@ void cmGlobalGenerator::EnableInstallTarget() this->InstallTargetEnabled = true; } -cmLocalGenerator* cmGlobalGenerator::CreateLocalGenerator(cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> cmGlobalGenerator::CreateLocalGenerator( + cmMakefile* mf) { - return new cmLocalGenerator(this, mf); + return cm::make_unique<cmLocalGenerator>(this, mf); } void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen, @@ -2142,7 +2146,7 @@ int cmGlobalGenerator::GetLinkerPreference(const std::string& lang) const void cmGlobalGenerator::FillProjectMap() { this->ProjectMap.clear(); // make sure we start with a clean map - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { // for each local generator add all projects cmStateSnapshot snp = localGen->GetStateSnapshot(); std::string name; @@ -2150,7 +2154,7 @@ void cmGlobalGenerator::FillProjectMap() std::string snpProjName = snp.GetProjectName(); if (name != snpProjName) { name = snpProjName; - this->ProjectMap[name].push_back(localGen); + this->ProjectMap[name].push_back(localGen.get()); } snp = snp.GetBuildsystemDirectoryParent(); } while (snp.IsValid()); @@ -2353,7 +2357,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets( void cmGlobalGenerator::AddGlobalTarget_Package( std::vector<GlobalTargetInfo>& targets) { - cmMakefile* mf = this->Makefiles[0]; + auto& mf = this->Makefiles[0]; std::string configFile = cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackConfig.cmake"); if (!cmSystemTools::FileExists(configFile)) { @@ -2402,7 +2406,7 @@ void cmGlobalGenerator::AddGlobalTarget_PackageSource( return; } - cmMakefile* mf = this->Makefiles[0]; + auto& mf = this->Makefiles[0]; std::string configFile = cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackSourceConfig.cmake"); if (!cmSystemTools::FileExists(configFile)) { @@ -2434,7 +2438,7 @@ void cmGlobalGenerator::AddGlobalTarget_PackageSource( void cmGlobalGenerator::AddGlobalTarget_Test( std::vector<GlobalTargetInfo>& targets) { - cmMakefile* mf = this->Makefiles[0]; + auto& mf = this->Makefiles[0]; if (!mf->IsOn("CMAKE_TESTING_ENABLED")) { return; } @@ -2475,6 +2479,7 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache( } GlobalTargetInfo gti; gti.Name = editCacheTargetName; + gti.PerConfig = false; cmCustomCommandLine singleLine; // Use generator preference for the edit_cache rule if it is defined. @@ -2509,6 +2514,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache( gti.Name = rebuildCacheTargetName; gti.Message = "Running CMake to regenerate build system..."; gti.UsesTerminal = true; + gti.PerConfig = false; cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCMakeCommand()); singleLine.push_back("-S$(CMAKE_SOURCE_DIR)"); @@ -2520,7 +2526,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache( void cmGlobalGenerator::AddGlobalTarget_Install( std::vector<GlobalTargetInfo>& targets) { - cmMakefile* mf = this->Makefiles[0]; + auto& mf = this->Makefiles[0]; const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir(); bool skipInstallRules = mf->IsOn("CMAKE_SKIP_INSTALL_RULES"); if (this->InstallTargetEnabled && skipInstallRules) { @@ -2570,7 +2576,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( singleLine.push_back(cmd); if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { std::string cfgArg = "-DBUILD_TYPE="; - bool useEPN = this->UseEffectivePlatformName(mf); + bool useEPN = this->UseEffectivePlatformName(mf.get()); if (useEPN) { cfgArg += "$(CONFIGURATION)"; singleLine.push_back(cfgArg); @@ -2653,19 +2659,19 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, { // Package cmTarget target(gti.Name, cmStateEnums::GLOBAL_TARGET, - cmTarget::VisibilityNormal, mf); + cmTarget::VisibilityNormal, mf, gti.PerConfig); target.SetProperty("EXCLUDE_FROM_ALL", "TRUE"); std::vector<std::string> no_outputs; std::vector<std::string> no_byproducts; std::vector<std::string> no_depends; // Store the custom command in the target. - cmCustomCommand cc(nullptr, no_outputs, no_byproducts, no_depends, - gti.CommandLines, nullptr, gti.WorkingDir.c_str()); + cmCustomCommand cc(no_outputs, no_byproducts, no_depends, gti.CommandLines, + cmListFileBacktrace(), nullptr, gti.WorkingDir.c_str()); cc.SetUsesTerminal(gti.UsesTerminal); target.AddPostBuildCommand(std::move(cc)); if (!gti.Message.empty()) { - target.SetProperty("EchoString", gti.Message.c_str()); + target.SetProperty("EchoString", gti.Message); } for (std::string const& d : gti.Depends) { target.AddUtility(d); @@ -2737,9 +2743,9 @@ bool cmGlobalGenerator::IsReservedTarget(std::string const& name) } void cmGlobalGenerator::SetExternalMakefileProjectGenerator( - cmExternalMakefileProjectGenerator* extraGenerator) + std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator) { - this->ExtraGenerator.reset(extraGenerator); + this->ExtraGenerator = std::move(extraGenerator); if (this->ExtraGenerator) { this->ExtraGenerator->SetGlobalGenerator(this); } @@ -2765,27 +2771,26 @@ void cmGlobalGenerator::GetFilesReplacedDuringGenerate( std::back_inserter(filenames)); } -void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets, - TargetDependSet& originalTargets, - cmLocalGenerator* root, - GeneratorVector const& generators) +void cmGlobalGenerator::GetTargetSets( + TargetDependSet& projectTargets, TargetDependSet& originalTargets, + cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { // loop over all local generators - for (cmLocalGenerator* generator : generators) { + for (auto generator : generators) { // check to make sure generator is not excluded if (this->IsExcluded(root, generator)) { continue; } // loop over all the generator targets in the makefile - for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) { - if (this->IsRootOnlyTarget(target) && + for (const auto& target : generator->GetGeneratorTargets()) { + if (this->IsRootOnlyTarget(target.get()) && target->GetLocalGenerator() != root) { continue; } // put the target in the set of original targets - originalTargets.insert(target); + originalTargets.insert(target.get()); // Get the set of targets that depend on target - this->AddTargetDepends(target, projectTargets); + this->AddTargetDepends(target.get(), projectTargets); } } } @@ -2961,12 +2966,12 @@ void cmGlobalGenerator::WriteSummary() "/CMakeFiles/TargetDirectories.txt"); cmGeneratedFileStream fout(fname); - for (cmLocalGenerator* lg : this->LocalGenerators) { - for (cmGeneratorTarget* tgt : lg->GetGeneratorTargets()) { + for (const auto& lg : this->LocalGenerators) { + for (const auto& tgt : lg->GetGeneratorTargets()) { if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - this->WriteSummary(tgt); + this->WriteSummary(tgt.get()); fout << tgt->GetSupportDirectory() << "\n"; } } @@ -3111,7 +3116,7 @@ cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const void cmGlobalGenerator::ProcessEvaluationFiles() { std::vector<std::string> generatedFiles; - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (auto& localGen : this->LocalGenerators) { localGen->ProcessEvaluationFiles(generatedFiles); } } @@ -3127,7 +3132,7 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() cmake::InstalledFilesMap const& installedFiles = this->CMakeInstance->GetInstalledFiles(); - cmLocalGenerator* lg = this->LocalGenerators[0]; + const auto& lg = this->LocalGenerators[0]; cmMakefile* mf = lg->GetMakefile(); std::vector<std::string> configs; @@ -3146,8 +3151,8 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() for (auto const& i : installedFiles) { cmInstalledFile const& installedFile = i.second; - cmCPackPropertiesGenerator cpackPropertiesGenerator(lg, installedFile, - configs); + cmCPackPropertiesGenerator cpackPropertiesGenerator( + lg.get(), installedFile, configs); cpackPropertiesGenerator.Generate(file, config, configs); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index f25ff7b77e..b42799275d 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -14,9 +14,10 @@ #include <utility> #include <vector> +#include <cmext/algorithm> + #include "cm_codecvt.hxx" -#include "cmAlgorithms.h" #include "cmCustomCommandLines.h" #include "cmDuration.h" #include "cmExportSet.h" @@ -71,7 +72,7 @@ struct GeneratedMakeCommand void Add(std::vector<std::string>::const_iterator start, std::vector<std::string>::const_iterator end) { - cmAppend(PrimaryCommand, start, end); + cm::append(PrimaryCommand, start, end); } std::string Printable() const { return cmJoin(PrimaryCommand, " "); } @@ -90,11 +91,14 @@ struct GeneratedMakeCommand class cmGlobalGenerator { public: + using LocalGeneratorVector = std::vector<std::unique_ptr<cmLocalGenerator>>; + //! Free any memory allocated with the GlobalGenerator cmGlobalGenerator(cmake* cm); virtual ~cmGlobalGenerator(); - virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf); + virtual std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf); //! Get the name for this generator virtual std::string GetName() const { return "Generic"; } @@ -128,7 +132,8 @@ public: /** Set the generator-specific toolset name. Returns true if toolset is supported and false otherwise. */ - virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); + virtual bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf); /** * Create LocalGenerators and process the CMakeLists files. This does not @@ -157,11 +162,11 @@ public: */ virtual void Generate(); - virtual cmLinkLineComputer* CreateLinkLineComputer( + virtual std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const; - cmLinkLineComputer* CreateMSVC60LinkLineComputer( + std::unique_ptr<cmLinkLineComputer> CreateMSVC60LinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const; @@ -244,11 +249,11 @@ public: cmake* GetCMakeInstance() const { return this->CMakeInstance; } void SetConfiguredFilesPath(cmGlobalGenerator* gen); - const std::vector<cmMakefile*>& GetMakefiles() const + const std::vector<std::unique_ptr<cmMakefile>>& GetMakefiles() const { return this->Makefiles; } - const std::vector<cmLocalGenerator*>& GetLocalGenerators() const + const LocalGeneratorVector& GetLocalGenerators() const { return this->LocalGenerators; } @@ -263,11 +268,11 @@ public: this->CurrentConfigureMakefile = mf; } - void AddMakefile(cmMakefile* mf); + void AddMakefile(std::unique_ptr<cmMakefile> mf); //! Set an generator for an "external makefile based project" void SetExternalMakefileProjectGenerator( - cmExternalMakefileProjectGenerator* extraGenerator); + std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator); std::string GetExtraGeneratorName() const; @@ -440,12 +445,13 @@ public: void ProcessEvaluationFiles(); - std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets() + std::map<std::string, std::unique_ptr<cmExportBuildFileGenerator>>& + GetBuildExportSets() { return this->BuildExportSets; } - void AddBuildExportSet(cmExportBuildFileGenerator*); - void AddBuildExportExportSet(cmExportBuildFileGenerator*); + void AddBuildExportSet(std::unique_ptr<cmExportBuildFileGenerator>); + void AddBuildExportExportSet(std::unique_ptr<cmExportBuildFileGenerator>); bool IsExportedTargetsFile(const std::string& filename) const; bool GenerateImportFile(const std::string& file); cmExportBuildFileGenerator* GetExportedTargetsFile( @@ -475,13 +481,17 @@ public: int RecursionDepth; + virtual void GetQtAutoGenConfigs(std::vector<std::string>& configs) const + { + configs.emplace_back("$<CONFIG>"); + } + protected: - using GeneratorVector = std::vector<cmLocalGenerator*>; // for a project collect all its targets by following depend // information, and also collect all the targets void GetTargetSets(TargetDependSet& projectTargets, TargetDependSet& originalTargets, cmLocalGenerator* root, - GeneratorVector const&); + std::vector<cmLocalGenerator*>& generators); bool IsRootOnlyTarget(cmGeneratorTarget* target) const; void AddTargetDepends(const cmGeneratorTarget* target, TargetDependSet& projectTargets); @@ -524,6 +534,7 @@ protected: std::vector<std::string> Depends; std::string WorkingDir; bool UsesTerminal = false; + bool PerConfig = true; }; void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets); @@ -539,8 +550,8 @@ protected: std::string FindMakeProgramFile; std::string ConfiguredFilesPath; cmake* CMakeInstance; - std::vector<cmMakefile*> Makefiles; - std::vector<cmLocalGenerator*> LocalGenerators; + std::vector<std::unique_ptr<cmMakefile>> Makefiles; + LocalGeneratorVector LocalGenerators; cmMakefile* CurrentConfigureMakefile; // map from project name to vector of local generators in that project std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap; @@ -549,7 +560,8 @@ protected: std::set<std::string> InstallComponents; // Sets of named target exports cmExportSetMap ExportSets; - std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets; + std::map<std::string, std::unique_ptr<cmExportBuildFileGenerator>> + BuildExportSets; std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets; std::map<std::string, std::string> AliasTargets; diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index bb5f74cca3..3709365970 100644 --- a/Source/cmGlobalGeneratorFactory.h +++ b/Source/cmGlobalGeneratorFactory.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include <cm/memory> + class cmGlobalGenerator; class cmake; struct cmDocumentationEntry; @@ -23,8 +25,8 @@ public: virtual ~cmGlobalGeneratorFactory() = default; /** Create a GlobalGenerator */ - virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& n, - cmake* cm) const = 0; + virtual std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& n, cmake* cm) const = 0; /** Get the documentation entry for this factory */ virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0; @@ -51,13 +53,13 @@ class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory { public: /** Create a GlobalGenerator */ - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { if (name != T::GetActualName()) { - return nullptr; + return std::unique_ptr<cmGlobalGenerator>(); } - return new T(cm); + return std::unique_ptr<cmGlobalGenerator>(cm::make_unique<T>(cm)); } /** Get the documentation entry for this factory */ diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 5a708abbcb..bb9dd37343 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -8,6 +8,8 @@ #include <ostream> #include <utility> +#include <cm/memory> + #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" @@ -40,10 +42,11 @@ cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() = default; -cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalGhsMultiGenerator(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalGhsMultiGenerator>(this, mf)); } void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) @@ -64,8 +67,11 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory( } bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, - cmMakefile* mf) + bool build, cmMakefile* mf) { + if (build) { + return true; + } std::string tsp; /* toolset path */ this->GetToolset(mf, tsp, ts); diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index ccfe073820..b82e9f57b9 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -4,6 +4,7 @@ #define cmGhsMultiGenerator_h #include <iosfwd> +#include <memory> #include <set> #include <string> #include <utility> @@ -28,13 +29,15 @@ public: cmGlobalGhsMultiGenerator(cmake* cm); ~cmGlobalGhsMultiGenerator() override; - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>()); } //! create the correct local generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /// @return the name of this generator. static std::string GetActualName() { return "Green Hills MULTI"; } @@ -58,7 +61,8 @@ public: static bool SupportsPlatform() { return true; } // Toolset / Platform Support - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; /** diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index ff54288680..fc3123a44d 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -66,7 +66,7 @@ cmGlobalJOMMakefileGenerator::GenerateBuildCommand( // Since we have full control over the invocation of JOM, let us // make it quiet. jomMakeOptions.push_back(this->MakeSilentFlag); - cmAppend(jomMakeOptions, makeOptions); + cm::append(jomMakeOptions, makeOptions); // JOM does parallel builds by default, the -j is only needed if a specific // number is given diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index fc39ddf427..9f1ec8bd44 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -4,6 +4,7 @@ #define cmGlobalJOMMakefileGenerator_h #include <iosfwd> +#include <memory> #include "cmGlobalUnixMakefileGenerator3.h" @@ -16,9 +17,10 @@ class cmGlobalJOMMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalJOMMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>()); } //! Get the name for the generator. std::string GetName() const override diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h index d6e4847feb..b2de4ff50c 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.h +++ b/Source/cmGlobalMSYSMakefileGenerator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalMSYSMakefileGenerator_h #define cmGlobalMSYSMakefileGenerator_h +#include <memory> + #include "cmGlobalUnixMakefileGenerator3.h" /** \class cmGlobalMSYSMakefileGenerator @@ -14,9 +16,10 @@ class cmGlobalMSYSMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalMSYSMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalMSYSMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalMSYSMakefileGenerator>()); } //! Get the name for the generator. diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h index 15297e3c7a..a9f92a1081 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.h +++ b/Source/cmGlobalMinGWMakefileGenerator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalMinGWMakefileGenerator_h #define cmGlobalMinGWMakefileGenerator_h +#include <memory> + #include "cmGlobalUnixMakefileGenerator3.h" /** \class cmGlobalMinGWMakefileGenerator @@ -14,10 +16,10 @@ class cmGlobalMinGWMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalMinGWMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalMinGWMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalMinGWMakefileGenerator>()); } //! Get the name for the generator. virtual std::string GetName() const diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 2273c00ac6..c4bec2387e 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -66,7 +66,7 @@ cmGlobalNMakeMakefileGenerator::GenerateBuildCommand( // Since we have full control over the invocation of nmake, let us // make it quiet. nmakeMakeOptions.push_back(this->MakeSilentFlag); - cmAppend(nmakeMakeOptions, makeOptions); + cm::append(nmakeMakeOptions, makeOptions); return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( makeProgram, projectName, projectDir, targetNames, config, fast, diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index 4586b77b15..fdf6006c2c 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -4,6 +4,7 @@ #define cmGlobalNMakeMakefileGenerator_h #include <iosfwd> +#include <memory> #include "cmGlobalUnixMakefileGenerator3.h" @@ -16,10 +17,10 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalNMakeMakefileGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalNMakeMakefileGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalNMakeMakefileGenerator>()); } //! Get the name for the generator. std::string GetName() const override diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index da21d6c2a2..ea66e3d79f 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -9,6 +9,8 @@ #include <sstream> #include <cm/memory> +#include <cmext/algorithm> +#include <cmext/memory> #include "cmsys/FStream.hxx" @@ -23,6 +25,7 @@ #include "cmGeneratorExpressionEvaluationFile.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmLinkLineComputer.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" @@ -42,8 +45,6 @@ #include "cmVersion.h" #include "cmake.h" -class cmLinkLineComputer; - const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja"; const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja"; const char* cmGlobalNinjaGenerator::INDENT = " "; @@ -83,13 +84,15 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os, os << "# " << comment.substr(lpos) << "\n\n"; } -cmLinkLineComputer* cmGlobalNinjaGenerator::CreateLinkLineComputer( +std::unique_ptr<cmLinkLineComputer> +cmGlobalNinjaGenerator::CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& /* stateDir */) const { - return new cmNinjaLinkLineComputer( - outputConverter, - this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this); + return std::unique_ptr<cmLinkLineComputer>( + cm::make_unique<cmNinjaLinkLineComputer>( + outputConverter, + this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this)); } std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name) @@ -114,6 +117,11 @@ std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit) std::string result = lit; cmSystemTools::ReplaceString(result, "$", "$$"); cmSystemTools::ReplaceString(result, "\n", "$\n"); + if (this->IsMultiConfig()) { + cmSystemTools::ReplaceString(result, + cmStrCat('$', this->GetCMakeCFGIntDir()), + this->GetCMakeCFGIntDir()); + } return result; } @@ -248,8 +256,8 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( const std::string& command, const std::string& description, const std::string& comment, const std::string& depfile, const std::string& job_pool, bool uses_terminal, bool restat, - const cmNinjaDeps& outputs, const cmNinjaDeps& explicitDeps, - const cmNinjaDeps& orderOnlyDeps) + const cmNinjaDeps& outputs, const std::string& config, + const cmNinjaDeps& explicitDeps, const cmNinjaDeps& orderOnlyDeps) { this->AddCustomCommandRule(); @@ -282,7 +290,11 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( if (!depfile.empty()) { vars["depfile"] = depfile; } - this->WriteBuild(*this->BuildFileStream, build); + if (config.empty()) { + this->WriteBuild(*this->GetCommonFileStream(), build); + } else { + this->WriteBuild(*this->GetConfigFileStream(config), build); + } } if (this->ComputingUnknownDependencies) { @@ -304,14 +316,15 @@ void cmGlobalNinjaGenerator::AddMacOSXContentRule() } void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(std::string input, - std::string output) + std::string output, + const std::string& config) { this->AddMacOSXContentRule(); { cmNinjaBuild build("COPY_OSX_CONTENT"); build.Outputs.push_back(std::move(output)); build.ExplicitDeps.push_back(std::move(input)); - this->WriteBuild(*this->BuildFileStream, build); + this->WriteBuild(*this->GetConfigFileStream(config), build); } } @@ -429,9 +442,11 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) // Virtual public methods. -cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator(cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> cmGlobalNinjaGenerator::CreateLocalGenerator( + cmMakefile* mf) { - return new cmLocalNinjaGenerator(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalNinjaGenerator>(this, mf)); } codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const @@ -470,14 +485,16 @@ void cmGlobalNinjaGenerator::Generate() msg.str()); return; } - if (!this->OpenBuildFileStream()) { + if (!this->OpenBuildFileStreams()) { return; } if (!this->OpenRulesFileStream()) { return; } - this->TargetDependsClosures.clear(); + for (auto& it : this->Configs) { + it.second.TargetDependsClosures.clear(); + } this->InitOutputPathPrefix(); this->TargetAll = this->NinjaOutputPath("all"); @@ -493,19 +510,55 @@ void cmGlobalNinjaGenerator::Generate() this->cmGlobalGenerator::Generate(); this->WriteAssumedSourceDependencies(); - this->WriteTargetAliases(*this->BuildFileStream); - this->WriteFolderTargets(*this->BuildFileStream); - this->WriteUnknownExplicitDependencies(*this->BuildFileStream); - this->WriteBuiltinTargets(*this->BuildFileStream); + this->WriteTargetAliases(*this->GetCommonFileStream()); + this->WriteFolderTargets(*this->GetCommonFileStream()); + this->WriteUnknownExplicitDependencies(*this->GetCommonFileStream()); + this->WriteBuiltinTargets(*this->GetCommonFileStream()); if (cmSystemTools::GetErrorOccuredFlag()) { this->RulesFileStream->setstate(std::ios::failbit); - this->BuildFileStream->setstate(std::ios::failbit); + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + this->GetConfigFileStream(config)->setstate(std::ios::failbit); + } + this->GetCommonFileStream()->setstate(std::ios::failbit); } this->CloseCompileCommandsStream(); this->CloseRulesFileStream(); - this->CloseBuildFileStream(); + this->CloseBuildFileStreams(); + + if (!this->WriteDefaultBuildFile()) { + return; + } + + auto run_ninja_tool = [this](char const* tool) { + std::vector<std::string> command; + command.push_back(this->NinjaCommand); + command.emplace_back("-t"); + command.emplace_back(tool); + std::string error; + if (!cmSystemTools::RunSingleCommand(command, nullptr, &error, nullptr, + nullptr, + cmSystemTools::OUTPUT_NONE)) { + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + "Running\n '" + + cmJoin(command, "' '") + + "'\n" + "failed with:\n " + + error); + cmSystemTools::SetFatalErrorOccured(); + } + }; + + if (this->NinjaSupportsCleanDeadTool) { + run_ninja_tool("cleandead"); + } + if (this->NinjaSupportsUnconditionalRecompactTool) { + run_ninja_tool("recompact"); + } + if (this->NinjaSupportsRestatTool) { + run_ninja_tool("restat"); + } } bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) @@ -569,6 +622,16 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() } } } + this->NinjaSupportsCleanDeadTool = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForCleanDeadTool().c_str()); + this->NinjaSupportsUnconditionalRecompactTool = + !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForUnconditionalRecompactTool().c_str()); + this->NinjaSupportsRestatTool = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForRestatTool().c_str()); } bool cmGlobalNinjaGenerator::CheckLanguages( @@ -609,6 +672,17 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const void cmGlobalNinjaGenerator::EnableLanguage( std::vector<std::string> const& langs, cmMakefile* mf, bool optional) { + if (this->IsMultiConfig()) { + if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { + mf->AddCacheDefinition( + "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", + "Semicolon separated list of supported configuration types, only " + "supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything " + "else will be ignored", + cmStateEnums::STRING); + } + } + this->cmGlobalGenerator::EnableLanguage(langs, mf, optional); for (std::string const& l : langs) { if (l == "NONE") { @@ -650,7 +724,7 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand> cmGlobalNinjaGenerator::GenerateBuildCommand( const std::string& makeProgram, const std::string& /*projectName*/, const std::string& /*projectDir*/, - std::vector<std::string> const& targetNames, const std::string& /*config*/, + std::vector<std::string> const& targetNames, const std::string& config, bool /*fast*/, int jobs, bool verbose, std::vector<std::string> const& makeOptions) { @@ -666,6 +740,9 @@ cmGlobalNinjaGenerator::GenerateBuildCommand( makeCommand.Add("-j", std::to_string(jobs)); } + this->AppendNinjaFileArgument(makeCommand, + config.empty() ? "Debug" : config); + makeCommand.Add(makeOptions.begin(), makeOptions.end()); for (const auto& tname : targetNames) { if (!tname.empty()) { @@ -707,44 +784,53 @@ void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { // Compute full path to object file directory for this target. - std::string dir = - cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/', - gt->LocalGenerator->GetTargetDirectory(gt), '/'); + std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), + '/', gt->LocalGenerator->GetTargetDirectory(gt), + '/', this->GetCMakeCFGIntDir(), '/'); gt->ObjectDirectory = dir; } // Private methods -bool cmGlobalNinjaGenerator::OpenBuildFileStream() +bool cmGlobalNinjaGenerator::OpenBuildFileStreams() { - // Compute Ninja's build file path. - std::string buildFilePath = - cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', - cmGlobalNinjaGenerator::NINJA_BUILD_FILE); + if (!this->OpenFileStream(this->BuildFileStream, + cmGlobalNinjaGenerator::NINJA_BUILD_FILE)) { + return false; + } + + // Write a comment about this file. + *this->BuildFileStream + << "# This file contains all the build statements describing the\n" + << "# compilation DAG.\n\n"; + return true; +} + +bool cmGlobalNinjaGenerator::OpenFileStream( + std::unique_ptr<cmGeneratedFileStream>& stream, const std::string& name) +{ // Get a stream where to generate things. - if (!this->BuildFileStream) { - this->BuildFileStream = cm::make_unique<cmGeneratedFileStream>( - buildFilePath, false, this->GetMakefileEncoding()); - if (!(*this->BuildFileStream)) { + if (!stream) { + // Compute Ninja's build file path. + std::string path = + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', name); + stream = cm::make_unique<cmGeneratedFileStream>( + path, false, this->GetMakefileEncoding()); + if (!(*stream)) { // An error message is generated by the constructor if it cannot // open the file. return false; } - } - - // Write the do not edit header. - this->WriteDisclaimer(*this->BuildFileStream); - // Write a comment about this file. - *this->BuildFileStream - << "# This file contains all the build statements describing the\n" - << "# compilation DAG.\n\n"; + // Write the do not edit header. + this->WriteDisclaimer(*stream); + } return true; } -void cmGlobalNinjaGenerator::CloseBuildFileStream() +void cmGlobalNinjaGenerator::CloseBuildFileStreams() { if (this->BuildFileStream) { this->BuildFileStream.reset(); @@ -755,25 +841,11 @@ void cmGlobalNinjaGenerator::CloseBuildFileStream() bool cmGlobalNinjaGenerator::OpenRulesFileStream() { - // Compute Ninja's build file path. - std::string rulesFilePath = - cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', - cmGlobalNinjaGenerator::NINJA_RULES_FILE); - - // Get a stream where to generate things. - if (!this->RulesFileStream) { - this->RulesFileStream = cm::make_unique<cmGeneratedFileStream>( - rulesFilePath, false, this->GetMakefileEncoding()); - if (!(*this->RulesFileStream)) { - // An error message is generated by the constructor if it cannot - // open the file. - return false; - } + if (!this->OpenFileStream(this->RulesFileStream, + cmGlobalNinjaGenerator::NINJA_RULES_FILE)) { + return false; } - // Write the do not edit header. - this->WriteDisclaimer(*this->RulesFileStream); - // Write comment about this file. /* clang-format off */ *this->RulesFileStream @@ -819,10 +891,10 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath( return f->second; } - cmLocalNinjaGenerator* ng = - static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]); - std::string const& bin_dir = ng->GetState()->GetBinaryDirectory(); - std::string convPath = ng->MaybeConvertToRelativePath(bin_dir, path); + const auto& ng = + cm::static_reference_cast<cmLocalNinjaGenerator>(this->LocalGenerators[0]); + std::string const& bin_dir = ng.GetState()->GetBinaryDirectory(); + std::string convPath = ng.MaybeConvertToRelativePath(bin_dir, path); convPath = this->NinjaOutputPath(convPath); #ifdef _WIN32 std::replace(convPath.begin(), convPath.end(), '/', '\\'); @@ -831,9 +903,10 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath( .first->second; } -void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName) +void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName, + const std::string& config) { - this->AdditionalCleanFiles.emplace(std::move(fileName)); + this->Configs[config].AdditionalCleanFiles.emplace(std::move(fileName)); } void cmGlobalNinjaGenerator::AddCXXCompileCommand( @@ -901,23 +974,22 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies() "Assume dependencies for generated source file.", /*depfile*/ "", /*job_pool*/ "", /*uses_terminal*/ false, - /*restat*/ true, cmNinjaDeps(1, asd.first), + /*restat*/ true, cmNinjaDeps(1, asd.first), "", cmNinjaDeps(), orderOnlyDeps); } } -std::string OrderDependsTargetForTarget(cmGeneratorTarget const* target) +std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget( + cmGeneratorTarget const* target, const std::string& config) { - return "cmake_object_order_depends_target_" + target->GetName(); + return "cmake_object_order_depends_target_" + target->GetName() + "_" + + config; } void cmGlobalNinjaGenerator::AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, - cmNinjaTargetDepends depends) + const std::string& config, cmNinjaTargetDepends depends) { - std::string configName = - target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); - // for frameworks, we want the real name, not smple name // frameworks always appear versioned, and the build.ninja // will always attempt to manage symbolic links instead @@ -929,19 +1001,19 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::MODULE_LIBRARY: { if (depends == DependOnTargetOrdering) { - outputs.push_back(OrderDependsTargetForTarget(target)); + outputs.push_back(OrderDependsTargetForTarget(target, config)); break; } } // FALLTHROUGH case cmStateEnums::EXECUTABLE: { outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath( - configName, cmStateEnums::RuntimeBinaryArtifact, realname))); + config, cmStateEnums::RuntimeBinaryArtifact, realname))); break; } case cmStateEnums::OBJECT_LIBRARY: { if (depends == DependOnTargetOrdering) { - outputs.push_back(OrderDependsTargetForTarget(target)); + outputs.push_back(OrderDependsTargetForTarget(target, config)); break; } } @@ -951,7 +1023,11 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( std::string path = target->GetLocalGenerator()->GetCurrentBinaryDirectory() + std::string("/") + target->GetName(); - outputs.push_back(this->ConvertToNinjaPath(path)); + std::string output = this->ConvertToNinjaPath(path); + if (target->Target->IsPerConfig()) { + output = this->BuildAlias(output, config); + } + outputs.push_back(output); break; } @@ -962,6 +1038,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( void cmGlobalNinjaGenerator::AppendTargetDepends( cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config, const std::string& fileConfig, cmNinjaTargetDepends depends) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { @@ -970,7 +1047,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( std::string d = target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + util.Value; - outputs.push_back(this->ConvertToNinjaPath(d)); + outputs.push_back(this->BuildAlias(this->ConvertToNinjaPath(d), config)); } } else { cmNinjaDeps outs; @@ -979,29 +1056,39 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - this->AppendTargetOutputs(targetDep, outs, depends); + // For some reason, object libraries show up as "utility" dependencies + // even though they're used for linking. Treat them as link dependencies. + if (targetDep.IsUtil() && + targetDep->GetType() != cmStateEnums::OBJECT_LIBRARY) { + this->AppendTargetOutputs(targetDep, outs, fileConfig, depends); + } else { + this->AppendTargetOutputs(targetDep, outs, config, depends); + } } std::sort(outs.begin(), outs.end()); - cmAppend(outputs, outs); + cm::append(outputs, outs); } } void cmGlobalNinjaGenerator::AppendTargetDependsClosure( - cmGeneratorTarget const* target, cmNinjaDeps& outputs) + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config) { cmNinjaOuts outs; - this->AppendTargetDependsClosure(target, outs, true); - cmAppend(outputs, outs); + this->AppendTargetDependsClosure(target, outs, config, true); + cm::append(outputs, outs); } void cmGlobalNinjaGenerator::AppendTargetDependsClosure( - cmGeneratorTarget const* target, cmNinjaOuts& outputs, bool omit_self) + cmGeneratorTarget const* target, cmNinjaOuts& outputs, + const std::string& config, bool omit_self) { // try to locate the target in the cache - auto find = this->TargetDependsClosures.lower_bound(target); + auto find = this->Configs[config].TargetDependsClosures.lower_bound(target); - if (find == this->TargetDependsClosures.end() || find->first != target) { + if (find == this->Configs[config].TargetDependsClosures.end() || + find->first != target) { // We now calculate the closure outputs by inspecting the dependent // targets recursively. // For that we have to distinguish between a local result set that is only @@ -1016,10 +1103,10 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( } // Collect the dependent targets for _this_ target - this->AppendTargetDependsClosure(dep_target, this_outs, false); + this->AppendTargetDependsClosure(dep_target, this_outs, config, false); } - find = this->TargetDependsClosures.emplace_hint(find, target, - std::move(this_outs)); + find = this->Configs[config].TargetDependsClosures.emplace_hint( + find, target, std::move(this_outs)); } // now fill the outputs of the final result from the newly generated cache @@ -1029,29 +1116,48 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( // finally generate the outputs of the target itself, if applicable cmNinjaDeps outs; if (!omit_self) { - this->AppendTargetOutputs(target, outs); + this->AppendTargetOutputs(target, outs, config); } outputs.insert(outs.begin(), outs.end()); } void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias, - cmGeneratorTarget* target) + cmGeneratorTarget* target, + const std::string& config) { - std::string buildAlias = this->NinjaOutputPath(alias); + std::string outputPath = this->NinjaOutputPath(alias); + std::string buildAlias = this->BuildAlias(outputPath, config); cmNinjaDeps outputs; - this->AppendTargetOutputs(target, outputs); - // Mark the target's outputs as ambiguous to ensure that no other target uses - // the output as an alias. + this->AppendTargetOutputs(target, outputs, config); + // Mark the target's outputs as ambiguous to ensure that no other target + // uses the output as an alias. for (std::string const& output : outputs) { - TargetAliases[output] = nullptr; + this->TargetAliases[output].GeneratorTarget = nullptr; + for (const std::string& config2 : + this->Makefiles.front()->GetGeneratorConfigs()) { + this->Configs[config2].TargetAliases[output].GeneratorTarget = nullptr; + } } // Insert the alias into the map. If the alias was already present in the // map and referred to another target, mark it as ambiguous. - std::pair<TargetAliasMap::iterator, bool> newAlias = - TargetAliases.insert(std::make_pair(buildAlias, target)); - if (newAlias.second && newAlias.first->second != target) { - newAlias.first->second = nullptr; + TargetAlias ta; + ta.GeneratorTarget = target; + ta.Config = config; + std::pair<TargetAliasMap::iterator, bool> newAliasGlobal = + this->TargetAliases.insert(std::make_pair(buildAlias, ta)); + if (newAliasGlobal.second && + newAliasGlobal.first->second.GeneratorTarget != target) { + newAliasGlobal.first->second.GeneratorTarget = nullptr; + } + if (config != "all") { + std::pair<TargetAliasMap::iterator, bool> newAliasConfig = + this->Configs[config].TargetAliases.insert( + std::make_pair(outputPath, ta)); + if (newAliasConfig.second && + newAliasConfig.first->second.GeneratorTarget != target) { + newAliasConfig.first->second.GeneratorTarget = nullptr; + } } } @@ -1061,10 +1167,10 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) os << "# Target aliases.\n\n"; cmNinjaBuild build("phony"); - build.Outputs.emplace_back(""); - for (auto const& ta : TargetAliases) { + build.Outputs.emplace_back(); + for (auto const& ta : this->TargetAliases) { // Don't write ambiguous aliases. - if (!ta.second) { + if (!ta.second.GeneratorTarget) { continue; } @@ -1074,14 +1180,43 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) continue; } - // Outputs - build.Outputs[0] = ta.first; - // Explicit depdendencies + build.Outputs.front() = ta.first; build.ExplicitDeps.clear(); - this->AppendTargetOutputs(ta.second, build.ExplicitDeps); - // Write + if (ta.second.Config == "all") { + for (auto const& config : + ta.second.GeneratorTarget->Makefile->GetGeneratorConfigs()) { + this->AppendTargetOutputs(ta.second.GeneratorTarget, + build.ExplicitDeps, config); + } + } else { + this->AppendTargetOutputs(ta.second.GeneratorTarget, build.ExplicitDeps, + ta.second.Config); + } this->WriteBuild(os, build); } + + if (this->IsMultiConfig()) { + for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) { + for (auto const& ta : this->Configs[config].TargetAliases) { + // Don't write ambiguous aliases. + if (!ta.second.GeneratorTarget) { + continue; + } + + // Don't write alias if there is a already a custom command with + // matching output + if (this->HasCustomCommandOutput(ta.first)) { + continue; + } + + build.Outputs.front() = ta.first; + build.ExplicitDeps.clear(); + this->AppendTargetOutputs(ta.second.GeneratorTarget, + build.ExplicitDeps, config); + this->WriteBuild(*this->GetConfigFileStream(config), build); + } + } + } } void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) @@ -1097,24 +1232,58 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); std::string const& currentBinaryDir = it.first; DirectoryTarget const& dt = it.second; + std::vector<std::string> configs; + dt.LG->GetMakefile()->GetConfigurations(configs, true); + if (configs.empty()) { + configs.emplace_back(); + } // Setup target + cmNinjaDeps configDeps; build.Comment = "Folder: " + currentBinaryDir; - build.Outputs.emplace_back( - this->ConvertToNinjaPath(currentBinaryDir + "/all")); - for (DirectoryTarget::Target const& t : dt.Targets) { - if (!t.ExcludeFromAll) { - this->AppendTargetOutputs(t.GT, build.ExplicitDeps); + build.Outputs.emplace_back(); + for (auto const& config : configs) { + build.ExplicitDeps.clear(); + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config); + configDeps.emplace_back(build.Outputs.front()); + for (DirectoryTarget::Target const& t : dt.Targets) { + if (!t.ExcludeFromAll) { + this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config); + } + } + for (DirectoryTarget::Dir const& d : dt.Children) { + if (!d.ExcludeFromAll) { + build.ExplicitDeps.emplace_back(this->BuildAlias( + this->ConvertToNinjaPath(d.Path + "/all"), config)); + } } + // Write target + this->WriteBuild(os, build); } - for (DirectoryTarget::Dir const& d : dt.Children) { - if (!d.ExcludeFromAll) { - build.ExplicitDeps.emplace_back( - this->ConvertToNinjaPath(d.Path + "/all")); + + // Add shortcut target + if (this->IsMultiConfig()) { + for (auto const& config : configs) { + build.ExplicitDeps = { this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config) }; + build.Outputs.front() = + this->ConvertToNinjaPath(currentBinaryDir + "/all"); + this->WriteBuild(*this->GetConfigFileStream(config), build); } } - // Write target - this->WriteBuild(os, build); + + // Add target for all configs + if (this->EnableCrossConfigBuild()) { + build.ExplicitDeps.clear(); + for (auto const& config : configs) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config)); + } + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), "all"); + this->WriteBuild(*this->GetCommonFileStream(), build); + } } } @@ -1148,7 +1317,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) // get the list of files that cmake itself has generated as a // product of configuration. - for (cmLocalGenerator* lg : this->LocalGenerators) { + for (const auto& lg : this->LocalGenerators) { // get the vector of files created by this makefile and convert them // to ninja paths, which are all relative in respect to the build directory for (std::string const& file : lg->GetMakefile()->GetOutputFiles()) { @@ -1247,10 +1416,13 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); os << "# Built-in targets\n\n"; - this->WriteTargetDefault(os); this->WriteTargetRebuildManifest(os); this->WriteTargetClean(os); this->WriteTargetHelp(os); + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + this->WriteTargetDefault(*this->GetConfigFileStream(config)); + } } void cmGlobalNinjaGenerator::WriteTargetDefault(std::ostream& os) @@ -1268,7 +1440,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { return; } - cmLocalGenerator* lg = this->LocalGenerators[0]; + const auto& lg = this->LocalGenerators[0]; { cmNinjaRule rule("RERUN_CMAKE"); @@ -1287,9 +1459,9 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) cmNinjaBuild reBuild("RERUN_CMAKE"); reBuild.Comment = "Re-run CMake if any of its inputs changed."; - reBuild.Outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); + this->AddRebuildManifestOutputs(reBuild.Outputs); - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { for (std::string const& fi : localGen->GetMakefile()->GetListFiles()) { reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi)); } @@ -1376,14 +1548,14 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) std::string cmGlobalNinjaGenerator::CMakeCmd() const { - cmLocalGenerator* lgen = this->LocalGenerators.at(0); + const auto& lgen = this->LocalGenerators.at(0); return lgen->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); } std::string cmGlobalNinjaGenerator::NinjaCmd() const { - cmLocalGenerator* lgen = this->LocalGenerators[0]; + const auto& lgen = this->LocalGenerators[0]; if (lgen != nullptr) { return lgen->ConvertToOutputFormat(this->NinjaCommand, cmOutputConverter::SHELL); @@ -1413,13 +1585,27 @@ bool cmGlobalNinjaGenerator::SupportsMultilineDepfile() const bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { - cmLocalGenerator* lgr = this->LocalGenerators.at(0); + const auto& lgr = this->LocalGenerators.at(0); std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake"; std::string cleanScriptAbs = cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel); + std::vector<std::string> configs; + this->Makefiles[0]->GetConfigurations(configs, true); + if (configs.empty()) { + configs.emplace_back(); + } // Check if there are additional files to clean - if (this->AdditionalCleanFiles.empty()) { + bool empty = true; + for (auto const& config : configs) { + auto const it = this->Configs.find(config); + if (it != this->Configs.end() && + !it->second.AdditionalCleanFiles.empty()) { + empty = false; + break; + } + } + if (empty) { // Remove cmake clean script file if it exists cmSystemTools::RemoveFile(cleanScriptAbs); return false; @@ -1431,14 +1617,23 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) if (!fout) { return false; } - fout << "# Additional clean files\n\n"; - fout << "file(REMOVE_RECURSE\n"; - for (std::string const& acf : this->AdditionalCleanFiles) { - fout << " " - << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf)) - << '\n'; + fout << "# Additional clean files\ncmake_minimum_required(VERSION 3.16)\n"; + for (auto const& config : configs) { + auto const it = this->Configs.find(config); + if (it != this->Configs.end() && + !it->second.AdditionalCleanFiles.empty()) { + fout << "\nif(\"${CONFIG}\" STREQUAL \"\" OR \"${CONFIG}\" STREQUAL \"" + << config << "\")\n"; + fout << " file(REMOVE_RECURSE\n"; + for (std::string const& acf : it->second.AdditionalCleanFiles) { + fout << " " + << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf)) + << '\n'; + } + fout << " )\n"; + fout << "endif()\n"; + } } - fout << ")\n"; } // Register clean script file lgr->GetMakefile()->AddCMakeOutputFile(cleanScriptAbs); @@ -1447,7 +1642,7 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { cmNinjaRule rule("CLEAN_ADDITIONAL"); rule.Command = cmStrCat( - CMakeCmd(), " -P ", + CMakeCmd(), " -DCONFIG=$CONFIG -P ", lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel), cmOutputConverter::SHELL)); rule.Description = "Cleaning additional files..."; @@ -1459,9 +1654,19 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { cmNinjaBuild build("CLEAN_ADDITIONAL"); build.Comment = "Clean additional files."; - build.Outputs.push_back( - this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); - WriteBuild(os, build); + build.Outputs.emplace_back(); + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), config); + build.Variables["CONFIG"] = config; + WriteBuild(os, build); + } + if (this->IsMultiConfig()) { + build.Outputs.front() = + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()); + build.Variables["CONFIG"] = ""; + WriteBuild(os, build); + } } // Return success return true; @@ -1476,22 +1681,94 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) // Write rule { cmNinjaRule rule("CLEAN"); - rule.Command = NinjaCmd() + " -t clean"; + rule.Command = NinjaCmd() + " $FILE_ARG -t clean $TARGETS"; rule.Description = "Cleaning all built files..."; rule.Comment = "Rule for cleaning all built files."; WriteRule(*this->RulesFileStream, rule); } + auto const configs = this->Makefiles.front()->GetGeneratorConfigs(); + // Write build { cmNinjaBuild build("CLEAN"); build.Comment = "Clean all the built files."; - build.Outputs.push_back(this->NinjaOutputPath(this->GetCleanTargetName())); - if (additionalFiles) { - build.ExplicitDeps.push_back( - this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); + build.Outputs.emplace_back(); + + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), config); + if (this->IsMultiConfig()) { + build.Variables["TARGETS"] = + cmStrCat(this->BuildAlias(GetByproductsForCleanTargetName(), config), + " ", GetByproductsForCleanTargetName()); + } + build.ExplicitDeps.clear(); + if (additionalFiles) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), + config)); + } + for (auto const& fileConfig : configs) { + if (fileConfig != config && !this->EnableCrossConfigBuild()) { + continue; + } + if (this->IsMultiConfig()) { + build.Variables["FILE_ARG"] = cmStrCat( + "-f ", cmGlobalNinjaMultiGenerator::GetNinjaFilename(fileConfig)); + } + this->WriteBuild(*this->GetConfigFileStream(fileConfig), build); + } } + + if (this->EnableCrossConfigBuild()) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), "all"); + build.ExplicitDeps.clear(); + + if (additionalFiles) { + build.ExplicitDeps.push_back( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); + } + + build.Variables["TARGETS"] = ""; + + for (auto const& fileConfig : configs) { + build.Variables["FILE_ARG"] = cmStrCat( + "-f ", cmGlobalNinjaMultiGenerator::GetNinjaFilename(fileConfig)); + this->WriteBuild(*this->GetConfigFileStream(fileConfig), build); + } + } + } + + if (this->IsMultiConfig()) { + cmNinjaBuild build("phony"); + build.Outputs.emplace_back( + this->NinjaOutputPath(this->GetCleanTargetName())); + build.ExplicitDeps.emplace_back(); + + for (auto const& config : configs) { + build.ExplicitDeps.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), config); + this->WriteBuild(*this->GetConfigFileStream(config), build); + } + } + + // Write byproducts + if (this->IsMultiConfig()) { + cmNinjaBuild build("phony"); + build.Comment = "Clean byproducts."; + build.Outputs.emplace_back( + this->ConvertToNinjaPath(GetByproductsForCleanTargetName())); + build.ExplicitDeps = this->ByproductsForCleanTarget; WriteBuild(os, build); + + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(GetByproductsForCleanTargetName()), config); + build.ExplicitDeps = this->Configs[config].ByproductsForCleanTarget; + WriteBuild(os, build); + } } } @@ -1809,11 +2086,9 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( snapshot.GetDirectory().SetRelativePathTopSource(dir_top_src.c_str()); snapshot.GetDirectory().SetRelativePathTopBinary(dir_top_bld.c_str()); auto mfd = cm::make_unique<cmMakefile>(this, snapshot); - std::unique_ptr<cmLocalNinjaGenerator> lgd( - static_cast<cmLocalNinjaGenerator*>( - this->CreateLocalGenerator(mfd.get()))); - this->Makefiles.push_back(mfd.release()); - this->LocalGenerators.push_back(lgd.release()); + auto lgd = this->CreateLocalGenerator(mfd.get()); + this->Makefiles.push_back(std::move(mfd)); + this->LocalGenerators.push_back(std::move(lgd)); } std::vector<cmDyndepObjectInfo> objects; @@ -1920,6 +2195,12 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( return true; } +bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const +{ + return this->IsMultiConfig() && + this->Makefiles.front()->IsOn("CMAKE_NINJA_CROSS_CONFIG_ENABLE"); +} + int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, std::vector<std::string>::const_iterator argEnd) { @@ -1990,13 +2271,146 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, cmake cm(cmake::RoleInternal, cmState::Unknown); cm.SetHomeDirectory(dir_top_src); cm.SetHomeOutputDirectory(dir_top_bld); - std::unique_ptr<cmGlobalNinjaGenerator> ggd( - static_cast<cmGlobalNinjaGenerator*>(cm.CreateGlobalGenerator("Ninja"))); + auto ggd = cm.CreateGlobalGenerator("Ninja"); if (!ggd || - !ggd->WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, - arg_dd, arg_ddis, module_dir, linked_target_dirs, - arg_lang)) { + !cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile( + dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis, + module_dir, linked_target_dirs, arg_lang)) { return 1; } return 0; } + +void cmGlobalNinjaGenerator::AppendDirectoryForConfig( + const std::string& prefix, const std::string& config, + const std::string& suffix, std::string& dir) +{ + if (!config.empty() && this->IsMultiConfig()) { + dir += prefix; + dir += config; + dir += suffix; + } +} + +const char* cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE = "common.ninja"; +const char* cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION = ".ninja"; + +cmGlobalNinjaMultiGenerator::cmGlobalNinjaMultiGenerator(cmake* cm) + : cmGlobalNinjaGenerator(cm) +{ + cm->GetState()->SetIsGeneratorMultiConfig(true); + cm->GetState()->SetNinjaMulti(true); +} + +void cmGlobalNinjaMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) +{ + entry.Name = cmGlobalNinjaMultiGenerator::GetActualName(); + entry.Brief = "Generates build-<Config>.ninja files."; +} + +std::string cmGlobalNinjaMultiGenerator::ExpandCFGIntDir( + const std::string& str, const std::string& config) const +{ + std::string result = str; + cmSystemTools::ReplaceString(result, this->GetCMakeCFGIntDir(), config); + return result; +} + +bool cmGlobalNinjaMultiGenerator::OpenBuildFileStreams() +{ + if (!this->OpenFileStream(this->CommonFileStream, + cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE)) { + return false; + } + + // Write a comment about this file. + *this->CommonFileStream + << "# This file contains build statements common to all " + "configurations.\n\n"; + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + if (!this->OpenFileStream(this->ConfigFileStreams[config], + GetNinjaFilename(config))) { + return false; + } + + // Write a comment about this file. + *this->ConfigFileStreams[config] + << "# This file contains build statements specific to the \"" << config + << "\"\n# configuration.\n\n"; + } + + return true; +} + +void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams() +{ + if (this->CommonFileStream) { + this->CommonFileStream.reset(); + } else { + cmSystemTools::Error("Common file stream was not open."); + } + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + if (this->ConfigFileStreams[config]) { + this->ConfigFileStreams[config].reset(); + } else { + cmSystemTools::Error( + cmStrCat("Config file stream for \"", config, "\" was not open.")); + } + } +} + +void cmGlobalNinjaMultiGenerator::AppendNinjaFileArgument( + GeneratedMakeCommand& command, const std::string& config) const +{ + command.Add("-f"); + command.Add(GetNinjaFilename(config)); +} + +std::string cmGlobalNinjaMultiGenerator::GetNinjaFilename( + const std::string& config) +{ + return cmStrCat("build-", config, + cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION); +} + +void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs( + cmNinjaDeps& outputs) const +{ + for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) { + outputs.push_back(this->NinjaOutputPath(GetNinjaFilename(config))); + } + if (this->Makefiles.front()->GetDefinition( + "CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE")) { + outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); + } +} + +void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs( + std::vector<std::string>& configs) const +{ + auto const oldSize = configs.size(); + this->Makefiles.front()->GetConfigurations(configs); + if (configs.size() == oldSize) { + configs.emplace_back(); + } +} + +bool cmGlobalNinjaMultiGenerator::WriteDefaultBuildFile() +{ + auto const* defaultConfig = this->Makefiles.front()->GetDefinition( + "CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE"); + if (defaultConfig) { + std::unique_ptr<cmGeneratedFileStream> defaultStream; + if (!this->OpenFileStream(defaultStream, NINJA_BUILD_FILE)) { + return false; + } + *defaultStream << "# This file is a convenience file generated by\n" + << "# CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.\n\n" + << "include " << this->GetNinjaFilename(defaultConfig) + << "\n"; + } + + return true; +} diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 244e9fd384..3545f1e869 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -22,6 +22,7 @@ #include "cmGlobalGeneratorFactory.h" #include "cmNinjaTypes.h" #include "cmPolicies.h" +#include "cmStringAlgorithms.h" class cmCustomCommand; class cmGeneratorTarget; @@ -73,10 +74,10 @@ public: static void WriteDivider(std::ostream& os); static std::string EncodeRuleName(std::string const& name); - static std::string EncodeLiteral(const std::string& lit); + std::string EncodeLiteral(const std::string& lit); std::string EncodePath(const std::string& path); - cmLinkLineComputer* CreateLinkLineComputer( + std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const override; @@ -111,11 +112,12 @@ public: const std::string& command, const std::string& description, const std::string& comment, const std::string& depfile, const std::string& pool, bool uses_terminal, bool restat, - const cmNinjaDeps& outputs, + const cmNinjaDeps& outputs, const std::string& config, const cmNinjaDeps& explicitDeps = cmNinjaDeps(), const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps()); - void WriteMacOSXContentBuild(std::string input, std::string output); + void WriteMacOSXContentBuild(std::string input, std::string output, + const std::string& config); /** * Write a rule statement to @a os. @@ -151,12 +153,14 @@ public: public: cmGlobalNinjaGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>()); } - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; std::string GetName() const override { @@ -204,7 +208,13 @@ public: } const char* GetCleanTargetName() const override { return "clean"; } - cmGeneratedFileStream* GetBuildFileStream() const + virtual cmGeneratedFileStream* GetConfigFileStream( + const std::string& /*config*/) const + { + return this->BuildFileStream.get(); + } + + virtual cmGeneratedFileStream* GetCommonFileStream() const { return this->BuildFileStream.get(); } @@ -231,12 +241,17 @@ public: MapToNinjaPathImpl MapToNinjaPath() { return { this }; } // -- Additional clean files - void AddAdditionalCleanFile(std::string fileName); + void AddAdditionalCleanFile(std::string fileName, const std::string& config); const char* GetAdditionalCleanTargetName() const { return "CMakeFiles/clean.additional"; } + static const char* GetByproductsForCleanTargetName() + { + return "CMakeFiles/cmake_byproducts_for_clean_target"; + } + void AddCXXCompileCommand(const std::string& commandLine, const std::string& sourceFile); @@ -260,9 +275,9 @@ public: /// Called when we have seen the given custom command. Returns true /// if we has seen it before. - bool SeenCustomCommand(cmCustomCommand const* cc) + bool SeenCustomCommand(cmCustomCommand const* cc, const std::string& config) { - return !this->CustomCommands.insert(cc).second; + return !this->Configs[config].CustomCommands.insert(cc).second; } /// Called when we have seen the given custom command output. @@ -284,25 +299,43 @@ public: ASD.insert(deps.begin(), deps.end()); } + static std::string OrderDependsTargetForTarget( + cmGeneratorTarget const* target, const std::string& config); + void AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDepends( cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config, const std::string& fileConfig, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDependsClosure(cmGeneratorTarget const* target, - cmNinjaDeps& outputs); + cmNinjaDeps& outputs, + const std::string& config); void AppendTargetDependsClosure(cmGeneratorTarget const* target, - cmNinjaOuts& outputs, bool omit_self); + cmNinjaOuts& outputs, + const std::string& config, bool omit_self); + + void AppendDirectoryForConfig(const std::string& prefix, + const std::string& config, + const std::string& suffix, + std::string& dir) override; + + virtual void AppendNinjaFileArgument(GeneratedMakeCommand& /*command*/, + const std::string& /*config*/) const + { + } - const std::vector<cmLocalGenerator*>& GetLocalGenerators() const + virtual void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const { - return LocalGenerators; + outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); } int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; } - void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target); + void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target, + const std::string& config); void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; @@ -316,6 +349,12 @@ public: return "1.9"; } static std::string RequiredNinjaVersionForDyndeps() { return "1.10"; } + static std::string RequiredNinjaVersionForRestatTool() { return "1.10"; } + static std::string RequiredNinjaVersionForUnconditionalRecompactTool() + { + return "1.10"; + } + static std::string RequiredNinjaVersionForCleanDeadTool() { return "1.10"; } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; @@ -335,11 +374,41 @@ public: std::vector<std::string> const& linked_target_dirs, std::string const& arg_lang); + virtual std::string BuildAlias(const std::string& alias, + const std::string& /*config*/) const + { + return alias; + } + + virtual std::string ConfigDirectory(const std::string& /*config*/) const + { + return ""; + } + + cmNinjaDeps& GetByproductsForCleanTarget() + { + return this->ByproductsForCleanTarget; + } + + cmNinjaDeps& GetByproductsForCleanTarget(const std::string& config) + { + return this->Configs[config].ByproductsForCleanTarget; + } + + bool EnableCrossConfigBuild() const; + protected: void Generate() override; bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; } + virtual bool OpenBuildFileStreams(); + virtual void CloseBuildFileStreams(); + virtual bool WriteDefaultBuildFile() { return true; } + + bool OpenFileStream(std::unique_ptr<cmGeneratedFileStream>& stream, + const std::string& name); + private: std::string GetEditCacheCommand() const override; bool FindMakeProgram(cmMakefile* mf) override; @@ -348,9 +417,6 @@ private: cmMakefile* mf) const override; bool CheckFortran(cmMakefile* mf) const; - bool OpenBuildFileStream(); - void CloseBuildFileStream(); - void CloseCompileCommandsStream(); bool OpenRulesFileStream(); @@ -395,9 +461,6 @@ private: bool UsingGCCOnWindows = false; - /// The set of custom commands we have seen. - std::set<cmCustomCommand const*> CustomCommands; - /// The set of custom command outputs we have seen. std::set<std::string> CustomCommandOutputs; @@ -416,11 +479,14 @@ private: /// The mapping from source file to assumed dependencies. std::map<std::string, std::set<std::string>> AssumedSourceDependencies; - using TargetAliasMap = std::map<std::string, cmGeneratorTarget*>; + struct TargetAlias + { + cmGeneratorTarget* GeneratorTarget; + std::string Config; + }; + using TargetAliasMap = std::map<std::string, TargetAlias>; TargetAliasMap TargetAliases; - std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures; - /// the local cache for calls to ConvertToNinjaPath mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache; @@ -431,6 +497,9 @@ private: bool NinjaSupportsManifestRestat = false; bool NinjaSupportsMultilineDepfile = false; bool NinjaSupportsDyndeps = false; + bool NinjaSupportsRestatTool = false; + bool NinjaSupportsUnconditionalRecompactTool = false; + bool NinjaSupportsCleanDeadTool = false; private: void InitOutputPathPrefix(); @@ -438,7 +507,102 @@ private: std::string OutputPathPrefix; std::string TargetAll; std::string CMakeCacheFile; - std::set<std::string> AdditionalCleanFiles; + + struct ByConfig + { + std::set<std::string> AdditionalCleanFiles; + + /// The set of custom commands we have seen. + std::set<cmCustomCommand const*> CustomCommands; + + std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures; + + TargetAliasMap TargetAliases; + + cmNinjaDeps ByproductsForCleanTarget; + }; + std::map<std::string, ByConfig> Configs; + + cmNinjaDeps ByproductsForCleanTarget; +}; + +class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator +{ +public: + /// The default name of Ninja's common file. Typically: common.ninja. + static const char* NINJA_COMMON_FILE; + /// The default file extension to use for per-config Ninja files. + static const char* NINJA_FILE_EXTENSION; + + cmGlobalNinjaMultiGenerator(cmake* cm); + bool IsMultiConfig() const override { return true; } + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() + { + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>()); + } + + static void GetDocumentation(cmDocumentationEntry& entry); + + std::string GetName() const override + { + return cmGlobalNinjaMultiGenerator::GetActualName(); + } + + static std::string GetActualName() { return "Ninja Multi-Config"; } + + std::string BuildAlias(const std::string& alias, + const std::string& config) const override + { + if (config.empty()) { + return alias; + } + return cmStrCat(alias, ":", config); + } + + std::string ConfigDirectory(const std::string& config) const override + { + if (!config.empty()) { + return cmStrCat('/', config); + } + return ""; + } + + const char* GetCMakeCFGIntDir() const override { return "${CONFIGURATION}"; } + + std::string ExpandCFGIntDir(const std::string& str, + const std::string& config) const override; + + cmGeneratedFileStream* GetConfigFileStream( + const std::string& config) const override + { + return this->ConfigFileStreams.at(config).get(); + } + + cmGeneratedFileStream* GetCommonFileStream() const override + { + return this->CommonFileStream.get(); + } + + void AppendNinjaFileArgument(GeneratedMakeCommand& command, + const std::string& config) const override; + + static std::string GetNinjaFilename(const std::string& config); + + void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override; + + void GetQtAutoGenConfigs(std::vector<std::string>& configs) const override; + + bool WriteDefaultBuildFile() override; + +protected: + bool OpenBuildFileStreams() override; + void CloseBuildFileStreams() override; + +private: + std::map<std::string, std::unique_ptr<cmGeneratedFileStream>> + ConfigFileStreams; + std::unique_ptr<cmGeneratedFileStream> CommonFileStream; }; #endif // ! cmGlobalNinjaGenerator_h diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 4c2d69f091..0591758d42 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -8,8 +8,9 @@ #include <utility> #include <cm/memory> +#include <cmext/algorithm> +#include <cmext/memory> -#include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -61,10 +62,11 @@ void cmGlobalUnixMakefileGenerator3::EnableLanguage( } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalUnixMakefileGenerator3::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalUnixMakefileGenerator3(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf)); } void cmGlobalUnixMakefileGenerator3::GetDocumentation( @@ -144,11 +146,11 @@ void cmGlobalUnixMakefileGenerator3::Generate() for (auto& pmi : this->ProgressMap) { pmi.second.WriteProgressVariables(total, current); } - for (cmLocalGenerator* lg : this->LocalGenerators) { + for (const auto& lg : this->LocalGenerators) { std::string markFileName = cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/progress.marks"); cmGeneratedFileStream markFile(markFileName); - markFile << this->CountProgressMarksInAll(lg) << "\n"; + markFile << this->CountProgressMarksInAll(*lg) << "\n"; } // write the main makefile @@ -203,11 +205,11 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() } // get a local generator for some useful methods - cmLocalUnixMakefileGenerator3* lg = - static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]); + auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>( + this->LocalGenerators[0]); // Write the do not edit header. - lg->WriteDisclaimer(makefileStream); + lg.WriteDisclaimer(makefileStream); // Write the main entry point target. This must be the VERY first // target so that make with no arguments will run it. @@ -217,10 +219,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() depends.emplace_back("all"); // Write the rule. - lg->WriteMakeRule(makefileStream, - "Default target executed when no arguments are " - "given to make.", - "default_target", depends, no_commands, true); + lg.WriteMakeRule(makefileStream, + "Default target executed when no arguments are " + "given to make.", + "default_target", depends, no_commands, true); depends.clear(); @@ -231,7 +233,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() } // Write out the "special" stuff - lg->WriteSpecialTargetsTop(makefileStream); + lg.WriteSpecialTargetsTop(makefileStream); // Write the directory level rules. for (auto const& it : this->ComputeDirectoryTargets()) { @@ -239,13 +241,14 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() } // Write the target convenience rules - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { this->WriteConvenienceRules2( - makefileStream, static_cast<cmLocalUnixMakefileGenerator3*>(localGen)); + makefileStream, + cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen)); } // Write special bottom targets - lg->WriteSpecialTargetsBottom(makefileStream); + lg.WriteSpecialTargetsBottom(makefileStream); } void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() @@ -268,12 +271,14 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() std::string makefileName = cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), "/Makefile"); - // get a local generator for some useful methods - cmLocalUnixMakefileGenerator3* lg = - static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]); + { + // get a local generator for some useful methods + auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>( + this->LocalGenerators[0]); - // Write the do not edit header. - lg->WriteDisclaimer(cmakefileStream); + // Write the do not edit header. + lg.WriteDisclaimer(cmakefileStream); + } // Save the generator name cmakefileStream << "# The generator used is:\n" @@ -282,9 +287,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() // for each cmMakefile get its list of dependencies std::vector<std::string> lfiles; - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { // Get the list of files contributing to this generation step. - cmAppend(lfiles, localGen->GetMakefile()->GetListFiles()); + cm::append(lfiles, localGen->GetMakefile()->GetListFiles()); } cmake* cm = this->GetCMakeInstance(); @@ -300,59 +305,61 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() lfiles.erase(new_end, lfiles.end()); #endif - // reset lg to the first makefile - lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]); - - std::string currentBinDir = lg->GetCurrentBinaryDirectory(); - // Save the list to the cmake file. - cmakefileStream - << "# The top level Makefile was generated from the following files:\n" - << "set(CMAKE_MAKEFILE_DEPENDS\n" - << " \"CMakeCache.txt\"\n"; - for (std::string const& f : lfiles) { - cmakefileStream << " \"" - << lg->MaybeConvertToRelativePath(currentBinDir, f) - << "\"\n"; - } - cmakefileStream << " )\n\n"; - - // Build the path to the cache check file. - std::string check = - cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), - "/CMakeFiles/cmake.check_cache"); - - // Set the corresponding makefile in the cmake file. - cmakefileStream << "# The corresponding makefile is:\n" - << "set(CMAKE_MAKEFILE_OUTPUTS\n" - << " \"" - << lg->MaybeConvertToRelativePath(currentBinDir, - makefileName) - << "\"\n" - << " \"" - << lg->MaybeConvertToRelativePath(currentBinDir, check) - << "\"\n"; - cmakefileStream << " )\n\n"; - - const std::string binDir = lg->GetBinaryDirectory(); - - // CMake must rerun if a byproduct is missing. { - cmakefileStream << "# Byproducts of CMake generate step:\n" - << "set(CMAKE_MAKEFILE_PRODUCTS\n"; - for (std::string const& outfile : lg->GetMakefile()->GetOutputFiles()) { + // reset lg to the first makefile + const auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>( + this->LocalGenerators[0]); + + const std::string& currentBinDir = lg.GetCurrentBinaryDirectory(); + // Save the list to the cmake file. + cmakefileStream + << "# The top level Makefile was generated from the following files:\n" + << "set(CMAKE_MAKEFILE_DEPENDS\n" + << " \"CMakeCache.txt\"\n"; + for (std::string const& f : lfiles) { cmakefileStream << " \"" - << lg->MaybeConvertToRelativePath(binDir, outfile) + << lg.MaybeConvertToRelativePath(currentBinDir, f) << "\"\n"; } + cmakefileStream << " )\n\n"; + + // Build the path to the cache check file. + std::string check = + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), + "/CMakeFiles/cmake.check_cache"); + + // Set the corresponding makefile in the cmake file. + cmakefileStream << "# The corresponding makefile is:\n" + << "set(CMAKE_MAKEFILE_OUTPUTS\n" + << " \"" + << lg.MaybeConvertToRelativePath(currentBinDir, + makefileName) + << "\"\n" + << " \"" + << lg.MaybeConvertToRelativePath(currentBinDir, check) + << "\"\n"; + cmakefileStream << " )\n\n"; + + const std::string& binDir = lg.GetBinaryDirectory(); + + // CMake must rerun if a byproduct is missing. + { + cmakefileStream << "# Byproducts of CMake generate step:\n" + << "set(CMAKE_MAKEFILE_PRODUCTS\n"; + for (std::string const& outfile : lg.GetMakefile()->GetOutputFiles()) { + cmakefileStream << " \"" + << lg.MaybeConvertToRelativePath(binDir, outfile) + << "\"\n"; + } + } // add in all the directory information files std::string tmpStr; - for (cmLocalGenerator* localGen : this->LocalGenerators) { - lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen); - tmpStr = cmStrCat(lg->GetCurrentBinaryDirectory(), + for (const auto& localGen : this->LocalGenerators) { + tmpStr = cmStrCat(localGen->GetCurrentBinaryDirectory(), "/CMakeFiles/CMakeDirectoryInformation.cmake"); cmakefileStream << " \"" - << lg->MaybeConvertToRelativePath(binDir, tmpStr) + << localGen->MaybeConvertToRelativePath(binDir, tmpStr) << "\"\n"; } cmakefileStream << " )\n\n"; @@ -364,26 +371,24 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules( cmGeneratedFileStream& cmakefileStream, - std::vector<cmLocalGenerator*>& lGenerators) + std::vector<std::unique_ptr<cmLocalGenerator>>& lGenerators) { - cmLocalUnixMakefileGenerator3* lg; - // now list all the target info files cmakefileStream << "# Dependency information for all targets:\n"; cmakefileStream << "set(CMAKE_DEPEND_INFO_FILES\n"; - for (cmLocalGenerator* lGenerator : lGenerators) { - lg = static_cast<cmLocalUnixMakefileGenerator3*>(lGenerator); + for (const auto& lGenerator : lGenerators) { + const auto& lg = + cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(lGenerator); // for all of out targets - for (cmGeneratorTarget* tgt : lg->GetGeneratorTargets()) { + for (const auto& tgt : lg.GetGeneratorTargets()) { if ((tgt->GetType() == cmStateEnums::EXECUTABLE) || (tgt->GetType() == cmStateEnums::STATIC_LIBRARY) || (tgt->GetType() == cmStateEnums::SHARED_LIBRARY) || (tgt->GetType() == cmStateEnums::MODULE_LIBRARY) || (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) || (tgt->GetType() == cmStateEnums::UTILITY)) { - cmGeneratorTarget* gt = tgt; - std::string tname = - cmStrCat(lg->GetRelativeTargetDirectory(gt), "/DependInfo.cmake"); + std::string tname = cmStrCat(lg.GetRelativeTargetDirectory(tgt.get()), + "/DependInfo.cmake"); cmSystemTools::ConvertToUnixSlashes(tname); cmakefileStream << " \"" << tname << "\"\n"; } @@ -487,7 +492,7 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( std::unique_ptr<cmMakefile> mfu; cmMakefile* mf; if (!this->Makefiles.empty()) { - mf = this->Makefiles[0]; + mf = this->Makefiles[0].get(); } else { cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentSource( @@ -545,11 +550,11 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( } // write the target convenience rules - for (cmLocalGenerator* localGen : this->LocalGenerators) { - cmLocalUnixMakefileGenerator3* lg = - static_cast<cmLocalUnixMakefileGenerator3*>(localGen); + for (const auto& localGen : this->LocalGenerators) { + auto& lg = + cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen); // for each target Generate the rule files for each target. - for (cmGeneratorTarget* gtarget : lg->GetGeneratorTargets()) { + for (const auto& gtarget : lg.GetGeneratorTargets()) { // Don't emit the same rule twice (e.g. two targets with the same // simple name) int type = gtarget->GetType(); @@ -564,23 +569,23 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( (type == cmStateEnums::OBJECT_LIBRARY) || (type == cmStateEnums::UTILITY))) { // Add a rule to build the target by name. - lg->WriteDivider(ruleFileStream); + lg.WriteDivider(ruleFileStream); ruleFileStream << "# Target rules for targets named " << name << "\n\n"; // Write the rule. commands.clear(); std::string tmp = "CMakeFiles/Makefile2"; - commands.push_back(lg->GetRecursiveMakeCall(tmp, name)); + commands.push_back(lg.GetRecursiveMakeCall(tmp, name)); depends.clear(); if (regenerate) { depends.emplace_back("cmake_check_build_system"); } - lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name, - depends, commands, true); + lg.WriteMakeRule(ruleFileStream, "Build rule for target.", name, + depends, commands, true); // Add a fast rule to build the target - std::string localName = lg->GetRelativeTargetDirectory(gtarget); + std::string localName = lg.GetRelativeTargetDirectory(gtarget.get()); std::string makefileName; makefileName = cmStrCat(localName, "/build.make"); depends.clear(); @@ -588,23 +593,23 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( std::string makeTargetName = cmStrCat(localName, "/build"); localName = cmStrCat(name, "/fast"); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); - lg->WriteMakeRule(ruleFileStream, "fast build rule for target.", - localName, depends, commands, true); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.WriteMakeRule(ruleFileStream, "fast build rule for target.", + localName, depends, commands, true); // Add a local name for the rule to relink the target before // installation. - if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) { - makeTargetName = - cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall"); + if (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) { + makeTargetName = cmStrCat( + lg.GetRelativeTargetDirectory(gtarget.get()), "/preinstall"); localName = cmStrCat(name, "/preinstall"); depends.clear(); commands.clear(); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); - lg->WriteMakeRule(ruleFileStream, - "Manual pre-install relink rule for target.", - localName, depends, commands, true); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.WriteMakeRule(ruleFileStream, + "Manual pre-install relink rule for target.", + localName, depends, commands, true); } } } @@ -612,7 +617,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( } void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( - std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg) + std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& lg) { std::vector<std::string> depends; std::vector<std::string> commands; @@ -625,7 +630,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( } // for each target Generate the rule files for each target. - for (cmGeneratorTarget* gtarget : lg->GetGeneratorTargets()) { + for (const auto& gtarget : lg.GetGeneratorTargets()) { int type = gtarget->GetType(); std::string name = gtarget->GetName(); if (!name.empty() && @@ -637,31 +642,31 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( (type == cmStateEnums::UTILITY))) { std::string makefileName; // Add a rule to build the target by name. - localName = lg->GetRelativeTargetDirectory(gtarget); + localName = lg.GetRelativeTargetDirectory(gtarget.get()); makefileName = cmStrCat(localName, "/build.make"); - lg->WriteDivider(ruleFileStream); + lg.WriteDivider(ruleFileStream); ruleFileStream << "# Target rules for target " << localName << "\n\n"; commands.clear(); makeTargetName = cmStrCat(localName, "/depend"); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); makeTargetName = cmStrCat(localName, "/build"); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); // Write the rule. localName += "/all"; depends.clear(); cmLocalUnixMakefileGenerator3::EchoProgress progress; - progress.Dir = cmStrCat(lg->GetBinaryDirectory(), "/CMakeFiles"); + progress.Dir = cmStrCat(lg.GetBinaryDirectory(), "/CMakeFiles"); { std::ostringstream progressArg; const char* sep = ""; - for (unsigned long progFile : this->ProgressMap[gtarget].Marks) { + for (unsigned long progFile : this->ProgressMap[gtarget.get()].Marks) { progressArg << sep << progFile; sep = ","; } @@ -676,13 +681,13 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( } if (targetMessages) { - lg->AppendEcho(commands, "Built target " + name, - cmLocalUnixMakefileGenerator3::EchoNormal, &progress); + lg.AppendEcho(commands, "Built target " + name, + cmLocalUnixMakefileGenerator3::EchoNormal, &progress); } - this->AppendGlobalTargetDepends(depends, gtarget); - lg->WriteMakeRule(ruleFileStream, "All Build rule for target.", - localName, depends, commands, true); + this->AppendGlobalTargetDepends(depends, gtarget.get()); + lg.WriteMakeRule(ruleFileStream, "All Build rule for target.", localName, + depends, commands, true); // Write the rule. commands.clear(); @@ -692,20 +697,21 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # in target - progCmd << lg->ConvertToOutputFormat( + progCmd << lg.ConvertToOutputFormat( cmSystemTools::CollapseFullPath(progress.Dir), cmOutputConverter::SHELL); // std::set<cmGeneratorTarget const*> emitted; - progCmd << " " << this->CountProgressMarksInTarget(gtarget, emitted); + progCmd << " " + << this->CountProgressMarksInTarget(gtarget.get(), emitted); commands.push_back(progCmd.str()); } std::string tmp = "CMakeFiles/Makefile2"; - commands.push_back(lg->GetRecursiveMakeCall(tmp, localName)); + commands.push_back(lg.GetRecursiveMakeCall(tmp, localName)); { std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0 - progCmd << lg->ConvertToOutputFormat( + progCmd << lg.ConvertToOutputFormat( cmSystemTools::CollapseFullPath(progress.Dir), cmOutputConverter::SHELL); progCmd << " 0"; @@ -715,39 +721,39 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( if (regenerate) { depends.emplace_back("cmake_check_build_system"); } - localName = cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/rule"); - lg->WriteMakeRule(ruleFileStream, - "Build rule for subdir invocation for target.", - localName, depends, commands, true); + localName = + cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()), "/rule"); + lg.WriteMakeRule(ruleFileStream, + "Build rule for subdir invocation for target.", + localName, depends, commands, true); // Add a target with the canonical name (no prefix, suffix or path). commands.clear(); depends.clear(); depends.push_back(localName); - lg->WriteMakeRule(ruleFileStream, "Convenience name for target.", name, - depends, commands, true); + lg.WriteMakeRule(ruleFileStream, "Convenience name for target.", name, + depends, commands, true); // Add rules to prepare the target for installation. - if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) { - localName = - cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall"); + if (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) { + localName = cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()), + "/preinstall"); depends.clear(); commands.clear(); - commands.push_back(lg->GetRecursiveMakeCall(makefileName, localName)); - lg->WriteMakeRule(ruleFileStream, - "Pre-install relink rule for target.", localName, - depends, commands, true); + commands.push_back(lg.GetRecursiveMakeCall(makefileName, localName)); + lg.WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.", + localName, depends, commands, true); } // add the clean rule - localName = lg->GetRelativeTargetDirectory(gtarget); + localName = lg.GetRelativeTargetDirectory(gtarget.get()); makeTargetName = cmStrCat(localName, "/clean"); depends.clear(); commands.clear(); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); - lg->WriteMakeRule(ruleFileStream, "clean rule for target.", - makeTargetName, depends, commands, true); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.WriteMakeRule(ruleFileStream, "clean rule for target.", + makeTargetName, depends, commands, true); commands.clear(); } } @@ -759,8 +765,8 @@ void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks() { this->DirectoryTargetsMap.clear(); // Loop over all targets in all local generators. - for (cmLocalGenerator* lg : this->LocalGenerators) { - for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) { + for (const auto& lg : this->LocalGenerators) { + for (const auto& gt : lg->GetGeneratorTargets()) { cmLocalGenerator* tlg = gt->GetLocalGenerator(); if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY || @@ -778,12 +784,13 @@ void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks() // This local generator includes the target. std::set<cmGeneratorTarget const*>& targetSet = this->DirectoryTargetsMap[csnp]; - targetSet.insert(gt); + targetSet.insert(gt.get()); // Add dependencies of the included target. An excluded // target may still be included if it is a dependency of a // non-excluded target. - for (cmTargetDepend const& tgtdep : this->GetTargetDirectDepends(gt)) { + for (cmTargetDepend const& tgtdep : + this->GetTargetDirectDepends(gt.get())) { targetSet.insert(tgtdep); } } @@ -808,12 +815,12 @@ size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInTarget( } size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInAll( - cmLocalGenerator* lg) + const cmLocalGenerator& lg) { size_t count = 0; std::set<cmGeneratorTarget const*> emitted; for (cmGeneratorTarget const* target : - this->DirectoryTargetsMap[lg->GetStateSnapshot()]) { + this->DirectoryTargetsMap[lg.GetStateSnapshot()]) { count += this->CountProgressMarksInTarget(target, emitted); } return count; @@ -887,14 +894,14 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule( std::set<std::string> emittedTargets; // for each local generator - for (cmLocalGenerator* localGen : this->LocalGenerators) { - cmLocalUnixMakefileGenerator3* lg2 = - static_cast<cmLocalUnixMakefileGenerator3*>(localGen); + for (const auto& localGen : this->LocalGenerators) { + const auto& lg2 = + cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen); // for the passed in makefile or if this is the top Makefile wripte out // the targets - if (lg2 == lg || lg->IsRootMakefile()) { + if (&lg2 == lg || lg->IsRootMakefile()) { // for each target Generate the rule files for each target. - for (cmGeneratorTarget* target : lg2->GetGeneratorTargets()) { + for (const auto& target : lg2.GetGeneratorTargets()) { cmStateEnums::TargetType type = target->GetType(); if ((type == cmStateEnums::EXECUTABLE) || (type == cmStateEnums::STATIC_LIBRARY) || diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 79db30ebd6..340a7efa5b 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -8,6 +8,7 @@ #include <cstddef> #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -61,10 +62,10 @@ class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator { public: cmGlobalUnixMakefileGenerator3(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalUnixMakefileGenerator3>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>()); } //! Get the name for the generator. @@ -89,7 +90,8 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /** * Try to determine system information such as shared library @@ -107,8 +109,9 @@ public: */ void Generate() override; - void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream, - std::vector<cmLocalGenerator*>&); + void WriteMainCMakefileLanguageRules( + cmGeneratedFileStream& cmakefileStream, + std::vector<std::unique_ptr<cmLocalGenerator>>&); // write out the help rule listing the valid targets void WriteHelpRule(std::ostream& ruleFileStream, @@ -161,7 +164,7 @@ protected: void WriteMainCMakefile(); void WriteConvenienceRules2(std::ostream& ruleFileStream, - cmLocalUnixMakefileGenerator3*); + cmLocalUnixMakefileGenerator3&); void WriteDirectoryRule2(std::ostream& ruleFileStream, DirectoryTarget const& dt, const char* pass, @@ -227,7 +230,7 @@ protected: size_t CountProgressMarksInTarget( cmGeneratorTarget const* target, std::set<cmGeneratorTarget const*>& emitted); - size_t CountProgressMarksInAll(cmLocalGenerator* lg); + size_t CountProgressMarksInAll(const cmLocalGenerator& lg); cmGeneratedFileStream* CommandDatabase; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 09a49e1e9d..a720cc3e14 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -4,6 +4,8 @@ #include <algorithm> +#include <cm/memory> + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" @@ -26,6 +28,16 @@ static const char vs10generatorName[] = "Visual Studio 10 2010"; static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles; +static void ConvertToWindowsSlashes(std::string& s) +{ + // first convert all of the slashes + for (auto& ch : s) { + if (ch == '/') { + ch = '\\'; + } + } +} + // Map generator name without year to name with year. static const char* cmVS10GenName(const std::string& name, std::string& genName) { @@ -45,27 +57,30 @@ class cmGlobalVisualStudio10Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS10GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudio10Generator(cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio10Generator(cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio10Generator(cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio10Generator(cm, genName, "x64")); } if (strcmp(p, "IA64") == 0) { - return new cmGlobalVisualStudio10Generator(cm, genName, "Itanium"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio10Generator(cm, genName, "Itanium")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -105,9 +120,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio10Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( @@ -193,7 +209,7 @@ static void cmCudaToolVersion(std::string& s) } bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( - std::string const& ts, cmMakefile* mf) + std::string const& ts, bool build, cmMakefile* mf) { if (this->SystemIsWindowsCE && ts.empty() && this->DefaultPlatformToolset.empty()) { @@ -208,7 +224,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( return false; } - if (!this->FindVCTargetsPath(mf)) { + if (build) { + return true; + } + + if (this->CustomVCTargetsPath.empty() && !this->FindVCTargetsPath(mf)) { return false; } @@ -349,6 +369,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir); } + if (const char* vcTargetsDir = this->GetCustomVCTargetsPath()) { + mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR", + vcTargetsDir); + } + return true; } @@ -442,6 +467,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( this->GeneratorToolsetVersion = value; return true; } + if (key == "VCTargetsPath") { + this->CustomVCTargetsPath = value; + ConvertToWindowsSlashes(this->CustomVCTargetsPath); + return true; + } return false; } @@ -550,10 +580,11 @@ std::string cmGlobalVisualStudio10Generator::SelectWindowsCEToolset() const } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalVisualStudio10Generator(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalVisualStudio10Generator>(this, mf)); } void cmGlobalVisualStudio10Generator::Generate() @@ -603,6 +634,14 @@ void cmGlobalVisualStudio10Generator::EnableLanguage( cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); } +const char* cmGlobalVisualStudio10Generator::GetCustomVCTargetsPath() const +{ + if (this->CustomVCTargetsPath.empty()) { + return nullptr; + } + return this->CustomVCTargetsPath.c_str(); +} + const char* cmGlobalVisualStudio10Generator::GetPlatformToolset() const { std::string const& toolset = this->GetPlatformToolsetString(); diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 9adcf08ae2..21207859c5 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalVisualStudio10Generator_h #define cmGlobalVisualStudio10Generator_h +#include <memory> + #include "cmGlobalVisualStudio8Generator.h" #include "cmVisualStudio10ToolsetOptions.h" @@ -14,13 +16,14 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; bool SetSystemName(std::string const& s, cmMakefile* mf) override; bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; std::vector<GeneratedMakeCommand> GenerateBuildCommand( const std::string& makeProgram, const std::string& projectName, @@ -30,7 +33,8 @@ public: std::vector<std::string>()) override; //! create the correct local generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /** * Try to determine system information such as shared library @@ -45,6 +49,9 @@ public: bool IsNsightTegra() const; std::string GetNsightTegraVersion() const; + /** The vctargets path for the target platform. */ + const char* GetCustomVCTargetsPath() const; + /** The toolset name for the target platform. */ const char* GetPlatformToolset() const; std::string const& GetPlatformToolsetString() const; @@ -155,6 +162,7 @@ protected: std::string GeneratorToolset; std::string GeneratorToolsetVersion; std::string GeneratorToolsetHostArchitecture; + std::string GeneratorToolsetCustomVCTargetsDir; std::string GeneratorToolsetCuda; std::string GeneratorToolsetCudaCustomDir; std::string DefaultPlatformToolset; @@ -206,6 +214,7 @@ private: bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + std::string CustomVCTargetsPath; std::string VCTargetsPath; bool FindVCTargetsPath(cmMakefile* mf); diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index 4b74ef1b2d..a385375d64 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio11Generator.h" +#include <utility> + #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio10Generator.h" @@ -28,38 +30,41 @@ class cmGlobalVisualStudio11Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS11GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudio11Generator(cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio11Generator(cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio11Generator(cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio11Generator(cm, genName, "x64")); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio11Generator(cm, genName, "ARM"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio11Generator(cm, genName, "ARM")); } std::set<std::string> installedSDKs = cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs(); if (installedSDKs.find(p) == installedSDKs.end()) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } - cmGlobalVisualStudio11Generator* ret = - new cmGlobalVisualStudio11Generator(cm, name, p); + auto ret = std::unique_ptr<cmGlobalVisualStudio11Generator>( + new cmGlobalVisualStudio11Generator(cm, name, p)); ret->WindowsCEVersion = "8.00"; - return ret; + return std::unique_ptr<cmGlobalGenerator>(std::move(ret)); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -113,9 +118,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio11Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator( diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index f8cce18980..5f1ff737e0 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <set> #include <string> @@ -20,7 +21,7 @@ class cmake; class cmGlobalVisualStudio11Generator : public cmGlobalVisualStudio10Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index d9702c9eed..5a27994872 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -28,27 +28,30 @@ class cmGlobalVisualStudio12Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS12GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudio12Generator(cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio12Generator(cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio12Generator(cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio12Generator(cm, genName, "x64")); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio12Generator(cm, genName, "ARM"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio12Generator(cm, genName, "ARM")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -88,9 +91,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio12Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator( diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 53b709157a..bdd40ff6eb 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include "cmGlobalVisualStudio11Generator.h" @@ -18,7 +19,7 @@ class cmake; class cmGlobalVisualStudio12Generator : public cmGlobalVisualStudio11Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index cd48474272..f549b6aae6 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -2,7 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio14Generator.h" -#include "cmAlgorithms.h" +#include <cm/vector> + #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" @@ -28,27 +29,30 @@ class cmGlobalVisualStudio14Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS14GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudio14Generator(cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio14Generator(cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio14Generator(cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio14Generator(cm, genName, "x64")); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio14Generator(cm, genName, "ARM"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio14Generator(cm, genName, "ARM")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -88,9 +92,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio14Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator( @@ -299,7 +304,7 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() // Skip SDKs that do not contain <um/windows.h> because that indicates that // only the UCRT MSIs were installed for them. - cmEraseIf(sdks, NoWindowsH()); + cm::erase_if(sdks, NoWindowsH()); // Only use the filename, which will be the SDK version. for (std::string& i : sdks) { @@ -309,7 +314,7 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() // Skip SDKs that cannot be used with our toolset. std::string maxVersion = this->GetWindows10SDKMaxVersion(); if (!maxVersion.empty()) { - cmEraseIf(sdks, WindowsSDKTooRecent(maxVersion)); + cm::erase_if(sdks, WindowsSDKTooRecent(maxVersion)); } // Sort the results to make sure we select the most recent one. diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 6e12d3e2c2..ccc29177ef 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include "cmGlobalVisualStudio12Generator.h" @@ -18,7 +19,7 @@ class cmake; class cmGlobalVisualStudio14Generator : public cmGlobalVisualStudio12Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 40b214c032..04ec7b38f3 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -2,8 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio7Generator.h" +#include <utility> #include <vector> +#include <cm/memory> #include <cm/string_view> #include <windows.h> @@ -263,12 +265,11 @@ cmGlobalVisualStudio7Generator::GenerateBuildCommand( } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalVisualStudio7Generator::CreateLocalGenerator(cmMakefile* mf) { - cmLocalVisualStudio7Generator* lg = - new cmLocalVisualStudio7Generator(this, mf); - return lg; + auto lg = cm::make_unique<cmLocalVisualStudio7Generator>(this, mf); + return std::unique_ptr<cmLocalGenerator>(std::move(lg)); } #if !defined(CMAKE_BOOTSTRAP) @@ -300,7 +301,7 @@ void cmGlobalVisualStudio7Generator::Generate() if (!cmSystemTools::GetErrorOccuredFlag() && !this->LocalGenerators.empty()) { this->CallVisualStudioMacro(MacroReload, - GetSLNFile(this->LocalGenerators[0])); + GetSLNFile(this->LocalGenerators[0].get())); } } diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 7a9fcefa24..974bb1d650 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalVisualStudio7Generator_h #define cmGlobalVisualStudio7Generator_h +#include <memory> + #include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudioGenerator.h" @@ -20,7 +22,8 @@ public: ~cmGlobalVisualStudio7Generator(); //! Create a local generator appropriate to this Global Generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; #if !defined(CMAKE_BOOTSTRAP) Json::Value GetJson() const override; diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 8e6125b8a2..ba54f98748 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -2,6 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio8Generator.h" +#include <cm/memory> +#include <cmext/memory> + #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmDocumentationEntry.h" @@ -96,21 +99,22 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() return false; } - std::vector<cmLocalGenerator*> const& generators = this->LocalGenerators; - cmLocalVisualStudio7Generator* lg = - static_cast<cmLocalVisualStudio7Generator*>(generators[0]); - cmMakefile* mf = lg->GetMakefile(); + std::vector<std::unique_ptr<cmLocalGenerator>> const& generators = + this->LocalGenerators; + auto& lg = + cm::static_reference_cast<cmLocalVisualStudio7Generator>(generators[0]); const char* no_working_directory = nullptr; std::vector<std::string> no_byproducts; std::vector<std::string> no_depends; cmCustomCommandLines no_commands; - cmTarget* tgt = mf->AddUtilityCommand( - CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, false, - no_working_directory, no_byproducts, no_depends, no_commands); + cmTarget* tgt = lg.AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false, + no_working_directory, no_byproducts, + no_depends, no_commands); - cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg); - lg->AddGeneratorTarget(gt); + auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, &lg); + auto gt = ptr.get(); + lg.AddGeneratorTarget(std::move(ptr)); // Organize in the "predefined targets" folder: // @@ -128,7 +132,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() stampList); std::string stampFile; cmGeneratedFileStream fout(stampListFile.c_str()); - for (cmLocalGenerator const* gi : generators) { + for (const auto& gi : generators) { stampFile = cmStrCat(gi->GetMakefile()->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp"); fout << stampFile << "\n"; @@ -141,8 +145,8 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // Collect the input files used to generate all targets in this // project. std::vector<std::string> listFiles; - for (cmLocalGenerator* gen : generators) { - cmAppend(listFiles, gen->GetMakefile()->GetListFiles()); + for (const auto& gen : generators) { + cm::append(listFiles, gen->GetMakefile()->GetListFiles()); } // Add a custom prebuild target to run the VerifyGlobs script. @@ -153,7 +157,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() std::vector<std::string> byproducts; byproducts.push_back(cm->GetGlobVerifyStamp()); - mf->AddCustomCommandToTarget( + lg.AddCustomCommandToTarget( CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts, no_depends, verifyCommandLines, cmCustomCommandType::PRE_BUILD, "Checking File Globs", no_working_directory, false); @@ -171,10 +175,10 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() listFiles.erase(new_end, listFiles.end()); // Create a rule to re-run CMake. - std::string argS = cmStrCat("-S", lg->GetSourceDirectory()); - std::string argB = cmStrCat("-B", lg->GetBinaryDirectory()); + std::string argS = cmStrCat("-S", lg.GetSourceDirectory()); + std::string argB = cmStrCat("-B", lg.GetBinaryDirectory()); std::string const sln = - lg->GetBinaryDirectory() + "/" + lg->GetProjectName() + ".sln"; + lg.GetBinaryDirectory() + "/" + lg.GetProjectName() + ".sln"; cmCustomCommandLines commandLines = cmMakeSingleCommandLine( { cmSystemTools::GetCMakeCommand(), argS, argB, "--check-stamp-list", stampList, "--vs-solution-file", sln }); @@ -185,7 +189,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // (this could be avoided with per-target source files) std::string no_main_dependency; cmImplicitDependsList no_implicit_depends; - if (cmSourceFile* file = mf->AddCustomCommandToOutput( + if (cmSourceFile* file = lg.AddCustomCommandToOutput( stamps, no_byproducts, listFiles, no_main_dependency, no_implicit_depends, commandLines, "Checking Build System", no_working_directory, true, false)) { @@ -203,10 +207,9 @@ void cmGlobalVisualStudio8Generator::AddExtraIDETargets() cmGlobalVisualStudio7Generator::AddExtraIDETargets(); if (this->AddCheckTarget()) { for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { - const std::vector<cmGeneratorTarget*>& tgts = - this->LocalGenerators[i]->GetGeneratorTargets(); + const auto& tgts = this->LocalGenerators[i]->GetGeneratorTargets(); // All targets depend on the build-system check target. - for (cmGeneratorTarget const* ti : tgts) { + for (const auto& ti : tgts) { if (ti->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { ti->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET); } diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index 6e61d2681c..9f73c15f0f 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio9Generator.h" +#include <utility> + #include "cmDocumentationEntry.h" #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" @@ -13,43 +15,46 @@ static const char vs9generatorName[] = "Visual Studio 9 2008"; class cmGlobalVisualStudio9Generator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { if (strncmp(name.c_str(), vs9generatorName, sizeof(vs9generatorName) - 1) != 0) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } const char* p = name.c_str() + sizeof(vs9generatorName) - 1; if (p[0] == '\0') { - return new cmGlobalVisualStudio9Generator(cm, name, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio9Generator(cm, name, "")); } if (p[0] != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } ++p; if (!strcmp(p, "IA64")) { - return new cmGlobalVisualStudio9Generator(cm, name, "Itanium"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio9Generator(cm, name, "Itanium")); } if (!strcmp(p, "Win64")) { - return new cmGlobalVisualStudio9Generator(cm, name, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudio9Generator(cm, name, "x64")); } cmVisualStudioWCEPlatformParser parser(p); parser.ParseVersion("9.0"); if (!parser.Found()) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } - cmGlobalVisualStudio9Generator* ret = - new cmGlobalVisualStudio9Generator(cm, name, p); + auto ret = std::unique_ptr<cmGlobalVisualStudio9Generator>( + new cmGlobalVisualStudio9Generator(cm, name, p)); ret->WindowsCEVersion = parser.GetOSVersion(); - return ret; + return std::unique_ptr<cmGlobalGenerator>(std::move(ret)); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -103,9 +108,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudio9Generator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator( diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index 7bebfd65f2..53318a62b1 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalVisualStudio9Generator_h #define cmGlobalVisualStudio9Generator_h +#include <memory> + #include "cmGlobalVisualStudio8Generator.h" /** \class cmGlobalVisualStudio9Generator @@ -13,7 +15,7 @@ class cmGlobalVisualStudio9Generator : public cmGlobalVisualStudio8Generator { public: - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); /** * Where does this version of Visual Studio look for macros for the diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index ed0cba7ddf..be5cfd4a6f 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -7,6 +7,7 @@ #include <iostream> #include <cm/iterator> +#include <cm/memory> #include <windows.h> @@ -196,12 +197,12 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets() if (!gen.empty()) { // Use no actual command lines so that the target itself is not // considered always out of date. - cmTarget* allBuild = gen[0]->GetMakefile()->AddUtilityCommand( - "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_dir, - no_byproducts, no_depends, no_commands, false, "Build all projects"); + cmTarget* allBuild = gen[0]->AddUtilityCommand( + "ALL_BUILD", true, no_working_dir, no_byproducts, no_depends, + no_commands, false, "Build all projects"); - cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]); - gen[0]->AddGeneratorTarget(gt); + gen[0]->AddGeneratorTarget( + cm::make_unique<cmGeneratorTarget>(allBuild, gen[0])); // // Organize in the "predefined targets" folder: @@ -212,12 +213,12 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets() // Now make all targets depend on the ALL_BUILD target for (cmLocalGenerator const* i : gen) { - for (cmGeneratorTarget* tgt : i->GetGeneratorTargets()) { + for (const auto& tgt : i->GetGeneratorTargets()) { if (tgt->GetType() == cmStateEnums::GLOBAL_TARGET || tgt->IsImported()) { continue; } - if (!this->IsExcluded(gen[0], tgt)) { + if (!this->IsExcluded(gen[0], tgt.get())) { allBuild->AddUtility(tgt->GetName()); } } @@ -389,8 +390,8 @@ bool cmGlobalVisualStudioGenerator::ComputeTargetDepends() } for (auto const& it : this->ProjectMap) { for (const cmLocalGenerator* i : it.second) { - for (cmGeneratorTarget* ti : i->GetGeneratorTargets()) { - this->ComputeVSTargetDepends(ti); + for (const auto& ti : i->GetGeneratorTargets()) { + this->ComputeVSTargetDepends(ti.get()); } } } @@ -799,19 +800,9 @@ void RegisterVisualStudioMacros(const std::string& macrosFile, bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( cmGeneratorTarget const* gt) { - // check to see if this is a fortran build - { - // Issue diagnostic if the source files depend on the config. - std::vector<cmSourceFile*> sources; - if (!gt->GetConfigCommonSourceFiles(sources)) { - return false; - } - } - // If there's only one source language, Fortran has to be used // in order for the sources to compile. - std::set<std::string> languages; - gt->GetLanguages(languages, ""); + std::set<std::string> languages = gt->GetAllConfigCompileLanguages(); // Consider an explicit linker language property, but *not* the // computed linker language that may depend on linked targets. // This allows the project to control the language choice in @@ -939,9 +930,10 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( cmCustomCommandLines commandLines = cmMakeSingleCommandLine( { cmakeCommand, "-E", "__create_def", mdi->DefFile, objs_file }); - cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty, - commandLines, "Auto build dll exports", "."); - commands.push_back(command); + cmCustomCommand command(outputs, empty, empty, commandLines, + gt->Target->GetMakefile()->GetBacktrace(), + "Auto build dll exports", "."); + commands.push_back(std::move(command)); } static bool OpenSolution(std::string sln) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index a371633ed0..13ae32a554 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -121,30 +121,33 @@ class cmGlobalVisualStudioVersionedGenerator::Factory15 : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS15GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudioVersionedGenerator( - cmGlobalVisualStudioGenerator::VS15, cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "")); } if (*p++ != ' ') { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudioVersionedGenerator( - cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64")); } if (strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudioVersionedGenerator( - cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM"); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -185,10 +188,10 @@ public: std::string GetDefaultPlatformName() const override { return "Win32"; } }; -cmGlobalGeneratorFactory* +std::unique_ptr<cmGlobalGeneratorFactory> cmGlobalVisualStudioVersionedGenerator::NewFactory15() { - return new Factory15; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory15); } static const char vs16generatorName[] = "Visual Studio 16 2019"; @@ -212,19 +215,20 @@ class cmGlobalVisualStudioVersionedGenerator::Factory16 : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override { std::string genName; const char* p = cmVS16GenName(name, genName); if (!p) { - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } if (!*p) { - return new cmGlobalVisualStudioVersionedGenerator( - cmGlobalVisualStudioGenerator::VS16, cm, genName, ""); + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS16, cm, genName, "")); } - return 0; + return std::unique_ptr<cmGlobalGenerator>(); } void GetDocumentation(cmDocumentationEntry& entry) const override @@ -265,10 +269,10 @@ public: } }; -cmGlobalGeneratorFactory* +std::unique_ptr<cmGlobalGeneratorFactory> cmGlobalVisualStudioVersionedGenerator::NewFactory16() { - return new Factory16; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory16); } cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 466816ba8b..abb609536e 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include "cmGlobalVisualStudio14Generator.h" @@ -19,8 +20,8 @@ class cmGlobalVisualStudioVersionedGenerator : public cmGlobalVisualStudio14Generator { public: - static cmGlobalGeneratorFactory* NewFactory15(); - static cmGlobalGeneratorFactory* NewFactory16(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory15(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory16(); bool MatchesGeneratorName(const std::string& name) const override; diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index 64ace13597..c0daf8a7fe 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include <vector> @@ -25,9 +26,10 @@ class cmGlobalWatcomWMakeGenerator : public cmGlobalUnixMakefileGenerator3 { public: cmGlobalWatcomWMakeGenerator(cmake* cm); - static cmGlobalGeneratorFactory* NewFactory() + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalWatcomWMakeGenerator>(); + return std::unique_ptr<cmGlobalGeneratorFactory>( + new cmGlobalGeneratorSimpleFactory<cmGlobalWatcomWMakeGenerator>()); } //! Get the name for the generator. std::string GetName() const override diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 3002b2a68c..f88728450a 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalXCodeGenerator.h" +#include <algorithm> #include <cassert> #include <cstdio> #include <cstring> @@ -9,6 +10,7 @@ #include <sstream> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/RegularExpression.hxx" @@ -129,8 +131,8 @@ public: class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory { public: - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const override; + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, cmake* cm) const override; void GetDocumentation(cmDocumentationEntry& entry) const override { @@ -179,16 +181,17 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( cm->GetState()->SetIsGeneratorMultiConfig(true); } -cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory() +std::unique_ptr<cmGlobalGeneratorFactory> cmGlobalXCodeGenerator::NewFactory() { - return new Factory; + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); } -cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( - const std::string& name, cmake* cm) const +std::unique_ptr<cmGlobalGenerator> +cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(const std::string& name, + cmake* cm) const { if (name != GetActualName()) { - return nullptr; + return std::unique_ptr<cmGlobalGenerator>(); } #if !defined(CMAKE_BOOTSTRAP) cmXcodeVersionParser parser; @@ -224,16 +227,17 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( if (version_number < 50) { cm->IssueMessage(MessageType::FATAL_ERROR, "Xcode " + version_string + " not supported."); - return nullptr; + return std::unique_ptr<cmGlobalGenerator>(); } - auto gg = cm::make_unique<cmGlobalXCodeGenerator>(cm, version_string, - version_number); - return gg.release(); + return std::unique_ptr<cmGlobalGenerator>( + cm::make_unique<cmGlobalXCodeGenerator>(cm, version_string, + version_number)); #else std::cerr << "CMake should be built with cmake to use Xcode, " "default to Xcode 1.5\n"; - return new cmGlobalXCodeGenerator(cm); + return std::unique_ptr<cmGlobalGenerator>( + cm::make_unique<cmGlobalXCodeGenerator>(cm)); #endif } @@ -267,7 +271,7 @@ std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand() } bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, - cmMakefile* mf) + bool build, cmMakefile* mf) { if (ts.find_first_of(",=") != std::string::npos) { std::ostringstream e; @@ -283,6 +287,9 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, return false; } this->GeneratorToolset = ts; + if (build) { + return true; + } if (!this->GeneratorToolset.empty()) { mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset); } @@ -388,9 +395,11 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> cmGlobalXCodeGenerator::CreateLocalGenerator( + cmMakefile* mf) { - return new cmLocalXCodeGenerator(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalXCodeGenerator>(this, mf)); } void cmGlobalXCodeGenerator::AddExtraIDETargets() @@ -409,10 +418,10 @@ void cmGlobalXCodeGenerator::ComputeTargetOrder() { size_t index = 0; auto const& lgens = this->GetLocalGenerators(); - for (cmLocalGenerator* lgen : lgens) { - auto const& targets = lgen->GetGeneratorTargets(); - for (cmGeneratorTarget const* gt : targets) { - this->ComputeTargetOrder(gt, index); + for (auto const& lgen : lgens) { + const auto& targets = lgen->GetGeneratorTargets(); + for (const auto& gt : targets) { + this->ComputeTargetOrder(gt.get(), index); } } assert(index == this->TargetOrderIndex.size()); @@ -496,20 +505,16 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget( void cmGlobalXCodeGenerator::AddExtraTargets( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens) { - cmMakefile* mf = root->GetMakefile(); - const char* no_working_directory = nullptr; std::vector<std::string> no_byproducts; std::vector<std::string> no_depends; // Add ALL_BUILD - cmTarget* allbuild = mf->AddUtilityCommand( - "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_directory, - no_byproducts, no_depends, + cmTarget* allbuild = root->AddUtilityCommand( + "ALL_BUILD", true, no_working_directory, no_byproducts, no_depends, cmMakeSingleCommandLine({ "echo", "Build all projects" })); - cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root); - root->AddGeneratorTarget(allBuildGt); + root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(allbuild, root)); // Add XCODE depend helper std::string dir = root->GetCurrentBinaryDirectory(); @@ -520,7 +525,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // Add ZERO_CHECK bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); bool generateTopLevelProjectOnly = - mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); + root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); bool isTopLevel = !root->GetStateSnapshot().GetBuildsystemDirectoryParent().IsValid(); if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) { @@ -528,19 +533,18 @@ void cmGlobalXCodeGenerator::AddExtraTargets( std::string file = this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile); cmSystemTools::ReplaceString(file, "\\ ", " "); - cmTarget* check = mf->AddUtilityCommand( - CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, true, - no_working_directory, no_byproducts, no_depends, - cmMakeSingleCommandLine({ "make", "-f", file })); + cmTarget* check = + root->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, + no_working_directory, no_byproducts, no_depends, + cmMakeSingleCommandLine({ "make", "-f", file })); - cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root); - root->AddGeneratorTarget(checkGt); + root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(check, root)); } // now make the allbuild depend on all the non-utility targets // in the project for (auto& gen : gens) { - for (auto target : gen->GetGeneratorTargets()) { + for (const auto& target : gen->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { continue; } @@ -557,14 +561,14 @@ void cmGlobalXCodeGenerator::AddExtraTargets( if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { commandLines.front().back() = // fill placeholder this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)"); - gen->GetMakefile()->AddCustomCommandToTarget( + gen->AddCustomCommandToTarget( target->GetName(), no_byproducts, no_depends, commandLines, cmCustomCommandType::POST_BUILD, "Depend check for xcode", dir.c_str(), true, false, "", "", false, cmObjectLibraryCommands::Accept); } - if (!this->IsExcluded(gens[0], target)) { + if (!this->IsExcluded(gens[0], target.get())) { allbuild->AddUtility(target->GetName()); } } @@ -576,7 +580,7 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( { std::vector<std::string> lfiles; for (auto gen : gens) { - cmAppend(lfiles, gen->GetMakefile()->GetListFiles()); + cm::append(lfiles, gen->GetMakefile()->GetListFiles()); } // sort the array @@ -1093,8 +1097,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets) { this->SetCurrentLocalGenerator(gen); - std::vector<cmGeneratorTarget*> gts = - this->CurrentLocalGenerator->GetGeneratorTargets(); + std::vector<cmGeneratorTarget*> gts; + cm::append(gts, this->CurrentLocalGenerator->GetGeneratorTargets()); std::sort(gts.begin(), gts.end(), [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { return this->TargetOrderIndex[l] < this->TargetOrderIndex[r]; @@ -1364,11 +1368,11 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( void cmGlobalXCodeGenerator::ForceLinkerLanguages() { - for (auto localGenerator : this->LocalGenerators) { + for (const auto& localGenerator : this->LocalGenerators) { // All targets depend on the build-system check target. - for (auto tgt : localGenerator->GetGeneratorTargets()) { + for (const auto& tgt : localGenerator->GetGeneratorTargets()) { // This makes sure all targets link using the proper language. - this->ForceLinkerLanguage(tgt); + this->ForceLinkerLanguage(tgt.get()); } } } @@ -1460,12 +1464,12 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( { cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library", str_file, str_so_file, str_link_file }); - cmCustomCommand command(this->CurrentMakefile, std::vector<std::string>(), - std::vector<std::string>(), - std::vector<std::string>(), cmd, - "Creating symlinks", ""); + cmCustomCommand command( + std::vector<std::string>(), std::vector<std::string>(), + std::vector<std::string>(), cmd, this->CurrentMakefile->GetBacktrace(), + "Creating symlinks", ""); - postbuild.push_back(command); + postbuild.push_back(std::move(command)); } std::vector<cmSourceFile*> classes; @@ -2353,9 +2357,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("SECTORDER_FLAGS", this->CreateString("")); buildSettings->AddAttribute("USE_HEADERMAP", this->CreateString("NO")); cmXCodeObject* group = this->CreateObject(cmXCodeObject::OBJECT_LIST); - group->AddObject(this->CreateString("-Wmost")); - group->AddObject(this->CreateString("-Wno-four-char-constants")); - group->AddObject(this->CreateString("-Wno-unknown-pragmas")); group->AddObject(this->CreateString("$(inherited)")); buildSettings->AddAttribute("WARNING_CFLAGS", group); @@ -2834,7 +2835,7 @@ bool cmGlobalXCodeGenerator::CreateGroups( for (auto& generator : generators) { cmMakefile* mf = generator->GetMakefile(); std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups(); - for (auto gtgt : generator->GetGeneratorTargets()) { + for (const auto& gtgt : generator->GetGeneratorTargets()) { // Same skipping logic here as in CreateXCodeTargets so that we do not // end up with (empty anyhow) ZERO_CHECK, install, or test source // groups: @@ -2849,11 +2850,12 @@ bool cmGlobalXCodeGenerator::CreateGroups( continue; } - auto addSourceToGroup = [this, mf, gtgt, + auto addSourceToGroup = [this, mf, >gt, &sourceGroups](std::string const& source) { cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups); - cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); - std::string key = GetGroupMapKeyFromPath(gtgt, source); + cmXCodeObject* pbxgroup = + this->CreateOrGetPBXGroup(gtgt.get(), sourceGroup); + std::string key = GetGroupMapKeyFromPath(gtgt.get(), source); this->GroupMap[key] = pbxgroup; }; @@ -2879,7 +2881,7 @@ bool cmGlobalXCodeGenerator::CreateGroups( // Add the Info.plist we are about to generate for an App Bundle. if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) { - std::string plist = this->ComputeInfoPListLocation(gtgt); + std::string plist = this->ComputeInfoPListLocation(gtgt.get()); cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource( plist, true, cmSourceFileLocationKind::Known); addSourceToGroup(sf->ResolveFullPath()); @@ -3415,7 +3417,7 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || obj->GetTarget()->GetPropertyAsBool("XCODE_GENERATE_SCHEME"))) { const std::string& targetName = obj->GetTarget()->GetName(); - cmXCodeScheme schm(obj, testables[targetName], + cmXCodeScheme schm(root, obj, testables[targetName], this->CurrentConfigurationTypes, this->XcodeVersion); schm.WriteXCodeSharedScheme(xcProjDir, diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index af905d00c4..df68f803e4 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -7,6 +7,7 @@ #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -34,7 +35,7 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator public: cmGlobalXCodeGenerator(cmake* cm, std::string const& version_string, unsigned int version_number); - static cmGlobalGeneratorFactory* NewFactory(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); //! Get the name for the generator. std::string GetName() const override @@ -47,7 +48,8 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); //! Create a local generator appropriate to this Global Generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /** * Try to determine system information such as shared library @@ -103,7 +105,8 @@ public: bool ShouldStripResourcePath(cmMakefile*) const override; - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; void AppendFlag(std::string& flags, std::string const& flag) const; protected: diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index e0d545d86d..f48789a878 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -2,174 +2,190 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGraphVizWriter.h" -#include <cstddef> +#include <cctype> #include <iostream> #include <memory> -#include <sstream> +#include <set> #include <utility> +#include <cm/memory> + #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include "cmTarget.h" #include "cmake.h" namespace { -enum LinkLibraryScopeType -{ - LLT_SCOPE_PUBLIC, - LLT_SCOPE_PRIVATE, - LLT_SCOPE_INTERFACE -}; -const char* const GRAPHVIZ_PRIVATE_EDEGE_STYLE = "dashed"; -const char* const GRAPHVIZ_INTERFACE_EDEGE_STYLE = "dotted"; +char const* const GRAPHVIZ_EDGE_STYLE_PUBLIC = "solid"; +char const* const GRAPHVIZ_EDGE_STYLE_INTERFACE = "dashed"; +char const* const GRAPHVIZ_EDGE_STYLE_PRIVATE = "dotted"; -std::string getLinkLibraryStyle(const LinkLibraryScopeType& type) -{ - std::string style; - switch (type) { - case LLT_SCOPE_PRIVATE: - style = "[style = " + std::string(GRAPHVIZ_PRIVATE_EDEGE_STYLE) + "]"; - break; - case LLT_SCOPE_INTERFACE: - style = "[style = " + std::string(GRAPHVIZ_INTERFACE_EDEGE_STYLE) + "]"; - break; - default: - break; - } - return style; -} +char const* const GRAPHVIZ_NODE_SHAPE_EXECUTABLE = "egg"; // egg-xecutable + +// Normal libraries. +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC = "octagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED = "doubleoctagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE = "tripleoctagon"; -const char* getShapeForTarget(const cmGeneratorTarget* target) +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE = "pentagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT = "hexagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN = "septagon"; + +char const* const GRAPHVIZ_NODE_SHAPE_UTILITY = "box"; + +const char* getShapeForTarget(const cmLinkItem& item) { - if (!target) { - return "ellipse"; + if (item.Target == nullptr) { + return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN; } - switch (target->GetType()) { + switch (item.Target->GetType()) { case cmStateEnums::EXECUTABLE: - return "house"; + return GRAPHVIZ_NODE_SHAPE_EXECUTABLE; case cmStateEnums::STATIC_LIBRARY: - return "diamond"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC; case cmStateEnums::SHARED_LIBRARY: - return "polygon"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED; case cmStateEnums::MODULE_LIBRARY: - return "octagon"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE; + case cmStateEnums::OBJECT_LIBRARY: + return GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT; + case cmStateEnums::UTILITY: + return GRAPHVIZ_NODE_SHAPE_UTILITY; + case cmStateEnums::INTERFACE_LIBRARY: + return GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE; + case cmStateEnums::UNKNOWN_LIBRARY: default: - break; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN; } +} +} - return "box"; +cmGraphVizWriter::cmGraphVizWriter(std::string const& fileName, + const cmGlobalGenerator* globalGenerator) + : FileName(fileName) + , GlobalFileStream(fileName) + , GraphName(globalGenerator->GetSafeGlobalSetting("CMAKE_PROJECT_NAME")) + , GraphHeader("node [\n fontsize = \"12\"\n];") + , GraphNodePrefix("node") + , GlobalGenerator(globalGenerator) + , NextNodeId(0) + , GenerateForExecutables(true) + , GenerateForStaticLibs(true) + , GenerateForSharedLibs(true) + , GenerateForModuleLibs(true) + , GenerateForInterfaceLibs(true) + , GenerateForObjectLibs(true) + , GenerateForUnknownLibs(true) + , GenerateForCustomTargets(false) + , GenerateForExternals(true) + , GeneratePerTarget(true) + , GenerateDependers(true) +{ } -std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget( - cmTarget* Target, const cmGlobalGenerator* globalGenerator) +cmGraphVizWriter::~cmGraphVizWriter() { - char sep = ';'; - std::map<std::string, LinkLibraryScopeType> tokens; - size_t start = 0; - size_t end = 0; + this->WriteFooter(this->GlobalFileStream); - const char* pInterfaceLinkLibraries = - Target->GetProperty("INTERFACE_LINK_LIBRARIES"); - const char* pLinkLibraries = Target->GetProperty("LINK_LIBRARIES"); + for (auto& fileStream : this->PerTargetFileStreams) { + this->WriteFooter(*fileStream.second); + } - if (!pInterfaceLinkLibraries && !pLinkLibraries) { - return tokens; // target is not linked against any other libraries + for (auto& fileStream : this->TargetDependersFileStreams) { + this->WriteFooter(*fileStream.second); } +} - // make sure we don't touch a null-ptr - auto interfaceLinkLibraries = - std::string(pInterfaceLinkLibraries ? pInterfaceLinkLibraries : ""); - auto linkLibraries = std::string(pLinkLibraries ? pLinkLibraries : ""); +void cmGraphVizWriter::VisitGraph(std::string const&) +{ + this->WriteHeader(GlobalFileStream, this->GraphName); + this->WriteLegend(GlobalFileStream); +} - // first extract interfaceLinkLibraries - while (start < interfaceLinkLibraries.length()) { +void cmGraphVizWriter::OnItem(cmLinkItem const& item) +{ + if (this->ItemExcluded(item)) { + return; + } - if ((end = interfaceLinkLibraries.find(sep, start)) == std::string::npos) { - end = interfaceLinkLibraries.length(); - } + NodeNames[item.AsStr()] = cmStrCat(GraphNodePrefix, NextNodeId); + ++NextNodeId; - std::string element = interfaceLinkLibraries.substr(start, end - start); - if (globalGenerator->IsAlias(element)) { - const auto tgt = globalGenerator->FindTarget(element); - if (tgt) { - element = tgt->GetName(); - } - } + this->WriteNode(this->GlobalFileStream, item); - if (std::string::npos == element.find("$<LINK_ONLY:", 0)) { - // we assume first, that this library is an interface library. - // if we find it again in the linklibraries property, we promote it to an - // public library. - tokens[element] = LLT_SCOPE_INTERFACE; - } else { - // this is an private linked static library. - // we take care of this case in the second iterator. - } - start = end + 1; + if (this->GeneratePerTarget) { + this->CreateTargetFile(this->PerTargetFileStreams, item); } - // second extract linkLibraries - start = 0; - while (start < linkLibraries.length()) { - - if ((end = linkLibraries.find(sep, start)) == std::string::npos) { - end = linkLibraries.length(); - } + if (this->GenerateDependers) { + this->CreateTargetFile(this->TargetDependersFileStreams, item, + ".dependers"); + } +} - std::string element = linkLibraries.substr(start, end - start); - if (globalGenerator->IsAlias(element)) { - const auto tgt = globalGenerator->FindTarget(element); - if (tgt) { - element = tgt->GetName(); - } - } +void cmGraphVizWriter::CreateTargetFile(FileStreamMap& fileStreamMap, + cmLinkItem const& item, + std::string const& fileNameSuffix) +{ + auto const pathSafeItemName = PathSafeString(item.AsStr()); + auto const perTargetFileName = + cmStrCat(this->FileName, '.', pathSafeItemName, fileNameSuffix); + auto perTargetFileStream = + cm::make_unique<cmGeneratedFileStream>(perTargetFileName); - if (tokens.find(element) == tokens.end()) { - // this library is not found in interfaceLinkLibraries but in - // linkLibraries. - // this results in a private linked library. - tokens[element] = LLT_SCOPE_PRIVATE; - } else if (LLT_SCOPE_INTERFACE == tokens[element]) { - // this library is found in interfaceLinkLibraries and linkLibraries. - // this results in a public linked library. - tokens[element] = LLT_SCOPE_PUBLIC; - } else { - // private and public linked libraries should not be changed anymore. - } + this->WriteHeader(*perTargetFileStream, item.AsStr()); + this->WriteNode(*perTargetFileStream, item); - start = end + 1; - } + fileStreamMap.emplace(item.AsStr(), std::move(perTargetFileStream)); +} - return tokens; +void cmGraphVizWriter::OnDirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee, + DependencyType dt) +{ + this->VisitLink(depender, dependee, true, GetEdgeStyle(dt)); } + +void cmGraphVizWriter::OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) +{ + this->VisitLink(depender, dependee, false); } -cmGraphVizWriter::cmGraphVizWriter(const cmGlobalGenerator* globalGenerator) - : GraphType("digraph") - , GraphName("GG") - , GraphHeader("node [\n fontsize = \"12\"\n];") - , GraphNodePrefix("node") - , GlobalGenerator(globalGenerator) - , LocalGenerators(globalGenerator->GetLocalGenerators()) - , GenerateForExecutables(true) - , GenerateForStaticLibs(true) - , GenerateForSharedLibs(true) - , GenerateForModuleLibs(true) - , GenerateForInterface(true) - , GenerateForExternals(true) - , GeneratePerTarget(true) - , GenerateDependers(true) - , HaveTargetsAndLibs(false) +void cmGraphVizWriter::VisitLink(cmLinkItem const& depender, + cmLinkItem const& dependee, bool isDirectLink, + std::string const& scopeType) { + if (this->ItemExcluded(depender) || this->ItemExcluded(dependee)) { + return; + } + + if (!isDirectLink) { + return; + } + + this->WriteConnection(this->GlobalFileStream, depender, dependee, scopeType); + + if (this->GeneratePerTarget) { + auto fileStream = PerTargetFileStreams[depender.AsStr()].get(); + this->WriteNode(*fileStream, dependee); + this->WriteConnection(*fileStream, depender, dependee, scopeType); + } + + if (this->GenerateDependers) { + auto fileStream = TargetDependersFileStreams[dependee.AsStr()].get(); + this->WriteNode(*fileStream, depender); + this->WriteConnection(*fileStream, depender, dependee, scopeType); + } } void cmGraphVizWriter::ReadSettings( @@ -208,7 +224,6 @@ void cmGraphVizWriter::ReadSettings( } \ } while (false) - __set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE"); __set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME"); __set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER"); __set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX"); @@ -225,7 +240,10 @@ void cmGraphVizWriter::ReadSettings( __set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS"); __set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS"); __set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS"); - __set_bool_if_set(this->GenerateForInterface, "GRAPHVIZ_INTERFACE"); + __set_bool_if_set(this->GenerateForInterfaceLibs, "GRAPHVIZ_INTERFACE_LIBS"); + __set_bool_if_set(this->GenerateForObjectLibs, "GRAPHVIZ_OBJECT_LIBS"); + __set_bool_if_set(this->GenerateForUnknownLibs, "GRAPHVIZ_UNKNOWN_LIBS"); + __set_bool_if_set(this->GenerateForCustomTargets, "GRAPHVIZ_CUSTOM_TARGETS"); __set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS"); __set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET"); __set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS"); @@ -248,329 +266,170 @@ void cmGraphVizWriter::ReadSettings( } } -// Iterate over all targets and write for each one a graph which shows -// which other targets depend on it. -void cmGraphVizWriter::WriteTargetDependersFiles(const std::string& fileName) +void cmGraphVizWriter::Write() { - if (!this->GenerateDependers) { - return; - } - - this->CollectTargetsAndLibs(); - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - std::string currentFilename = - cmStrCat(fileName, '.', ptr.first, ".dependers"); - - cmGeneratedFileStream str(currentFilename); - if (!str) { - return; + auto gg = this->GlobalGenerator; + + this->VisitGraph(gg->GetName()); + + // We want to traverse in a determined order, such that the output is always + // the same for a given project (this makes tests reproducible, etc.) + std::set<cmGeneratorTarget const*, cmGeneratorTarget::StrictTargetComparison> + sortedGeneratorTargets; + + for (const auto& lg : gg->GetLocalGenerators()) { + for (const auto& gt : lg->GetGeneratorTargets()) { + // Reserved targets have inconsistent names across platforms (e.g. 'all' + // vs. 'ALL_BUILD'), which can disrupt the traversal ordering. + // We don't need or want them anyway. + if (!cmGlobalGenerator::IsReservedTarget(gt->GetName())) { + sortedGeneratorTargets.insert(gt.get()); + } } - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - std::cout << "Writing " << currentFilename << "..." << std::endl; - this->WriteHeader(str); - - this->WriteDependerConnections(ptr.first, insertedNodes, - insertedConnections, str); - - this->WriteFooter(str); - } -} - -// Iterate over all targets and write for each one a graph which shows -// on which targets it depends. -void cmGraphVizWriter::WritePerTargetFiles(const std::string& fileName) -{ - if (!this->GeneratePerTarget) { - return; } - this->CollectTargetsAndLibs(); - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - std::string currentFilename = cmStrCat(fileName, '.', ptr.first); - cmGeneratedFileStream str(currentFilename); - if (!str) { - return; - } - - std::cout << "Writing " << currentFilename << "..." << std::endl; - this->WriteHeader(str); - - this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str); - this->WriteFooter(str); + for (auto const gt : sortedGeneratorTargets) { + auto item = cmLinkItem(gt, gt->GetBacktrace()); + this->VisitItem(item); } } -void cmGraphVizWriter::WriteGlobalFile(const std::string& fileName) +void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& fs, + const std::string& name) { - this->CollectTargetsAndLibs(); - - cmGeneratedFileStream str(fileName); - if (!str) { - return; - } - this->WriteHeader(str); - - std::cout << "Writing " << fileName << "..." << std::endl; - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str); - } - this->WriteFooter(str); + auto const escapedGraphName = EscapeForDotFile(name); + fs << "digraph \"" << escapedGraphName << "\" {" << std::endl; + fs << this->GraphHeader << std::endl; } -void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& fs) { - str << this->GraphType << " \"" << this->GraphName << "\" {" << std::endl; - str << this->GraphHeader << std::endl; + fs << "}" << std::endl; } -void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteLegend(cmGeneratedFileStream& fs) { - str << "}" << std::endl; + // Note that the subgraph name must start with "cluster", as done here, to + // make Graphviz layout engines do the right thing and keep the nodes + // together. + fs << "subgraph clusterLegend {" << std::endl; + fs << " label = \"Legend\";" << std::endl; + // Set the color of the box surrounding the legend. + fs << " color = black;" << std::endl; + // We use invisible edges just to enforce the layout. + fs << " edge [ style = invis ];" << std::endl; + + // Nodes. + fs << " legendNode0 [ label = \"Executable\", shape = " + << GRAPHVIZ_NODE_SHAPE_EXECUTABLE << " ];" << std::endl; + + fs << " legendNode1 [ label = \"Static Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC << " ];" << std::endl; + fs << " legendNode2 [ label = \"Shared Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED << " ];" << std::endl; + fs << " legendNode3 [ label = \"Module Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE << " ];" << std::endl; + + fs << " legendNode4 [ label = \"Interface Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE << " ];" << std::endl; + fs << " legendNode5 [ label = \"Object Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT << " ];" << std::endl; + fs << " legendNode6 [ label = \"Unknown Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN << " ];" << std::endl; + + fs << " legendNode7 [ label = \"Custom Target\", shape = " + << GRAPHVIZ_NODE_SHAPE_UTILITY << " ];" << std::endl; + + // Edges. + // Some of those are dummy (invisible) edges to enforce a layout. + fs << " legendNode0 -> legendNode1 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + fs << " legendNode0 -> legendNode2 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + fs << " legendNode0 -> legendNode3;" << std::endl; + + fs << " legendNode1 -> legendNode4 [ label = \"Interface\", style = " + << GRAPHVIZ_EDGE_STYLE_INTERFACE << " ];" << std::endl; + fs << " legendNode2 -> legendNode5 [ label = \"Private\", style = " + << GRAPHVIZ_EDGE_STYLE_PRIVATE << " ];" << std::endl; + fs << " legendNode3 -> legendNode6 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + + fs << " legendNode0 -> legendNode7;" << std::endl; + + fs << "}" << std::endl; } -void cmGraphVizWriter::WriteConnections( - const std::string& targetName, std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteNode(cmGeneratedFileStream& fs, + cmLinkItem const& item) { - auto targetPtrIt = this->TargetPtrs.find(targetName); + auto const& itemName = item.AsStr(); + auto const& nodeName = this->NodeNames[itemName]; - if (targetPtrIt == this->TargetPtrs.end()) // not found at all - { - return; - } - - this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str); - - if (targetPtrIt->second == nullptr) // it's an external library - { - return; - } + auto const itemNameWithAliases = ItemNameWithAliases(itemName); + auto const escapedLabel = EscapeForDotFile(itemNameWithAliases); - std::string myNodeName = this->TargetNamesNodes.find(targetName)->second; - std::map<std::string, LinkLibraryScopeType> ll = - getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target, - GlobalGenerator); - - for (auto const& llit : ll) { - const std::string& libName = llit.first; - auto libNameIt = this->TargetNamesNodes.find(libName); - - // can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used - if (libNameIt == this->TargetNamesNodes.end()) { - continue; - } + fs << " \"" << nodeName << "\" [ label = \"" << escapedLabel + << "\", shape = " << getShapeForTarget(item) << " ];" << std::endl; +} - std::string connectionName = cmStrCat(myNodeName, '-', libNameIt->second); - if (insertedConnections.find(connectionName) == - insertedConnections.end()) { - insertedConnections.insert(connectionName); - this->WriteNode(libName, this->TargetPtrs.find(libName)->second, - insertedNodes, str); +void cmGraphVizWriter::WriteConnection(cmGeneratedFileStream& fs, + cmLinkItem const& depender, + cmLinkItem const& dependee, + std::string const& edgeStyle) +{ + auto const& dependerName = depender.AsStr(); + auto const& dependeeName = dependee.AsStr(); - str << " \"" << myNodeName << "\" -> \"" << libNameIt->second << "\""; + fs << " \"" << this->NodeNames[dependerName] << "\" -> \"" + << this->NodeNames[dependeeName] << "\" "; - str << getLinkLibraryStyle(llit.second); + fs << edgeStyle; - str << " // " << targetName << " -> " << libName << std::endl; - this->WriteConnections(libName, insertedNodes, insertedConnections, str); - } - } + fs << " // " << dependerName << " -> " << dependeeName << std::endl; } -void cmGraphVizWriter::WriteDependerConnections( - const std::string& targetName, std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const +bool cmGraphVizWriter::ItemExcluded(cmLinkItem const& item) { - auto targetPtrIt = this->TargetPtrs.find(targetName); + auto const itemName = item.AsStr(); - if (targetPtrIt == this->TargetPtrs.end()) // not found at all - { - return; + if (this->ItemNameFilteredOut(itemName)) { + return true; } - this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str); - - if (targetPtrIt->second == nullptr) // it's an external library - { - return; + if (item.Target == nullptr) { + return !this->GenerateForExternals; } - std::string myNodeName = this->TargetNamesNodes.find(targetName)->second; - - // now search who links against me - for (auto const& tptr : this->TargetPtrs) { - if (tptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(tptr.second->GetType())) { - continue; - } - - // Now we have a target, check whether it links against targetName. - // If so, draw a connection, and then continue with dependers on that one. - std::map<std::string, LinkLibraryScopeType> ll = - getScopedLinkLibrariesFromTarget(tptr.second->Target, GlobalGenerator); - - for (auto const& llit : ll) { - if (llit.first == targetName) { - // So this target links against targetName. - auto dependerNodeNameIt = this->TargetNamesNodes.find(tptr.first); - - if (dependerNodeNameIt != this->TargetNamesNodes.end()) { - std::string connectionName = - cmStrCat(dependerNodeNameIt->second, '-', myNodeName); - - if (insertedConnections.find(connectionName) == - insertedConnections.end()) { - insertedConnections.insert(connectionName); - this->WriteNode(tptr.first, tptr.second, insertedNodes, str); - - str << " \"" << dependerNodeNameIt->second << "\" -> \"" - << myNodeName << "\""; - str << " // " << targetName << " -> " << tptr.first << std::endl; - str << getLinkLibraryStyle(llit.second); - this->WriteDependerConnections(tptr.first, insertedNodes, - insertedConnections, str); - } - } - break; - } + if (item.Target->GetType() == cmStateEnums::UTILITY) { + if ((itemName.find("Nightly") == 0) || + (itemName.find("Continuous") == 0) || + (itemName.find("Experimental") == 0)) { + return true; } } -} -void cmGraphVizWriter::WriteNode(const std::string& targetName, - const cmGeneratorTarget* target, - std::set<std::string>& insertedNodes, - cmGeneratedFileStream& str) const -{ - if (insertedNodes.find(targetName) == insertedNodes.end()) { - insertedNodes.insert(targetName); - auto nameIt = this->TargetNamesNodes.find(targetName); - - str << " \"" << nameIt->second << "\" [ label=\"" << targetName - << "\" shape=\"" << getShapeForTarget(target) << "\"];" << std::endl; + if (item.Target->IsImported() && !this->GenerateForExternals) { + return true; } -} -void cmGraphVizWriter::CollectTargetsAndLibs() -{ - if (!this->HaveTargetsAndLibs) { - this->HaveTargetsAndLibs = true; - int cnt = this->CollectAllTargets(); - if (this->GenerateForExternals) { - this->CollectAllExternalLibs(cnt); - } - } + return !this->TargetTypeEnabled(item.Target->GetType()); } -int cmGraphVizWriter::CollectAllTargets() +bool cmGraphVizWriter::ItemNameFilteredOut(std::string const& itemName) { - int cnt = 0; - // First pass get the list of all cmake targets - for (cmLocalGenerator* lg : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { - const std::string& realTargetName = target->GetName(); - if (this->IgnoreThisTarget(realTargetName)) { - // Skip ignored targets - continue; - } - // std::cout << "Found target: " << tit->first << std::endl; - std::ostringstream ostr; - ostr << this->GraphNodePrefix << cnt++; - this->TargetNamesNodes[realTargetName] = ostr.str(); - this->TargetPtrs[realTargetName] = target; - } + if (itemName == ">") { + // FIXME: why do we even receive such a target here? + return true; } - return cnt; -} - -int cmGraphVizWriter::CollectAllExternalLibs(int cnt) -{ - // Ok, now find all the stuff we link to that is not in cmake - for (cmLocalGenerator* lg : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { - const std::string& realTargetName = target->GetName(); - if (this->IgnoreThisTarget(realTargetName)) { - // Skip ignored targets - continue; - } - const cmTarget::LinkLibraryVectorType* ll = - &(target->Target->GetOriginalLinkLibraries()); - for (auto const& llit : *ll) { - std::string libName = llit.first; - if (this->IgnoreThisTarget(libName)) { - // Skip ignored targets - continue; - } - - if (GlobalGenerator->IsAlias(libName)) { - const auto tgt = GlobalGenerator->FindTarget(libName); - if (tgt) { - libName = tgt->GetName(); - } - } - - auto tarIt = this->TargetPtrs.find(libName); - if (tarIt == this->TargetPtrs.end()) { - std::ostringstream ostr; - ostr << this->GraphNodePrefix << cnt++; - this->TargetNamesNodes[libName] = ostr.str(); - this->TargetPtrs[libName] = nullptr; - // str << " \"" << ostr << "\" [ label=\"" << libName - // << "\" shape=\"ellipse\"];" << std::endl; - } - } - } + if (cmGlobalGenerator::IsReservedTarget(itemName)) { + return true; } - return cnt; -} -bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name) -{ for (cmsys::RegularExpression& regEx : this->TargetsToIgnoreRegex) { if (regEx.is_valid()) { - if (regEx.find(name)) { + if (regEx.find(itemName)) { return true; } } @@ -579,7 +438,7 @@ bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name) return false; } -bool cmGraphVizWriter::GenerateForTargetType( +bool cmGraphVizWriter::TargetTypeEnabled( cmStateEnums::TargetType targetType) const { switch (targetType) { @@ -592,9 +451,73 @@ bool cmGraphVizWriter::GenerateForTargetType( case cmStateEnums::MODULE_LIBRARY: return this->GenerateForModuleLibs; case cmStateEnums::INTERFACE_LIBRARY: - return this->GenerateForInterface; + return this->GenerateForInterfaceLibs; + case cmStateEnums::OBJECT_LIBRARY: + return this->GenerateForObjectLibs; + case cmStateEnums::UNKNOWN_LIBRARY: + return this->GenerateForUnknownLibs; + case cmStateEnums::UTILITY: + return this->GenerateForCustomTargets; + case cmStateEnums::GLOBAL_TARGET: + // Built-in targets like edit_cache, etc. + // We don't need/want those in the dot file. + return false; default: break; } return false; } + +std::string cmGraphVizWriter::ItemNameWithAliases( + std::string const& itemName) const +{ + auto nameWithAliases = itemName; + + for (auto const& lg : this->GlobalGenerator->GetLocalGenerators()) { + for (auto const& aliasTargets : lg->GetMakefile()->GetAliasTargets()) { + if (aliasTargets.second == itemName) { + nameWithAliases += "\\n(" + aliasTargets.first + ")"; + } + } + } + + return nameWithAliases; +} + +std::string cmGraphVizWriter::GetEdgeStyle(DependencyType dt) +{ + std::string style; + switch (dt) { + case DependencyType::LinkPrivate: + style = "[ style = " + std::string(GRAPHVIZ_EDGE_STYLE_PRIVATE) + " ]"; + break; + case DependencyType::LinkInterface: + style = "[ style = " + std::string(GRAPHVIZ_EDGE_STYLE_INTERFACE) + " ]"; + break; + default: + break; + } + return style; +} + +std::string cmGraphVizWriter::EscapeForDotFile(std::string const& str) +{ + return cmSystemTools::EscapeChars(str.data(), "\""); +} + +std::string cmGraphVizWriter::PathSafeString(std::string const& str) +{ + std::string pathSafeStr; + + // We'll only keep alphanumerical characters, plus the following ones that + // are common, and safe on all platforms: + auto const extra_chars = std::set<char>{ '.', '-', '_' }; + + for (char c : str) { + if (std::isalnum(c) || extra_chars.find(c) != extra_chars.cend()) { + pathSafeStr += c; + } + } + + return pathSafeStr; +} diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index 9c3051f2c1..578660dbbb 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -6,87 +6,106 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> -#include <set> +#include <memory> #include <string> #include <vector> #include "cmsys/RegularExpression.hxx" +#include "cmGeneratedFileStream.h" +#include "cmLinkItemGraphVisitor.h" #include "cmStateTypes.h" -class cmGeneratedFileStream; -class cmGeneratorTarget; -class cmLocalGenerator; +class cmLinkItem; class cmGlobalGenerator; /** This class implements writing files for graphviz (dot) for graphs * representing the dependencies between the targets in the project. */ -class cmGraphVizWriter +class cmGraphVizWriter : public cmLinkItemGraphVisitor { public: - cmGraphVizWriter(const cmGlobalGenerator* globalGenerator); + cmGraphVizWriter(std::string const& fileName, + const cmGlobalGenerator* globalGenerator); + ~cmGraphVizWriter() override; + + void VisitGraph(std::string const& name) override; + + void OnItem(cmLinkItem const& item) override; + + void OnDirectLink(cmLinkItem const& depender, cmLinkItem const& dependee, + DependencyType dt) override; + + void OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) override; void ReadSettings(const std::string& settingsFileName, const std::string& fallbackSettingsFileName); - void WritePerTargetFiles(const std::string& fileName); - void WriteTargetDependersFiles(const std::string& fileName); + void Write(); + +private: + using FileStreamMap = + std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>; + + void VisitLink(cmLinkItem const& depender, cmLinkItem const& dependee, + bool isDirectLink, std::string const& scopeType = ""); + + void WriteHeader(cmGeneratedFileStream& fs, std::string const& name); - void WriteGlobalFile(const std::string& fileName); + void WriteFooter(cmGeneratedFileStream& fs); -protected: - void CollectTargetsAndLibs(); + void WriteLegend(cmGeneratedFileStream& fs); - int CollectAllTargets(); + void WriteNode(cmGeneratedFileStream& fs, cmLinkItem const& item); - int CollectAllExternalLibs(int cnt); + void CreateTargetFile(FileStreamMap& fileStreamMap, cmLinkItem const& target, + std::string const& fileNameSuffix = ""); - void WriteHeader(cmGeneratedFileStream& str) const; + void WriteConnection(cmGeneratedFileStream& fs, + cmLinkItem const& dependerTargetName, + cmLinkItem const& dependeeTargetName, + std::string const& edgeStyle); - void WriteConnections(const std::string& targetName, - std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, - cmGeneratedFileStream& str) const; + bool ItemExcluded(cmLinkItem const& item); + bool ItemNameFilteredOut(std::string const& itemName); + bool TargetTypeEnabled(cmStateEnums::TargetType targetType) const; - void WriteDependerConnections(const std::string& targetName, - std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, - cmGeneratedFileStream& str) const; + std::string ItemNameWithAliases(std::string const& itemName) const; - void WriteNode(const std::string& targetName, - const cmGeneratorTarget* target, - std::set<std::string>& insertedNodes, - cmGeneratedFileStream& str) const; + static std::string GetEdgeStyle(DependencyType dt); - void WriteFooter(cmGeneratedFileStream& str) const; + static std::string EscapeForDotFile(std::string const& str); - bool IgnoreThisTarget(const std::string& name); + static std::string PathSafeString(std::string const& str); - bool GenerateForTargetType(cmStateEnums::TargetType targetType) const; + std::string FileName; + cmGeneratedFileStream GlobalFileStream; + FileStreamMap PerTargetFileStreams; + FileStreamMap TargetDependersFileStreams; - std::string GraphType; std::string GraphName; std::string GraphHeader; std::string GraphNodePrefix; std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex; - const cmGlobalGenerator* GlobalGenerator; - const std::vector<cmLocalGenerator*>& LocalGenerators; + cmGlobalGenerator const* GlobalGenerator; - std::map<std::string, const cmGeneratorTarget*> TargetPtrs; - // maps from the actual target names to node names in dot: - std::map<std::string, std::string> TargetNamesNodes; + int NextNodeId; + // maps from the actual item names to node names in dot: + std::map<std::string, std::string> NodeNames; bool GenerateForExecutables; bool GenerateForStaticLibs; bool GenerateForSharedLibs; bool GenerateForModuleLibs; - bool GenerateForInterface; + bool GenerateForInterfaceLibs; + bool GenerateForObjectLibs; + bool GenerateForUnknownLibs; + bool GenerateForCustomTargets; bool GenerateForExternals; bool GeneratePerTarget; bool GenerateDependers; - bool HaveTargetsAndLibs; }; #endif diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 71326d23ad..b53319f510 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -4,6 +4,8 @@ #include <iterator> +#include <cmext/algorithm> + #include <string.h> #include "cmsys/String.h" @@ -173,7 +175,7 @@ void cmIDEOptions::AddDefines(std::string const& defines) } void cmIDEOptions::AddDefines(const std::vector<std::string>& defines) { - cmAppend(this->Defines, defines); + cm::append(this->Defines, defines); } std::vector<std::string> const& cmIDEOptions::GetDefines() const @@ -195,7 +197,7 @@ void cmIDEOptions::AddIncludes(std::string const& includes) } void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes) { - cmAppend(this->Includes, includes); + cm::append(this->Includes, includes); } std::vector<std::string> const& cmIDEOptions::GetIncludes() const diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index 170aea1258..b408f7210f 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -6,7 +6,8 @@ #include <set> #include <utility> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" @@ -58,9 +59,9 @@ bool cmIncludeDirectoryCommand(std::vector<std::string> const& args, GetIncludes(mf, *i, includes); if (before) { - cmAppend(beforeIncludes, includes); + cm::append(beforeIncludes, includes); } else { - cmAppend(afterIncludes, includes); + cm::append(afterIncludes, includes); } if (system) { systemIncludes.insert(includes.begin(), includes.end()); diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx index fa1e8bcf96..e59c428777 100644 --- a/Source/cmIncludeExternalMSProjectCommand.cxx +++ b/Source/cmIncludeExternalMSProjectCommand.cxx @@ -83,22 +83,21 @@ bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args, } // Create a target instance for this utility. - cmTarget* target = - mf.AddNewTarget(cmStateEnums::UTILITY, utility_name.c_str()); + cmTarget* target = mf.AddNewTarget(cmStateEnums::UTILITY, utility_name); if (mf.GetPropertyAsBool("EXCLUDE_FROM_ALL")) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } - target->SetProperty("GENERATOR_FILE_NAME", utility_name.c_str()); - target->SetProperty("EXTERNAL_MSPROJECT", path.c_str()); + target->SetProperty("GENERATOR_FILE_NAME", utility_name); + target->SetProperty("EXTERNAL_MSPROJECT", path); if (!customType.empty()) - target->SetProperty("VS_PROJECT_TYPE", customType.c_str()); + target->SetProperty("VS_PROJECT_TYPE", customType); if (!platformMapping.empty()) - target->SetProperty("VS_PLATFORM_MAPPING", platformMapping.c_str()); + target->SetProperty("VS_PLATFORM_MAPPING", platformMapping); for (std::string const& d : depends) { - target->AddUtility(d.c_str()); + target->AddUtility(d); } } #endif diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index d623943117..efbcb981b4 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -7,11 +7,14 @@ #include "cmGlobalGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +class cmListFileBacktrace; + static std::string FindInstallSource(cmMakefile& makefile, const char* name); static void CreateInstallGenerator(cmMakefile& makefile, std::string const& dest, @@ -43,9 +46,10 @@ bool cmInstallFilesCommand(std::vector<std::string> const& args, CreateInstallGenerator(mf, dest, files); } else { std::vector<std::string> finalArgs(args.begin() + 1, args.end()); - mf.AddFinalAction([dest, finalArgs](cmMakefile& makefile) { - FinalAction(makefile, dest, finalArgs); - }); + mf.AddGeneratorAction( + [dest, finalArgs](cmLocalGenerator& lg, const cmListFileBacktrace&) { + FinalAction(*lg.GetMakefile(), dest, finalArgs); + }); } mf.GetGlobalGenerator()->AddInstallComponent( diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 6bb4409d5a..2088eae19c 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -7,10 +7,13 @@ #include "cmGlobalGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +class cmListFileBacktrace; + static void FinalAction(cmMakefile& makefile, std::string const& dest, std::vector<std::string> const& args); static std::string FindInstallSource(cmMakefile& makefile, const char* name); @@ -33,9 +36,10 @@ bool cmInstallProgramsCommand(std::vector<std::string> const& args, std::string const& dest = args[0]; std::vector<std::string> const finalArgs(args.begin() + 1, args.end()); - mf.AddFinalAction([dest, finalArgs](cmMakefile& makefile) { - FinalAction(makefile, dest, finalArgs); - }); + mf.AddGeneratorAction( + [dest, finalArgs](cmLocalGenerator& lg, const cmListFileBacktrace&) { + FinalAction(*lg.GetMakefile(), dest, finalArgs); + }); return true; } diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index aa92fa71ae..69c9b7ed20 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -554,7 +554,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule( // components of the install_name field then we need to create a // mapping to be applied after installation. std::string for_build = tgt->GetInstallNameDirForBuildTree(config); - std::string for_install = tgt->GetInstallNameDirForInstallTree(); + std::string for_install = tgt->GetInstallNameDirForInstallTree( + config, "${CMAKE_INSTALL_PREFIX}"); if (for_build != for_install) { // The directory portions differ. Append the filename to // create the mapping. @@ -577,7 +578,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule( if (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) { std::string for_build = this->Target->GetInstallNameDirForBuildTree(config); - std::string for_install = this->Target->GetInstallNameDirForInstallTree(); + std::string for_install = this->Target->GetInstallNameDirForInstallTree( + config, "${CMAKE_INSTALL_PREFIX}"); if (this->Target->IsFrameworkOnApple() && for_install.empty()) { // Frameworks seem to have an id corresponding to their own full diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index eabe5903bd..a65ae037e0 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -4,7 +4,6 @@ #include <utility> -#include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmListFileCache.h" #include "cmMakefile.h" @@ -12,17 +11,11 @@ cmInstalledFile::cmInstalledFile() = default; -cmInstalledFile::~cmInstalledFile() -{ - delete NameExpression; -} +cmInstalledFile::~cmInstalledFile() = default; cmInstalledFile::Property::Property() = default; -cmInstalledFile::Property::~Property() -{ - cmDeleteAll(this->ValueExpressions); -} +cmInstalledFile::Property::~Property() = default; void cmInstalledFile::SetName(cmMakefile* mf, const std::string& name) { @@ -30,7 +23,7 @@ void cmInstalledFile::SetName(cmMakefile* mf, const std::string& name) cmGeneratorExpression ge(backtrace); this->Name = name; - this->NameExpression = ge.Parse(name).release(); + this->NameExpression = ge.Parse(name); } std::string const& cmInstalledFile::GetName() const @@ -63,7 +56,7 @@ void cmInstalledFile::AppendProperty(cmMakefile const* mf, cmGeneratorExpression ge(backtrace); Property& property = this->Properties[prop]; - property.ValueExpressions.push_back(ge.Parse(value).release()); + property.ValueExpressions.push_back(ge.Parse(value)); } bool cmInstalledFile::HasProperty(const std::string& prop) const @@ -84,7 +77,7 @@ bool cmInstalledFile::GetProperty(const std::string& prop, std::string output; std::string separator; - for (auto ve : property.ValueExpressions) { + for (const auto& ve : property.ValueExpressions) { output += separator; output += ve->GetInput(); separator = ";"; diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index ee809ee790..698151e3c8 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -24,7 +24,7 @@ public: using CompiledGeneratorExpressionPtrType = std::unique_ptr<cmCompiledGeneratorExpression>; - using ExpressionVectorType = std::vector<cmCompiledGeneratorExpression*>; + using ExpressionVectorType = std::vector<CompiledGeneratorExpressionPtrType>; struct Property { @@ -73,7 +73,7 @@ public: private: std::string Name; - cmCompiledGeneratorExpression* NameExpression = nullptr; + CompiledGeneratorExpressionPtrType NameExpression; PropertyMapType Properties; }; diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index b23ab43d82..54edabcc9b 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -8,13 +8,15 @@ #include <functional> #include <limits> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> #include <utility> #include <vector> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -43,7 +45,7 @@ namespace { std::vector<std::string> getConfigurations(const cmake* cm) { std::vector<std::string> configurations; - auto makefiles = cm->GetGlobalGenerator()->GetMakefiles(); + const auto& makefiles = cm->GetGlobalGenerator()->GetMakefiles(); if (makefiles.empty()) { return configurations; } @@ -82,8 +84,8 @@ void cmGetCMakeInputs(const cmGlobalGenerator* gg, std::vector<std::string>* tmpFiles) { const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/'; - std::vector<cmMakefile*> const& makefiles = gg->GetMakefiles(); - for (cmMakefile const* mf : makefiles) { + auto const& makefiles = gg->GetMakefiles(); + for (const auto& mf : makefiles) { for (std::string const& lf : mf->GetListFiles()) { const std::string startOfFile = lf.substr(0, cmakeRootDir.size()); @@ -601,7 +603,7 @@ static Json::Value DumpTargetsList( std::vector<cmGeneratorTarget*> targetList; for (auto const& lgIt : generators) { - cmAppend(targetList, lgIt->GetGeneratorTargets()); + cm::append(targetList, lgIt->GetGeneratorTargets()); } std::sort(targetList.begin(), targetList.end()); diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx new file mode 100644 index 0000000000..ab2cf9ea11 --- /dev/null +++ b/Source/cmLinkItemGraphVisitor.cxx @@ -0,0 +1,142 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmLinkItemGraphVisitor.h" + +#include <map> +#include <utility> +#include <vector> + +#include "cmGeneratorTarget.h" +#include "cmLinkItem.h" +#include "cmMakefile.h" + +void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item) +{ + if (this->ItemVisited(item)) { + return; + } + + this->OnItem(item); + + this->VisitLinks(item, item); +} + +void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, + cmLinkItem const& rootItem) +{ + if (this->LinkVisited(item, rootItem)) { + return; + } + + if (item.Target == nullptr) { + return; + } + + for (auto const& config : item.Target->Makefile->GetGeneratorConfigs()) { + this->VisitLinks(item, rootItem, config); + } +} + +void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, + cmLinkItem const& rootItem, + std::string const& config) +{ + auto const& target = *item.Target; + + DependencyMap dependencies; + cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies); + + for (auto const& d : dependencies) { + auto const& dependency = d.second; + auto const& dependencyType = dependency.first; + auto const& dependee = dependency.second; + this->VisitItem(dependee); + + if (this->LinkVisited(item, dependee)) { + continue; + } + + this->OnDirectLink(item, dependee, dependencyType); + + if (rootItem.AsStr() != item.AsStr()) { + this->OnIndirectLink(rootItem, dependee); + } + + // Visit all the direct and indirect links. + this->VisitLinks(dependee, dependee); + this->VisitLinks(dependee, item); + this->VisitLinks(dependee, rootItem); + } +} + +bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item) +{ + auto& collection = this->VisitedItems; + + bool const visited = collection.find(item.AsStr()) != collection.cend(); + + if (!visited) { + collection.insert(item.AsStr()); + } + + return visited; +} + +bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender, + cmLinkItem const& dependee) +{ + auto const link = std::make_pair<>(depender.AsStr(), dependee.AsStr()); + + bool const linkVisited = + this->VisitedLinks.find(link) != this->VisitedLinks.cend(); + + if (!linkVisited) { + this->VisitedLinks.insert(link); + } + + return linkVisited; +} + +void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target, + std::string const& config, + DependencyMap& dependencies) +{ + auto implementationLibraries = target.GetLinkImplementationLibraries(config); + if (implementationLibraries != nullptr) { + for (auto const& lib : implementationLibraries->Libraries) { + auto const& name = lib.AsStr(); + dependencies[name] = Dependency(DependencyType::LinkPrivate, lib); + } + } + + auto interfaceLibraries = + target.GetLinkInterfaceLibraries(config, &target, true); + if (interfaceLibraries != nullptr) { + for (auto const& lib : interfaceLibraries->Libraries) { + auto const& name = lib.AsStr(); + if (dependencies.find(name) != dependencies.cend()) { + dependencies[name] = Dependency(DependencyType::LinkPublic, lib); + } else { + dependencies[name] = Dependency(DependencyType::LinkInterface, lib); + } + } + } + + std::vector<cmGeneratorTarget*> objectLibraries; + target.GetObjectLibrariesCMP0026(objectLibraries); + for (auto const& lib : objectLibraries) { + auto const& name = lib->GetName(); + if (dependencies.find(name) == dependencies.cend()) { + auto objectItem = cmLinkItem(lib, lib->GetBacktrace()); + dependencies[name] = Dependency(DependencyType::Object, objectItem); + } + } + + auto const& utilityItems = target.GetUtilityItems(); + for (auto const& item : utilityItems) { + auto const& name = item.AsStr(); + if (dependencies.find(name) == dependencies.cend()) { + dependencies[name] = Dependency(DependencyType::Utility, item); + } + } +} diff --git a/Source/cmLinkItemGraphVisitor.h b/Source/cmLinkItemGraphVisitor.h new file mode 100644 index 0000000000..21dc659ad3 --- /dev/null +++ b/Source/cmLinkItemGraphVisitor.h @@ -0,0 +1,75 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmLinkItemGraphVisitor_h +#define cmLinkItemGraphVisitor_h + +#include <map> +#include <set> +#include <string> +#include <utility> + +#include "cmLinkItem.h" + +class cmGeneratorTarget; + +/** \class cmLinkItemGraphVisitor + * \brief Visits a graph of linked items. + * + * Allows to visit items and dependency links (direct and indirect) between + * those items. + * This abstract class takes care of the graph traversal, making sure that: + * - it terminates even in the presence of cycles; + * - it visits every object once (and only once); + * - it visits the objects in the same order every time. + * + * Children classes only have to implement OnItem() etc. to handle whatever + * logic they care about. + */ +class cmLinkItemGraphVisitor +{ +public: + virtual ~cmLinkItemGraphVisitor() = default; + + virtual void VisitGraph(std::string const& name) = 0; + + void VisitItem(cmLinkItem const& item); + +protected: + enum class DependencyType + { + LinkInterface, + LinkPublic, + LinkPrivate, + Object, + Utility + }; + + virtual void OnItem(cmLinkItem const& item) = 0; + + virtual void OnDirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee, DependencyType dt) = 0; + + virtual void OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) = 0; + +private: + std::set<std::string> VisitedItems; + + std::set<std::pair<std::string, std::string>> VisitedLinks; + + void VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem); + void VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem, + std::string const& config); + + using Dependency = std::pair<DependencyType, cmLinkItem>; + using DependencyMap = std::map<std::string, Dependency>; + + bool ItemVisited(cmLinkItem const& item); + bool LinkVisited(cmLinkItem const& depender, cmLinkItem const& dependee); + + static void GetDependencies(cmGeneratorTarget const& target, + std::string const& config, + DependencyMap& dependencies); +}; + +#endif diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 0dc6236a0b..4320010621 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -23,6 +23,7 @@ cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, , OutputConverter(outputConverter) , ForResponse(false) , UseWatcomQuote(false) + , UseNinjaMulti(false) , Relink(false) { } @@ -34,6 +35,11 @@ void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote) this->UseWatcomQuote = useWatcomQuote; } +void cmLinkLineComputer::SetUseNinjaMulti(bool useNinjaMulti) +{ + this->UseNinjaMulti = useNinjaMulti; +} + void cmLinkLineComputer::SetForResponse(bool forResponse) { this->ForResponse = forResponse; @@ -106,10 +112,14 @@ void cmLinkLineComputer::ComputeLinkLibs( std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input) { - cmOutputConverter::OutputFormat shellFormat = (this->ForResponse) - ? cmOutputConverter::RESPONSE - : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE - : cmOutputConverter::SHELL); + cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL; + if (this->ForResponse) { + shellFormat = cmOutputConverter::RESPONSE; + } else if (this->UseWatcomQuote) { + shellFormat = cmOutputConverter::WATCOMQUOTE; + } else if (this->UseNinjaMulti) { + shellFormat = cmOutputConverter::NINJAMULTI; + } return this->OutputConverter->ConvertToOutputFormat(input, shellFormat); } @@ -117,10 +127,14 @@ std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input) std::string cmLinkLineComputer::ConvertToOutputForExisting( std::string const& input) { - cmOutputConverter::OutputFormat shellFormat = (this->ForResponse) - ? cmOutputConverter::RESPONSE - : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE - : cmOutputConverter::SHELL); + cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL; + if (this->ForResponse) { + shellFormat = cmOutputConverter::RESPONSE; + } else if (this->UseWatcomQuote) { + shellFormat = cmOutputConverter::WATCOMQUOTE; + } else if (this->UseNinjaMulti) { + shellFormat = cmOutputConverter::NINJAMULTI; + } return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat); } diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index f426976a2f..df424683fd 100644 --- a/Source/cmLinkLineComputer.h +++ b/Source/cmLinkLineComputer.h @@ -28,6 +28,7 @@ public: cmLinkLineComputer& operator=(cmLinkLineComputer const&) = delete; void SetUseWatcomQuote(bool useWatcomQuote); + void SetUseNinjaMulti(bool useNinjaMulti); void SetForResponse(bool forResponse); void SetRelink(bool relink); @@ -69,6 +70,7 @@ protected: bool ForResponse; bool UseWatcomQuote; + bool UseNinjaMulti; bool Relink; }; diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index d8456523d6..847334b20d 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -183,29 +183,29 @@ bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, return cmIsOn(resolveDeviceSymbols); } - if (const char* separableCompilation = - target.GetProperty("CUDA_SEPARABLE_COMPILATION")) { - if (cmIsOn(separableCompilation)) { - bool doDeviceLinking = false; - switch (target.GetType()) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::EXECUTABLE: - doDeviceLinking = true; - break; - default: - break; - } - return doDeviceLinking; - } - } - // Determine if we have any dependencies that require // us to do a device link step cmGeneratorTarget::LinkClosure const* closure = target.GetLinkClosure(config); if (cmContains(closure->Languages, "CUDA")) { + if (const char* separableCompilation = + target.GetProperty("CUDA_SEPARABLE_COMPILATION")) { + if (cmIsOn(separableCompilation)) { + bool doDeviceLinking = false; + switch (target.GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::EXECUTABLE: + doDeviceLinking = true; + break; + default: + break; + } + return doDeviceLinking; + } + } + cmComputeLinkInformation* pcli = target.GetLinkInformation(config); if (pcli) { cmLinkLineDeviceComputer deviceLinkComputer( diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx index 1184bcb583..d49e7117c1 100644 --- a/Source/cmLoadCacheCommand.cxx +++ b/Source/cmLoadCacheCommand.cxx @@ -24,12 +24,20 @@ bool cmLoadCacheCommand(std::vector<std::string> const& args, { if (args.empty()) { status.SetError("called with wrong number of arguments."); + return false; } if (args.size() >= 2 && args[1] == "READ_WITH_PREFIX") { return ReadWithPrefix(args, status); } + if (status.GetMakefile().GetCMakeInstance()->GetWorkingMode() == + cmake::SCRIPT_MODE) { + status.SetError( + "Only load_cache(READ_WITH_PREFIX) may be used in script mode"); + return false; + } + // Cache entries to be excluded from the import list. // If this set is empty, all cache entries are brought in // and they can not be overridden. diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 23ace649a8..92258e27be 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -14,6 +14,7 @@ #include "cmCommand.h" #include "cmDynamicLoader.h" #include "cmExecutionStatus.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStringAlgorithms.h" @@ -25,6 +26,8 @@ # include <malloc.h> /* for malloc/free on QNX */ #endif +class cmListFileBacktrace; + namespace { const char* LastName = nullptr; @@ -158,8 +161,10 @@ bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args, if (result) { if (this->Impl->FinalPass) { auto impl = this->Impl; - this->Makefile->AddFinalAction( - [impl](cmMakefile& makefile) { impl->DoFinalPass(&makefile); }); + this->Makefile->AddGeneratorAction( + [impl](cmLocalGenerator& lg, const cmListFileBacktrace&) { + impl->DoFinalPass(lg.GetMakefile()); + }); } return true; } diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index f86955dd0c..025ef7e6bb 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -17,13 +17,9 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, : cmLocalGenerator(gg, mf) , WorkingDirectory(std::move(wd)) { - // Store the configuration name that will be generated. - if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { - // Use the build type given by the user. - this->ConfigName = config; - } else { - // No configuration type given. - this->ConfigName.clear(); + this->Makefile->GetConfigurations(this->ConfigNames); + if (this->ConfigNames.empty()) { + this->ConfigNames.emplace_back(); } } diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index eaef6ab530..378ca634d1 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -7,6 +7,7 @@ #include <map> #include <string> +#include <vector> #include "cmLocalGenerator.h" @@ -25,7 +26,10 @@ public: std::string wd); ~cmLocalCommonGenerator() override; - std::string const& GetConfigName() const { return this->ConfigName; } + std::vector<std::string> const& GetConfigNames() const + { + return this->ConfigNames; + } std::string GetWorkingDirectory() const { return this->WorkingDirectory; } @@ -39,7 +43,7 @@ public: protected: std::string WorkingDirectory; - std::string ConfigName; + std::vector<std::string> ConfigNames; friend class cmCommonTargetGenerator; }; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 17544213b5..4969d55d59 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2,6 +2,22 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalGenerator.h" +#include <algorithm> +#include <cassert> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <initializer_list> +#include <iterator> +#include <sstream> +#include <unordered_set> +#include <utility> +#include <vector> + +#include <cm/memory> +#include <cm/string_view> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" #include "cmAlgorithms.h" @@ -40,20 +56,6 @@ # include "cmCryptoHash.h" #endif -#include <algorithm> -#include <cassert> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <initializer_list> -#include <iterator> -#include <sstream> -#include <unordered_set> -#include <utility> -#include <vector> - -#include <cm/string_view> - #if defined(__HAIKU__) # include <FindDirectory.h> # include <StorageDefs.h> @@ -181,11 +183,7 @@ cmRulePlaceholderExpander* cmLocalGenerator::CreateRulePlaceholderExpander() this->LinkerSysroot); } -cmLocalGenerator::~cmLocalGenerator() -{ - cmDeleteAll(this->GeneratorTargets); - cmDeleteAll(this->OwnedImportedGeneratorTargets); -} +cmLocalGenerator::~cmLocalGenerator() = default; void cmLocalGenerator::IssueMessage(MessageType t, std::string const& text) const @@ -263,8 +261,8 @@ static void MoveSystemIncludesToEnd(std::vector<BT<std::string>>& includeDirs, void cmLocalGenerator::TraceDependencies() { // Generate the rule files for each target. - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = this->GetGeneratorTargets(); + for (const auto& target : targets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } @@ -395,7 +393,7 @@ void cmLocalGenerator::ProcessEvaluationFiles( return; } - cmAppend(generatedFiles, files); + cm::append(generatedFiles, files); std::inplace_merge(generatedFiles.begin(), generatedFiles.end() - files.size(), generatedFiles.end()); @@ -635,11 +633,14 @@ void cmLocalGenerator::GenerateInstallRules() } } -void cmLocalGenerator::AddGeneratorTarget(cmGeneratorTarget* gt) +void cmLocalGenerator::AddGeneratorTarget( + std::unique_ptr<cmGeneratorTarget> gt) { - this->GeneratorTargets.push_back(gt); - this->GeneratorTargetSearchIndex.emplace(gt->GetName(), gt); - this->GlobalGenerator->IndexGeneratorTarget(gt); + cmGeneratorTarget* gt_ptr = gt.get(); + + this->GeneratorTargets.push_back(std::move(gt)); + this->GeneratorTargetSearchIndex.emplace(gt_ptr->GetName(), gt_ptr); + this->GlobalGenerator->IndexGeneratorTarget(gt_ptr); } void cmLocalGenerator::AddImportedGeneratorTarget(cmGeneratorTarget* gt) @@ -648,9 +649,10 @@ void cmLocalGenerator::AddImportedGeneratorTarget(cmGeneratorTarget* gt) this->GlobalGenerator->IndexGeneratorTarget(gt); } -void cmLocalGenerator::AddOwnedImportedGeneratorTarget(cmGeneratorTarget* gt) +void cmLocalGenerator::AddOwnedImportedGeneratorTarget( + std::unique_ptr<cmGeneratorTarget> gt) { - this->OwnedImportedGeneratorTargets.push_back(gt); + this->OwnedImportedGeneratorTargets.push_back(std::move(gt)); } cmGeneratorTarget* cmLocalGenerator::FindLocalNonAliasGeneratorTarget( @@ -673,8 +675,8 @@ void cmLocalGenerator::ComputeTargetManifest() } // Add our targets to the manifest for each configuration. - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = this->GetGeneratorTargets(); + for (const auto& target : targets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } @@ -695,17 +697,18 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures() using LanguagePair = std::pair<std::string, std::string>; std::vector<LanguagePair> pairedLanguages{ { "OBJC", "C" }, - { "OBJCXX", "CXX" } }; - std::set<LanguagePair> objcEnabledLanguages; + { "OBJCXX", "CXX" }, + { "CUDA", "CXX" } }; + std::set<LanguagePair> inferredEnabledLanguages; for (auto const& lang : pairedLanguages) { if (this->Makefile->GetState()->GetLanguageEnabled(lang.first)) { - objcEnabledLanguages.insert(lang); + inferredEnabledLanguages.insert(lang); } } // Process compile features of all targets. - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = this->GetGeneratorTargets(); + for (const auto& target : targets) { for (std::string const& c : configNames) { if (!target->ComputeCompileFeatures(c)) { return false; @@ -738,12 +741,17 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures() target->GetProperty(cmStrCat(lang.second, property))); } }; - for (auto const& lang : objcEnabledLanguages) { + for (auto const& lang : pairedLanguages) { if (copyStandardToObjLang(lang)) { copyPropertyToObjLang(lang, "_STANDARD_REQUIRED"); copyPropertyToObjLang(lang, "_EXTENSIONS"); } } + if (const char* standard = target->GetProperty("CUDA_STANDARD")) { + if (std::string{ standard } == "98") { + target->Target->SetProperty("CUDA_STANDARD", "03"); + } + } } } @@ -988,6 +996,91 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, } } +cmTarget* cmLocalGenerator::AddCustomCommandToTarget( + const std::string& target, const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, cmCustomCommandType type, + const char* comment, const char* workingDir, bool escapeOldStyle, + bool uses_terminal, const std::string& depfile, const std::string& job_pool, + bool command_expand_lists, cmObjectLibraryCommands objLibCommands) +{ + cmTarget* t = this->Makefile->GetCustomCommandTarget( + target, objLibCommands, this->DirectoryBacktrace); + if (!t) { + return nullptr; + } + + detail::AddCustomCommandToTarget( + *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, t, byproducts, + depends, commandLines, type, comment, workingDir, escapeOldStyle, + uses_terminal, depfile, job_pool, command_expand_lists); + + return t; +} + +cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput( + const std::string& output, const std::vector<std::string>& depends, + const std::string& main_dependency, const cmCustomCommandLines& commandLines, + const char* comment, const char* workingDir, bool replace, + bool escapeOldStyle, bool uses_terminal, bool command_expand_lists, + const std::string& depfile, const std::string& job_pool) +{ + std::vector<std::string> no_byproducts; + cmImplicitDependsList no_implicit_depends; + return this->AddCustomCommandToOutput( + { output }, no_byproducts, depends, main_dependency, no_implicit_depends, + commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal, + command_expand_lists, depfile, job_pool); +} + +cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput( + const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool) +{ + // Make sure there is at least one output. + if (outputs.empty()) { + cmSystemTools::Error("Attempt to add a custom rule with no output!"); + return nullptr; + } + + return detail::AddCustomCommandToOutput( + *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, outputs, + byproducts, depends, main_dependency, implicit_depends, commandLines, + comment, workingDir, replace, escapeOldStyle, uses_terminal, + command_expand_lists, depfile, job_pool); +} + +cmTarget* cmLocalGenerator::AddUtilityCommand( + const std::string& utilityName, bool excludeFromAll, const char* workingDir, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, bool escapeOldStyle, + const char* comment, bool uses_terminal, bool command_expand_lists, + const std::string& job_pool) +{ + cmTarget* target = + this->Makefile->AddNewUtilityTarget(utilityName, excludeFromAll); + target->SetIsGeneratorProvided(true); + + if (commandLines.empty() && depends.empty()) { + return target; + } + + detail::AddUtilityCommand( + *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, target, + this->Makefile->GetUtilityOutput(target), workingDir, byproducts, depends, + commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists, + job_pool); + + return target; +} + std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( cmGeneratorTarget const* target, std::string const& lang, std::string const& config, bool stripImplicitDirs, @@ -1685,10 +1778,18 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, const std::string& lang, const std::string& config) { - // Only add macOS specific flags on Darwin platforms (macOS and iOS): + // Only add Apple specific flags on Apple platforms if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) { std::vector<std::string> archs; target->GetAppleArchs(config, archs); + if (!archs.empty() && !lang.empty() && + (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) { + for (std::string const& arch : archs) { + flags += " -arch "; + flags += arch; + } + } + const char* sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT"); if (sysroot && sysroot[0] == '/' && !sysroot[1]) { sysroot = nullptr; @@ -1696,27 +1797,37 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, std::string sysrootFlagVar = std::string("CMAKE_") + lang + "_SYSROOT_FLAG"; const char* sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar); + if (sysrootFlag && *sysrootFlag) { + std::vector<std::string> arch_sysroots; + if (const char* arch_sysroots_str = + this->Makefile->GetDefinition("CMAKE_APPLE_ARCH_SYSROOTS")) { + cmExpandList(std::string(arch_sysroots_str), arch_sysroots, true); + } + if (!arch_sysroots.empty()) { + assert(arch_sysroots.size() == archs.size()); + for (size_t i = 0; i < archs.size(); ++i) { + if (arch_sysroots[i].empty()) { + continue; + } + flags += " -Xarch_" + archs[i] + " "; + // Combine sysroot flag and path to work with -Xarch + std::string arch_sysroot = sysrootFlag + arch_sysroots[i]; + flags += this->ConvertToOutputFormat(arch_sysroot, SHELL); + } + } else if (sysroot && *sysroot) { + flags += " "; + flags += sysrootFlag; + flags += " "; + flags += this->ConvertToOutputFormat(sysroot, SHELL); + } + } + const char* deploymentTarget = this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET"); std::string deploymentTargetFlagVar = std::string("CMAKE_") + lang + "_OSX_DEPLOYMENT_TARGET_FLAG"; const char* deploymentTargetFlag = this->Makefile->GetDefinition(deploymentTargetFlagVar); - if (!archs.empty() && !lang.empty() && - (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) { - for (std::string const& arch : archs) { - flags += " -arch "; - flags += arch; - } - } - - if (sysrootFlag && *sysrootFlag && sysroot && *sysroot) { - flags += " "; - flags += sysrootFlag; - flags += " "; - flags += this->ConvertToOutputFormat(sysroot, SHELL); - } - if (deploymentTargetFlag && *deploymentTargetFlag && deploymentTarget && *deploymentTarget) { flags += " "; @@ -2004,17 +2115,22 @@ void cmLocalGenerator::AddCompilerRequirementFlag( langStdMap["OBJC"].emplace_back("99"); langStdMap["OBJC"].emplace_back("90"); + langStdMap["CUDA"].emplace_back("20"); + langStdMap["CUDA"].emplace_back("17"); langStdMap["CUDA"].emplace_back("14"); langStdMap["CUDA"].emplace_back("11"); - langStdMap["CUDA"].emplace_back("98"); + langStdMap["CUDA"].emplace_back("03"); } std::string standard(standardProp); - + if (lang == "CUDA" && standard == "98") { + standard = "03"; + } std::vector<std::string>& stds = langStdMap[lang]; auto stdIt = std::find(stds.begin(), stds.end(), standard); if (stdIt == stds.end()) { + std::string e = lang + "_STANDARD is set to invalid value '" + standard + "'"; this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( @@ -2104,10 +2220,11 @@ static void AddVisibilityCompileOption(std::string& flags, static void AddInlineVisibilityCompileOption(std::string& flags, cmGeneratorTarget const* target, cmLocalGenerator* lg, - std::string* warnCMP0063) + std::string* warnCMP0063, + const std::string& lang) { std::string compileOption = - "CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN"; + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN"); const char* opt = lg->GetMakefile()->GetDefinition(compileOption); if (!opt) { return; @@ -2149,8 +2266,8 @@ void cmLocalGenerator::AddVisibilityPresetFlags( AddVisibilityCompileOption(flags, target, this, lang, pWarnCMP0063); - if (lang == "CXX") { - AddInlineVisibilityCompileOption(flags, target, this, pWarnCMP0063); + if (lang == "CXX" || lang == "OBJCXX") { + AddInlineVisibilityCompileOption(flags, target, this, pWarnCMP0063, lang); } if (!warnCMP0063.empty() && this->WarnCMP0063.insert(target).second) { @@ -2295,7 +2412,9 @@ void cmLocalGenerator::AppendFlags( void cmLocalGenerator::AppendFlagEscape(std::string& flags, const std::string& rawFlag) const { - this->AppendFlags(flags, this->EscapeForShell(rawFlag)); + this->AppendFlags( + flags, + this->EscapeForShell(rawFlag, false, false, false, this->IsNinjaMulti())); } void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) @@ -2404,13 +2523,9 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) file << "endif()\n"; } - cmCustomCommandLines commandLines; - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back(cmStrCat("-DPDB_PREFIX=", pdb_prefix)); - currentLine.push_back("-P"); - currentLine.push_back(copy_script); - commandLines.push_back(std::move(currentLine)); + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), + cmStrCat("-DPDB_PREFIX=", pdb_prefix), "-P", copy_script }); const std::string no_main_dependency; const std::vector<std::string> no_deps; @@ -2423,16 +2538,14 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) pchReuseFrom, ".pdb")); if (this->GetGlobalGenerator()->IsMultiConfig()) { - this->Makefile->AddCustomCommandToTarget( + this->AddCustomCommandToTarget( target->GetName(), outputs, no_deps, commandLines, cmCustomCommandType::PRE_BUILD, no_message, no_current_dir); } else { cmImplicitDependsList no_implicit_depends; - cmSourceFile* copy_rule = - this->Makefile->AddCustomCommandToOutput( - outputs, no_byproducts, no_deps, no_main_dependency, - no_implicit_depends, commandLines, no_message, - no_current_dir); + cmSourceFile* copy_rule = this->AddCustomCommandToOutput( + outputs, no_byproducts, no_deps, no_main_dependency, + no_implicit_depends, commandLines, no_message, no_current_dir); if (copy_rule) { target->AddSource(copy_rule->ResolveFullPath()); @@ -2440,7 +2553,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) } target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", - target_compile_pdb_dir.c_str()); + target_compile_pdb_dir); } std::string pchSourceObj = @@ -2449,8 +2562,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) // Link to the pch object file target->Target->AppendProperty( "LINK_FLAGS", - cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)) - .c_str(), + cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)), true); } } else { @@ -2515,8 +2627,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) batchSize = filtered_sources.size(); } - for (size_t itemsLeft = filtered_sources.size(), chunk = batchSize, - batch = 0; + for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0; itemsLeft > 0; itemsLeft -= chunk, ++batch) { chunk = std::min(itemsLeft, batchSize); @@ -2900,8 +3011,8 @@ void cmLocalGenerator::GenerateTargetInstallRules( { // Convert the old-style install specification from each target to // an install generator and run it. - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); - for (cmGeneratorTarget* l : tgts) { + const auto& tgts = this->GetGeneratorTargets(); + for (const auto& l : tgts) { if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } @@ -3117,6 +3228,11 @@ bool cmLocalGenerator::IsNMake() const return this->GetState()->UseNMake(); } +bool cmLocalGenerator::IsNinjaMulti() const +{ + return this->GetState()->UseNinjaMulti(); +} + std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( const cmSourceFile& source, std::string const& dir_max, bool* hasSourceExtension, char const* customOutputExtension) @@ -3444,3 +3560,245 @@ void cmLocalGenerator::GenerateFrameworkInfoPList( cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION"); mf->ConfigureFile(inFile, fname, false, false, false); } + +namespace { +void CreateGeneratedSource(cmLocalGenerator& lg, const std::string& output, + cmCommandOrigin origin, + const cmListFileBacktrace& lfbt) +{ + if (cmGeneratorExpression::Find(output) == std::string::npos) { + // Outputs without generator expressions from the project are already + // created and marked as generated. Do not mark them again, because + // other commands might have overwritten the property. + if (origin == cmCommandOrigin::Generator) { + lg.GetMakefile()->GetOrCreateGeneratedSource(output); + } + } else { + lg.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "Generator expressions in custom command outputs are not implemented!", + lfbt); + } +} + +void CreateGeneratedSources(cmLocalGenerator& lg, + const std::vector<std::string>& outputs, + cmCommandOrigin origin, + const cmListFileBacktrace& lfbt) +{ + for (std::string const& o : outputs) { + CreateGeneratedSource(lg, o, origin, lfbt); + } +} + +cmSourceFile* AddCustomCommand( + cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool) +{ + cmMakefile* mf = lg.GetMakefile(); + + // Choose a source file on which to store the custom command. + cmSourceFile* file = nullptr; + if (!commandLines.empty() && !main_dependency.empty()) { + // The main dependency was specified. Use it unless a different + // custom command already used it. + file = mf->GetSource(main_dependency); + if (file && file->GetCustomCommand() && !replace) { + // The main dependency already has a custom command. + if (commandLines == file->GetCustomCommand()->GetCommandLines()) { + // The existing custom command is identical. Silently ignore + // the duplicate. + return file; + } + // The existing custom command is different. We need to + // generate a rule file for this new command. + file = nullptr; + } else if (!file) { + file = mf->CreateSource(main_dependency); + } + } + + // Generate a rule file if the main dependency is not available. + if (!file) { + cmGlobalGenerator* gg = lg.GetGlobalGenerator(); + + // Construct a rule file associated with the first output produced. + std::string outName = gg->GenerateRuleFile(outputs[0]); + + // Check if the rule file already exists. + file = mf->GetSource(outName, cmSourceFileLocationKind::Known); + if (file && file->GetCustomCommand() && !replace) { + // The rule file already exists. + if (commandLines != file->GetCustomCommand()->GetCommandLines()) { + lg.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Attempt to add a custom rule to output\n ", outName, + "\nwhich already has a custom rule."), + lfbt); + } + return file; + } + + // Create a cmSourceFile for the rule file. + if (!file) { + file = mf->CreateSource(outName, true, cmSourceFileLocationKind::Known); + } + file->SetProperty("__CMAKE_RULE", "1"); + } + + // Attach the custom command to the file. + if (file) { + // Construct a complete list of dependencies. + std::vector<std::string> depends2(depends); + if (!main_dependency.empty()) { + depends2.push_back(main_dependency); + } + + std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>( + outputs, byproducts, depends2, commandLines, lfbt, comment, workingDir); + cc->SetEscapeOldStyle(escapeOldStyle); + cc->SetEscapeAllowMakeVars(true); + cc->SetImplicitDepends(implicit_depends); + cc->SetUsesTerminal(uses_terminal); + cc->SetCommandExpandLists(command_expand_lists); + cc->SetDepfile(depfile); + cc->SetJobPool(job_pool); + file->SetCustomCommand(std::move(cc)); + + mf->AddSourceOutputs(file, outputs, byproducts); + } + return file; +} +} + +namespace detail { +void AddCustomCommandToTarget(cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, cmTarget* target, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, + cmCustomCommandType type, const char* comment, + const char* workingDir, bool escapeOldStyle, + bool uses_terminal, const std::string& depfile, + const std::string& job_pool, + bool command_expand_lists) +{ + cmMakefile* mf = lg.GetMakefile(); + + // Always create the byproduct sources and mark them generated. + CreateGeneratedSources(lg, byproducts, origin, lfbt); + + // Add the command to the appropriate build step for the target. + std::vector<std::string> no_output; + cmCustomCommand cc(no_output, byproducts, depends, commandLines, lfbt, + comment, workingDir); + cc.SetEscapeOldStyle(escapeOldStyle); + cc.SetEscapeAllowMakeVars(true); + cc.SetUsesTerminal(uses_terminal); + cc.SetCommandExpandLists(command_expand_lists); + cc.SetDepfile(depfile); + cc.SetJobPool(job_pool); + switch (type) { + case cmCustomCommandType::PRE_BUILD: + target->AddPreBuildCommand(std::move(cc)); + break; + case cmCustomCommandType::PRE_LINK: + target->AddPreLinkCommand(std::move(cc)); + break; + case cmCustomCommandType::POST_BUILD: + target->AddPostBuildCommand(std::move(cc)); + break; + } + + mf->AddTargetByproducts(target, byproducts); +} + +cmSourceFile* AddCustomCommandToOutput( + cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool) +{ + // Always create the output sources and mark them generated. + CreateGeneratedSources(lg, outputs, origin, lfbt); + CreateGeneratedSources(lg, byproducts, origin, lfbt); + + return AddCustomCommand( + lg, lfbt, outputs, byproducts, depends, main_dependency, implicit_depends, + commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal, + command_expand_lists, depfile, job_pool); +} + +void AppendCustomCommandToOutput(cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt, + const std::string& output, + const std::vector<std::string>& depends, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines) +{ + // Lookup an existing command. + if (cmSourceFile* sf = lg.GetMakefile()->GetSourceFileWithOutput(output)) { + if (cmCustomCommand* cc = sf->GetCustomCommand()) { + cc->AppendCommands(commandLines); + cc->AppendDepends(depends); + cc->AppendImplicitDepends(implicit_depends); + return; + } + } + + // No existing command found. + lg.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Attempt to append to output\n ", output, + "\nwhich is not already a custom command output."), + lfbt); +} + +void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, cmTarget* target, + const cmUtilityOutput& force, const char* workingDir, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, + bool escapeOldStyle, const char* comment, + bool uses_terminal, bool command_expand_lists, + const std::string& job_pool) +{ + // Always create the byproduct sources and mark them generated. + CreateGeneratedSource(lg, force.Name, origin, lfbt); + CreateGeneratedSources(lg, byproducts, origin, lfbt); + + // Use an empty comment to avoid generation of default comment. + if (!comment) { + comment = ""; + } + + std::string no_main_dependency; + cmImplicitDependsList no_implicit_depends; + cmSourceFile* rule = AddCustomCommand( + lg, lfbt, { force.Name }, byproducts, depends, no_main_dependency, + no_implicit_depends, commandLines, comment, workingDir, /*replace=*/false, + escapeOldStyle, uses_terminal, command_expand_lists, /*depfile=*/"", + job_pool); + if (rule) { + lg.GetMakefile()->AddTargetByproducts(target, byproducts); + } + + if (!force.NameCMP0049.empty()) { + target->AddSource(force.NameCMP0049); + } +} +} diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 12359dbddd..b91d5f7d14 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -7,6 +7,7 @@ #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -14,6 +15,7 @@ #include "cm_kwiml.h" +#include "cmCustomCommandTypes.h" #include "cmListFileCache.h" #include "cmMessageType.h" #include "cmOutputConverter.h" @@ -22,13 +24,16 @@ class cmComputeLinkInformation; class cmCustomCommandGenerator; +class cmCustomCommandLines; class cmGeneratorTarget; class cmGlobalGenerator; +class cmImplicitDependsList; class cmLinkLineComputer; class cmMakefile; class cmRulePlaceholderExpander; class cmSourceFile; class cmState; +class cmTarget; class cmake; /** \class cmLocalGenerator @@ -143,14 +148,16 @@ public: bool forResponseFile = false, const std::string& config = ""); - const std::vector<cmGeneratorTarget*>& GetGeneratorTargets() const + using GeneratorTargetVector = + std::vector<std::unique_ptr<cmGeneratorTarget>>; + const GeneratorTargetVector& GetGeneratorTargets() const { return this->GeneratorTargets; } - void AddGeneratorTarget(cmGeneratorTarget* gt); + void AddGeneratorTarget(std::unique_ptr<cmGeneratorTarget> gt); void AddImportedGeneratorTarget(cmGeneratorTarget* gt); - void AddOwnedImportedGeneratorTarget(cmGeneratorTarget* gt); + void AddOwnedImportedGeneratorTarget(std::unique_ptr<cmGeneratorTarget> gt); cmGeneratorTarget* FindLocalNonAliasGeneratorTarget( const std::string& name) const; @@ -292,6 +299,51 @@ public: cmGeneratorTarget* target, const std::string& lang, const std::string& config); + /** + * Add a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a target. + */ + cmTarget* AddCustomCommandToTarget( + const std::string& target, const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, cmCustomCommandType type, + const char* comment, const char* workingDir, bool escapeOldStyle = true, + bool uses_terminal = false, const std::string& depfile = "", + const std::string& job_pool = "", bool command_expand_lists = false, + cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject); + + /** + * Add a custom command to a source file. + */ + cmSourceFile* AddCustomCommandToOutput( + const std::string& output, const std::vector<std::string>& depends, + const std::string& main_dependency, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace = false, bool escapeOldStyle = true, + bool uses_terminal = false, bool command_expand_lists = false, + const std::string& depfile = "", const std::string& job_pool = ""); + cmSourceFile* AddCustomCommandToOutput( + const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace = false, bool escapeOldStyle = true, + bool uses_terminal = false, bool command_expand_lists = false, + const std::string& depfile = "", const std::string& job_pool = ""); + + /** + * Add a utility to the build. A utility target is a command that is run + * every time the target is built. + */ + cmTarget* AddUtilityCommand( + const std::string& utilityName, bool excludeFromAll, + const char* workingDir, const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, bool escapeOldStyle = true, + const char* comment = nullptr, bool uses_terminal = false, + bool command_expand_lists = false, const std::string& job_pool = ""); + std::string GetProjectName() const; /** Compute the language used to compile the given source file. */ @@ -414,6 +466,7 @@ public: bool IsWatcomWMake() const; bool IsMinGWMake() const; bool IsNMake() const; + bool IsNinjaMulti() const; void IssueMessage(MessageType t, std::string const& text) const; @@ -461,11 +514,11 @@ protected: using GeneratorTargetMap = std::unordered_map<std::string, cmGeneratorTarget*>; GeneratorTargetMap GeneratorTargetSearchIndex; - std::vector<cmGeneratorTarget*> GeneratorTargets; + GeneratorTargetVector GeneratorTargets; std::set<cmGeneratorTarget const*> WarnCMP0063; GeneratorTargetMap ImportedGeneratorTargets; - std::vector<cmGeneratorTarget*> OwnedImportedGeneratorTargets; + GeneratorTargetVector OwnedImportedGeneratorTargets; std::map<std::string, std::string> AliasTargets; std::map<std::string, std::string> Compilers; @@ -494,4 +547,46 @@ bool cmLocalGeneratorCheckObjectName(std::string& objName, std::string::size_type max_total_len); #endif +namespace detail { +void AddCustomCommandToTarget(cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, cmTarget* target, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, + cmCustomCommandType type, const char* comment, + const char* workingDir, bool escapeOldStyle, + bool uses_terminal, const std::string& depfile, + const std::string& job_pool, + bool command_expand_lists); + +cmSourceFile* AddCustomCommandToOutput( + cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool); + +void AppendCustomCommandToOutput(cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt, + const std::string& output, + const std::vector<std::string>& depends, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines); + +void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, cmTarget* target, + const cmUtilityOutput& force, const char* workingDir, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, + bool escapeOldStyle, const char* comment, + bool uses_terminal, bool command_expand_lists, + const std::string& job_pool); +} + #endif diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index 4b10798e1f..098fa5a577 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -5,6 +5,8 @@ #include <algorithm> #include <utility> +#include <cmext/algorithm> + #include "cmGeneratorTarget.h" #include "cmGhsMultiTargetGenerator.h" #include "cmGlobalGenerator.h" @@ -50,10 +52,11 @@ void cmLocalGhsMultiGenerator::GenerateTargetsDepthFirst( void cmLocalGhsMultiGenerator::Generate() { - std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets(); + std::vector<cmGeneratorTarget*> remaining; + cm::append(remaining, this->GetGeneratorTargets()); for (auto& t : remaining) { if (t) { - GenerateTargetsDepthFirst(t, remaining); + this->GenerateTargetsDepthFirst(t, remaining); } } } diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 134bbe18af..69670975b9 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -29,6 +29,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" #include "cmake.h" cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, @@ -61,7 +62,12 @@ void cmLocalNinjaGenerator::Generate() this->HomeRelativeOutputPath.clear(); } - this->WriteProcessedMakefile(this->GetBuildFileStream()); + if (this->GetGlobalGenerator()->IsMultiConfig()) { + for (auto const& config : this->GetConfigNames()) { + this->WriteProcessedMakefile(this->GetConfigFileStream(config)); + } + } + this->WriteProcessedMakefile(this->GetCommonFileStream()); #ifdef NINJA_GEN_VERBOSE_FILES this->WriteProcessedMakefile(this->GetRulesFileStream()); #endif @@ -82,18 +88,26 @@ void cmLocalNinjaGenerator::Generate() } } - for (cmGeneratorTarget* target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - auto tg = cmNinjaTargetGenerator::New(target); + auto tg = cmNinjaTargetGenerator::New(target.get()); if (tg) { - tg->Generate(); + if (target->Target->IsPerConfig()) { + for (auto const& config : this->GetConfigNames()) { + tg->Generate(config); + } + } else { + tg->Generate(""); + } } } - this->WriteCustomCommandBuildStatements(); - this->AdditionalCleanFiles(); + for (auto const& config : this->GetConfigNames()) { + this->WriteCustomCommandBuildStatements(config); + this->AdditionalCleanFiles(config); + } } // TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it. @@ -140,9 +154,15 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference( // Private methods. -cmGeneratedFileStream& cmLocalNinjaGenerator::GetBuildFileStream() const +cmGeneratedFileStream& cmLocalNinjaGenerator::GetConfigFileStream( + const std::string& config) const { - return *this->GetGlobalNinjaGenerator()->GetBuildFileStream(); + return *this->GetGlobalNinjaGenerator()->GetConfigFileStream(config); +} + +cmGeneratedFileStream& cmLocalNinjaGenerator::GetCommonFileStream() const +{ + return *this->GetGlobalNinjaGenerator()->GetCommonFileStream(); } cmGeneratedFileStream& cmLocalNinjaGenerator::GetRulesFileStream() const @@ -162,10 +182,22 @@ cmake* cmLocalNinjaGenerator::GetCMakeInstance() void cmLocalNinjaGenerator::WriteBuildFileTop() { - // For the build file. - this->WriteProjectHeader(this->GetBuildFileStream()); - this->WriteNinjaRequiredVersion(this->GetBuildFileStream()); - this->WriteNinjaFilesInclusion(this->GetBuildFileStream()); + this->WriteProjectHeader(this->GetCommonFileStream()); + + if (this->GetGlobalGenerator()->IsMultiConfig()) { + for (auto const& config : this->GetConfigNames()) { + auto& stream = this->GetConfigFileStream(config); + this->WriteProjectHeader(stream); + this->WriteNinjaRequiredVersion(stream); + this->WriteNinjaConfigurationVariable(stream, config); + this->WriteNinjaFilesInclusionConfig(stream); + } + } else { + this->WriteNinjaRequiredVersion(this->GetCommonFileStream()); + this->WriteNinjaConfigurationVariable(this->GetCommonFileStream(), + this->GetConfigNames().front()); + } + this->WriteNinjaFilesInclusionCommon(this->GetCommonFileStream()); // For the rule file. this->WriteProjectHeader(this->GetRulesFileStream()); @@ -175,7 +207,8 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); os << "# Project: " << this->GetProjectName() << std::endl - << "# Configuration: " << this->ConfigName << std::endl; + << "# Configurations: " << cmJoin(this->GetConfigNames(), ", ") + << std::endl; cmGlobalNinjaGenerator::WriteDivider(os); } @@ -206,6 +239,14 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) << std::endl; } +void cmLocalNinjaGenerator::WriteNinjaConfigurationVariable( + std::ostream& os, const std::string& config) +{ + cmGlobalNinjaGenerator::WriteVariable( + os, "CONFIGURATION", config, + "Set configuration variable for custom commands."); +} + void cmLocalNinjaGenerator::WritePools(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); @@ -235,7 +276,21 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) } } -void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os) +void cmLocalNinjaGenerator::WriteNinjaFilesInclusionConfig(std::ostream& os) +{ + cmGlobalNinjaGenerator::WriteDivider(os); + os << "# Include auxiliary files.\n" + << "\n"; + cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator(); + std::string const ninjaCommonFile = + ng->NinjaOutputPath(cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE); + std::string const commonFilePath = ng->EncodePath(ninjaCommonFile); + cmGlobalNinjaGenerator::WriteInclude(os, commonFilePath, + "Include common file."); + os << "\n"; +} + +void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); os << "# Include auxiliary files.\n" @@ -263,25 +318,30 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) } void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target, - cmNinjaDeps& outputs) + cmNinjaDeps& outputs, + const std::string& config) { - this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs); + this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs, + config); } void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs, + const std::string& config, + const std::string& fileConfig, cmNinjaTargetDepends depends) { - this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, - depends); + this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, config, + fileConfig, depends); } void cmLocalNinjaGenerator::AppendCustomCommandDeps( - cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps) + cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps, + const std::string& config) { for (std::string const& i : ccg.GetDepends()) { std::string dep; - if (this->GetRealDependency(i, this->GetConfigName(), dep)) { + if (this->GetRealDependency(i, config, dep)) { ninjaDeps.push_back( this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep)); } @@ -416,6 +476,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( void cmLocalNinjaGenerator::AppendCustomCommandLines( cmCustomCommandGenerator const& ccg, std::vector<std::string>& cmdLines) { + auto* gg = this->GetGlobalNinjaGenerator(); + if (ccg.GetNumberOfCommands() > 0) { std::string wd = ccg.GetWorkingDirectory(); if (wd.empty()) { @@ -437,8 +499,10 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines( for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) { cmdLines.push_back(launcher + - this->ConvertToOutputFormat(ccg.GetCommand(i), - cmOutputConverter::SHELL)); + this->ConvertToOutputFormat( + ccg.GetCommand(i), + gg->IsMultiConfig() ? cmOutputConverter::NINJAMULTI + : cmOutputConverter::SHELL)); std::string& cmd = cmdLines.back(); ccg.AppendArguments(i, cmd); @@ -446,14 +510,15 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines( } void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( - cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps) + cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps, + const std::string& config) { cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator(); - if (gg->SeenCustomCommand(cc)) { + if (gg->SeenCustomCommand(cc, config)) { return; } - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this); + cmCustomCommandGenerator ccg(*cc, config, this); const std::vector<std::string>& outputs = ccg.GetOutputs(); const std::vector<std::string>& byproducts = ccg.GetByproducts(); @@ -484,7 +549,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( } cmNinjaDeps ninjaDeps; - this->AppendCustomCommandDeps(ccg, ninjaDeps); + this->AppendCustomCommandDeps(ccg, ninjaDeps, config); std::vector<std::string> cmdLines; this->AppendCustomCommandLines(ccg, cmdLines); @@ -495,7 +560,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( build.Outputs = std::move(ninjaOutputs); build.ExplicitDeps = std::move(ninjaDeps); build.OrderOnlyDeps = orderOnlyDeps; - gg->WriteBuild(this->GetBuildFileStream(), build); + gg->WriteBuild(this->GetConfigFileStream(config), build); } else { std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]); // Hash full path to make unique. @@ -507,8 +572,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( this->BuildCommandLine(cmdLines, customStep), this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(), - /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps, - orderOnlyDeps); + /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config, + ninjaDeps, orderOnlyDeps); } } @@ -524,7 +589,8 @@ void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc, ins.first->second.insert(target); } -void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() +void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements( + const std::string& config) { for (cmCustomCommand const* customCommand : this->CustomCommands) { auto i = this->CustomCommandTargets.find(customCommand); @@ -542,15 +608,16 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() auto j = i->second.begin(); assert(j != i->second.end()); std::vector<std::string> ccTargetDeps; - this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, - ccTargetDeps); + this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure( + *j, ccTargetDeps, config); std::sort(ccTargetDeps.begin(), ccTargetDeps.end()); ++j; for (; j != i->second.end(); ++j) { std::vector<std::string> jDeps; std::vector<std::string> depsIntersection; - this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps); + this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps, + config); std::sort(jDeps.begin(), jDeps.end()); std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(), jDeps.begin(), jDeps.end(), @@ -558,7 +625,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() ccTargetDeps = depsIntersection; } - this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps); + this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps, config); } } @@ -599,15 +666,13 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( return launcher; } -void cmLocalNinjaGenerator::AdditionalCleanFiles() +void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config) { if (const char* prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { std::vector<std::string> cleanFiles; { - cmExpandList(cmGeneratorExpression::Evaluate( - prop_value, this, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), + cmExpandList(cmGeneratorExpression::Evaluate(prop_value, this, config), cleanFiles); } std::string const& binaryDir = this->GetCurrentBinaryDirectory(); @@ -615,7 +680,7 @@ void cmLocalNinjaGenerator::AdditionalCleanFiles() for (std::string const& cleanFile : cleanFiles) { // Support relative paths gg->AddAdditionalCleanFile( - cmSystemTools::CollapseFullPath(cleanFile, binaryDir)); + cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config); } } } diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index f64534ce11..0445879c7f 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -64,9 +64,11 @@ public: std::string const& customStep = std::string(), cmGeneratorTarget const* target = nullptr) const; - void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs); + void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs, + const std::string& config); void AppendTargetDepends( - cmGeneratorTarget* target, cmNinjaDeps& outputs, + cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config, + const std::string& fileConfig, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AddCustomCommandTarget(cmCustomCommand const* cc, @@ -74,7 +76,8 @@ public: void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg, std::vector<std::string>& cmdLines); void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg, - cmNinjaDeps& ninjaDeps); + cmNinjaDeps& ninjaDeps, + const std::string& config); protected: std::string ConvertToIncludeReference( @@ -83,20 +86,25 @@ protected: bool forceFullPaths = false) override; private: - cmGeneratedFileStream& GetBuildFileStream() const; + cmGeneratedFileStream& GetConfigFileStream(const std::string& config) const; + cmGeneratedFileStream& GetCommonFileStream() const; cmGeneratedFileStream& GetRulesFileStream() const; void WriteBuildFileTop(); void WriteProjectHeader(std::ostream& os); void WriteNinjaRequiredVersion(std::ostream& os); - void WriteNinjaFilesInclusion(std::ostream& os); + void WriteNinjaConfigurationVariable(std::ostream& os, + const std::string& config); + void WriteNinjaFilesInclusionConfig(std::ostream& os); + void WriteNinjaFilesInclusionCommon(std::ostream& os); void WriteProcessedMakefile(std::ostream& os); void WritePools(std::ostream& os); void WriteCustomCommandBuildStatement(cmCustomCommand const* cc, - const cmNinjaDeps& orderOnlyDeps); + const cmNinjaDeps& orderOnlyDeps, + const std::string& config); - void WriteCustomCommandBuildStatements(); + void WriteCustomCommandBuildStatements(const std::string& config); std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg); @@ -104,7 +112,7 @@ private: std::string const& customStep, cmGeneratorTarget const* target) const; - void AdditionalCleanFiles(); + void AdditionalCleanFiles(const std::string& config); std::string HomeRelativeOutputPath; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 4a70248d6f..dbdde486ad 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -3,16 +3,18 @@ #include "cmLocalUnixMakefileGenerator3.h" #include <algorithm> +#include <cassert> #include <cstdio> #include <sstream> #include <utility> #include <cm/memory> +#include <cm/vector> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/Terminal.h" -#include "cmAlgorithms.h" #include "cmCustomCommand.h" // IWYU pragma: keep #include "cmCustomCommandGenerator.h" #include "cmFileTimeCache.h" @@ -106,6 +108,13 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3( cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() = default; +std::string cmLocalUnixMakefileGenerator3::GetConfigName() const +{ + auto const& configNames = this->GetConfigNames(); + assert(configNames.size() == 1); + return configNames.front(); +} + void cmLocalUnixMakefileGenerator3::Generate() { // Record whether some options are enabled to avoid checking many @@ -121,12 +130,12 @@ void cmLocalUnixMakefileGenerator3::Generate() // Generate the rule files for each target. cmGlobalUnixMakefileGenerator3* gg = static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator); - for (cmGeneratorTarget* target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } std::unique_ptr<cmMakefileTargetGenerator> tg( - cmMakefileTargetGenerator::New(target)); + cmMakefileTargetGenerator::New(target.get())); if (tg) { tg->WriteRuleFiles(); gg->RecordTargetProgress(tg.get()); @@ -157,15 +166,15 @@ void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath() void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles( std::map<std::string, LocalObjectInfo>& localObjectFiles) { - for (cmGeneratorTarget* gt : this->GetGeneratorTargets()) { + for (const auto& gt : this->GetGeneratorTargets()) { if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } std::vector<cmSourceFile const*> objectSources; - gt->GetObjectSources(objectSources, this->ConfigName); + gt->GetObjectSources(objectSources, this->GetConfigName()); // Compute full path to object file directory for this target. std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), - '/', this->GetTargetDirectory(gt), '/'); + '/', this->GetTargetDirectory(gt.get()), '/'); // Compute the name of each object file. for (cmSourceFile const* sf : objectSources) { bool hasSourceExtension = true; @@ -176,7 +185,7 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles( } LocalObjectInfo& info = localObjectFiles[objectName]; info.HasSourceExtension = hasSourceExtension; - info.emplace_back(gt, sf->GetLanguage()); + info.emplace_back(gt.get(), sf->GetLanguage()); } } } @@ -352,7 +361,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( // for each target we just provide a rule to cd up to the top and do a make // on the target std::string localName; - for (cmGeneratorTarget* target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { if ((target->GetType() == cmStateEnums::EXECUTABLE) || (target->GetType() == cmStateEnums::STATIC_LIBRARY) || (target->GetType() == cmStateEnums::SHARED_LIBRARY) || @@ -362,7 +371,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( emitted.insert(target->GetName()); // for subdirs add a rule to build this specific target by name. - localName = cmStrCat(this->GetRelativeTargetDirectory(target), "/rule"); + localName = + cmStrCat(this->GetRelativeTargetDirectory(target.get()), "/rule"); commands.clear(); depends.clear(); @@ -383,11 +393,11 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( } // Add a fast rule to build the target - std::string makefileName = - cmStrCat(this->GetRelativeTargetDirectory(target), "/build.make"); + std::string makefileName = cmStrCat( + this->GetRelativeTargetDirectory(target.get()), "/build.make"); // make sure the makefile name is suitable for a makefile std::string makeTargetName = - cmStrCat(this->GetRelativeTargetDirectory(target), "/build"); + cmStrCat(this->GetRelativeTargetDirectory(target.get()), "/build"); localName = cmStrCat(target->GetName(), "/fast"); depends.clear(); commands.clear(); @@ -400,9 +410,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( // Add a local name for the rule to relink the target before // installation. - if (target->NeedRelinkBeforeInstall(this->ConfigName)) { - makeTargetName = - cmStrCat(this->GetRelativeTargetDirectory(target), "/preinstall"); + if (target->NeedRelinkBeforeInstall(this->GetConfigName())) { + makeTargetName = cmStrCat( + this->GetRelativeTargetDirectory(target.get()), "/preinstall"); localName = cmStrCat(target->GetName(), "/preinstall"); depends.clear(); commands.clear(); @@ -628,7 +638,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeVariables( << "# The command to remove a file.\n" << "RM = " << cmakeShellCommand - << " -E remove -f\n" + << " -E rm -f\n" << "\n"; makefileStream << "# Escaping for special characters.\n" @@ -849,7 +859,7 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepends( // Add a dependency on the rule file itself unless an option to skip // it is specifically enabled by the user or project. if (!this->Makefile->IsOn("CMAKE_SKIP_RULE_DEPENDENCY")) { - cmAppend(depends, ruleFiles); + cm::append(depends, ruleFiles); } } @@ -857,7 +867,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepends( std::vector<std::string>& depends, const std::vector<cmCustomCommand>& ccs) { for (cmCustomCommand const& cc : ccs) { - cmCustomCommandGenerator ccg(cc, this->ConfigName, this); + cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this); this->AppendCustomDepend(depends, ccg); } } @@ -868,7 +878,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepend( for (std::string const& d : ccg.GetDepends()) { // Lookup the real name of the dependency in case it is a CMake target. std::string dep; - if (this->GetRealDependency(d, this->ConfigName, dep)) { + if (this->GetRealDependency(d, this->GetConfigName(), dep)) { depends.push_back(std::move(dep)); } } @@ -879,7 +889,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommands( cmGeneratorTarget* target, std::string const& relative) { for (cmCustomCommand const& cc : ccs) { - cmCustomCommandGenerator ccg(cc, this->ConfigName, this); + cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this); this->AppendCustomCommand(commands, ccg, target, relative, true); } } @@ -1022,7 +1032,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( this->CreateCDCommand(commands1, dir, relative); // push back the custom commands - cmAppend(commands, commands1); + cm::append(commands, commands1); } void cmLocalUnixMakefileGenerator3::AppendCleanCommand( @@ -1093,8 +1103,7 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( return; } - cmLocalGenerator* rootLG = - this->GetGlobalGenerator()->GetLocalGenerators().at(0); + const auto& rootLG = this->GetGlobalGenerator()->GetLocalGenerators().at(0); std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory(); std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory(); std::string cleanfile = @@ -1551,8 +1560,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( this->WriteDivider(ruleFileStream); ruleFileStream << "# Targets provided globally by CMake.\n" << "\n"; - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (cmGeneratorTarget* gt : targets) { + const auto& targets = this->GetGeneratorTargets(); + for (const auto& gt : targets) { if (gt->GetType() == cmStateEnums::GLOBAL_TARGET) { std::string targetString = "Special rule for the target " + gt->GetName(); @@ -1573,10 +1582,10 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( // Global targets store their rules in pre- and post-build commands. this->AppendCustomDepends(depends, gt->GetPreBuildCommands()); this->AppendCustomDepends(depends, gt->GetPostBuildCommands()); - this->AppendCustomCommands(commands, gt->GetPreBuildCommands(), gt, - this->GetCurrentBinaryDirectory()); - this->AppendCustomCommands(commands, gt->GetPostBuildCommands(), gt, + this->AppendCustomCommands(commands, gt->GetPreBuildCommands(), gt.get(), this->GetCurrentBinaryDirectory()); + this->AppendCustomCommands(commands, gt->GetPostBuildCommands(), + gt.get(), this->GetCurrentBinaryDirectory()); std::string targetName = gt->GetName(); this->WriteMakeRule(ruleFileStream, targetString.c_str(), targetName, depends, commands, true); @@ -1839,7 +1848,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( // Build a list of preprocessor definitions for the target. std::set<std::string> defines; - this->GetTargetDefines(target, this->ConfigName, implicitLang.first, + this->GetTargetDefines(target, this->GetConfigName(), implicitLang.first, defines); if (!defines.empty()) { /* clang-format off */ @@ -1863,11 +1872,11 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( std::vector<std::string> includes; this->GetIncludeDirectories(includes, target, implicitLang.first, - this->ConfigName); + this->GetConfigName()); std::string binaryDir = this->GetState()->GetBinaryDirectory(); if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) { std::string const& sourceDir = this->GetState()->GetSourceDirectory(); - cmEraseIf(includes, ::NotInProjectDir(sourceDir, binaryDir)); + cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir)); } for (std::string const& include : includes) { cmakefileStream << " \"" diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index f12ae8b161..1629e638d6 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -33,6 +33,8 @@ public: cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf); ~cmLocalUnixMakefileGenerator3() override; + std::string GetConfigName() const; + void ComputeHomeRelativeOutputPath() override; /** diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index f3d828b28e..6f456c640a 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -2,8 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalVisualStudio10Generator.h" +#include <cmext/algorithm> + #include "cm_expat.h" +#include "cmAlgorithms.h" #include "cmGeneratorTarget.h" #include "cmGlobalVisualStudio10Generator.h" #include "cmMakefile.h" @@ -101,10 +104,11 @@ void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst( void cmLocalVisualStudio10Generator::Generate() { - std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets(); + std::vector<cmGeneratorTarget*> remaining; + cm::append(remaining, this->GetGeneratorTargets()); for (auto& t : remaining) { if (t) { - GenerateTargetsDepthFirst(t, remaining); + this->GenerateTargetsDepthFirst(t, remaining); } } this->WriteStampFiles(); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index f19549d7bc..55a9a72cb1 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -64,8 +64,8 @@ cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() void cmLocalVisualStudio7Generator::AddHelperCommands() { // Now create GUIDs for targets - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); - for (cmGeneratorTarget const* l : tgts) { + const auto& tgts = this->GetGeneratorTargets(); + for (const auto& l : tgts) { if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } @@ -89,8 +89,8 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() // Visual Studio .NET 2003 Service Pack 1 will not run post-build // commands for targets in which no sources are built. Add dummy // rules to force these targets to build. - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); - for (cmGeneratorTarget* l : tgts) { + const auto& tgts = this->GetGeneratorTargets(); + for (auto& l : tgts) { if (l->GetType() == cmStateEnums::GLOBAL_TARGET) { std::vector<std::string> no_depends; cmCustomCommandLines force_commands = @@ -102,9 +102,9 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() this->Makefile->GetOrCreateGeneratedSource(force)) { sf->SetProperty("SYMBOLIC", "1"); } - if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput( - force.c_str(), no_depends, no_main_dependency, force_commands, " ", - 0, true)) { + if (cmSourceFile* file = this->AddCustomCommandToOutput( + force, no_depends, no_main_dependency, force_commands, " ", + nullptr, true)) { l->AddSource(file->ResolveFullPath()); } } @@ -125,17 +125,17 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles() } // Get the set of targets in this directory. - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); + const auto& tgts = this->GetGeneratorTargets(); // Create the project file for each target. - for (cmGeneratorTarget* l : tgts) { + for (const auto& l : tgts) { if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace // so don't build a projectfile for it if (!l->GetProperty("EXTERNAL_MSPROJECT")) { - this->CreateSingleVCProj(l->GetName(), l); + this->CreateSingleVCProj(l->GetName(), l.get()); } } } @@ -194,7 +194,7 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj( } // add to the list of projects - target->Target->SetProperty("GENERATOR_FILE_NAME", lname.c_str()); + target->Target->SetProperty("GENERATOR_FILE_NAME", lname); // create the dsp.cmake file std::string fname; fname = cmStrCat(this->GetCurrentBinaryDirectory(), '/', lname); @@ -259,9 +259,9 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() const char* no_working_directory = nullptr; std::string fullpathStampName = cmSystemTools::CollapseFullPath(stampName.c_str()); - this->Makefile->AddCustomCommandToOutput( - fullpathStampName, listFiles, makefileIn, commandLines, comment.c_str(), - no_working_directory, true, false); + this->AddCustomCommandToOutput(fullpathStampName, listFiles, makefileIn, + commandLines, comment.c_str(), + no_working_directory, true, false); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) { // Finalize the source file path now since we're adding this after // the generator validated all project-named sources. @@ -1337,7 +1337,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // Add CMakeLists.txt file with rule to re-run CMake for user convenience. if (target->GetType() != cmStateEnums::GLOBAL_TARGET && target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { - if (cmSourceFile const* sf = this->CreateVCProjBuildRule()) { + if (cmSourceFile* sf = this->CreateVCProjBuildRule()) { cmGeneratorTarget::AllConfigSource acs; acs.Source = sf; acs.Kind = cmGeneratorTarget::SourceKindCustomCommand; @@ -2061,7 +2061,7 @@ std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPathSingle( } void cmVS7GeneratorOptions::OutputFlag(std::ostream& fout, int indent, - const char* flag, + const std::string& flag, const std::string& content) { fout.fill('\t'); diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 671783fa53..22a5f9ab4b 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -30,7 +30,7 @@ public: : cmVisualStudioGeneratorOptions(lg, tool, table, extraTable) { } - void OutputFlag(std::ostream& fout, int indent, const char* tag, + void OutputFlag(std::ostream& fout, int indent, const std::string& tag, const std::string& content) override; }; diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 336e3a5a17..8d508980e1 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -104,8 +104,8 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target, std::vector<std::string> no_depends; cmCustomCommandLines commands = cmMakeSingleCommandLine( { cmSystemTools::GetCMakeCommand(), "-E", "make_directory", impDir }); - pcc.reset(new cmCustomCommand(0, no_output, no_byproducts, no_depends, - commands, 0, 0)); + pcc.reset(new cmCustomCommand(no_output, no_byproducts, no_depends, commands, + cmListFileBacktrace(), nullptr, nullptr)); pcc->SetEscapeOldStyle(false); pcc->SetEscapeAllowMakeVars(true); return pcc; diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 5a06d4a53b..ac0d35ea88 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -40,7 +40,7 @@ void cmLocalXCodeGenerator::Generate() { cmLocalGenerator::Generate(); - for (auto target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { target->HasMacOSXRpathInstallNameDir(""); } } @@ -49,7 +49,7 @@ void cmLocalXCodeGenerator::GenerateInstallRules() { cmLocalGenerator::GenerateInstallRules(); - for (auto target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { target->HasMacOSXRpathInstallNameDir(""); } } diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index ba9947a335..a35dc20428 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -7,10 +7,10 @@ #include <cm/memory> #include <cm/string_view> +#include <cmext/algorithm> #include "cm_static_string_view.hxx" -#include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmFunctionBlocker.h" #include "cmListFileCache.h" @@ -190,7 +190,7 @@ bool cmMacroCommand(std::vector<std::string> const& args, // create a function blocker { auto fb = cm::make_unique<cmMacroFunctionBlocker>(); - cmAppend(fb->Args, args); + cm::append(fb->Args, args); status.GetMakefile().AddFunctionBlocker(std::move(fb)); } return true; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f143ef704f..7435e47964 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -7,6 +7,7 @@ #include <algorithm> #include <cassert> #include <cctype> +#include <cstdint> #include <cstdio> #include <cstdlib> #include <cstring> @@ -15,10 +16,15 @@ #include <cm/iterator> #include <cm/memory> +#include <cm/optional> +#include <cm/vector> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" #include "cm_sys_stat.h" #include "cmAlgorithms.h" @@ -36,6 +42,7 @@ #include "cmInstallGenerator.h" // IWYU pragma: keep #include "cmInstallSubdirectoryGenerator.h" #include "cmListFileCache.h" +#include "cmLocalGenerator.h" #include "cmMessageType.h" #include "cmRange.h" #include "cmSourceFile.h" @@ -133,7 +140,7 @@ cmDirectoryId cmMakefile::GetDirectoryId() const // If we ever need to expose this to CMake language code we should // add a read-only property in cmMakefile::GetProperty. char buf[32]; - sprintf(buf, "<%p>", + sprintf(buf, "(%p)", static_cast<void const*>(this)); // cast avoids format warning return std::string(buf); } @@ -146,7 +153,7 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text) const this->ExecutionStatusStack.back()->SetNestedError(); } } - this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace()); + this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace); } bool cmMakefile::CheckCMP0037(std::string const& targetName, @@ -313,21 +320,51 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const } std::ostringstream msg; - msg << full_path << "(" << lff.Line << "): "; - msg << lff.Name.Original << "("; - bool expand = this->GetCMakeInstance()->GetTraceExpand(); + std::vector<std::string> args; std::string temp; + bool expand = this->GetCMakeInstance()->GetTraceExpand(); + + args.reserve(lff.Arguments.size()); for (cmListFileArgument const& arg : lff.Arguments) { if (expand) { temp = arg.Value; this->ExpandVariablesInString(temp); - msg << temp; + args.push_back(temp); } else { - msg << arg.Value; + args.push_back(arg.Value); + } + } + + switch (this->GetCMakeInstance()->GetTraceFormat()) { + case cmake::TraceFormat::TRACE_JSON_V1: { +#ifndef CMAKE_BOOTSTRAP + Json::Value val; + Json::StreamWriterBuilder builder; + builder["indentation"] = ""; + val["file"] = full_path; + val["line"] = static_cast<std::int64_t>(lff.Line); + val["cmd"] = lff.Name.Original; + val["args"] = Json::Value(Json::arrayValue); + for (std::string const& arg : args) { + val["args"].append(arg); + } + msg << Json::writeString(builder, val); +#endif + break; } - msg << " "; + case cmake::TraceFormat::TRACE_HUMAN: + msg << full_path << "(" << lff.Line << "): "; + msg << lff.Name.Original << "("; + + for (std::string const& arg : args) { + msg << arg << " "; + } + msg << ")"; + break; + case cmake::TraceFormat::TRACE_UNDEFINED: + msg << "INTERNAL ERROR: Trace format is TRACE_UNDEFINED"; + break; } - msg << ")"; auto& f = this->GetCMakeInstance()->GetTraceFile(); if (f) { @@ -780,38 +817,42 @@ struct file_not_persistent }; } -void cmMakefile::AddFinalAction(FinalAction action) +void cmMakefile::AddGeneratorAction(GeneratorAction action) { - this->FinalActions.push_back(std::move(action)); + assert(!this->GeneratorActionsInvoked); + this->GeneratorActions.emplace_back(std::move(action), this->Backtrace); } -void cmMakefile::FinalPass() +void cmMakefile::DoGenerate(cmLocalGenerator& lg) { // do all the variable expansions here this->ExpandVariablesCMP0019(); // give all the commands a chance to do something // after the file has been parsed before generation - for (FinalAction& action : this->FinalActions) { - action(*this); + for (const BT<GeneratorAction>& action : this->GeneratorActions) { + action.Value(lg, action.Backtrace); } + this->GeneratorActionsInvoked = true; + this->DelayedOutputFiles.clear(); + this->DelayedOutputFilesHaveGenex = false; // go through all configured files and see which ones still exist. // we don't want cmake to re-run if a configured file is created and deleted // during processing as that would make it a transient file that can't // influence the build process - cmEraseIf(this->OutputFiles, file_not_persistent()); + cm::erase_if(this->OutputFiles, file_not_persistent()); // if a configured file is used as input for another configured file, // and then deleted it will show up in the input list files so we // need to scan those too - cmEraseIf(this->ListFiles, file_not_persistent()); + cm::erase_if(this->ListFiles, file_not_persistent()); } // Generate the output file -void cmMakefile::ConfigureFinalPass() +void cmMakefile::Generate(cmLocalGenerator& lg) { - this->FinalPass(); + this->DoGenerate(lg); const char* oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); if (oldValue && cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) { @@ -825,6 +866,39 @@ void cmMakefile::ConfigureFinalPass() } } +namespace { +// There are still too many implicit backtraces through cmMakefile. As a +// workaround we reset the backtrace temporarily. +struct BacktraceGuard +{ + BacktraceGuard(cmListFileBacktrace& lfbt, cmListFileBacktrace current) + : Backtrace(lfbt) + , Previous(lfbt) + { + this->Backtrace = std::move(current); + } + + ~BacktraceGuard() { this->Backtrace = std::move(Previous); } + +private: + cmListFileBacktrace& Backtrace; + cmListFileBacktrace Previous; +}; + +cm::optional<std::string> MakeOptionalString(const char* str) +{ + if (str) { + return str; + } + return cm::nullopt; +} + +const char* GetCStrOrNull(const cm::optional<std::string>& str) +{ + return str ? str->c_str() : nullptr; +} +} + bool cmMakefile::ValidateCustomCommand( const cmCustomCommandLines& commandLines) const { @@ -842,7 +916,8 @@ bool cmMakefile::ValidateCustomCommand( } cmTarget* cmMakefile::GetCustomCommandTarget( - const std::string& target, cmObjectLibraryCommands objLibCommands) const + const std::string& target, cmObjectLibraryCommands objLibCommands, + const cmListFileBacktrace& lfbt) const { // Find the target to which to add the custom command. auto ti = this->Targets.find(target); @@ -876,7 +951,7 @@ cmTarget* cmMakefile::GetCustomCommandTarget( e << "No TARGET '" << target << "' has been created in this directory."; } - this->IssueMessage(messageType, e.str()); + this->GetCMakeInstance()->IssueMessage(messageType, e.str(), lfbt); } return nullptr; @@ -889,7 +964,8 @@ cmTarget* cmMakefile::GetCustomCommandTarget( e << "Target \"" << target << "\" is an OBJECT library " "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), + lfbt); return nullptr; } if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -897,7 +973,8 @@ cmTarget* cmMakefile::GetCustomCommandTarget( e << "Target \"" << target << "\" is an INTERFACE library " "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), + lfbt); return nullptr; } @@ -910,9 +987,10 @@ cmTarget* cmMakefile::AddCustomCommandToTarget( const cmCustomCommandLines& commandLines, cmCustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle, bool uses_terminal, const std::string& depfile, const std::string& job_pool, - bool command_expand_lists, cmObjectLibraryCommands objLibCommands) + bool command_expand_lists) { - cmTarget* t = this->GetCustomCommandTarget(target, objLibCommands); + cmTarget* t = this->GetCustomCommandTarget( + target, cmObjectLibraryCommands::Reject, this->Backtrace); // Validate custom commands. if (!t || !this->ValidateCustomCommand(commandLines)) { @@ -920,175 +998,83 @@ cmTarget* cmMakefile::AddCustomCommandToTarget( } // Always create the byproduct sources and mark them generated. - this->CreateGeneratedSources(byproducts); - - this->CommitCustomCommandToTarget( - t, byproducts, depends, commandLines, type, comment, workingDir, - escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists); + this->CreateGeneratedByproducts(byproducts); + + // Strings could be moved into the callback function with C++14. + cm::optional<std::string> commentStr = MakeOptionalString(comment); + cm::optional<std::string> workingStr = MakeOptionalString(workingDir); + + // Dispatch command creation to allow generator expressions in outputs. + this->AddGeneratorAction([=](cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt) { + BacktraceGuard guard(this->Backtrace, lfbt); + detail::AddCustomCommandToTarget( + lg, lfbt, cmCommandOrigin::Project, t, byproducts, depends, commandLines, + type, GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), + escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists); + }); return t; } -void cmMakefile::CommitCustomCommandToTarget( - cmTarget* target, const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, cmCustomCommandType type, - const char* comment, const char* workingDir, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile, const std::string& job_pool, - bool command_expand_lists) -{ - // Add the command to the appropriate build step for the target. - std::vector<std::string> no_output; - cmCustomCommand cc(this, no_output, byproducts, depends, commandLines, - comment, workingDir); - cc.SetEscapeOldStyle(escapeOldStyle); - cc.SetEscapeAllowMakeVars(true); - cc.SetUsesTerminal(uses_terminal); - cc.SetCommandExpandLists(command_expand_lists); - cc.SetDepfile(depfile); - cc.SetJobPool(job_pool); - switch (type) { - case cmCustomCommandType::PRE_BUILD: - target->AddPreBuildCommand(std::move(cc)); - break; - case cmCustomCommandType::PRE_LINK: - target->AddPreLinkCommand(std::move(cc)); - break; - case cmCustomCommandType::POST_BUILD: - target->AddPostBuildCommand(std::move(cc)); - break; - } - - this->AddTargetByproducts(target, byproducts); -} - -cmSourceFile* cmMakefile::AddCustomCommandToOutput( +void cmMakefile::AddCustomCommandToOutput( const std::string& output, const std::vector<std::string>& depends, const std::string& main_dependency, const cmCustomCommandLines& commandLines, - const char* comment, const char* workingDir, bool replace, - bool escapeOldStyle, bool uses_terminal, bool command_expand_lists, - const std::string& depfile, const std::string& job_pool) + const char* comment, const char* workingDir, + const CommandSourceCallback& callback, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool) { - std::vector<std::string> outputs; - outputs.push_back(output); std::vector<std::string> no_byproducts; cmImplicitDependsList no_implicit_depends; - return this->AddCustomCommandToOutput( - outputs, no_byproducts, depends, main_dependency, no_implicit_depends, - commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal, - command_expand_lists, depfile, job_pool); + this->AddCustomCommandToOutput( + { output }, no_byproducts, depends, main_dependency, no_implicit_depends, + commandLines, comment, workingDir, callback, replace, escapeOldStyle, + uses_terminal, command_expand_lists, depfile, job_pool); } -cmSourceFile* cmMakefile::AddCustomCommandToOutput( +void cmMakefile::AddCustomCommandToOutput( const std::vector<std::string>& outputs, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const std::string& main_dependency, const cmImplicitDependsList& implicit_depends, const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace, bool escapeOldStyle, - bool uses_terminal, bool command_expand_lists, const std::string& depfile, - const std::string& job_pool) + const char* workingDir, const CommandSourceCallback& callback, bool replace, + bool escapeOldStyle, bool uses_terminal, bool command_expand_lists, + const std::string& depfile, const std::string& job_pool) { // Make sure there is at least one output. if (outputs.empty()) { cmSystemTools::Error("Attempt to add a custom rule with no output!"); - return nullptr; + return; } // Validate custom commands. if (!this->ValidateCustomCommand(commandLines)) { - return nullptr; + return; } // Always create the output sources and mark them generated. - this->CreateGeneratedSources(outputs); - this->CreateGeneratedSources(byproducts); - - return this->CommitCustomCommandToOutput( - outputs, byproducts, depends, main_dependency, implicit_depends, - commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal, - command_expand_lists, depfile, job_pool); -} - -cmSourceFile* cmMakefile::CommitCustomCommandToOutput( - const std::vector<std::string>& outputs, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, const std::string& main_dependency, - const cmImplicitDependsList& implicit_depends, - const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace, bool escapeOldStyle, - bool uses_terminal, bool command_expand_lists, const std::string& depfile, - const std::string& job_pool) -{ - // Choose a source file on which to store the custom command. - cmSourceFile* file = nullptr; - if (!commandLines.empty() && !main_dependency.empty()) { - // The main dependency was specified. Use it unless a different - // custom command already used it. - file = this->GetSource(main_dependency); - if (file && file->GetCustomCommand() && !replace) { - // The main dependency already has a custom command. - if (commandLines == file->GetCustomCommand()->GetCommandLines()) { - // The existing custom command is identical. Silently ignore - // the duplicate. - return file; - } - // The existing custom command is different. We need to - // generate a rule file for this new command. - file = nullptr; - } else if (!file) { - file = this->CreateSource(main_dependency); + this->CreateGeneratedOutputs(outputs); + this->CreateGeneratedByproducts(byproducts); + + // Strings could be moved into the callback function with C++14. + cm::optional<std::string> commentStr = MakeOptionalString(comment); + cm::optional<std::string> workingStr = MakeOptionalString(workingDir); + + // Dispatch command creation to allow generator expressions in outputs. + this->AddGeneratorAction([=](cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt) { + BacktraceGuard guard(this->Backtrace, lfbt); + cmSourceFile* sf = detail::AddCustomCommandToOutput( + lg, lfbt, cmCommandOrigin::Project, outputs, byproducts, depends, + main_dependency, implicit_depends, commandLines, + GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), replace, + escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool); + if (callback && sf) { + callback(sf); } - } - - // Generate a rule file if the main dependency is not available. - if (!file) { - cmGlobalGenerator* gg = this->GetGlobalGenerator(); - - // Construct a rule file associated with the first output produced. - std::string outName = gg->GenerateRuleFile(outputs[0]); - - // Check if the rule file already exists. - file = this->GetSource(outName, cmSourceFileLocationKind::Known); - if (file && file->GetCustomCommand() && !replace) { - // The rule file already exists. - if (commandLines != file->GetCustomCommand()->GetCommandLines()) { - cmSystemTools::Error("Attempt to add a custom rule to output \"" + - outName + "\" which already has a custom rule."); - } - return file; - } - - // Create a cmSourceFile for the rule file. - if (!file) { - file = - this->CreateSource(outName, true, cmSourceFileLocationKind::Known); - } - file->SetProperty("__CMAKE_RULE", "1"); - } - - // Attach the custom command to the file. - if (file) { - // Construct a complete list of dependencies. - std::vector<std::string> depends2(depends); - if (!main_dependency.empty()) { - depends2.push_back(main_dependency); - } - - std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>( - this, outputs, byproducts, depends2, commandLines, comment, workingDir); - cc->SetEscapeOldStyle(escapeOldStyle); - cc->SetEscapeAllowMakeVars(true); - cc->SetImplicitDepends(implicit_depends); - cc->SetUsesTerminal(uses_terminal); - cc->SetCommandExpandLists(command_expand_lists); - cc->SetDepfile(depfile); - cc->SetJobPool(job_pool); - file->SetCustomCommand(std::move(cc)); - - this->AddSourceOutputs(file, outputs, byproducts); - } - return file; + }); } void cmMakefile::AddCustomCommandOldStyle( @@ -1136,11 +1122,8 @@ void cmMakefile::AddCustomCommandOldStyle( if (sourceFiles.find(source)) { // The source looks like a real file. Use it as the main dependency. for (std::string const& output : outputs) { - cmSourceFile* sf = this->AddCustomCommandToOutput( - output, depends, source, commandLines, comment, nullptr); - if (sf) { - addRuleFileToTarget(sf); - } + this->AddCustomCommandToOutput(output, depends, source, commandLines, + comment, nullptr, addRuleFileToTarget); } } else { std::string no_main_dependency; @@ -1149,11 +1132,9 @@ void cmMakefile::AddCustomCommandOldStyle( // The source may not be a real file. Do not use a main dependency. for (std::string const& output : outputs) { - cmSourceFile* sf = this->AddCustomCommandToOutput( - output, depends2, no_main_dependency, commandLines, comment, nullptr); - if (sf) { - addRuleFileToTarget(sf); - } + this->AddCustomCommandToOutput(output, depends2, no_main_dependency, + commandLines, comment, nullptr, + addRuleFileToTarget); } } } @@ -1170,29 +1151,18 @@ bool cmMakefile::AppendCustomCommandToOutput( // Validate custom commands. if (this->ValidateCustomCommand(commandLines)) { - // Add command factory to allow generator expressions in output. - this->CommitAppendCustomCommandToOutput(output, depends, implicit_depends, - commandLines); + // Dispatch command creation to allow generator expressions in outputs. + this->AddGeneratorAction( + [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) { + BacktraceGuard guard(this->Backtrace, lfbt); + detail::AppendCustomCommandToOutput(lg, lfbt, output, depends, + implicit_depends, commandLines); + }); } return true; } -void cmMakefile::CommitAppendCustomCommandToOutput( - const std::string& output, const std::vector<std::string>& depends, - const cmImplicitDependsList& implicit_depends, - const cmCustomCommandLines& commandLines) -{ - // Lookup an existing command. - if (cmSourceFile* sf = this->GetSourceFileWithOutput(output)) { - if (cmCustomCommand* cc = sf->GetCustomCommand()) { - cc->AppendCommands(commandLines); - cc->AppendDepends(depends); - cc->AppendImplicitDepends(implicit_depends); - } - } -} - cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target) { std::string force = cmStrCat(this->GetCurrentBinaryDirectory(), @@ -1215,15 +1185,14 @@ cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target) } cmTarget* cmMakefile::AddUtilityCommand( - const std::string& utilityName, cmCommandOrigin origin, bool excludeFromAll, - const char* workingDirectory, const std::vector<std::string>& byproducts, + const std::string& utilityName, bool excludeFromAll, const char* workingDir, + const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle, const char* comment, bool uses_terminal, bool command_expand_lists, const std::string& job_pool) { - cmTarget* target = - this->AddNewUtilityTarget(utilityName, origin, excludeFromAll); + cmTarget* target = this->AddNewUtilityTarget(utilityName, excludeFromAll); // Validate custom commands. if ((commandLines.empty() && depends.empty()) || @@ -1236,45 +1205,26 @@ cmTarget* cmMakefile::AddUtilityCommand( this->GetOrCreateGeneratedSource(force.Name); // Always create the byproduct sources and mark them generated. - this->CreateGeneratedSources(byproducts); - - if (!comment) { - // Use an empty comment to avoid generation of default comment. - comment = ""; - } - - this->CommitUtilityCommand(target, force, workingDirectory, byproducts, - depends, commandLines, escapeOldStyle, comment, - uses_terminal, command_expand_lists, job_pool); + this->CreateGeneratedByproducts(byproducts); + + // Strings could be moved into the callback function with C++14. + cm::optional<std::string> commentStr = MakeOptionalString(comment); + cm::optional<std::string> workingStr = MakeOptionalString(workingDir); + + // Dispatch command creation to allow generator expressions in outputs. + this->AddGeneratorAction( + [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) { + BacktraceGuard guard(this->Backtrace, lfbt); + detail::AddUtilityCommand(lg, lfbt, cmCommandOrigin::Project, target, + force, GetCStrOrNull(workingStr), byproducts, + depends, commandLines, escapeOldStyle, + GetCStrOrNull(commentStr), uses_terminal, + command_expand_lists, job_pool); + }); return target; } -void cmMakefile::CommitUtilityCommand( - cmTarget* target, const cmUtilityOutput& force, const char* workingDirectory, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, bool escapeOldStyle, - const char* comment, bool uses_terminal, bool command_expand_lists, - const std::string& job_pool) -{ - std::vector<std::string> forced; - forced.push_back(force.Name); - std::string no_main_dependency; - cmImplicitDependsList no_implicit_depends; - bool no_replace = false; - cmSourceFile* sf = this->AddCustomCommandToOutput( - forced, byproducts, depends, no_main_dependency, no_implicit_depends, - commandLines, comment, workingDirectory, no_replace, escapeOldStyle, - uses_terminal, command_expand_lists, /*depfile=*/"", job_pool); - if (!force.NameCMP0049.empty()) { - target->AddSource(force.NameCMP0049); - } - if (sf) { - this->AddTargetByproducts(target, byproducts); - } -} - static void s_AddDefineFlag(std::string const& flag, std::string& dflags) { // remove any \n\r @@ -1357,13 +1307,12 @@ void cmMakefile::AddLinkOption(std::string const& option) void cmMakefile::AddLinkDirectory(std::string const& directory, bool before) { - cmListFileBacktrace lfbt = this->GetBacktrace(); if (before) { - this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(directory, - lfbt); + this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry( + directory, this->Backtrace); } else { - this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(directory, - lfbt); + this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry( + directory, this->Backtrace); } } @@ -1776,8 +1725,10 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, cmSystemTools::MakeDirectory(binPath); - cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot); - this->GetGlobalGenerator()->AddMakefile(subMf); + auto subMfu = + cm::make_unique<cmMakefile>(this->GlobalGenerator, newSnapshot); + auto subMf = subMfu.get(); + this->GetGlobalGenerator()->AddMakefile(std::move(subMfu)); if (excludeFromAll) { subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); @@ -1820,20 +1771,19 @@ void cmMakefile::AddIncludeDirectories(const std::vector<std::string>& incs, return; } - cmListFileBacktrace lfbt = this->GetBacktrace(); std::string entryString = cmJoin(incs, ";"); if (before) { this->StateSnapshot.GetDirectory().PrependIncludeDirectoriesEntry( - entryString, lfbt); + entryString, this->Backtrace); } else { this->StateSnapshot.GetDirectory().AppendIncludeDirectoriesEntry( - entryString, lfbt); + entryString, this->Backtrace); } // Property on each target: for (auto& target : this->Targets) { cmTarget& t = target.second; - t.InsertInclude(entryString, lfbt, before); + t.InsertInclude(entryString, this->Backtrace, before); } } @@ -2027,7 +1977,7 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target) target.AddLinkLibrary(*this, libraryName, libType); target.AppendProperty( "INTERFACE_LINK_LIBRARIES", - target.GetDebugGeneratorExpressions(libraryName, libType).c_str()); + target.GetDebugGeneratorExpressions(libraryName, libType)); } } } @@ -2080,7 +2030,8 @@ cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type, { auto it = this->Targets - .emplace(name, cmTarget(name, type, cmTarget::VisibilityNormal, this)) + .emplace(name, + cmTarget(name, type, cmTarget::VisibilityNormal, this, true)) .first; this->OrderedTargets.push_back(&it->second); this->GetGlobalGenerator()->IndexTarget(&it->second); @@ -2089,11 +2040,9 @@ cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type, } cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName, - cmCommandOrigin origin, bool excludeFromAll) { cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName); - target->SetIsGeneratorProvided(origin == cmCommandOrigin::Generator); if (excludeFromAll) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } @@ -2211,8 +2160,8 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput( (!o->second.Sources.SourceIsByproduct || kind == cmSourceOutputKind::OutputOrByproduct)) { // Source file could also be null pointer for example if we found the - // byproduct of a utility target or a PRE_BUILD, PRE_LINK, or POST_BUILD - // command of a target. + // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD + // command of a target, or a not yet created custom command. return o->second.Sources.Source; } return nullptr; @@ -2220,12 +2169,20 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput( bool cmMakefile::MightHaveCustomCommand(const std::string& name) const { - // This will have to be changed for delaying custom command creation, because - // GetSourceFileWithOutput requires the command to be already created. - if (cmSourceFile* sf = this->GetSourceFileWithOutput(name)) { - if (sf->GetCustomCommand()) { - return true; - } + if (this->DelayedOutputFilesHaveGenex || + cmGeneratorExpression::Find(name) != std::string::npos) { + // Could be more restrictive, but for now we assume that there could always + // be a match when generator expressions are involved. + return true; + } + // Also see LinearGetSourceFileWithOutput. + if (!cmSystemTools::FileIsFullPath(name)) { + return AnyOutputMatches(name, this->DelayedOutputFiles); + } + // Otherwise we use an efficient lookup map. + auto o = this->OutputToSource.find(name); + if (o != this->OutputToSource.end()) { + return o->second.SourceMightBeOutput; } return false; } @@ -2278,6 +2235,7 @@ void cmMakefile::UpdateOutputToSourceMap(std::string const& output, SourceEntry entry; entry.Sources.Source = source; entry.Sources.SourceIsByproduct = byproduct; + entry.SourceMightBeOutput = !byproduct; auto pr = this->OutputToSource.emplace(output, entry); if (!pr.second) { @@ -2287,6 +2245,7 @@ void cmMakefile::UpdateOutputToSourceMap(std::string const& output, (current.Sources.SourceIsByproduct && !byproduct)) { current.Sources.Source = source; current.Sources.SourceIsByproduct = false; + current.SourceMightBeOutput = true; } else { // Multiple custom commands produce the same output but may // be attached to a different source file (MAIN_DEPENDENCY). @@ -2478,7 +2437,7 @@ void cmMakefile::ExpandVariablesCMP0019() << " " << dirs << "\n"; /* clang-format on */ } - t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); + t.SetProperty("INCLUDE_DIRECTORIES", dirs); } } @@ -2739,7 +2698,7 @@ const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const std::vector<std::string> cmMakefile::GetDefinitions() const { std::vector<std::string> res = this->StateSnapshot.ClosureKeys(); - cmAppend(res, this->GetState()->GetCacheEntryKeys()); + cm::append(res, this->GetState()->GetCacheEntryKeys()); std::sort(res.begin(), res.end()); return res; } @@ -3553,11 +3512,41 @@ cmSourceFile* cmMakefile::GetOrCreateGeneratedSource( return sf; } -void cmMakefile::CreateGeneratedSources( +void cmMakefile::CreateGeneratedOutputs( const std::vector<std::string>& outputs) { - for (std::string const& output : outputs) { - this->GetOrCreateGeneratedSource(output); + for (std::string const& o : outputs) { + if (cmGeneratorExpression::Find(o) == std::string::npos) { + this->GetOrCreateGeneratedSource(o); + this->AddDelayedOutput(o); + } else { + this->DelayedOutputFilesHaveGenex = true; + } + } +} + +void cmMakefile::CreateGeneratedByproducts( + const std::vector<std::string>& byproducts) +{ + for (std::string const& o : byproducts) { + if (cmGeneratorExpression::Find(o) == std::string::npos) { + this->GetOrCreateGeneratedSource(o); + } + } +} + +void cmMakefile::AddDelayedOutput(std::string const& output) +{ + // Note that this vector might contain the output names in a different order + // than in source file iteration order. + this->DelayedOutputFiles.push_back(output); + + SourceEntry entry; + entry.SourceMightBeOutput = true; + + auto pr = this->OutputToSource.emplace(output, entry); + if (!pr.second) { + pr.first->second.SourceMightBeOutput = true; } } @@ -3630,8 +3619,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, // be run that way but the cmake object requires a vailid path cmake cm(cmake::RoleProject, cmState::Project); cm.SetIsInTryCompile(true); - cmGlobalGenerator* gg = - cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); + auto gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); if (!gg) { this->IssueMessage(MessageType::INTERNAL_ERROR, "Global generator '" + @@ -3642,7 +3630,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, return 1; } gg->RecursionDepth = this->RecursionDepth; - cm.SetGlobalGenerator(gg); + cm.SetGlobalGenerator(std::move(gg)); // do a configure cm.SetHomeDirectory(srcdir); @@ -3651,7 +3639,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, cm.SetGeneratorPlatform(this->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM")); cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET")); cm.LoadCache(); - if (!gg->IsMultiConfig()) { + if (!cm.GetGlobalGenerator()->IsMultiConfig()) { if (const char* config = this->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION")) { // Tell the single-configuration generator which one to use. @@ -3697,7 +3685,8 @@ int cmMakefile::TryCompile(const std::string& srcdir, cm.SetCacheArgs(*cmakeArgs); } // to save time we pass the EnableLanguage info directly - gg->EnableLanguagesFromGenerator(this->GetGlobalGenerator(), this); + cm.GetGlobalGenerator()->EnableLanguagesFromGenerator( + this->GetGlobalGenerator(), this); if (this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE", "", cmStateEnums::INTERNAL); @@ -3777,7 +3766,8 @@ void cmMakefile::DisplayStatus(const std::string& message, float s) const } std::string cmMakefile::GetModulesFile(const std::string& filename, - bool& system) const + bool& system, bool debug, + std::string& debugBuffer) const { std::string result; @@ -3808,6 +3798,9 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, moduleInCMakeModulePath = itempl; break; } + if (debug) { + debugBuffer = cmStrCat(debugBuffer, " ", itempl, "\n"); + } } } @@ -3816,6 +3809,9 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/", filename); cmSystemTools::ConvertToUnixSlashes(moduleInCMakeRoot); if (!cmSystemTools::FileExists(moduleInCMakeRoot)) { + if (debug) { + debugBuffer = cmStrCat(debugBuffer, " ", moduleInCMakeRoot, "\n"); + } moduleInCMakeRoot.clear(); } @@ -4029,16 +4025,14 @@ int cmMakefile::ConfigureFile(const std::string& infile, void cmMakefile::SetProperty(const std::string& prop, const char* value) { - cmListFileBacktrace lfbt = this->GetBacktrace(); - this->StateSnapshot.GetDirectory().SetProperty(prop, value, lfbt); + this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace); } void cmMakefile::AppendProperty(const std::string& prop, const char* value, bool asString) { - cmListFileBacktrace lfbt = this->GetBacktrace(); this->StateSnapshot.GetDirectory().AppendProperty(prop, value, asString, - lfbt); + this->Backtrace); } const char* cmMakefile::GetProperty(const std::string& prop) const @@ -4214,7 +4208,7 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name, new cmTarget(name, type, global ? cmTarget::VisibilityImportedGlobally : cmTarget::VisibilityImported, - this)); + this, true)); // Add to the set of available imported targets. this->ImportedTargets[name] = target.get(); @@ -4487,7 +4481,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0067 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0069 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. @@ -4587,17 +4581,21 @@ static const char* const C_FEATURES[] = { nullptr FOR_EACH_C_FEATURE( static const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE( FEATURE_STRING) }; + +static const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE( + FEATURE_STRING) }; #undef FEATURE_STRING static const char* const C_STANDARDS[] = { "90", "99", "11" }; static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" }; +static const char* const CUDA_STANDARDS[] = { "03", "11", "14", "17", "20" }; bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, const std::string& feature, std::string* error) const { if (cmGeneratorExpression::Find(feature) != std::string::npos) { - target->AppendProperty("COMPILE_FEATURES", feature.c_str()); + target->AppendProperty("COMPILE_FEATURES", feature); return true; } @@ -4628,11 +4626,15 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, return false; } - target->AppendProperty("COMPILE_FEATURES", feature.c_str()); + target->AppendProperty("COMPILE_FEATURES", feature); - return lang == "C" || lang == "OBJC" - ? this->AddRequiredTargetCFeature(target, feature, lang, error) - : this->AddRequiredTargetCxxFeature(target, feature, lang, error); + if (lang == "C" || lang == "OBJC") { + return this->AddRequiredTargetCFeature(target, feature, lang, error); + } + if (lang == "CUDA") { + return this->AddRequiredTargetCudaFeature(target, feature, lang, error); + } + return this->AddRequiredTargetCxxFeature(target, feature, lang, error); } bool cmMakefile::CompileFeatureKnown(cmTarget const* target, @@ -4656,6 +4658,13 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target, lang = "CXX"; return true; } + bool isCudaFeature = + std::find_if(cm::cbegin(CUDA_FEATURES) + 1, cm::cend(CUDA_FEATURES), + cmStrCmp(feature)) != cm::cend(CUDA_FEATURES); + if (isCudaFeature) { + lang = "CUDA"; + return true; + } std::ostringstream e; if (error) { e << "specified"; @@ -4724,9 +4733,13 @@ bool cmMakefile::HaveStandardAvailable(cmTarget const* target, std::string const& lang, const std::string& feature) const { - return lang == "C" || lang == "OBJC" - ? this->HaveCStandardAvailable(target, feature, lang) - : this->HaveCxxStandardAvailable(target, feature, lang); + if (lang == "C" || lang == "OBJC") { + return this->HaveCStandardAvailable(target, feature, lang); + } + if (lang == "CUDA") { + return this->HaveCudaStandardAvailable(target, feature, lang); + } + return this->HaveCxxStandardAvailable(target, feature, lang); } bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, @@ -4809,6 +4822,14 @@ bool cmMakefile::IsLaterStandard(std::string const& lang, return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) != cm::cend(C_STANDARDS); } + if (lang == "CUDA") { + const char* const* rhsIt = std::find_if( + cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), cmStrCmp(rhs)); + + return std::find_if(rhsIt, cm::cend(CUDA_STANDARDS), cmStrCmp(lhs)) != + cm::cend(CUDA_STANDARDS); + } + const char* const* rhsIt = std::find_if( cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs)); @@ -4953,27 +4974,6 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, } } - const char* existingCudaStandard = target->GetProperty("CUDA_STANDARD"); - const char* const* existingCudaLevel = nullptr; - if (existingCudaStandard) { - existingCudaLevel = - std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), - cmStrCmp(existingCudaStandard)); - if (existingCudaLevel == cm::cend(CXX_STANDARDS)) { - std::ostringstream e; - e << "The CUDA_STANDARD property on target \"" << target->GetName() - << "\" contained an invalid value: \"" << existingCudaStandard - << "\"."; - if (error) { - *error = e.str(); - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, - e.str(), this->Backtrace); - } - return false; - } - } - /* clang-format off */ const char* const* needCxxLevel = needCxx20 ? &CXX_STANDARDS[4] @@ -4990,11 +4990,164 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, if (!existingCxxLevel || existingCxxLevel < needCxxLevel) { target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel); } + } + + return true; +} + +bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target, + const std::string& feature, + std::string const& lang) const +{ + const char* defaultCudaStandard = + this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + if (!defaultCudaStandard) { + this->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("CMAKE_", lang, + "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " + "not fully configured for this compiler.")); + // Return true so the caller does not try to lookup the default standard. + return true; + } + if (std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), + cmStrCmp(defaultCudaStandard)) == + cm::cend(CUDA_STANDARDS)) { + const std::string e = + cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ", + "invalid value: \"", defaultCudaStandard, "\"."); + this->IssueMessage(MessageType::INTERNAL_ERROR, e); + return false; + } + + bool needCuda03 = false; + bool needCuda11 = false; + bool needCuda14 = false; + bool needCuda17 = false; + bool needCuda20 = false; + this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11, + needCuda14, needCuda17, needCuda20); + + const char* existingCudaStandard = + target->GetProperty(cmStrCat(lang, "_STANDARD")); + if (!existingCudaStandard) { + existingCudaStandard = defaultCudaStandard; + } + + const char* const* existingCudaLevel = + std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), + cmStrCmp(existingCudaStandard)); + if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) { + const std::string e = cmStrCat( + "The ", lang, "_STANDARD property on target \"", target->GetName(), + "\" contained an invalid value: \"", existingCudaStandard, "\"."); + this->IssueMessage(MessageType::FATAL_ERROR, e); + return false; + } + + /* clang-format off */ + const char* const* needCudaLevel = + needCuda20 ? &CUDA_STANDARDS[4] + : needCuda17 ? &CUDA_STANDARDS[3] + : needCuda14 ? &CUDA_STANDARDS[2] + : needCuda11 ? &CUDA_STANDARDS[1] + : needCuda03 ? &CUDA_STANDARDS[0] + : nullptr; + /* clang-format on */ + + return !needCudaLevel || needCudaLevel <= existingCudaLevel; +} + +void cmMakefile::CheckNeededCudaLanguage(const std::string& feature, + std::string const& lang, + bool& needCuda03, bool& needCuda11, + bool& needCuda14, bool& needCuda17, + bool& needCuda20) const +{ + if (const char* propCuda03 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "03_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda03); + needCuda03 = cmContains(props, feature); + } + if (const char* propCuda11 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda11); + needCuda11 = cmContains(props, feature); + } + if (const char* propCuda14 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda14); + needCuda14 = cmContains(props, feature); + } + if (const char* propCuda17 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda17); + needCuda17 = cmContains(props, feature); + } + if (const char* propCuda20 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda20); + needCuda20 = cmContains(props, feature); + } +} + +bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target, + const std::string& feature, + std::string const& lang, + std::string* error) const +{ + bool needCuda03 = false; + bool needCuda11 = false; + bool needCuda14 = false; + bool needCuda17 = false; + bool needCuda20 = false; + + this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11, + needCuda14, needCuda17, needCuda20); + + const char* existingCudaStandard = + target->GetProperty(cmStrCat(lang, "_STANDARD")); + if (existingCudaStandard == nullptr) { + const char* defaultCudaStandard = + this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + if (defaultCudaStandard && *defaultCudaStandard) { + existingCudaStandard = defaultCudaStandard; + } + } + const char* const* existingCudaLevel = nullptr; + if (existingCudaStandard) { + existingCudaLevel = + std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), + cmStrCmp(existingCudaStandard)); + if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) { + const std::string e = cmStrCat( + "The ", lang, "_STANDARD property on target \"", target->GetName(), + "\" contained an invalid value: \"", existingCudaStandard, "\"."); + if (error) { + *error = e; + } else { + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, + this->Backtrace); + } + return false; + } + } + /* clang-format off */ + const char* const* needCudaLevel = + needCuda20 ? &CUDA_STANDARDS[4] + : needCuda17 ? &CUDA_STANDARDS[3] + : needCuda14 ? &CUDA_STANDARDS[2] + : needCuda11 ? &CUDA_STANDARDS[1] + : needCuda03 ? &CUDA_STANDARDS[0] + : nullptr; + /* clang-format on */ + + if (needCudaLevel) { // Ensure the CUDA language level is high enough to support - // the needed C++ features. - if (!existingCudaLevel || existingCudaLevel < needCxxLevel) { - target->SetProperty("CUDA_STANDARD", *needCxxLevel); + // the needed CUDA features. + if (!existingCudaLevel || existingCudaLevel < needCudaLevel) { + target->SetProperty("CUDA_STANDARD", *needCudaLevel); } } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 6e59494049..085c1d634b 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -49,6 +49,7 @@ class cmGeneratorExpressionEvaluationFile; class cmGlobalGenerator; class cmImplicitDependsList; class cmInstallGenerator; +class cmLocalGenerator; class cmMessenger; class cmSourceFile; class cmState; @@ -151,54 +152,64 @@ public: bool EnforceUniqueName(std::string const& name, std::string& msg, bool isCustom = false) const; - using FinalAction = std::function<void(cmMakefile&)>; + using GeneratorAction = + std::function<void(cmLocalGenerator&, const cmListFileBacktrace&)>; /** - * Register an action that is executed during FinalPass + * Register an action that is executed during Generate */ - void AddFinalAction(FinalAction action); + void AddGeneratorAction(GeneratorAction action); /** - * Perform FinalPass, Library dependency analysis etc before output of the - * makefile. + * Perform generate actions, Library dependency analysis etc before output of + * the makefile. */ - void ConfigureFinalPass(); + void Generate(cmLocalGenerator& lg); /** - * run all FinalActions. + * Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands. */ - void FinalPass(); + cmTarget* GetCustomCommandTarget(const std::string& target, + cmObjectLibraryCommands objLibCommands, + const cmListFileBacktrace& lfbt) const; /** - * Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands. + * Dispatch adding a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a + * target. */ - cmTarget* GetCustomCommandTarget( - const std::string& target, cmObjectLibraryCommands objLibCommands) const; - - /** Add a custom command to the build. */ cmTarget* AddCustomCommandToTarget( const std::string& target, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, cmCustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle = true, bool uses_terminal = false, const std::string& depfile = "", - const std::string& job_pool = "", bool command_expand_lists = false, - cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject); - cmSourceFile* AddCustomCommandToOutput( + const std::string& job_pool = "", bool command_expand_lists = false); + + /** + * Called for each file with custom command. + */ + using CommandSourceCallback = std::function<void(cmSourceFile*)>; + + /** + * Dispatch adding a custom command to a source file. + */ + void AddCustomCommandToOutput( const std::string& output, const std::vector<std::string>& depends, const std::string& main_dependency, const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace = false, bool escapeOldStyle = true, + const char* workingDir, const CommandSourceCallback& callback = nullptr, + bool replace = false, bool escapeOldStyle = true, bool uses_terminal = false, bool command_expand_lists = false, const std::string& depfile = "", const std::string& job_pool = ""); - cmSourceFile* AddCustomCommandToOutput( + void AddCustomCommandToOutput( const std::vector<std::string>& outputs, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const std::string& main_dependency, const cmImplicitDependsList& implicit_depends, const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace = false, bool escapeOldStyle = true, + const char* workingDir, const CommandSourceCallback& callback = nullptr, + bool replace = false, bool escapeOldStyle = true, bool uses_terminal = false, bool command_expand_lists = false, const std::string& depfile = "", const std::string& job_pool = ""); void AddCustomCommandOldStyle(const std::string& target, @@ -244,7 +255,7 @@ public: /** Create a target instance for the utility. */ cmTarget* AddNewUtilityTarget(const std::string& utilityName, - cmCommandOrigin origin, bool excludeFromAll); + bool excludeFromAll); /** * Add an executable to the build. @@ -259,13 +270,12 @@ public: cmUtilityOutput GetUtilityOutput(cmTarget* target); /** - * Add a utility to the build. A utility target is a command that - * is run every time the target is built. + * Dispatch adding a utility to the build. A utility target is a command + * that is run every time the target is built. */ cmTarget* AddUtilityCommand( - const std::string& utilityName, cmCommandOrigin origin, - bool excludeFromAll, const char* workingDirectory, - const std::vector<std::string>& byproducts, + const std::string& utilityName, bool excludeFromAll, + const char* workingDir, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle = true, const char* comment = nullptr, bool uses_terminal = false, @@ -756,10 +766,21 @@ public: std::string GetModulesFile(const std::string& name) const { bool system; - return this->GetModulesFile(name, system); + std::string debugBuffer; + return this->GetModulesFile(name, system, false, debugBuffer); } - std::string GetModulesFile(const std::string& name, bool& system) const; + /** + * Return a location of a file in cmake or custom modules directory + */ + std::string GetModulesFile(const std::string& name, bool& system) const + { + std::string debugBuffer; + return this->GetModulesFile(name, system, false, debugBuffer); + } + + std::string GetModulesFile(const std::string& name, bool& system, bool debug, + std::string& debugBuffer) const; //! Set/Get a property of this directory void SetProperty(const std::string& prop, const char* value); @@ -1001,7 +1022,6 @@ protected: size_t ObjectLibrariesSourceGroupIndex; #endif - std::vector<FinalAction> FinalActions; cmGlobalGenerator* GlobalGenerator; bool IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus& status); @@ -1011,6 +1031,8 @@ private: cmListFileBacktrace Backtrace; int RecursionDepth; + void DoGenerate(cmLocalGenerator& lg); + void ReadListFile(cmListFile const& listFile, const std::string& filenametoread); @@ -1080,38 +1102,15 @@ private: bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const; - void CreateGeneratedSources(const std::vector<std::string>& outputs); + void CreateGeneratedOutputs(const std::vector<std::string>& outputs); + void CreateGeneratedByproducts(const std::vector<std::string>& byproducts); - void CommitCustomCommandToTarget( - cmTarget* target, const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, cmCustomCommandType type, - const char* comment, const char* workingDir, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile, - const std::string& job_pool, bool command_expand_lists); - cmSourceFile* CommitCustomCommandToOutput( - const std::vector<std::string>& outputs, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const std::string& main_dependency, - const cmImplicitDependsList& implicit_depends, - const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace, bool escapeOldStyle, - bool uses_terminal, bool command_expand_lists, const std::string& depfile, - const std::string& job_pool); - void CommitAppendCustomCommandToOutput( - const std::string& output, const std::vector<std::string>& depends, - const cmImplicitDependsList& implicit_depends, - const cmCustomCommandLines& commandLines); + std::vector<BT<GeneratorAction>> GeneratorActions; + bool GeneratorActionsInvoked = false; + bool DelayedOutputFilesHaveGenex = false; + std::vector<std::string> DelayedOutputFiles; - void CommitUtilityCommand(cmTarget* target, const cmUtilityOutput& force, - const char* workingDirectory, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, - bool escapeOldStyle, const char* comment, - bool uses_terminal, bool command_expand_lists, - const std::string& job_pool); + void AddDelayedOutput(std::string const& output); /** * See LinearGetSourceFileWithOutput for background information @@ -1131,6 +1130,7 @@ private: struct SourceEntry { cmSourcesWithOutput Sources; + bool SourceMightBeOutput = false; }; // A map for fast output to input look up. @@ -1149,11 +1149,14 @@ private: bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature, std::string const& lang, std::string* error = nullptr) const; - bool AddRequiredTargetCxxFeature(cmTarget* target, const std::string& feature, std::string const& lang, std::string* error = nullptr) const; + bool AddRequiredTargetCudaFeature(cmTarget* target, + const std::string& feature, + std::string const& lang, + std::string* error = nullptr) const; void CheckNeededCLanguage(const std::string& feature, std::string const& lang, bool& needC90, @@ -1162,6 +1165,10 @@ private: std::string const& lang, bool& needCxx98, bool& needCxx11, bool& needCxx14, bool& needCxx17, bool& needCxx20) const; + void CheckNeededCudaLanguage(const std::string& feature, + std::string const& lang, bool& needCuda03, + bool& needCuda11, bool& needCuda14, + bool& needCuda17, bool& needCuda20) const; bool HaveCStandardAvailable(cmTarget const* target, const std::string& feature, @@ -1169,6 +1176,9 @@ private: bool HaveCxxStandardAvailable(cmTarget const* target, const std::string& feature, std::string const& lang) const; + bool HaveCudaStandardAvailable(cmTarget const* target, + const std::string& feature, + std::string const& lang) const; void CheckForUnusedVariables() const; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 40265ff656..1df54104f2 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -9,8 +9,8 @@ #include <vector> #include <cm/memory> +#include <cmext/algorithm> -#include "cmAlgorithms.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" @@ -35,10 +35,9 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( { this->CustomCommandDriver = OnDepends; this->TargetNames = - this->GeneratorTarget->GetExecutableNames(this->ConfigName); + this->GeneratorTarget->GetExecutableNames(this->GetConfigName()); - this->OSXBundleGenerator = - cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } @@ -64,7 +63,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles() // write the link rules this->WriteExecutableRule(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteExecutableRule(true); } @@ -85,7 +84,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( { #ifndef CMAKE_BOOTSTRAP const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (!requiresDeviceLinking) { return; } @@ -141,10 +140,10 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( // Add language feature flags. this->LocalGenerator->AddLanguageFlagsForLinking( - flags, this->GeneratorTarget, linkLanguage, this->ConfigName); + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); - this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddArchitectureFlags( + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); // Add target-specific linker flags. this->GetTargetLinkFlags(linkFlags, linkLanguage); @@ -213,7 +212,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), output); - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); std::string targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB, cmOutputConverter::SHELL); @@ -263,7 +263,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); // Write the build rule. @@ -287,12 +287,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Get the name of the executable to generate. cmGeneratorTarget::Names targetNames = - this->GeneratorTarget->GetExecutableNames(this->ConfigName); + this->GeneratorTarget->GetExecutableNames(this->GetConfigName()); // Construct the full path version of the names. - std::string outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + std::string outpath = + this->GeneratorTarget->GetDirectory(this->GetConfigName()); if (this->GeneratorTarget->IsAppBundleOnApple()) { - this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath); + this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath, + this->GetConfigName()); } outpath += '/'; std::string outpathImp; @@ -308,18 +310,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) cmSystemTools::MakeDirectory(outpath); if (!targetNames.ImportLibrary.empty()) { outpathImp = this->GeneratorTarget->GetDirectory( - this->ConfigName, cmStateEnums::ImportLibraryArtifact); + this->GetConfigName(), cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp); outpathImp += '/'; } } std::string compilePdbOutputPath = - this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(compilePdbOutputPath); std::string pdbOutputPath = - this->GeneratorTarget->GetPDBDirectory(this->ConfigName); + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(pdbOutputPath); pdbOutputPath += '/'; @@ -347,7 +349,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Get the language to use for linking this executable. std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); // Make sure we have a link language. if (linkLanguage.empty()) { @@ -380,7 +382,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add flags to create an executable. this->LocalGenerator->AddConfigVariableFlags( - linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->ConfigName); + linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GetConfigName()); if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) { this->LocalGenerator->AppendFlags( @@ -409,25 +411,26 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add language feature flags. this->LocalGenerator->AddLanguageFlagsForLinking( - flags, this->GeneratorTarget, linkLanguage, this->ConfigName); + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); - this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddArchitectureFlags( + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); // Add target-specific linker flags. this->GetTargetLinkFlags(linkFlags, linkLanguage); { - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); - this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags, + this->GetConfigName()); } - this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget, - this->ConfigName, linkLanguage); + this->LocalGenerator->AppendIPOLinkerFlags( + linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); // Construct a list of files associated with this executable that // may need to be cleaned. @@ -451,7 +454,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS( - this->ConfigName, targetFullPathImport, implib)) { + this->GetConfigName(), targetFullPathImport, implib)) { exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } @@ -479,7 +482,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Construct the main link rule. std::vector<std::string> real_link_commands; std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( - linkLanguage, this->ConfigName); + linkLanguage, this->GetConfigName()); std::string linkRule = this->GetLinkRule(linkRuleVar); std::vector<std::string> commands1; cmExpandList(linkRule, real_link_commands); @@ -506,10 +509,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Set path conversion for link script shells. this->LocalGenerator->SetLinkScriptShell(useLinkScript); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); linkLineComputer->SetForResponse(useResponseFileForLibs); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); linkLineComputer->SetRelink(relink); @@ -536,7 +539,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // maybe create .def file from list of objects this->GenDefFile(real_link_commands); - std::string manifests = this->GetManifests(); + std::string manifests = this->GetManifests(this->GetConfigName()); cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); @@ -627,7 +630,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); // Add a rule to create necessary symlinks for the library. @@ -639,7 +642,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); } diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 54a66065c2..357e273770 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -9,8 +9,8 @@ #include <vector> #include <cm/memory> +#include <cmext/algorithm> -#include "cmAlgorithms.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" @@ -36,11 +36,10 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( this->CustomCommandDriver = OnDepends; if (this->GeneratorTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) { this->TargetNames = - this->GeneratorTarget->GetLibraryNames(this->ConfigName); + this->GeneratorTarget->GetLibraryNames(this->GetConfigName()); } - this->OSXBundleGenerator = - cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } @@ -69,14 +68,16 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() break; case cmStateEnums::SHARED_LIBRARY: this->WriteSharedLibraryRules(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall( + this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteSharedLibraryRules(true); } break; case cmStateEnums::MODULE_LIBRARY: this->WriteModuleLibraryRules(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall( + this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteModuleLibraryRules(true); } @@ -126,21 +127,21 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules() void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, false); } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( - linkLanguage, this->ConfigName); + linkLanguage, this->GetConfigName()); std::string extraFlags; this->LocalGenerator->GetStaticLibraryFlags( - extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage, + extraFlags, cmSystemTools::UpperCase(this->GetConfigName()), linkLanguage, this->GeneratorTarget); this->WriteLibraryRules(linkRuleVar, extraFlags, false); } @@ -154,7 +155,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) if (!relink) { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); @@ -162,21 +163,22 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->GetConfigName()); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); - this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, + this->GetConfigName()); if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed"); @@ -188,7 +190,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) { if (!relink) { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); @@ -196,21 +198,22 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_MODULE"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->GetConfigName()); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); - this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, + this->GetConfigName()); this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } @@ -218,14 +221,14 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) { std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_MACOSX_FRAMEWORK"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->GetConfigName()); this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } @@ -331,7 +334,8 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), output); - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); std::string targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB, cmOutputConverter::SHELL); @@ -347,7 +351,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // Add language-specific flags. std::string langFlags; this->LocalGenerator->AddLanguageFlagsForLinking( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); vars.LanguageCompileFlags = langFlags.c_str(); @@ -393,7 +397,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); // Compute the list of outputs. @@ -420,7 +424,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Get the language to use for linking this library. std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); // Make sure we have a link language. if (linkLanguage.empty()) { @@ -439,8 +443,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Create set of linking flags. std::string linkFlags; this->LocalGenerator->AppendFlags(linkFlags, extraFlags); - this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget, - this->ConfigName, linkLanguage); + this->LocalGenerator->AppendIPOLinkerFlags( + linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); // Add OSX version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -450,20 +454,20 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } // Construct the name of the library. - this->GeneratorTarget->GetLibraryNames(this->ConfigName); + this->GeneratorTarget->GetLibraryNames(this->GetConfigName()); // Construct the full path version of the names. std::string outpath; std::string outpathImp; if (this->GeneratorTarget->IsFrameworkOnApple()) { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output, - outpath); + outpath, this->GetConfigName()); outpath += '/'; } else if (this->GeneratorTarget->IsCFBundleOnApple()) { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); - this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, - outpath); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); + this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, outpath, + this->GetConfigName()); outpath += '/'; } else if (relink) { outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), @@ -474,23 +478,23 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( outpathImp = outpath; } } else { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(outpath); outpath += '/'; if (!this->TargetNames.ImportLibrary.empty()) { outpathImp = this->GeneratorTarget->GetDirectory( - this->ConfigName, cmStateEnums::ImportLibraryArtifact); + this->GetConfigName(), cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp); outpathImp += '/'; } } std::string compilePdbOutputPath = - this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(compilePdbOutputPath); std::string pdbOutputPath = - this->GeneratorTarget->GetPDBDirectory(this->ConfigName); + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(pdbOutputPath); pdbOutputPath += "/"; @@ -567,7 +571,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); } @@ -586,7 +590,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS( - this->ConfigName, targetFullPathImport, implib)) { + this->GetConfigName(), targetFullPathImport, implib)) { libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } @@ -638,7 +642,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_CREATE"); arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arCreateVar, linkLanguage, this->ConfigName); + arCreateVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) { cmExpandList(rule, archiveCreateCommands); @@ -647,7 +651,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_APPEND"); arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arAppendVar, linkLanguage, this->ConfigName); + arAppendVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) { cmExpandList(rule, archiveAppendCommands); @@ -656,7 +660,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_FINISH"); arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arFinishVar, linkLanguage, this->ConfigName); + arFinishVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) { cmExpandList(rule, archiveFinishCommands); @@ -696,10 +700,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string linkLibs; if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) { - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = this->CreateLinkLineComputer( this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); + this->LocalGenerator->GetStateSnapshot().GetDirectory()); linkLineComputer->SetForResponse(useResponseFileForLibs); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); linkLineComputer->SetRelink(relink); @@ -726,7 +730,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // maybe create .def file from list of objects this->GenDefFile(real_link_commands); - std::string manifests = this->GetManifests(); + std::string manifests = this->GetManifests(this->GetConfigName()); cmRulePlaceholderExpander::RuleVariables vars; vars.TargetPDB = targetOutPathPDB.c_str(); @@ -771,7 +775,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); - if (this->GeneratorTarget->HasSOName(this->ConfigName)) { + if (this->GeneratorTarget->HasSOName(this->GetConfigName())) { vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage); vars.TargetSOName = this->TargetNames.SharedObject.c_str(); } @@ -783,8 +787,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string install_name_dir; if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY) { // Get the install_name directory for the build tree. - install_name_dir = - this->GeneratorTarget->GetInstallNameDirForBuildTree(this->ConfigName); + install_name_dir = this->GeneratorTarget->GetInstallNameDirForBuildTree( + this->GetConfigName()); // Set the rule variable replacement value. if (install_name_dir.empty()) { @@ -800,10 +804,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Add language-specific flags. std::string langFlags; this->LocalGenerator->AddLanguageFlagsForLinking( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); this->LocalGenerator->AddArchitectureFlags( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); vars.LanguageCompileFlags = langFlags.c_str(); @@ -903,7 +907,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); // Add a rule to create necessary symlinks for the library. @@ -917,7 +921,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 767f4e0aa8..77b6bc2c5b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -2,12 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileTargetGenerator.h" +#include <cassert> #include <cstdio> #include <memory> #include <sstream> #include <utility> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" @@ -15,6 +17,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" +#include "cmLinkLineComputer.h" #include "cmLocalCommonGenerator.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" @@ -85,6 +88,13 @@ cmMakefileTargetGenerator* cmMakefileTargetGenerator::New( return result; } +std::string cmMakefileTargetGenerator::GetConfigName() +{ + auto const& configNames = this->LocalGenerator->GetConfigNames(); + assert(configNames.size() == 1); + return configNames.front(); +} + void cmMakefileTargetGenerator::GetTargetLinkFlags( std::string& flags, const std::string& linkLanguage) { @@ -92,17 +102,18 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags( flags, this->GeneratorTarget->GetSafeProperty("LINK_FLAGS")); std::string linkFlagsConfig = - cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->ConfigName)); + cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->GetConfigName())); this->LocalGenerator->AppendFlags( flags, this->GeneratorTarget->GetSafeProperty(linkFlagsConfig)); std::vector<std::string> opts; - this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage); + this->GeneratorTarget->GetLinkOptions(opts, this->GetConfigName(), + linkLanguage); // LINK_OPTIONS are escaped. this->LocalGenerator->AppendCompileOptions(flags, opts); this->LocalGenerator->AppendPositionIndependentLinkerFlags( - flags, this->GeneratorTarget, this->ConfigName, linkLanguage); + flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); } void cmMakefileTargetGenerator::CreateRuleFile() @@ -154,10 +165,10 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() auto evaluatedFiles = [this](const char* prop_value) -> std::vector<std::string> { std::vector<std::string> files; - cmExpandList( - cmGeneratorExpression::Evaluate(prop_value, this->LocalGenerator, - this->ConfigName, this->GeneratorTarget), - files); + cmExpandList(cmGeneratorExpression::Evaluate( + prop_value, this->LocalGenerator, this->GetConfigName(), + this->GeneratorTarget), + files); return files; }; @@ -187,12 +198,13 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // First generate the object rule files. Save a list of all object // files for this target. std::vector<cmSourceFile const*> customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName); + this->GeneratorTarget->GetCustomCommands(customCommands, + this->GetConfigName()); std::string currentBinDir = this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmSourceFile const* sf : customCommands) { - cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), this->ConfigName, - this->LocalGenerator); + cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), + this->GetConfigName(), this->LocalGenerator); this->GenerateCustomRuleFile(ccg); if (clean) { const std::vector<std::string>& outputs = ccg.GetOutputs(); @@ -215,12 +227,14 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() std::vector<cmCustomCommand> buildEventCommands = this->GeneratorTarget->GetPreBuildCommands(); - cmAppend(buildEventCommands, this->GeneratorTarget->GetPreLinkCommands()); - cmAppend(buildEventCommands, - this->GeneratorTarget->GetPostBuildCommands()); + cm::append(buildEventCommands, + this->GeneratorTarget->GetPreLinkCommands()); + cm::append(buildEventCommands, + this->GeneratorTarget->GetPostBuildCommands()); for (const auto& be : buildEventCommands) { - cmCustomCommandGenerator beg(be, this->ConfigName, this->LocalGenerator); + cmCustomCommandGenerator beg(be, this->GetConfigName(), + this->LocalGenerator); const std::vector<std::string>& byproducts = beg.GetByproducts(); for (std::string const& byproduct : byproducts) { this->CleanFiles.insert( @@ -230,17 +244,19 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } std::vector<cmSourceFile const*> headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName); + this->GeneratorTarget->GetHeaderSources(headerSources, + this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - headerSources, this->MacOSXContentGenerator); + headerSources, this->MacOSXContentGenerator, this->GetConfigName()); std::vector<cmSourceFile const*> extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName); + this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - extraSources, this->MacOSXContentGenerator); + extraSources, this->MacOSXContentGenerator, this->GetConfigName()); const char* pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects, this->ConfigName); + this->GeneratorTarget->GetExternalObjects(externalObjects, + this->GetConfigName()); for (cmSourceFile const* sf : externalObjects) { auto const& objectFileName = sf->GetFullPath(); if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { @@ -248,7 +264,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } std::vector<cmSourceFile const*> objectSources; - this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName); + this->GeneratorTarget->GetObjectSources(objectSources, + this->GetConfigName()); for (cmSourceFile const* sf : objectSources) { // Generate this object file's rule file. this->WriteObjectRuleFiles(*sf); @@ -334,9 +351,9 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() } for (std::string const& language : languages) { - std::string flags = this->GetFlags(language); - std::string defines = this->GetDefines(language); - std::string includes = this->GetIncludes(language); + std::string flags = this->GetFlags(language, this->GetConfigName()); + std::string defines = this->GetDefines(language, this->GetConfigName()); + std::string includes = this->GetIncludes(language, this->GetConfigName()); // Escape comment characters so they do not terminate assignment. cmSystemTools::ReplaceString(flags, "#", "\\#"); cmSystemTools::ReplaceString(defines, "#", "\\#"); @@ -348,7 +365,7 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() } void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( - cmSourceFile const& source, const char* pkgloc) + cmSourceFile const& source, const char* pkgloc, const std::string& config) { // Skip OS X content when not building a Framework or Bundle. if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { @@ -356,7 +373,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( } std::string macdir = - this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc); + this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc, + config); // Get the input file location. std::string const& input = source.GetFullPath(); @@ -451,7 +469,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // generate the depend scanning rule this->WriteObjectDependRules(source, depends); - std::string config = this->LocalGenerator->GetConfigName(); + std::string config = this->GetConfigName(); std::string configUpper = cmSystemTools::UpperCase(config); // Add precompile headers dependencies @@ -593,16 +611,17 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( { std::string targetFullPathReal; std::string targetFullPathPDB; - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE || this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { targetFullPathReal = this->GeneratorTarget->GetFullPath( - this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true); - targetFullPathPDB = - cmStrCat(this->GeneratorTarget->GetPDBDirectory(this->ConfigName), '/', - this->GeneratorTarget->GetPDBName(this->ConfigName)); + this->GetConfigName(), cmStateEnums::RuntimeBinaryArtifact, true); + targetFullPathPDB = cmStrCat( + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/', + this->GeneratorTarget->GetPDBName(this->GetConfigName())); } targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( @@ -708,13 +727,15 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string workingDirectory = cmSystemTools::CollapseFullPath( this->LocalGenerator->GetCurrentBinaryDirectory()); compileCommand.replace(compileCommand.find(langFlags), langFlags.size(), - this->GetFlags(lang)); + this->GetFlags(lang, this->GetConfigName())); std::string langDefines = std::string("$(") + lang + "_DEFINES)"; compileCommand.replace(compileCommand.find(langDefines), - langDefines.size(), this->GetDefines(lang)); + langDefines.size(), + this->GetDefines(lang, this->GetConfigName())); std::string langIncludes = std::string("$(") + lang + "_INCLUDES)"; compileCommand.replace(compileCommand.find(langIncludes), - langIncludes.size(), this->GetIncludes(lang)); + langIncludes.size(), + this->GetIncludes(lang, this->GetConfigName())); const char* eliminate[] = { this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"), @@ -733,8 +754,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // See if we need to use a compiler launcher like ccache or distcc std::string compilerLauncher; if (!compileCommands.empty() && - (lang == "C" || lang == "CXX" || lang == "Fortran" || - lang == "CUDA")) { + (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || + lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); @@ -823,7 +844,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->LocalGenerator->CreateCDCommand( compileCommands, this->LocalGenerator->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, compileCommands); + cm::append(commands, compileCommands); } // Check for extra outputs created by the compilation. @@ -882,7 +903,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( preprocessCommands, this->LocalGenerator->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, preprocessCommands); + cm::append(commands, preprocessCommands); } else { std::string cmd = cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ", @@ -926,7 +947,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->LocalGenerator->CreateCDCommand( assemblyCommands, this->LocalGenerator->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, assemblyCommands); + cm::append(commands, assemblyCommands); } else { std::string cmd = cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ", @@ -1068,7 +1089,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() << "# Targets to which this target links.\n" << "set(CMAKE_TARGET_LINKED_INFO_FILES\n"; /* clang-format on */ - std::vector<std::string> dirs = this->GetLinkedTargetDirectories(); + std::vector<std::string> dirs = + this->GetLinkedTargetDirectories(this->GetConfigName()); for (std::string const& d : dirs) { *this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n"; } @@ -1171,9 +1193,9 @@ void cmMakefileTargetGenerator::DriveCustomCommands( sources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (cmSourceFile* source : sources) { if (cmCustomCommand* cc = source->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->ConfigName, + cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->LocalGenerator); - cmAppend(depends, ccg.GetOutputs()); + cm::append(depends, ccg.GetOutputs()); } } } @@ -1410,7 +1432,7 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule( } // Make sure the extra files are built. - cmAppend(depends, this->ExtraFiles); + cm::append(depends, this->ExtraFiles); } // Write the driver rule. @@ -1429,10 +1451,10 @@ void cmMakefileTargetGenerator::AppendTargetDepends( } // Loop over all library dependencies. - const std::string& cfg = this->LocalGenerator->GetConfigName(); + const std::string& cfg = this->GetConfigName(); if (cmComputeLinkInformation* cli = this->GeneratorTarget->GetLinkInformation(cfg)) { - cmAppend(depends, cli->GetDepends()); + cm::append(depends, cli->GetDepends()); } } @@ -1448,7 +1470,7 @@ void cmMakefileTargetGenerator::AppendObjectDepends( } // Add dependencies on the external object files. - cmAppend(depends, this->ExternalObjects); + cm::append(depends, this->ExternalObjects); // Add a dependency on the rule file itself. this->LocalGenerator->AppendRuleDepend(depends, @@ -1474,13 +1496,13 @@ void cmMakefileTargetGenerator::AppendLinkDepends( // Add a dependency on user-specified manifest files, if any. std::vector<cmSourceFile const*> manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, this->GetConfigName()); for (cmSourceFile const* manifest_src : manifest_srcs) { depends.push_back(manifest_src->GetFullPath()); } // Add user-specified dependencies. - this->GeneratorTarget->GetLinkDepends(depends, this->ConfigName, + this->GeneratorTarget->GetLinkDepends(depends, this->GetConfigName(), linkLanguage); } @@ -1488,10 +1510,11 @@ std::string cmMakefileTargetGenerator::GetLinkRule( const std::string& linkRuleVar) { std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar); - if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) { - std::string ruleVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_GNUtoMS_RULE"); + if (this->GeneratorTarget->HasImplibGNUtoMS(this->GetConfigName())) { + std::string ruleVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_GNUtoMS_RULE"); if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { linkRule += rule; } @@ -1612,7 +1635,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile( return responseFileName; } -cmLinkLineComputer* cmMakefileTargetGenerator::CreateLinkLineComputer( +std::unique_ptr<cmLinkLineComputer> +cmMakefileTargetGenerator::CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) { if (this->Makefile->IsOn("MSVC60")) { @@ -1630,7 +1654,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs( std::string frameworkPath; std::string linkPath; cmComputeLinkInformation* pcli = - this->GeneratorTarget->GetLinkInformation(this->ConfigName); + this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); linkLibs = frameworkPath + linkPath + linkLibs; @@ -1638,9 +1662,10 @@ void cmMakefileTargetGenerator::CreateLinkLibs( if (useResponseFile && linkLibs.find_first_not_of(' ') != std::string::npos) { // Lookup the response file reference flag. - std::string responseFlagVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_RESPONSE_FILE_LINK_FLAG"); + std::string responseFlagVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_RESPONSE_FILE_LINK_FLAG"); const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); if (!responseFlag) { responseFlag = "@"; @@ -1675,9 +1700,10 @@ void cmMakefileTargetGenerator::CreateObjectLists( this->WriteObjectsStrings(object_strings, responseFileLimit); // Lookup the response file reference flag. - std::string responseFlagVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_RESPONSE_FILE_LINK_FLAG"); + std::string responseFlagVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_RESPONSE_FILE_LINK_FLAG"); const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); if (!responseFlag) { responseFlag = "@"; @@ -1716,7 +1742,8 @@ void cmMakefileTargetGenerator::CreateObjectLists( } void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, - const std::string& lang) + const std::string& lang, + const std::string& /*config*/) { std::string responseVar = cmStrCat("CMAKE_", lang, "_USE_RESPONSE_FILE_FOR_INCLUDES"); @@ -1724,11 +1751,11 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, std::vector<std::string> includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - lang, this->ConfigName); + lang, this->GetConfigName()); std::string includeFlags = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, lang, false, useResponseFile, - this->ConfigName); + this->GetConfigName()); if (includeFlags.empty()) { return; } diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 7b9c7a5ffe..fd6293398f 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -52,6 +52,8 @@ public: cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; } + std::string GetConfigName(); + protected: void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage); @@ -81,7 +83,8 @@ protected: { } - void operator()(cmSourceFile const& source, const char* pkgloc) override; + void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) override; private: cmMakefileTargetGenerator* Generator; @@ -137,7 +140,7 @@ protected: std::vector<std::string>& makefile_commands, std::vector<std::string>& makefile_depends); - cmLinkLineComputer* CreateLinkLineComputer( + std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir); /** Create a response file with the given set of options. Returns @@ -163,7 +166,8 @@ protected: /** Add commands for generate def files */ void GenDefFile(std::vector<std::string>& real_link_commands); - void AddIncludeFlags(std::string& flags, const std::string& lang) override; + void AddIncludeFlags(std::string& flags, const std::string& lang, + const std::string& config) override; virtual void CloseFileStreams(); cmLocalUnixMakefileGenerator3* LocalGenerator; diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 1625e4fdb0..6c18e482e6 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -22,8 +22,7 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator( : cmMakefileTargetGenerator(target) { this->CustomCommandDriver = OnUtility; - this->OSXBundleGenerator = - cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 96a6386bf1..bf8183bbf1 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -3,6 +3,11 @@ #include "cmMessageCommand.h" #include <cassert> +#include <utility> + +#include <cm/string_view> + +#include "cm_static_string_view.hxx" #include "cmExecutionStatus.h" #include "cmMakefile.h" @@ -13,6 +18,55 @@ #include "cmSystemTools.h" #include "cmake.h" +namespace { + +enum class CheckingType +{ + UNDEFINED, + CHECK_START, + CHECK_PASS, + CHECK_FAIL +}; + +std::string IndentText(std::string text, cmMakefile& mf) +{ + auto indent = + cmJoin(cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT")), ""); + + const auto showContext = mf.GetCMakeInstance()->GetShowLogContext() || + mf.IsOn("CMAKE_MESSAGE_CONTEXT_SHOW"); + if (showContext) { + auto context = cmJoin( + cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT")), "."); + if (!context.empty()) { + indent.insert(0u, cmStrCat("["_s, context, "] "_s)); + } + } + + if (!indent.empty()) { + cmSystemTools::ReplaceString(text, "\n", "\n" + indent); + text.insert(0u, indent); + } + return text; +} + +void ReportCheckResult(cm::string_view what, std::string result, + cmMakefile& mf) +{ + if (mf.GetCMakeInstance()->HasCheckInProgress()) { + auto text = mf.GetCMakeInstance()->GetTopCheckInProgressMessage() + " - " + + std::move(result); + mf.DisplayStatus(IndentText(std::move(text), mf), -1); + } else { + mf.GetMessenger()->DisplayMessage( + MessageType::AUTHOR_WARNING, + cmStrCat("Ignored "_s, what, " without CHECK_START"_s), + mf.GetBacktrace()); + } +} + +} // anonymous namespace + // cmLibraryCommand bool cmMessageCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -21,11 +75,15 @@ bool cmMessageCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments"); return false; } + + auto& mf = status.GetMakefile(); + auto i = args.cbegin(); auto type = MessageType::MESSAGE; auto fatal = false; auto level = cmake::LogLevel::LOG_UNDEFINED; + auto checkingType = CheckingType::UNDEFINED; if (*i == "SEND_ERROR") { type = MessageType::FATAL_ERROR; level = cmake::LogLevel::LOG_ERROR; @@ -40,19 +98,30 @@ bool cmMessageCommand(std::vector<std::string> const& args, level = cmake::LogLevel::LOG_WARNING; ++i; } else if (*i == "AUTHOR_WARNING") { - if (status.GetMakefile().IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && - !status.GetMakefile().IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { + if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && + !mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { fatal = true; type = MessageType::AUTHOR_ERROR; level = cmake::LogLevel::LOG_ERROR; - } else if (!status.GetMakefile().IsOn( - "CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { + } else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { type = MessageType::AUTHOR_WARNING; level = cmake::LogLevel::LOG_WARNING; } else { return true; } ++i; + } else if (*i == "CHECK_START") { + level = cmake::LogLevel::LOG_STATUS; + checkingType = CheckingType::CHECK_START; + ++i; + } else if (*i == "CHECK_PASS") { + level = cmake::LogLevel::LOG_STATUS; + checkingType = CheckingType::CHECK_PASS; + ++i; + } else if (*i == "CHECK_FAIL") { + level = cmake::LogLevel::LOG_STATUS; + checkingType = CheckingType::CHECK_FAIL; + ++i; } else if (*i == "STATUS") { level = cmake::LogLevel::LOG_STATUS; ++i; @@ -66,12 +135,12 @@ bool cmMessageCommand(std::vector<std::string> const& args, level = cmake::LogLevel::LOG_TRACE; ++i; } else if (*i == "DEPRECATION") { - if (status.GetMakefile().IsOn("CMAKE_ERROR_DEPRECATED")) { + if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) { fatal = true; type = MessageType::DEPRECATION_ERROR; level = cmake::LogLevel::LOG_ERROR; - } else if (!status.GetMakefile().IsSet("CMAKE_WARN_DEPRECATED") || - status.GetMakefile().IsOn("CMAKE_WARN_DEPRECATED")) { + } else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") || + mf.IsOn("CMAKE_WARN_DEPRECATED")) { type = MessageType::DEPRECATION_WARNING; level = cmake::LogLevel::LOG_WARNING; } else { @@ -89,10 +158,19 @@ bool cmMessageCommand(std::vector<std::string> const& args, assert("Message log level expected to be set" && level != cmake::LogLevel::LOG_UNDEFINED); - auto desiredLevel = status.GetMakefile().GetCMakeInstance()->GetLogLevel(); + auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel(); assert("Expected a valid log level here" && desiredLevel != cmake::LogLevel::LOG_UNDEFINED); + // Command line option takes precedence over the cache variable + if (!mf.GetCMakeInstance()->WasLogLevelSetViaCLI()) { + const auto desiredLevelFromCache = + cmake::StringToLogLevel(mf.GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL")); + if (desiredLevelFromCache != cmake::LogLevel::LOG_UNDEFINED) { + desiredLevel = desiredLevelFromCache; + } + } + if (desiredLevel < level) { // Suppress the message return true; @@ -100,37 +178,42 @@ bool cmMessageCommand(std::vector<std::string> const& args, auto message = cmJoin(cmMakeRange(i, args.cend()), ""); - if (cmake::LogLevel::LOG_NOTICE <= level) { - // Check if any indentation has requested: - // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces - // to be joined and prepended to the message lines. - auto indent = cmJoin(cmExpandedList(status.GetMakefile().GetSafeDefinition( - "CMAKE_MESSAGE_INDENT")), - ""); - // Make every line of the `message` indented - // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted` - // here cuz it appends `\n` to the EOM ;-( - cmSystemTools::ReplaceString(message, "\n", "\n" + indent); - message = indent + message; - } - switch (level) { case cmake::LogLevel::LOG_ERROR: case cmake::LogLevel::LOG_WARNING: // we've overridden the message type, above, so display it directly - status.GetMakefile().GetMessenger()->DisplayMessage( - type, message, status.GetMakefile().GetBacktrace()); + mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace()); break; case cmake::LogLevel::LOG_NOTICE: - cmSystemTools::Message(message); + cmSystemTools::Message(IndentText(message, mf)); break; case cmake::LogLevel::LOG_STATUS: + switch (checkingType) { + case CheckingType::CHECK_START: + mf.DisplayStatus(IndentText(message, mf), -1); + mf.GetCMakeInstance()->PushCheckInProgressMessage(message); + break; + + case CheckingType::CHECK_PASS: + ReportCheckResult("CHECK_PASS"_s, message, mf); + break; + + case CheckingType::CHECK_FAIL: + ReportCheckResult("CHECK_FAIL"_s, message, mf); + break; + + default: + mf.DisplayStatus(IndentText(message, mf), -1); + break; + } + break; + case cmake::LogLevel::LOG_VERBOSE: case cmake::LogLevel::LOG_DEBUG: case cmake::LogLevel::LOG_TRACE: - status.GetMakefile().DisplayStatus(message, -1); + mf.DisplayStatus(IndentText(message, mf), -1); break; default: diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index beedef4c25..517241ee48 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -11,8 +11,8 @@ #include <utility> #include <cm/memory> +#include <cm/vector> -#include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" // IWYU pragma: keep #include "cmCustomCommandGenerator.h" @@ -41,33 +41,25 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( cmGeneratorTarget* target) : cmNinjaTargetGenerator(target) - , TargetLinkLanguage("") { - this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName()); - if (target->GetType() == cmStateEnums::EXECUTABLE) { - this->TargetNames = this->GetGeneratorTarget()->GetExecutableNames( - GetLocalGenerator()->GetConfigName()); - } else { - this->TargetNames = this->GetGeneratorTarget()->GetLibraryNames( - GetLocalGenerator()->GetConfigName()); - } - if (target->GetType() != cmStateEnums::OBJECT_LIBRARY) { // on Windows the output dir is already needed at compile time // ensure the directory exists (OutDir test) - EnsureDirectoryExists(target->GetDirectory(this->GetConfigName())); + for (auto const& config : this->GetConfigNames()) { + EnsureDirectoryExists(target->GetDirectory(config)); + } } - this->OSXBundleGenerator = - cm::make_unique<cmOSXBundleGenerator>(target, this->GetConfigName()); + this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default; -void cmNinjaNormalTargetGenerator::Generate() +void cmNinjaNormalTargetGenerator::Generate(const std::string& config) { - if (this->TargetLinkLanguage.empty()) { + std::string lang = this->GeneratorTarget->GetLinkerLanguage(config); + if (this->TargetLinkLanguage(config).empty()) { cmSystemTools::Error("CMake can not determine linker language for " "target: " + this->GetGeneratorTarget()->GetName()); @@ -75,25 +67,46 @@ void cmNinjaNormalTargetGenerator::Generate() } // Write the rules for each language. - this->WriteLanguagesRules(); + this->WriteLanguagesRules(config); // Write the build statements - this->WriteObjectBuildStatements(); + bool firstForConfig = true; + for (auto const& fileConfig : this->GetConfigNames()) { + if (fileConfig != config && + !this->GetGlobalGenerator()->EnableCrossConfigBuild()) { + continue; + } + this->WriteObjectBuildStatements(config, fileConfig, firstForConfig); + firstForConfig = false; + } if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) { - this->WriteObjectLibStatement(); + this->WriteObjectLibStatement(config); } else { // If this target has cuda language link inputs, and we need to do // device linking - this->WriteDeviceLinkStatement(); - this->WriteLinkStatement(); + this->WriteDeviceLinkStatement(config); + firstForConfig = true; + for (auto const& fileConfig : this->GetConfigNames()) { + if (fileConfig != config && + !this->GetGlobalGenerator()->EnableCrossConfigBuild()) { + continue; + } + this->WriteLinkStatement(config, fileConfig, firstForConfig); + firstForConfig = false; + } + } + if (this->GetGlobalGenerator()->EnableCrossConfigBuild()) { + this->GetGlobalGenerator()->AddTargetAlias( + this->GetTargetName(), this->GetGeneratorTarget(), "all"); } // Find ADDITIONAL_CLEAN_FILES - this->AdditionalCleanFiles(); + this->AdditionalCleanFiles(config); } -void cmNinjaNormalTargetGenerator::WriteLanguagesRules() +void cmNinjaNormalTargetGenerator::WriteLanguagesRules( + const std::string& config) { #ifdef NINJA_GEN_VERBOSE_FILES cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream()); @@ -106,8 +119,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() // Write rules for languages compiled in this target. std::set<std::string> languages; std::vector<cmSourceFile const*> sourceFiles; - this->GetGeneratorTarget()->GetObjectSources( - sourceFiles, this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE")); + this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config); for (cmSourceFile const* sf : sourceFiles) { std::string const lang = sf->GetLanguage(); if (!lang.empty()) { @@ -115,7 +127,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() } } for (std::string const& language : languages) { - this->WriteLanguageRules(language); + this->WriteLanguageRules(language, config); } } @@ -139,22 +151,26 @@ const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const } } -std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule() const +std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule( + const std::string& config) const { - return this->TargetLinkLanguage + "_" + + return this->TargetLinkLanguage(config) + "_" + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + "_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()); + this->GetGeneratorTarget()->GetName()) + + "_" + config; } -std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule() const +std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule( + const std::string& config) const { - return this->TargetLinkLanguage + "_" + + return this->TargetLinkLanguage(config) + "_" + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + "_DEVICE_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()); + this->GetGeneratorTarget()->GetName()) + + "_" + config; } struct cmNinjaRemoveNoOpCommands @@ -165,9 +181,10 @@ struct cmNinjaRemoveNoOpCommands } }; -void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) +void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule( + bool useResponseFile, const std::string& config) { - cmNinjaRule rule(this->LanguageLinkerDeviceRule()); + cmNinjaRule rule(this->LanguageLinkerDeviceRule(config)); if (!this->GetGlobalGenerator()->HasRule(rule.Name)) { cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); @@ -236,35 +253,39 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) } // If there is no ranlib the command will be ":". Skip it. - cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); + cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands()); rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); // Write the linker rule with response file if needed. - rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), '.'); - rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), " $TARGET_FILE"); + rule.Comment = + cmStrCat("Rule for linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), '.'); + rule.Description = + cmStrCat("Linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), " $TARGET_FILE"); rule.Restat = "$RESTAT"; this->GetGlobalGenerator()->AddRule(rule); } } -void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) +void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, + const std::string& config) { cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType(); - std::string linkRuleName = this->LanguageLinkerRule(); + std::string linkRuleName = this->LanguageLinkerRule(config); if (!this->GetGlobalGenerator()->HasRule(linkRuleName)) { cmNinjaRule rule(std::move(linkRuleName)); cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(targetType); - vars.Language = this->TargetLinkLanguage.c_str(); + std::string lang = this->TargetLinkLanguage(config); + vars.Language = config.c_str(); - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { vars.SwiftLibraryName = "$SWIFT_LIBRARY_NAME"; vars.SwiftModule = "$SWIFT_MODULE"; vars.SwiftModuleName = "$SWIFT_MODULE_NAME"; @@ -278,7 +299,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) std::string responseFlag; - std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage); + std::string cmakeVarLang = + cmStrCat("CMAKE_", this->TargetLinkLanguage(config)); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; @@ -286,7 +308,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) if (flag) { responseFlag = flag; - } else if (this->TargetLinkLanguage != "CUDA") { + } else if (this->TargetLinkLanguage(config) != "CUDA") { responseFlag = "@"; } @@ -304,7 +326,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) rule.RspContent = "$in_newline"; } rule.RspContent += " $LINK_PATH $LINK_LIBRARIES"; - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { vars.SwiftSources = responseFlag.c_str(); } else { vars.Objects = responseFlag.c_str(); @@ -359,7 +381,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) this->GetLocalGenerator()->CreateRulePlaceholderExpander()); // Rule for linking library/executable. - std::vector<std::string> linkCmds = this->ComputeLinkCmd(); + std::vector<std::string> linkCmds = this->ComputeLinkCmd(config); for (std::string& linkCmd : linkCmds) { linkCmd = cmStrCat(launcher, linkCmd); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), @@ -367,22 +389,25 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) } // If there is no ranlib the command will be ":". Skip it. - cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); + cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands()); linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); linkCmds.emplace_back("$POST_BUILD"); rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); // Write the linker rule with response file if needed. - rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), '.'); - rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), " $TARGET_FILE"); + rule.Comment = + cmStrCat("Rule for linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), '.'); + rule.Description = + cmStrCat("Linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), " $TARGET_FILE"); rule.Restat = "$RESTAT"; this->GetGlobalGenerator()->AddRule(rule); } - if (this->TargetNames.Output != this->TargetNames.Real && + auto const tgtNames = this->TargetNames(config); + if (tgtNames.Output != tgtNames.Real && !this->GetGeneratorTarget()->IsFrameworkOnApple()) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -441,7 +466,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd() return linkCmds; } -std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() +std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( + const std::string& config) { std::vector<std::string> linkCmds; cmMakefile* mf = this->GetMakefile(); @@ -450,14 +476,14 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() // this occurs when things like IPO is enabled, and we need to use the // CMAKE_<lang>_CREATE_STATIC_LIBRARY_IPO define instead. std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable( - this->TargetLinkLanguage, this->GetConfigName()); + this->TargetLinkLanguage(config), config); const char* linkCmd = mf->GetDefinition(linkCmdVar); if (linkCmd) { std::string linkCmdStr = linkCmd; - if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) { - std::string ruleVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_GNUtoMS_RULE"); + if (this->GetGeneratorTarget()->HasImplibGNUtoMS(config)) { + std::string ruleVar = + cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(config), + "_GNUtoMS_RULE"); if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { linkCmdStr += rule; } @@ -469,9 +495,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), " -E __run_co_compile --lwyu="); cmGeneratorTarget& gt = *this->GetGeneratorTarget(); - const std::string cfgName = this->GetConfigName(); std::string targetOutputReal = this->ConvertToNinjaPath( - gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, + gt.GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, /*realname=*/true)); cmakeCommand += targetOutputReal; linkCmds.push_back(std::move(cmakeCommand)); @@ -486,25 +511,25 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); - linkCmds.push_back(cmakeCommand + " -E remove $TARGET_FILE"); + linkCmds.push_back(cmakeCommand + " -E rm -f $TARGET_FILE"); } // TODO: Use ARCHIVE_APPEND for archives over a certain size. { - std::string linkCmdVar = - cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_CREATE"); + std::string linkCmdVar = cmStrCat( + "CMAKE_", this->TargetLinkLanguage(config), "_ARCHIVE_CREATE"); linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); + linkCmdVar, this->TargetLinkLanguage(config), config); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmExpandList(linkCmd, linkCmds); } { - std::string linkCmdVar = - cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_FINISH"); + std::string linkCmdVar = cmStrCat( + "CMAKE_", this->TargetLinkLanguage(config), "_ARCHIVE_FINISH"); linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); + linkCmdVar, this->TargetLinkLanguage(config), config); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmExpandList(linkCmd, linkCmds); @@ -535,7 +560,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() return std::vector<std::string>(); } -void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() +void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( + const std::string& config) { cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); if (!globalGen->GetLanguageEnabled("CUDA")) { @@ -545,7 +571,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() cmGeneratorTarget* genTarget = this->GetGeneratorTarget(); bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->GetLocalGenerator(), this->ConfigName); + *this->GeneratorTarget, *this->GetLocalGenerator(), config); if (!requiresDeviceLinking) { return; } @@ -558,24 +584,23 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() std::string const& objExt = this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); - std::string const cfgName = this->GetConfigName(); std::string const targetOutputReal = ConvertToNinjaPath( genTarget->ObjectDirectory + "cmake_device_link" + objExt); std::string const targetOutputImplib = ConvertToNinjaPath( - genTarget->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); + genTarget->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); this->DeviceLinkObject = targetOutputReal; // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); + cmGlobalNinjaGenerator::WriteDivider(this->GetCommonFileStream()); const cmStateEnums::TargetType targetType = genTarget->GetType(); - this->GetBuildFileStream() << "# Device Link build statements for " - << cmState::GetTargetTypeName(targetType) - << " target " << this->GetTargetName() << "\n\n"; + this->GetCommonFileStream() << "# Device Link build statements for " + << cmState::GetTargetTypeName(targetType) + << " target " << this->GetTargetName() << "\n\n"; // Compute the comment. - cmNinjaBuild build(this->LanguageLinkerDeviceRule()); + cmNinjaBuild build(this->LanguageLinkerDeviceRule(config)); build.Comment = cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal); @@ -584,14 +609,15 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // Compute outputs. build.Outputs.push_back(targetOutputReal); // Compute specific libraries to link with. - build.ExplicitDeps = this->GetObjects(); - build.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); + build.ExplicitDeps = this->GetObjects(config); + build.ImplicitDeps = + this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); std::string frameworkPath; std::string linkPath; - std::string createRule = genTarget->GetCreateRuleVariable( - this->TargetLinkLanguage, this->GetConfigName()); + std::string createRule = + genTarget->GetCreateRuleVariable(this->TargetLinkLanguage(config), config); const bool useWatcomQuote = this->GetMakefile()->IsOn(createRule + "_USE_WATCOM_QUOTE"); cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator(); @@ -605,17 +631,17 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(), globalGen)); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); + linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig()); localGen.GetTargetFlags( - linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"], - vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget); + linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"], + vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget); this->addPoolNinjaVariable("JOB_POOL_LINK", genTarget, vars); - vars["LINK_FLAGS"] = - cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); + vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); - vars["MANIFESTS"] = this->GetManifests(); + vars["MANIFESTS"] = this->GetManifests(config); vars["LINK_PATH"] = frameworkPath + linkPath; @@ -624,24 +650,25 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // code between the Makefile executable and library generators. if (targetType == cmStateEnums::EXECUTABLE) { std::string t = vars["FLAGS"]; - localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, config); vars["FLAGS"] = t; } else { std::string t = vars["ARCH_FLAGS"]; - localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, config); vars["ARCH_FLAGS"] = t; t.clear(); localGen.AddLanguageFlagsForLinking(t, genTarget, cudaLinkLanguage, - cfgName); + config); vars["LANGUAGE_COMPILE_FLAGS"] = t; } - if (genTarget->HasSOName(cfgName)) { + auto const tgtNames = this->TargetNames(config); + if (genTarget->HasSOName(config)) { vars["SONAME_FLAG"] = - this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage); - vars["SONAME"] = this->TargetNames.SharedObject; + this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage(config)); + vars["SONAME"] = tgtNames.SharedObject; if (targetType == cmStateEnums::SHARED_LIBRARY) { std::string install_dir = - this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName); + this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(config); if (!install_dir.empty()) { vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat( install_dir, cmOutputConverter::SHELL); @@ -649,25 +676,28 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() } } - if (!this->TargetNames.ImportLibrary.empty()) { + if (!tgtNames.ImportLibrary.empty()) { const std::string impLibPath = localGen.ConvertToOutputFormat( targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; EnsureParentDirectoryExists(impLibPath); } - const std::string objPath = GetGeneratorTarget()->GetSupportDirectory(); + const std::string objPath = + cmStrCat(GetGeneratorTarget()->GetSupportDirectory(), + globalGen->ConfigDirectory(config)); + vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL); EnsureDirectoryExists(objPath); - this->SetMsvcTargetPdbVariable(vars); + this->SetMsvcTargetPdbVariable(vars, config); + std::string& linkLibraries = vars["LINK_LIBRARIES"]; + std::string& link_path = vars["LINK_PATH"]; if (globalGen->IsGCCOnWindows()) { // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) - std::string& linkLibraries = vars["LINK_LIBRARIES"]; std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); - std::string& link_path = vars["LINK_PATH"]; std::replace(link_path.begin(), link_path.end(), '\\', '/'); } @@ -675,65 +705,88 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // do not check if the user has explicitly forced a response file. int const commandLineLengthLimit = static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) - - globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule()); + globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule(config)); build.RspFile = this->ConvertToNinjaPath(std::string("CMakeFiles/") + genTarget->GetName() + ".rsp"); // Gather order-only dependencies. - this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(), - build.OrderOnlyDeps); + this->GetLocalGenerator()->AppendTargetDepends( + this->GetGeneratorTarget(), build.OrderOnlyDeps, config, config); // Write the build statement for this target. bool usedResponseFile = false; - globalGen->WriteBuild(this->GetBuildFileStream(), build, + globalGen->WriteBuild(this->GetCommonFileStream(), build, commandLineLengthLimit, &usedResponseFile); - this->WriteDeviceLinkRule(usedResponseFile); + this->WriteDeviceLinkRule(usedResponseFile, config); } -void cmNinjaNormalTargetGenerator::WriteLinkStatement() +void cmNinjaNormalTargetGenerator::WriteLinkStatement( + const std::string& config, const std::string& fileConfig, + bool firstForConfig) { cmMakefile* mf = this->GetMakefile(); cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); cmGeneratorTarget* gt = this->GetGeneratorTarget(); - const std::string cfgName = this->GetConfigName(); - std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(cfgName)); + std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(config)); std::string targetOutputReal = ConvertToNinjaPath( - gt->GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, + gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, /*realname=*/true)); std::string targetOutputImplib = ConvertToNinjaPath( - gt->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); + gt->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); + + if (config != fileConfig) { + if (targetOutput == ConvertToNinjaPath(gt->GetFullPath(fileConfig))) { + return; + } + if (targetOutputReal == + ConvertToNinjaPath(gt->GetFullPath(fileConfig, + cmStateEnums::RuntimeBinaryArtifact, + /*realname=*/true))) { + return; + } + if (!gt->GetFullName(config, cmStateEnums::ImportLibraryArtifact) + .empty() && + !gt->GetFullName(fileConfig, cmStateEnums::ImportLibraryArtifact) + .empty() && + targetOutputImplib == + ConvertToNinjaPath(gt->GetFullPath( + fileConfig, cmStateEnums::ImportLibraryArtifact))) { + return; + } + } + auto const tgtNames = this->TargetNames(config); if (gt->IsAppBundleOnApple()) { // Create the app bundle - std::string outpath = gt->GetDirectory(cfgName); - this->OSXBundleGenerator->CreateAppBundle(this->TargetNames.Output, - outpath); + std::string outpath = gt->GetDirectory(config); + this->OSXBundleGenerator->CreateAppBundle(tgtNames.Output, outpath, + config); // Calculate the output path - targetOutput = cmStrCat(outpath, '/', this->TargetNames.Output); + targetOutput = cmStrCat(outpath, '/', tgtNames.Output); targetOutput = this->ConvertToNinjaPath(targetOutput); - targetOutputReal = cmStrCat(outpath, '/', this->TargetNames.Real); + targetOutputReal = cmStrCat(outpath, '/', tgtNames.Real); targetOutputReal = this->ConvertToNinjaPath(targetOutputReal); } else if (gt->IsFrameworkOnApple()) { // Create the library framework. - this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output, - gt->GetDirectory(cfgName)); + this->OSXBundleGenerator->CreateFramework( + tgtNames.Output, gt->GetDirectory(config), config); } else if (gt->IsCFBundleOnApple()) { // Create the core foundation bundle. - this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, - gt->GetDirectory(cfgName)); + this->OSXBundleGenerator->CreateCFBundle(tgtNames.Output, + gt->GetDirectory(config), config); } // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); + cmGlobalNinjaGenerator::WriteDivider(this->GetConfigFileStream(fileConfig)); const cmStateEnums::TargetType targetType = gt->GetType(); - this->GetBuildFileStream() + this->GetConfigFileStream(fileConfig) << "# Link build statements for " << cmState::GetTargetTypeName(targetType) << " target " << this->GetTargetName() << "\n\n"; - cmNinjaBuild linkBuild(this->LanguageLinkerRule()); + cmNinjaBuild linkBuild(this->LanguageLinkerRule(config)); cmNinjaVars& vars = linkBuild.Variables; // Compute the comment. @@ -742,11 +795,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Compute outputs. linkBuild.Outputs.push_back(targetOutputReal); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutputReal); + } - if (this->TargetLinkLanguage == "Swift") { - vars["SWIFT_LIBRARY_NAME"] = [this]() -> std::string { + if (this->TargetLinkLanguage(config) == "Swift") { + vars["SWIFT_LIBRARY_NAME"] = [this, config]() -> std::string { cmGeneratorTarget::Names targetNames = - this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName()); + this->GetGeneratorTarget()->GetLibraryNames(config); return targetNames.Base; }(); @@ -782,12 +838,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() "/output-file-map.json"), cmOutputConverter::SHELL); - vars["SWIFT_SOURCES"] = [this]() -> std::string { + vars["SWIFT_SOURCES"] = [this, config]() -> std::string { std::vector<cmSourceFile const*> sources; std::stringstream oss; - this->GetGeneratorTarget()->GetObjectSources(sources, - this->GetConfigName()); + this->GetGeneratorTarget()->GetObjectSources(sources, config); cmLocalGenerator const* LocalGen = this->GetLocalGenerator(); for (const auto& source : sources) { oss << " " @@ -801,27 +856,28 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Since we do not perform object builds, compute the // defines/flags/includes here so that they can be passed along // appropriately. - vars["DEFINES"] = this->GetDefines("Swift"); - vars["FLAGS"] = this->GetFlags("Swift"); - vars["INCLUDES"] = this->GetIncludes("Swift"); + vars["DEFINES"] = this->GetDefines("Swift", config); + vars["FLAGS"] = this->GetFlags("Swift", config); + vars["INCLUDES"] = this->GetIncludes("Swift", config); } // Compute specific libraries to link with. - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { std::vector<cmSourceFile const*> sources; - gt->GetObjectSources(sources, this->GetConfigName()); + gt->GetObjectSources(sources, config); for (const auto& source : sources) { linkBuild.Outputs.push_back( - this->ConvertToNinjaPath(this->GetObjectFilePath(source))); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config))); linkBuild.ExplicitDeps.push_back( this->ConvertToNinjaPath(this->GetSourceFilePath(source))); } linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]); } else { - linkBuild.ExplicitDeps = this->GetObjects(); + linkBuild.ExplicitDeps = this->GetObjects(config); } - linkBuild.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); + linkBuild.ImplicitDeps = + this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); if (!this->DeviceLinkObject.empty()) { linkBuild.ExplicitDeps.push_back(this->DeviceLinkObject); @@ -831,39 +887,41 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string linkPath; std::string createRule = - gt->GetCreateRuleVariable(this->TargetLinkLanguage, this->GetConfigName()); + gt->GetCreateRuleVariable(this->TargetLinkLanguage(config), config); bool useWatcomQuote = mf->IsOn(createRule + "_USE_WATCOM_QUOTE"); cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator(); vars["TARGET_FILE"] = localGen.ConvertToOutputFormat(targetOutputReal, cmOutputConverter::SHELL); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineComputer> linkLineComputer = globalGen->CreateLinkLineComputer( this->GetLocalGenerator(), - this->GetLocalGenerator()->GetStateSnapshot().GetDirectory())); + this->GetLocalGenerator()->GetStateSnapshot().GetDirectory()); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); + linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig()); - localGen.GetTargetFlags(linkLineComputer.get(), this->GetConfigName(), + localGen.GetTargetFlags(linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, gt); // Add OS X version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { - this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage, - "COMPATIBILITY", true); - this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage, - "CURRENT", false); + this->AppendOSXVerFlag(vars["LINK_FLAGS"], + this->TargetLinkLanguage(config), "COMPATIBILITY", + true); + this->AppendOSXVerFlag(vars["LINK_FLAGS"], + this->TargetLinkLanguage(config), "CURRENT", false); } this->addPoolNinjaVariable("JOB_POOL_LINK", gt, vars); - this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]); - vars["LINK_FLAGS"] = - cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); + this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], + config); + vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); - vars["MANIFESTS"] = this->GetManifests(); + vars["MANIFESTS"] = this->GetManifests(config); vars["LINK_PATH"] = frameworkPath + linkPath; std::string lwyuFlags; @@ -876,23 +934,26 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // code between the Makefile executable and library generators. if (targetType == cmStateEnums::EXECUTABLE) { std::string t = vars["FLAGS"]; - localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config), + config); t += lwyuFlags; vars["FLAGS"] = t; } else { std::string t = vars["ARCH_FLAGS"]; - localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config), + config); vars["ARCH_FLAGS"] = t; t.clear(); t += lwyuFlags; - localGen.AddLanguageFlagsForLinking(t, gt, TargetLinkLanguage, cfgName); + localGen.AddLanguageFlagsForLinking( + t, gt, this->TargetLinkLanguage(config), config); vars["LANGUAGE_COMPILE_FLAGS"] = t; } - if (gt->HasSOName(cfgName)) { - vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage); - vars["SONAME"] = this->TargetNames.SharedObject; + if (gt->HasSOName(config)) { + vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage(config)); + vars["SONAME"] = tgtNames.SharedObject; if (targetType == cmStateEnums::SHARED_LIBRARY) { - std::string install_dir = gt->GetInstallNameDirForBuildTree(cfgName); + std::string install_dir = gt->GetInstallNameDirForBuildTree(config); if (!install_dir.empty()) { vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat( install_dir, cmOutputConverter::SHELL); @@ -902,17 +963,21 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() cmNinjaDeps byproducts; - if (!this->TargetNames.ImportLibrary.empty()) { + if (!tgtNames.ImportLibrary.empty()) { const std::string impLibPath = localGen.ConvertToOutputFormat( targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; EnsureParentDirectoryExists(impLibPath); - if (gt->HasImportLibrary(cfgName)) { + if (gt->HasImportLibrary(config)) { byproducts.push_back(targetOutputImplib); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back( + targetOutputImplib); + } } } - if (!this->SetMsvcTargetPdbVariable(vars)) { + if (!this->SetMsvcTargetPdbVariable(vars, config)) { // It is common to place debug symbols at a specific place, // so we need a plain target name in the rule available. std::string prefix; @@ -927,16 +992,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["TARGET_PDB"] = base + suffix + dbg_suffix; } - const std::string objPath = gt->GetSupportDirectory(); + const std::string objPath = + cmStrCat(gt->GetSupportDirectory(), globalGen->ConfigDirectory(config)); vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL); EnsureDirectoryExists(objPath); + std::string& linkLibraries = vars["LINK_LIBRARIES"]; + std::string& link_path = vars["LINK_PATH"]; if (globalGen->IsGCCOnWindows()) { // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) - std::string& linkLibraries = vars["LINK_LIBRARIES"]; std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); - std::string& link_path = vars["LINK_PATH"]; std::replace(link_path.begin(), link_path.end(), '\\', '/'); } @@ -947,23 +1013,30 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::vector<std::string> preLinkCmdLines; std::vector<std::string> postBuildCmdLines; - std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines, - &preLinkCmdLines, - &postBuildCmdLines }; - - for (unsigned i = 0; i != 3; ++i) { - for (cmCustomCommand const& cc : *cmdLists[i]) { - cmCustomCommandGenerator ccg(cc, cfgName, this->GetLocalGenerator()); - localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); - std::vector<std::string> const& ccByproducts = ccg.GetByproducts(); - std::transform(ccByproducts.begin(), ccByproducts.end(), - std::back_inserter(byproducts), MapToNinjaPath()); + + if (config == fileConfig) { + std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines, + &preLinkCmdLines, + &postBuildCmdLines }; + + for (unsigned i = 0; i != 3; ++i) { + for (cmCustomCommand const& cc : *cmdLists[i]) { + cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator()); + localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); + std::vector<std::string> const& ccByproducts = ccg.GetByproducts(); + std::transform(ccByproducts.begin(), ccByproducts.end(), + std::back_inserter(byproducts), MapToNinjaPath()); + std::transform( + ccByproducts.begin(), ccByproducts.end(), + std::back_inserter(globalGen->GetByproductsForCleanTarget()), + MapToNinjaPath()); + } } } // maybe create .def file from list of objects cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - gt->GetModuleDefinitionInfo(this->GetConfigName()); + gt->GetModuleDefinitionInfo(config); if (mdi && mdi->DefFileGenerated) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -989,7 +1062,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() cmGeneratedFileStream fout(obj_list_file); if (mdi->WindowsExportAllSymbols) { - cmNinjaDeps objs = this->GetObjects(); + cmNinjaDeps objs = this->GetObjects(config); for (std::string const& obj : objs) { if (cmHasLiteralSuffix(obj, ".obj")) { fout << obj << "\n"; @@ -1024,7 +1097,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() symlinkVars["POST_BUILD"] = postBuildCmdLine; } - std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage); + std::string cmakeVarLang = + cmStrCat("CMAKE_", this->TargetLinkLanguage(config)); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; @@ -1032,8 +1106,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar); bool const lang_supports_response = - !(this->TargetLinkLanguage == "RC" || - (this->TargetLinkLanguage == "CUDA" && !flag)); + !(this->TargetLinkLanguage(config) == "RC" || + (this->TargetLinkLanguage(config) == "CUDA" && !flag)); int commandLineLengthLimit = -1; if (!lang_supports_response || !this->ForceResponseFile()) { commandLineLengthLimit = @@ -1045,18 +1119,19 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() gt->GetName() + ".rsp"); // Gather order-only dependencies. - this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps); + this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps, + config, fileConfig); // Add order-only dependencies on versioning symlinks of shared libs we link. if (!this->GeneratorTarget->IsDLLPlatform()) { if (cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->GetConfigName())) { + this->GeneratorTarget->GetLinkInformation(config)) { for (auto const& item : cli->GetItems()) { if (item.Target && item.Target->GetType() == cmStateEnums::SHARED_LIBRARY && !item.Target->IsFrameworkOnApple()) { - std::string const& lib = this->ConvertToNinjaPath( - item.Target->GetFullPath(this->GetConfigName())); + std::string const& lib = + this->ConvertToNinjaPath(item.Target->GetFullPath(config)); if (std::find(linkBuild.ImplicitDeps.begin(), linkBuild.ImplicitDeps.end(), lib) == linkBuild.ImplicitDeps.end()) { @@ -1077,24 +1152,27 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Write the build statement for this target. bool usedResponseFile = false; - globalGen->WriteBuild(this->GetBuildFileStream(), linkBuild, + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), linkBuild, commandLineLengthLimit, &usedResponseFile); - this->WriteLinkRule(usedResponseFile); + this->WriteLinkRule(usedResponseFile, config); if (symlinkNeeded) { if (targetType == cmStateEnums::EXECUTABLE) { cmNinjaBuild build("CMAKE_SYMLINK_EXECUTABLE"); build.Comment = "Create executable symlink " + targetOutput; build.Outputs.push_back(targetOutput); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutput); + } build.ExplicitDeps.push_back(targetOutputReal); build.Variables = std::move(symlinkVars); - globalGen->WriteBuild(this->GetBuildFileStream(), build); + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), build); } else { cmNinjaBuild build("CMAKE_SYMLINK_LIBRARY"); build.Comment = "Create library symlink " + targetOutput; std::string const soName = this->ConvertToNinjaPath( - this->GetTargetFilePath(this->TargetNames.SharedObject)); + this->GetTargetFilePath(tgtNames.SharedObject, config)); // If one link has to be created. if (targetOutputReal == soName || targetOutput == soName) { symlinkVars["SONAME"] = @@ -1103,33 +1181,58 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } else { symlinkVars["SONAME"].clear(); build.Outputs.push_back(soName); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(soName); + } } build.Outputs.push_back(targetOutput); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutput); + } build.ExplicitDeps.push_back(targetOutputReal); build.Variables = std::move(symlinkVars); - globalGen->WriteBuild(this->GetBuildFileStream(), build); + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), build); } } // Add aliases for the file name and the target name. - globalGen->AddTargetAlias(this->TargetNames.Output, gt); - globalGen->AddTargetAlias(this->GetTargetName(), gt); + globalGen->AddTargetAlias(tgtNames.Output, gt, config); + globalGen->AddTargetAlias(this->GetTargetName(), gt, config); } -void cmNinjaNormalTargetGenerator::WriteObjectLibStatement() +void cmNinjaNormalTargetGenerator::WriteObjectLibStatement( + const std::string& config) { // Write a phony output that depends on all object files. { cmNinjaBuild build("phony"); build.Comment = "Object library " + this->GetTargetName(); this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(), - build.Outputs); - build.ExplicitDeps = this->GetObjects(); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + build.Outputs, config); + this->GetLocalGenerator()->AppendTargetOutputs( + this->GetGeneratorTarget(), + this->GetGlobalGenerator()->GetByproductsForCleanTarget(config), config); + build.ExplicitDeps = this->GetObjects(config); + this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), build); } // Add aliases for the target name. - this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), - this->GetGeneratorTarget()); + this->GetGlobalGenerator()->AddTargetAlias( + this->GetTargetName(), this->GetGeneratorTarget(), config); +} + +cmGeneratorTarget::Names cmNinjaNormalTargetGenerator::TargetNames( + const std::string& config) const +{ + if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { + return this->GeneratorTarget->GetExecutableNames(config); + } + return this->GeneratorTarget->GetLibraryNames(config); +} + +std::string cmNinjaNormalTargetGenerator::TargetLinkLanguage( + const std::string& config) const +{ + return this->GeneratorTarget->GetLinkerLanguage(config); } diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index ebc1268232..cda76d8da8 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -17,30 +17,31 @@ public: cmNinjaNormalTargetGenerator(cmGeneratorTarget* target); ~cmNinjaNormalTargetGenerator() override; - void Generate() override; + void Generate(const std::string& config) override; private: - std::string LanguageLinkerRule() const; - std::string LanguageLinkerDeviceRule() const; + std::string LanguageLinkerRule(const std::string& config) const; + std::string LanguageLinkerDeviceRule(const std::string& config) const; const char* GetVisibleTypeName() const; - void WriteLanguagesRules(); + void WriteLanguagesRules(const std::string& config); - void WriteLinkRule(bool useResponseFile); - void WriteDeviceLinkRule(bool useResponseFile); + void WriteLinkRule(bool useResponseFile, const std::string& config); + void WriteDeviceLinkRule(bool useResponseFile, const std::string& config); - void WriteLinkStatement(); - void WriteDeviceLinkStatement(); + void WriteLinkStatement(const std::string& config, + const std::string& fileConfig, bool firstForConfig); + void WriteDeviceLinkStatement(const std::string& config); - void WriteObjectLibStatement(); + void WriteObjectLibStatement(const std::string& config); - std::vector<std::string> ComputeLinkCmd(); + std::vector<std::string> ComputeLinkCmd(const std::string& config); std::vector<std::string> ComputeDeviceLinkCmd(); private: // Target name info. - cmGeneratorTarget::Names TargetNames; - std::string TargetLinkLanguage; + cmGeneratorTarget::Names TargetNames(const std::string& config) const; + std::string TargetLinkLanguage(const std::string& config) const; std::string DeviceLinkObject; }; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 919a5dbb3c..bd19b28bcc 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -10,11 +10,11 @@ #include <utility> #include <cm/memory> +#include <cmext/algorithm> #include "cm_jsoncpp_value.h" #include "cm_jsoncpp_writer.h" -#include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" #include "cmGeneratedFileStream.h" @@ -68,9 +68,15 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target) cmNinjaTargetGenerator::~cmNinjaTargetGenerator() = default; -cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const +cmGeneratedFileStream& cmNinjaTargetGenerator::GetConfigFileStream( + const std::string& config) const { - return *this->GetGlobalGenerator()->GetBuildFileStream(); + return *this->GetGlobalGenerator()->GetConfigFileStream(config); +} + +cmGeneratedFileStream& cmNinjaTargetGenerator::GetCommonFileStream() const +{ + return *this->GetGlobalGenerator()->GetCommonFileStream(); } cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const @@ -84,17 +90,19 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const } std::string cmNinjaTargetGenerator::LanguageCompilerRule( - const std::string& lang) const + const std::string& lang, const std::string& config) const { return lang + "_COMPILER__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } std::string cmNinjaTargetGenerator::LanguagePreprocessRule( - std::string const& lang) const + std::string const& lang, const std::string& config) const { return lang + "_PREPROCESS__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } bool cmNinjaTargetGenerator::NeedExplicitPreprocessing( @@ -117,10 +125,11 @@ bool cmNinjaTargetGenerator::CompilePreprocessedSourceWithDefines( } std::string cmNinjaTargetGenerator::LanguageDyndepRule( - const std::string& lang) const + const std::string& lang, const std::string& config) const { return lang + "_DYNDEP__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const @@ -128,9 +137,11 @@ bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const return lang == "Fortran"; } -std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget() +std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget( + const std::string& config) { - return "cmake_object_order_depends_target_" + this->GetTargetName(); + return cmGlobalNinjaGenerator::OrderDependsTargetForTarget( + this->GeneratorTarget, config); } // TODO: Most of the code is picked up from @@ -138,10 +149,10 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget() // void cmMakefileTargetGenerator::WriteTargetLanguageFlags() // Refactor it. std::string cmNinjaTargetGenerator::ComputeFlagsForObject( - cmSourceFile const* source, const std::string& language) + cmSourceFile const* source, const std::string& language, + const std::string& config) { - std::string flags = this->GetFlags(language); - const std::string configName = this->LocalGenerator->GetConfigName(); + std::string flags = this->GetFlags(language, config); // Add Fortran format flags. if (language == "Fortran") { @@ -150,7 +161,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add source file specific flags. cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, configName, this->GeneratorTarget, language); + this->LocalGenerator, config, this->GeneratorTarget, language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) { @@ -166,16 +177,16 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add precompile headers compile options. const std::string pchSource = - this->GeneratorTarget->GetPchSource(configName, language); + this->GeneratorTarget->GetPchSource(config, language); if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { std::string pchOptions; if (source->GetFullPath() == pchSource) { - pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions( - configName, language); + pchOptions = + this->GeneratorTarget->GetPchCreateCompileOptions(config, language); } else { pchOptions = - this->GeneratorTarget->GetPchUseCompileOptions(configName, language); + this->GeneratorTarget->GetPchUseCompileOptions(config, language); } this->LocalGenerator->AppendCompileOptions( @@ -186,16 +197,17 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( } void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, - std::string const& language) + std::string const& language, + const std::string& config) { std::vector<std::string> includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - language, this->GetConfigName()); + language, config); // Add include directory flags. std::string includeFlags = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, language, language == "RC", // full include paths for RC needed by cmcldeps - false, this->GetConfigName()); + false, config); if (this->GetGlobalGenerator()->IsGCCOnWindows()) { std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/'); } @@ -232,13 +244,18 @@ bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const // TODO: Refactor with // void cmMakefileTargetGenerator::WriteTargetLanguageFlags(). std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, - const std::string& language) + const std::string& language, + const std::string& config) { std::set<std::string> defines; - const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( this->LocalGenerator, config, this->GeneratorTarget, language); + // Seriously?? + if (this->GetGlobalGenerator()->IsMultiConfig()) { + defines.insert(cmStrCat("CMAKE_INTDIR=\"", config, '"')); + } + const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { this->LocalGenerator->AppendDefines( @@ -253,17 +270,17 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS)); } - std::string definesString = this->GetDefines(language); + std::string definesString = this->GetDefines(language, config); this->LocalGenerator->JoinDefines(defines, definesString, language); return definesString; } std::string cmNinjaTargetGenerator::ComputeIncludes( - cmSourceFile const* source, const std::string& language) + cmSourceFile const* source, const std::string& language, + const std::string& config) { std::vector<std::string> includes; - const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( this->LocalGenerator, config, this->GeneratorTarget, language); @@ -277,13 +294,13 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( std::string includesString = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, language, true, false, config); this->LocalGenerator->AppendFlags(includesString, - this->GetIncludes(language)); + this->GetIncludes(language, config)); return includesString; } cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( - const std::string& linkLanguage) const + const std::string& linkLanguage, const std::string& config) const { // Static libraries never depend on other targets for linking. if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -292,7 +309,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( } cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); + this->GeneratorTarget->GetLinkInformation(config); if (!cli) { return cmNinjaDeps(); } @@ -303,8 +320,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( // Add a dependency on the link definitions file, if any. if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - this->GeneratorTarget->GetModuleDefinitionInfo( - this->GetConfigName())) { + this->GeneratorTarget->GetModuleDefinitionInfo(config)) { for (cmSourceFile const* src : mdi->Sources) { result.push_back(this->ConvertToNinjaPath(src->GetFullPath())); } @@ -312,15 +328,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( // Add a dependency on user-specified manifest files, if any. std::vector<cmSourceFile const*> manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, config); for (cmSourceFile const* manifest_src : manifest_srcs) { result.push_back(this->ConvertToNinjaPath(manifest_src->GetFullPath())); } // Add user-specified dependencies. std::vector<std::string> linkDeps; - this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName, - linkLanguage); + this->GeneratorTarget->GetLinkDepends(linkDeps, config, linkLanguage); std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result), MapToNinjaPath()); @@ -334,7 +349,7 @@ std::string cmNinjaTargetGenerator::GetSourceFilePath( } std::string cmNinjaTargetGenerator::GetObjectFilePath( - cmSourceFile const* source) const + cmSourceFile const* source, const std::string& config) const { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { @@ -342,13 +357,14 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath( } std::string const& objectName = this->GeneratorTarget->GetObjectName(source); path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += objectName; return path; } std::string cmNinjaTargetGenerator::GetPreprocessedFilePath( - cmSourceFile const* source) const + cmSourceFile const* source, const std::string& config) const { // Choose an extension to compile already-preprocessed source. std::string ppExt = source->GetExtension(); @@ -378,19 +394,21 @@ std::string cmNinjaTargetGenerator::GetPreprocessedFilePath( path += "/"; } path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += ppName; return path; } std::string cmNinjaTargetGenerator::GetDyndepFilePath( - std::string const& lang) const + std::string const& lang, const std::string& config) const { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { path += "/"; } path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += lang; path += ".dd"; @@ -398,25 +416,27 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath( } std::string cmNinjaTargetGenerator::GetTargetDependInfoPath( - std::string const& lang) const + std::string const& lang, const std::string& config) const { std::string path = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), - '/', lang, "DependInfo.json"); + this->GetGlobalGenerator()->ConfigDirectory(config), '/', lang, + "DependInfo.json"); return path; } -std::string cmNinjaTargetGenerator::GetTargetOutputDir() const +std::string cmNinjaTargetGenerator::GetTargetOutputDir( + const std::string& config) const { - std::string dir = this->GeneratorTarget->GetDirectory(this->GetConfigName()); + std::string dir = this->GeneratorTarget->GetDirectory(config); return ConvertToNinjaPath(dir); } std::string cmNinjaTargetGenerator::GetTargetFilePath( - const std::string& name) const + const std::string& name, const std::string& config) const { - std::string path = this->GetTargetOutputDir(); + std::string path = this->GetTargetOutputDir(config); if (path.empty() || path == ".") { return name; } @@ -430,21 +450,21 @@ std::string cmNinjaTargetGenerator::GetTargetName() const return this->GeneratorTarget->GetName(); } -bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const +bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable( + cmNinjaVars& vars, const std::string& config) const { cmMakefile* mf = this->GetMakefile(); if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") || mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") || mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) { std::string pdbPath; - std::string compilePdbPath = this->ComputeTargetCompilePDB(); + std::string compilePdbPath = this->ComputeTargetCompilePDB(config); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE || this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { - pdbPath = cmStrCat( - this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/', - this->GeneratorTarget->GetPDBName(this->GetConfigName())); + pdbPath = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config), '/', + this->GeneratorTarget->GetPDBName(config)); } vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -460,15 +480,17 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const return false; } -void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language) +void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language, + const std::string& config) { #ifdef NINJA_GEN_VERBOSE_FILES this->GetRulesFileStream() << "# Rules for language " << language << "\n\n"; #endif - this->WriteCompileRule(language); + this->WriteCompileRule(language, config); } -void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) +void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, + const std::string& config) { cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); @@ -509,7 +531,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetLocalGenerator()->CreateRulePlaceholderExpander()); std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat( - ConvertToNinjaPath(this->GetTargetDependInfoPath(lang)), + ConvertToNinjaPath(this->GetTargetDependInfoPath(lang, config)), cmLocalGenerator::SHELL); std::string launcher; @@ -524,7 +546,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); if (explicitPP) { - cmNinjaRule rule(this->LanguagePreprocessRule(lang)); + cmNinjaRule rule(this->LanguagePreprocessRule(lang, config)); // Explicit preprocessing always uses a depfile. rule.DepType = ""; // no deps= for multiple outputs rule.DepFile = "$DEP_FILE"; @@ -604,7 +626,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) if (needDyndep) { // Write the rule for ninja dyndep file generation. - cmNinjaRule rule(this->LanguageDyndepRule(lang)); + cmNinjaRule rule(this->LanguageDyndepRule(lang, config)); // Command line length is almost always limited -> use response file for // dyndep rules rule.RspFile = "$out.rsp"; @@ -628,7 +650,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetGlobalGenerator()->AddRule(rule); } - cmNinjaRule rule(this->LanguageCompilerRule(lang)); + cmNinjaRule rule(this->LanguageCompilerRule(lang, config)); // If using a response file, move defines, includes, and flags into it. if (!responseFlag.empty()) { rule.RspFile = "$RSP_FILE"; @@ -702,7 +724,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) // See if we need to use a compiler launcher like ccache or distcc std::string compilerLauncher; if (!compileCmds.empty() && - (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) { + (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || + lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); if (clauncher && *clauncher) { @@ -787,50 +810,52 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetGlobalGenerator()->AddRule(rule); } -void cmNinjaTargetGenerator::WriteObjectBuildStatements() +void cmNinjaTargetGenerator::WriteObjectBuildStatements( + const std::string& config, const std::string& fileConfig, + bool firstForConfig) { // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); - this->GetBuildFileStream() + cmGlobalNinjaGenerator::WriteDivider(this->GetConfigFileStream(fileConfig)); + this->GetConfigFileStream(fileConfig) << "# Object build statements for " << cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) << " target " << this->GetTargetName() << "\n\n"; { std::vector<cmSourceFile const*> customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName); + this->GeneratorTarget->GetCustomCommands(customCommands, config); for (cmSourceFile const* sf : customCommands) { cmCustomCommand const* cc = sf->GetCustomCommand(); this->GetLocalGenerator()->AddCustomCommandTarget( cc, this->GetGeneratorTarget()); // Record the custom commands for this target. The container is used // in WriteObjectBuildStatement when called in a loop below. - this->CustomCommands.push_back(cc); + this->Configs[config].CustomCommands.push_back(cc); } } { std::vector<cmSourceFile const*> headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName); + this->GeneratorTarget->GetHeaderSources(headerSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - headerSources, this->MacOSXContentGenerator.get()); + headerSources, this->MacOSXContentGenerator.get(), config); } { std::vector<cmSourceFile const*> extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName); + this->GeneratorTarget->GetExtraSources(extraSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - extraSources, this->MacOSXContentGenerator.get()); + extraSources, this->MacOSXContentGenerator.get(), config); } - { + if (firstForConfig) { const char* pchExtension = GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects, - this->ConfigName); + this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { - const auto objectFileName = this->GetSourceFilePath(sf); + auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir( + this->GetSourceFilePath(sf), config); if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { - this->Objects.push_back(objectFileName); + this->Configs[config].Objects.push_back(objectFileName); } } } @@ -838,19 +863,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() { cmNinjaBuild build("phony"); build.Comment = "Order-only phony target for " + this->GetTargetName(); - build.Outputs.push_back(this->OrderDependsTargetForTarget()); + build.Outputs.push_back(this->OrderDependsTargetForTarget(config)); cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps; this->GetLocalGenerator()->AppendTargetDepends( - this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering); + this->GeneratorTarget, orderOnlyDeps, config, fileConfig, + DependOnTargetOrdering); // Add order-only dependencies on other files associated with the target. - cmAppend(orderOnlyDeps, this->ExtraFiles); + cm::append(orderOnlyDeps, this->Configs[config].ExtraFiles); // Add order-only dependencies on custom command outputs. - for (cmCustomCommand const* cc : this->CustomCommands) { - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), - this->GetLocalGenerator()); + for (cmCustomCommand const* cc : this->Configs[config].CustomCommands) { + cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator()); const std::vector<std::string>& ccoutputs = ccg.GetOutputs(); const std::vector<std::string>& ccbyproducts = ccg.GetByproducts(); std::transform(ccoutputs.begin(), ccoutputs.end(), @@ -876,26 +901,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir)); } - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } { std::vector<cmSourceFile const*> objectSources; - this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName); + this->GeneratorTarget->GetObjectSources(objectSources, config); for (cmSourceFile const* sf : objectSources) { - this->WriteObjectBuildStatement(sf); + this->WriteObjectBuildStatement(sf, config, fileConfig, firstForConfig); } } - for (auto const& langDDIFiles : this->DDIFiles) { + for (auto const& langDDIFiles : this->Configs[config].DDIFiles) { std::string const& language = langDDIFiles.first; cmNinjaDeps const& ddiFiles = langDDIFiles.second; - cmNinjaBuild build(this->LanguageDyndepRule(language)); - build.Outputs.push_back(this->GetDyndepFilePath(language)); + cmNinjaBuild build(this->LanguageDyndepRule(language, config)); + build.Outputs.push_back(this->GetDyndepFilePath(language, config)); build.ExplicitDeps = ddiFiles; - this->WriteTargetDependInfo(language); + this->WriteTargetDependInfo(language, config); // Make sure dyndep files for all our dependencies have already // been generated so that the '<LANG>Modules.json' files they @@ -906,46 +932,51 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() // refactoring the Ninja generator to generate targets in // dependency order so that we can collect the needed information. this->GetLocalGenerator()->AppendTargetDepends( - this->GeneratorTarget, build.OrderOnlyDeps, DependOnTargetArtifact); + this->GeneratorTarget, build.OrderOnlyDeps, config, fileConfig, + DependOnTargetArtifact); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } - this->GetBuildFileStream() << "\n"; + this->GetConfigFileStream(fileConfig) << "\n"; - if (!this->SwiftOutputMap.empty()) { + if (!this->Configs[config].SwiftOutputMap.empty()) { std::string const mapFilePath = this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json"; - std::string const targetSwiftDepsPath = [this]() -> std::string { + std::string const targetSwiftDepsPath = [this, config]() -> std::string { cmGeneratorTarget const* target = this->GeneratorTarget; if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) { return name; } return this->ConvertToNinjaPath(target->GetSupportDirectory() + "/" + - target->GetName() + ".swiftdeps"); + config + "/" + target->GetName() + + ".swiftdeps"); }(); // build the global target dependencies // https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps Json::Value deps(Json::objectValue); deps["swift-dependencies"] = targetSwiftDepsPath; - this->SwiftOutputMap[""] = deps; + this->Configs[config].SwiftOutputMap[""] = deps; cmGeneratedFileStream output(mapFilePath); - output << this->SwiftOutputMap; + output << this->Configs[config].SwiftOutputMap; } } void cmNinjaTargetGenerator::WriteObjectBuildStatement( - cmSourceFile const* source) + cmSourceFile const* source, const std::string& config, + const std::string& fileConfig, bool firstForConfig) { std::string const language = source->GetLanguage(); std::string const sourceFileName = language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source); - std::string const objectDir = - this->ConvertToNinjaPath(this->GeneratorTarget->GetSupportDirectory()); + std::string const objectDir = this->ConvertToNinjaPath( + cmStrCat(this->GeneratorTarget->GetSupportDirectory(), + this->GetGlobalGenerator()->ConfigDirectory(config))); std::string const objectFileName = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); @@ -961,11 +992,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( int const commandLineLengthLimit = ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0; - cmNinjaBuild objBuild(this->LanguageCompilerRule(language)); + cmNinjaBuild objBuild(this->LanguageCompilerRule(language, config)); cmNinjaVars& vars = objBuild.Variables; - vars["FLAGS"] = this->ComputeFlagsForObject(source, language); - vars["DEFINES"] = this->ComputeDefines(source, language); - vars["INCLUDES"] = this->ComputeIncludes(source, language); + vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config); + vars["DEFINES"] = this->ComputeDefines(source, language, config); + vars["INCLUDES"] = this->ComputeIncludes(source, language, config); if (!this->NeedDepTypeMSVC(language)) { bool replaceExt(false); @@ -993,11 +1024,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]); objBuild.Outputs.push_back(objectFileName); - const char* pchExtension = - this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); - if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { - // Add this object to the list of object files. - this->Objects.push_back(objectFileName); + if (firstForConfig) { + const char* pchExtension = + this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); + if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + // Add this object to the list of object files. + this->Configs[config].Objects.push_back(objectFileName); + } } objBuild.ExplicitDeps.push_back(sourceFileName); @@ -1006,13 +1039,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::vector<std::string> depList; const std::string pchSource = - this->GeneratorTarget->GetPchSource(this->GetConfigName(), language); + this->GeneratorTarget->GetPchSource(config, language); if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { - depList.push_back( - this->GeneratorTarget->GetPchHeader(this->GetConfigName(), language)); + depList.push_back(this->GeneratorTarget->GetPchHeader(config, language)); if (source->GetFullPath() != pchSource) { - depList.push_back( - this->GeneratorTarget->GetPchFile(this->GetConfigName(), language)); + depList.push_back(this->GeneratorTarget->GetPchFile(config, language)); } } @@ -1033,7 +1064,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( MapToNinjaPath()); } - objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget()); + objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config)); // If the source file is GENERATED and does not have a custom command // (either attached to this source file or another one), assume that one of @@ -1053,10 +1084,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // For some cases we do an explicit preprocessor invocation. bool const explicitPP = this->NeedExplicitPreprocessing(language); if (explicitPP) { - cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language)); + cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language, config)); std::string const ppFileName = - this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source)); + this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config)); ppBuild.Outputs.push_back(ppFileName); ppBuild.RspFile = ppFileName + ".rsp"; @@ -1114,7 +1145,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags( sourceDirectory, this->GeneratorTarget, language, false, false, - this->GetConfigName()); + config); vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"]; } @@ -1138,17 +1169,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string const ddiFile = objectFileName + ".ddi"; ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile; ppBuild.ImplicitOuts.push_back(ddiFile); - this->DDIFiles[language].push_back(ddiFile); + if (firstForConfig) { + this->Configs[config].DDIFiles[language].push_back(ddiFile); + } } this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), ppBuild.Variables); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), ppBuild, - commandLineLengthLimit); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), ppBuild, commandLineLengthLimit); } if (needDyndep) { - std::string const dyndep = this->GetDyndepFilePath(language); + std::string const dyndep = this->GetDyndepFilePath(language, config); objBuild.OrderOnlyDeps.push_back(dyndep); vars["dyndep"] = dyndep; } @@ -1163,15 +1196,15 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), vars); - this->SetMsvcTargetPdbVariable(vars); + this->SetMsvcTargetPdbVariable(vars, config); objBuild.RspFile = objectFileName + ".rsp"; if (language == "Swift") { - this->EmitSwiftDependencyInfo(source); + this->EmitSwiftDependencyInfo(source, config); } else { - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), - objBuild, commandLineLengthLimit); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), objBuild, commandLineLengthLimit); } if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { @@ -1181,11 +1214,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::transform(build.Outputs.begin(), build.Outputs.end(), build.Outputs.begin(), MapToNinjaPath()); build.ExplicitDeps = objBuild.Outputs; - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } } -void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) +void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, + const std::string& config) { Json::Value tdi(Json::objectValue); tdi["language"] = lang; @@ -1213,7 +1248,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) Json::Value& tdi_include_dirs = tdi["include-dirs"] = Json::arrayValue; std::vector<std::string> includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - lang, this->GetConfigName()); + lang, config); for (std::string const& i : includes) { // Convert the include directories the same way we do for -I flags. // See upstream ninja issue 1251. @@ -1222,22 +1257,22 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] = Json::arrayValue; - for (std::string const& l : this->GetLinkedTargetDirectories()) { + for (std::string const& l : this->GetLinkedTargetDirectories(config)) { tdi_linked_target_dirs.append(l); } - std::string const tdin = this->GetTargetDependInfoPath(lang); + std::string const tdin = this->GetTargetDependInfoPath(lang, config); cmGeneratedFileStream tdif(tdin); tdif << tdi; } void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( - cmSourceFile const* source) + cmSourceFile const* source, const std::string& config) { std::string const sourceFilePath = this->ConvertToNinjaPath(this->GetSourceFilePath(source)); std::string const objectFilePath = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const swiftDepsPath = [source, objectFilePath]() -> std::string { if (const char* name = source->GetProperty("Swift_DEPENDENCIES_FILE")) { return name; @@ -1250,10 +1285,10 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( } return objectFilePath + ".dia"; }(); - std::string const makeDepsPath = [this, source]() -> std::string { + std::string const makeDepsPath = [this, source, config]() -> std::string { cmLocalNinjaGenerator const* local = this->GetLocalGenerator(); std::string const objectFileName = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); @@ -1274,7 +1309,7 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( entry["dependencies"] = makeDepsPath; entry["swift-dependencies"] = swiftDepsPath; entry["diagnostics"] = swiftDiaPath; - SwiftOutputMap[sourceFilePath] = entry; + this->Configs[config].SwiftOutputMap[sourceFilePath] = entry; } void cmNinjaTargetGenerator::ExportObjectCompileCommand( @@ -1349,27 +1384,34 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName); } -void cmNinjaTargetGenerator::AdditionalCleanFiles() +void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config) { if (const char* prop_value = this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmLocalNinjaGenerator* lg = this->LocalGenerator; std::vector<std::string> cleanFiles; - cmExpandList(cmGeneratorExpression::Evaluate( - prop_value, lg, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"), - this->GeneratorTarget), + cmExpandList(cmGeneratorExpression::Evaluate(prop_value, lg, config, + this->GeneratorTarget), cleanFiles); std::string const& binaryDir = lg->GetCurrentBinaryDirectory(); cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator(); for (std::string const& cleanFile : cleanFiles) { // Support relative paths gg->AddAdditionalCleanFile( - cmSystemTools::CollapseFullPath(cleanFile, binaryDir)); + cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config); } } } +cmNinjaDeps cmNinjaTargetGenerator::GetObjects(const std::string& config) const +{ + auto const it = this->Configs.find(config); + if (it != this->Configs.end()) { + return it->second.Objects; + } + return {}; +} + void cmNinjaTargetGenerator::EnsureDirectoryExists( const std::string& path) const { @@ -1392,7 +1434,7 @@ void cmNinjaTargetGenerator::EnsureParentDirectoryExists( } void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( - cmSourceFile const& source, const char* pkgloc) + cmSourceFile const& source, const char* pkgloc, const std::string& config) { // Skip OS X content when not building a Framework or Bundle. if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { @@ -1400,7 +1442,8 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( } std::string macdir = - this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc); + this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc, + config); // Get the input file location. std::string input = source.GetFullPath(); @@ -1412,11 +1455,11 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( output = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output); // Write a build statement to copy the content into the bundle. - this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input, - output); + this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input, output, + config); // Add as a dependency to the target so that it gets called. - this->Generator->ExtraFiles.push_back(std::move(output)); + this->Generator->Configs[config].ExtraFiles.push_back(std::move(output)); } void cmNinjaTargetGenerator::addPoolNinjaVariable( diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 4627bcdc6f..22dd7b8cb5 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -38,16 +38,17 @@ public: /// Destructor. ~cmNinjaTargetGenerator() override; - virtual void Generate() = 0; + virtual void Generate(const std::string& config) = 0; std::string GetTargetName() const; bool NeedDepTypeMSVC(const std::string& lang) const; protected: - bool SetMsvcTargetPdbVariable(cmNinjaVars&) const; + bool SetMsvcTargetPdbVariable(cmNinjaVars&, const std::string& config) const; - cmGeneratedFileStream& GetBuildFileStream() const; + cmGeneratedFileStream& GetConfigFileStream(const std::string& config) const; + cmGeneratedFileStream& GetCommonFileStream() const; cmGeneratedFileStream& GetRulesFileStream() const; cmGeneratorTarget* GetGeneratorTarget() const @@ -64,15 +65,18 @@ protected: cmMakefile* GetMakefile() const { return this->Makefile; } - std::string LanguageCompilerRule(const std::string& lang) const; - std::string LanguagePreprocessRule(std::string const& lang) const; + std::string LanguageCompilerRule(const std::string& lang, + const std::string& config) const; + std::string LanguagePreprocessRule(std::string const& lang, + const std::string& config) const; bool NeedExplicitPreprocessing(std::string const& lang) const; - std::string LanguageDyndepRule(std::string const& lang) const; + std::string LanguageDyndepRule(std::string const& lang, + const std::string& config) const; bool NeedDyndep(std::string const& lang) const; bool UsePreprocessedSource(std::string const& lang) const; bool CompilePreprocessedSourceWithDefines(std::string const& lang) const; - std::string OrderDependsTargetForTarget(); + std::string OrderDependsTargetForTarget(const std::string& config); std::string ComputeOrderDependsForTarget(); @@ -82,15 +86,19 @@ protected: * by LanguageFlagsVarName(). */ std::string ComputeFlagsForObject(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); - void AddIncludeFlags(std::string& flags, std::string const& lang) override; + void AddIncludeFlags(std::string& flags, std::string const& lang, + const std::string& config) override; std::string ComputeDefines(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); std::string ComputeIncludes(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); std::string ConvertToNinjaPath(const std::string& path) const { @@ -102,36 +110,51 @@ protected: } /// @return the list of link dependency for the given target @a target. - cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage) const; + cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage, + const std::string& config) const; /// @return the source file path for the given @a source. std::string GetSourceFilePath(cmSourceFile const* source) const; /// @return the object file path for the given @a source. - std::string GetObjectFilePath(cmSourceFile const* source) const; + std::string GetObjectFilePath(cmSourceFile const* source, + const std::string& config) const; /// @return the preprocessed source file path for the given @a source. - std::string GetPreprocessedFilePath(cmSourceFile const* source) const; + std::string GetPreprocessedFilePath(cmSourceFile const* source, + const std::string& config) const; /// @return the dyndep file path for this target. - std::string GetDyndepFilePath(std::string const& lang) const; + std::string GetDyndepFilePath(std::string const& lang, + const std::string& config) const; /// @return the target dependency scanner info file path - std::string GetTargetDependInfoPath(std::string const& lang) const; + std::string GetTargetDependInfoPath(std::string const& lang, + const std::string& config) const; /// @return the file path where the target named @a name is generated. - std::string GetTargetFilePath(const std::string& name) const; + std::string GetTargetFilePath(const std::string& name, + const std::string& config) const; /// @return the output path for the target. - virtual std::string GetTargetOutputDir() const; - - void WriteLanguageRules(const std::string& language); - void WriteCompileRule(const std::string& language); - void WriteObjectBuildStatements(); - void WriteObjectBuildStatement(cmSourceFile const* source); - void WriteTargetDependInfo(std::string const& lang); - - void EmitSwiftDependencyInfo(cmSourceFile const* source); + virtual std::string GetTargetOutputDir(const std::string& config) const; + + void WriteLanguageRules(const std::string& language, + const std::string& config); + void WriteCompileRule(const std::string& language, + const std::string& config); + void WriteObjectBuildStatements(const std::string& config, + const std::string& fileConfig, + bool firstForConfig); + void WriteObjectBuildStatement(cmSourceFile const* source, + const std::string& config, + const std::string& fileConfig, + bool firstForConfig); + void WriteTargetDependInfo(std::string const& lang, + const std::string& config); + + void EmitSwiftDependencyInfo(cmSourceFile const* source, + const std::string& config); void ExportObjectCompileCommand( std::string const& language, std::string const& sourceFileName, @@ -139,9 +162,9 @@ protected: std::string const& objectFileDir, std::string const& flags, std::string const& defines, std::string const& includes); - void AdditionalCleanFiles(); + void AdditionalCleanFiles(const std::string& config); - cmNinjaDeps GetObjects() const { return this->Objects; } + cmNinjaDeps GetObjects(const std::string& config) const; void EnsureDirectoryExists(const std::string& dir) const; void EnsureParentDirectoryExists(const std::string& path) const; @@ -155,7 +178,8 @@ protected: { } - void operator()(cmSourceFile const& source, const char* pkgloc) override; + void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) override; private: cmNinjaTargetGenerator* Generator; @@ -174,14 +198,20 @@ protected: private: cmLocalNinjaGenerator* LocalGenerator; - /// List of object files for this target. - cmNinjaDeps Objects; - // Fortran Support - std::map<std::string, cmNinjaDeps> DDIFiles; - // Swift Support - Json::Value SwiftOutputMap; - std::vector<cmCustomCommand const*> CustomCommands; - cmNinjaDeps ExtraFiles; + + struct ByConfig + { + /// List of object files for this target. + cmNinjaDeps Objects; + // Fortran Support + std::map<std::string, cmNinjaDeps> DDIFiles; + // Swift Support + Json::Value SwiftOutputMap; + std::vector<cmCustomCommand const*> CustomCommands; + cmNinjaDeps ExtraFiles; + }; + + std::map<std::string, ByConfig> Configs; }; #endif // ! cmNinjaTargetGenerator_h diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 5259037bfd..0cddb127cf 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -15,13 +15,13 @@ #include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" #include "cmLocalNinjaGenerator.h" -#include "cmMakefile.h" #include "cmNinjaTypes.h" #include "cmOutputConverter.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmGeneratorTarget* target) @@ -31,14 +31,18 @@ cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() = default; -void cmNinjaUtilityTargetGenerator::Generate() +void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) { cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator(); cmLocalNinjaGenerator* lg = this->GetLocalGenerator(); cmGeneratorTarget* genTarget = this->GetGeneratorTarget(); + std::string configDir; + if (genTarget->Target->IsPerConfig()) { + configDir = gg->ConfigDirectory(config); + } std::string utilCommandName = - cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/", + cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles", configDir, "/", this->GetTargetName(), ".util"); utilCommandName = this->ConvertToNinjaPath(utilCommandName); @@ -55,8 +59,8 @@ void cmNinjaUtilityTargetGenerator::Generate() for (std::vector<cmCustomCommand> const* cmdList : cmdLists) { for (cmCustomCommand const& ci : *cmdList) { - cmCustomCommandGenerator ccg(ci, this->GetConfigName(), lg); - lg->AppendCustomCommandDeps(ccg, deps); + cmCustomCommandGenerator ccg(ci, config, lg); + lg->AppendCustomCommandDeps(ccg, deps, config); lg->AppendCustomCommandLines(ccg, commands); std::vector<std::string> const& ccByproducts = ccg.GetByproducts(); std::transform(ccByproducts.begin(), ccByproducts.end(), @@ -69,13 +73,11 @@ void cmNinjaUtilityTargetGenerator::Generate() } { - std::string const& config = - this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); std::vector<cmSourceFile*> sources; genTarget->GetSourceFiles(sources, config); for (cmSourceFile const* source : sources) { if (cmCustomCommand const* cc = source->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), lg); + cmCustomCommandGenerator ccg(*cc, config, lg); lg->AddCustomCommandTarget(cc, genTarget); // Depend on all custom command outputs. @@ -89,13 +91,21 @@ void cmNinjaUtilityTargetGenerator::Generate() } } - lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs); - lg->AppendTargetDepends(genTarget, deps); + std::string outputConfig; + if (genTarget->Target->IsPerConfig()) { + outputConfig = config; + } + lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs, outputConfig); + if (genTarget->Target->GetType() != cmStateEnums::GLOBAL_TARGET) { + lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(), + config); + } + lg->AppendTargetDepends(genTarget, deps, config, config); if (commands.empty()) { phonyBuild.Comment = "Utility command for " + this->GetTargetName(); phonyBuild.ExplicitDeps = std::move(deps); - gg->WriteBuild(this->GetBuildFileStream(), phonyBuild); + gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); } else { std::string command = lg->BuildCommandLine(commands, "utility", this->GeneratorTarget); @@ -118,6 +128,7 @@ void cmNinjaUtilityTargetGenerator::Generate() lg->ConvertToOutputFormat(lg->GetBinaryDirectory(), cmOutputConverter::SHELL)); cmSystemTools::ReplaceString(command, "$(ARGS)", ""); + command = gg->ExpandCFGIntDir(command, config); if (command.find('$') != std::string::npos) { return; @@ -127,22 +138,32 @@ void cmNinjaUtilityTargetGenerator::Generate() gg->SeenCustomCommandOutput(util_output); } + std::string ccConfig; + if (genTarget->Target->IsPerConfig() && + genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { + ccConfig = config; + } gg->WriteCustomCommandBuild(command, desc, "Utility command for " + this->GetTargetName(), /*depfile*/ "", /*job_pool*/ "", uses_terminal, - /*restat*/ true, util_outputs, deps); + /*restat*/ true, util_outputs, ccConfig, deps); phonyBuild.ExplicitDeps.push_back(utilCommandName); - gg->WriteBuild(this->GetBuildFileStream(), phonyBuild); + gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); } // Find ADDITIONAL_CLEAN_FILES - this->AdditionalCleanFiles(); + this->AdditionalCleanFiles(config); // Add an alias for the logical target name regardless of what directory // contains it. Skip this for GLOBAL_TARGET because they are meant to // be per-directory and have one at the top-level anyway. if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { - gg->AddTargetAlias(this->GetTargetName(), genTarget); + gg->AddTargetAlias(this->GetTargetName(), genTarget, config); + } else if (gg->IsMultiConfig() && genTarget->Target->IsPerConfig()) { + cmNinjaBuild phonyAlias("phony"); + gg->AppendTargetOutputs(genTarget, phonyAlias.Outputs, ""); + phonyAlias.ExplicitDeps = phonyBuild.Outputs; + gg->WriteBuild(this->GetConfigFileStream(config), phonyAlias); } } diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h index 01cc4595fe..ca3f0a4648 100644 --- a/Source/cmNinjaUtilityTargetGenerator.h +++ b/Source/cmNinjaUtilityTargetGenerator.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <string> + #include "cmNinjaTargetGenerator.h" class cmGeneratorTarget; @@ -15,7 +17,7 @@ public: cmNinjaUtilityTargetGenerator(cmGeneratorTarget* target); ~cmNinjaUtilityTargetGenerator() override; - void Generate() override; + void Generate(const std::string& config) override; }; #endif // ! cmNinjaUtilityTargetGenerator_h diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index a6f4e512ea..382b563e20 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -3,7 +3,6 @@ #include "cmOSXBundleGenerator.h" #include <cassert> -#include <utility> #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" @@ -15,12 +14,10 @@ class cmSourceFile; -cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target, - std::string configName) +cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target) : GT(target) , Makefile(target->Target->GetMakefile()) , LocalGenerator(target->GetLocalGenerator()) - , ConfigName(std::move(configName)) , MacContentFolders(nullptr) { if (this->MustSkip()) { @@ -34,34 +31,34 @@ bool cmOSXBundleGenerator::MustSkip() } void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, - std::string& outpath) + std::string& outpath, + const std::string& config) { if (this->MustSkip()) { return; } // Compute bundle directory names. - std::string out = - cmStrCat(outpath, '/', - this->GT->GetAppBundleDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel)); + std::string out = cmStrCat( + outpath, '/', + this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::FullLevel)); cmSystemTools::MakeDirectory(out); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = - cmStrCat(outpath, '/', - this->GT->GetAppBundleDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - "/Info.plist"); + std::string plist = cmStrCat( + outpath, '/', + this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::ContentLevel), + "/Info.plist"); this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist); this->Makefile->AddCMakeOutputFile(plist); outpath = out; } void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, - const std::string& outpath) + const std::string& outpath, + const std::string& config) { if (this->MustSkip()) { return; @@ -70,15 +67,13 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, assert(this->MacContentFolders); // Compute the location of the top-level foo.framework directory. - std::string contentdir = - cmStrCat(outpath, '/', - this->GT->GetFrameworkDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - '/'); + std::string contentdir = cmStrCat( + outpath, '/', + this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::ContentLevel), + '/'); std::string newoutpath = outpath + "/" + - this->GT->GetFrameworkDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel); + this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel); std::string frameworkVersion = this->GT->GetFrameworkVersion(); @@ -156,27 +151,26 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, } void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, - const std::string& root) + const std::string& root, + const std::string& config) { if (this->MustSkip()) { return; } // Compute bundle directory names. - std::string out = - cmStrCat(root, '/', - this->GT->GetCFBundleDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel)); + std::string out = cmStrCat( + root, '/', + this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel)); cmSystemTools::MakeDirectory(out); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = - cmStrCat(root, '/', - this->GT->GetCFBundleDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - "/Info.plist"); + std::string plist = cmStrCat( + root, '/', + this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel), + "/Info.plist"); std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist); this->Makefile->AddCMakeOutputFile(plist); @@ -184,7 +178,7 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, void cmOSXBundleGenerator::GenerateMacOSXContentStatements( std::vector<cmSourceFile const*> const& sources, - MacOSXContentGeneratorType* generator) + MacOSXContentGeneratorType* generator, const std::string& config) { if (this->MustSkip()) { return; @@ -194,20 +188,19 @@ void cmOSXBundleGenerator::GenerateMacOSXContentStatements( cmGeneratorTarget::SourceFileFlags tsFlags = this->GT->GetTargetSourceFileFlags(source); if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) { - (*generator)(*source, tsFlags.MacFolder); + (*generator)(*source, tsFlags.MacFolder, config); } } } std::string cmOSXBundleGenerator::InitMacOSXContentDirectory( - const char* pkgloc) + const char* pkgloc, const std::string& config) { // Construct the full path to the content subdirectory. - std::string macdir = - cmStrCat(this->GT->GetMacContentDirectory( - this->ConfigName, cmStateEnums::RuntimeBinaryArtifact), - '/', pkgloc); + std::string macdir = cmStrCat(this->GT->GetMacContentDirectory( + config, cmStateEnums::RuntimeBinaryArtifact), + '/', pkgloc); cmSystemTools::MakeDirectory(macdir); // Record use of this content location. Only the first level diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 3dea6cc8a8..232be48834 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -17,29 +17,33 @@ class cmSourceFile; class cmOSXBundleGenerator { public: - cmOSXBundleGenerator(cmGeneratorTarget* target, std::string configName); + cmOSXBundleGenerator(cmGeneratorTarget* target); // create an app bundle at a given root, and return // the directory within the bundle that contains the executable - void CreateAppBundle(const std::string& targetName, std::string& root); + void CreateAppBundle(const std::string& targetName, std::string& root, + const std::string& config); // create a framework at a given root - void CreateFramework(const std::string& targetName, const std::string& root); + void CreateFramework(const std::string& targetName, const std::string& root, + const std::string& config); // create a cf bundle at a given root - void CreateCFBundle(const std::string& targetName, const std::string& root); + void CreateCFBundle(const std::string& targetName, const std::string& root, + const std::string& config); struct MacOSXContentGeneratorType { virtual ~MacOSXContentGeneratorType() = default; - virtual void operator()(cmSourceFile const& source, - const char* pkgloc) = 0; + virtual void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) = 0; }; void GenerateMacOSXContentStatements( std::vector<cmSourceFile const*> const& sources, - MacOSXContentGeneratorType* generator); - std::string InitMacOSXContentDirectory(const char* pkgloc); + MacOSXContentGeneratorType* generator, const std::string& config); + std::string InitMacOSXContentDirectory(const char* pkgloc, + const std::string& config); void SetMacContentFolders(std::set<std::string>* macContentFolders) { @@ -53,7 +57,6 @@ private: cmGeneratorTarget* GT; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; - std::string ConfigName; std::set<std::string>* MacContentFolders; }; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 073222cd80..0369af0021 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -8,7 +8,9 @@ #include <sstream> #include <vector> -#include "cmAlgorithms.h" +#include <cm/memory> +#include <cmext/algorithm> + #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmMessageType.h" @@ -248,11 +250,7 @@ cmOrderDirectories::cmOrderDirectories(cmGlobalGenerator* gg, this->Computed = false; } -cmOrderDirectories::~cmOrderDirectories() -{ - cmDeleteAll(this->ConstraintEntries); - cmDeleteAll(this->ImplicitDirEntries); -} +cmOrderDirectories::~cmOrderDirectories() = default; std::vector<std::string> const& cmOrderDirectories::GetOrderedDirectories() { @@ -286,14 +284,16 @@ void cmOrderDirectories::AddRuntimeLibrary(std::string const& fullPath, if (this->IsImplicitDirectory(dir)) { this->ImplicitDirEntries.push_back( - new cmOrderDirectoriesConstraintSOName(this, fullPath, soname)); + cm::make_unique<cmOrderDirectoriesConstraintSOName>(this, fullPath, + soname)); return; } } // Construct the runtime information entry for this library. this->ConstraintEntries.push_back( - new cmOrderDirectoriesConstraintSOName(this, fullPath, soname)); + cm::make_unique<cmOrderDirectoriesConstraintSOName>(this, fullPath, + soname)); } else { // This can happen if the same library is linked multiple times. // In that case the runtime information check need be done only @@ -314,27 +314,28 @@ void cmOrderDirectories::AddLinkLibrary(std::string const& fullPath) std::string dir = cmSystemTools::GetFilenamePath(fullPath); if (this->IsImplicitDirectory(dir)) { this->ImplicitDirEntries.push_back( - new cmOrderDirectoriesConstraintLibrary(this, fullPath)); + cm::make_unique<cmOrderDirectoriesConstraintLibrary>(this, + fullPath)); return; } } // Construct the link library entry. this->ConstraintEntries.push_back( - new cmOrderDirectoriesConstraintLibrary(this, fullPath)); + cm::make_unique<cmOrderDirectoriesConstraintLibrary>(this, fullPath)); } } void cmOrderDirectories::AddUserDirectories( std::vector<std::string> const& extra) { - cmAppend(this->UserDirectories, extra); + cm::append(this->UserDirectories, extra); } void cmOrderDirectories::AddLanguageDirectories( std::vector<std::string> const& dirs) { - cmAppend(this->LanguageDirectories, dirs); + cm::append(this->LanguageDirectories, dirs); } void cmOrderDirectories::SetImplicitDirectories( @@ -369,7 +370,7 @@ void cmOrderDirectories::CollectOriginalDirectories() this->AddOriginalDirectories(this->UserDirectories); // Add directories containing constraints. - for (cmOrderDirectoriesConstraint* entry : this->ConstraintEntries) { + for (const auto& entry : this->ConstraintEntries) { entry->AddDirectory(); } @@ -454,7 +455,7 @@ void cmOrderDirectories::FindImplicitConflicts() // Check for items in implicit link directories that have conflicts // in the explicit directories. std::ostringstream conflicts; - for (cmOrderDirectoriesConstraint* entry : this->ImplicitDirEntries) { + for (const auto& entry : this->ImplicitDirEntries) { entry->FindImplicitConflicts(conflicts); } diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h index 23c5145009..8ce53e075c 100644 --- a/Source/cmOrderDirectories.h +++ b/Source/cmOrderDirectories.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> +#include <memory> #include <set> #include <string> #include <utility> @@ -46,8 +47,9 @@ private: std::vector<std::string> OrderedDirectories; - std::vector<cmOrderDirectoriesConstraint*> ConstraintEntries; - std::vector<cmOrderDirectoriesConstraint*> ImplicitDirEntries; + std::vector<std::unique_ptr<cmOrderDirectoriesConstraint>> ConstraintEntries; + std::vector<std::unique_ptr<cmOrderDirectoriesConstraint>> + ImplicitDirEntries; std::vector<std::string> UserDirectories; std::vector<std::string> LanguageDirectories; cmsys::RegularExpression RemoveLibraryExtension; diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index e602a6d0ab..1c6fad1482 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -43,9 +43,10 @@ std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source, { std::string result(source); // Convert it to an output path. - if (output == SHELL || output == WATCOMQUOTE) { + if (output == SHELL || output == WATCOMQUOTE || output == NINJAMULTI) { result = this->ConvertDirectorySeparatorsForShell(source); - result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE); + result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE, + output == NINJAMULTI); } else if (output == RESPONSE) { result = this->EscapeForShell(result, false, false, false); } @@ -79,9 +80,9 @@ static bool cmOutputConverterIsShellOperator(cm::string_view str) return (shellOperators.count(str) != 0); } -std::string cmOutputConverter::EscapeForShell(cm::string_view str, - bool makeVars, bool forEcho, - bool useWatcomQuote) const +std::string cmOutputConverter::EscapeForShell( + cm::string_view str, bool makeVars, bool forEcho, bool useWatcomQuote, + bool unescapeNinjaConfiguration) const { // Do not escape shell operators. if (cmOutputConverterIsShellOperator(str)) { @@ -95,6 +96,9 @@ std::string cmOutputConverter::EscapeForShell(cm::string_view str, } else if (!this->LinkScriptShell) { flags |= Shell_Flag_Make; } + if (unescapeNinjaConfiguration) { + flags |= Shell_Flag_UnescapeNinjaConfiguration; + } if (makeVars) { flags |= Shell_Flag_AllowMakeVariables; } @@ -511,5 +515,14 @@ std::string cmOutputConverter::Shell__GetArgument(cm::string_view in, } } + if (flags & Shell_Flag_UnescapeNinjaConfiguration) { + std::string ninjaConfigReplace; + if (flags & Shell_Flag_IsUnix) { + ninjaConfigReplace += '\\'; + } + ninjaConfigReplace += "$${CONFIGURATION}"; + cmSystemTools::ReplaceString(out, ninjaConfigReplace, "${CONFIGURATION}"); + } + return out; } diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 349a069d61..6583ab5cb9 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -22,6 +22,7 @@ public: { SHELL, WATCOMQUOTE, + NINJAMULTI, RESPONSE }; std::string ConvertToOutputFormat(cm::string_view source, @@ -70,12 +71,14 @@ public: /** The target shell quoting uses extra single Quotes for Watcom tools. */ Shell_Flag_WatcomQuote = (1 << 7), - Shell_Flag_IsUnix = (1 << 8) + Shell_Flag_IsUnix = (1 << 8), + + Shell_Flag_UnescapeNinjaConfiguration = (1 << 9), }; std::string EscapeForShell(cm::string_view str, bool makeVars = false, - bool forEcho = false, - bool useWatcomQuote = false) const; + bool forEcho = false, bool useWatcomQuote = false, + bool unescapeNinjaConfiguration = false) const; static std::string EscapeForCMake(cm::string_view str); diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index e093be019c..147f97f731 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -7,10 +7,11 @@ #include <set> #include <utility> +#include <cm/memory> + #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" @@ -94,7 +95,7 @@ public: /** * Destructor. */ - ~cmLBDepend() { cmDeleteAll(this->DependInformationMap); } + ~cmLBDepend() = default; cmLBDepend(const cmLBDepend&) = delete; cmLBDepend& operator=(const cmLBDepend&) = delete; @@ -152,9 +153,9 @@ public: * Generate dependencies for the file given. Returns a pointer to * the cmDependInformation object for the file. */ - const cmDependInformation* FindDependencies(const char* file) + const cmDependInformation* FindDependencies(const std::string& file) { - cmDependInformation* info = this->GetDependInformation(file, nullptr); + cmDependInformation* info = this->GetDependInformation(file, ""); this->GenerateDependInformation(info); return info; } @@ -203,7 +204,7 @@ protected: } // Add this file and all its dependencies. - this->AddDependency(info, includeFile.c_str()); + this->AddDependency(info, includeFile); /// add the cxx file if it exists std::string cxxFile = includeFile; std::string::size_type pos = cxxFile.rfind('.'); @@ -254,7 +255,7 @@ protected: } } if (found) { - this->AddDependency(info, cxxFile.c_str()); + this->AddDependency(info, cxxFile); } } } @@ -264,10 +265,10 @@ protected: /** * Add a dependency. Possibly walk it for more dependencies. */ - void AddDependency(cmDependInformation* info, const char* file) + void AddDependency(cmDependInformation* info, const std::string& file) { cmDependInformation* dependInfo = - this->GetDependInformation(file, info->PathOnly.c_str()); + this->GetDependInformation(file, info->PathOnly); this->GenerateDependInformation(dependInfo); info->AddDependencies(dependInfo); } @@ -313,7 +314,7 @@ protected: // Dependency hints have been given. Use them to begin the // recursion. for (std::string const& file : cFile.GetDepends()) { - this->AddDependency(info, file.c_str()); + this->AddDependency(info, file); } // Found dependency information. We are done. @@ -361,8 +362,8 @@ protected: * Get an instance of cmDependInformation corresponding to the given file * name. */ - cmDependInformation* GetDependInformation(const char* file, - const char* extraPath) + cmDependInformation* GetDependInformation(const std::string& file, + const std::string& extraPath) { // Get the full path for the file so that lookup is unambiguous. std::string fullPath = this->FullPath(file, extraPath); @@ -371,15 +372,16 @@ protected: auto result = this->DependInformationMap.find(fullPath); if (result != this->DependInformationMap.end()) { // Found an instance, return it. - return result->second; + return result->second.get(); } // Didn't find an instance. Create a new one and save it. - cmDependInformation* info = new cmDependInformation; + auto info = cm::make_unique<cmDependInformation>(); + auto ptr = info.get(); info->FullPath = fullPath; info->PathOnly = cmSystemTools::GetFilenamePath(fullPath); info->IncludeName = file; - this->DependInformationMap[fullPath] = info; - return info; + this->DependInformationMap[fullPath] = std::move(info); + return ptr; } /** @@ -387,14 +389,9 @@ protected: * This uses the include directories. * TODO: Cache path conversions to reduce FileExists calls. */ - std::string FullPath(const char* fname, const char* extraPath) + std::string FullPath(const std::string& fname, const std::string& extraPath) { - DirectoryToFileToPathMapType::iterator m; - if (extraPath) { - m = this->DirectoryToFileToPathMap.find(extraPath); - } else { - m = this->DirectoryToFileToPathMap.find(""); - } + auto m = this->DirectoryToFileToPathMap.find(extraPath); if (m != this->DirectoryToFileToPathMap.end()) { FileToPathMapType& map = m->second; @@ -406,7 +403,7 @@ protected: if (cmSystemTools::FileExists(fname, true)) { std::string fp = cmSystemTools::CollapseFullPath(fname); - this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp; + this->DirectoryToFileToPathMap[extraPath][fname] = fp; return fp; } @@ -418,12 +415,12 @@ protected: if (cmSystemTools::FileExists(path, true) && !cmSystemTools::FileIsDirectory(path)) { std::string fp = cmSystemTools::CollapseFullPath(path); - this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp; + this->DirectoryToFileToPathMap[extraPath][fname] = fp; return fp; } } - if (extraPath) { + if (!extraPath.empty()) { std::string path = extraPath; if (!path.empty() && path.back() != '/') { path = path + "/"; @@ -438,7 +435,7 @@ protected: } // Couldn't find the file. - return std::string(fname); + return fname; } cmMakefile* Makefile; @@ -449,7 +446,8 @@ protected: using FileToPathMapType = std::map<std::string, std::string>; using DirectoryToFileToPathMapType = std::map<std::string, FileToPathMapType>; - using DependInformationMapType = std::map<std::string, cmDependInformation*>; + using DependInformationMapType = + std::map<std::string, std::unique_ptr<cmDependInformation>>; DependInformationMapType DependInformationMap; DirectoryToFileToPathMapType DirectoryToFileToPathMap; }; @@ -476,7 +474,7 @@ bool cmOutputRequiredFilesCommand(std::vector<std::string> const& args, md.SetMakefile(&status.GetMakefile()); md.AddSearchPath(status.GetMakefile().GetCurrentSourceDirectory()); // find the depends for a file - const cmDependInformation* info = md.FindDependencies(file.c_str()); + const cmDependInformation* info = md.FindDependencies(file); if (info) { // write them out FILE* fout = cmsys::SystemTools::Fopen(outputFile, "w"); diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 92c80bb4c1..eef41c089b 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -290,7 +290,19 @@ class cmMakefile; SELECT(POLICY, CMP0097, \ "ExternalProject_Add with GIT_SUBMODULES \"\" initializes no " \ "submodules.", \ - 3, 16, 0, cmPolicies::WARN) + 3, 16, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0098, \ + "FindFLEX runs flex in CMAKE_CURRENT_BINARY_DIR when executing.", 3, \ + 17, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0099, \ + "Link properties are transitive over private dependency on static " \ + "libraries.", \ + 3, 17, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0100, "Let AUTOMOC and AUTOUIC process .hh files.", 3, \ + 17, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0101, \ + "target_compile_options honors BEFORE keyword in all scopes.", 3, \ + 17, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -319,7 +331,8 @@ class cmMakefile; F(CMP0076) \ F(CMP0081) \ F(CMP0083) \ - F(CMP0095) + F(CMP0095) \ + F(CMP0099) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 7bb5209da0..a25fd42d10 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -39,6 +39,11 @@ bool cmProjectCommand(std::vector<std::string> const& args, std::string const& projectName = args[0]; + if (!IncludeByVariable(status, + "CMAKE_PROJECT_" + projectName + "_INCLUDE_BEFORE")) { + return false; + } + mf.SetProjectName(projectName); mf.AddCacheDefinition(projectName + "_BINARY_DIR", diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index eb7c900c3d..d5891c4470 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -8,6 +8,8 @@ #include <sstream> #include <utility> +#include <cmext/algorithm> + #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" @@ -67,7 +69,7 @@ void MergeOptions(std::vector<std::string>& baseOpts, } } // Append options - cmAppend(baseOpts, extraOpts); + cm::append(baseOpts, extraOpts); } // - Class definitions @@ -328,7 +330,7 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, { std::vector<std::string> cmd; cmd.emplace_back(this->RccExcutable_); - cmAppend(cmd, this->ListOptions_); + cm::append(cmd, this->ListOptions_); cmd.emplace_back(cmSystemTools::GetFilenameName(qrcFile)); // Log command diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index ef6b886364..db5a8ba667 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -7,7 +7,6 @@ #include <cm/memory> #include "cmCustomCommandLines.h" -#include "cmCustomCommandTypes.h" #include "cmDuration.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" @@ -41,9 +40,9 @@ cmQtAutoGenGlobalInitializer::Keywords::Keywords() } cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( - std::vector<cmLocalGenerator*> const& localGenerators) + std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators) { - for (cmLocalGenerator* localGen : localGenerators) { + for (const auto& localGen : localGenerators) { // Detect global autogen and autorcc target names bool globalAutoGenTarget = false; bool globalAutoRccTarget = false; @@ -56,7 +55,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( if (targetName.empty()) { targetName = "autogen"; } - GlobalAutoGenTargets_.emplace(localGen, std::move(targetName)); + GlobalAutoGenTargets_.emplace(localGen.get(), std::move(targetName)); globalAutoGenTarget = true; } @@ -67,13 +66,13 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( if (targetName.empty()) { targetName = "autorcc"; } - GlobalAutoRccTargets_.emplace(localGen, std::move(targetName)); + GlobalAutoRccTargets_.emplace(localGen.get(), std::move(targetName)); globalAutoRccTarget = true; } } // Find targets that require AUTOMOC/UIC/RCC processing - for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) { + for (const auto& target : localGen->GetGeneratorTargets()) { // Process only certain target types switch (target->GetType()) { case cmStateEnums::EXECUTABLE: @@ -104,7 +103,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( target->GetSafeProperty(kw().AUTORCC_EXECUTABLE); // We support Qt4, Qt5 and Qt6 - auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target); + auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target.get()); bool const validQt = (qtVersion.first.Major == 4) || (qtVersion.first.Major == 5) || (qtVersion.first.Major == 6); @@ -135,8 +134,8 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( if (mocIsValid || uicIsValid || rccIsValid) { // Create autogen target initializer Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>( - this, target, qtVersion.first, mocIsValid, uicIsValid, rccIsValid, - globalAutoGenTarget, globalAutoRccTarget)); + this, target.get(), qtVersion.first, mocIsValid, uicIsValid, + rccIsValid, globalAutoGenTarget, globalAutoRccTarget)); } } } @@ -154,13 +153,14 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget( cmMakefile* makefile = localGen->GetMakefile(); // Create utility target - cmTarget* target = makefile->AddUtilityCommand( - name, cmCommandOrigin::Generator, true, - makefile->GetHomeOutputDirectory().c_str() /*work dir*/, - std::vector<std::string>() /*output*/, - std::vector<std::string>() /*depends*/, cmCustomCommandLines(), false, - comment.c_str()); - localGen->AddGeneratorTarget(new cmGeneratorTarget(target, localGen)); + std::vector<std::string> no_byproducts; + std::vector<std::string> no_depends; + cmCustomCommandLines no_commands; + cmTarget* target = localGen->AddUtilityCommand( + name, true, makefile->GetHomeOutputDirectory().c_str(), no_byproducts, + no_depends, no_commands, false, comment.c_str()); + localGen->AddGeneratorTarget( + cm::make_unique<cmGeneratorTarget>(target, localGen)); // Set FOLDER property in the target { diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h index 806725a01b..2f6e581852 100644 --- a/Source/cmQtAutoGenGlobalInitializer.h +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -48,7 +48,7 @@ public: public: cmQtAutoGenGlobalInitializer( - std::vector<cmLocalGenerator*> const& localGenerators); + std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators); ~cmQtAutoGenGlobalInitializer(); Keywords const& kw() const { return Keywords_; }; diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 6b0fc1e931..46f1716e6b 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -25,7 +25,6 @@ #include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" -#include "cmCustomCommandTypes.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -43,6 +42,7 @@ #include "cmSourceGroup.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmString.hxx" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -355,24 +355,38 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } } - // Check status of policy CMP0071 - { - cmPolicies::PolicyStatus const CMP0071_status = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0071); - switch (CMP0071_status) { - case cmPolicies::WARN: - this->CMP0071Warn = true; - CM_FALLTHROUGH; - case cmPolicies::OLD: - // Ignore GENERATED file - break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Process GENERATED file - this->CMP0071Accept = true; - break; - } + // Check status of policy CMP0071 regarding handling of GENERATED files + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0071)) { + case cmPolicies::WARN: + // Ignore GENERATED files but warn + this->CMP0071Warn = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + // Ignore GENERATED files + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Process GENERATED files + this->CMP0071Accept = true; + break; + } + + // Check status of policy CMP0100 regarding handling of .hh headers + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0100)) { + case cmPolicies::WARN: + // Ignore but .hh files but warn + this->CMP0100Warn = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + // Ignore .hh files + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Process .hh file + this->CMP0100Accept = true; + break; } // Common directories @@ -734,15 +748,26 @@ bool cmQtAutoGenInitializer::InitScanFiles() return muf; }; - auto addMUFile = [&](MUFileHandle&& muf, bool isHeader) { + auto addMUHeader = [this](MUFileHandle&& muf, cm::string_view extension) { + cmSourceFile* sf = muf->SF; + const bool muIt = (muf->MocIt || muf->UicIt); + if (this->CMP0100Accept || (extension != "hh")) { + // Accept + if (muIt && muf->Generated) { + this->AutogenTarget.FilesGenerated.emplace_back(muf.get()); + } + this->AutogenTarget.Headers.emplace(sf, std::move(muf)); + } else if (muIt && this->CMP0100Warn) { + // Store file for warning message + this->AutogenTarget.CMP0100HeadersWarn.push_back(sf); + } + }; + + auto addMUSource = [this](MUFileHandle&& muf) { if ((muf->MocIt || muf->UicIt) && muf->Generated) { this->AutogenTarget.FilesGenerated.emplace_back(muf.get()); } - if (isHeader) { - this->AutogenTarget.Headers.emplace(muf->SF, std::move(muf)); - } else { - this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf)); - } + this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf)); }; // Scan through target files @@ -764,11 +789,10 @@ bool cmQtAutoGenInitializer::InitScanFiles() // Register files that will be scanned by moc or uic if (this->MocOrUicEnabled()) { - // FIXME: Add a policy to include .hh files. - if (cm->IsHeaderExtension(extLower) && extLower != "hh") { - addMUFile(makeMUFile(sf, fullPath, true), true); + if (cm->IsHeaderExtension(extLower)) { + addMUHeader(makeMUFile(sf, fullPath, true), extLower); } else if (cm->IsSourceExtension(extLower)) { - addMUFile(makeMUFile(sf, fullPath, true), false); + addMUSource(makeMUFile(sf, fullPath, true)); } } @@ -802,8 +826,6 @@ bool cmQtAutoGenInitializer::InitScanFiles() // For source files find additional headers and private headers if (this->MocOrUicEnabled()) { - std::vector<MUFileHandle> extraHeaders; - extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2); // Header search suffixes and extensions static std::initializer_list<cm::string_view> const suffixes{ "", "_p" }; auto const& exts = cm->GetHeaderExtensions(); @@ -848,16 +870,12 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!muf.UicIt) { eMuf->UicIt = false; } - extraHeaders.emplace_back(std::move(eMuf)); + addMUHeader(std::move(eMuf), ext); } } } } } - // Move generated files to main headers list - for (auto& eMuf : extraHeaders) { - addMUFile(std::move(eMuf), true); - } } // Scan through all source files in the makefile to extract moc and uic @@ -877,19 +895,18 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::string const& extLower = cmSystemTools::LowerCase(sf->GetExtension()); - // FIXME: Add a policy to include .hh files. - if (cm->IsHeaderExtension(extLower) && extLower != "hh") { + if (cm->IsHeaderExtension(extLower)) { if (!cmContains(this->AutogenTarget.Headers, sf)) { auto muf = makeMUFile(sf, fullPath, false); if (muf->SkipMoc || muf->SkipUic) { - this->AutogenTarget.Headers.emplace(sf, std::move(muf)); + addMUHeader(std::move(muf), extLower); } } } else if (cm->IsSourceExtension(extLower)) { - if (!cmContains(this->AutogenTarget.Headers, sf)) { + if (!cmContains(this->AutogenTarget.Sources, sf)) { auto muf = makeMUFile(sf, fullPath, false); if (muf->SkipMoc || muf->SkipUic) { - this->AutogenTarget.Sources.emplace(sf, std::move(muf)); + addMUSource(std::move(muf)); } } } else if (this->Uic.Enabled && (extLower == kw.ui)) { @@ -947,6 +964,35 @@ bool cmQtAutoGenInitializer::InitScanFiles() } } + // Generate CMP0100 warning + if (this->MocOrUicEnabled() && + !this->AutogenTarget.CMP0100HeadersWarn.empty()) { + cm::string_view property; + if (this->Moc.Enabled && this->Uic.Enabled) { + property = "SKIP_AUTOGEN"; + } else if (this->Moc.Enabled) { + property = "SKIP_AUTOMOC"; + } else if (this->Uic.Enabled) { + property = "SKIP_AUTOUIC"; + } + std::string files; + for (cmSourceFile* sf : this->AutogenTarget.CMP0100HeadersWarn) { + files += cmStrCat(" ", Quoted(sf->GetFullPath()), '\n'); + } + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + cmPolicies::GetPolicyWarning(cmPolicies::CMP0100), '\n', + "For compatibility, CMake is excluding the header file(s):\n", files, + "from processing by ", + cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false), + ". If any of the files should be processed, set CMP0100 to NEW. " + "If any of the files should not be processed, " + "explicitly exclude them by setting the source file property ", + property, ":\n set_property(SOURCE file.hh PROPERTY ", property, + " ON)\n")); + } + // Process qrc files if (!this->Rcc.Qrcs.empty()) { const bool modernQt = (this->QtVersion.Major >= 5); @@ -1045,9 +1091,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() } // Compose command lines - cmCustomCommandLines commandLines = cmMakeSingleCommandLine( - { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", - this->AutogenTarget.InfoFile, "$<CONFIGURATION>" }); + // TODO: Refactor autogen to output a per-config mocs_compilation.cpp instead + // of fiddling with the include directories + std::vector<std::string> configs; + this->GlobalGen->GetQtAutoGenConfigs(configs); + cmCustomCommandLines commandLines; + for (auto const& config : configs) { + commandLines.push_back(cmMakeCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", + this->AutogenTarget.InfoFile, config })); + } // Use PRE_BUILD on demand bool usePRE_BUILD = false; @@ -1084,8 +1137,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // PRE_BUILD does not support file dependencies! const std::vector<std::string> no_output; const std::vector<std::string> no_deps; - cmCustomCommand cc(this->Makefile, no_output, autogenProvides, no_deps, - commandLines, autogenComment.c_str(), + cmCustomCommand cc(no_output, autogenProvides, no_deps, commandLines, + this->Makefile->GetBacktrace(), autogenComment.c_str(), this->Dir.Work.c_str()); cc.SetEscapeOldStyle(false); cc.SetEscapeAllowMakeVars(true); @@ -1120,15 +1173,15 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() } // Create autogen target - cmTarget* autogenTarget = this->Makefile->AddUtilityCommand( - this->AutogenTarget.Name, cmCommandOrigin::Generator, true, - this->Dir.Work.c_str(), /*byproducts=*/autogenProvides, + cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand( + this->AutogenTarget.Name, true, this->Dir.Work.c_str(), + /*byproducts=*/autogenProvides, std::vector<std::string>(this->AutogenTarget.DependFiles.begin(), this->AutogenTarget.DependFiles.end()), commandLines, false, autogenComment.c_str()); // Create autogen generator target this->LocalGen->AddGeneratorTarget( - new cmGeneratorTarget(autogenTarget, this->LocalGen)); + cm::make_unique<cmGeneratorTarget>(autogenTarget, this->LocalGen)); // Forward origin utilities to autogen target if (this->AutogenTarget.DependOrigin) { @@ -1143,7 +1196,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Set FOLDER property in autogen target if (!this->TargetsFolder.empty()) { - autogenTarget->SetProperty("FOLDER", this->TargetsFolder.c_str()); + autogenTarget->SetProperty("FOLDER", this->TargetsFolder); } // Add autogen target to the origin target dependencies @@ -1202,17 +1255,17 @@ bool cmQtAutoGenInitializer::InitRccTargets() ccName += cmStrCat('_', qrc.QrcPathChecksum); } - cmTarget* autoRccTarget = this->Makefile->AddUtilityCommand( - ccName, cmCommandOrigin::Generator, true, this->Dir.Work.c_str(), - ccOutput, ccDepends, commandLines, false, ccComment.c_str()); + cmTarget* autoRccTarget = this->LocalGen->AddUtilityCommand( + ccName, true, this->Dir.Work.c_str(), ccOutput, ccDepends, + commandLines, false, ccComment.c_str()); // Create autogen generator target this->LocalGen->AddGeneratorTarget( - new cmGeneratorTarget(autoRccTarget, this->LocalGen)); + cm::make_unique<cmGeneratorTarget>(autoRccTarget, this->LocalGen)); // Set FOLDER property in autogen target if (!this->TargetsFolder.empty()) { - autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str()); + autoRccTarget->SetProperty("FOLDER", this->TargetsFolder); } if (!this->Rcc.ExecutableTargetName.empty()) { autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName, @@ -1241,7 +1294,7 @@ bool cmQtAutoGenInitializer::InitRccTargets() } std::string no_main_dependency; cmImplicitDependsList no_implicit_depends; - this->Makefile->AddCustomCommandToOutput( + this->LocalGen->AddCustomCommandToOutput( ccOutput, ccByproducts, ccDepends, no_main_dependency, no_implicit_depends, commandLines, ccComment.c_str(), this->Dir.Work.c_str()); @@ -1524,8 +1577,8 @@ bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName) { - this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", - fileName.c_str(), false); + this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName, + false); } void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString, @@ -1628,21 +1681,39 @@ std::string cmQtAutoGenInitializer::GetMocBuildPath(MUFile const& muf) if (!muf.MocIt) { return res; } - { - std::string const basePath = - cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_", - FileNameWithoutLastExtension(muf.FullPath)); - std::string suffix; - constexpr std::size_t num_tries_max = 256; - for (std::size_t ii = 0; ii != num_tries_max; ++ii) { - res = cmStrCat(basePath, suffix, ".cpp"); - if (this->Moc.EmittedBuildPaths.emplace(res).second) { - break; - } - // Compute new suffix - suffix = cmStrCat('_', ii + 1); + + std::string basePath = + cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_", + FileNameWithoutLastExtension(muf.FullPath)); + + res = cmStrCat(basePath, ".cpp"); + if (this->Moc.EmittedBuildPaths.emplace(res).second) { + return res; + } + + // File name already emitted. + // Try appending the header suffix to the base path. + basePath = cmStrCat(basePath, '_', muf.SF->GetExtension()); + res = cmStrCat(basePath, ".cpp"); + if (this->Moc.EmittedBuildPaths.emplace(res).second) { + return res; + } + + // File name with header extension already emitted. + // Try adding a number to the base path. + constexpr std::size_t number_begin = 2; + constexpr std::size_t number_end = 256; + for (std::size_t ii = number_begin; ii != number_end; ++ii) { + res = cmStrCat(basePath, '_', ii, ".cpp"); + if (this->Moc.EmittedBuildPaths.emplace(res).second) { + return res; } } + + // Output file name conflict (unlikely, but still...) + cmSystemTools::Error( + cmStrCat("moc output file name conflict for ", muf.FullPath)); + return res; } diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 486dab71fc..847e4e544f 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -159,6 +159,8 @@ private: bool MultiConfig = false; bool CMP0071Accept = false; bool CMP0071Warn = false; + bool CMP0100Accept = false; + bool CMP0100Warn = false; std::string ConfigDefault; std::vector<std::string> ConfigsList; std::string TargetsFolder; @@ -192,6 +194,7 @@ private: std::unordered_map<cmSourceFile*, MUFileHandle> Headers; std::unordered_map<cmSourceFile*, MUFileHandle> Sources; std::vector<MUFile*> FilesGenerated; + std::vector<cmSourceFile*> CMP0100HeadersWarn; } AutogenTarget; /** moc variables. */ diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index f8b8981524..fa5129d589 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -16,13 +16,13 @@ #include <cm/memory> #include <cm/string_view> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" #include "cm_jsoncpp_value.h" -#include "cmAlgorithms.h" #include "cmCryptoHash.h" #include "cmFileTime.h" #include "cmGeneratedFileStream.h" @@ -808,9 +808,9 @@ void cmQtAutoMocUicT::JobMocPredefsT::Process() // Compose command std::vector<std::string> cmd = MocConst().PredefsCmd; // Add definitions - cmAppend(cmd, MocConst().OptionsDefinitions); + cm::append(cmd, MocConst().OptionsDefinitions); // Add includes - cmAppend(cmd, MocConst().OptionsIncludes); + cm::append(cmd, MocConst().OptionsIncludes); // Execute command if (!RunProcess(GenT::MOC, result, cmd, reason.get())) { LogCommandError(GenT::MOC, @@ -1916,9 +1916,9 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() MocConst().OptionsExtra.size() + 16); cmd.push_back(MocConst().Executable); // Add definitions - cmAppend(cmd, MocConst().OptionsDefinitions); + cm::append(cmd, MocConst().OptionsDefinitions); // Add includes - cmAppend(cmd, MocConst().OptionsIncludes); + cm::append(cmd, MocConst().OptionsIncludes); // Add predefs include if (!MocConst().PredefsFileAbs.empty()) { cmd.emplace_back("--include"); @@ -1946,7 +1946,7 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() } } // Add extra options - cmAppend(cmd, MocConst().OptionsExtra); + cm::append(cmd, MocConst().OptionsExtra); // Add output file cmd.emplace_back("-o"); cmd.push_back(outputFile); @@ -1994,7 +1994,7 @@ void cmQtAutoMocUicT::JobCompileUicT::Process() UicMergeOptions(allOpts, optionIt->second.Options, (BaseConst().QtVersionMajor == 5)); } - cmAppend(cmd, allOpts); + cm::append(cmd, allOpts); } cmd.emplace_back("-o"); cmd.emplace_back(outputFile); diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx index 3af81ad38a..08eb4b5e28 100644 --- a/Source/cmQtAutoRcc.cxx +++ b/Source/cmQtAutoRcc.cxx @@ -6,7 +6,8 @@ #include <string> #include <vector> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmCryptoHash.h" #include "cmDuration.h" #include "cmFileLock.h" @@ -405,7 +406,7 @@ bool cmQtAutoRccT::GenerateRcc() // Compose rcc command std::vector<std::string> cmd; cmd.push_back(RccExecutable_); - cmAppend(cmd, Options_); + cm::append(cmd, Options_); cmd.emplace_back("-o"); cmd.push_back(RccFileOutput_); cmd.push_back(QrcFile_); diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h index 2a576ed59b..3ecc73bca2 100644 --- a/Source/cmSearchPath.h +++ b/Source/cmSearchPath.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <set> #include <string> #include <vector> @@ -27,6 +28,7 @@ public: ~cmSearchPath(); const std::vector<std::string>& GetPaths() const { return this->Paths; } + std::size_t size() const { return this->Paths.size(); } void ExtractWithout(const std::set<std::string>& ignore, std::vector<std::string>& outPaths, diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 56003df75f..1d4ea01534 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -744,7 +744,7 @@ void cmServerProtocol1::GeneratorInformation::SetupGenerator( cm->SetHomeDirectory(SourceDirectory); cm->SetHomeOutputDirectory(BuildDirectory); - cmGlobalGenerator* gg = cm->CreateGlobalGenerator(fullGeneratorName); + auto gg = cm->CreateGlobalGenerator(fullGeneratorName); if (!gg) { setErrorMessage( errorMessage, @@ -753,7 +753,7 @@ void cmServerProtocol1::GeneratorInformation::SetupGenerator( return; } - cm->SetGlobalGenerator(gg); + cm->SetGlobalGenerator(std::move(gg)); cm->SetGeneratorToolset(Toolset); cm->SetGeneratorPlatform(Platform); diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 8c3a4cb486..5e2a1462c4 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -121,7 +121,7 @@ bool cmSetCommand(std::vector<std::string> const& args, if (cache) { std::string::size_type cacheStart = args.size() - 3 - (force ? 1 : 0); - if (!cmState::StringToCacheEntryType(args[cacheStart + 1].c_str(), type)) { + if (!cmState::StringToCacheEntryType(args[cacheStart + 1], type)) { std::string m = "implicitly converting '" + args[cacheStart + 1] + "' to 'STRING' type."; status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, m); diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index 8d917dbe57..cd0fa402a2 100644 --- a/Source/cmSetTargetPropertiesCommand.cxx +++ b/Source/cmSetTargetPropertiesCommand.cxx @@ -4,7 +4,8 @@ #include <iterator> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -33,7 +34,7 @@ bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments."); return false; } - cmAppend(propertyPairs, j, args.end()); + cm::append(propertyPairs, j, args.end()); break; } numFiles++; @@ -70,7 +71,7 @@ static bool SetOneTarget(const std::string& tname, // now loop through all the props and set them unsigned int k; for (k = 0; k < propertyPairs.size(); k = k + 2) { - target->SetProperty(propertyPairs[k], propertyPairs[k + 1].c_str()); + target->SetProperty(propertyPairs[k], propertyPairs[k + 1]); target->CheckProperty(propertyPairs[k], mf); } } diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx index de61edaf0d..2e7aecabc9 100644 --- a/Source/cmSetTestsPropertiesCommand.cxx +++ b/Source/cmSetTestsPropertiesCommand.cxx @@ -4,7 +4,8 @@ #include <iterator> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -36,7 +37,7 @@ bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments."); return false; } - cmAppend(propertyPairs, j, args.end()); + cm::append(propertyPairs, j, args.end()); break; } numFiles++; diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 82a3625b8b..19a0d29136 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -154,9 +154,8 @@ private: #define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$" #define CM_SOURCE_REGEX \ - "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|rc|def|r|odl|idl|" \ - "hpj" \ - "|bat)$" + "\\.(C|F|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|" \ + "rc|def|r|odl|idl|hpj|bat)$" #define CM_PCH_REGEX "cmake_pch\\.(h|hxx)$" diff --git a/Source/cmState.cxx b/Source/cmState.cxx index f9b5ed1c08..35f07a1d0f 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -3,9 +3,9 @@ #include "cmState.h" #include <algorithm> +#include <array> #include <cassert> #include <cstdlib> -#include <cstring> #include <utility> #include <cm/memory> @@ -60,43 +60,44 @@ const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType) return nullptr; } -const char* cmCacheEntryTypes[] = { "BOOL", "PATH", "FILEPATH", - "STRING", "INTERNAL", "STATIC", - "UNINITIALIZED", nullptr }; +static const std::array<std::string, 7> cmCacheEntryTypes = { + { "BOOL", "PATH", "FILEPATH", "STRING", "INTERNAL", "STATIC", + "UNINITIALIZED" } +}; -const char* cmState::CacheEntryTypeToString(cmStateEnums::CacheEntryType type) +const std::string& cmState::CacheEntryTypeToString( + cmStateEnums::CacheEntryType type) { - if (type > 6) { - return cmCacheEntryTypes[6]; + if (type < cmStateEnums::BOOL || type > cmStateEnums::UNINITIALIZED) { + type = cmStateEnums::UNINITIALIZED; } return cmCacheEntryTypes[type]; } -cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(const char* s) +cmStateEnums::CacheEntryType cmState::StringToCacheEntryType( + const std::string& s) { cmStateEnums::CacheEntryType type = cmStateEnums::STRING; StringToCacheEntryType(s, type); return type; } -bool cmState::StringToCacheEntryType(const char* s, +bool cmState::StringToCacheEntryType(const std::string& s, cmStateEnums::CacheEntryType& type) { - int i = 0; - while (cmCacheEntryTypes[i]) { - if (strcmp(s, cmCacheEntryTypes[i]) == 0) { + for (size_t i = 0; i < cmCacheEntryTypes.size(); ++i) { + if (s == cmCacheEntryTypes[i]) { type = static_cast<cmStateEnums::CacheEntryType>(i); return true; } - ++i; } return false; } bool cmState::IsCacheEntryType(std::string const& key) { - for (int i = 0; cmCacheEntryTypes[i]; ++i) { - if (key == cmCacheEntryTypes[i]) { + for (const std::string& i : cmCacheEntryTypes) { + if (key == i) { return true; } } @@ -149,8 +150,7 @@ const std::string* cmState::GetInitializedCacheValue( cmStateEnums::CacheEntryType cmState::GetCacheEntryType( std::string const& key) const { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); return it.GetType(); } @@ -164,8 +164,7 @@ void cmState::SetCacheEntryProperty(std::string const& key, std::string const& propertyName, std::string const& value) { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); it.SetProperty(propertyName, value.c_str()); } @@ -173,24 +172,21 @@ void cmState::SetCacheEntryBoolProperty(std::string const& key, std::string const& propertyName, bool value) { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); it.SetProperty(propertyName, value); } std::vector<std::string> cmState::GetCacheEntryPropertyList( const std::string& key) { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); return it.GetPropertyList(); } const char* cmState::GetCacheEntryProperty(std::string const& key, std::string const& propertyName) { - cmCacheManager::CacheIterator it = - this->CacheManager->GetCacheIterator(key.c_str()); + cmCacheManager::CacheIterator it = this->CacheManager->GetCacheIterator(key); if (!it.PropertyExists(propertyName)) { return nullptr; } @@ -200,8 +196,8 @@ const char* cmState::GetCacheEntryProperty(std::string const& key, bool cmState::GetCacheEntryPropertyAsBool(std::string const& key, std::string const& propertyName) { - return this->CacheManager->GetCacheIterator(key.c_str()) - .GetPropertyAsBool(propertyName); + return this->CacheManager->GetCacheIterator(key).GetPropertyAsBool( + propertyName); } void cmState::AddCacheEntry(const std::string& key, const char* value, @@ -253,15 +249,14 @@ void cmState::AppendCacheEntryProperty(const std::string& key, const std::string& property, const std::string& value, bool asString) { - this->CacheManager->GetCacheIterator(key.c_str()) - .AppendProperty(property, value.c_str(), asString); + this->CacheManager->GetCacheIterator(key).AppendProperty(property, value, + asString); } void cmState::RemoveCacheEntryProperty(std::string const& key, std::string const& propertyName) { - this->CacheManager->GetCacheIterator(key.c_str()) - .SetProperty(propertyName, nullptr); + this->CacheManager->GetCacheIterator(key).SetProperty(propertyName, nullptr); } cmStateSnapshot cmState::Reset() @@ -615,6 +610,9 @@ const char* cmState::GetGlobalProperty(const std::string& prop) if (prop == "CMAKE_CXX14_KNOWN_FEATURES") { return &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]; } + if (prop == "CMAKE_CUDA_KNOWN_FEATURES") { + return &FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]; + } #undef STRING_LIST_ELEMENT return this->GlobalProperties.GetPropertyValue(prop); @@ -712,6 +710,16 @@ bool cmState::UseMSYSShell() const return this->MSYSShell; } +void cmState::SetNinjaMulti(bool ninjaMulti) +{ + this->NinjaMulti = ninjaMulti; +} + +bool cmState::UseNinjaMulti() const +{ + return this->NinjaMulti; +} + unsigned int cmState::GetCacheMajorVersion() const { return this->CacheManager->GetCacheMajorVersion(); @@ -993,12 +1001,12 @@ bool cmState::ParseCacheEntry(const std::string& entry, std::string& var, bool flag = false; if (regQuoted.find(entry)) { var = regQuoted.match(1); - type = cmState::StringToCacheEntryType(regQuoted.match(2).c_str()); + type = cmState::StringToCacheEntryType(regQuoted.match(2)); value = regQuoted.match(3); flag = true; } else if (reg.find(entry)) { var = reg.match(1); - type = cmState::StringToCacheEntryType(reg.match(2).c_str()); + type = cmState::StringToCacheEntryType(reg.match(2)); value = reg.match(3); flag = true; } diff --git a/Source/cmState.h b/Source/cmState.h index a7ca015c1c..a74426620c 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -70,10 +70,12 @@ public: cmStateSnapshot const& originSnapshot); cmStateSnapshot Pop(cmStateSnapshot const& originSnapshot); - static cmStateEnums::CacheEntryType StringToCacheEntryType(const char*); - static bool StringToCacheEntryType(const char*, + static cmStateEnums::CacheEntryType StringToCacheEntryType( + const std::string&); + static bool StringToCacheEntryType(const std::string&, cmStateEnums::CacheEntryType& type); - static const char* CacheEntryTypeToString(cmStateEnums::CacheEntryType); + static const std::string& CacheEntryTypeToString( + cmStateEnums::CacheEntryType); static bool IsCacheEntryType(std::string const& key); bool LoadCache(const std::string& path, bool internal, @@ -190,6 +192,8 @@ public: bool UseNMake() const; void SetMSYSShell(bool mSYSShell); bool UseMSYSShell() const; + void SetNinjaMulti(bool ninjaMulti); + bool UseNinjaMulti() const; unsigned int GetCacheMajorVersion() const; unsigned int GetCacheMinorVersion() const; @@ -245,6 +249,7 @@ private: bool MinGWMake = false; bool NMake = false; bool MSYSShell = false; + bool NinjaMulti = false; Mode CurrentMode = Unknown; }; diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 1262f53d97..97fdbbe1b9 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -8,6 +8,7 @@ #include <vector> #include <cm/iterator> +#include <cmext/algorithm> #include "cmAlgorithms.h" #include "cmProperty.h" @@ -607,7 +608,7 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, } if (prop == "VARIABLES") { std::vector<std::string> res = this->Snapshot_.ClosureKeys(); - cmAppend(res, this->Snapshot_.State->GetCacheEntryKeys()); + cm::append(res, this->Snapshot_.State->GetCacheEntryKeys()); std::sort(res.begin(), res.end()); output = cmJoin(res, ";"); return output.c_str(); diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 645907c21e..832e74ec7f 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -315,10 +315,14 @@ void cmStateSnapshot::SetDefaultDefinitions() this->SetDefinition("UNIX", "1"); this->SetDefinition("CMAKE_HOST_UNIX", "1"); +# if defined(__ANDROID__) + this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Android"); +# else struct utsname uts_name; if (uname(&uts_name) >= 0) { this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname); } +# endif #endif #if defined(__CYGWIN__) std::string legacy; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index c4a4220f81..9127c50e91 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2,9 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSystemTools.h" +#include <cmext/algorithm> + #include "cm_uv.h" -#include "cmAlgorithms.h" #include "cmDuration.h" #include "cmProcessOutput.h" #include "cmRange.h" @@ -360,7 +361,7 @@ std::vector<std::string> cmSystemTools::HandleResponseFile( #else cmSystemTools::ParseUnixCommandLine(line.c_str(), args2); #endif - cmAppend(arg_full, args2); + cm::append(arg_full, args2); } } else { arg_full.push_back(arg); @@ -585,7 +586,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, cmSystemTools::Stdout(strdata); } if (captureStdOut) { - cmAppend(tempStdOut, data, data + length); + cm::append(tempStdOut, data, data + length); } } else if (pipe == cmsysProcess_Pipe_STDERR) { if (outputflag != OUTPUT_NONE) { @@ -593,7 +594,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, cmSystemTools::Stderr(strdata); } if (captureStdErr) { - cmAppend(tempStdErr, data, data + length); + cm::append(tempStdErr, data, data + length); } } } @@ -814,6 +815,8 @@ void cmSystemTools::InitializeLibUV() # else _fmode = _O_TEXT; # endif + // Replace libuv's report handler with our own to suppress popups. + cmSystemTools::EnableMSVCDebugHook(); #endif } @@ -1710,26 +1713,26 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line, processOutput.DecodeText(data, length, strdata, 1); // Append to the stdout buffer. std::vector<char>::size_type size = out.size(); - cmAppend(out, strdata); + cm::append(out, strdata); outiter = out.begin() + size; } else if (pipe == cmsysProcess_Pipe_STDERR) { processOutput.DecodeText(data, length, strdata, 2); // Append to the stderr buffer. std::vector<char>::size_type size = err.size(); - cmAppend(err, strdata); + cm::append(err, strdata); erriter = err.begin() + size; } else if (pipe == cmsysProcess_Pipe_None) { // Both stdout and stderr pipes have broken. Return leftover data. processOutput.DecodeText(std::string(), strdata, 1); if (!strdata.empty()) { std::vector<char>::size_type size = out.size(); - cmAppend(out, strdata); + cm::append(out, strdata); outiter = out.begin() + size; } processOutput.DecodeText(std::string(), strdata, 2); if (!strdata.empty()) { std::vector<char>::size_type size = err.size(); - cmAppend(err, strdata); + cm::append(err, strdata); erriter = err.begin() + size; } if (!out.empty()) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2db89dea1c..95633215fb 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -12,6 +12,7 @@ #include <unordered_set> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/RegularExpression.hxx" @@ -176,6 +177,7 @@ public: bool IsImportedTarget; bool ImportedGloballyVisible; bool BuildInterfaceIncludesAppended; + bool PerConfig; std::set<BT<std::string>> Utilities; std::vector<cmCustomCommand> PreBuildCommands; std::vector<cmCustomCommand> PreLinkCommands; @@ -213,7 +215,7 @@ public: }; cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, - Visibility vis, cmMakefile* mf) + Visibility vis, cmMakefile* mf, bool perConfig) : impl(cm::make_unique<cmTargetInternals>()) { assert(mf); @@ -229,6 +231,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, (vis == VisibilityImported || vis == VisibilityImportedGlobally); impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally; impl->BuildInterfaceIncludesAppended = false; + impl->PerConfig = perConfig; // Check whether this is a DLL platform. impl->IsDLLPlatform = @@ -333,6 +336,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("C_STANDARD"); initProp("C_STANDARD_REQUIRED"); initProp("C_EXTENSIONS"); + initProp("OBJC_COMPILER_LAUNCHER"); initProp("OBJC_STANDARD"); initProp("OBJC_STANDARD_REQUIRED"); initProp("OBJC_EXTENSIONS"); @@ -344,6 +348,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("CXX_STANDARD"); initProp("CXX_STANDARD_REQUIRED"); initProp("CXX_EXTENSIONS"); + initProp("OBJCXX_COMPILER_LAUNCHER"); initProp("OBJCXX_STANDARD"); initProp("OBJCXX_STANDARD_REQUIRED"); initProp("OBJCXX_EXTENSIONS"); @@ -355,7 +360,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("CUDA_RESOLVE_DEVICE_SYMBOLS"); initProp("LINK_SEARCH_START_STATIC"); initProp("LINK_SEARCH_END_STATIC"); - initProp("FOLDER"); initProp("Swift_LANGUAGE_VERSION"); initProp("Swift_MODULE_DIRECTORY"); initProp("VS_JUST_MY_CODE_DEBUGGING"); @@ -371,6 +375,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP"); initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"); initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"); + initProp("XCODE_SCHEME_WORKING_DIRECTORY"); initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"); initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP"); initProp("XCODE_SCHEME_MALLOC_SCRIBBLE"); @@ -380,11 +385,14 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("XCODE_SCHEME_MALLOC_STACK"); initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"); initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS"); + initProp("XCODE_SCHEME_ENVIRONMENT"); } #endif } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { + initProp("FOLDER"); + if (this->GetGlobalGenerator()->IsXcode()) { initProp("XCODE_GENERATE_SCHEME"); } @@ -435,30 +443,30 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (!this->IsImported()) { // Initialize the INCLUDE_DIRECTORIES property based on the current value // of the same directory property: - cmAppend(impl->IncludeDirectoriesEntries, - impl->Makefile->GetIncludeDirectoriesEntries()); - cmAppend(impl->IncludeDirectoriesBacktraces, - impl->Makefile->GetIncludeDirectoriesBacktraces()); + cm::append(impl->IncludeDirectoriesEntries, + impl->Makefile->GetIncludeDirectoriesEntries()); + cm::append(impl->IncludeDirectoriesBacktraces, + impl->Makefile->GetIncludeDirectoriesBacktraces()); { auto const& sysInc = impl->Makefile->GetSystemIncludeDirectories(); impl->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end()); } - cmAppend(impl->CompileOptionsEntries, - impl->Makefile->GetCompileOptionsEntries()); - cmAppend(impl->CompileOptionsBacktraces, - impl->Makefile->GetCompileOptionsBacktraces()); + cm::append(impl->CompileOptionsEntries, + impl->Makefile->GetCompileOptionsEntries()); + cm::append(impl->CompileOptionsBacktraces, + impl->Makefile->GetCompileOptionsBacktraces()); - cmAppend(impl->LinkOptionsEntries, - impl->Makefile->GetLinkOptionsEntries()); - cmAppend(impl->LinkOptionsBacktraces, - impl->Makefile->GetLinkOptionsBacktraces()); + cm::append(impl->LinkOptionsEntries, + impl->Makefile->GetLinkOptionsEntries()); + cm::append(impl->LinkOptionsBacktraces, + impl->Makefile->GetLinkOptionsBacktraces()); - cmAppend(impl->LinkDirectoriesEntries, - impl->Makefile->GetLinkDirectoriesEntries()); - cmAppend(impl->LinkDirectoriesBacktraces, - impl->Makefile->GetLinkDirectoriesBacktraces()); + cm::append(impl->LinkDirectoriesEntries, + impl->Makefile->GetLinkDirectoriesEntries()); + cm::append(impl->LinkDirectoriesBacktraces, + impl->Makefile->GetLinkDirectoriesBacktraces()); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && @@ -511,8 +519,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("DOTNET_TARGET_FRAMEWORK_VERSION"); } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetType() != cmStateEnums::UTILITY) { + if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { // check for "CMAKE_VS_GLOBALS" variable and set up target properties // if any @@ -948,9 +955,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, (isNonImportedTarget && llt != GENERAL_LibraryType) ? targetNameGenex(libRef) : libRef; - this->AppendProperty( - "LINK_LIBRARIES", - this->GetDebugGeneratorExpressions(libName, llt).c_str()); + this->AppendProperty("LINK_LIBRARIES", + this->GetDebugGeneratorExpressions(libName, llt)); } if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef || @@ -1284,9 +1290,9 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) impl->Properties.SetProperty(prop, reusedFrom.c_str()); - reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom.c_str()); + reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom); reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", - cmStrCat(reusedFrom, ".dir/").c_str()); + cmStrCat(reusedFrom, ".dir/")); this->SetProperty("COMPILE_PDB_NAME", reusedTarget->GetProperty("COMPILE_PDB_NAME")); @@ -1421,7 +1427,7 @@ void cmTarget::AppendBuildInterfaceIncludes() dirs += impl->Makefile->GetCurrentSourceDirectory(); if (!dirs.empty()) { this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", - ("$<BUILD_INTERFACE:" + dirs + ">").c_str()); + ("$<BUILD_INTERFACE:" + dirs + ">")); } } } @@ -1799,6 +1805,11 @@ bool cmTarget::IsImportedGloballyVisible() const return impl->ImportedGloballyVisible; } +bool cmTarget::IsPerConfig() const +{ + return impl->PerConfig; +} + const char* cmTarget::GetSuffixVariableInternal( cmStateEnums::ArtifactType artifact) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 65a1ce36fd..bdf8c0f84c 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -44,7 +44,7 @@ public: }; cmTarget(std::string const& name, cmStateEnums::TargetType type, - Visibility vis, cmMakefile* mf); + Visibility vis, cmMakefile* mf, bool perConfig); cmTarget(cmTarget const&) = delete; cmTarget(cmTarget&&) noexcept; @@ -164,8 +164,17 @@ public: //! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); + void SetProperty(const std::string& prop, const std::string& value) + { + SetProperty(prop, value.c_str()); + } void AppendProperty(const std::string& prop, const char* value, bool asString = false); + void AppendProperty(const std::string& prop, const std::string& value, + bool asString = false) + { + AppendProperty(prop, value.c_str(), asString); + } //! 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 @@ -186,6 +195,7 @@ public: bool IsImported() const; bool IsImportedGloballyVisible() const; + bool IsPerConfig() const; bool GetMappedConfig(std::string const& desired_config, const char** loc, const char** imp, std::string& suffix) const; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index edee167004..b56b245de5 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -28,7 +28,7 @@ private: const std::vector<std::string>& content, bool /*prepend*/, bool /*system*/) override { - tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str()); + tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content)); return true; // Successfully handled. } diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index e39b726705..dee2c10a39 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -5,6 +5,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmTargetPropCommandBase.h" @@ -27,10 +28,16 @@ private: bool HandleDirectContent(cmTarget* tgt, const std::vector<std::string>& content, - bool /*prepend*/, bool /*system*/) override + bool prepend, bool /*system*/) override { + cmPolicies::PolicyStatus policyStatus = + this->Makefile->GetPolicyStatus(cmPolicies::CMP0101); + if (policyStatus == cmPolicies::OLD || policyStatus == cmPolicies::WARN) { + prepend = false; + } + cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertCompileOption(this->Join(content), lfbt); + tgt->InsertCompileOption(this->Join(content), lfbt, prepend); return true; // Successfully handled. } diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 95b69f3998..35635b94b8 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -88,8 +88,7 @@ void TargetIncludeDirectoriesImpl::HandleInterfaceContent( system); if (system) { std::string joined = this->Join(content); - tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", - joined.c_str()); + tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", joined); } } diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 0d2383a1cd..ad59748d29 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -406,6 +406,10 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // the name to tell ResolveLinkItem to look up the name in the // caller's directory. cmDirectoryId const dirId = mf.GetDirectoryId(); + // FIXME: The "lib" may be a genex with a list inside it. + // After expansion this id will only attach to the last entry, + // or may attach to an empty string! We will need another way + // to encode this that can apply to a whole list. See issue #20204. libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String; } else { // This is an absolute path or a library name added by a caller @@ -480,7 +484,7 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, cmGeneratorExpression::Find(lib) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } - target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib.c_str()); + target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib); } return true; } @@ -488,9 +492,8 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // Handle general case where the command was called with another keyword than // PRIVATE / LINK_PRIVATE or none at all. (The "INTERFACE_LINK_LIBRARIES" // property of the target on the LHS shall be populated.) - target->AppendProperty( - "INTERFACE_LINK_LIBRARIES", - target->GetDebugGeneratorExpressions(libRef, llt).c_str()); + target->AppendProperty("INTERFACE_LINK_LIBRARIES", + target->GetDebugGeneratorExpressions(libRef, llt)); // Stop processing if called without any keyword. if (currentProcessingState == ProcessingLinkLibraries) { @@ -522,12 +525,12 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // Put in the DEBUG configuration interfaces. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - target->AppendProperty(prop, libRef.c_str()); + target->AppendProperty(prop, libRef); } } if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) { // Put in the non-DEBUG configuration interfaces. - target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.c_str()); + target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef); // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx index c6e2e5c4fe..0670bd962a 100644 --- a/Source/cmTargetPrecompileHeadersCommand.cxx +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -47,9 +47,8 @@ private: bool /*prepend*/, bool /*system*/) override { std::string const& base = this->Makefile->GetCurrentSourceDirectory(); - tgt->AppendProperty( - "PRECOMPILE_HEADERS", - this->Join(ConvertToAbsoluteContent(content, base)).c_str()); + tgt->AppendProperty("PRECOMPILE_HEADERS", + this->Join(ConvertToAbsoluteContent(content, base))); return true; } diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index bbc1e16f76..0de8d6d05a 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -84,9 +84,7 @@ bool cmTargetPropCommandBase::HandleArguments( } ++argIndex; - this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", - args[argIndex].c_str()); - + this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", args[argIndex]); ++argIndex; } @@ -162,9 +160,8 @@ void cmTargetPropCommandBase::HandleInterfaceContent( const char* propValue = tgt->GetProperty(propName); const std::string totalContent = this->Join(content) + (propValue ? std::string(";") + propValue : std::string()); - tgt->SetProperty(propName, totalContent.c_str()); + tgt->SetProperty(propName, totalContent); } else { - tgt->AppendProperty("INTERFACE_" + this->Property, - this->Join(content).c_str()); + tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content)); } } diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index baab8da0ad..f37995c23d 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -62,6 +62,7 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( "COMPATIBLE_INTERFACE_NUMBER_MAX", "COMPATIBLE_INTERFACE_NUMBER_MIN", "COMPATIBLE_INTERFACE_STRING", + "DEPRECATION", "EXPORT_NAME", "EXPORT_PROPERTIES", "IMPORTED", diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index c2e0b28fe1..a1fbc9b9b0 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -43,8 +43,7 @@ private: bool /*prepend*/, bool /*system*/) override { tgt->AppendProperty( - "SOURCES", - this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str()); + "SOURCES", this->Join(ConvertToAbsoluteContent(tgt, content, false))); return true; // Successfully handled. } diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx index 4995da972f..35e1c8c56f 100644 --- a/Source/cmVariableWatch.cxx +++ b/Source/cmVariableWatch.cxx @@ -2,19 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVariableWatch.h" +#include <array> #include <memory> #include <utility> #include <vector> -static const char* const cmVariableWatchAccessStrings[] = { - "READ_ACCESS", "UNKNOWN_READ_ACCESS", "UNKNOWN_DEFINED_ACCESS", - "MODIFIED_ACCESS", "REMOVED_ACCESS", "NO_ACCESS" -}; - -const char* cmVariableWatch::GetAccessAsString(int access_type) +const std::string& cmVariableWatch::GetAccessAsString(int access_type) { + static const std::array<std::string, 6> cmVariableWatchAccessStrings = { + { "READ_ACCESS", "UNKNOWN_READ_ACCESS", "UNKNOWN_DEFINED_ACCESS", + "MODIFIED_ACCESS", "REMOVED_ACCESS", "NO_ACCESS" } + }; if (access_type < 0 || access_type >= cmVariableWatch::NO_ACCESS) { - return "NO_ACCESS"; + access_type = cmVariableWatch::NO_ACCESS; } return cmVariableWatchAccessStrings[access_type]; } diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h index e4b3b7c47f..6c418ed0ab 100644 --- a/Source/cmVariableWatch.h +++ b/Source/cmVariableWatch.h @@ -46,7 +46,7 @@ public: */ enum { - VARIABLE_READ_ACCESS = 0, + VARIABLE_READ_ACCESS, UNKNOWN_VARIABLE_READ_ACCESS, UNKNOWN_VARIABLE_DEFINED_ACCESS, VARIABLE_MODIFIED_ACCESS, @@ -57,7 +57,7 @@ public: /** * Return the access as string */ - static const char* GetAccessAsString(int access_type); + static const std::string& GetAccessAsString(int access_type); protected: struct Pair diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index f2c8f3cdb9..35b9a1d5b7 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVariableWatchCommand.h" +#include <limits> #include <memory> #include <utility> @@ -14,17 +15,19 @@ #include "cmVariableWatch.h" #include "cmake.h" +class cmLocalGenerator; + +namespace { struct cmVariableWatchCallbackData { bool InCallback; std::string Command; }; -static void cmVariableWatchCommandVariableAccessed(const std::string& variable, - int access_type, - void* client_data, - const char* newValue, - const cmMakefile* mf) +void cmVariableWatchCommandVariableAccessed(const std::string& variable, + int access_type, void* client_data, + const char* newValue, + const cmMakefile* mf) { cmVariableWatchCallbackData* data = static_cast<cmVariableWatchCallbackData*>(client_data); @@ -34,40 +37,35 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, } data->InCallback = true; - cmListFileFunction newLFF; - cmListFileArgument arg; - bool processed = false; - const char* accessString = cmVariableWatch::GetAccessAsString(access_type); - const char* currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE"); + auto accessString = cmVariableWatch::GetAccessAsString(access_type); /// Ultra bad!! cmMakefile* makefile = const_cast<cmMakefile*>(mf); std::string stack = makefile->GetProperty("LISTFILE_STACK"); if (!data->Command.empty()) { - newLFF.Arguments.clear(); - newLFF.Arguments.emplace_back(variable, cmListFileArgument::Quoted, 9999); - newLFF.Arguments.emplace_back(accessString, cmListFileArgument::Quoted, - 9999); - newLFF.Arguments.emplace_back(newValue ? newValue : "", - cmListFileArgument::Quoted, 9999); - newLFF.Arguments.emplace_back(currentListFile, cmListFileArgument::Quoted, - 9999); - newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999); + cmListFileFunction newLFF; + const char* const currentListFile = + mf->GetDefinition("CMAKE_CURRENT_LIST_FILE"); + const auto fakeLineNo = + std::numeric_limits<decltype(cmListFileArgument::Line)>::max(); + newLFF.Arguments = { + { variable, cmListFileArgument::Quoted, fakeLineNo }, + { accessString, cmListFileArgument::Quoted, fakeLineNo }, + { newValue ? newValue : "", cmListFileArgument::Quoted, fakeLineNo }, + { currentListFile, cmListFileArgument::Quoted, fakeLineNo }, + { stack, cmListFileArgument::Quoted, fakeLineNo } + }; newLFF.Name = data->Command; - newLFF.Line = 9999; + newLFF.Line = fakeLineNo; cmExecutionStatus status(*makefile); if (!makefile->ExecuteCommand(newLFF, status)) { cmSystemTools::Error( cmStrCat("Error in cmake code at\nUnknown:0:\nA command failed " "during the invocation of callback \"", data->Command, "\".")); - data->InCallback = false; - return; } - processed = true; - } - if (!processed) { + } else { makefile->IssueMessage( MessageType::LOG, cmStrCat("Variable \"", variable, "\" was accessed using ", accessString, @@ -77,7 +75,7 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, data->InCallback = false; } -static void deleteVariableWatchCallbackData(void* client_data) +void deleteVariableWatchCallbackData(void* client_data) { cmVariableWatchCallbackData* data = static_cast<cmVariableWatchCallbackData*>(client_data); @@ -91,18 +89,18 @@ class FinalAction public: /* NOLINTNEXTLINE(performance-unnecessary-value-param) */ FinalAction(cmMakefile* makefile, std::string variable) - : Action(std::make_shared<Impl>(makefile, std::move(variable))) + : Action{ std::make_shared<Impl>(makefile, std::move(variable)) } { } - void operator()(cmMakefile&) const {} + void operator()(cmLocalGenerator&, const cmListFileBacktrace&) const {} private: struct Impl { Impl(cmMakefile* makefile, std::string variable) - : Makefile(makefile) - , Variable(std::move(variable)) + : Makefile{ makefile } + , Variable{ std::move(variable) } { } @@ -112,12 +110,13 @@ private: this->Variable, cmVariableWatchCommandVariableAccessed); } - cmMakefile* Makefile; - std::string Variable; + cmMakefile* const Makefile; + std::string const Variable; }; std::shared_ptr<Impl const> Action; }; +} // anonymous namespace bool cmVariableWatchCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -136,10 +135,10 @@ bool cmVariableWatchCommand(std::vector<std::string> const& args, return false; } - cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData; + auto* const data = new cmVariableWatchCallbackData; data->InCallback = false; - data->Command = command; + data->Command = std::move(command); if (!status.GetMakefile().GetCMakeInstance()->GetVariableWatch()->AddWatch( variable, cmVariableWatchCommandVariableAccessed, data, @@ -148,7 +147,7 @@ bool cmVariableWatchCommand(std::vector<std::string> const& args, return false; } - status.GetMakefile().AddFinalAction( - FinalAction(&status.GetMakefile(), variable)); + status.GetMakefile().AddGeneratorAction( + FinalAction{ &status.GetMakefile(), variable }); return true; } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 53fc93cf66..f707bb44da 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -52,7 +52,7 @@ struct cmVisualStudio10TargetGenerator::Elem bool HasContent = false; std::string Tag; - Elem(std::ostream& s, const char* tag) + Elem(std::ostream& s, const std::string& tag) : S(s) , Indent(0) , Tag(tag) @@ -60,7 +60,7 @@ struct cmVisualStudio10TargetGenerator::Elem this->StartElement(); } Elem(const Elem&) = delete; - Elem(Elem& par, const char* tag) + Elem(Elem& par, const std::string& tag) : S(par.S) , Indent(par.Indent + 1) , Tag(tag) @@ -71,13 +71,13 @@ struct cmVisualStudio10TargetGenerator::Elem void SetHasElements() { if (!HasElements) { - this->S << ">\n"; + this->S << ">"; HasElements = true; } } std::ostream& WriteString(const char* line); void StartElement() { this->WriteString("<") << this->Tag; } - void Element(const char* tag, const std::string& val) + void Element(const std::string& tag, const std::string& val) { Elem(*this, tag).Content(val); } @@ -103,19 +103,14 @@ struct cmVisualStudio10TargetGenerator::Elem if (HasElements) { this->WriteString("</") << this->Tag << ">"; - if (this->Indent > 0) { - this->S << '\n'; - } else { - // special case: don't print EOL at EOF - } } else if (HasContent) { - this->S << "</" << this->Tag << ">\n"; + this->S << "</" << this->Tag << ">"; } else { - this->S << " />\n"; + this->S << " />"; } } - void WritePlatformConfigTag(const char* tag, const std::string& cond, + void WritePlatformConfigTag(const std::string& tag, const std::string& cond, const std::string& content); }; @@ -131,8 +126,8 @@ public: { } - void OutputFlag(std::ostream& /*fout*/, int /*indent*/, const char* tag, - const std::string& content) override + void OutputFlag(std::ostream& /*fout*/, int /*indent*/, + const std::string& tag, const std::string& content) override { if (!this->GetConfiguration().empty()) { // if there are configuration specific flags, then @@ -274,7 +269,7 @@ std::string cmVisualStudio10TargetGenerator::CalcCondition( } void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag( - const char* tag, const std::string& cond, const std::string& content) + const std::string& tag, const std::string& cond, const std::string& content) { Elem(*this, tag).Attribute("Condition", cond).Content(content); } @@ -282,6 +277,7 @@ void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag( std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( const char* line) { + this->S << '\n'; this->S.fill(' '); this->S.width(this->Indent * 2); // write an empty string to get the fill level indent to print @@ -334,9 +330,9 @@ void cmVisualStudio10TargetGenerator::Generate() } // Tell the global generator the name of the project file this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", - this->Name.c_str()); + this->Name); this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME_EXT", - ProjectFileExtension.c_str()); + ProjectFileExtension); this->DotNetHintReferences.clear(); this->AdditionalUsingDirectories.clear(); if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) { @@ -376,8 +372,7 @@ void cmVisualStudio10TargetGenerator::Generate() char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; BuildFileStream.write(magic, 3); BuildFileStream << "<?xml version=\"1.0\" encoding=\"" - << this->GlobalGenerator->Encoding() << "\"?>" - << "\n"; + << this->GlobalGenerator->Encoding() << "\"?>"; { Elem e0(BuildFileStream, "Project"); e0.Attribute("DefaultTargets", "Build"); @@ -543,6 +538,11 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element("VCProjectUpgraderObjectName", "NoUpgrade"); } + if (const char* vcTargetsPath = + this->GlobalGenerator->GetCustomVCTargetsPath()) { + e1.Element("VCTargetsPath", vcTargetsPath); + } + std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys(); for (std::string const& keyIt : keys) { static const char* prefix = "VS_GLOBAL_"; @@ -557,7 +557,7 @@ void cmVisualStudio10TargetGenerator::Generate() const char* value = this->GeneratorTarget->GetProperty(keyIt); if (!value) continue; - e1.Element(globalKey.c_str(), value); + e1.Element(globalKey, value); } if (this->Managed) { @@ -676,6 +676,8 @@ void cmVisualStudio10TargetGenerator::Generate() this->WritePlatformExtensions(e1); } + + this->WriteDotNetDocumentationFile(e0); Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros"); this->WriteWinRTPackageCertificateKeyFile(e0); this->WritePathAndIncrementalLinkOptions(e0); @@ -906,7 +908,19 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags( } } for (auto const& tag : tags) { - e2.Element(tag.first.c_str(), tag.second); + e2.Element(tag.first, tag.second); + } +} + +void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0) +{ + std::string const documentationFile = + this->GeneratorTarget->GetSafeProperty("VS_DOTNET_DOCUMENTATION_FILE"); + + if (this->ProjectType == csproj && !documentationFile.empty()) { + Elem e1(e0, "PropertyGroup"); + Elem e2(e1, "DocumentationFile"); + e2.Content(documentationFile); } } @@ -1000,7 +1014,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) if (!tagName.empty()) { std::string value = props.GetPropertyValue(p); if (!value.empty()) { - e2.Element(tagName.c_str(), value); + e2.Element(tagName, value); } } } @@ -1592,8 +1606,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() fout.write(magic, 3); fout << "<?xml version=\"1.0\" encoding=\"" - << this->GlobalGenerator->Encoding() << "\"?>" - << "\n"; + << this->GlobalGenerator->Encoding() << "\"?>"; { Elem e0(fout, "Project"); e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion()); @@ -1732,7 +1745,7 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources( std::string const& filter = sourceGroup->GetFullName(); std::string path = this->ConvertPath(source, s.RelativePath); ConvertToWindowsSlash(path); - Elem e2(e1, name.c_str()); + Elem e2(e1, name); e2.Attribute("Include", path); if (!filter.empty()) { e2.Element("Filter", filter); @@ -2622,9 +2635,9 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( // Some link options belong here. Use them now and remove them so that // WriteLinkOptions does not use them. - const char* flags[] = { "LinkDelaySign", "LinkKeyFile", 0 }; - for (const char** f = flags; *f; ++f) { - const char* flag = *f; + static const std::vector<std::string> flags{ "LinkDelaySign", + "LinkKeyFile" }; + for (const std::string& flag : flags) { if (const char* value = linkOptions.GetFlag(flag)) { e1.WritePlatformConfigTag(flag, cond, value); linkOptions.RemoveFlag(flag); @@ -2816,10 +2829,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } if (this->MSTools) { - // If we have the VS_WINRT_COMPONENT or CMAKE_VS_WINRT_BY_DEFAULT - // set then force Compile as WinRT. - if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") || - this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) { + // If we have the VS_WINRT_COMPONENT set then force Compile as WinRT + if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) { clOptions.AddFlag("CompileAsWinRT", "true"); // For WinRT components, add the _WINRT_DLL define to produce a lib if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -2827,7 +2838,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( clOptions.AddDefine("_WINRT_DLL"); } } else if (this->GlobalGenerator->TargetsWindowsStore() || - this->GlobalGenerator->TargetsWindowsPhone()) { + this->GlobalGenerator->TargetsWindowsPhone() || + this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) { if (!clOptions.IsWinRt()) { clOptions.AddFlag("CompileAsWinRT", "false"); } @@ -4025,8 +4037,8 @@ void cmVisualStudio10TargetGenerator::WriteEvents( } void cmVisualStudio10TargetGenerator::WriteEvent( - Elem& e1, const char* name, std::vector<cmCustomCommand> const& commands, - std::string const& configName) + Elem& e1, const std::string& name, + std::vector<cmCustomCommand> const& commands, std::string const& configName) { if (commands.empty()) { return; @@ -4845,7 +4857,7 @@ void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties( Elem& e2, const std::map<std::string, std::string>& tags) { for (const auto& i : tags) { - e2.Element(i.first.c_str(), i.second); + e2.Element(i.first, i.second); } } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index a18a33dd89..30027c9e72 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -79,6 +79,7 @@ private: void WriteDotNetReference(Elem& e1, std::string const& ref, std::string const& hint, std::string const& config); + void WriteDotNetDocumentationFile(Elem& e0); void WriteImports(Elem& e0); void WriteDotNetReferenceCustomTags(Elem& e2, std::string const& ref); void WriteEmbeddedResourceGroup(Elem& e0); @@ -164,7 +165,7 @@ private: void WriteLibOptions(Elem& e1, std::string const& config); void WriteManifestOptions(Elem& e1, std::string const& config); void WriteEvents(Elem& e1, std::string const& configName); - void WriteEvent(Elem& e1, const char* name, + void WriteEvent(Elem& e1, std::string const& name, std::vector<cmCustomCommand> const& commands, std::string const& configName); void WriteGroupSources(Elem& e0, std::string const& name, diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 1139aa9745..18c19b7d69 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -431,7 +431,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( if (this->Defines.empty()) { return; } - const char* tag = "PreprocessorDefinitions"; + std::string tag = "PreprocessorDefinitions"; if (lang == "CUDA") { tag = "Defines"; } @@ -473,7 +473,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories( return; } - const char* tag = "AdditionalIncludeDirectories"; + std::string tag = "AdditionalIncludeDirectories"; if (lang == "CUDA") { tag = "Include"; } else if (lang == "ASM_MASM" || lang == "ASM_NASM") { @@ -528,6 +528,6 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout, sep = ";"; } - this->OutputFlag(fout, indent, m.first.c_str(), oss.str()); + this->OutputFlag(fout, indent, m.first, oss.str()); } } diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 560593e011..d8dcfe2d22 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -86,7 +86,8 @@ public: const std::string& GetConfiguration() const; protected: - virtual void OutputFlag(std::ostream& fout, int indent, const char* tag, + virtual void OutputFlag(std::ostream& fout, int indent, + const std::string& tag, const std::string& content) = 0; private: diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index afc95f56c5..b34c2f6e14 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -8,13 +8,16 @@ #include <utility> #include "cmGeneratedFileStream.h" +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmXMLSafe.h" -cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, TestObjects tests, +cmXCodeScheme::cmXCodeScheme(cmLocalGenerator* lg, cmXCodeObject* xcObj, + TestObjects tests, const std::vector<std::string>& configList, unsigned int xcVersion) - : Target(xcObj) + : LocalGenerator(lg) + , Target(xcObj) , Tests(std::move(tests)) , TargetName(xcObj->GetTarget()->GetName()) , ConfigList(configList) @@ -135,7 +138,8 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, xout.Attribute("selectedLauncherIdentifier", "Xcode.DebuggerFoundation.Launcher.LLDB"); xout.Attribute("launchStyle", "0"); - xout.Attribute("useCustomWorkingDirectory", "NO"); + WriteCustomWorkingDirectory(xout, configuration); + xout.Attribute("ignoresPersistentStateOnLaunch", "NO"); WriteLaunchActionBooleanAttribute(xout, "debugDocumentVersioning", "XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING", @@ -355,7 +359,7 @@ void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout, xout.Attribute("buildConfiguration", configuration); xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); xout.Attribute("savedToolIdentifier", ""); - xout.Attribute("useCustomWorkingDirectory", "NO"); + WriteCustomWorkingDirectory(xout, configuration); WriteLaunchActionBooleanAttribute(xout, "debugDocumentVersioning", "XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING", true); @@ -395,6 +399,22 @@ void cmXCodeScheme::WriteBuildableReference(cmXMLWriter& xout, xout.EndElement(); } +void cmXCodeScheme::WriteCustomWorkingDirectory( + cmXMLWriter& xout, const std::string& configuration) +{ + std::string propertyValue = this->Target->GetTarget()->GetSafeProperty( + "XCODE_SCHEME_WORKING_DIRECTORY"); + if (propertyValue.empty()) { + xout.Attribute("useCustomWorkingDirectory", "NO"); + } else { + xout.Attribute("useCustomWorkingDirectory", "YES"); + + auto customWorkingDirectory = cmGeneratorExpression::Evaluate( + propertyValue, this->LocalGenerator, configuration); + xout.Attribute("customWorkingDirectory", customWorkingDirectory); + } +} + std::string cmXCodeScheme::WriteVersionString() { std::ostringstream v; diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h index dff5e35e39..da4085669f 100644 --- a/Source/cmXCodeScheme.h +++ b/Source/cmXCodeScheme.h @@ -20,7 +20,7 @@ class cmXCodeScheme public: using TestObjects = std::vector<const cmXCodeObject*>; - cmXCodeScheme(cmXCodeObject* xcObj, TestObjects tests, + cmXCodeScheme(cmLocalGenerator* lg, cmXCodeObject* xcObj, TestObjects tests, const std::vector<std::string>& configList, unsigned int xcVersion); @@ -28,6 +28,7 @@ public: const std::string& container); private: + cmLocalGenerator* const LocalGenerator; const cmXCodeObject* const Target; const TestObjects Tests; const std::string& TargetName; @@ -63,6 +64,9 @@ private: void WriteBuildableReference(cmXMLWriter& xout, const cmXCodeObject* xcObj, const std::string& container); + void WriteCustomWorkingDirectory(cmXMLWriter& xout, + const std::string& configuration); + std::string WriteVersionString(); std::string FindConfiguration(const std::string& name); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index f63a264006..ab76df9103 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2,12 +2,27 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmake.h" +#include <algorithm> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <initializer_list> +#include <iostream> +#include <sstream> +#include <utility> + #include <cm/memory> #include <cm/string_view> #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) # include <cm/iterator> #endif +#include <cmext/algorithm> + +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" + #include "cm_sys_stat.h" #include "cmAlgorithms.h" @@ -56,6 +71,8 @@ // include the generator #if defined(_WIN32) && !defined(__CYGWIN__) # if !defined(CMAKE_BOOT_MINGW) +# include <cmext/memory> + # include "cmGlobalBorlandMakefileGenerator.h" # include "cmGlobalJOMMakefileGenerator.h" # include "cmGlobalNMakeMakefileGenerator.h" @@ -106,19 +123,6 @@ # include <sys/time.h> #endif -#include <algorithm> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <initializer_list> -#include <iostream> -#include <sstream> -#include <utility> - -#include "cmsys/FStream.hxx" -#include "cmsys/Glob.hxx" -#include "cmsys/RegularExpression.hxx" - namespace { #if !defined(CMAKE_BOOTSTRAP) @@ -201,14 +205,7 @@ cmake::cmake(Role role, cmState::Mode mode) } } -cmake::~cmake() -{ - if (this->GlobalGenerator) { - delete this->GlobalGenerator; - this->GlobalGenerator = nullptr; - } - cmDeleteAll(this->Generators); -} +cmake::~cmake() = default; #if !defined(CMAKE_BOOTSTRAP) Json::Value cmake::ReportVersionJson() const @@ -330,9 +327,8 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) } } } else { - std::cerr << "Parse error in command line argument: " << arg << "\n" - << "Should be: VAR:type=value\n"; - cmSystemTools::Error("No cmake script provided."); + cmSystemTools::Error("Parse error in command line argument: " + arg + + "\n" + "Should be: VAR:type=value\n"); return false; } } else if (cmHasLiteralPrefix(arg, "-W")) { @@ -422,7 +418,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) return false; } } - std::cout << "loading initial cache file " << path << "\n"; + cmSystemTools::Stdout("loading initial cache file " + path + "\n"); // Resolve script path specified on command line relative to $PWD. path = cmSystemTools::CollapseFullPath(path); this->ReadListFile(args, path); @@ -462,12 +458,12 @@ void cmake::ReadListFile(const std::vector<std::string>& args, { // if a generator was not yet created, temporarily create one cmGlobalGenerator* gg = this->GetGlobalGenerator(); - bool created = false; // if a generator was not specified use a generic one + std::unique_ptr<cmGlobalGenerator> gen; if (!gg) { - gg = new cmGlobalGenerator(this); - created = true; + gen = cm::make_unique<cmGlobalGenerator>(this); + gg = gen.get(); } // read in the list file to fill the cache @@ -489,11 +485,6 @@ void cmake::ReadListFile(const std::vector<std::string>& args, cmSystemTools::Error("Error processing file: " + path); } } - - // free generic one if generated - if (created) { - delete gg; - } } bool cmake::FindPackage(const std::vector<std::string>& args) @@ -501,9 +492,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory()); this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); - // if a generator was not yet created, temporarily create one - cmGlobalGenerator* gg = new cmGlobalGenerator(this); - this->SetGlobalGenerator(gg); + this->SetGlobalGenerator(cm::make_unique<cmGlobalGenerator>(this)); cmStateSnapshot snapshot = this->GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentBinary( @@ -512,8 +501,9 @@ bool cmake::FindPackage(const std::vector<std::string>& args) cmSystemTools::GetCurrentWorkingDirectory()); // read in the list file to fill the cache snapshot.SetDefaultDefinitions(); - cmMakefile* mf = new cmMakefile(gg, snapshot); - gg->AddMakefile(mf); + auto mfu = cm::make_unique<cmMakefile>(this->GetGlobalGenerator(), snapshot); + cmMakefile* mf = mfu.get(); + this->GlobalGenerator->AddMakefile(std::move(mfu)); mf->SetArgcArgv(args); @@ -538,8 +528,8 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS"); std::vector<std::string> includeDirs = cmExpandedList(includes); - gg->CreateGenerationObjects(); - cmLocalGenerator* lg = gg->LocalGenerators[0]; + this->GlobalGenerator->CreateGenerationObjects(); + const auto& lg = this->GlobalGenerator->LocalGenerators[0]; std::string includeFlags = lg->GetIncludeFlags(includeDirs, nullptr, language); @@ -549,7 +539,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) const char* targetName = "dummy"; std::vector<std::string> srcs; cmTarget* tgt = mf->AddExecutable(targetName, srcs, true); - tgt->SetProperty("LINKER_LANGUAGE", language.c_str()); + tgt->SetProperty("LINKER_LANGUAGE", language); std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES"); std::vector<std::string> libList = cmExpandedList(libs); @@ -565,8 +555,9 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::string linkPath; std::string flags; std::string linkFlags; - gg->CreateGenerationObjects(); - cmGeneratorTarget* gtgt = gg->FindGeneratorTarget(tgt->GetName()); + this->GlobalGenerator->CreateGenerationObjects(); + cmGeneratorTarget* gtgt = + this->GlobalGenerator->FindGeneratorTarget(tgt->GetName()); cmLocalGenerator* lg = gtgt->GetLocalGenerator(); cmLinkLineComputer linkLineComputer(lg, lg->GetStateSnapshot().GetDirectory()); @@ -586,10 +577,6 @@ bool cmake::FindPackage(const std::vector<std::string>& args) }*/ } - // free generic one if generated - // this->SetGlobalGenerator(0); // setting 0-pointer is not possible - // delete gg; // this crashes inside the cmake instance - return packageFound; } @@ -735,6 +722,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetLogLevel(logLevel); + this->LogLevelWasSetViaCLI = true; } else if (arg.find("--loglevel=", 0) == 0) { // This is supported for backward compatibility. This option only // appeared in the 3.15.x release series and was renamed to @@ -746,10 +734,25 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetLogLevel(logLevel); + this->LogLevelWasSetViaCLI = true; + } else if (arg == "--log-context") { + this->SetShowLogContext(true); + } else if (arg.find("--debug-find", 0) == 0) { + std::cout << "Running with debug output on for the `find` commands.\n"; + this->SetDebugFindOutputOn(true); } else if (arg.find("--trace-expand", 0) == 0) { std::cout << "Running with expanded trace output on.\n"; this->SetTrace(true); this->SetTraceExpand(true); + } else if (arg.find("--trace-format=", 0) == 0) { + this->SetTrace(true); + const auto traceFormat = + StringToTraceFormat(arg.substr(strlen("--trace-format="))); + if (traceFormat == TraceFormat::TRACE_UNDEFINED) { + cmSystemTools::Error("Invalid format specified for --trace-format"); + return; + } + this->SetTraceFormat(traceFormat); } else if (arg.find("--trace-source=", 0) == 0) { std::string file = arg.substr(strlen("--trace-source=")); cmSystemTools::ConvertToUnixSlashes(file); @@ -821,7 +824,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) } value = args[i]; } - cmGlobalGenerator* gen = this->CreateGlobalGenerator(value); + auto gen = this->CreateGlobalGenerator(value); if (!gen) { std::string kdevError; if (value.find("KDevelop3", 0) != std::string::npos) { @@ -833,7 +836,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) this->PrintGeneratorList(); return; } - this->SetGlobalGenerator(gen); + this->SetGlobalGenerator(std::move(gen)); } // no option assume it is the path to the source or an existing build else { @@ -890,6 +893,23 @@ cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr) return (it != levels.cend()) ? it->second : LogLevel::LOG_UNDEFINED; } +cmake::TraceFormat cmake::StringToTraceFormat(const std::string& traceStr) +{ + using TracePair = std::pair<std::string, TraceFormat>; + static const std::vector<TracePair> levels = { + { "human", TraceFormat::TRACE_HUMAN }, + { "json-v1", TraceFormat::TRACE_JSON_V1 }, + }; + + const auto traceStrLowCase = cmSystemTools::LowerCase(traceStr); + + const auto it = std::find_if(levels.cbegin(), levels.cend(), + [&traceStrLowCase](const TracePair& p) { + return p.first == traceStrLowCase; + }); + return (it != levels.cend()) ? it->second : TraceFormat::TRACE_UNDEFINED; +} + void cmake::SetTraceFile(const std::string& file) { this->TraceFile.close(); @@ -904,6 +924,48 @@ void cmake::SetTraceFile(const std::string& file) std::cout << "Trace will be written to " << file << "\n"; } +void cmake::PrintTraceFormatVersion() +{ + if (!this->GetTrace()) { + return; + } + + std::string msg; + + switch (this->GetTraceFormat()) { + case TraceFormat::TRACE_JSON_V1: { +#ifndef CMAKE_BOOTSTRAP + Json::Value val; + Json::Value version; + Json::StreamWriterBuilder builder; + builder["indentation"] = ""; + version["major"] = 1; + version["minor"] = 0; + val["version"] = version; + msg = Json::writeString(builder, val); +#endif + break; + } + case TraceFormat::TRACE_HUMAN: + msg = ""; + break; + case TraceFormat::TRACE_UNDEFINED: + msg = "INTERNAL ERROR: Trace format is TRACE_UNDEFINED"; + break; + } + + if (msg.empty()) { + return; + } + + auto& f = this->GetTraceFile(); + if (f) { + f << msg << '\n'; + } else { + cmSystemTools::Message(msg); + } +} + void cmake::SetDirectoriesFromFile(const std::string& arg) { // Check if the argument refers to a CMakeCache.txt or @@ -1042,11 +1104,11 @@ void cmake::AddDefaultExtraGenerators() void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, bool includeNamesWithPlatform) const { - for (cmGlobalGeneratorFactory* gen : this->Generators) { + for (const auto& gen : this->Generators) { std::vector<std::string> names = gen->GetGeneratorNames(); if (includeNamesWithPlatform) { - cmAppend(names, gen->GetGeneratorNamesWithPlatform()); + cm::append(names, gen->GetGeneratorNamesWithPlatform()); } for (std::string const& name : names) { @@ -1091,7 +1153,8 @@ void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, } } -static std::pair<cmExternalMakefileProjectGenerator*, std::string> +static std::pair<std::unique_ptr<cmExternalMakefileProjectGenerator>, + std::string> createExtraGenerator( const std::vector<cmExternalMakefileProjectGeneratorFactory*>& in, const std::string& name) @@ -1114,15 +1177,17 @@ createExtraGenerator( return { nullptr, name }; } -cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname) +std::unique_ptr<cmGlobalGenerator> cmake::CreateGlobalGenerator( + const std::string& gname) { - std::pair<cmExternalMakefileProjectGenerator*, std::string> extra = - createExtraGenerator(this->ExtraGenerators, gname); - cmExternalMakefileProjectGenerator* extraGenerator = extra.first; - const std::string name = extra.second; + std::pair<std::unique_ptr<cmExternalMakefileProjectGenerator>, std::string> + extra = createExtraGenerator(this->ExtraGenerators, gname); + std::unique_ptr<cmExternalMakefileProjectGenerator>& extraGenerator = + extra.first; + const std::string& name = extra.second; - cmGlobalGenerator* generator = nullptr; - for (cmGlobalGeneratorFactory* g : this->Generators) { + std::unique_ptr<cmGlobalGenerator> generator; + for (const auto& g : this->Generators) { generator = g->CreateGlobalGenerator(name, this); if (generator) { break; @@ -1130,9 +1195,7 @@ cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname) } if (generator) { - generator->SetExternalMakefileProjectGenerator(extraGenerator); - } else { - delete extraGenerator; + generator->SetExternalMakefileProjectGenerator(std::move(extraGenerator)); } return generator; @@ -1184,15 +1247,13 @@ std::string cmake::FindCacheFile(const std::string& binaryDir) return cachePath; } -void cmake::SetGlobalGenerator(cmGlobalGenerator* gg) +void cmake::SetGlobalGenerator(std::unique_ptr<cmGlobalGenerator> gg) { if (!gg) { cmSystemTools::Error("Error SetGlobalGenerator called with null"); return; } - // delete the old generator if (this->GlobalGenerator) { - delete this->GlobalGenerator; // restore the original environment variables CXX and CC // Restore CC std::string env = "CC="; @@ -1208,7 +1269,7 @@ void cmake::SetGlobalGenerator(cmGlobalGenerator* gg) } // set the new - this->GlobalGenerator = gg; + this->GlobalGenerator = std::move(gg); // set the global flag for unix style paths on cmSystemTools as soon as // the generator is set. This allows gmake to be used on windows. @@ -1571,7 +1632,7 @@ int cmake::ActualConfigure() } } - cmMakefile* mf = this->GlobalGenerator->GetMakefiles()[0]; + auto& mf = this->GlobalGenerator->GetMakefiles()[0]; if (mf->IsOn("CTEST_USE_LAUNCHERS") && !this->State->GetGlobalProperty("RULE_LAUNCH_COMPILE")) { cmSystemTools::Error( @@ -1592,13 +1653,12 @@ int cmake::ActualConfigure() std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() { if (!this->EnvironmentGenerator.empty()) { - cmGlobalGenerator* gen = - this->CreateGlobalGenerator(this->EnvironmentGenerator); + auto gen = this->CreateGlobalGenerator(this->EnvironmentGenerator); if (!gen) { cmSystemTools::Error("CMAKE_GENERATOR was set but the specified " "generator doesn't exist. Using CMake default."); } else { - return std::unique_ptr<cmGlobalGenerator>(gen); + return gen; } } #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) @@ -1648,13 +1708,14 @@ std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() } } } - cmGlobalGenerator* gen = this->CreateGlobalGenerator(found); + auto gen = this->CreateGlobalGenerator(found); if (!gen) { - gen = new cmGlobalNMakeMakefileGenerator(this); + gen = cm::make_unique<cmGlobalNMakeMakefileGenerator>(this); } - return std::unique_ptr<cmGlobalGenerator>(gen); + return std::unique_ptr<cmGlobalGenerator>(std::move(gen)); #else - return cm::make_unique<cmGlobalUnixMakefileGenerator3>(this); + return std::unique_ptr<cmGlobalGenerator>( + cm::make_unique<cmGlobalUnixMakefileGenerator3>(this)); #endif } @@ -1665,7 +1726,7 @@ void cmake::CreateDefaultGlobalGenerator() // This print could be unified for all platforms std::cout << "-- Building for: " << gen->GetName() << "\n"; #endif - this->SetGlobalGenerator(gen.release()); + this->SetGlobalGenerator(std::move(gen)); } void cmake::PreLoadCMakeFiles() @@ -1696,6 +1757,11 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) return -1; } + // Log the trace format version to the desired output + if (this->GetTrace()) { + this->PrintTraceFormatVersion(); + } + // If we are given a stamp list file check if it is really out of date. if (!this->CheckStampList.empty() && cmakeCheckStampList(this->CheckStampList)) { @@ -1763,10 +1829,11 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) cmSystemTools::Message("CMake Configure step failed. " "Build files cannot be regenerated correctly. " "Attempting to stop IDE build."); - cmGlobalVisualStudioGenerator* gg = - static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); - gg->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop, - this->VSSolutionFile); + cmGlobalVisualStudioGenerator& gg = + cm::static_reference_cast<cmGlobalVisualStudioGenerator>( + this->GlobalGenerator); + gg.CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop, + this->VSSolutionFile); } #endif return ret; @@ -1916,6 +1983,7 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory()); # endif this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory()); + this->Generators.push_back(cmGlobalNinjaMultiGenerator::NewFactory()); #endif #if defined(CMAKE_USE_WMAKE) this->Generators.push_back(cmGlobalWatcomWMakeGenerator::NewFactory()); @@ -2021,7 +2089,7 @@ void cmake::AppendGlobalGeneratorsDocumentation( const std::string defaultName = defaultGenerator->GetName(); bool foundDefaultOne = false; - for (cmGlobalGeneratorFactory* g : this->Generators) { + for (const auto& g : this->Generators) { cmDocumentationEntry e; g->GetDocumentation(e); if (!foundDefaultOne && cmHasPrefix(e.Name, defaultName)) { @@ -2161,12 +2229,12 @@ int cmake::CheckBuildSystem() } // Create the generator and use it to clear the dependencies. - std::unique_ptr<cmGlobalGenerator> ggd( - this->CreateGlobalGenerator(genName)); + std::unique_ptr<cmGlobalGenerator> ggd = + this->CreateGlobalGenerator(genName); if (ggd) { cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmMakefile mfd(ggd.get(), cm.GetCurrentSnapshot()); - std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mfd)); + auto lgd = ggd->CreateLocalGenerator(&mfd); lgd->ClearDependencies(&mfd, verbose); } } @@ -2287,7 +2355,7 @@ void cmake::MarkCliAsUsed(const std::string& variable) void cmake::GenerateGraphViz(const std::string& fileName) const { #ifndef CMAKE_BOOTSTRAP - cmGraphVizWriter gvWriter(this->GetGlobalGenerator()); + cmGraphVizWriter gvWriter(fileName, this->GetGlobalGenerator()); std::string settingsFile = cmStrCat(this->GetHomeOutputDirectory(), "/CMakeGraphVizOptions.cmake"); @@ -2295,9 +2363,8 @@ void cmake::GenerateGraphViz(const std::string& fileName) const cmStrCat(this->GetHomeDirectory(), "/CMakeGraphVizOptions.cmake"); gvWriter.ReadSettings(settingsFile, fallbackSettingsFile); - gvWriter.WritePerTargetFiles(fileName); - gvWriter.WriteTargetDependersFiles(fileName); - gvWriter.WriteGlobalFile(fileName); + + gvWriter.Write(); #endif } @@ -2376,12 +2443,12 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) } value = args[i]; } - cmGlobalGenerator* gen = this->CreateGlobalGenerator(value); + auto gen = this->CreateGlobalGenerator(value); if (!gen) { cmSystemTools::Error("Could not create named generator " + value); this->PrintGeneratorList(); } else { - this->SetGlobalGenerator(gen); + this->SetGlobalGenerator(std::move(gen)); } } // no option assume it is the output file @@ -2593,26 +2660,37 @@ int cmake::Build(int jobs, const std::string& dir, std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n"; return 1; } - cmGlobalGenerator* gen = this->CreateGlobalGenerator(cachedGenerator); + auto gen = this->CreateGlobalGenerator(cachedGenerator); if (!gen) { std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator << "\"\n"; return 1; } - this->SetGlobalGenerator(gen); + this->SetGlobalGenerator(std::move(gen)); const char* cachedGeneratorInstance = this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE"); if (cachedGeneratorInstance) { - cmMakefile mf(gen, this->GetCurrentSnapshot()); - if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) { + cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); + if (!this->GlobalGenerator->SetGeneratorInstance(cachedGeneratorInstance, + &mf)) { return 1; } } const char* cachedGeneratorPlatform = this->State->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); if (cachedGeneratorPlatform) { - cmMakefile mf(gen, this->GetCurrentSnapshot()); - if (!gen->SetGeneratorPlatform(cachedGeneratorPlatform, &mf)) { + cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); + if (!this->GlobalGenerator->SetGeneratorPlatform(cachedGeneratorPlatform, + &mf)) { + return 1; + } + } + const char* cachedGeneratorToolset = + this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); + if (cachedGeneratorToolset) { + cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); + if (!this->GlobalGenerator->SetGeneratorToolset(cachedGeneratorToolset, + true, &mf)) { return 1; } } @@ -2687,10 +2765,11 @@ int cmake::Build(int jobs, const std::string& dir, } #endif - gen->PrintBuildCommandAdvice(std::cerr, jobs); - return gen->Build(jobs, "", dir, projName, targets, output, "", config, - clean, false, verbose, cmDuration::zero(), - cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions); + this->GlobalGenerator->PrintBuildCommandAdvice(std::cerr, jobs); + return this->GlobalGenerator->Build( + jobs, "", dir, projName, targets, output, "", config, clean, false, + verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH, + nativeOptions); } bool cmake::Open(const std::string& dir, bool dryRun) @@ -2718,8 +2797,8 @@ bool cmake::Open(const std::string& dir, bool dryRun) cmExternalMakefileProjectGenerator::CreateFullGeneratorName( genName, extraGenName ? *extraGenName : ""); - std::unique_ptr<cmGlobalGenerator> gen( - this->CreateGlobalGenerator(fullName)); + std::unique_ptr<cmGlobalGenerator> gen = + this->CreateGlobalGenerator(fullName); if (!gen) { std::cerr << "Error: could create CMAKE_GENERATOR \"" << fullName << "\"\n"; diff --git a/Source/cmake.h b/Source/cmake.h index 687c1056b1..22d3c39b0b 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -5,12 +5,15 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <functional> #include <map> #include <memory> #include <set> +#include <stack> #include <string> #include <unordered_set> +#include <utility> #include <vector> #include "cmGeneratedFileStream.h" @@ -110,6 +113,14 @@ public: LOG_TRACE }; + /** \brief Define supported trace formats **/ + enum TraceFormat + { + TRACE_UNDEFINED, + TRACE_HUMAN, + TRACE_JSON_V1, + }; + struct GeneratorInfo { std::string name; @@ -202,21 +213,25 @@ public: void PreLoadCMakeFiles(); //! Create a GlobalGenerator - cmGlobalGenerator* CreateGlobalGenerator(const std::string& name); + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name); //! Return the global generator assigned to this instance of cmake - cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; } + cmGlobalGenerator* GetGlobalGenerator() + { + return this->GlobalGenerator.get(); + } //! Return the global generator assigned to this instance of cmake, const const cmGlobalGenerator* GetGlobalGenerator() const { - return this->GlobalGenerator; + return this->GlobalGenerator.get(); } //! 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 - void SetGlobalGenerator(cmGlobalGenerator*); + void SetGlobalGenerator(std::unique_ptr<cmGlobalGenerator>); //! Get the names of the current registered generators void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, @@ -380,20 +395,52 @@ public: */ cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache.get(); } + bool WasLogLevelSetViaCLI() const { return this->LogLevelWasSetViaCLI; } + //! Get the selected log level for `message()` commands during the cmake run. LogLevel GetLogLevel() const { return this->MessageLogLevel; } void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; } static LogLevel StringToLogLevel(const std::string& levelStr); + static TraceFormat StringToTraceFormat(const std::string& levelStr); + + bool HasCheckInProgress() const + { + return !this->CheckInProgressMessages.empty(); + } + std::size_t GetCheckInProgressSize() const + { + return this->CheckInProgressMessages.size(); + } + std::string GetTopCheckInProgressMessage() + { + auto message = this->CheckInProgressMessages.top(); + this->CheckInProgressMessages.pop(); + return message; + } + void PushCheckInProgressMessage(std::string message) + { + this->CheckInProgressMessages.emplace(std::move(message)); + } + + //! Should `message` command display context. + bool GetShowLogContext() const { return this->LogContext; } + void SetShowLogContext(bool b) { this->LogContext = b; } //! Do we want debug output during the cmake run. bool GetDebugOutput() { return this->DebugOutput; } void SetDebugOutputOn(bool b) { this->DebugOutput = b; } + //! Do we want debug output from the find commands during the cmake run. + bool GetDebugFindOutput() { return this->DebugFindOutput; } + void SetDebugFindOutputOn(bool b) { this->DebugFindOutput = b; } + //! Do we want trace output during the cmake run. - bool GetTrace() { return this->Trace; } + bool GetTrace() const { return this->Trace; } void SetTrace(bool b) { this->Trace = b; } - bool GetTraceExpand() { return this->TraceExpand; } + bool GetTraceExpand() const { return this->TraceExpand; } void SetTraceExpand(bool b) { this->TraceExpand = b; } + TraceFormat GetTraceFormat() const { return this->TraceFormatVar; } + void SetTraceFormat(TraceFormat f) { this->TraceFormatVar = f; } void AddTraceSource(std::string const& file) { this->TraceOnlyThisSources.push_back(file); @@ -404,6 +451,7 @@ public: } cmGeneratedFileStream& GetTraceFile() { return this->TraceFile; } void SetTraceFile(std::string const& file); + void PrintTraceFormatVersion(); bool GetWarnUninitialized() { return this->WarnUninitialized; } void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; } @@ -503,7 +551,8 @@ protected: void RunCheckForUnusedVariables(); int HandleDeleteCacheVariables(const std::string& var); - using RegisteredGeneratorsVector = std::vector<cmGlobalGeneratorFactory*>; + using RegisteredGeneratorsVector = + std::vector<std::unique_ptr<cmGlobalGeneratorFactory>>; RegisteredGeneratorsVector Generators; using RegisteredExtraGeneratorsVector = std::vector<cmExternalMakefileProjectGeneratorFactory*>; @@ -513,7 +562,6 @@ protected: void AddDefaultGenerators(); void AddDefaultExtraGenerators(); - cmGlobalGenerator* GlobalGenerator = nullptr; std::map<std::string, DiagLevel> DiagLevels; std::string GeneratorInstance; std::string GeneratorPlatform; @@ -549,8 +597,10 @@ private: ProgressCallbackType ProgressCallback; WorkingMode CurrentWorkingMode = NORMAL_MODE; bool DebugOutput = false; + bool DebugFindOutput = false; bool Trace = false; bool TraceExpand = false; + TraceFormat TraceFormatVar = TRACE_HUMAN; cmGeneratedFileStream TraceFile; bool WarnUninitialized = false; bool WarnUnused = false; @@ -587,6 +637,12 @@ private: std::vector<std::string> TraceOnlyThisSources; LogLevel MessageLogLevel = LogLevel::LOG_STATUS; + bool LogLevelWasSetViaCLI = false; + bool LogContext = false; + + std::stack<std::string> CheckInProgressMessages; + + std::unique_ptr<cmGlobalGenerator> GlobalGenerator; void UpdateConversionPathTable(); @@ -714,4 +770,11 @@ private: FOR_EACH_CXX11_FEATURE(F) \ FOR_EACH_CXX14_FEATURE(F) +#define FOR_EACH_CUDA_FEATURE(F) \ + F(cuda_std_03) \ + F(cuda_std_11) \ + F(cuda_std_14) \ + F(cuda_std_17) \ + F(cuda_std_20) + #endif diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 6d3e6ee300..5579ae16e9 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -1,7 +1,16 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmAlgorithms.h" +#include <cassert> +#include <cctype> +#include <climits> +#include <cstring> +#include <iostream> +#include <string> +#include <vector> + +#include <cmext/algorithm> + #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -24,14 +33,6 @@ # include "cmsys/ConsoleBuf.hxx" #endif -#include <cassert> -#include <cctype> -#include <climits> -#include <cstring> -#include <iostream> -#include <string> -#include <vector> - namespace { #ifndef CMAKE_BOOTSTRAP const char* cmDocumentationName[][2] = { @@ -73,12 +74,15 @@ const char* cmDocumentationOptions[][2] = { { "--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>", "Set the verbosity of messages from CMake files. " "--loglevel is also accepted for backward compatibility reasons." }, + { "--log-context", "Prepend log messages with context, if given" }, { "--debug-trycompile", "Do not delete the try_compile build tree. Only " "useful on one try_compile at a time." }, { "--debug-output", "Put cmake in a debug mode." }, + { "--debug-find", "Put cmake find in a debug mode." }, { "--trace", "Put cmake in trace mode." }, { "--trace-expand", "Put cmake in trace mode with variable expansion." }, + { "--trace-format=<human|json-v1>", "Set the output format of the trace." }, { "--trace-source=<file>", "Trace only this CMake file/module. Multiple options allowed." }, { "--trace-redirect=<file>", @@ -99,7 +103,7 @@ int do_command(int ac, char const* const* av) std::vector<std::string> args; args.reserve(ac - 1); args.emplace_back(av[0]); - cmAppend(args, av + 2, av + ac); + cm::append(args, av + 2, av + ac); return cmcmd::ExecuteCMakeCommand(args); } @@ -682,7 +686,6 @@ int main(int ac, char const* const* av) ac = args.argc(); av = args.argv(); - cmSystemTools::EnableMSVCDebugHook(); cmSystemTools::InitializeLibUV(); cmSystemTools::FindCMakeResources(av[0]); if (ac > 1) { diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index d05e3c81ba..67c776e743 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmcmd.h" +#include <cmext/algorithm> + #include "cmAlgorithms.h" #include "cmDuration.h" #include "cmGlobalGenerator.h" @@ -21,16 +23,15 @@ #if !defined(CMAKE_BOOTSTRAP) # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback. +# include "cmFileTime.h" # include "cmServer.h" # include "cmServerConnection.h" + +# include "bindexplib.h" #endif #if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) # include "cmsys/ConsoleBuf.hxx" - -# include "cmFileTime.h" - -# include "bindexplib.h" #endif #if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__) @@ -107,10 +108,12 @@ void CMakeCommandUsage(const char* program) << " sha384sum <file>... - create SHA384 checksum of files\n" << " sha512sum <file>... - create SHA512 checksum of files\n" << " remove [-f] <file>... - remove the file(s), use -f to force " - "it\n" - << " remove_directory <dir>... - remove directories and their contents\n" + "it (deprecated: use rm instead)\n" + << " remove_directory <dir>... - remove directories and their contents (deprecated: use rm instead)\n" << " rename oldname newname - rename a file or directory " "(on one volume)\n" + << " rm [-rRf] <file/dir>... - remove files or directories, use -f to " + "force it, r or R to remove directories and their contents recursively\n" << " server - start cmake in server mode\n" << " sleep <number>... - sleep for given number of seconds\n" << " tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n" @@ -172,6 +175,24 @@ static bool cmTarFilesFrom(std::string const& file, return true; } +static bool cmRemoveDirectory(const std::string& dir, bool recursive = true) +{ + if (cmSystemTools::FileIsSymlink(dir)) { + if (!cmSystemTools::RemoveFile(dir)) { + std::cerr << "Error removing directory symlink \"" << dir << "\".\n"; + return false; + } + } else if (!recursive) { + std::cerr << "Error removing directory \"" << dir + << "\" without recursive option.\n"; + return false; + } else if (!cmSystemTools::RemoveADirectory(dir)) { + std::cerr << "Error removing directory \"" << dir << "\".\n"; + return false; + } + return true; +} + static int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */, const std::vector<std::string>& orig_cmd) @@ -179,7 +200,7 @@ static int HandleIWYU(const std::string& runCmd, // Construct the iwyu command line by taking what was given // and adding all the arguments we give to the compiler. std::vector<std::string> iwyu_cmd = cmExpandedList(runCmd, true); - cmAppend(iwyu_cmd, orig_cmd.begin() + 1, orig_cmd.end()); + cm::append(iwyu_cmd, orig_cmd.begin() + 1, orig_cmd.end()); // Run the iwyu command line. Capture its stderr and hide its stdout. // Ignore its return code because the tool always returns non-zero. std::string stdErr; @@ -210,7 +231,7 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile, std::vector<std::string> tidy_cmd = cmExpandedList(runCmd, true); tidy_cmd.push_back(sourceFile); tidy_cmd.emplace_back("--"); - cmAppend(tidy_cmd, orig_cmd); + cm::append(tidy_cmd, orig_cmd); // Run the tidy command line. Capture its stdout and hide its stderr. std::string stdOut; @@ -561,11 +582,11 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } -#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) - else if (args[1] == "__create_def") { +#if !defined(CMAKE_BOOTSTRAP) + if (args[1] == "__create_def") { if (args.size() < 4) { std::cerr << "__create_def Usage: -E __create_def outfile.def " - "objlistfile [-nm=nm-path]\n"; + "objlistfile [--nm=nm-path]\n"; return 1; } cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary); @@ -592,7 +613,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } } - FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+"); + FILE* fout = cmsys::SystemTools::Fopen(args[2], "w+"); if (!fout) { std::cerr << "could not open output .def file: " << args[2].c_str() << "\n"; @@ -706,14 +727,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) bool return_value = false; for (auto const& arg : cmMakeRange(args).advance(2)) { if (cmSystemTools::FileIsDirectory(arg)) { - if (cmSystemTools::FileIsSymlink(arg)) { - if (!cmSystemTools::RemoveFile(arg)) { - std::cerr << "Error removing directory symlink \"" << arg - << "\".\n"; - return_value = true; - } - } else if (!cmSystemTools::RemoveADirectory(arg)) { - std::cerr << "Error removing directory \"" << arg << "\".\n"; + if (!cmRemoveDirectory(arg)) { return_value = true; } } @@ -739,6 +753,65 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } + // Remove directories or files with rm + if (args[1] == "rm" && args.size() > 2) { + // If an error occurs, we want to continue removing the remaining + // files/directories. + int return_value = 0; + bool force = false; + bool recursive = false; + bool doing_options = true; + bool at_least_one_file = false; + for (auto const& arg : cmMakeRange(args).advance(2)) { + if (doing_options && cmHasLiteralPrefix(arg, "-")) { + if (arg == "--") { + doing_options = false; + } + if (arg.find('f') != std::string::npos) { + force = true; + } + if (arg.find_first_of("rR") != std::string::npos) { + recursive = true; + } + if (arg.find_first_not_of("-frR") != std::string::npos) { + cmSystemTools::Error("Unknown -E rm argument: " + arg); + return 1; + } + } else { + if (arg.empty()) { + continue; + } + at_least_one_file = true; + // Complain if the -f option was not given and + // either file does not exist or + // file could not be removed and still exists + bool file_exists_or_forced_remove = cmSystemTools::FileExists(arg) || + cmSystemTools::FileIsSymlink(arg) || force; + if (cmSystemTools::FileIsDirectory(arg)) { + if (!cmRemoveDirectory(arg, recursive)) { + return_value = 1; + } + } else if ((!file_exists_or_forced_remove) || + (!cmSystemTools::RemoveFile(arg) && + cmSystemTools::FileExists(arg))) { + if (!file_exists_or_forced_remove) { + cmSystemTools::Error( + "File to remove does not exist and force is not set: " + arg); + } else { + cmSystemTools::Error("File can't be removed and still exist: " + + arg); + } + return_value = 1; + } + } + } + if (!at_least_one_file) { + cmSystemTools::Error("Missing file/directory to remove"); + return 1; + } + return return_value; + } + // Touch file if (args[1] == "touch" && args.size() > 2) { for (auto const& arg : cmMakeRange(args).advance(2)) { @@ -1007,13 +1080,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) cm.SetHomeDirectory(homeDir); cm.SetHomeOutputDirectory(homeOutDir); cm.GetCurrentSnapshot().SetDefaultDefinitions(); - if (cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen)) { - cm.SetGlobalGenerator(ggd); + if (auto ggd = cm.CreateGlobalGenerator(gen)) { + cm.SetGlobalGenerator(std::move(ggd)); cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentBinary(startOutDir); snapshot.GetDirectory().SetCurrentSource(startDir); - cmMakefile mf(ggd, snapshot); - std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mf)); + cmMakefile mf(cm.GetGlobalGenerator(), snapshot); + auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf); // Actually scan dependencies. return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2; @@ -1956,7 +2029,7 @@ int cmVSLink::RunMT(std::string const& out, bool notify) if (this->LinkGeneratesManifest) { mtCommand.push_back(this->LinkerManifestFile); } - cmAppend(mtCommand, this->UserManifests); + cm::append(mtCommand, this->UserManifests); mtCommand.push_back(out); if (notify) { // Add an undocumented option that enables a special return diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 0d65902ef0..9b45bb05c0 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -98,9 +98,12 @@ static const char* cmDocumentationOptions[][2] = { "Run a specific number of tests by number." }, { "-U, --union", "Take the Union of -I and -R" }, { "--rerun-failed", "Run only the tests that failed previously" }, - { "--repeat-until-fail <n>", - "Require each test to run <n> " - "times without failing in order to pass" }, + { "--repeat until-fail:<n>, --repeat-until-fail <n>", + "Require each test to run <n> times without failing in order to pass" }, + { "--repeat until-pass:<n>", + "Allow each test to run up to <n> times in order to pass" }, + { "--repeat after-timeout:<n>", + "Allow each test to run up to <n> times if it times out" }, { "--max-width <width>", "Set the max width for a test name to output" }, { "--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1." }, { "--resource-spec-file <file>", "Set the resource spec file to use." }, @@ -161,7 +164,6 @@ int main(int argc, char const* const* argv) argv = encoding_args.argv(); cmSystemTools::DoNotInheritStdPipes(); - cmSystemTools::EnableMSVCDebugHook(); cmSystemTools::InitializeLibUV(); cmSystemTools::FindCMakeResources(argv[0]); diff --git a/Source/kwsys/CTestCustom.cmake.in b/Source/kwsys/CTestCustom.cmake.in index 760221b124..c07f0f30f8 100644 --- a/Source/kwsys/CTestCustom.cmake.in +++ b/Source/kwsys/CTestCustom.cmake.in @@ -12,3 +12,7 @@ list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE kwsys.testProcess-10 ) + +list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION + "LICENSE WARNING" + ) diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in index b06752115c..75a2d4d0f9 100644 --- a/Source/kwsys/Encoding.hxx.in +++ b/Source/kwsys/Encoding.hxx.in @@ -68,6 +68,8 @@ public: * absolute paths with Windows-style backslashes. **/ static std::wstring ToWindowsExtendedPath(std::string const&); + static std::wstring ToWindowsExtendedPath(const char* source); + static std::wstring ToWindowsExtendedPath(std::wstring const& wsource); # endif #endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx index 4593c9251c..5cad934ec3 100644 --- a/Source/kwsys/EncodingCXX.cxx +++ b/Source/kwsys/EncodingCXX.cxx @@ -221,8 +221,18 @@ std::string Encoding::ToNarrow(const wchar_t* wcstr) // Convert local paths to UNC style paths std::wstring Encoding::ToWindowsExtendedPath(std::string const& source) { - std::wstring wsource = Encoding::ToWide(source); + return ToWindowsExtendedPath(ToWide(source)); +} +// Convert local paths to UNC style paths +std::wstring Encoding::ToWindowsExtendedPath(const char* source) +{ + return ToWindowsExtendedPath(ToWide(source)); +} + +// Convert local paths to UNC style paths +std::wstring Encoding::ToWindowsExtendedPath(std::wstring const& wsource) +{ // Resolve any relative paths DWORD wfull_len; @@ -269,7 +279,7 @@ std::wstring Encoding::ToWindowsExtendedPath(std::string const& source) // If this case has been reached, then the path is invalid. Leave it // unchanged - return Encoding::ToWide(source); + return wsource; } # endif diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in index d79bbdf16b..b424488920 100644 --- a/Source/kwsys/FStream.hxx.in +++ b/Source/kwsys/FStream.hxx.in @@ -87,7 +87,7 @@ public: bool _open(char const* file_name, std::ios_base::openmode mode) { - if (is_open() || file_) { + if (_is_open() || file_) { return false; } # if defined(_MSC_VER) @@ -108,7 +108,7 @@ public: return success; } - bool is_open() + bool _is_open() { if (!buf_) { return false; @@ -116,7 +116,7 @@ public: return buf_->is_open(); } - bool is_open() const + bool _is_open() const { if (!buf_) { return false; @@ -198,9 +198,11 @@ public: this->_set_state(this->_open(file_name, mode), this, this); } + bool is_open() { return this->_is_open(); } + void close() { this->_set_state(this->_close(), this, this); } - using basic_efilebuf<CharType, Traits>::is_open; + using basic_efilebuf<CharType, Traits>::_is_open; internal_buffer_type* rdbuf() const { return this->buf_; } @@ -212,7 +214,7 @@ class basic_ofstream : public std::basic_ostream<CharType, Traits> , public basic_efilebuf<CharType, Traits> { - using basic_efilebuf<CharType, Traits>::is_open; + using basic_efilebuf<CharType, Traits>::_is_open; public: typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type @@ -242,6 +244,8 @@ public: void close() { this->_set_state(this->_close(), this, this); } + bool is_open() { return this->_is_open(); } + internal_buffer_type* rdbuf() const { return this->buf_; } ~basic_ofstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); } diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in index df7eb45589..d11db88280 100644 --- a/Source/kwsys/RegularExpression.hxx.in +++ b/Source/kwsys/RegularExpression.hxx.in @@ -66,16 +66,27 @@ private: const char* searchstring; }; +#ifdef _MSC_VER +# pragma warning(push) +# if _MSC_VER < 1900 +# pragma warning(disable : 4351) /* new behavior */ +# endif +#endif + /** * \brief Creates an invalid match object */ inline RegularExpressionMatch::RegularExpressionMatch() + : startp{} + , endp{} + , searchstring{} { - startp[0] = nullptr; - endp[0] = nullptr; - searchstring = nullptr; } +#ifdef _MSC_VER +# pragma warning(pop) +#endif + /** * \brief Returns true if the match pointers are valid */ diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index ce4d6ef950..39873e630d 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -2326,14 +2326,8 @@ bool SystemTools::TextFilesDiffer(const std::string& path1, static bool CopyFileContentBlockwise(const std::string& source, const std::string& destination) { -// Open files -#if defined(_WIN32) - kwsys::ifstream fin( - Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(), - std::ios::in | std::ios::binary); -#else + // Open files kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); -#endif if (!fin) { return false; } @@ -2344,14 +2338,8 @@ static bool CopyFileContentBlockwise(const std::string& source, // that do not allow file removal can be modified. SystemTools::RemoveFile(destination); -#if defined(_WIN32) - kwsys::ofstream fout( - Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(destination)).c_str(), - std::ios::out | std::ios::trunc | std::ios::binary); -#else kwsys::ofstream fout(destination.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); -#endif if (!fout) { return false; } @@ -4678,8 +4666,12 @@ void SystemTools::ClassFinalize() # include <stdlib.h> namespace KWSYS_NAMESPACE { -static int SystemToolsDebugReport(int, char* message, int*) +static int SystemToolsDebugReport(int, char* message, int* ret) { + if (ret) { + // Pretend user clicked on Retry button in popup. + *ret = 1; + } fprintf(stderr, "%s", message); fflush(stderr); return 1; // no further reporting required diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index 4dd246148c..c9515ee7d0 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -172,6 +172,14 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, } } + /* GNU make 4.1+ may tell us that its output is destined for a TTY. */ + { + const char* termout = getenv("MAKE_TERMOUT"); + if (termout && *termout != '\0') { + return 1; + } + } + /* If running inside emacs the terminal is not VT100. Some emacs seem to claim the TERM is xterm even though they do not support VT100 escapes. */ |