diff options
Diffstat (limited to 'Source')
331 files changed, 13934 insertions, 5975 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index b1f7b29..c57f713 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -134,6 +134,9 @@ set(SRCS LexerParser/cmFortranParser.cxx LexerParser/cmFortranParserTokens.h LexerParser/cmFortranParser.y + LexerParser/cmGccDepfileLexer.cxx + LexerParser/cmGccDepfileLexer.h + LexerParser/cmGccDepfileLexer.in.l LexerParser/cmListFileLexer.c LexerParser/cmListFileLexer.in.l @@ -270,6 +273,10 @@ set(SRCS cmFortranParserImpl.cxx cmFSPermissions.cxx cmFSPermissions.h + cmGccDepfileLexerHelper.cxx + cmGccDepfileLexerHelper.h + cmGccDepfileReader.cxx + cmGccDepfileReader.h cmGeneratedFileStream.cxx cmGeneratorExpressionContext.cxx cmGeneratorExpressionContext.h @@ -289,6 +296,8 @@ set(SRCS cmGeneratorExpression.h cmGeneratorTarget.cxx cmGeneratorTarget.h + cmLinkItemGraphVisitor.cxx + cmLinkItemGraphVisitor.h cmGetPipes.cxx cmGetPipes.h cmGlobalCommonGenerator.cxx @@ -691,6 +700,8 @@ set(SRCS cmDuration.h cmDuration.cxx + + bindexplib.cxx ) SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS @@ -713,7 +724,6 @@ if (WIN32) set(SRCS ${SRCS} cmCallVisualStudioMacro.cxx cmCallVisualStudioMacro.h - bindexplib.cxx ) if(NOT UNIX) @@ -1193,6 +1203,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 79b1dac..1b0765b 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 3) +set(CMake_VERSION_PATCH 20200205) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index ea71007..fe7abf4 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -138,11 +138,16 @@ int cmCPackDragNDropGenerator::InitializeInternal() } for (auto const& language : languages) { std::string license = slaDirectory + "/" + language + ".license.txt"; - if (!singleLicense && !cmSystemTools::FileExists(license)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Missing license file " << language << ".license.txt" - << std::endl); - return 0; + std::string license_rtf = slaDirectory + "/" + language + ".license.rtf"; + if (!singleLicense) { + if (!cmSystemTools::FileExists(license) && + !cmSystemTools::FileExists(license_rtf)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Missing license file " + << language << ".license.txt" + << " / " << language << ".license.rtf" << std::endl); + return 0; + } } std::string menu = slaDirectory + "/" + language + ".menu.txt"; if (!cmSystemTools::FileExists(menu)) { @@ -775,6 +780,11 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( } } + std::string componentFileName = + "CPACK_DMG_" + cmSystemTools::UpperCase(componentName) + "_FILE_NAME"; + if (this->IsSet(componentFileName)) { + return this->GetOption(componentFileName); + } return GetComponentPackageFileName(package_file_name, componentName, false); } @@ -788,13 +798,29 @@ bool cmCPackDragNDropGenerator::WriteLicense( licenseLanguage = "English"; } + // License file + std::string license_format = "TEXT"; + std::string actual_license; + if (!licenseFile.empty()) { + if (cmHasLiteralSuffix(licenseFile, ".rtf")) { + license_format = "RTF "; + } + actual_license = licenseFile; + } else { + std::string license_wo_ext = + slaDirectory + "/" + licenseLanguage + ".license"; + if (cmSystemTools::FileExists(license_wo_ext + ".txt")) { + actual_license = license_wo_ext + ".txt"; + } else { + license_format = "RTF "; + actual_license = license_wo_ext + ".rtf"; + } + } + // License header - outputStream << "data 'TEXT' (" << licenseNumber << ", \"" << licenseLanguage - << "\") {\n"; + outputStream << "data '" << license_format << "' (" << licenseNumber + << ", \"" << licenseLanguage << "\") {\n"; // License body - std::string actual_license = !licenseFile.empty() - ? licenseFile - : (slaDirectory + "/" + licenseLanguage + ".license.txt"); cmsys::ifstream license_ifs; license_ifs.open(actual_license.c_str()); if (license_ifs.is_open()) { @@ -873,8 +899,9 @@ bool cmCPackDragNDropGenerator::BreakLongLine(const std::string& line, std::string* error) { const size_t max_line_length = 512; - for (size_t i = 0; i < line.size(); i += max_line_length) { - size_t line_length = max_line_length; + size_t line_length = max_line_length; + for (size_t i = 0; i < line.size(); i += line_length) { + line_length = max_line_length; if (i + line_length > line.size()) { line_length = line.size() - i; } else { diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 6698f3c..712eb77 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -621,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 9bf72df..363f536 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/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index 951c65f..5de4a6f 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -178,6 +178,9 @@ int cmCPackOSXX11Generator::PackageFiles() int cmCPackOSXX11Generator::InitializeInternal() { + cmCPackLogger(cmCPackLog::LOG_WARNING, + "The OSXX11 generator is deprecated " + "and will be removed in a future version.\n"); cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackOSXX11Generator::Initialize()" << std::endl); std::vector<std::string> path; diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index dae5ec9..ac3d64d 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 69286ff..be730ab 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 c5ba726..f51ea42 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"), @@ -321,6 +321,9 @@ int cmCPackPackageMakerGenerator::PackageFiles() int cmCPackPackageMakerGenerator::InitializeInternal() { + cmCPackLogger(cmCPackLog::LOG_WARNING, + "The PackageMaker generator is deprecated " + "and will be removed in a future version.\n"); this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr"); // Starting with Xcode 4.3, PackageMaker is a separate app, and you diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index dae268c..a3e55de 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 5895652..dc31623 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 8640c46..c87fb83b 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 2ad661c..5e29386 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 18df214..d1b7701 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 da00a43..0f82817 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 9cb5449..03a3fd3 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 f2f42b4..3854710 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 4cd783f..2c8f119 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 ccac832..3ad4749 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 3265498..5f4581e 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 a5ec1ae..c1ecaf1 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 eda65f7..52667f8 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 02d396e..37679b9 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 1db4bfd..4837401 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 e2063e1..1375be4 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/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 3091050..cc5de43 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 f781c7a..7eeaebd 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 34395c9..44dfab2 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 60facbd..7803e37 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 46b00b1..acb75b2 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 2ac5af6..a8f201a 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 9784214..0f9b695 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 4019694..2345afb 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 c8bbb0b..78c68be 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -410,10 +410,15 @@ int cmCTestTestHandler::ProcessHandler() auto clock_finish = std::chrono::steady_clock::now(); + bool noTestsFoundError = false; if (passed.size() + failed.size() == 0) { - if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) { + if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels() && + this->CTest->GetNoTestsMode() != cmCTest::NoTests::Ignore) { cmCTestLog(this->CTest, ERROR_MESSAGE, "No tests were found!!!" << std::endl); + if (this->CTest->GetNoTestsMode() == cmCTest::NoTests::Error) { + noTestsFoundError = true; + } } } else { if (this->HandlerVerbose && !passed.empty() && @@ -459,6 +464,12 @@ int cmCTestTestHandler::ProcessHandler() this->LogFile = nullptr; return -1; } + + if (noTestsFoundError) { + this->LogFile = nullptr; + return -1; + } + this->LogFile = nullptr; return 0; } @@ -471,6 +482,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"))); } @@ -1235,6 +1270,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 eab75d0..55237f9 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 d0e3848..eaef1ca 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 87f7147..cdf899c 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); @@ -277,9 +278,6 @@ void cmProcess::OnTimeoutCB(uv_timer_t* timer) void cmProcess::OnTimeout() { - if (this->ProcessState != cmProcess::State::Executing) { - return; - } this->ProcessState = cmProcess::State::Expired; bool const was_still_reading = !this->ReadHandleClosed; if (!this->ReadHandleClosed) { diff --git a/Source/Checks/Curses.cmake b/Source/Checks/Curses.cmake index 2942b66..d35dd2a 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 6b8d10b..2263be3 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 38606b9..e5656bf 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 4da2fd7..dba3eaf 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 29863b1..abbe22c 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 fb68ed7..3b00dfb 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 0000000..024c397 --- /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 7009717..c24ee76 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 9e9dfbd..01fce85 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 97b0811..c4dbed8 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 0000000..641d48c --- /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 0000000..78ca52c --- /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 e2d8d06..806e663 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 42f9c71..88efe62 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 6b71e8a..2c92835 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 b8769b7..b7c204d 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 eb773ad..a15241f 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 bb3808e..8ed42de 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 6296af2..c629478 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/.gitattributes b/Source/LexerParser/.gitattributes index bf70249..63d9afb 100644 --- a/Source/LexerParser/.gitattributes +++ b/Source/LexerParser/.gitattributes @@ -16,4 +16,6 @@ /cmFortranLexer.h generated /cmFortranParser.cxx generated /cmFortranParserTokens.h generated +/cmGccDepfileLexer.cxx generated +/cmGccDepfileLexer.h generated /cmListFileLexer.c generated diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx index ae7fb42..34dc8ec 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 56c9794..033b899 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 6c1fb2c..b15082d 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 6bbc084..e0dfa01 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 8416e72..562b35b 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 5ffd7c5..e30a832 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 2ca7927..2494aad 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 87f3e0a..1b54dd9 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 0da4c1c..f66a15c 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/LexerParser/cmGccDepfileLexer.cxx b/Source/LexerParser/cmGccDepfileLexer.cxx new file mode 100644 index 0000000..a98969d --- /dev/null +++ b/Source/LexerParser/cmGccDepfileLexer.cxx @@ -0,0 +1,2210 @@ +#include "cmStandardLexer.h" + +#define FLEXINT_H 1 +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define cmGccDepfile_yy_create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer cmGccDepfile_yy_create_buffer +#endif + +#ifdef yy_delete_buffer +#define cmGccDepfile_yy_delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer cmGccDepfile_yy_delete_buffer +#endif + +#ifdef yy_scan_buffer +#define cmGccDepfile_yy_scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer cmGccDepfile_yy_scan_buffer +#endif + +#ifdef yy_scan_string +#define cmGccDepfile_yy_scan_string_ALREADY_DEFINED +#else +#define yy_scan_string cmGccDepfile_yy_scan_string +#endif + +#ifdef yy_scan_bytes +#define cmGccDepfile_yy_scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes cmGccDepfile_yy_scan_bytes +#endif + +#ifdef yy_init_buffer +#define cmGccDepfile_yy_init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer cmGccDepfile_yy_init_buffer +#endif + +#ifdef yy_flush_buffer +#define cmGccDepfile_yy_flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer cmGccDepfile_yy_flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define cmGccDepfile_yy_load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state cmGccDepfile_yy_load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define cmGccDepfile_yy_switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer cmGccDepfile_yy_switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define cmGccDepfile_yypush_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state cmGccDepfile_yypush_buffer_state +#endif + +#ifdef yypop_buffer_state +#define cmGccDepfile_yypop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state cmGccDepfile_yypop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define cmGccDepfile_yyensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack cmGccDepfile_yyensure_buffer_stack +#endif + +#ifdef yylex +#define cmGccDepfile_yylex_ALREADY_DEFINED +#else +#define yylex cmGccDepfile_yylex +#endif + +#ifdef yyrestart +#define cmGccDepfile_yyrestart_ALREADY_DEFINED +#else +#define yyrestart cmGccDepfile_yyrestart +#endif + +#ifdef yylex_init +#define cmGccDepfile_yylex_init_ALREADY_DEFINED +#else +#define yylex_init cmGccDepfile_yylex_init +#endif + +#ifdef yylex_init_extra +#define cmGccDepfile_yylex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra cmGccDepfile_yylex_init_extra +#endif + +#ifdef yylex_destroy +#define cmGccDepfile_yylex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy cmGccDepfile_yylex_destroy +#endif + +#ifdef yyget_debug +#define cmGccDepfile_yyget_debug_ALREADY_DEFINED +#else +#define yyget_debug cmGccDepfile_yyget_debug +#endif + +#ifdef yyset_debug +#define cmGccDepfile_yyset_debug_ALREADY_DEFINED +#else +#define yyset_debug cmGccDepfile_yyset_debug +#endif + +#ifdef yyget_extra +#define cmGccDepfile_yyget_extra_ALREADY_DEFINED +#else +#define yyget_extra cmGccDepfile_yyget_extra +#endif + +#ifdef yyset_extra +#define cmGccDepfile_yyset_extra_ALREADY_DEFINED +#else +#define yyset_extra cmGccDepfile_yyset_extra +#endif + +#ifdef yyget_in +#define cmGccDepfile_yyget_in_ALREADY_DEFINED +#else +#define yyget_in cmGccDepfile_yyget_in +#endif + +#ifdef yyset_in +#define cmGccDepfile_yyset_in_ALREADY_DEFINED +#else +#define yyset_in cmGccDepfile_yyset_in +#endif + +#ifdef yyget_out +#define cmGccDepfile_yyget_out_ALREADY_DEFINED +#else +#define yyget_out cmGccDepfile_yyget_out +#endif + +#ifdef yyset_out +#define cmGccDepfile_yyset_out_ALREADY_DEFINED +#else +#define yyset_out cmGccDepfile_yyset_out +#endif + +#ifdef yyget_leng +#define cmGccDepfile_yyget_leng_ALREADY_DEFINED +#else +#define yyget_leng cmGccDepfile_yyget_leng +#endif + +#ifdef yyget_text +#define cmGccDepfile_yyget_text_ALREADY_DEFINED +#else +#define yyget_text cmGccDepfile_yyget_text +#endif + +#ifdef yyget_lineno +#define cmGccDepfile_yyget_lineno_ALREADY_DEFINED +#else +#define yyget_lineno cmGccDepfile_yyget_lineno +#endif + +#ifdef yyset_lineno +#define cmGccDepfile_yyset_lineno_ALREADY_DEFINED +#else +#define yyset_lineno cmGccDepfile_yyset_lineno +#endif + +#ifdef yyget_column +#define cmGccDepfile_yyget_column_ALREADY_DEFINED +#else +#define yyget_column cmGccDepfile_yyget_column +#endif + +#ifdef yyset_column +#define cmGccDepfile_yyset_column_ALREADY_DEFINED +#else +#define yyset_column cmGccDepfile_yyset_column +#endif + +#ifdef yywrap +#define cmGccDepfile_yywrap_ALREADY_DEFINED +#else +#define yywrap cmGccDepfile_yywrap +#endif + +#ifdef yyalloc +#define cmGccDepfile_yyalloc_ALREADY_DEFINED +#else +#define yyalloc cmGccDepfile_yyalloc +#endif + +#ifdef yyrealloc +#define cmGccDepfile_yyrealloc_ALREADY_DEFINED +#else +#define yyrealloc cmGccDepfile_yyrealloc +#endif + +#ifdef yyfree +#define cmGccDepfile_yyfree_ALREADY_DEFINED +#else +#define yyfree cmGccDepfile_yyfree +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin , yyscanner ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +static void yyensure_buffer_stack ( yyscan_t yyscanner ); +static void yy_load_buffer_state ( yyscan_t yyscanner ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define cmGccDepfile_yywrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); +static int yy_get_next_buffer ( yyscan_t yyscanner ); +static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; +#define YY_NUM_RULES 11 +#define YY_END_OF_BUFFER 12 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static const flex_int16_t yy_accept[26] = + { 0, + 0, 0, 12, 10, 8, 6, 10, 9, 10, 10, + 10, 8, 0, 6, 9, 1, 7, 5, 0, 3, + 2, 0, 4, 0, 0 + } ; + +static const YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 5, 6, 1, 7, 8, 6, 1, 1, 6, + 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 9, 1, 1, + 6, 1, 1, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 10, 6, 1, 6, 1, 6, 6, 6, 6, + + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 1, 6, 6, 1, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6 + } ; + +static const YY_CHAR yy_meta[11] = + { 0, + 1, 2, 1, 1, 2, 1, 1, 1, 1, 3 + } ; + +static const flex_int16_t yy_base[28] = + { 0, + 0, 0, 29, 35, 18, 35, 22, 18, 15, 0, + 8, 12, 16, 35, 11, 35, 0, 35, 13, 35, + 35, 16, 35, 22, 35, 31, 12 + } ; + +static const flex_int16_t yy_def[28] = + { 0, + 25, 1, 25, 25, 26, 25, 25, 25, 25, 27, + 25, 26, 25, 25, 25, 25, 27, 25, 25, 25, + 25, 25, 25, 25, 0, 25, 25 + } ; + +static const flex_int16_t yy_nxt[46] = + { 0, + 4, 5, 6, 7, 5, 8, 4, 9, 10, 11, + 18, 19, 20, 17, 21, 18, 15, 22, 18, 19, + 23, 13, 16, 15, 14, 24, 20, 13, 25, 25, + 25, 22, 12, 12, 3, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25 + } ; + +static const flex_int16_t yy_chk[46] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 11, 11, 27, 11, 19, 15, 11, 13, 13, + 22, 12, 9, 8, 7, 22, 24, 5, 3, 0, + 0, 24, 26, 26, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +/* IWYU pragma: no_forward_declare yyguts_t */ + +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + +#include <cmGccDepfileLexerHelper.h> +#include <string> + +#define INITIAL 0 + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + }; /* end struct yyguts_t */ + +static int yy_init_globals ( yyscan_t yyscanner ); + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); + + int yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +#ifndef YY_NO_UNPUT + + static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner); + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput ( yyscan_t yyscanner ); +#else +static int input ( yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (yyscan_t yyscanner); + +#define YY_DECL int yylex (yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); + } + + yy_load_buffer_state( yyscanner ); + } + + { + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 26 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 35 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +{ + // Unescape the dollar sign. + yyextra->addToCurrentPath("$"); + } + YY_BREAK +case 2: +YY_RULE_SETUP +{ + // Unescape the hash. + yyextra->addToCurrentPath("#"); + } + YY_BREAK +case 3: +YY_RULE_SETUP +{ + // 2N+1 backslashes plus space -> N backslashes plus space. + size_t c = (strlen(yytext) - 1) / 2; + std::string s(c, '\\'); + s.push_back(' '); + yyextra->addToCurrentPath(s.c_str()); + } + YY_BREAK +case 4: +YY_RULE_SETUP +{ + // 2N backslashes plus space -> 2N backslashes, end of filename. + yytext[strlen(yytext) - 1] = 0; + yyextra->addToCurrentPath(yytext); + yyextra->newDependency(); + } + YY_BREAK +case 5: +/* rule 5 can match eol */ +YY_RULE_SETUP +{ + // A line continuation ends the current file name. + yyextra->newDependency(); + } + YY_BREAK +case 6: +/* rule 6 can match eol */ +YY_RULE_SETUP +{ + // A newline ends the current file name and the current rule. + yyextra->newEntry(); + } + YY_BREAK +case 7: +YY_RULE_SETUP +{ + // A colon followed by space ends the rules and starts a new dependency. + yyextra->newDependency(); + } + YY_BREAK +case 8: +YY_RULE_SETUP +{ + // Rules and dependencies are separated by blocks of whitespace. + yyextra->newRuleOrDependency(); + } + YY_BREAK +case 9: +YY_RULE_SETUP +{ + // Got a span of plain text. + yyextra->addToCurrentPath(yytext); + } + YY_BREAK +case 10: +YY_RULE_SETUP +{ + // Got an otherwise unmatched character. + yyextra->addToCurrentPath(yytext); + } + YY_BREAK +case 11: +YY_RULE_SETUP +ECHO; + YY_BREAK +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( yywrap( yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin , yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + yy_state_type yy_current_state; + char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 26 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + char *yy_cp = yyg->yy_c_buf_p; + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 26 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 25); + + (void)yyg; + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + + static void yyunput (int c, char * yy_bp , yyscan_t yyscanner) +{ + char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_cp = yyg->yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yyg->yy_hold_char; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + int number_to_move = yyg->yy_n_chars + 2; + char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + yyg->yytext_ptr = yy_bp; + yyg->yy_hold_char = *yy_cp; + yyg->yy_c_buf_p = yy_cp; +} + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin , yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( yyscanner ) ) + return 0; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); + } + + yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); + yy_load_buffer_state( yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file , yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * @param yyscanner The scanner object. + */ + void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree( (void *) b->yy_ch_buf , yyscanner ); + + yyfree( (void *) b , yyscanner ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_flush_buffer( b , yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(yyscanner); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (yyscan_t yyscanner) +{ + yy_size_t num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b , yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) +{ + + return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n , yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n , yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param _line_number line number + * @param yyscanner The scanner object. + */ +void yyset_lineno (int _line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); + + yylineno = _line_number; +} + +/** Set the current column. + * @param _column_no column number + * @param yyscanner The scanner object. + */ +void yyset_column (int _column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + YY_FATAL_ERROR( "yyset_column called with no buffer" ); + + yycolumn = _column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * @param yyscanner The scanner object. + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = _out_str ; +} + +int yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void yyset_debug (int _bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = _bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +/* User-visible API */ + +/* yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ +int yylex_init(yyscan_t* ptr_yy_globals) +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* yylex_init_extra has the same functionality as yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to yyalloc in + * the yyextra field. + */ +int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) +{ + struct yyguts_t dummy_yyguts; + + yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = NULL; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = NULL; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + yyfree(yyg->yy_buffer_stack , yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + yyfree( yyg->yy_start_stack , yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s , yyscan_t yyscanner) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + return malloc(size); +} + +void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree (void * ptr , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/LexerParser/cmGccDepfileLexer.h b/Source/LexerParser/cmGccDepfileLexer.h new file mode 100644 index 0000000..7d34060 --- /dev/null +++ b/Source/LexerParser/cmGccDepfileLexer.h @@ -0,0 +1,687 @@ +#ifndef cmGccDepfile_yyHEADER_H +#define cmGccDepfile_yyHEADER_H 1 +#define cmGccDepfile_yyIN_HEADER 1 + +#define FLEXINT_H 1 +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define cmGccDepfile_yy_create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer cmGccDepfile_yy_create_buffer +#endif + +#ifdef yy_delete_buffer +#define cmGccDepfile_yy_delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer cmGccDepfile_yy_delete_buffer +#endif + +#ifdef yy_scan_buffer +#define cmGccDepfile_yy_scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer cmGccDepfile_yy_scan_buffer +#endif + +#ifdef yy_scan_string +#define cmGccDepfile_yy_scan_string_ALREADY_DEFINED +#else +#define yy_scan_string cmGccDepfile_yy_scan_string +#endif + +#ifdef yy_scan_bytes +#define cmGccDepfile_yy_scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes cmGccDepfile_yy_scan_bytes +#endif + +#ifdef yy_init_buffer +#define cmGccDepfile_yy_init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer cmGccDepfile_yy_init_buffer +#endif + +#ifdef yy_flush_buffer +#define cmGccDepfile_yy_flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer cmGccDepfile_yy_flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define cmGccDepfile_yy_load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state cmGccDepfile_yy_load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define cmGccDepfile_yy_switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer cmGccDepfile_yy_switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define cmGccDepfile_yypush_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state cmGccDepfile_yypush_buffer_state +#endif + +#ifdef yypop_buffer_state +#define cmGccDepfile_yypop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state cmGccDepfile_yypop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define cmGccDepfile_yyensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack cmGccDepfile_yyensure_buffer_stack +#endif + +#ifdef yylex +#define cmGccDepfile_yylex_ALREADY_DEFINED +#else +#define yylex cmGccDepfile_yylex +#endif + +#ifdef yyrestart +#define cmGccDepfile_yyrestart_ALREADY_DEFINED +#else +#define yyrestart cmGccDepfile_yyrestart +#endif + +#ifdef yylex_init +#define cmGccDepfile_yylex_init_ALREADY_DEFINED +#else +#define yylex_init cmGccDepfile_yylex_init +#endif + +#ifdef yylex_init_extra +#define cmGccDepfile_yylex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra cmGccDepfile_yylex_init_extra +#endif + +#ifdef yylex_destroy +#define cmGccDepfile_yylex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy cmGccDepfile_yylex_destroy +#endif + +#ifdef yyget_debug +#define cmGccDepfile_yyget_debug_ALREADY_DEFINED +#else +#define yyget_debug cmGccDepfile_yyget_debug +#endif + +#ifdef yyset_debug +#define cmGccDepfile_yyset_debug_ALREADY_DEFINED +#else +#define yyset_debug cmGccDepfile_yyset_debug +#endif + +#ifdef yyget_extra +#define cmGccDepfile_yyget_extra_ALREADY_DEFINED +#else +#define yyget_extra cmGccDepfile_yyget_extra +#endif + +#ifdef yyset_extra +#define cmGccDepfile_yyset_extra_ALREADY_DEFINED +#else +#define yyset_extra cmGccDepfile_yyset_extra +#endif + +#ifdef yyget_in +#define cmGccDepfile_yyget_in_ALREADY_DEFINED +#else +#define yyget_in cmGccDepfile_yyget_in +#endif + +#ifdef yyset_in +#define cmGccDepfile_yyset_in_ALREADY_DEFINED +#else +#define yyset_in cmGccDepfile_yyset_in +#endif + +#ifdef yyget_out +#define cmGccDepfile_yyget_out_ALREADY_DEFINED +#else +#define yyget_out cmGccDepfile_yyget_out +#endif + +#ifdef yyset_out +#define cmGccDepfile_yyset_out_ALREADY_DEFINED +#else +#define yyset_out cmGccDepfile_yyset_out +#endif + +#ifdef yyget_leng +#define cmGccDepfile_yyget_leng_ALREADY_DEFINED +#else +#define yyget_leng cmGccDepfile_yyget_leng +#endif + +#ifdef yyget_text +#define cmGccDepfile_yyget_text_ALREADY_DEFINED +#else +#define yyget_text cmGccDepfile_yyget_text +#endif + +#ifdef yyget_lineno +#define cmGccDepfile_yyget_lineno_ALREADY_DEFINED +#else +#define yyget_lineno cmGccDepfile_yyget_lineno +#endif + +#ifdef yyset_lineno +#define cmGccDepfile_yyset_lineno_ALREADY_DEFINED +#else +#define yyset_lineno cmGccDepfile_yyset_lineno +#endif + +#ifdef yyget_column +#define cmGccDepfile_yyget_column_ALREADY_DEFINED +#else +#define yyget_column cmGccDepfile_yyget_column +#endif + +#ifdef yyset_column +#define cmGccDepfile_yyset_column_ALREADY_DEFINED +#else +#define yyset_column cmGccDepfile_yyset_column +#endif + +#ifdef yywrap +#define cmGccDepfile_yywrap_ALREADY_DEFINED +#else +#define yywrap cmGccDepfile_yywrap +#endif + +#ifdef yyalloc +#define cmGccDepfile_yyalloc_ALREADY_DEFINED +#else +#define yyalloc cmGccDepfile_yyalloc +#endif + +#ifdef yyrealloc +#define cmGccDepfile_yyrealloc_ALREADY_DEFINED +#else +#define yyrealloc cmGccDepfile_yyrealloc +#endif + +#ifdef yyfree +#define cmGccDepfile_yyfree_ALREADY_DEFINED +#else +#define yyfree cmGccDepfile_yyfree +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +/* Begin user sect3 */ + +#define cmGccDepfile_yywrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP + +#define yytext_ptr yytext_r + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 + +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); + + int yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (yyscan_t yyscanner); + +#define YY_DECL int yylex (yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#ifndef cmGccDepfile_yy_create_buffer_ALREADY_DEFINED +#undef yy_create_buffer +#endif +#ifndef cmGccDepfile_yy_delete_buffer_ALREADY_DEFINED +#undef yy_delete_buffer +#endif +#ifndef cmGccDepfile_yy_scan_buffer_ALREADY_DEFINED +#undef yy_scan_buffer +#endif +#ifndef cmGccDepfile_yy_scan_string_ALREADY_DEFINED +#undef yy_scan_string +#endif +#ifndef cmGccDepfile_yy_scan_bytes_ALREADY_DEFINED +#undef yy_scan_bytes +#endif +#ifndef cmGccDepfile_yy_init_buffer_ALREADY_DEFINED +#undef yy_init_buffer +#endif +#ifndef cmGccDepfile_yy_flush_buffer_ALREADY_DEFINED +#undef yy_flush_buffer +#endif +#ifndef cmGccDepfile_yy_load_buffer_state_ALREADY_DEFINED +#undef yy_load_buffer_state +#endif +#ifndef cmGccDepfile_yy_switch_to_buffer_ALREADY_DEFINED +#undef yy_switch_to_buffer +#endif +#ifndef cmGccDepfile_yypush_buffer_state_ALREADY_DEFINED +#undef yypush_buffer_state +#endif +#ifndef cmGccDepfile_yypop_buffer_state_ALREADY_DEFINED +#undef yypop_buffer_state +#endif +#ifndef cmGccDepfile_yyensure_buffer_stack_ALREADY_DEFINED +#undef yyensure_buffer_stack +#endif +#ifndef cmGccDepfile_yylex_ALREADY_DEFINED +#undef yylex +#endif +#ifndef cmGccDepfile_yyrestart_ALREADY_DEFINED +#undef yyrestart +#endif +#ifndef cmGccDepfile_yylex_init_ALREADY_DEFINED +#undef yylex_init +#endif +#ifndef cmGccDepfile_yylex_init_extra_ALREADY_DEFINED +#undef yylex_init_extra +#endif +#ifndef cmGccDepfile_yylex_destroy_ALREADY_DEFINED +#undef yylex_destroy +#endif +#ifndef cmGccDepfile_yyget_debug_ALREADY_DEFINED +#undef yyget_debug +#endif +#ifndef cmGccDepfile_yyset_debug_ALREADY_DEFINED +#undef yyset_debug +#endif +#ifndef cmGccDepfile_yyget_extra_ALREADY_DEFINED +#undef yyget_extra +#endif +#ifndef cmGccDepfile_yyset_extra_ALREADY_DEFINED +#undef yyset_extra +#endif +#ifndef cmGccDepfile_yyget_in_ALREADY_DEFINED +#undef yyget_in +#endif +#ifndef cmGccDepfile_yyset_in_ALREADY_DEFINED +#undef yyset_in +#endif +#ifndef cmGccDepfile_yyget_out_ALREADY_DEFINED +#undef yyget_out +#endif +#ifndef cmGccDepfile_yyset_out_ALREADY_DEFINED +#undef yyset_out +#endif +#ifndef cmGccDepfile_yyget_leng_ALREADY_DEFINED +#undef yyget_leng +#endif +#ifndef cmGccDepfile_yyget_text_ALREADY_DEFINED +#undef yyget_text +#endif +#ifndef cmGccDepfile_yyget_lineno_ALREADY_DEFINED +#undef yyget_lineno +#endif +#ifndef cmGccDepfile_yyset_lineno_ALREADY_DEFINED +#undef yyset_lineno +#endif +#ifndef cmGccDepfile_yyget_column_ALREADY_DEFINED +#undef yyget_column +#endif +#ifndef cmGccDepfile_yyset_column_ALREADY_DEFINED +#undef yyset_column +#endif +#ifndef cmGccDepfile_yywrap_ALREADY_DEFINED +#undef yywrap +#endif +#ifndef cmGccDepfile_yyget_lval_ALREADY_DEFINED +#undef yyget_lval +#endif +#ifndef cmGccDepfile_yyset_lval_ALREADY_DEFINED +#undef yyset_lval +#endif +#ifndef cmGccDepfile_yyget_lloc_ALREADY_DEFINED +#undef yyget_lloc +#endif +#ifndef cmGccDepfile_yyset_lloc_ALREADY_DEFINED +#undef yyset_lloc +#endif +#ifndef cmGccDepfile_yyalloc_ALREADY_DEFINED +#undef yyalloc +#endif +#ifndef cmGccDepfile_yyrealloc_ALREADY_DEFINED +#undef yyrealloc +#endif +#ifndef cmGccDepfile_yyfree_ALREADY_DEFINED +#undef yyfree +#endif +#ifndef cmGccDepfile_yytext_ALREADY_DEFINED +#undef yytext +#endif +#ifndef cmGccDepfile_yyleng_ALREADY_DEFINED +#undef yyleng +#endif +#ifndef cmGccDepfile_yyin_ALREADY_DEFINED +#undef yyin +#endif +#ifndef cmGccDepfile_yyout_ALREADY_DEFINED +#undef yyout +#endif +#ifndef cmGccDepfile_yy_flex_debug_ALREADY_DEFINED +#undef yy_flex_debug +#endif +#ifndef cmGccDepfile_yylineno_ALREADY_DEFINED +#undef yylineno +#endif +#ifndef cmGccDepfile_yytables_fload_ALREADY_DEFINED +#undef yytables_fload +#endif +#ifndef cmGccDepfile_yytables_destroy_ALREADY_DEFINED +#undef yytables_destroy +#endif +#ifndef cmGccDepfile_yyTABLES_NAME_ALREADY_DEFINED +#undef yyTABLES_NAME +#endif + +#undef cmGccDepfile_yyIN_HEADER +#endif /* cmGccDepfile_yyHEADER_H */ diff --git a/Source/LexerParser/cmGccDepfileLexer.in.l b/Source/LexerParser/cmGccDepfileLexer.in.l new file mode 100644 index 0000000..08f8577 --- /dev/null +++ b/Source/LexerParser/cmGccDepfileLexer.in.l @@ -0,0 +1,72 @@ +%{ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +/* IWYU pragma: no_forward_declare yyguts_t */ + +#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ + +#include <cmGccDepfileLexerHelper.h> +#include <string> +%} + +%option prefix="cmGccDepfile_yy" +%option noyywrap +%option reentrant +%pointer + +WSPACE [ \t] +NEWLINE \r?\n + +%% +\${2} { + // Unescape the dollar sign. + yyextra->addToCurrentPath("$"); + } +\\# { + // Unescape the hash. + yyextra->addToCurrentPath("#"); + } +(\\\\)*\\[ ] { + // 2N+1 backslashes plus space -> N backslashes plus space. + size_t c = (strlen(yytext) - 1) / 2; + std::string s(c, '\\'); + s.push_back(' '); + yyextra->addToCurrentPath(s.c_str()); + } +(\\\\)+[ ] { + // 2N backslashes plus space -> 2N backslashes, end of filename. + yytext[strlen(yytext) - 1] = 0; + yyextra->addToCurrentPath(yytext); + yyextra->newDependency(); + } +{WSPACE}*\\{NEWLINE} { + // A line continuation ends the current file name. + yyextra->newDependency(); + } +{NEWLINE} { + // A newline ends the current file name and the current rule. + yyextra->newEntry(); + } +:{WSPACE}+ { + // A colon followed by space ends the rules and starts a new dependency. + yyextra->newDependency(); + } +{WSPACE}+ { + // Rules and dependencies are separated by blocks of whitespace. + yyextra->newRuleOrDependency(); + } +[a-zA-Z0-9+,/_.~()}{%=@\x5B\x5D!\x80-\xFF-]+ { + // Got a span of plain text. + yyextra->addToCurrentPath(yytext); + } +. { + // Got an otherwise unmatched character. + yyextra->addToCurrentPath(yytext); + } + +%% + +/*--------------------------------------------------------------------------*/ + +#endif /* __clang_analyzer__ */ diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index cb89d19..98dd0e2 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 b608fcb..3b5dc04 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 b85cc33..0b2750d 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 6e04ce5..5deba8b 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -215,7 +215,8 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, } if (cmSystemTools::FileIsFullPath(filename)) { - filename = cmSystemTools::CollapseFullPath(filename); + filename = cmSystemTools::CollapseFullPath( + filename, status.GetMakefile().GetHomeOutputDirectory()); } switch (doing) { case doing_depfile: @@ -261,9 +262,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 +344,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 e27b126..aa98d89 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 0439c51..f443fc6 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/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index 6a1a514..35eabaf 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -53,7 +53,8 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, status.SetError(error); return false; } - srcPath = cmSystemTools::CollapseFullPath(srcPath); + srcPath = + cmSystemTools::CollapseFullPath(srcPath, mf.GetHomeOutputDirectory()); // Compute the full path to the binary directory. std::string binPath; diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx index 8942113..205c1c7 100644 --- a/Source/cmAddTestCommand.cxx +++ b/Source/cmAddTestCommand.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddTestCommand.h" +#include <cm/memory> + #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -44,7 +46,7 @@ bool cmAddTestCommand(std::vector<std::string> const& args, } else { test = mf.CreateTest(args[0]); test->SetOldStyle(true); - mf.AddTestGenerator(new cmTestGenerator(test)); + mf.AddTestGenerator(cm::make_unique<cmTestGenerator>(test)); } test->SetCommand(command); @@ -141,7 +143,7 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args, test->SetProperty("WORKING_DIRECTORY", working_directory.c_str()); } test->SetCommandExpandLists(command_expand_lists); - mf.AddTestGenerator(new cmTestGenerator(test, configurations)); + mf.AddTestGenerator(cm::make_unique<cmTestGenerator>(test, configurations)); return true; } diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index e0d27ee..19da2a0 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)) @@ -72,40 +67,6 @@ bool cmContains(Range const& range, Key const& key) namespace ContainerAlgorithms { -template <typename T> -struct cmIsPair -{ - enum - { - value = false - }; -}; - -template <typename K, typename V> -struct cmIsPair<std::pair<K, V>> -{ - enum - { - value = true - }; -}; - -template <typename Range, - bool valueTypeIsPair = cmIsPair<typename Range::value_type>::value> -struct DefaultDeleter -{ - void operator()(typename Range::value_type value) const { delete value; } -}; - -template <typename Range> -struct DefaultDeleter<Range, /* valueTypeIsPair = */ true> -{ - void operator()(typename Range::value_type value) const - { - delete value.second; - } -}; - template <typename FwdIt> FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n) { @@ -138,25 +99,6 @@ using cmBacktraceRange = cmRange<std::vector<cmListFileBacktrace>::const_iterator>; template <typename Range> -void cmDeleteAll(Range const& r) -{ - std::for_each(r.begin(), r.end(), - 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) { return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n); diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index e5eea79..d29b2ac 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -200,8 +200,11 @@ bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix, bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix, bool recursive) { - if (!this->AddFile(path, skip, prefix)) { - return false; + if (strcmp(path, ".") != 0 || + (this->Format != "zip" && this->Format != "7zip")) { + if (!this->AddFile(path, skip, prefix)) { + return false; + } } if ((!cmSystemTools::FileIsDirectory(path) || !recursive) || cmSystemTools::FileIsSymlink(path)) { @@ -210,6 +213,9 @@ bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix, cmsys::Directory d; if (d.Load(path)) { std::string next = cmStrCat(path, '/'); + if (next == "./" && (this->Format == "zip" || this->Format == "7zip")) { + next.clear(); + } std::string::size_type end = next.size(); unsigned long n = d.GetNumberOfFiles(); for (unsigned long i = 0; i < n; ++i) { diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 177bca8..b5c7e96 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 6a95148..19626f0 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 6eae26e..04f75bd 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; @@ -207,6 +208,8 @@ struct cmCTest::Private bool OutputColorCode = cmCTest::ColoredOutputSupportedByConsole(); std::map<std::string, std::string> Definitions; + + cmCTest::NoTests NoTestsMode = cmCTest::NoTests::Legacy; }; struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag) @@ -1279,7 +1282,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 +1842,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 +1859,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; } } @@ -2020,6 +2061,19 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, this->SetNotesFiles(args[i].c_str()); } + const std::string noTestsPrefix = "--no-tests="; + if (cmHasPrefix(arg, noTestsPrefix)) { + const std::string noTestsMode = arg.substr(noTestsPrefix.length()); + if (noTestsMode == "error") { + this->Impl->NoTestsMode = cmCTest::NoTests::Error; + } else if (noTestsMode != "ignore") { + errormsg = "'--no-tests=' given unknown value '" + noTestsMode + "'"; + return false; + } else { + this->Impl->NoTestsMode = cmCTest::NoTests::Ignore; + } + } + // options that control what tests are run if (this->CheckArgument(arg, "-I", "--tests-information") && i < args.size() - 1) { @@ -2204,7 +2258,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 +2901,19 @@ 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->RepeatCount; +} + +cmCTest::Repeat cmCTest::GetRepeatMode() const { - return this->Impl->RepeatTests; + return this->Impl->RepeatMode; } -bool cmCTest::GetRepeatUntilFail() const +cmCTest::NoTests cmCTest::GetNoTestsMode() const { - return this->Impl->RepeatUntilFail; + return this->Impl->NoTestsMode; } void cmCTest::SetBuildID(const std::string& id) @@ -2964,10 +3023,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 82a6f4c..7f8f913 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -431,10 +431,24 @@ 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; + + enum class NoTests + { + Legacy, + Error, + Ignore + }; + NoTests GetNoTestsMode() const; void GenerateSubprojectsOutput(cmXMLWriter& xml); std::vector<std::string> GetLabelsForSubprojects(); diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index d627465..dc9aba1 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,14 +644,15 @@ 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 : "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; @@ -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 faa60c5..d8be991 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 6f19697..896b6a9 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 19a096b..5ff6f8c 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -17,6 +17,7 @@ #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmTarget.h" cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) : GeneratorTarget(gt) @@ -25,27 +26,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 +97,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 +171,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 +199,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()); @@ -206,6 +217,20 @@ std::string cmCommonTargetGenerator::GetManifests() return cmJoin(manifests, " "); } +std::string cmCommonTargetGenerator::GetAIXExports(std::string const&) +{ + std::string aixExports; + if (this->GeneratorTarget->Target->IsAIX()) { + if (const char* exportAll = + this->GeneratorTarget->GetProperty("AIX_EXPORT_ALL_SYMBOLS")) { + if (cmIsOff(exportAll)) { + aixExports = "-n"; + } + } + } + return aixExports; +} + void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, const std::string& lang, const char* name, bool so) @@ -223,7 +248,10 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, int major; int minor; int patch; - this->GeneratorTarget->GetTargetVersion(so, major, minor, patch); + std::string prop = cmStrCat("OSX_", name, "_VERSION"); + std::string fallback_prop = so ? "SOVERSION" : "VERSION"; + this->GeneratorTarget->GetTargetVersionFallback(prop, fallback_prop, major, + minor, patch); if (major > 0 || minor > 0 || patch > 0) { // Append the flag since a non-zero version is specified. std::ostringstream vflag; diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 17792d6..b40a2ed 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -25,42 +25,51 @@ 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::string GetAIXExports(std::string const& 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 645189a..47c821b 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/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 8773d10..7be6d2c 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -8,8 +8,11 @@ #include <sstream> #include <utility> +#include <cm/memory> + #include "cmAlgorithms.h" #include "cmComputeLinkDepends.h" +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmListFileCache.h" @@ -256,11 +259,10 @@ cmComputeLinkInformation::cmComputeLinkInformation( "FIND_LIBRARY_USE_OPENBSD_VERSIONING"); // Allocate internals. - this->OrderLinkerSearchPath = new cmOrderDirectories( + this->OrderLinkerSearchPath = cm::make_unique<cmOrderDirectories>( this->GlobalGenerator, target, "linker search path"); - this->OrderRuntimeSearchPath = new cmOrderDirectories( + this->OrderRuntimeSearchPath = cm::make_unique<cmOrderDirectories>( this->GlobalGenerator, target, "runtime search path"); - this->OrderDependentRPath = nullptr; // Get the language used for linking this target. this->LinkLanguage = this->Target->GetLinkerLanguage(config); @@ -358,7 +360,7 @@ cmComputeLinkInformation::cmComputeLinkInformation( this->SharedDependencyMode = SharedDepModeLibDir; } else if (!this->RPathLinkFlag.empty()) { this->SharedDependencyMode = SharedDepModeDir; - this->OrderDependentRPath = new cmOrderDirectories( + this->OrderDependentRPath = cm::make_unique<cmOrderDirectories>( this->GlobalGenerator, target, "dependent library path"); } @@ -400,12 +402,7 @@ cmComputeLinkInformation::cmComputeLinkInformation( "CMAKE_POLICY_WARNING_CMP0060"); } -cmComputeLinkInformation::~cmComputeLinkInformation() -{ - delete this->OrderLinkerSearchPath; - delete this->OrderRuntimeSearchPath; - delete this->OrderDependentRPath; -} +cmComputeLinkInformation::~cmComputeLinkInformation() = default; void cmComputeLinkInformation::AppendValues( std::string& result, std::vector<BT<std::string>>& values) @@ -573,6 +570,15 @@ void cmComputeLinkInformation::AddImplicitLinkInfo() cmGeneratorTarget::LinkClosure const* lc = this->Target->GetLinkClosure(this->Config); for (std::string const& li : lc->Languages) { + + if (li == "CUDA") { + // These need to go before the other implicit link information + // as they could require symbols from those other library + // Currently restricted to CUDA as it is the only language + // we have documented runtime behavior controls for + this->AddRuntimeLinkLibrary(li); + } + // Skip those of the linker language. They are implicit. if (li != this->LinkLanguage) { this->AddImplicitLinkInfo(li); @@ -580,6 +586,39 @@ void cmComputeLinkInformation::AddImplicitLinkInfo() } } +void cmComputeLinkInformation::AddRuntimeLinkLibrary(std::string const& lang) +{ // Add the lang runtime library flags. This is activated by the presence + // of a default selection whether or not it is overridden by a property. + std::string defaultVar = + cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARY_DEFAULT"); + const char* langRuntimeLibraryDefault = + this->Makefile->GetDefinition(defaultVar); + if (langRuntimeLibraryDefault && *langRuntimeLibraryDefault) { + const char* runtimeLibraryValue = + this->Target->GetProperty(cmStrCat(lang, "_RUNTIME_LIBRARY")); + if (!runtimeLibraryValue) { + runtimeLibraryValue = langRuntimeLibraryDefault; + } + + std::string runtimeLibrary = + cmSystemTools::UpperCase(cmGeneratorExpression::Evaluate( + runtimeLibraryValue, this->Target->GetLocalGenerator(), this->Config, + this->Target)); + if (!runtimeLibrary.empty()) { + if (const char* runtimeLinkOptions = this->Makefile->GetDefinition( + "CMAKE_" + lang + "_RUNTIME_LIBRARY_LINK_OPTIONS_" + + runtimeLibrary)) { + std::vector<std::string> libsVec = cmExpandedList(runtimeLinkOptions); + for (std::string const& i : libsVec) { + if (!cmContains(this->ImplicitLinkLibs, i)) { + this->AddItem(i, nullptr); + } + } + } + } + } +} + void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) { // Add libraries for this language that are not implied by the @@ -747,10 +786,10 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item, if (this->SharedDependencyMode == SharedDepModeLibDir && !this->LinkWithRuntimePath /* AddLibraryRuntimeInfo adds it */) { // Add the item to the linker search path. - order = this->OrderLinkerSearchPath; + order = this->OrderLinkerSearchPath.get(); } else if (this->SharedDependencyMode == SharedDepModeDir) { // Add the item to the separate dependent library search path. - order = this->OrderDependentRPath; + order = this->OrderDependentRPath.get(); } if (order) { if (tgt) { diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 92ab83b..3bc9c16 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <set> #include <string> #include <utility> @@ -29,6 +30,9 @@ class cmComputeLinkInformation public: cmComputeLinkInformation(cmGeneratorTarget const* target, const std::string& config); + cmComputeLinkInformation(const cmComputeLinkInformation&) = delete; + cmComputeLinkInformation& operator=(const cmComputeLinkInformation&) = + delete; ~cmComputeLinkInformation(); bool Compute(); @@ -164,7 +168,7 @@ private: cmsys::RegularExpression SplitFramework; // Linker search path computation. - cmOrderDirectories* OrderLinkerSearchPath; + std::unique_ptr<cmOrderDirectories> OrderLinkerSearchPath; bool FinishLinkerSearchDirectories(); void PrintLinkPolicyDiagnosis(std::ostream&); @@ -172,6 +176,7 @@ private: void LoadImplicitLinkInfo(); void AddImplicitLinkInfo(); void AddImplicitLinkInfo(std::string const& lang); + void AddRuntimeLinkLibrary(std::string const& lang); std::set<std::string> ImplicitLinkDirs; std::set<std::string> ImplicitLinkLibs; @@ -184,9 +189,9 @@ private: std::vector<std::string> OldUserFlagItems; std::set<std::string> CMP0060WarnItems; // Dependent library path computation. - cmOrderDirectories* OrderDependentRPath; + std::unique_ptr<cmOrderDirectories> OrderDependentRPath; // Runtime path computation. - cmOrderDirectories* OrderRuntimeSearchPath; + std::unique_ptr<cmOrderDirectories> OrderRuntimeSearchPath; bool OldLinkDirMode; bool OpenBSD; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 162bab2..58ec53a 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 003e60d..fda687f 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 5711cae..da04396 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 09d269b..0dd8722 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 4689ace..d300fa5 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 c1f412d..2432d2b 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -6,7 +6,8 @@ #include <memory> #include <utility> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmGeneratorExpression.h" @@ -29,10 +30,11 @@ void AppendPaths(const std::vector<std::string>& inputs, for (std::string& it : result) { cmSystemTools::ConvertToUnixSlashes(it); if (cmSystemTools::FileIsFullPath(it)) { - it = cmSystemTools::CollapseFullPath(it); + it = cmSystemTools::CollapseFullPath( + it, lg->GetMakefile()->GetHomeOutputDirectory()); } } - cmAppend(output, result); + cm::append(output, result); } } } @@ -56,7 +58,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)); } @@ -137,7 +139,7 @@ const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const (target->IsImported() || target->GetProperty("CROSSCOMPILING_EMULATOR") || !this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) { - return target->GetLocation(this->Config); + return target->GetLocation(this->Config).c_str(); } return nullptr; } @@ -201,7 +203,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 +226,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 3bb6e36..868c94a 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 15cada6..641263d 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 5976b2f..202b205 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 80e4bcd..5be5bce 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 7e9a987..d22bd48 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 11fbd02..66e8cbb 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 2a6bf5d..b7cc193 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 aeef602..6441e6f 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -14,6 +14,7 @@ #include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -60,9 +61,9 @@ void cmExportFileGenerator::SetExportFile(const char* mainFile) cmSystemTools::GetFilenameLastExtension(this->MainImportFile); } -const char* cmExportFileGenerator::GetMainExportFileName() const +const std::string& cmExportFileGenerator::GetMainExportFileName() const { - return this->MainImportFile.c_str(); + return this->MainImportFile; } bool cmExportFileGenerator::GenerateImportFile() @@ -640,6 +641,9 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( std::string sep; input.clear(); for (std::string& li : parts) { + if (cmHasLiteralPrefix(li, CMAKE_DIRECTORY_ID_SEP)) { + continue; + } if (cmGeneratorExpression::Find(li) == std::string::npos) { this->AddTargetNamespace(li, target, missingTargets); } else { @@ -1062,6 +1066,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/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 0d69779..e9d0da7 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -46,7 +46,7 @@ public: /** Set the full path to the export file to generate. */ void SetExportFile(const char* mainFile); - const char* GetMainExportFileName() const; + const std::string& GetMainExportFileName() const; /** Set the namespace in which to place exported target names. */ void SetNamespace(const std::string& ns) { this->Namespace = ns; } diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index 2d732c1..9702e0e 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 6d29c99..987ec9e 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 89093e9..6011ba4 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 fafa51b..3df6a5c 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 a472a06..2b8d505 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 5a5d959..b710467 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 c7b7457..de40c77 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 b286acf..78cabce 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 ff4c59e..a7aa549 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 e8c9dd0..3a22846 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) { @@ -248,8 +246,7 @@ std::string cmExtraKateGenerator::GenerateFilesString( } } - const std::vector<cmSourceFile*>& sources = makefile->GetSourceFiles(); - for (cmSourceFile* sf : sources) { + for (const auto& sf : makefile->GetSourceFiles()) { if (sf->GetIsGenerated()) { continue; } diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h index be1376a..1fb81b4 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 495324c..413449c 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; @@ -296,8 +297,7 @@ void cmExtraSublimeTextGenerator::AppendTarget( fout << "\t{\n\t\t\t\"name\": \"" << lg->GetProjectName() << " - " << targetName << "\",\n"; fout << "\t\t\t\"cmd\": [" - << this->BuildMakeCommand(make, makefileName.c_str(), targetName) - << "],\n"; + << this->BuildMakeCommand(make, makefileName, targetName) << "],\n"; fout << "\t\t\t\"working_dir\": \"${project_path}\",\n"; fout << "\t\t\t\"file_regex\": \"" "^(..[^:]*)(?::|\\\\()([0-9]+)(?::|\\\\))(?:([0-9]+):)?\\\\s*(.*)" @@ -308,7 +308,8 @@ void cmExtraSublimeTextGenerator::AppendTarget( // Create the command line for building the given target using the selected // make std::string cmExtraSublimeTextGenerator::BuildMakeCommand( - const std::string& make, const char* makefile, const std::string& target) + const std::string& make, const std::string& makefile, + const std::string& target) { std::string command = cmStrCat('"', make, '"'); std::string generator = this->GlobalGenerator->GetName(); diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h index 7e8f2d4..078cfe7 100644 --- a/Source/cmExtraSublimeTextGenerator.h +++ b/Source/cmExtraSublimeTextGenerator.h @@ -44,7 +44,8 @@ private: /** Returns the build command that needs to be executed to build the * specified target. */ - std::string BuildMakeCommand(const std::string& make, const char* makefile, + std::string BuildMakeCommand(const std::string& make, + const std::string& makefile, const std::string& target); /** Appends the specified target to the generated project file as a Sublime * Text build system. diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 11844e4..d88617a 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 f419997..44ba96c 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 d7993c7..955195f 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); @@ -492,8 +493,9 @@ void CodemodelConfig::ProcessDirectories() Directory& d = *di; // Accumulate the presence of install rules on the way up. - for (auto gen : d.LocalGenerator->GetMakefile()->GetInstallGenerators()) { - if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen)) { + for (const auto& gen : + d.LocalGenerator->GetMakefile()->GetInstallGenerators()) { + if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen.get())) { d.HasInstallRule = true; break; } @@ -554,8 +556,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 d55b959..79110ab 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" @@ -783,7 +784,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 +1395,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 +1409,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 +1419,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: @@ -1707,7 +1708,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, // as we receive downloaded bits from curl... // std::string dir = cmSystemTools::GetFilenamePath(file); - if (!cmSystemTools::FileExists(dir) && !cmSystemTools::MakeDirectory(dir)) { + if (!dir.empty() && !cmSystemTools::FileExists(dir) && + !cmSystemTools::MakeDirectory(dir)) { std::string errstring = "DOWNLOAD error: cannot create directory '" + dir + "' - Specify file by full path name and verify that you " "have directory creation and file write privileges."; @@ -2673,9 +2675,20 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, cmSystemTools::SetFatalErrorOccured(); return false; } - argIt = keywordsMissingValues.begin(); - if (argIt != keywordsMissingValues.end()) { - status.SetError(cmStrCat("Keyword missing value: ", *argIt)); + + const std::vector<std::string> LIST_ARGS = { "DIRECTORIES", + "EXECUTABLES", + "LIBRARIES", + "MODULES", + "POST_EXCLUDE_REGEXES", + "POST_INCLUDE_REGEXES", + "PRE_EXCLUDE_REGEXES", + "PRE_INCLUDE_REGEXES" }; + auto kwbegin = keywordsMissingValues.cbegin(); + auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); + if (kwend != kwbegin) { + status.SetError(cmStrCat("Keywords missing values:\n ", + cmJoin(cmMakeRange(kwbegin, kwend), "\n "))); cmSystemTools::SetFatalErrorOccured(); return false; } diff --git a/Source/cmFileLock.cxx b/Source/cmFileLock.cxx index e90f571..6010233 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 2130d65..5fe068e 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 8db2db2..e1f6e94 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 dae68dd..d45c82c 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 ac8a37e..8cfdb2d 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 7ffc929..b510a2c 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 7d74118..bec99bb 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 f75db5f..fce0b11 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 badec55..82acfed 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 8177eac..916f3bc 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 20221b1..d5a4bde 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 2b11b62..297c72b 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 85fe7b6..ae9ade7 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 f5e2631..908f0c1 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 8d1ea8b..18bfb7d 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 e0a3fbf..3e49172 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 44392ba..ac48287 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 b3ddfe0..a4c9072 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/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx new file mode 100644 index 0000000..957896f --- /dev/null +++ b/Source/cmGccDepfileLexerHelper.cxx @@ -0,0 +1,126 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmGccDepfileLexerHelper.h" + +#include <cstdio> +#include <memory> +#include <string> +#include <vector> + +#include "cmGccDepfileReaderTypes.h" + +#include "LexerParser/cmGccDepfileLexer.h" + +#ifdef _WIN32 +# include "cmsys/Encoding.h" +#endif + +bool cmGccDepfileLexerHelper::readFile(const char* filePath) +{ +#ifdef _WIN32 + wchar_t* wpath = cmsysEncoding_DupToWide(filePath); + FILE* file = _wfopen(wpath, L"rb"); + free(wpath); +#else + FILE* file = fopen(filePath, "r"); +#endif + if (!file) { + return false; + } + newEntry(); + yyscan_t scanner; + cmGccDepfile_yylex_init(&scanner); + cmGccDepfile_yyset_extra(this, scanner); + cmGccDepfile_yyrestart(file, scanner); + cmGccDepfile_yylex(scanner); + cmGccDepfile_yylex_destroy(scanner); + sanitizeContent(); + fclose(file); + return true; +} + +void cmGccDepfileLexerHelper::newEntry() +{ + this->HelperState = State::Rule; + this->Content.emplace_back(); + newRule(); +} + +void cmGccDepfileLexerHelper::newRule() +{ + auto& entry = this->Content.back(); + if (entry.rules.empty() || !entry.rules.back().empty()) { + entry.rules.emplace_back(); + } +} + +void cmGccDepfileLexerHelper::newDependency() +{ + // printf("NEW DEP\n"); + this->HelperState = State::Dependency; + if (this->Content.back().paths.empty() || + !this->Content.back().paths.back().empty()) { + this->Content.back().paths.emplace_back(); + } +} + +void cmGccDepfileLexerHelper::newRuleOrDependency() +{ + if (this->HelperState == State::Rule) { + newRule(); + } else { + newDependency(); + } +} + +void cmGccDepfileLexerHelper::addToCurrentPath(const char* s) +{ + if (this->Content.empty()) { + return; + } + cmGccStyleDependency* dep = &this->Content.back(); + std::string* dst = nullptr; + switch (this->HelperState) { + case State::Rule: { + if (dep->rules.empty()) { + return; + } + dst = &dep->rules.back(); + } break; + case State::Dependency: { + if (dep->paths.empty()) { + return; + } + dst = &dep->paths.back(); + } break; + } + dst->append(s); +} + +void cmGccDepfileLexerHelper::sanitizeContent() +{ + for (auto it = this->Content.begin(); it != this->Content.end();) { + // Remove empty rules + for (auto rit = it->rules.begin(); rit != it->rules.end();) { + if (rit->empty()) { + rit = it->rules.erase(rit); + } else { + ++rit; + } + } + // Remove the entry if rules are empty + if (it->rules.empty()) { + it = this->Content.erase(it); + } else { + // Remove empty paths + for (auto pit = it->paths.begin(); pit != it->paths.end();) { + if (pit->empty()) { + pit = it->paths.erase(pit); + } else { + ++pit; + } + } + ++it; + } + } +} diff --git a/Source/cmGccDepfileLexerHelper.h b/Source/cmGccDepfileLexerHelper.h new file mode 100644 index 0000000..e6b2fcf --- /dev/null +++ b/Source/cmGccDepfileLexerHelper.h @@ -0,0 +1,40 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmGccDepfileLexerHelper_h +#define cmGccDepfileLexerHelper_h + +#include <utility> + +#include <cmGccDepfileReaderTypes.h> + +class cmGccDepfileLexerHelper +{ +public: + cmGccDepfileLexerHelper() = default; + + bool readFile(const char* filePath); + cmGccDepfileContent extractContent() && { return std::move(this->Content); } + + // Functions called by the lexer + void newEntry(); + void newRule(); + void newDependency(); + void newRuleOrDependency(); + void addToCurrentPath(const char* s); + +private: + void sanitizeContent(); + + cmGccDepfileContent Content; + + enum class State + { + Rule, + Dependency + }; + State HelperState = State::Rule; +}; + +#define YY_EXTRA_TYPE cmGccDepfileLexerHelper* + +#endif diff --git a/Source/cmGccDepfileReader.cxx b/Source/cmGccDepfileReader.cxx new file mode 100644 index 0000000..9d70ede --- /dev/null +++ b/Source/cmGccDepfileReader.cxx @@ -0,0 +1,18 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmGccDepfileReader.h" + +#include <type_traits> +#include <utility> + +#include "cmGccDepfileLexerHelper.h" + +cmGccDepfileContent cmReadGccDepfile(const char* filePath) +{ + cmGccDepfileContent result; + cmGccDepfileLexerHelper helper; + if (helper.readFile(filePath)) { + result = std::move(helper).extractContent(); + } + return result; +} diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h new file mode 100644 index 0000000..9313010 --- /dev/null +++ b/Source/cmGccDepfileReader.h @@ -0,0 +1,10 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmGccDepfileReader_h +#define cmGccDepfileReader_h + +#include "cmGccDepfileReaderTypes.h" + +cmGccDepfileContent cmReadGccDepfile(const char* filePath); + +#endif diff --git a/Source/cmGccDepfileReaderTypes.h b/Source/cmGccDepfileReaderTypes.h new file mode 100644 index 0000000..8b15c73 --- /dev/null +++ b/Source/cmGccDepfileReaderTypes.h @@ -0,0 +1,17 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmGccDepfileReaderTypes_h +#define cmGccDepfileReaderTypes_h + +#include <string> +#include <vector> + +struct cmGccStyleDependency +{ + std::vector<std::string> rules; + std::vector<std::string> paths; +}; + +using cmGccDepfileContent = std::vector<cmGccStyleDependency>; + +#endif diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index b7f7d1d..81d1e46 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 4bd1c9f..c4be3a1 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 e0ae170..4129a0c 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 b10bb5b..10496fd 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/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 66f1c71..14478c2 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -14,6 +14,7 @@ #include <utility> #include <cm/iterator> +#include <cm/string_view> #include "cmsys/RegularExpression.hxx" #include "cmsys/String.h" @@ -37,7 +38,6 @@ #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" -#include "cmString.hxx" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index d6cc6ab..c2c9ef7 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 e663496..1ba1654 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 171c3ed..4dfc33d 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" @@ -55,11 +54,11 @@ const char* cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( cmGeneratorTarget const* tgt, cmMessenger* /* messenger */, cmListFileBacktrace const& /* context */) { - return tgt->GetSourcesProperty(); + return tgt->GetSourcesProperty().c_str(); } template <> -const char* +const std::string& cmTargetPropertyComputer::ComputeLocationForBuild<cmGeneratorTarget>( cmGeneratorTarget const* tgt) { @@ -67,7 +66,8 @@ cmTargetPropertyComputer::ComputeLocationForBuild<cmGeneratorTarget>( } template <> -const char* cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>( +const std::string& +cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>( cmGeneratorTarget const* tgt, const std::string& config) { return tgt->GetLocation(config); @@ -162,7 +162,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 +173,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 +223,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 +238,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,29 +309,18 @@ 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 +const std::string& 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; value.clear(); value = cmJoin(values, ";"); - return value.c_str(); + return value; } cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const @@ -655,6 +649,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 +739,7 @@ void cmGeneratorTarget::GetObjectSources( { IMPLEMENT_VISIT(SourceKindObjectSource); - if (!this->Objects.empty()) { + if (this->VisitedConfigsForObjects.count(config)) { return; } @@ -753,16 +748,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); @@ -1001,7 +997,8 @@ void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& data, IMPLEMENT_VISIT(SourceKindXaml); } -const char* cmGeneratorTarget::GetLocation(const std::string& config) const +const std::string& cmGeneratorTarget::GetLocation( + const std::string& config) const { static std::string location; if (this->IsImported()) { @@ -1010,7 +1007,7 @@ const char* cmGeneratorTarget::GetLocation(const std::string& config) const } else { location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); } - return location.c_str(); + return location; } std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPreBuildCommands() @@ -1041,13 +1038,13 @@ bool cmGeneratorTarget::IsImportedGloballyVisible() const return this->Target->IsImportedGloballyVisible(); } -const char* cmGeneratorTarget::GetLocationForBuild() const +const std::string& cmGeneratorTarget::GetLocationForBuild() const { static std::string location; if (this->IsImported()) { location = this->Target->ImportedGetFullPath( "", cmStateEnums::RuntimeBinaryArtifact); - return location.c_str(); + return location; } // Now handle the deprecated build-time configuration location. @@ -1067,7 +1064,7 @@ const char* cmGeneratorTarget::GetLocationForBuild() const } location += "/"; location += this->GetFullName("", cmStateEnums::RuntimeBinaryArtifact); - return location.c_str(); + return location; } bool cmGeneratorTarget::IsSystemIncludeDirectory( @@ -1122,7 +1119,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 +1139,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 +1149,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 +1164,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 +1203,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 +1218,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 +1247,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 +1261,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 +1674,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 +2129,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 +2149,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 +2158,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 +2516,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) { @@ -2691,6 +2715,17 @@ void cmTargetTraceDependencies::FollowName(std::string const& name) if (i == this->NameMap.end() || i->first != name) { // Check if we know how to generate this file. cmSourcesWithOutput sources = this->Makefile->GetSourcesWithOutput(name); + // If we failed to find a target or source and we have a relative path, it + // might be a valid source if made relative to the current binary + // directory. + if (!sources.Target && !sources.Source && + !cmSystemTools::FileIsFullPath(name)) { + auto fullname = + cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', name); + fullname = cmSystemTools::CollapseFullPath( + fullname, this->Makefile->GetHomeOutputDirectory()); + sources = this->Makefile->GetSourcesWithOutput(fullname); + } i = this->NameMap.emplace_hint(i, name, sources); } if (cmTarget* t = i->second.Target) { @@ -3064,7 +3099,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( cmLinkImplementationLibraries const* impl = this->GetLinkImplementationLibraries(config); for (cmLinkImplItem const& lib : impl->Libraries) { - std::string libDir = cmSystemTools::CollapseFullPath(lib.AsStr()); + std::string libDir = cmSystemTools::CollapseFullPath( + lib.AsStr(), this->Makefile->GetHomeOutputDirectory()); static cmsys::RegularExpression frameworkCheck( "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); @@ -3277,10 +3313,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: @@ -3373,8 +3409,15 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, { "OBJCXX", ".objcxx.hxx" } }; - filename = cmStrCat(filename, "CMakeFiles/", generatorTarget->GetName(), - ".dir/cmake_pch", languageToExtension.at(language)); + filename = + cmStrCat(filename, "CMakeFiles/", generatorTarget->GetName(), ".dir"); + + if (this->GetGlobalGenerator()->IsMultiConfig()) { + filename = cmStrCat(filename, "/", config); + } + + filename = + cmStrCat(filename, "/cmake_pch", languageToExtension.at(language)); const std::string filename_tmp = cmStrCat(filename, ".tmp"); if (!pchReuseFrom) { @@ -3647,7 +3690,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 +3823,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 +3946,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 +3978,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 +4766,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 +5113,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,32 +5264,41 @@ 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 { int patch; - this->GetTargetVersion(false, major, minor, patch); + this->GetTargetVersion("VERSION", major, minor, patch); } -void cmGeneratorTarget::GetTargetVersion(bool soversion, int& major, - int& minor, int& patch) const +void cmGeneratorTarget::GetTargetVersionFallback( + const std::string& property, const std::string& fallback_property, + int& major, int& minor, int& patch) const +{ + if (this->GetProperty(property)) { + this->GetTargetVersion(property, major, minor, patch); + } else { + this->GetTargetVersion(fallback_property, major, minor, patch); + } +} + +void cmGeneratorTarget::GetTargetVersion(const std::string& property, + int& major, int& minor, + int& patch) const { // Set the default values. major = 0; @@ -5251,9 +5307,7 @@ void cmGeneratorTarget::GetTargetVersion(bool soversion, int& major, assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY); - // Look for a VERSION or SOVERSION property. - const char* prop = soversion ? "SOVERSION" : "VERSION"; - if (const char* version = this->GetProperty(prop)) { + if (const char* version = this->GetProperty(property)) { // Try to parse the version number and store the results that were // successfully parsed. int parsed_major; @@ -5383,16 +5437,39 @@ void cmGeneratorTarget::ReportPropertyOrigin( areport); } +bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n, + cmLocalGenerator const*& lg) const +{ + if (cmHasLiteralPrefix(n, CMAKE_DIRECTORY_ID_SEP)) { + cmDirectoryId const dirId = n.substr(sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); + if (dirId.String.empty()) { + lg = this->LocalGenerator; + return true; + } + if (cmLocalGenerator const* otherLG = + this->GlobalGenerator->FindLocalGenerator(dirId)) { + lg = otherLG; + return true; + } + } + return false; +} + void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, cmListFileBacktrace const& bt, std::vector<cmLinkItem>& items) const { + cmLocalGenerator const* lg = this->LocalGenerator; for (std::string const& n : names) { + if (this->IsLinkLookupScope(n, lg)) { + continue; + } + std::string name = this->CheckCMP0004(n); if (name == this->GetName() || name.empty()) { continue; } - items.push_back(this->ResolveLinkItem(name, bt)); + items.push_back(this->ResolveLinkItem(name, bt, lg)); } } @@ -5401,6 +5478,7 @@ void cmGeneratorTarget::ExpandLinkItems( cmGeneratorTarget const* headTarget, bool usage_requirements_only, std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const { + // Keep this logic in sync with ComputeLinkImplementationLibraries. cmGeneratorExpression ge; cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr); // The $<LINK_ONLY> expression may be in a link interface to specify private @@ -6330,6 +6408,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 +6472,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"); @@ -6462,6 +6554,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( const std::string& config, cmOptionalLinkImplementation& impl, cmGeneratorTarget const* head) const { + cmLocalGenerator const* lg = this->LocalGenerator; cmStringRange entryRange = this->Target->GetLinkImplementationEntries(); cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces(); cmBacktraceRange::const_iterator btIt = btRange.begin(); @@ -6470,6 +6563,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( end = entryRange.end(); le != end; ++le, ++btIt) { std::vector<std::string> llibs; + // Keep this logic in sync with ExpandLinkItems. cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, nullptr); cmGeneratorExpression ge(*btIt); @@ -6482,6 +6576,10 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } for (std::string const& lib : llibs) { + if (this->IsLinkLookupScope(lib, lg)) { + continue; + } + // Skip entries that resolve to the target itself or are empty. std::string name = this->CheckCMP0004(lib); if (name == this->GetName() || name.empty()) { @@ -6516,7 +6614,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt), + impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt, lg), evaluated != *le); } @@ -6553,38 +6651,16 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( std::string const& name) const { - cmLocalGenerator const* lg = this->LocalGenerator; - std::string const* lookupName = &name; - - // When target_link_libraries() is called with a LHS target that is - // not created in the calling directory it adds a directory id suffix - // that we can use to look up the calling directory. It is that scope - // in which the item name is meaningful. This case is relatively rare - // so we allocate a separate string only when the directory id is present. - std::string::size_type pos = name.find(CMAKE_DIRECTORY_ID_SEP); - std::string plainName; - if (pos != std::string::npos) { - // We will look up the plain name without the directory id suffix. - plainName = name.substr(0, pos); - - // We will look up in the scope of the directory id. - // If we do not recognize the id then leave the original - // syntax in place to produce an indicative error later. - cmDirectoryId const dirId = - name.substr(pos + sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); - if (cmLocalGenerator const* otherLG = - this->GlobalGenerator->FindLocalGenerator(dirId)) { - lg = otherLG; - lookupName = &plainName; - } - } + return this->ResolveTargetReference(name, this->LocalGenerator); +} +cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( + std::string const& name, cmLocalGenerator const* lg) const +{ TargetOrString resolved; - if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(*lookupName)) { + if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(name)) { resolved.Target = tgt; - } else if (lookupName == &plainName) { - resolved.String = std::move(plainName); } else { resolved.String = name; } @@ -6595,12 +6671,32 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( cmLinkItem cmGeneratorTarget::ResolveLinkItem( std::string const& name, cmListFileBacktrace const& bt) const { - TargetOrString resolved = this->ResolveTargetReference(name); + return this->ResolveLinkItem(name, bt, this->LocalGenerator); +} + +cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name, + cmListFileBacktrace const& bt, + cmLocalGenerator const* lg) const +{ + TargetOrString resolved = this->ResolveTargetReference(name, lg); if (!resolved.Target) { 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 493eafc..b647b25 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> @@ -45,7 +46,7 @@ public: bool IsImported() const; bool IsImportedGloballyVisible() const; - const char* GetLocation(const std::string& config) const; + const std::string& GetLocation(const std::string& config) const; std::vector<cmCustomCommand> const& GetPreBuildCommands() const; std::vector<cmCustomCommand> const& GetPreLinkCommands() const; @@ -64,7 +65,7 @@ public: /** Get the location of the target in the build tree with a placeholder referencing the configuration in the native build system. This location is suitable for use as the LOCATION target property. */ - const char* GetLocationForBuild() const; + const std::string& GetLocationForBuild() const; cmComputeLinkInformation* GetLinkInformation( const std::string& config) const; @@ -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; @@ -365,9 +378,14 @@ public: cmGeneratorTarget* Target = nullptr; }; TargetOrString ResolveTargetReference(std::string const& name) const; + TargetOrString ResolveTargetReference(std::string const& name, + cmLocalGenerator const* lg) const; cmLinkItem ResolveLinkItem(std::string const& name, cmListFileBacktrace const& bt) const; + cmLinkItem ResolveLinkItem(std::string const& name, + cmListFileBacktrace const& bt, + cmLocalGenerator const* lg) const; // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change @@ -701,7 +719,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; @@ -736,14 +755,22 @@ public: void GetTargetVersion(int& major, int& minor) const; /** Get the target major, minor, and patch version numbers - interpreted from the VERSION or SOVERSION property. Version 0 + interpreted from the given property. Version 0 is returned if the property is not set or cannot be parsed. */ - void GetTargetVersion(bool soversion, int& major, int& minor, + void GetTargetVersion(std::string const& property, int& major, int& minor, int& patch) const; + /** Get the target major, minor, and patch version numbers + interpreted from the given property and if empty use the + fallback property. Version 0 is returned if the property is + not set or cannot be parsed. */ + void GetTargetVersionFallback(const std::string& property, + const std::string& fallback_property, + int& major, int& minor, int& patch) const; + std::string GetFortranModuleDirectory(std::string const& working_dir) const; - const char* GetSourcesProperty() const; + const std::string& GetSourcesProperty() const; private: void AddSourceCommon(const std::string& src, bool before = false); @@ -760,6 +787,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 +844,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 +908,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; @@ -900,6 +932,9 @@ private: std::unordered_set<std::string> UnityBatchedSourceFiles; + bool IsLinkLookupScope(std::string const& n, + cmLocalGenerator const*& lg) const; + void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, const cmGeneratorTarget* headTarget, diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 8e4352e..5e2248e 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 51d681d..06943e7 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 da04743..9af0eac 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 9fa4467..e04eef1 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 09fb87d..1f084f5 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -7,9 +7,13 @@ #include <cstdio> #include <cstdlib> #include <cstring> +#include <functional> #include <initializer_list> #include <iterator> #include <sstream> +#include <utility> + +#include <cm/memory> #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" @@ -31,6 +35,7 @@ #include "cmGeneratorTarget.h" #include "cmInstallGenerator.h" #include "cmLinkLineComputer.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMSVC60LinkLineComputer.h" #include "cmMakefile.h" @@ -121,6 +126,7 @@ Json::Value cmGlobalGenerator::GetJson() const { Json::Value generator = Json::objectValue; generator["name"] = this->GetName(); + generator["multiConfig"] = this->IsMultiConfig(); return generator; } #endif @@ -165,7 +171,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 +262,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 +282,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 +300,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 +340,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 +368,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 +655,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 +1204,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 +1225,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 +1246,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 +1263,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 +1285,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 +1299,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 +1317,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 +1356,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 +1395,7 @@ bool cmGlobalGenerator::Compute() } // Add generator specific helper commands - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->AddHelperCommands(); } @@ -1397,16 +1405,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)) { + for (const auto& g : mf->GetInstallGenerators()) { + if (!g->Compute(localGen.get())) { return false; } } @@ -1416,7 +1424,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 +1436,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 +1453,7 @@ bool cmGlobalGenerator::Compute() return false; } - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->ComputeHomeRelativeOutputPath(); } @@ -1460,6 +1468,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 +1481,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 +1566,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 +1610,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 = @@ -1632,7 +1645,9 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() for (std::string const& c : configs) { std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c)); - t->AppendProperty(defPropName, mf->GetProperty(defPropName)); + if (const char* val = mf->GetProperty(defPropName)) { + t->AppendProperty(defPropName, val); + } } } } @@ -1661,8 +1676,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 +1689,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]; - for (cmTarget* ownedImpTgt : mf->GetOwnedImportedTargets()) { - cmLocalGenerator* lg = this->LocalGenerators[i]; - cmGeneratorTarget* gt = new cmGeneratorTarget(ownedImpTgt, lg); - lg->AddOwnedImportedGeneratorTarget(gt); - importedMap[ownedImpTgt] = gt; + auto& mf = this->Makefiles[i]; + for (const auto& ownedImpTgt : mf->GetOwnedImportedTargets()) { + cmLocalGenerator* lg = this->LocalGenerators[i].get(); + auto gt = cm::make_unique<cmGeneratorTarget>(ownedImpTgt.get(), lg); + importedMap[ownedImpTgt.get()] = 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 +1733,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 +1782,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 +2005,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 +2031,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 +2051,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 +2149,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 +2157,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 +2360,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 +2409,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 +2441,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; } @@ -2454,6 +2461,13 @@ void cmGlobalGenerator::AddGlobalTarget_Test( cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCTestCommand()); singleLine.push_back("--force-new-ctest-process"); + if (auto testArgs = mf->GetDefinition("CMAKE_CTEST_ARGUMENTS")) { + std::vector<std::string> args; + cmExpandList(testArgs, args); + for (auto const& arg : args) { + singleLine.push_back(arg); + } + } if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { singleLine.push_back("-C"); singleLine.push_back(cmakeCfgIntDir); @@ -2475,6 +2489,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,8 +2524,10 @@ 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("--regenerate-during-build"); singleLine.push_back("-S$(CMAKE_SOURCE_DIR)"); singleLine.push_back("-B$(CMAKE_BINARY_DIR)"); gti.CommandLines.push_back(std::move(singleLine)); @@ -2520,7 +2537,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 +2587,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 +2670,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 +2754,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 +2782,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 +2977,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"; } } @@ -3108,10 +3124,20 @@ cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const return this->FilenameTargetDepends[sf]; } +const std::string& cmGlobalGenerator::GetRealPath(const std::string& dir) +{ + auto i = this->RealPaths.lower_bound(dir); + if (i == this->RealPaths.end() || + this->RealPaths.key_comp()(dir, i->first)) { + i = this->RealPaths.emplace_hint(i, dir, cmSystemTools::GetRealPath(dir)); + } + return i->second; +} + void cmGlobalGenerator::ProcessEvaluationFiles() { std::vector<std::string> generatedFiles; - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (auto& localGen : this->LocalGenerators) { localGen->ProcessEvaluationFiles(generatedFiles); } } @@ -3127,7 +3153,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 +3172,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 f25ff7b..f6ed10f 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; @@ -410,6 +415,8 @@ public: virtual bool IsXcode() const { return false; } + virtual bool IsVisualStudio() const { return false; } + /** Return true if we know the exact location of object files. If false, store the reason in the given string. This is meaningful only after EnableLanguage has been called. */ @@ -440,12 +447,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 +483,19 @@ public: int RecursionDepth; + virtual void GetQtAutoGenConfigs(std::vector<std::string>& configs) const + { + configs.emplace_back("$<CONFIG>"); + } + + std::string const& GetRealPath(std::string const& dir); + 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 +538,7 @@ protected: std::vector<std::string> Depends; std::string WorkingDir; bool UsesTerminal = false; + bool PerConfig = true; }; void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets); @@ -539,8 +554,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 +564,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; @@ -666,6 +682,8 @@ private: mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*>> FilenameTargetDepends; + std::map<std::string, std::string> RealPaths; + #if !defined(CMAKE_BOOTSTRAP) // Pool of file locks cmFileLockPool FileLockPool; diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index bb5f74c..3709365 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 5a708ab..bb9dd37 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 ccfe073..b82e9f5 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 ff54288..fc3123a 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 fc39ddf..9f1ec8b 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 d6e4847..b2de4ff 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 15297e3..a9f92a1 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 2273c00..c4bec23 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 4586b77..fdf6006 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 da21d6c..f7694ff 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->GetImplFileStream(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->GetImplFileStream(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,19 @@ void cmGlobalNinjaGenerator::Generate() msg.str()); return; } - if (!this->OpenBuildFileStream()) { + if (!this->InspectConfigTypeVariables()) { + return; + } + 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 +513,101 @@ 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->GetImplFileStream(config)->setstate(std::ios::failbit); + this->GetConfigFileStream(config)->setstate(std::ios::failbit); + } + this->GetCommonFileStream()->setstate(std::ios::failbit); } this->CloseCompileCommandsStream(); this->CloseRulesFileStream(); - this->CloseBuildFileStream(); + this->CloseBuildFileStreams(); + +#ifdef _WIN32 + // The ninja tools will not be able to update metadata on Windows + // when we are re-generating inside an existing 'ninja' invocation + // because the outer tool has the files open for write. + if (!this->GetCMakeInstance()->GetRegenerateDuringBuild()) +#endif + { + this->CleanMetaData(); + } +} + +void cmGlobalNinjaGenerator::CleanMetaData() +{ + auto run_ninja_tool = [this](std::vector<char const*> const& args) { + std::vector<std::string> command; + command.push_back(this->NinjaCommand); + command.emplace_back("-C"); + command.emplace_back(this->GetCMakeInstance()->GetHomeOutputDirectory()); + command.emplace_back("-t"); + for (auto const& arg : args) { + command.emplace_back(arg); + } + 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(); + } + }; + + // Can the tools below expect 'build.ninja' to be loadable? + bool const expectBuildManifest = + !this->IsMultiConfig() && this->OutputPathPrefix.empty(); + + // Skip some ninja tools if they need 'build.ninja' but it is missing. + bool const missingBuildManifest = expectBuildManifest && + (this->NinjaSupportsCleanDeadTool || + this->NinjaSupportsUnconditionalRecompactTool) && + !cmSystemTools::FileExists("build.ninja"); + + // The `cleandead` tool needs to know about all outputs in the build we just + // wrote out. Ninja-Multi doesn't have a single `build.ninja` we can use that + // is the union of all generated configurations, so we can't run it reliably + // in that case. + if (this->NinjaSupportsCleanDeadTool && expectBuildManifest && + !missingBuildManifest) { + run_ninja_tool({ "cleandead" }); + } + // The `recompact` tool loads the manifest. As above, we don't have a single + // `build.ninja` to load for this in Ninja-Multi. This may be relaxed in the + // future pending further investigation into how Ninja works upstream + // (ninja#1721). + if (this->NinjaSupportsUnconditionalRecompactTool && expectBuildManifest && + !missingBuildManifest) { + run_ninja_tool({ "recompact" }); + } + if (this->NinjaSupportsRestatTool && this->OutputPathPrefix.empty()) { + // XXX(ninja): We only list `build.ninja` entry files here because CMake + // *always* rewrites these files on a reconfigure. If CMake ever gets + // smarter about this, all CMake-time created/edited files listed as + // outputs for the reconfigure build statement will need to be listed here. + cmNinjaDeps outputs; + this->AddRebuildManifestOutputs(outputs); + std::vector<const char*> args; + args.reserve(outputs.size() + 1); + args.push_back("restat"); + for (auto const& output : outputs) { + args.push_back(output.c_str()); + } + run_ninja_tool(args); + } } bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) @@ -569,6 +671,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( @@ -577,6 +689,17 @@ bool cmGlobalNinjaGenerator::CheckLanguages( if (cmContains(languages, "Fortran")) { return this->CheckFortran(mf); } + if (cmContains(languages, "Swift")) { + const std::string architectures = + mf->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES"); + if (architectures.find_first_of(';') != std::string::npos) { + mf->IssueMessage(MessageType::FATAL_ERROR, + "multiple values for CMAKE_OSX_ARCHITECTURES not " + "supported with Swift"); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } return true; } @@ -609,6 +732,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 +784,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 +800,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 +844,75 @@ 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(*stream); } - // Write the do not edit header. - this->WriteDisclaimer(*this->BuildFileStream); + return true; +} - // Write a comment about this file. - *this->BuildFileStream - << "# This file contains all the build statements describing the\n" - << "# compilation DAG.\n\n"; +cm::optional<std::set<std::string>> cmGlobalNinjaGenerator::ListSubsetWithAll( + const std::set<std::string>& defaults, const std::vector<std::string>& items) +{ + std::set<std::string> result; - return true; + for (auto const& item : items) { + if (item == "all") { + if (items.size() == 1) { + result = defaults; + } else { + return cm::nullopt; + } + } else if (defaults.count(item)) { + result.insert(item); + } else { + return cm::nullopt; + } + } + + return cm::make_optional(result); } -void cmGlobalNinjaGenerator::CloseBuildFileStream() +void cmGlobalNinjaGenerator::CloseBuildFileStreams() { if (this->BuildFileStream) { this->BuildFileStream.reset(); @@ -755,25 +923,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 +973,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 +985,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 +1056,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 +1083,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 +1105,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 +1120,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 +1129,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 +1138,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 +1185,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 +1198,56 @@ 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; + this->DefaultTargetAliases[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; + + auto newAliasGlobal = + this->TargetAliases.insert(std::make_pair(buildAlias, ta)); + if (newAliasGlobal.second && + newAliasGlobal.first->second.GeneratorTarget != target) { + newAliasGlobal.first->second.GeneratorTarget = nullptr; + } + + auto newAliasConfig = + this->Configs[config].TargetAliases.insert(std::make_pair(outputPath, ta)); + if (newAliasConfig.second && + newAliasConfig.first->second.GeneratorTarget != target) { + newAliasConfig.first->second.GeneratorTarget = nullptr; + } + if (this->DefaultConfigs.count(config)) { + auto newAliasDefaultGlobal = + this->DefaultTargetAliases.insert(std::make_pair(outputPath, ta)); + if (newAliasDefaultGlobal.second && + newAliasDefaultGlobal.first->second.GeneratorTarget != target) { + newAliasDefaultGlobal.first->second.GeneratorTarget = nullptr; + } } } @@ -1061,10 +1257,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,13 +1270,69 @@ 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 - this->WriteBuild(os, build); + if (ta.second.Config == "all") { + for (auto const& config : this->CrossConfigs) { + this->AppendTargetOutputs(ta.second.GeneratorTarget, + build.ExplicitDeps, config); + } + } else { + this->AppendTargetOutputs(ta.second.GeneratorTarget, build.ExplicitDeps, + ta.second.Config); + } + this->WriteBuild(this->EnableCrossConfigBuild() && + (ta.second.Config == "all" || + this->CrossConfigs.count(ta.second.Config)) + ? os + : *this->GetImplFileStream(ta.second.Config), + 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); + } + } + + if (!this->DefaultConfigs.empty()) { + for (auto const& ta : this->DefaultTargetAliases) { + // 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(); + for (auto const& config : this->DefaultConfigs) { + this->AppendTargetOutputs(ta.second.GeneratorTarget, + build.ExplicitDeps, config); + } + this->WriteBuild(*this->GetDefaultFileStream(), build); + } + } } } @@ -1097,24 +1349,73 @@ 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(this->EnableCrossConfigBuild() && + this->CrossConfigs.count(config) + ? os + : *this->GetImplFileStream(config), + 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); + } + + if (!this->DefaultFileConfig.empty()) { + build.ExplicitDeps.clear(); + for (auto const& config : this->DefaultConfigs) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config)); + } + build.Outputs.front() = + this->ConvertToNinjaPath(currentBinaryDir + "/all"); + this->WriteBuild(*this->GetDefaultFileStream(), build); } } - // Write target - this->WriteBuild(os, build); + + // Add target for all configs + if (this->EnableCrossConfigBuild()) { + build.ExplicitDeps.clear(); + for (auto const& config : this->CrossConfigs) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config)); + } + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), "all"); + this->WriteBuild(os, build); + } } } @@ -1148,7 +1449,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()) { @@ -1161,8 +1462,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) knownDependencies.insert(this->ConvertToNinjaPath(j)); } } - for (cmGeneratorExpressionEvaluationFile* li : - lg->GetMakefile()->GetEvaluationFiles()) { + for (const auto& li : lg->GetMakefile()->GetEvaluationFiles()) { // get all the files created by generator expressions and convert them // to ninja paths for (std::string const& evaluationFile : li->GetFiles()) { @@ -1247,10 +1547,17 @@ 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)); + } + + if (!this->DefaultFileConfig.empty()) { + this->WriteTargetDefault(*this->GetDefaultFileStream()); + } } void cmGlobalNinjaGenerator::WriteTargetDefault(std::ostream& os) @@ -1268,12 +1575,12 @@ 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"); rule.Command = - cmStrCat(CMakeCmd(), " -S", + cmStrCat(CMakeCmd(), " --regenerate-during-build -S", lg->ConvertToOutputFormat(lg->GetSourceDirectory(), cmOutputConverter::SHELL), " -B", @@ -1287,9 +1594,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 +1683,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 +1720,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 +1752,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 +1777,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 +1789,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 +1816,113 @@ 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::GetNinjaImplFilename(fileConfig)); + } + this->WriteBuild(*this->GetImplFileStream(fileConfig), build); + } + } + + if (this->EnableCrossConfigBuild()) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), "all"); + build.ExplicitDeps.clear(); + + if (additionalFiles) { + for (auto const& config : this->CrossConfigs) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), + config)); + } + } + + std::vector<std::string> byproducts; + for (auto const& config : this->CrossConfigs) { + byproducts.push_back( + this->BuildAlias(GetByproductsForCleanTargetName(), config)); + } + build.Variables["TARGETS"] = cmJoin(byproducts, " "); + + for (auto const& fileConfig : configs) { + build.Variables["FILE_ARG"] = cmStrCat( + "-f ", + cmGlobalNinjaMultiGenerator::GetNinjaImplFilename(fileConfig)); + this->WriteBuild(*this->GetImplFileStream(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); + } + + if (!this->DefaultConfigs.empty()) { + build.ExplicitDeps.clear(); + for (auto const& config : this->DefaultConfigs) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), config)); + } + this->WriteBuild(*this->GetDefaultFileStream(), 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 +2240,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 +2349,11 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( return true; } +bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const +{ + return !this->CrossConfigs.empty(); +} + int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, std::vector<std::string>::const_iterator argEnd) { @@ -1990,13 +2424,245 @@ 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; + } +} + +std::set<std::string> cmGlobalNinjaGenerator::GetCrossConfigs( + const std::string& fileConfig) const +{ + auto result = this->CrossConfigs; + result.insert(fileConfig); + return result; +} + +const char* cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE = + "CMakeFiles/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; + } + + if (!this->DefaultFileConfig.empty()) { + if (!this->OpenFileStream(this->DefaultFileStream, NINJA_BUILD_FILE)) { + return false; + } + *this->DefaultFileStream + << "# This file is a convenience file generated by\n" + << "# CMAKE_NMC_DEFAULT_BUILD_FILE_CONFIG.\n\n" + << "include " << GetNinjaImplFilename(this->DefaultFileConfig) << "\n\n"; + } + + // 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()) { + // Open impl file. + if (!this->OpenFileStream(this->ImplFileStreams[config], + GetNinjaImplFilename(config))) { + return false; + } + + // Write a comment about this file. + *this->ImplFileStreams[config] + << "# This file contains build statements specific to the \"" << config + << "\"\n# configuration.\n\n"; + + // Open config file. + if (!this->OpenFileStream(this->ConfigFileStreams[config], + GetNinjaConfigFilename(config))) { + return false; + } + + // Write a comment about this file. + *this->ConfigFileStreams[config] + << "# This file contains aliases specific to the \"" << config + << "\"\n# configuration.\n\n" + << "include " << GetNinjaImplFilename(config) << "\n\n"; + } + + return true; +} + +void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams() +{ + if (this->CommonFileStream) { + this->CommonFileStream.reset(); + } else { + cmSystemTools::Error("Common file stream was not open."); + } + + if (this->DefaultFileStream) { + this->DefaultFileStream.reset(); + } // No error if it wasn't open + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + if (this->ImplFileStreams[config]) { + this->ImplFileStreams[config].reset(); + } else { + cmSystemTools::Error( + cmStrCat("Impl file stream for \"", config, "\" was not open.")); + } + 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(GetNinjaConfigFilename(config)); +} + +std::string cmGlobalNinjaMultiGenerator::GetNinjaImplFilename( + const std::string& config) +{ + return cmStrCat("CMakeFiles/impl-", config, + cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION); +} + +std::string cmGlobalNinjaMultiGenerator::GetNinjaConfigFilename( + 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(GetNinjaImplFilename(config))); + outputs.push_back(this->NinjaOutputPath(GetNinjaConfigFilename(config))); + } + if (!this->DefaultFileConfig.empty()) { + 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::InspectConfigTypeVariables() +{ + auto configsVec = this->Makefiles.front()->GetGeneratorConfigs(); + std::set<std::string> configs(configsVec.cbegin(), configsVec.cend()); + + this->DefaultFileConfig = this->Makefiles.front()->GetSafeDefinition( + "CMAKE_NMC_DEFAULT_BUILD_FILE_CONFIG"); + if (!this->DefaultFileConfig.empty() && + !configs.count(this->DefaultFileConfig)) { + std::ostringstream msg; + msg << "The configuration specified by " + << "CMAKE_NMC_DEFAULT_BUILD_FILE_CONFIG (" << this->DefaultFileConfig + << ") is not present in CMAKE_CONFIGURATION_TYPES"; + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + msg.str()); + return false; + } + + std::vector<std::string> crossConfigsVec; + cmExpandList( + this->Makefiles.front()->GetSafeDefinition("CMAKE_NMC_CROSS_CONFIGS"), + crossConfigsVec); + auto crossConfigs = ListSubsetWithAll(configs, crossConfigsVec); + if (!crossConfigs) { + std::ostringstream msg; + msg << "CMAKE_NMC_CROSS_CONFIGS is not a subset of " + << "CMAKE_CONFIGURATION_TYPES"; + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + msg.str()); + return false; + } + this->CrossConfigs = *crossConfigs; + + auto defaultConfigsString = + this->Makefiles.front()->GetSafeDefinition("CMAKE_NMC_DEFAULT_CONFIGS"); + if (defaultConfigsString.empty()) { + defaultConfigsString = this->DefaultFileConfig; + } + if (!defaultConfigsString.empty() && + (this->DefaultFileConfig.empty() || this->CrossConfigs.empty())) { + std::ostringstream msg; + msg << "CMAKE_NMC_DEFAULT_CONFIGS cannot be used without " + << "CMAKE_NMC_DEFAULT_BUILD_FILE_CONFIG or " + << "CMAKE_NMC_CROSS_CONFIGS"; + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + msg.str()); + return false; + } + + std::vector<std::string> defaultConfigsVec; + cmExpandList(defaultConfigsString, defaultConfigsVec); + if (!this->DefaultFileConfig.empty()) { + auto defaultConfigs = ListSubsetWithAll( + this->GetCrossConfigs(this->DefaultFileConfig), defaultConfigsVec); + if (!defaultConfigs) { + std::ostringstream msg; + msg << "CMAKE_NMC_DEFAULT_CONFIGS is not a subset of " + << "CMAKE_NMC_CROSS_CONFIGS"; + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + msg.str()); + return false; + } + this->DefaultConfigs = *defaultConfigs; + } + + return true; +} diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 244e9fd..3b45249 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -15,6 +15,8 @@ #include <utility> #include <vector> +#include <cm/optional> + #include "cm_codecvt.hxx" #include "cmGeneratedFileStream.h" @@ -22,6 +24,7 @@ #include "cmGlobalGeneratorFactory.h" #include "cmNinjaTypes.h" #include "cmPolicies.h" +#include "cmStringAlgorithms.h" class cmCustomCommand; class cmGeneratorTarget; @@ -73,10 +76,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 +114,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 +155,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 +210,24 @@ public: } const char* GetCleanTargetName() const override { return "clean"; } - cmGeneratedFileStream* GetBuildFileStream() const + virtual cmGeneratedFileStream* GetImplFileStream( + const std::string& /*config*/) const + { + return this->BuildFileStream.get(); + } + + virtual cmGeneratedFileStream* GetConfigFileStream( + const std::string& /*config*/) const + { + return this->BuildFileStream.get(); + } + + virtual cmGeneratedFileStream* GetDefaultFileStream() const + { + return this->BuildFileStream.get(); + } + + virtual cmGeneratedFileStream* GetCommonFileStream() const { return this->BuildFileStream.get(); } @@ -231,12 +254,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 +288,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 +312,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 +362,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 +387,52 @@ 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; + + std::set<std::string> GetCrossConfigs(const std::string& config) const; + protected: void Generate() override; bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; } + virtual bool OpenBuildFileStreams(); + virtual void CloseBuildFileStreams(); + + bool OpenFileStream(std::unique_ptr<cmGeneratedFileStream>& stream, + const std::string& name); + + static cm::optional<std::set<std::string>> ListSubsetWithAll( + const std::set<std::string>& defaults, + const std::vector<std::string>& items); + + virtual bool InspectConfigTypeVariables() { return true; } + + std::set<std::string> CrossConfigs; + std::set<std::string> DefaultConfigs; + std::string DefaultFileConfig; + private: std::string GetEditCacheCommand() const override; bool FindMakeProgram(cmMakefile* mf) override; @@ -348,13 +441,11 @@ private: cmMakefile* mf) const override; bool CheckFortran(cmMakefile* mf) const; - bool OpenBuildFileStream(); - void CloseBuildFileStream(); - void CloseCompileCommandsStream(); bool OpenRulesFileStream(); void CloseRulesFileStream(); + void CleanMetaData(); /// Write the common disclaimer text at the top of each build file. void WriteDisclaimer(std::ostream& os); @@ -395,9 +486,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,10 +504,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; + TargetAliasMap DefaultTargetAliases; /// the local cache for calls to ConvertToNinjaPath mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache; @@ -431,6 +523,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 +533,117 @@ 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* GetImplFileStream( + const std::string& config) const override + { + return this->ImplFileStreams.at(config).get(); + } + + cmGeneratedFileStream* GetConfigFileStream( + const std::string& config) const override + { + return this->ConfigFileStreams.at(config).get(); + } + + cmGeneratedFileStream* GetDefaultFileStream() const override + { + return this->DefaultFileStream.get(); + } + + cmGeneratedFileStream* GetCommonFileStream() const override + { + return this->CommonFileStream.get(); + } + + void AppendNinjaFileArgument(GeneratedMakeCommand& command, + const std::string& config) const override; + + static std::string GetNinjaImplFilename(const std::string& config); + static std::string GetNinjaConfigFilename(const std::string& config); + + void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override; + + void GetQtAutoGenConfigs(std::vector<std::string>& configs) const override; + + bool InspectConfigTypeVariables() override; + +protected: + bool OpenBuildFileStreams() override; + void CloseBuildFileStreams() override; + +private: + std::map<std::string, std::unique_ptr<cmGeneratedFileStream>> + ImplFileStreams; + std::map<std::string, std::unique_ptr<cmGeneratedFileStream>> + ConfigFileStreams; + std::unique_ptr<cmGeneratedFileStream> CommonFileStream; + std::unique_ptr<cmGeneratedFileStream> DefaultFileStream; }; #endif // ! cmGlobalNinjaGenerator_h diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 4c2d69f..90c9ef0 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; @@ -885,33 +892,48 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule( // Keep track of targets already listed. std::set<std::string> emittedTargets; + std::set<std::string> utility_targets; + std::set<std::string> globals_targets; + std::set<std::string> project_targets; // 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) || (type == cmStateEnums::SHARED_LIBRARY) || (type == cmStateEnums::MODULE_LIBRARY) || - (type == cmStateEnums::OBJECT_LIBRARY) || - (type == cmStateEnums::GLOBAL_TARGET) || - (type == cmStateEnums::UTILITY)) { - std::string const& name = target->GetName(); - if (emittedTargets.insert(name).second) { - path = cmStrCat("... ", name); - lg->AppendEcho(commands, path); - } + (type == cmStateEnums::OBJECT_LIBRARY)) { + project_targets.insert(target->GetName()); + } else if (type == cmStateEnums::GLOBAL_TARGET) { + globals_targets.insert(target->GetName()); + } else if (type == cmStateEnums::UTILITY) { + utility_targets.insert(target->GetName()); } } } } + + for (std::string const& name : globals_targets) { + path = cmStrCat("... ", name); + lg->AppendEcho(commands, path); + } + for (std::string const& name : utility_targets) { + path = cmStrCat("... ", name); + lg->AppendEcho(commands, path); + } + for (std::string const& name : project_targets) { + path = cmStrCat("... ", name); + lg->AppendEcho(commands, path); + } + for (std::string const& o : lg->GetLocalHelp()) { path = cmStrCat("... ", o); lg->AppendEcho(commands, path); diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 79db30e..340a7ef 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 f6472ab..ccb6c50 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; } @@ -355,6 +375,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; } @@ -448,6 +473,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( this->GeneratorToolsetVersion = value; return true; } + if (key == "VCTargetsPath") { + this->CustomVCTargetsPath = value; + ConvertToWindowsSlashes(this->CustomVCTargetsPath); + return true; + } return false; } @@ -556,10 +586,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() @@ -590,7 +621,7 @@ void cmGlobalVisualStudio10Generator::Generate() "To avoid this problem CMake must use a full path for this file " "which then triggers the VS 10 property dialog bug."; /* clang-format on */ - lg->IssueMessage(MessageType::WARNING, e.str().c_str()); + lg->IssueMessage(MessageType::WARNING, e.str()); } } @@ -609,6 +640,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(); @@ -803,7 +842,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) // Prepare the work directory. if (!cmSystemTools::MakeDirectory(wd)) { std::string e = "Failed to make directory:\n " + wd; - mf->IssueMessage(MessageType::FATAL_ERROR, e.c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -924,7 +963,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) if (ret != 0) { e << "Exit code: " << ret << "\n"; } - mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -1098,8 +1137,7 @@ std::string cmGlobalVisualStudio10Generator::GenerateRuleFile( // Hide them away under the CMakeFiles directory. std::string ruleDir = cmStrCat( this->GetCMakeInstance()->GetHomeOutputDirectory(), "/CMakeFiles/", - cmSystemTools::ComputeStringMD5( - cmSystemTools::GetFilenamePath(output).c_str())); + cmSystemTools::ComputeStringMD5(cmSystemTools::GetFilenamePath(output))); std::string ruleFile = cmStrCat(ruleDir, '/', cmSystemTools::GetFilenameName(output), ".rule"); return ruleFile; @@ -1293,7 +1331,7 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( e << "JSON flag table \"" << filename << "\" could not be loaded.\n"; /* clang-format on */ - mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); } return ret; } diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 56f1193..f659ff3 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; @@ -157,6 +164,7 @@ protected: std::string GeneratorToolset; std::string GeneratorToolsetVersion; std::string GeneratorToolsetHostArchitecture; + std::string GeneratorToolsetCustomVCTargetsDir; std::string GeneratorToolsetCuda; std::string GeneratorToolsetCudaCustomDir; std::string DefaultPlatformToolset; @@ -209,6 +217,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 4b74ef1..a385375 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 f8cce18..5f1ff73 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 d9702c9..5a27994 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 53b7091..bdd40ff 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 cd48474..f549b6a 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 6e12d3e..ccc2917 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/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index e8e9ece..ec1380b 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -87,7 +87,7 @@ void cmGlobalVisualStudio71Generator::WriteSolutionConfigurations( // the libraries it uses are also done here void cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout, const std::string& dspname, - const char* dir, + const std::string& dir, cmGeneratorTarget const* t) { // check to see if this is a fortran build @@ -109,7 +109,7 @@ void cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout, std::string guid = this->GetGUID(dspname); fout << project << dspname << "\", \"" << this->ConvertToSolutionPath(dir) - << (dir[0] ? "\\" : "") << dspname << ext << "\", \"{" << guid + << (!dir.empty() ? "\\" : "") << dspname << ext << "\", \"{" << guid << "}\"\n"; fout << "\tProjectSection(ProjectDependencies) = postProject\n"; this->WriteProjectDepends(fout, dspname, dir, t); @@ -138,7 +138,7 @@ void cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout, // Note, that dependencies from executables to // the libraries it uses are also done here void cmGlobalVisualStudio71Generator::WriteProjectDepends( - std::ostream& fout, const std::string&, const char*, + std::ostream& fout, const std::string&, const std::string&, cmGeneratorTarget const* target) { VSDependSet const& depends = this->VSTargetDepends[target]; @@ -156,7 +156,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends( // Write a dsp file into the SLN file, Note, that dependencies from // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator::WriteExternalProject( - std::ostream& fout, const std::string& name, const char* location, + std::ostream& fout, const std::string& name, const std::string& location, const char* typeGuid, const std::set<BT<std::string>>& depends) { fout << "Project(\"{" diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index 85755af..61a2f6f 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -22,9 +22,10 @@ protected: virtual void WriteSolutionConfigurations( std::ostream& fout, std::vector<std::string> const& configs); void WriteProject(std::ostream& fout, const std::string& name, - const char* path, const cmGeneratorTarget* t) override; + const std::string& path, + const cmGeneratorTarget* t) override; void WriteProjectDepends(std::ostream& fout, const std::string& name, - const char* path, + const std::string& path, cmGeneratorTarget const* t) override; void WriteProjectConfigurations( std::ostream& fout, const std::string& name, @@ -32,7 +33,7 @@ protected: const std::set<std::string>& configsPartOfDefaultBuild, const std::string& platformMapping = "") override; void WriteExternalProject(std::ostream& fout, const std::string& name, - const char* path, const char* typeGuid, + const std::string& path, const char* typeGuid, const std::set<BT<std::string>>& depends) override; // Folders are not supported by VS 7.1. diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 40b214c..9799124 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> @@ -184,7 +186,7 @@ std::string cmGlobalVisualStudio7Generator::FindDevEnvCommand() } const char* cmGlobalVisualStudio7Generator::ExternalProjectType( - const char* location) + const std::string& location) { std::string extension = cmSystemTools::GetFilenameLastExtension(location); if (extension == ".vbproj") { @@ -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())); } } @@ -345,8 +346,8 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( if (expath) { std::set<std::string> allConfigurations(configs.begin(), configs.end()); const char* mapping = target->GetProperty("VS_PLATFORM_MAPPING"); - this->WriteProjectConfigurations(fout, target->GetName().c_str(), - *target, configs, allConfigurations, + this->WriteProjectConfigurations(fout, target->GetName(), *target, + configs, allConfigurations, mapping ? mapping : ""); } else { const std::set<std::string>& configsPartOfDefaultBuild = @@ -379,7 +380,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( std::string project = target->GetName(); std::string location = expath; - this->WriteExternalProject(fout, project.c_str(), location.c_str(), + this->WriteExternalProject(fout, project, location, target->GetProperty("VS_PROJECT_TYPE"), target->GetUtilities()); written = true; @@ -388,11 +389,11 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( if (vcprojName) { cmLocalGenerator* lg = target->GetLocalGenerator(); std::string dir = lg->GetCurrentBinaryDirectory(); - dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir.c_str()); + dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir); if (dir == ".") { dir.clear(); // msbuild cannot handle ".\" prefix } - this->WriteProject(fout, vcprojName, dir.c_str(), target); + this->WriteProject(fout, vcprojName, dir, target); written = true; } } @@ -482,7 +483,7 @@ void cmGlobalVisualStudio7Generator::WriteFoldersContent(std::ostream& fout) } std::string cmGlobalVisualStudio7Generator::ConvertToSolutionPath( - const char* path) + const std::string& path) { // Convert to backslashes. Do not use ConvertToOutputPath because // we will add quoting ourselves, and we know these projects always diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 7a9fcef..699f091 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; @@ -107,16 +110,17 @@ protected: std::string const& GetDevEnvCommand(); virtual std::string FindDevEnvCommand(); - static const char* ExternalProjectType(const char* location); + static const char* ExternalProjectType(const std::string& location); virtual void OutputSLNFile(cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators); virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) = 0; virtual void WriteProject(std::ostream& fout, const std::string& name, - const char* path, const cmGeneratorTarget* t) = 0; + const std::string& path, + const cmGeneratorTarget* t) = 0; virtual void WriteProjectDepends(std::ostream& fout, const std::string& name, - const char* path, + const std::string& path, cmGeneratorTarget const* t) = 0; virtual void WriteProjectConfigurations( std::ostream& fout, const std::string& name, @@ -138,10 +142,10 @@ protected: OrderedTargetDependSet const& projectTargets); virtual void WriteExternalProject( - std::ostream& fout, const std::string& name, const char* path, + std::ostream& fout, const std::string& name, const std::string& path, const char* typeGuid, const std::set<BT<std::string>>& dependencies) = 0; - std::string ConvertToSolutionPath(const char* path); + std::string ConvertToSolutionPath(const std::string& path); std::set<std::string> IsPartOfDefaultBuild( std::vector<std::string> const& configs, diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 8e6125b..c0551f7 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); } @@ -304,7 +307,7 @@ bool cmGlobalVisualStudio8Generator::ComputeTargetDepends() } void cmGlobalVisualStudio8Generator::WriteProjectDepends( - std::ostream& fout, const std::string&, const char*, + std::ostream& fout, const std::string&, const std::string&, cmGeneratorTarget const* gt) { TargetDependSet const& unordered = this->GetTargetDirectDepends(gt); diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 352bc3c..8f8e33b 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -74,7 +74,7 @@ protected: const std::string& platformMapping = "") override; bool ComputeTargetDepends() override; void WriteProjectDepends(std::ostream& fout, const std::string& name, - const char* path, + const std::string& path, const cmGeneratorTarget* t) override; bool UseFolderProperty() const override; diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index 6e61d26..9f73c15 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 7bebfd6..53318a6 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 ed0cba7..012a77c 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()); } } @@ -307,7 +308,7 @@ void cmGlobalVisualStudioGenerator::CallVisualStudioMacro( if (!dir.empty()) { std::string macrosFile = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME; std::string nextSubkeyName; - if (cmSystemTools::FileExists(macrosFile.c_str()) && + if (cmSystemTools::FileExists(macrosFile) && IsVisualStudioMacrosFileRegistered( macrosFile, this->GetUserMacrosRegKeyBase(), nextSubkeyName)) { if (m == MacroReload) { @@ -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()); } } } @@ -592,7 +593,7 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, std::string filepath; std::string filepathname; std::string filepathpath; - if (cmSystemTools::FileExists(fullname.c_str())) { + if (cmSystemTools::FileExists(fullname)) { filename = cmSystemTools::GetFilenameName(fullname); filepath = cmSystemTools::GetFilenamePath(fullname); filepathname = cmSystemTools::GetFilenameName(filepath); @@ -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 @@ -926,7 +917,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( std::string objFile = it; // replace $(ConfigurationName) in the object names cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(), - configName.c_str()); + configName); if (cmHasLiteralSuffix(objFile, ".obj")) { fout << objFile << "\n"; } @@ -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/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 4f2007f..29a5c2c 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -150,6 +150,8 @@ public: bool Open(const std::string& bindir, const std::string& projectName, bool dryRun) override; + bool IsVisualStudio() const override { return true; } + protected: cmGlobalVisualStudioGenerator(cmake* cm, std::string const& platformInGeneratorName); diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index a371633..13ae32a 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 466816b..abb6095 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 64ace13..c0daf8a 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 3002b2a..3d5c9c4 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,27 +525,27 @@ 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)) { + bool isGenerateProject = isTopLevel || !generateTopLevelProjectOnly; + if (regenerate && isGenerateProject) { this->CreateReRunCMakeFile(root, gens); 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; } @@ -554,17 +559,18 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // run the depend check makefile as a post build rule // this will make sure that when the next target is built // things are up-to-date - if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (isGenerateProject && + 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 +582,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 +1099,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 +1370,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 +1466,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 +2359,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); @@ -2365,8 +2368,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, int minor; int patch; - // VERSION -> current_version - gtgt->GetTargetVersion(false, major, minor, patch); + // OSX_CURRENT_VERSION or VERSION -> current_version + gtgt->GetTargetVersionFallback("OSX_CURRENT_VERSION", "VERSION", major, + minor, patch); std::ostringstream v; // Xcode always wants at least 1.0.0 or nothing @@ -2376,8 +2380,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("DYLIB_CURRENT_VERSION", this->CreateString(v.str())); - // SOVERSION -> compatibility_version - gtgt->GetTargetVersion(true, major, minor, patch); + // OSX_COMPATIBILITY_VERSION or SOVERSION -> compatibility_version + gtgt->GetTargetVersionFallback("OSX_COMPATIBILITY_VERSION", "SOVERSION", + major, minor, patch); std::ostringstream vso; // Xcode always wants at least 1.0.0 or nothing @@ -2834,7 +2839,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 +2854,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 +2885,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 +3421,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 af905d0..df68f80 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 e0d545d..f48789a 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 9c3051f..578660d 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 71326d2..b53319f 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 170aea1..b408f72 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 fa1e8bc..86a0921 100644 --- a/Source/cmIncludeExternalMSProjectCommand.cxx +++ b/Source/cmIncludeExternalMSProjectCommand.cxx @@ -77,28 +77,27 @@ bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args, if (!customGuid.empty()) { std::string guidVariable = utility_name + "_GUID_CMAKE"; - mf.GetCMakeInstance()->AddCacheEntry(guidVariable.c_str(), - customGuid.c_str(), "Stored GUID", + mf.GetCMakeInstance()->AddCacheEntry(guidVariable, customGuid.c_str(), + "Stored GUID", cmStateEnums::INTERNAL); } // 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/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 0c52cc5..c67358f 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -85,7 +85,7 @@ public: std::string DefaultComponentName; }; -cmInstallTargetGenerator* CreateInstallTargetGenerator( +std::unique_ptr<cmInstallTargetGenerator> CreateInstallTargetGenerator( cmTarget& target, const cmInstallCommandArguments& args, bool impLib, cmListFileBacktrace const& backtrace, const std::string& destination, bool forceOpt = false, bool namelink = false) @@ -93,18 +93,17 @@ cmInstallTargetGenerator* CreateInstallTargetGenerator( cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(target.GetMakefile()); target.SetHaveInstallRule(true); - const char* component = namelink ? args.GetNamelinkComponent().c_str() - : args.GetComponent().c_str(); - auto g = new cmInstallTargetGenerator( - target.GetName(), destination.c_str(), impLib, - args.GetPermissions().c_str(), args.GetConfigurations(), component, - message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt, - backtrace); - target.AddInstallGenerator(g); + const std::string& component = + namelink ? args.GetNamelinkComponent() : args.GetComponent(); + auto g = cm::make_unique<cmInstallTargetGenerator>( + target.GetName(), destination, impLib, args.GetPermissions(), + args.GetConfigurations(), component, message, args.GetExcludeFromAll(), + args.GetOptional() || forceOpt, backtrace); + target.AddInstallGenerator(g.get()); return g; } -cmInstallTargetGenerator* CreateInstallTargetGenerator( +std::unique_ptr<cmInstallTargetGenerator> CreateInstallTargetGenerator( cmTarget& target, const cmInstallCommandArguments& args, bool impLib, cmListFileBacktrace const& backtrace, bool forceOpt = false, bool namelink = false) @@ -114,20 +113,20 @@ cmInstallTargetGenerator* CreateInstallTargetGenerator( namelink); } -cmInstallFilesGenerator* CreateInstallFilesGenerator( +std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator( cmMakefile* mf, const std::vector<std::string>& absFiles, const cmInstallCommandArguments& args, bool programs, const std::string& destination) { cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(mf); - return new cmInstallFilesGenerator( - absFiles, destination.c_str(), programs, args.GetPermissions().c_str(), - args.GetConfigurations(), args.GetComponent().c_str(), message, - args.GetExcludeFromAll(), args.GetRename().c_str(), args.GetOptional()); + return cm::make_unique<cmInstallFilesGenerator>( + absFiles, destination, programs, args.GetPermissions(), + args.GetConfigurations(), args.GetComponent(), message, + args.GetExcludeFromAll(), args.GetRename(), args.GetOptional()); } -cmInstallFilesGenerator* CreateInstallFilesGenerator( +std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator( cmMakefile* mf, const std::vector<std::string>& absFiles, const cmInstallCommandArguments& args, bool programs) { @@ -196,13 +195,15 @@ bool HandleScriptMode(std::vector<std::string> const& args, status.SetError("given a directory as value of SCRIPT argument."); return false; } - helper.Makefile->AddInstallGenerator(new cmInstallScriptGenerator( - script.c_str(), false, component.c_str(), exclude_from_all)); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallScriptGenerator>(script, false, component, + exclude_from_all)); } else if (doing_code) { doing_code = false; std::string const& code = arg; - helper.Makefile->AddInstallGenerator(new cmInstallScriptGenerator( - code.c_str(), true, component.c_str(), exclude_from_all)); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallScriptGenerator>(code, true, component, + exclude_from_all)); } } @@ -449,16 +450,16 @@ bool HandleTargetsMode(std::vector<std::string> const& args, for (cmTarget* ti : targets) { // Handle each target type. cmTarget& target = *ti; - cmInstallTargetGenerator* archiveGenerator = nullptr; - cmInstallTargetGenerator* libraryGenerator = nullptr; - cmInstallTargetGenerator* namelinkGenerator = nullptr; - cmInstallTargetGenerator* runtimeGenerator = nullptr; - cmInstallTargetGenerator* objectGenerator = nullptr; - cmInstallTargetGenerator* frameworkGenerator = nullptr; - cmInstallTargetGenerator* bundleGenerator = nullptr; - cmInstallFilesGenerator* privateHeaderGenerator = nullptr; - cmInstallFilesGenerator* publicHeaderGenerator = nullptr; - cmInstallFilesGenerator* resourceGenerator = nullptr; + std::unique_ptr<cmInstallTargetGenerator> archiveGenerator; + std::unique_ptr<cmInstallTargetGenerator> libraryGenerator; + std::unique_ptr<cmInstallTargetGenerator> namelinkGenerator; + std::unique_ptr<cmInstallTargetGenerator> runtimeGenerator; + std::unique_ptr<cmInstallTargetGenerator> objectGenerator; + std::unique_ptr<cmInstallTargetGenerator> frameworkGenerator; + std::unique_ptr<cmInstallTargetGenerator> bundleGenerator; + std::unique_ptr<cmInstallFilesGenerator> privateHeaderGenerator; + std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator; + std::unique_ptr<cmInstallFilesGenerator> resourceGenerator; // Track whether this is a namelink-only rule. bool namelinkOnly = false; @@ -485,7 +486,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, runtimeGenerator = CreateInstallTargetGenerator( target, runtimeArgs, false, helper.Makefile->GetBacktrace()); } - if ((archiveGenerator == nullptr) && (runtimeGenerator == nullptr)) { + if (!archiveGenerator && !runtimeGenerator) { archiveGenerator = CreateInstallTargetGenerator( target, archiveArgs, true, helper.Makefile->GetBacktrace(), helper.GetArchiveDestination(nullptr)); @@ -712,43 +713,18 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } } - // Keep track of whether we're installing anything in each category - installsArchive = installsArchive || archiveGenerator != nullptr; - installsLibrary = installsLibrary || libraryGenerator != nullptr; - installsNamelink = installsNamelink || namelinkGenerator != nullptr; - installsRuntime = installsRuntime || runtimeGenerator != nullptr; - installsObject = installsObject || objectGenerator != nullptr; - installsFramework = installsFramework || frameworkGenerator != nullptr; - installsBundle = installsBundle || bundleGenerator != nullptr; - installsPrivateHeader = - installsPrivateHeader || privateHeaderGenerator != nullptr; - installsPublicHeader = - installsPublicHeader || publicHeaderGenerator != nullptr; - installsResource = installsResource || resourceGenerator; - - helper.Makefile->AddInstallGenerator(archiveGenerator); - helper.Makefile->AddInstallGenerator(libraryGenerator); - helper.Makefile->AddInstallGenerator(namelinkGenerator); - helper.Makefile->AddInstallGenerator(runtimeGenerator); - helper.Makefile->AddInstallGenerator(objectGenerator); - helper.Makefile->AddInstallGenerator(frameworkGenerator); - helper.Makefile->AddInstallGenerator(bundleGenerator); - helper.Makefile->AddInstallGenerator(privateHeaderGenerator); - helper.Makefile->AddInstallGenerator(publicHeaderGenerator); - helper.Makefile->AddInstallGenerator(resourceGenerator); - // Add this install rule to an export if one was specified and // this is not a namelink-only rule. if (!exports.empty() && !namelinkOnly) { auto te = cm::make_unique<cmTargetExport>(); te->TargetName = target.GetName(); - te->ArchiveGenerator = archiveGenerator; - te->BundleGenerator = bundleGenerator; - te->FrameworkGenerator = frameworkGenerator; - te->HeaderGenerator = publicHeaderGenerator; - te->LibraryGenerator = libraryGenerator; - te->RuntimeGenerator = runtimeGenerator; - te->ObjectsGenerator = objectGenerator; + te->ArchiveGenerator = archiveGenerator.get(); + te->BundleGenerator = bundleGenerator.get(); + te->FrameworkGenerator = frameworkGenerator.get(); + te->HeaderGenerator = publicHeaderGenerator.get(); + te->LibraryGenerator = libraryGenerator.get(); + te->RuntimeGenerator = runtimeGenerator.get(); + te->ObjectsGenerator = objectGenerator.get(); te->InterfaceIncludeDirectories = cmJoin(includesArgs.GetIncludeDirs(), ";"); @@ -756,6 +732,29 @@ bool HandleTargetsMode(std::vector<std::string> const& args, ->GetExportSets()[exports] .AddTargetExport(std::move(te)); } + + // Keep track of whether we're installing anything in each category + installsArchive = installsArchive || archiveGenerator; + installsLibrary = installsLibrary || libraryGenerator; + installsNamelink = installsNamelink || namelinkGenerator; + installsRuntime = installsRuntime || runtimeGenerator; + installsObject = installsObject || objectGenerator; + installsFramework = installsFramework || frameworkGenerator; + installsBundle = installsBundle || bundleGenerator; + installsPrivateHeader = installsPrivateHeader || privateHeaderGenerator; + installsPublicHeader = installsPublicHeader || publicHeaderGenerator; + installsResource = installsResource || resourceGenerator; + + helper.Makefile->AddInstallGenerator(std::move(archiveGenerator)); + helper.Makefile->AddInstallGenerator(std::move(libraryGenerator)); + helper.Makefile->AddInstallGenerator(std::move(namelinkGenerator)); + helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator)); + helper.Makefile->AddInstallGenerator(std::move(objectGenerator)); + helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator)); + helper.Makefile->AddInstallGenerator(std::move(bundleGenerator)); + helper.Makefile->AddInstallGenerator(std::move(privateHeaderGenerator)); + helper.Makefile->AddInstallGenerator(std::move(publicHeaderGenerator)); + helper.Makefile->AddInstallGenerator(std::move(resourceGenerator)); } // Tell the global generator about any installation component names @@ -943,7 +942,7 @@ bool HandleDirectoryMode(std::vector<std::string> const& args, bool exclude_from_all = false; bool message_never = false; std::vector<std::string> dirs; - const char* destination = nullptr; + const std::string* destination = nullptr; std::string permissions_file; std::string permissions_dir; std::vector<std::string> configurations; @@ -1102,7 +1101,7 @@ bool HandleDirectoryMode(std::vector<std::string> const& args, } else if (doing == DoingConfigurations) { configurations.push_back(args[i]); } else if (doing == DoingDestination) { - destination = args[i].c_str(); + destination = &args[i]; doing = DoingNone; } else if (doing == DoingType) { if (allowedTypes.count(args[i]) == 0) { @@ -1188,7 +1187,7 @@ bool HandleDirectoryMode(std::vector<std::string> const& args, return false; } destinationStr = helper.GetDestinationForType(nullptr, type); - destination = destinationStr.c_str(); + destination = &destinationStr; } else if (!type.empty()) { status.SetError(cmStrCat(args[0], " given both TYPE and DESTINATION " @@ -1200,10 +1199,10 @@ bool HandleDirectoryMode(std::vector<std::string> const& args, cmInstallGenerator::SelectMessageLevel(helper.Makefile, message_never); // Create the directory install generator. - helper.Makefile->AddInstallGenerator(new cmInstallDirectoryGenerator( - dirs, destination, permissions_file.c_str(), permissions_dir.c_str(), - configurations, component.c_str(), message, exclude_from_all, - literal_args.c_str(), optional)); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallDirectoryGenerator>( + dirs, *destination, permissions_file, permissions_dir, configurations, + component, message, exclude_from_all, literal_args, optional)); // Tell the global generator about any installation component names // specified. @@ -1291,12 +1290,11 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args, cmInstallGenerator::SelectMessageLevel(helper.Makefile); // Create the export install generator. - cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( - &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), - ica.GetConfigurations(), ica.GetComponent().c_str(), message, - ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld, - true); - helper.Makefile->AddInstallGenerator(exportGenerator); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallExportGenerator>( + &exportSet, ica.GetDestination(), ica.GetPermissions(), + ica.GetConfigurations(), ica.GetComponent(), message, + ica.GetExcludeFromAll(), fname, name_space, exportOld, true)); return true; #else @@ -1405,12 +1403,11 @@ bool HandleExportMode(std::vector<std::string> const& args, cmInstallGenerator::SelectMessageLevel(helper.Makefile); // Create the export install generator. - cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( - &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), - ica.GetConfigurations(), ica.GetComponent().c_str(), message, - ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld, - false); - helper.Makefile->AddInstallGenerator(exportGenerator); + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallExportGenerator>( + &exportSet, ica.GetDestination(), ica.GetPermissions(), + ica.GetConfigurations(), ica.GetComponent(), message, + ica.GetExcludeFromAll(), fname, name_space, exportOld, false)); return true; } diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index 259c7f7..175e7cf 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallDirectoryGenerator.h" +#include <utility> + #include "cmGeneratorExpression.h" #include "cmInstallType.h" #include "cmLocalGenerator.h" @@ -10,18 +12,18 @@ #include "cmSystemTools.h" cmInstallDirectoryGenerator::cmInstallDirectoryGenerator( - std::vector<std::string> const& dirs, const char* dest, - const char* file_permissions, const char* dir_permissions, - std::vector<std::string> const& configurations, const char* component, - MessageLevel message, bool exclude_from_all, const char* literal_args, + std::vector<std::string> const& dirs, std::string const& dest, + std::string file_permissions, std::string dir_permissions, + std::vector<std::string> const& configurations, std::string const& component, + MessageLevel message, bool exclude_from_all, std::string literal_args, bool optional) : cmInstallGenerator(dest, configurations, component, message, exclude_from_all) , LocalGenerator(nullptr) , Directories(dirs) - , FilePermissions(file_permissions) - , DirPermissions(dir_permissions) - , LiteralArguments(literal_args) + , FilePermissions(std::move(file_permissions)) + , DirPermissions(std::move(dir_permissions)) + , LiteralArguments(std::move(literal_args)) , Optional(optional) { // We need per-config actions if destination have generator expressions. diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h index 84c0694..bec89df 100644 --- a/Source/cmInstallDirectoryGenerator.h +++ b/Source/cmInstallDirectoryGenerator.h @@ -21,12 +21,13 @@ class cmInstallDirectoryGenerator : public cmInstallGenerator { public: cmInstallDirectoryGenerator(std::vector<std::string> const& dirs, - const char* dest, const char* file_permissions, - const char* dir_permissions, + std::string const& dest, + std::string file_permissions, + std::string dir_permissions, std::vector<std::string> const& configurations, - const char* component, MessageLevel message, - bool exclude_from_all, const char* literal_args, - bool optional = false); + std::string const& component, + MessageLevel message, bool exclude_from_all, + std::string literal_args, bool optional = false); ~cmInstallDirectoryGenerator() override; bool Compute(cmLocalGenerator* lg) override; @@ -41,11 +42,11 @@ protected: Indent indent, std::vector<std::string> const& dirs); cmLocalGenerator* LocalGenerator; - std::vector<std::string> Directories; - std::string FilePermissions; - std::string DirPermissions; - std::string LiteralArguments; - bool Optional; + std::vector<std::string> const Directories; + std::string const FilePermissions; + std::string const DirPermissions; + std::string const LiteralArguments; + bool const Optional; }; #endif diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index cba68be..2c53a28 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -18,16 +18,16 @@ #include "cmSystemTools.h" cmInstallExportGenerator::cmInstallExportGenerator( - cmExportSet* exportSet, const char* destination, - const char* file_permissions, std::vector<std::string> const& configurations, - const char* component, MessageLevel message, bool exclude_from_all, - const char* filename, const char* name_space, bool exportOld, bool android) + cmExportSet* exportSet, std::string const& destination, + std::string file_permissions, std::vector<std::string> const& configurations, + std::string const& component, MessageLevel message, bool exclude_from_all, + std::string filename, std::string name_space, bool exportOld, bool android) : cmInstallGenerator(destination, configurations, component, message, exclude_from_all) , ExportSet(exportSet) - , FilePermissions(file_permissions) - , FileName(filename) - , Namespace(name_space) + , FilePermissions(std::move(file_permissions)) + , FileName(std::move(filename)) + , Namespace(std::move(name_space)) , ExportOld(exportOld) , LocalGenerator(nullptr) { diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index f44127e..cf28b35 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -23,12 +23,12 @@ class cmLocalGenerator; class cmInstallExportGenerator : public cmInstallGenerator { public: - cmInstallExportGenerator(cmExportSet* exportSet, const char* dest, - const char* file_permissions, + cmInstallExportGenerator(cmExportSet* exportSet, std::string const& dest, + std::string file_permissions, const std::vector<std::string>& configurations, - const char* component, MessageLevel message, - bool exclude_from_all, const char* filename, - const char* name_space, bool exportOld, + std::string const& component, MessageLevel message, + bool exclude_from_all, std::string filename, + std::string name_space, bool exportOld, bool android); ~cmInstallExportGenerator() override; @@ -52,11 +52,11 @@ protected: void ComputeTempDir(); size_t GetMaxConfigLength() const; - cmExportSet* ExportSet; - std::string FilePermissions; - std::string FileName; - std::string Namespace; - bool ExportOld; + cmExportSet* const ExportSet; + std::string const FilePermissions; + std::string const FileName; + std::string const Namespace; + bool const ExportOld; cmLocalGenerator* LocalGenerator; std::string TempDir; diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index d623943..3c59f01 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -2,16 +2,21 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallFilesCommand.h" +#include <cm/memory> + #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #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 +48,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( @@ -109,17 +115,17 @@ static void CreateInstallGenerator(cmMakefile& makefile, } // Use a file install generator. - const char* no_permissions = ""; - const char* no_rename = ""; + const std::string no_permissions; + const std::string no_rename; bool no_exclude_from_all = false; std::string no_component = makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); std::vector<std::string> no_configurations; cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(&makefile); - makefile.AddInstallGenerator(new cmInstallFilesGenerator( - files, destination.c_str(), false, no_permissions, no_configurations, - no_component.c_str(), message, no_exclude_from_all, no_rename)); + makefile.AddInstallGenerator(cm::make_unique<cmInstallFilesGenerator>( + files, destination, false, no_permissions, no_configurations, no_component, + message, no_exclude_from_all, no_rename)); } /** diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index f5b69a5..ad2f84e 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallFilesGenerator.h" +#include <utility> + #include "cmGeneratorExpression.h" #include "cmInstallType.h" #include "cmStringAlgorithms.h" @@ -9,16 +11,17 @@ class cmLocalGenerator; cmInstallFilesGenerator::cmInstallFilesGenerator( - std::vector<std::string> const& files, const char* dest, bool programs, - const char* file_permissions, std::vector<std::string> const& configurations, - const char* component, MessageLevel message, bool exclude_from_all, - const char* rename, bool optional) + std::vector<std::string> const& files, std::string const& dest, + bool programs, std::string file_permissions, + std::vector<std::string> const& configurations, std::string const& component, + MessageLevel message, bool exclude_from_all, std::string rename, + bool optional) : cmInstallGenerator(dest, configurations, component, message, exclude_from_all) , LocalGenerator(nullptr) , Files(files) - , FilePermissions(file_permissions) - , Rename(rename) + , FilePermissions(std::move(file_permissions)) + , Rename(std::move(rename)) , Programs(programs) , Optional(optional) { diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index a680037..8266603 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -21,11 +21,11 @@ class cmInstallFilesGenerator : public cmInstallGenerator { public: cmInstallFilesGenerator(std::vector<std::string> const& files, - const char* dest, bool programs, - const char* file_permissions, + std::string const& dest, bool programs, + std::string file_permissions, std::vector<std::string> const& configurations, - const char* component, MessageLevel message, - bool exclude_from_all, const char* rename, + std::string const& component, MessageLevel message, + bool exclude_from_all, std::string rename, bool optional = false); ~cmInstallFilesGenerator() override; @@ -42,11 +42,11 @@ protected: std::vector<std::string> const& files); cmLocalGenerator* LocalGenerator; - std::vector<std::string> Files; - std::string FilePermissions; - std::string Rename; - bool Programs; - bool Optional; + std::vector<std::string> const Files; + std::string const FilePermissions; + std::string const Rename; + bool const Programs; + bool const Optional; }; #endif diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index ec17361..0665895 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -3,16 +3,17 @@ #include "cmInstallGenerator.h" #include <ostream> +#include <utility> #include "cmMakefile.h" #include "cmSystemTools.h" cmInstallGenerator::cmInstallGenerator( - const char* destination, std::vector<std::string> const& configurations, - const char* component, MessageLevel message, bool exclude_from_all) + std::string destination, std::vector<std::string> const& configurations, + std::string component, MessageLevel message, bool exclude_from_all) : cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations) - , Destination(destination ? destination : "") - , Component(component ? component : "") + , Destination(std::move(destination)) + , Component(std::move(component)) , Message(message) , ExcludeFromAll(exclude_from_all) { @@ -139,8 +140,8 @@ void cmInstallGenerator::AddInstallRule( os << ")\n"; } -std::string cmInstallGenerator::CreateComponentTest(const char* component, - bool exclude_from_all) +std::string cmInstallGenerator::CreateComponentTest( + const std::string& component, bool exclude_from_all) { std::string result = R"("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "x)"; result += component; @@ -158,7 +159,7 @@ void cmInstallGenerator::GenerateScript(std::ostream& os) // Begin this block of installation. std::string component_test = - this->CreateComponentTest(this->Component.c_str(), this->ExcludeFromAll); + this->CreateComponentTest(this->Component, this->ExcludeFromAll); os << indent << "if(" << component_test << ")\n"; // Generate the script possibly with per-configuration code. diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index 024027d..d786d24 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -30,9 +30,9 @@ public: MessageNever }; - cmInstallGenerator(const char* destination, + cmInstallGenerator(std::string destination, std::vector<std::string> const& configurations, - const char* component, MessageLevel message, + std::string component, MessageLevel message, bool exclude_from_all); ~cmInstallGenerator() override; @@ -65,14 +65,14 @@ public: protected: void GenerateScript(std::ostream& os) override; - std::string CreateComponentTest(const char* component, + std::string CreateComponentTest(const std::string& component, bool exclude_from_all); // Information shared by most generator types. - std::string Destination; - std::string Component; - MessageLevel Message; - bool ExcludeFromAll; + std::string const Destination; + std::string const Component; + MessageLevel const Message; + bool const ExcludeFromAll; }; #endif diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 6bb4409..be07fd4 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -2,15 +2,20 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallProgramsCommand.h" +#include <cm/memory> + #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #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 +38,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; } @@ -83,17 +89,17 @@ static void FinalAction(cmMakefile& makefile, std::string const& dest, } // Use a file install generator. - const char* no_permissions = ""; - const char* no_rename = ""; + const std::string no_permissions; + const std::string no_rename; bool no_exclude_from_all = false; std::string no_component = makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); std::vector<std::string> no_configurations; cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(&makefile); - makefile.AddInstallGenerator(new cmInstallFilesGenerator( - files, destination.c_str(), true, no_permissions, no_configurations, - no_component.c_str(), message, no_exclude_from_all, no_rename)); + makefile.AddInstallGenerator(cm::make_unique<cmInstallFilesGenerator>( + files, destination, true, no_permissions, no_configurations, no_component, + message, no_exclude_from_all, no_rename)); } /** diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index ea29455..7cdf3b4 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -3,6 +3,7 @@ #include "cmInstallScriptGenerator.h" #include <ostream> +#include <utility> #include <vector> #include "cmGeneratorExpression.h" @@ -11,13 +12,12 @@ #include "cmPolicies.h" #include "cmScriptGenerator.h" -cmInstallScriptGenerator::cmInstallScriptGenerator(const char* script, - bool code, - const char* component, - bool exclude_from_all) - : cmInstallGenerator(nullptr, std::vector<std::string>(), component, +cmInstallScriptGenerator::cmInstallScriptGenerator( + std::string script, bool code, std::string const& component, + bool exclude_from_all) + : cmInstallGenerator("", std::vector<std::string>(), component, MessageDefault, exclude_from_all) - , Script(script) + , Script(std::move(script)) , Code(code) , AllowGenex(false) { diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h index 7efa321..0a9c4ba 100644 --- a/Source/cmInstallScriptGenerator.h +++ b/Source/cmInstallScriptGenerator.h @@ -19,8 +19,9 @@ class cmLocalGenerator; class cmInstallScriptGenerator : public cmInstallGenerator { public: - cmInstallScriptGenerator(const char* script, bool code, - const char* component, bool exclude_from_all); + cmInstallScriptGenerator(std::string script, bool code, + std::string const& component, + bool exclude_from_all); ~cmInstallScriptGenerator() override; bool Compute(cmLocalGenerator* lg) override; @@ -32,8 +33,8 @@ protected: void AddScriptInstallRule(std::ostream& os, Indent indent, std::string const& script); - std::string Script; - bool Code; + std::string const Script; + bool const Code; cmLocalGenerator* LocalGenerator; bool AllowGenex; }; diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx index 8a0fefa..12bc92b 100644 --- a/Source/cmInstallSubdirectoryGenerator.cxx +++ b/Source/cmInstallSubdirectoryGenerator.cxx @@ -2,7 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallSubdirectoryGenerator.h" +#include <memory> #include <sstream> +#include <utility> #include <vector> #include "cmLocalGenerator.h" @@ -12,11 +14,11 @@ #include "cmSystemTools.h" cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator( - cmMakefile* makefile, const char* binaryDirectory, bool excludeFromAll) - : cmInstallGenerator(nullptr, std::vector<std::string>(), nullptr, - MessageDefault, excludeFromAll) + cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll) + : cmInstallGenerator("", std::vector<std::string>(), "", MessageDefault, + excludeFromAll) , Makefile(makefile) - , BinaryDirectory(binaryDirectory) + , BinaryDirectory(std::move(binaryDirectory)) { } @@ -24,7 +26,7 @@ cmInstallSubdirectoryGenerator::~cmInstallSubdirectoryGenerator() = default; bool cmInstallSubdirectoryGenerator::HaveInstall() { - for (auto generator : this->Makefile->GetInstallGenerators()) { + for (const auto& generator : this->Makefile->GetInstallGenerators()) { if (generator->HaveInstall()) { return true; } diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h index b99bdd5..f9cd0f1 100644 --- a/Source/cmInstallSubdirectoryGenerator.h +++ b/Source/cmInstallSubdirectoryGenerator.h @@ -20,7 +20,7 @@ class cmInstallSubdirectoryGenerator : public cmInstallGenerator { public: cmInstallSubdirectoryGenerator(cmMakefile* makefile, - const char* binaryDirectory, + std::string binaryDirectory, bool excludeFromAll); ~cmInstallSubdirectoryGenerator() override; @@ -33,8 +33,8 @@ public: protected: void GenerateScript(std::ostream& os) override; - cmMakefile* Makefile; - std::string BinaryDirectory; + cmMakefile* const Makefile; + std::string const BinaryDirectory; cmLocalGenerator* LocalGenerator; }; diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index aa92fa7..e05daa8 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -25,15 +25,15 @@ #include "cmake.h" cmInstallTargetGenerator::cmInstallTargetGenerator( - std::string targetName, const char* dest, bool implib, - const char* file_permissions, std::vector<std::string> const& configurations, - const char* component, MessageLevel message, bool exclude_from_all, + std::string targetName, std::string const& dest, bool implib, + std::string file_permissions, std::vector<std::string> const& configurations, + std::string const& component, MessageLevel message, bool exclude_from_all, bool optional, cmListFileBacktrace backtrace) : cmInstallGenerator(dest, configurations, component, message, exclude_from_all) , TargetName(std::move(targetName)) , Target(nullptr) - , FilePermissions(file_permissions) + , FilePermissions(std::move(file_permissions)) , ImportLibrary(implib) , Optional(optional) , Backtrace(std::move(backtrace)) @@ -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/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 8730454..e21001f 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -23,11 +23,11 @@ class cmInstallTargetGenerator : public cmInstallGenerator { public: cmInstallTargetGenerator( - std::string targetName, const char* dest, bool implib, - const char* file_permissions, - std::vector<std::string> const& configurations, const char* component, - MessageLevel message, bool exclude_from_all, bool optional, - cmListFileBacktrace backtrace = cmListFileBacktrace()); + std::string targetName, std::string const& dest, bool implib, + std::string file_permissions, + std::vector<std::string> const& configurations, + std::string const& component, MessageLevel message, bool exclude_from_all, + bool optional, cmListFileBacktrace backtrace = cmListFileBacktrace()); ~cmInstallTargetGenerator() override; /** Select the policy for installing shared library linkable name @@ -106,13 +106,13 @@ protected: const std::string& toDestDirPath); void IssueCMP0095Warning(const std::string& unescapedRpath); - std::string TargetName; + std::string const TargetName; cmGeneratorTarget* Target; - std::string FilePermissions; + std::string const FilePermissions; NamelinkModeType NamelinkMode; - bool ImportLibrary; - bool Optional; - cmListFileBacktrace Backtrace; + bool const ImportLibrary; + bool const Optional; + cmListFileBacktrace const Backtrace; }; #endif diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index eabe590..a65ae03 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 ee809ee..698151e 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 b23ab43..dd36386 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()); @@ -485,10 +487,10 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, result[kHAS_INSTALL_RULE] = true; Json::Value installPaths = Json::arrayValue; - auto targetGenerators = target->Makefile->GetInstallGenerators(); - for (auto installGenerator : targetGenerators) { + for (const auto& installGenerator : + target->Makefile->GetInstallGenerators()) { auto installTargetGenerator = - dynamic_cast<cmInstallTargetGenerator*>(installGenerator); + dynamic_cast<cmInstallTargetGenerator*>(installGenerator.get()); if (installTargetGenerator != nullptr && installTargetGenerator->GetTarget()->Target == target->Target) { auto dest = installTargetGenerator->GetDestination(config); @@ -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()); @@ -641,9 +643,9 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config) // associated generators. bool hasInstallRule = false; for (const auto generator : projectIt.second) { - for (const auto installGen : + for (const auto& installGen : generator->GetMakefile()->GetInstallGenerators()) { - if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(installGen)) { + if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(installGen.get())) { hasInstallRule = true; break; } diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx new file mode 100644 index 0000000..ab2cf9e --- /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 0000000..21dc659 --- /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/cmLinkLibrariesCommand.cxx b/Source/cmLinkLibrariesCommand.cxx index cb63ceb..2b8f836 100644 --- a/Source/cmLinkLibrariesCommand.cxx +++ b/Source/cmLinkLibrariesCommand.cxx @@ -32,7 +32,7 @@ bool cmLinkLibrariesCommand(std::vector<std::string> const& args, } mf.AppendProperty("LINK_LIBRARIES", "optimized"); } - mf.AppendProperty("LINK_LIBRARIES", i->c_str()); + mf.AppendProperty("LINK_LIBRARIES", *i); } return true; diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 0dc6236..4320010 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 f426976..df42468 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/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx index 1184bcb..d49e711 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 23ace64..92258e2 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 f86955d..025ef7e 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 eaef6ab..378ca63 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 ffd46d4..cf6802d 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; } @@ -317,9 +315,7 @@ void cmLocalGenerator::GenerateTestFiles() } // Ask each test generator to write its code. - std::vector<cmTestGenerator*> const& testers = - this->Makefile->GetTestGenerators(); - for (cmTestGenerator* tester : testers) { + for (const auto& tester : this->Makefile->GetTestGenerators()) { tester->Compute(this); tester->Generate(fout, config, configurationTypes); } @@ -365,9 +361,7 @@ void cmLocalGenerator::CreateEvaluationFileOutputs() void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config) { - std::vector<cmGeneratorExpressionEvaluationFile*> ef = - this->Makefile->GetEvaluationFiles(); - for (cmGeneratorExpressionEvaluationFile* geef : ef) { + for (const auto& geef : this->Makefile->GetEvaluationFiles()) { geef->CreateOutputFile(this, config); } } @@ -375,8 +369,7 @@ void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config) void cmLocalGenerator::ProcessEvaluationFiles( std::vector<std::string>& generatedFiles) { - for (cmGeneratorExpressionEvaluationFile* geef : - this->Makefile->GetEvaluationFiles()) { + for (const auto& geef : this->Makefile->GetEvaluationFiles()) { geef->Generate(this); if (cmSystemTools::GetFatalErrorOccured()) { return; @@ -395,7 +388,7 @@ void cmLocalGenerator::ProcessEvaluationFiles( return; } - cmAppend(generatedFiles, files); + cm::append(generatedFiles, files); std::inplace_merge(generatedFiles.begin(), generatedFiles.end() - files.size(), generatedFiles.end()); @@ -559,18 +552,17 @@ void cmLocalGenerator::GenerateInstallRules() // Ask each install generator to write its code. cmPolicies::PolicyStatus status = this->GetPolicyStatus(cmPolicies::CMP0082); - std::vector<cmInstallGenerator*> const& installers = - this->Makefile->GetInstallGenerators(); + auto const& installers = this->Makefile->GetInstallGenerators(); bool haveSubdirectoryInstall = false; bool haveInstallAfterSubdirectory = false; if (status == cmPolicies::WARN) { - for (cmInstallGenerator* installer : installers) { + for (const auto& installer : installers) { installer->CheckCMP0082(haveSubdirectoryInstall, haveInstallAfterSubdirectory); installer->Generate(fout, config, configurationTypes); } } else { - for (cmInstallGenerator* installer : installers) { + for (const auto& installer : installers) { installer->Generate(fout, config, configurationTypes); } } @@ -635,11 +627,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 +643,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 +669,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 +691,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 +735,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 +990,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, @@ -1084,7 +1171,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( } for (std::string const& i : impDirVec) { - if (implicitSet.insert(cmSystemTools::GetRealPath(i)).second) { + if (implicitSet.insert(this->GlobalGenerator->GetRealPath(i)).second) { implicitDirs.emplace_back(i); } } @@ -1095,7 +1182,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( &lang](std::string const& dir) { return ( // Do not exclude directories that are not in an excluded set. - ((!cmContains(implicitSet, cmSystemTools::GetRealPath(dir))) && + ((!cmContains(implicitSet, this->GlobalGenerator->GetRealPath(dir))) && (!cmContains(implicitExclude, dir))) // Do not exclude entries of the CPATH environment variable even though // they are implicitly searched by the compiler. They are meant to be @@ -1685,10 +1772,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 +1791,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 += " "; @@ -1864,7 +1969,8 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName, case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: case cmStateEnums::UNKNOWN_LIBRARY: - dep = target->GetLocation(config); + dep = target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, + /*realname=*/true); return true; case cmStateEnums::OBJECT_LIBRARY: // An object library has no single file on which to depend. @@ -1898,8 +2004,16 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName, // Treat the name as relative to the source directory in which it // was given. - dep = cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentSource(), '/', - inName); + dep = cmStrCat(this->GetCurrentSourceDirectory(), '/', inName); + + // If the in-source path does not exist, assume it instead lives in the + // binary directory. + if (!cmSystemTools::FileExists(dep)) { + dep = cmStrCat(this->GetCurrentBinaryDirectory(), '/', inName); + } + + dep = cmSystemTools::CollapseFullPath(dep, this->GetBinaryDirectory()); + return true; } @@ -2004,17 +2118,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( @@ -2296,175 +2415,177 @@ 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) { - // FIXME: Handle all configurations in multi-config generators. - std::string config; - if (!this->GetGlobalGenerator()->IsMultiConfig()) { - config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + std::vector<std::string> configsList; + std::string configDefault = this->Makefile->GetConfigurations(configsList); + if (configsList.empty()) { + configsList.push_back(configDefault); } - const std::string buildType = cmSystemTools::UpperCase(config); - // FIXME: Refactor collection of sources to not evaluate object libraries. - std::vector<cmSourceFile*> sources; - target->GetSourceFiles(sources, buildType); - - for (const std::string& lang : { "C", "CXX", "OBJC", "OBJCXX" }) { - auto langSources = - std::count_if(sources.begin(), sources.end(), [lang](cmSourceFile* sf) { - return lang == sf->GetLanguage() && - !sf->GetProperty("SKIP_PRECOMPILE_HEADERS"); - }); - if (langSources == 0) { - continue; - } + for (std::string const& config : configsList) { + const std::string buildType = cmSystemTools::UpperCase(config); - const std::string pchSource = target->GetPchSource(config, lang); - const std::string pchHeader = target->GetPchHeader(config, lang); + // FIXME: Refactor collection of sources to not evaluate object libraries. + std::vector<cmSourceFile*> sources; + target->GetSourceFiles(sources, buildType); - if (pchSource.empty() || pchHeader.empty()) { - continue; - } - - const std::string pchExtension = - this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); + for (const std::string& lang : { "C", "CXX", "OBJC", "OBJCXX" }) { + auto langSources = std::count_if( + sources.begin(), sources.end(), [lang](cmSourceFile* sf) { + return lang == sf->GetLanguage() && + !sf->GetProperty("SKIP_PRECOMPILE_HEADERS"); + }); + if (langSources == 0) { + continue; + } - if (pchExtension.empty()) { - continue; - } + const std::string pchSource = target->GetPchSource(config, lang); + const std::string pchHeader = target->GetPchHeader(config, lang); - const char* pchReuseFrom = - target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + if (pchSource.empty() || pchHeader.empty()) { + continue; + } - auto pch_sf = this->Makefile->GetOrCreateSource( - pchSource, false, cmSourceFileLocationKind::Known); + const std::string pchExtension = + this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); - if (!this->GetGlobalGenerator()->IsXcode()) { - if (!pchReuseFrom) { - target->AddSource(pchSource, true); + if (pchExtension.empty()) { + continue; } - const std::string pchFile = target->GetPchFile(config, lang); + const char* pchReuseFrom = + target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); - // Exclude the pch files from linking - if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { - if (!pchReuseFrom) { - pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); - } else { - auto reuseTarget = - this->GlobalGenerator->FindGeneratorTarget(pchReuseFrom); + auto pch_sf = this->Makefile->GetOrCreateSource( + pchSource, false, cmSourceFileLocationKind::Known); - if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) { + if (!this->GetGlobalGenerator()->IsXcode()) { + if (!pchReuseFrom) { + target->AddSource(pchSource, true); + } - const std::string pdb_prefix = - this->GetGlobalGenerator()->IsMultiConfig() - ? cmStrCat(this->GlobalGenerator->GetCMakeCFGIntDir(), "/") - : ""; + const std::string pchFile = target->GetPchFile(config, lang); - const std::string target_compile_pdb_dir = cmStrCat( - target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/", - target->GetName(), ".dir/"); + // Exclude the pch files from linking + if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { + if (!pchReuseFrom) { + pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); + } else { + auto reuseTarget = + this->GlobalGenerator->FindGeneratorTarget(pchReuseFrom); - const std::string copy_script = - cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake"); - cmGeneratedFileStream file(copy_script); + if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) { - file << "# CMake generated file\n"; - for (auto extension : { ".pdb", ".idb" }) { - const std::string from_file = cmStrCat( - reuseTarget->GetLocalGenerator()->GetCurrentBinaryDirectory(), - "/", pchReuseFrom, ".dir/${PDB_PREFIX}", pchReuseFrom, - extension); + const std::string pdb_prefix = + this->GetGlobalGenerator()->IsMultiConfig() + ? cmStrCat(this->GlobalGenerator->GetCMakeCFGIntDir(), "/") + : ""; - const std::string to_dir = cmStrCat( + const std::string target_compile_pdb_dir = cmStrCat( target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/", - target->GetName(), ".dir/${PDB_PREFIX}"); + target->GetName(), ".dir/"); - const std::string to_file = - cmStrCat(to_dir, pchReuseFrom, extension); + const std::string copy_script = + cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake"); + cmGeneratedFileStream file(copy_script); - std::string dest_file = to_file; + file << "# CMake generated file\n"; + for (auto extension : { ".pdb", ".idb" }) { + const std::string from_file = + cmStrCat(reuseTarget->GetLocalGenerator() + ->GetCurrentBinaryDirectory(), + "/", pchReuseFrom, ".dir/${PDB_PREFIX}", + pchReuseFrom, extension); - const std::string prefix = target->GetSafeProperty("PREFIX"); - if (!prefix.empty()) { - dest_file = cmStrCat(to_dir, prefix, pchReuseFrom, extension); - } + const std::string to_dir = cmStrCat( + target->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/", target->GetName(), ".dir/${PDB_PREFIX}"); + + const std::string to_file = + cmStrCat(to_dir, pchReuseFrom, extension); + + std::string dest_file = to_file; + + const std::string prefix = target->GetSafeProperty("PREFIX"); + if (!prefix.empty()) { + dest_file = + cmStrCat(to_dir, prefix, pchReuseFrom, extension); + } - file << "if (EXISTS \"" << from_file << "\" AND \"" << from_file - << "\" IS_NEWER_THAN \"" << dest_file << "\")\n"; - file << " file(COPY \"" << from_file << "\"" - << " DESTINATION \"" << to_dir << "\")\n"; - if (!prefix.empty()) { - file << " file(REMOVE \"" << dest_file << "\")\n"; - file << " file(RENAME \"" << to_file << "\" \"" << dest_file + file << "if (EXISTS \"" << from_file << "\" AND \"" + << from_file << "\" IS_NEWER_THAN \"" << dest_file << "\")\n"; + file << " file(COPY \"" << from_file << "\"" + << " DESTINATION \"" << to_dir << "\")\n"; + if (!prefix.empty()) { + file << " file(REMOVE \"" << dest_file << "\")\n"; + file << " file(RENAME \"" << to_file << "\" \"" << dest_file + << "\")\n"; + } + file << "endif()\n"; } - 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)); - - const std::string no_main_dependency; - const std::vector<std::string> no_deps; - const char* no_message = ""; - const char* no_current_dir = nullptr; - std::vector<std::string> no_byproducts; - - std::vector<std::string> outputs; - outputs.push_back(cmStrCat(target_compile_pdb_dir, pdb_prefix, - pchReuseFrom, ".pdb")); - - if (this->GetGlobalGenerator()->IsMultiConfig()) { - this->Makefile->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( + 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; + const char* no_message = ""; + const char* no_current_dir = nullptr; + std::vector<std::string> no_byproducts; + + std::vector<std::string> outputs; + outputs.push_back(cmStrCat(target_compile_pdb_dir, pdb_prefix, + pchReuseFrom, ".pdb")); + + if (this->GetGlobalGenerator()->IsVisualStudio()) { + 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->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()); + if (copy_rule) { + target->AddSource(copy_rule->ResolveFullPath()); + } } - } - target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", - target_compile_pdb_dir.c_str()); - } + target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", + target_compile_pdb_dir); + } - std::string pchSourceObj = - reuseTarget->GetPchFileObject(config, lang); + std::string pchSourceObj = + reuseTarget->GetPchFileObject(config, lang); - // Link to the pch object file - target->Target->AppendProperty( - "LINK_FLAGS", - cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)) - .c_str(), - true); + // Link to the pch object file + target->Target->AppendProperty( + "LINK_FLAGS", + cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)), + true); + } + } else { + pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); } - } else { - pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); - } - // Add pchHeader to source files, which will - // be grouped as "Precompile Header File" - auto pchHeader_sf = this->Makefile->GetOrCreateSource( - pchHeader, false, cmSourceFileLocationKind::Known); - std::string err; - pchHeader_sf->ResolveFullPath(&err); - target->AddSource(pchHeader); + // Add pchHeader to source files, which will + // be grouped as "Precompile Header File" + auto pchHeader_sf = this->Makefile->GetOrCreateSource( + pchHeader, false, cmSourceFileLocationKind::Known); + std::string err; + pchHeader_sf->ResolveFullPath(&err); + target->AddSource(pchHeader); + } } } } @@ -2516,8 +2637,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); @@ -2629,11 +2749,11 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags( } void cmLocalGenerator::AppendCompileOptions(std::string& options, - const char* options_list, + std::string const& options_list, const char* regex) const { // Short-circuit if there are no options. - if (!options_list) { + if (options_list.empty()) { return; } @@ -2687,11 +2807,11 @@ void cmLocalGenerator::AppendCompileOptions( } void cmLocalGenerator::AppendIncludeDirectories( - std::vector<std::string>& includes, const char* includes_list, + std::vector<std::string>& includes, const std::string& includes_list, const cmSourceFile& sourceFile) const { // Short-circuit if there are no includes. - if (!includes_list) { + if (includes_list.empty()) { return; } @@ -2885,7 +3005,7 @@ class cmInstallTargetGeneratorLocal : public cmInstallTargetGenerator { public: cmInstallTargetGeneratorLocal(cmLocalGenerator* lg, std::string const& t, - const char* dest, bool implib) + std::string const& dest, bool implib) : cmInstallTargetGenerator( t, dest, implib, "", std::vector<std::string>(), "Unspecified", cmInstallGenerator::SelectMessageLevel(lg->GetMakefile()), false, @@ -2901,15 +3021,15 @@ 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; } // Include the user-specified pre-install script for this target. if (const char* preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) { - cmInstallScriptGenerator g(preinstall, false, nullptr, false); + cmInstallScriptGenerator g(preinstall, false, "", false); g.Generate(os, config, configurationTypes); } @@ -2930,8 +3050,8 @@ void cmLocalGenerator::GenerateTargetInstallRules( case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::MODULE_LIBRARY: { // Use a target install generator. - cmInstallTargetGeneratorLocal g(this, l->GetName(), - destination.c_str(), false); + cmInstallTargetGeneratorLocal g(this, l->GetName(), destination, + false); g.Generate(os, config, configurationTypes); } break; case cmStateEnums::SHARED_LIBRARY: { @@ -2939,19 +3059,19 @@ void cmLocalGenerator::GenerateTargetInstallRules( // Special code to handle DLL. Install the import library // to the normal destination and the DLL to the runtime // destination. - cmInstallTargetGeneratorLocal g1(this, l->GetName(), - destination.c_str(), true); + cmInstallTargetGeneratorLocal g1(this, l->GetName(), destination, + true); g1.Generate(os, config, configurationTypes); // We also skip over the leading slash given by the user. destination = l->Target->GetRuntimeInstallPath().substr(1); cmSystemTools::ConvertToUnixSlashes(destination); - cmInstallTargetGeneratorLocal g2(this, l->GetName(), - destination.c_str(), false); + cmInstallTargetGeneratorLocal g2(this, l->GetName(), destination, + false); g2.Generate(os, config, configurationTypes); #else // Use a target install generator. - cmInstallTargetGeneratorLocal g(this, l->GetName(), - destination.c_str(), false); + cmInstallTargetGeneratorLocal g(this, l->GetName(), destination, + false); g.Generate(os, config, configurationTypes); #endif } break; @@ -2962,7 +3082,7 @@ void cmLocalGenerator::GenerateTargetInstallRules( // Include the user-specified post-install script for this target. if (const char* postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) { - cmInstallScriptGenerator g(postinstall, false, nullptr, false); + cmInstallScriptGenerator g(postinstall, false, "", false); g.Generate(os, config, configurationTypes); } } @@ -3118,6 +3238,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) @@ -3446,3 +3571,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 12359db..88194b7 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; @@ -160,15 +167,8 @@ public: * Process a list of include directories */ void AppendIncludeDirectories(std::vector<std::string>& includes, - const char* includes_list, - const cmSourceFile& sourceFile) const; - void AppendIncludeDirectories(std::vector<std::string>& includes, std::string const& includes_list, - const cmSourceFile& sourceFile) const - { - this->AppendIncludeDirectories(includes, includes_list.c_str(), - sourceFile); - } + const cmSourceFile& sourceFile) const; void AppendIncludeDirectories(std::vector<std::string>& includes, const std::vector<std::string>& includes_vec, const cmSourceFile& sourceFile) const; @@ -188,14 +188,9 @@ public: * Encode a list of compile options for the compiler * command line. */ - void AppendCompileOptions(std::string& options, const char* options_list, - const char* regex = nullptr) const; void AppendCompileOptions(std::string& options, std::string const& options_list, - const char* regex = nullptr) const - { - this->AppendCompileOptions(options, options_list.c_str(), regex); - } + const char* regex = nullptr) const; void AppendCompileOptions(std::string& options, const std::vector<std::string>& options_vec, const char* regex = nullptr) const; @@ -292,6 +287,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 +454,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 +502,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 +535,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 4b10798..098fa5a 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 134bbe1..be1dd0d 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->GetImplFileStream(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::GetImplFileStream( + const std::string& config) const { - return *this->GetGlobalNinjaGenerator()->GetBuildFileStream(); + return *this->GetGlobalNinjaGenerator()->GetImplFileStream(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->GetImplFileStream(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->GetImplFileStream(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 f64534c..ef160e7 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& GetImplFileStream(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 4a70248..d037b93 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" @@ -673,9 +683,15 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop( if (!this->IsNMake() && !this->IsWatcomWMake() && !this->BorlandMakeCurlyHack) { // turn off RCS and SCCS automatic stuff from gmake - makefileStream - << "# Remove some rules from gmake that .SUFFIXES does not remove.\n" - << "SUFFIXES =\n\n"; + constexpr const char* vcs_rules[] = { + "%,v", "RCS/%", "RCS/%,v", "SCCS/s.%", "s.%", + }; + for (auto vcs_rule : vcs_rules) { + std::vector<std::string> vcs_depend; + vcs_depend.emplace_back(vcs_rule); + this->WriteMakeRule(makefileStream, "Disable VCS-based implicit rules.", + "%", vcs_depend, no_commands, false); + } } // Add a fake suffix to keep HP happy. Must be max 32 chars for SGI make. std::vector<std::string> depends; @@ -849,7 +865,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 +873,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 +884,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 +895,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 +1038,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 +1109,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 +1566,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 +1588,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 +1854,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 +1878,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 << " \"" @@ -1957,18 +1972,18 @@ void cmLocalUnixMakefileGenerator3::WriteDivider(std::ostream& os) } void cmLocalUnixMakefileGenerator3::WriteCMakeArgument(std::ostream& os, - const char* s) + const std::string& s) { // Write the given string to the stream with escaping to get it back // into CMake through the lexical scanner. os << "\""; - for (const char* c = s; *c; ++c) { - if (*c == '\\') { + for (char c : s) { + if (c == '\\') { os << "\\\\"; - } else if (*c == '"') { + } else if (c == '"') { os << "\\\""; } else { - os << *c; + os << c; } } os << "\""; diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index f12ae8b..68eeb29 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; /** @@ -75,7 +77,7 @@ public: void SetBorlandMakeCurlyHack(bool b) { this->BorlandMakeCurlyHack = b; } // used in writing out Cmake files such as WriteDirectoryInformation - static void WriteCMakeArgument(std::ostream& os, const char* s); + static void WriteCMakeArgument(std::ostream& os, const std::string& s); /** creates the common disclaimer text at the top of each makefile */ void WriteDisclaimer(std::ostream& os); diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index f3d828b..02e2c6d 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(); @@ -124,8 +128,7 @@ void cmLocalVisualStudio10Generator::ReadAndStoreExternalGUID( std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); // save the GUID in the cache this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry( - guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID", - cmStateEnums::INTERNAL); + guidStoreName, parser.GUID.c_str(), "Stored GUID", cmStateEnums::INTERNAL); } const char* cmLocalVisualStudio10Generator::ReportErrorLabel() const diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index f19549d..1a6b7b2 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()); } } } @@ -146,7 +146,7 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() // out of date. std::string stampName = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles"); - cmSystemTools::MakeDirectory(stampName.c_str()); + cmSystemTools::MakeDirectory(stampName); stampName += "/generate.stamp"; cmsys::ofstream stamp(stampName.c_str()); stamp << "# CMake generation timestamp file for this directory.\n"; @@ -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); @@ -257,12 +257,11 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() "--check-stamp-file", stampName }); std::string comment = cmStrCat("Building Custom Rule ", makefileIn); 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); - if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) { + std::string fullpathStampName = cmSystemTools::CollapseFullPath(stampName); + this->AddCustomCommandToOutput(fullpathStampName, listFiles, makefileIn, + commandLines, comment.c_str(), + no_working_directory, true, false); + if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) { // Finalize the source file path now since we're adding this after // the generator validated all project-named sources. file->ResolveFullPath(); @@ -279,7 +278,7 @@ void cmLocalVisualStudio7Generator::WriteConfigurations( { fout << "\t<Configurations>\n"; for (std::string const& config : configs) { - this->WriteConfiguration(fout, config.c_str(), libName, target); + this->WriteConfiguration(fout, config, libName, target); } fout << "\t</Configurations>\n"; } @@ -580,7 +579,7 @@ public: this->Stream << this->LG->EscapeForXML("\n"); } std::string script = this->LG->ConstructScript(ccg); - this->Stream << this->LG->EscapeForXML(script.c_str()); + this->Stream << this->LG->EscapeForXML(script); } private: @@ -733,13 +732,13 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( : target->GetDirectory(configName); /* clang-format off */ fout << "\t\t\tOutputDirectory=\"" - << this->ConvertToXMLOutputPathSingle(outDir.c_str()) << "\"\n"; + << this->ConvertToXMLOutputPathSingle(outDir) << "\"\n"; /* clang-format on */ } /* clang-format off */ fout << "\t\t\tIntermediateDirectory=\"" - << this->ConvertToXMLOutputPath(intermediateDir.c_str()) + << this->ConvertToXMLOutputPath(intermediateDir) << "\"\n" << "\t\t\tConfigurationType=\"" << configType << "\"\n" << "\t\t\tUseOfMFC=\"" << mfcFlag << "\"\n" @@ -788,8 +787,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( } else { modDir = "."; } - fout << "\t\t\t\tModulePath=\"" - << this->ConvertToXMLOutputPath(modDir.c_str()) + fout << "\t\t\t\tModulePath=\"" << this->ConvertToXMLOutputPath(modDir) << "\\$(ConfigurationName)\"\n"; } targetOptions.OutputAdditionalIncludeDirectories( @@ -802,7 +800,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( std::string pdb = target->GetCompilePDBPath(configName); if (!pdb.empty()) { fout << "\t\t\t\tProgramDataBaseFileName=\"" - << this->ConvertToXMLOutputPathSingle(pdb.c_str()) << "\"\n"; + << this->ConvertToXMLOutputPathSingle(pdb) << "\"\n"; } } fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool @@ -879,7 +877,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( fout << "\n\t\t\t\tAdditionalManifestFiles=\""; for (cmSourceFile const* manifest : manifest_srcs) { std::string m = manifest->GetFullPath(); - fout << this->ConvertToXMLOutputPath(m.c_str()) << ";"; + fout << this->ConvertToXMLOutputPath(m) << ";"; } fout << "\""; } @@ -946,7 +944,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( } std::string configTypeUpper = cmSystemTools::UpperCase(configName); std::string linkFlagsConfig = cmStrCat("LINK_FLAGS_", configTypeUpper); - targetLinkFlags = target->GetProperty(linkFlagsConfig.c_str()); + targetLinkFlags = target->GetProperty(linkFlagsConfig); if (targetLinkFlags) { extraLinkOptions += " "; extraLinkOptions += targetLinkFlags; @@ -985,7 +983,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( fout << "\t\t\t<Tool\n" << "\t\t\t\tName=\"" << tool << "\"\n"; fout << "\t\t\t\tOutputFile=\"" - << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n"; + << this->ConvertToXMLOutputPathSingle(libpath) << "\"/>\n"; break; } case cmStateEnums::STATIC_LIBRARY: { @@ -1015,7 +1013,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n"; } fout << "\t\t\t\tOutputFile=\"" - << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n"; + << this->ConvertToXMLOutputPathSingle(libpath) << "\"/>\n"; break; } case cmStateEnums::SHARED_LIBRARY: @@ -1057,7 +1055,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( temp = cmStrCat(target->GetDirectory(configName), '/', targetNames.Output); fout << "\t\t\t\tOutputFile=\"" - << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; + << this->ConvertToXMLOutputPathSingle(temp) << "\"\n"; this->WriteTargetVersionAttribute(fout, target); linkOptions.OutputFlagMap(fout, 4); fout << "\t\t\t\tAdditionalLibraryDirectories=\""; @@ -1066,7 +1064,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( temp = cmStrCat(target->GetPDBDirectory(configName), '/', targetNames.PDB); fout << "\t\t\t\tProgramDatabaseFile=\"" - << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; + << this->ConvertToXMLOutputPathSingle(temp) << "\"\n"; if (targetOptions.IsDebug()) { fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n"; } @@ -1078,7 +1076,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( } } std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"); - const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str()); + const char* stackVal = this->Makefile->GetDefinition(stackVar); if (stackVal) { fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n"; } @@ -1086,7 +1084,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact), '/', targetNames.ImportLibrary); fout << "\t\t\t\tImportLibrary=\"" - << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\""; + << this->ConvertToXMLOutputPathSingle(temp) << "\""; if (this->FortranProject) { fout << "\n\t\t\t\tLinkDLL=\"true\""; } @@ -1132,14 +1130,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( temp = cmStrCat(target->GetDirectory(configName), '/', targetNames.Output); fout << "\t\t\t\tOutputFile=\"" - << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; + << this->ConvertToXMLOutputPathSingle(temp) << "\"\n"; this->WriteTargetVersionAttribute(fout, target); linkOptions.OutputFlagMap(fout, 4); fout << "\t\t\t\tAdditionalLibraryDirectories=\""; this->OutputLibraryDirectories(fout, cli.GetDirectories()); fout << "\"\n"; std::string path = this->ConvertToXMLOutputPathSingle( - target->GetPDBDirectory(configName).c_str()); + target->GetPDBDirectory(configName)); fout << "\t\t\t\tProgramDatabaseFile=\"" << path << "/" << targetNames.PDB << "\"\n"; if (targetOptions.IsDebug()) { @@ -1167,7 +1165,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( << "\"\n"; } std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"); - const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str()); + const char* stackVal = this->Makefile->GetDefinition(stackVar); if (stackVal) { fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\""; } @@ -1175,7 +1173,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact), '/', targetNames.ImportLibrary); fout << "\t\t\t\tImportLibrary=\"" - << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n"; + << this->ConvertToXMLOutputPathSingle(temp) << "\"/>\n"; break; } case cmStateEnums::UTILITY: @@ -1256,8 +1254,8 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries( for (auto const& lib : libs) { if (lib.IsPath) { std::string rel = - lg->MaybeConvertToRelativePath(currentBinDir, lib.Value.c_str()); - fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " "; + lg->MaybeConvertToRelativePath(currentBinDir, lib.Value); + fout << lg->ConvertToXMLOutputPath(rel) << " "; } else if (!lib.Target || lib.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { fout << lib.Value << " "; @@ -1282,7 +1280,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects( if (!obj->GetObjectLibrary().empty()) { std::string const& objFile = obj->GetFullPath(); std::string rel = lg->MaybeConvertToRelativePath(currentBinDir, objFile); - fout << sep << lg->ConvertToXMLOutputPath(rel.c_str()); + fout << sep << lg->ConvertToXMLOutputPath(rel); sep = " "; } } @@ -1303,9 +1301,8 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories( } // Switch to a relative path specification if it is shorter. - if (cmSystemTools::FileIsFullPath(dir.c_str())) { - std::string rel = - this->MaybeConvertToRelativePath(currentBinDir, dir.c_str()); + if (cmSystemTools::FileIsFullPath(dir)) { + std::string rel = this->MaybeConvertToRelativePath(currentBinDir, dir); if (rel.size() < dir.size()) { dir = rel; } @@ -1314,9 +1311,8 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories( // First search a configuration-specific subdirectory and then the // original directory. fout << comma - << this->ConvertToXMLOutputPath( - (dir + "/$(ConfigurationName)").c_str()) - << "," << this->ConvertToXMLOutputPath(dir.c_str()); + << this->ConvertToXMLOutputPath(dir + "/$(ConfigurationName)") << "," + << this->ConvertToXMLOutputPath(dir); comma = ","; } } @@ -1337,7 +1333,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; @@ -1518,13 +1514,13 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( for (std::vector<std::string>::iterator j = depends.begin(); j != depends.end(); ++j) { fc.AdditionalDeps += sep; - fc.AdditionalDeps += lg->ConvertToXMLOutputPath(j->c_str()); + fc.AdditionalDeps += lg->ConvertToXMLOutputPath(*j); sep = ";"; needfc = true; } } - const std::string& linkLanguage = gt->GetLinkerLanguage(config.c_str()); + const std::string& linkLanguage = gt->GetLinkerLanguage(config); // If HEADER_FILE_ONLY is set, we must suppress this generation in // the project file fc.ExcludedFromBuild = sf.GetPropertyAsBool("HEADER_FILE_ONLY") || @@ -1629,7 +1625,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup( FCInfo fcinfo(this, target, acs, configs); fout << "\t\t\t<File\n"; - std::string d = this->ConvertToXMLOutputPathSingle(source.c_str()); + std::string d = this->ConvertToXMLOutputPathSingle(source); // Tell MS-Dev what the source is. If the compiler knows how to // build it, then it will. fout << "\t\t\t\tRelativePath=\"" << d << "\">\n"; @@ -1759,21 +1755,21 @@ void cmLocalVisualStudio7Generator::WriteCustomRule( fout << "\t\t\t\t\t<Tool\n" << "\t\t\t\t\tName=\"" << compileTool << "\"\n" << "\t\t\t\t\tAdditionalOptions=\"" - << this->EscapeForXML(fc.CompileFlags.c_str()) << "\"/>\n"; + << this->EscapeForXML(fc.CompileFlags) << "\"/>\n"; } std::string comment = this->ConstructComment(ccg); std::string script = this->ConstructScript(ccg); if (this->FortranProject) { - cmSystemTools::ReplaceString(script, "$(Configuration)", config.c_str()); + cmSystemTools::ReplaceString(script, "$(Configuration)", config); } /* clang-format off */ fout << "\t\t\t\t\t<Tool\n" << "\t\t\t\t\tName=\"" << customTool << "\"\n" << "\t\t\t\t\tDescription=\"" - << this->EscapeForXML(comment.c_str()) << "\"\n" + << this->EscapeForXML(comment) << "\"\n" << "\t\t\t\t\tCommandLine=\"" - << this->EscapeForXML(script.c_str()) << "\"\n" + << this->EscapeForXML(script) << "\"\n" << "\t\t\t\t\tAdditionalDependencies=\""; /* clang-format on */ if (ccg.GetDepends().empty()) { @@ -1789,8 +1785,8 @@ void cmLocalVisualStudio7Generator::WriteCustomRule( for (std::string const& d : ccg.GetDepends()) { // Get the real name of the dependency in case it is a CMake target. std::string dep; - if (this->GetRealDependency(d.c_str(), config.c_str(), dep)) { - fout << this->ConvertToXMLOutputPath(dep.c_str()) << ";"; + if (this->GetRealDependency(d, config, dep)) { + fout << this->ConvertToXMLOutputPath(dep) << ";"; } } } @@ -1802,7 +1798,7 @@ void cmLocalVisualStudio7Generator::WriteCustomRule( // Write a rule for the output generated by this command. const char* sep = ""; for (std::string const& output : ccg.GetOutputs()) { - fout << sep << this->ConvertToXMLOutputPathSingle(output.c_str()); + fout << sep << this->ConvertToXMLOutputPathSingle(output); sep = ";"; } } @@ -1948,7 +1944,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran( this->WriteProjectSCC(fout, target); /* clang-format off */ fout<< "\tKeyword=\"" << keyword << "\">\n" - << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\">\n" + << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\">\n" << "\t<Platforms>\n" << "\t\t<Platform\n\t\t\tName=\"" << gg->GetPlatformName() << "\"/>\n" << "\t</Platforms>\n"; @@ -1983,7 +1979,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStart( keyword = "Win32Proj"; } fout << "\tName=\"" << projLabel << "\"\n"; - fout << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\"\n"; + fout << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\"\n"; this->WriteProjectSCC(fout, target); if (const char* targetFrameworkVersion = target->GetProperty("VS_DOTNET_TARGET_FRAMEWORK_VERSION")) { @@ -2037,7 +2033,7 @@ std::string cmLocalVisualStudio7Generator::EscapeForXML(const std::string& s) } std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPath( - const char* path) + const std::string& path) { std::string ret = this->ConvertToOutputFormat(path, cmOutputConverter::SHELL); @@ -2049,7 +2045,7 @@ std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPath( } std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPathSingle( - const char* path) + const std::string& path) { std::string ret = this->ConvertToOutputFormat(path, cmOutputConverter::SHELL); @@ -2061,7 +2057,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'); @@ -2130,8 +2126,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID( std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); // save the GUID in the cache this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry( - guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID", - cmStateEnums::INTERNAL); + guidStoreName, parser.GUID.c_str(), "Stored GUID", cmStateEnums::INTERNAL); } std::string cmLocalVisualStudio7Generator::GetTargetDirectory( diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 671783f..745766c 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; }; @@ -101,8 +101,8 @@ private: void WriteConfiguration(std::ostream& fout, const std::string& configName, const std::string& libName, cmGeneratorTarget* tgt); std::string EscapeForXML(const std::string& s); - std::string ConvertToXMLOutputPath(const char* path); - std::string ConvertToXMLOutputPathSingle(const char* path); + std::string ConvertToXMLOutputPath(const std::string& path); + std::string ConvertToXMLOutputPathSingle(const std::string& path); void OutputTargetRules(std::ostream& fout, const std::string& configName, cmGeneratorTarget* target, const std::string& libName); diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 336e3a5..8d50898 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 5a06d4a..ac0d35e 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 ba9947a..0b0d9ac 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" @@ -167,7 +167,7 @@ bool cmMacroFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, cmExecutionStatus& status) { cmMakefile& mf = status.GetMakefile(); - mf.AppendProperty("MACROS", this->Args[0].c_str()); + mf.AppendProperty("MACROS", this->Args[0]); // create a new command and add it to cmake cmMacroHelperCommand f; f.Args = this->Args; @@ -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 f143ef7..b2e59bd 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -15,10 +15,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 +41,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" @@ -117,15 +123,7 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, #endif } -cmMakefile::~cmMakefile() -{ - cmDeleteAll(this->InstallGenerators); - cmDeleteAll(this->TestGenerators); - cmDeleteAll(this->SourceFiles); - cmDeleteAll(this->Tests); - cmDeleteAll(this->ImportedTargetsOwned); - cmDeleteAll(this->EvaluationFiles); -} +cmMakefile::~cmMakefile() = default; cmDirectoryId cmMakefile::GetDirectoryId() const { @@ -133,7 +131,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 +144,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 +311,54 @@ 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); } - msg << " "; } - msg << ")"; + + 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<Json::Value::Int64>(lff.Line); + val["cmd"] = lff.Name.Original; + val["args"] = Json::Value(Json::arrayValue); + for (std::string const& arg : args) { + val["args"].append(arg); + } + val["time"] = cmSystemTools::GetTime(); + val["frame"] = + static_cast<Json::Value::UInt64>(this->ExecutionStatusStack.size()); + msg << Json::writeString(builder, val); +#endif + break; + } + 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; + } auto& f = this->GetCMakeInstance()->GetTraceFile(); if (f) { @@ -737,12 +768,13 @@ void cmMakefile::AddEvaluationFile( std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent) { - this->EvaluationFiles.push_back(new cmGeneratorExpressionEvaluationFile( - inputFile, std::move(outputName), std::move(condition), inputIsContent, - this->GetPolicyStatus(cmPolicies::CMP0070))); + this->EvaluationFiles.push_back( + cm::make_unique<cmGeneratorExpressionEvaluationFile>( + inputFile, std::move(outputName), std::move(condition), inputIsContent, + this->GetPolicyStatus(cmPolicies::CMP0070))); } -std::vector<cmGeneratorExpressionEvaluationFile*> +const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>& cmMakefile::GetEvaluationFiles() const { return this->EvaluationFiles; @@ -780,38 +812,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 +861,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 +911,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 +946,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 +959,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 +968,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 +982,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 +993,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); - } - } - - // 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; + 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); } - - // 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 +1117,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 +1127,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 +1146,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 +1180,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 +1200,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 @@ -1342,28 +1287,27 @@ void cmMakefile::RemoveDefineFlag(std::string const& flag) void cmMakefile::AddCompileDefinition(std::string const& option) { - this->AppendProperty("COMPILE_DEFINITIONS", option.c_str()); + this->AppendProperty("COMPILE_DEFINITIONS", option); } void cmMakefile::AddCompileOption(std::string const& option) { - this->AppendProperty("COMPILE_OPTIONS", option.c_str()); + this->AppendProperty("COMPILE_OPTIONS", option); } void cmMakefile::AddLinkOption(std::string const& option) { - this->AppendProperty("LINK_OPTIONS", option.c_str()); + this->AppendProperty("LINK_OPTIONS", 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); } } @@ -1476,6 +1420,20 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) this->RecursionDepth = parent->RecursionDepth; } +void cmMakefile::AddInstallGenerator(std::unique_ptr<cmInstallGenerator> g) +{ + if (g) { + this->InstallGenerators.push_back(std::move(g)); + } +} + +void cmMakefile::AddTestGenerator(std::unique_ptr<cmTestGenerator> g) +{ + if (g) { + this->TestGenerators.push_back(std::move(g)); + } +} + void cmMakefile::PushFunctionScope(std::string const& fileName, const cmPolicies::PolicyMap& pm) { @@ -1776,8 +1734,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"); @@ -1789,8 +1749,8 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, this->UnConfiguredDirectories.push_back(subMf); } - this->AddInstallGenerator(new cmInstallSubdirectoryGenerator( - subMf, binPath.c_str(), excludeFromAll)); + this->AddInstallGenerator(cm::make_unique<cmInstallSubdirectoryGenerator>( + subMf, binPath, excludeFromAll)); } const std::string& cmMakefile::GetCurrentSourceDirectory() const @@ -1820,20 +1780,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 +1986,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 +2039,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 +2049,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"); } @@ -2155,18 +2113,18 @@ cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput( // Look through all the source files that have custom commands and see if the // custom command has the passed source file as an output. - for (cmSourceFile* src : this->SourceFiles) { + for (const auto& src : this->SourceFiles) { // Does this source file have a custom command? if (src->GetCustomCommand()) { // Does the output of the custom command match the source file name? if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) { // Return the first matching output. - return src; + return src.get(); } if (kind == cmSourceOutputKind::OutputOrByproduct) { if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) { // Do not return the source yet as there might be a matching output. - fallback = src; + fallback = src.get(); } } } @@ -2211,8 +2169,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 +2178,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 +2244,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 +2254,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 +2446,7 @@ void cmMakefile::ExpandVariablesCMP0019() << " " << dirs << "\n"; /* clang-format on */ } - t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); + t.SetProperty("INCLUDE_DIRECTORIES", dirs); } } @@ -2739,7 +2707,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; } @@ -3514,24 +3482,25 @@ cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName, bool generated, cmSourceFileLocationKind kind) { - cmSourceFile* sf = new cmSourceFile(this, sourceName, kind); + auto sf = cm::make_unique<cmSourceFile>(this, sourceName, kind); if (generated) { sf->SetProperty("GENERATED", "1"); } - this->SourceFiles.push_back(sf); auto name = this->GetCMakeInstance()->StripExtension(sf->GetLocation().GetName()); #if defined(_WIN32) || defined(__APPLE__) name = cmSystemTools::LowerCase(name); #endif - this->SourceFileSearchIndex[name].push_back(sf); + this->SourceFileSearchIndex[name].push_back(sf.get()); // for "Known" paths add direct lookup (used for faster lookup in GetSource) if (kind == cmSourceFileLocationKind::Known) { - this->KnownFileSearchIndex[sourceName] = sf; + this->KnownFileSearchIndex[sourceName] = sf.get(); } - return sf; + this->SourceFiles.push_back(std::move(sf)); + + return this->SourceFiles.back().get(); } cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName, @@ -3553,11 +3522,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 +3629,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 +3640,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 +3649,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 +3695,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 +3776,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 +3808,9 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, moduleInCMakeModulePath = itempl; break; } + if (debug) { + debugBuffer = cmStrCat(debugBuffer, " ", itempl, "\n"); + } } } @@ -3816,6 +3819,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 +4035,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) +void cmMakefile::AppendProperty(const std::string& prop, + const std::string& 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 @@ -4090,9 +4094,10 @@ cmTest* cmMakefile::CreateTest(const std::string& testName) if (test) { return test; } - test = new cmTest(this); - test->SetName(testName); - this->Tests[testName] = test; + auto newTest = cm::make_unique<cmTest>(this); + test = newTest.get(); + newTest->SetName(testName); + this->Tests[testName] = std::move(newTest); return test; } @@ -4100,7 +4105,7 @@ cmTest* cmMakefile::GetTest(const std::string& testName) const { auto mi = this->Tests.find(testName); if (mi != this->Tests.end()) { - return mi->second; + return mi->second.get(); } return nullptr; } @@ -4108,7 +4113,7 @@ cmTest* cmMakefile::GetTest(const std::string& testName) const void cmMakefile::GetTests(const std::string& config, std::vector<cmTest*>& tests) { - for (auto generator : this->GetTestGenerators()) { + for (const auto& generator : this->GetTestGenerators()) { if (generator->TestsForConfig(config)) { tests.push_back(generator->GetTest()); } @@ -4214,15 +4219,15 @@ 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(); this->GetGlobalGenerator()->IndexTarget(target.get()); // Transfer ownership to this cmMakefile object. - this->ImportedTargetsOwned.push_back(target.get()); - return target.release(); + this->ImportedTargetsOwned.push_back(std::move(target)); + return this->ImportedTargetsOwned.back().get(); } cmTarget* cmMakefile::FindTargetToUse(const std::string& name, @@ -4487,7 +4492,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 +4592,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 +4637,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 +4669,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 +4744,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 +4833,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 +4985,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 +5001,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 6e59494..f1a68c2 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; @@ -134,7 +135,7 @@ public: std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker(); /** - * Try running cmake and building a file. This is used for dynalically + * Try running cmake and building a file. This is used for dynamically * loaded commands, not as part of the usual build process. */ int TryCompile(const std::string& srcdir, const std::string& bindir, @@ -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, @@ -409,9 +419,9 @@ public: { this->ComplainFileRegularExpression = regex; } - const char* GetComplainRegularExpression() const + const std::string& GetComplainRegularExpression() const { - return this->ComplainFileRegularExpression.c_str(); + return this->ComplainFileRegularExpression; } // -- List of targets @@ -421,7 +431,7 @@ public: /** Get the target map - const version */ cmTargetMap const& GetTargets() const { return this->Targets; } - const std::vector<cmTarget*>& GetOwnedImportedTargets() const + const std::vector<std::unique_ptr<cmTarget>>& GetOwnedImportedTargets() const { return this->ImportedTargetsOwned; } @@ -717,7 +727,7 @@ public: /** * Get all the source files this makefile knows about */ - const std::vector<cmSourceFile*>& GetSourceFiles() const + const std::vector<std::unique_ptr<cmSourceFile>>& GetSourceFiles() const { return this->SourceFiles; } @@ -756,14 +766,25 @@ 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); - void AppendProperty(const std::string& prop, const char* value, + void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); const char* GetProperty(const std::string& prop) const; const char* GetProperty(const std::string& prop, bool chain) const; @@ -773,28 +794,22 @@ public: //! Initialize a makefile from its parent void InitializeFromParent(cmMakefile* parent); - void AddInstallGenerator(cmInstallGenerator* g) - { - if (g) { - this->InstallGenerators.push_back(g); - } - } - std::vector<cmInstallGenerator*>& GetInstallGenerators() + void AddInstallGenerator(std::unique_ptr<cmInstallGenerator> g); + + std::vector<std::unique_ptr<cmInstallGenerator>>& GetInstallGenerators() { return this->InstallGenerators; } - const std::vector<cmInstallGenerator*>& GetInstallGenerators() const + const std::vector<std::unique_ptr<cmInstallGenerator>>& + GetInstallGenerators() const { return this->InstallGenerators; } - void AddTestGenerator(cmTestGenerator* g) - { - if (g) { - this->TestGenerators.push_back(g); - } - } - const std::vector<cmTestGenerator*>& GetTestGenerators() const + void AddTestGenerator(std::unique_ptr<cmTestGenerator> g); + + const std::vector<std::unique_ptr<cmTestGenerator>>& GetTestGenerators() + const { return this->TestGenerators; } @@ -927,7 +942,8 @@ public: std::unique_ptr<cmCompiledGeneratorExpression> outputName, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent); - std::vector<cmGeneratorExpressionEvaluationFile*> GetEvaluationFiles() const; + const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>& + GetEvaluationFiles() const; std::vector<cmExportBuildFileGenerator*> GetExportBuildFileGenerators() const; @@ -962,8 +978,7 @@ protected: using TargetsVec = std::vector<cmTarget*>; TargetsVec OrderedTargets; - using SourceFileVec = std::vector<cmSourceFile*>; - SourceFileVec SourceFiles; + std::vector<std::unique_ptr<cmSourceFile>> SourceFiles; // Because cmSourceFile names are compared in a fuzzy way (see // cmSourceFileLocation::Match()) we can't have a straight mapping from @@ -971,14 +986,15 @@ protected: // Name portion of the cmSourceFileLocation and then compare on the list of // cmSourceFiles that might match that name. Note that on platforms which // have a case-insensitive filesystem we store the key in all lowercase. - using SourceFileMap = std::unordered_map<std::string, SourceFileVec>; + using SourceFileMap = + std::unordered_map<std::string, std::vector<cmSourceFile*>>; SourceFileMap SourceFileSearchIndex; // For "Known" paths we can store a direct filename to cmSourceFile map std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex; // Tests - std::map<std::string, cmTest*> Tests; + std::map<std::string, std::unique_ptr<cmTest>> Tests; // The set of include directories that are marked as system include // directories. @@ -987,8 +1003,8 @@ protected: std::vector<std::string> ListFiles; std::vector<std::string> OutputFiles; - std::vector<cmInstallGenerator*> InstallGenerators; - std::vector<cmTestGenerator*> TestGenerators; + std::vector<std::unique_ptr<cmInstallGenerator>> InstallGenerators; + std::vector<std::unique_ptr<cmTestGenerator>> TestGenerators; std::string ComplainFileRegularExpression; std::string DefineFlags; @@ -1001,7 +1017,6 @@ protected: size_t ObjectLibrariesSourceGroupIndex; #endif - std::vector<FinalAction> FinalActions; cmGlobalGenerator* GlobalGenerator; bool IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus& status); @@ -1011,6 +1026,8 @@ private: cmListFileBacktrace Backtrace; int RecursionDepth; + void DoGenerate(cmLocalGenerator& lg); + void ReadListFile(cmListFile const& listFile, const std::string& filenametoread); @@ -1038,13 +1055,14 @@ private: std::vector<cmMakefile*> UnConfiguredDirectories; std::vector<cmExportBuildFileGenerator*> ExportBuildFileGenerators; - std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles; + std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>> + EvaluationFiles; std::vector<cmExecutionStatus*> ExecutionStatusStack; friend class cmMakefileCall; friend class cmParseFileScope; - std::vector<cmTarget*> ImportedTargetsOwned; + std::vector<std::unique_ptr<cmTarget>> ImportedTargetsOwned; using TargetMap = std::unordered_map<std::string, cmTarget*>; TargetMap ImportedTargets; @@ -1080,38 +1098,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 +1126,7 @@ private: struct SourceEntry { cmSourcesWithOutput Sources; + bool SourceMightBeOutput = false; }; // A map for fast output to input look up. @@ -1149,11 +1145,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 +1161,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 +1172,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 40265ff..0471a45 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); @@ -197,6 +196,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects, buildObjs, depends, useWatcomQuote); + std::string const& aixExports = this->GetAIXExports(this->GetConfigName()); + cmRulePlaceholderExpander::RuleVariables vars; std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); @@ -213,12 +214,14 @@ 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); vars.Language = linkLanguage.c_str(); + vars.AIXExports = aixExports.c_str(); vars.Objects = buildObjs.c_str(); vars.ObjectDir = objectDir.c_str(); vars.Target = target.c_str(); @@ -263,7 +266,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 +290,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 +313,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 +352,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 +385,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 +414,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 +457,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 +485,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 +512,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 +542,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 +633,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 +645,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 54a6606..d3f3a4f 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); @@ -723,10 +727,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmOutputConverter::SHELL); } + std::string const& aixExports = this->GetAIXExports(this->GetConfigName()); + // 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(); @@ -752,6 +758,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.CMTargetType = cmState::GetTargetTypeName(this->GeneratorTarget->GetType()); vars.Language = linkLanguage.c_str(); + vars.AIXExports = aixExports.c_str(); vars.Objects = buildObjs.c_str(); std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); @@ -771,7 +778,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 +790,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 +807,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 +910,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 +924,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 dd8a389..d7e2de6 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 <cm/memory> +#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" @@ -35,12 +38,7 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) : cmCommonTargetGenerator(target) - , OSXBundleGenerator(nullptr) - , MacOSXContentGenerator(nullptr) { - this->BuildFileStream = nullptr; - this->InfoFileStream = nullptr; - this->FlagFileStream = nullptr; this->CustomCommandDriver = OnBuild; this->LocalGenerator = static_cast<cmLocalUnixMakefileGenerator3*>(target->GetLocalGenerator()); @@ -52,31 +50,28 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) { this->NoRuleMessages = cmIsOff(ruleStatus); } - MacOSXContentGenerator = new MacOSXContentGeneratorType(this); + MacOSXContentGenerator = cm::make_unique<MacOSXContentGeneratorType>(this); } -cmMakefileTargetGenerator::~cmMakefileTargetGenerator() -{ - delete MacOSXContentGenerator; -} +cmMakefileTargetGenerator::~cmMakefileTargetGenerator() = default; -cmMakefileTargetGenerator* cmMakefileTargetGenerator::New( +std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New( cmGeneratorTarget* tgt) { - cmMakefileTargetGenerator* result = nullptr; + std::unique_ptr<cmMakefileTargetGenerator> result; switch (tgt->GetType()) { case cmStateEnums::EXECUTABLE: - result = new cmMakefileExecutableTargetGenerator(tgt); + result = cm::make_unique<cmMakefileExecutableTargetGenerator>(tgt); break; case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: case cmStateEnums::OBJECT_LIBRARY: - result = new cmMakefileLibraryTargetGenerator(tgt); + result = cm::make_unique<cmMakefileLibraryTargetGenerator>(tgt); break; case cmStateEnums::UTILITY: - result = new cmMakefileUtilityTargetGenerator(tgt); + result = cm::make_unique<cmMakefileUtilityTargetGenerator>(tgt); break; default: return result; @@ -85,6 +80,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 +94,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() @@ -128,9 +131,9 @@ void cmMakefileTargetGenerator::CreateRuleFile() // Open the rule file. This should be copy-if-different because the // rules may depend on this file itself. - this->BuildFileStream = - new cmGeneratedFileStream(this->BuildFileNameFull, false, - this->GlobalGenerator->GetMakefileEncoding()); + this->BuildFileStream = cm::make_unique<cmGeneratedFileStream>( + this->BuildFileNameFull, false, + this->GlobalGenerator->GetMakefileEncoding()); if (!this->BuildFileStream) { return; } @@ -154,10 +157,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 +190,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 +219,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 +236,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.get(), 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.get(), 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 +256,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); @@ -299,9 +308,9 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() // rules may depend on this file itself. this->FlagFileNameFull = cmStrCat(this->TargetBuildDirectoryFull, "/flags.make"); - this->FlagFileStream = - new cmGeneratedFileStream(this->FlagFileNameFull, false, - this->GlobalGenerator->GetMakefileEncoding()); + this->FlagFileStream = cm::make_unique<cmGeneratedFileStream>( + this->FlagFileNameFull, false, + this->GlobalGenerator->GetMakefileEncoding()); if (!this->FlagFileStream) { return; } @@ -334,9 +343,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 +357,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 +365,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 +461,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 +603,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 +719,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"), @@ -769,7 +782,13 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } if (tidy && *tidy) { run_iwyu += " --tidy="; - run_iwyu += this->LocalGenerator->EscapeForShell(tidy); + const char* driverMode = this->Makefile->GetDefinition( + "CMAKE_" + lang + "_CLANG_TIDY_DRIVER_MODE"); + if (!(driverMode && *driverMode)) { + driverMode = lang == "C" ? "gcc" : "g++"; + } + run_iwyu += this->LocalGenerator->EscapeForShell( + cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode)); } if (cpplint && *cpplint) { run_iwyu += " --cpplint="; @@ -823,7 +842,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 +901,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 +945,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 ", @@ -1036,7 +1055,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() this->InfoFileNameFull = cmStrCat(dir, "/DependInfo.cmake"); this->InfoFileNameFull = this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull); - this->InfoFileStream = new cmGeneratedFileStream(this->InfoFileNameFull); + this->InfoFileStream = + cm::make_unique<cmGeneratedFileStream>(this->InfoFileNameFull); if (!this->InfoFileStream) { return; } @@ -1068,7 +1088,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 +1192,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 +1431,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 +1450,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 +1469,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 +1495,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 +1509,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; } @@ -1501,9 +1523,9 @@ std::string cmMakefileTargetGenerator::GetLinkRule( void cmMakefileTargetGenerator::CloseFileStreams() { - delete this->BuildFileStream; - delete this->InfoFileStream; - delete this->FlagFileStream; + this->BuildFileStream.reset(); + this->InfoFileStream.reset(); + this->FlagFileStream.reset(); } void cmMakefileTargetGenerator::CreateLinkScript( @@ -1612,7 +1634,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 +1653,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 +1661,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 +1699,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 +1741,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 +1750,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 7b9c7a5..ec6b314 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -34,10 +34,15 @@ class cmMakefileTargetGenerator : public cmCommonTargetGenerator public: // constructor to set the ivars cmMakefileTargetGenerator(cmGeneratorTarget* target); + cmMakefileTargetGenerator(const cmMakefileTargetGenerator&) = delete; ~cmMakefileTargetGenerator() override; + cmMakefileTargetGenerator& operator=(const cmMakefileTargetGenerator&) = + delete; + // construct using this factory call - static cmMakefileTargetGenerator* New(cmGeneratorTarget* tgt); + static std::unique_ptr<cmMakefileTargetGenerator> New( + cmGeneratorTarget* tgt); /* the main entry point for this class. Writes the Makefiles associated with this target */ @@ -52,6 +57,8 @@ public: cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; } + std::string GetConfigName(); + protected: void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage); @@ -81,7 +88,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 +145,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 +171,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; @@ -191,11 +200,11 @@ protected: std::string TargetBuildDirectoryFull; // the stream for the build file - cmGeneratedFileStream* BuildFileStream; + std::unique_ptr<cmGeneratedFileStream> BuildFileStream; // the stream for the flag file std::string FlagFileNameFull; - cmGeneratedFileStream* FlagFileStream; + std::unique_ptr<cmGeneratedFileStream> FlagFileStream; class StringList : public std::vector<std::string> { }; @@ -203,7 +212,7 @@ protected: // the stream for the info file std::string InfoFileNameFull; - cmGeneratedFileStream* InfoFileStream; + std::unique_ptr<cmGeneratedFileStream> InfoFileStream; // files to clean std::set<std::string> CleanFiles; @@ -232,7 +241,7 @@ protected: // macOS content info. std::set<std::string> MacContentFolders; std::unique_ptr<cmOSXBundleGenerator> OSXBundleGenerator; - MacOSXContentGeneratorType* MacOSXContentGenerator; + std::unique_ptr<MacOSXContentGeneratorType> MacOSXContentGenerator; }; #endif diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 1625e4f..6c18e48 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/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx index ca46e14..45043fa 100644 --- a/Source/cmMarkAsAdvancedCommand.cxx +++ b/Source/cmMarkAsAdvancedCommand.cxx @@ -4,8 +4,11 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -28,14 +31,63 @@ bool cmMarkAsAdvancedCommand(std::vector<std::string> const& args, } i = 1; } + + cmMakefile& mf = status.GetMakefile(); + cmState* state = mf.GetState(); + for (; i < args.size(); ++i) { std::string const& variable = args[i]; - cmState* state = status.GetMakefile().GetState(); - if (!state->GetCacheEntryValue(variable)) { - status.GetMakefile().GetCMakeInstance()->AddCacheEntry( - variable, nullptr, nullptr, cmStateEnums::UNINITIALIZED); - overwrite = true; + + bool issueMessage = false; + bool oldBehavior = false; + bool ignoreVariable = false; + switch (mf.GetPolicyStatus(cmPolicies::CMP0102)) { + case cmPolicies::WARN: + if (mf.PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0102")) { + if (!state->GetCacheEntryValue(variable)) { + issueMessage = true; + } + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + oldBehavior = true; + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + if (!state->GetCacheEntryValue(variable)) { + ignoreVariable = true; + } + break; + } + + // First see if we should issue a message about CMP0102 + if (issueMessage) { + std::string err = cmStrCat( + "Policy CMP0102 is not set: The variable named \"", variable, + "\" is not in the cache. This results in an empty cache entry which " + "is no longer created when policy CMP0102 is set to NEW. Run \"cmake " + "--help-policy CMP0102\" for policy details. Use the cmake_policy " + "command to set the policy and suppress this warning."); + mf.IssueMessage(MessageType::AUTHOR_WARNING, err); } + + // If it's not in the cache and we're using the new behavior, nothing to + // see here. + if (ignoreVariable) { + continue; + } + + // Check if we want the old behavior of making a dummy cache entry. + if (oldBehavior) { + if (!state->GetCacheEntryValue(variable)) { + status.GetMakefile().GetCMakeInstance()->AddCacheEntry( + variable, nullptr, nullptr, cmStateEnums::UNINITIALIZED); + overwrite = true; + } + } + + // We need a cache entry to do this. if (!state->GetCacheEntryValue(variable)) { cmSystemTools::Error("This should never happen..."); return false; diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 96a6386..bf8183b 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 beedef4..ff79a17 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,48 @@ 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 (!this->GetGlobalGenerator() + ->GetCrossConfigs(fileConfig) + .count(config)) { + 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(); + firstForConfig = true; + for (auto const& fileConfig : this->GetConfigNames()) { + if (!this->GetGlobalGenerator() + ->GetCrossConfigs(fileConfig) + .count(config)) { + continue; + } + // If this target has cuda language link inputs, and we need to do + // device linking + this->WriteDeviceLinkStatement(config, fileConfig, firstForConfig); + 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 +121,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 +129,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() } } for (std::string const& language : languages) { - this->WriteLanguageRules(language); + this->WriteLanguageRules(language, config); } } @@ -139,22 +153,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 +183,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 +255,40 @@ 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(); + vars.AIXExports = "$AIX_EXPORTS"; - 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 +302,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 +311,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) if (flag) { responseFlag = flag; - } else if (this->TargetLinkLanguage != "CUDA") { + } else if (this->TargetLinkLanguage(config) != "CUDA") { responseFlag = "@"; } @@ -304,7 +329,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 +384,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 +392,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 +469,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 +479,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 +498,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 +514,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); @@ -523,19 +551,28 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() linkCmds.push_back(cmakeCommand + " -E touch $TARGET_FILE"); } #endif - return linkCmds; - } + } break; case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: + break; case cmStateEnums::EXECUTABLE: + if (this->TargetLinkLanguage(config) == "Swift") { + if (this->GeneratorTarget->IsExecutableWithExports()) { + const std::string flags = + this->Makefile->GetSafeDefinition("CMAKE_EXE_EXPORTS_Swift_FLAG"); + cmExpandList(flags, linkCmds); + } + } break; default: assert(false && "Unexpected target type"); } - return std::vector<std::string>(); + return linkCmds; } -void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() +void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( + const std::string& config, const std::string& fileConfig, + bool firstForConfig) { cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); if (!globalGen->GetLanguageEnabled("CUDA")) { @@ -545,7 +582,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 +595,53 @@ 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 targetOutputDir = + cmStrCat(this->GetLocalGenerator()->GetTargetDirectory(genTarget), + globalGen->ConfigDirectory(config), "/"); + targetOutputDir = globalGen->ExpandCFGIntDir(targetOutputDir, config); - std::string const targetOutputImplib = ConvertToNinjaPath( - genTarget->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); + std::string targetOutputReal = + ConvertToNinjaPath(targetOutputDir + "cmake_device_link" + objExt); + std::string targetOutputImplib = ConvertToNinjaPath( + genTarget->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); + + if (config != fileConfig) { + std::string targetOutputFileConfigDir = + cmStrCat(this->GetLocalGenerator()->GetTargetDirectory(genTarget), + globalGen->ConfigDirectory(fileConfig), "/"); + targetOutputFileConfigDir = + globalGen->ExpandCFGIntDir(targetOutputDir, fileConfig); + if (targetOutputDir == targetOutputFileConfigDir) { + return; + } + + if (!genTarget->GetFullName(config, cmStateEnums::ImportLibraryArtifact) + .empty() && + !genTarget + ->GetFullName(fileConfig, cmStateEnums::ImportLibraryArtifact) + .empty() && + targetOutputImplib == + ConvertToNinjaPath(genTarget->GetFullPath( + fileConfig, cmStateEnums::ImportLibraryArtifact))) { + return; + } + } + + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutputReal); + } 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 +650,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 +672,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 +691,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 +717,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 +746,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->GetImplFileStream(fileConfig)); const cmStateEnums::TargetType targetType = gt->GetType(); - this->GetBuildFileStream() + this->GetImplFileStream(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 +836,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 +879,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 +897,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 +928,42 @@ 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["AIX_EXPORTS"] = this->GetAIXExports(config); vars["LINK_PATH"] = frameworkPath + linkPath; std::string lwyuFlags; @@ -876,23 +976,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 +1005,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 +1034,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 +1055,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 +1104,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 +1139,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 +1148,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 +1161,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 +1194,27 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Write the build statement for this target. bool usedResponseFile = false; - globalGen->WriteBuild(this->GetBuildFileStream(), linkBuild, + globalGen->WriteBuild(this->GetImplFileStream(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->GetImplFileStream(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 +1223,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->GetImplFileStream(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 ebc1268..9de99b9 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -17,30 +17,33 @@ 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, + const std::string& fileConfig, + bool firstForConfig); - 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 0aab912..0e74678 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" @@ -58,19 +58,27 @@ std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New( cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target) : cmCommonTargetGenerator(target) - , MacOSXContentGenerator(nullptr) , OSXBundleGenerator(nullptr) , LocalGenerator( static_cast<cmLocalNinjaGenerator*>(target->GetLocalGenerator())) { - MacOSXContentGenerator = cm::make_unique<MacOSXContentGeneratorType>(this); + for (auto const& fileConfig : target->Makefile->GetGeneratorConfigs()) { + this->Configs[fileConfig].MacOSXContentGenerator = + cm::make_unique<MacOSXContentGeneratorType>(this, fileConfig); + } } cmNinjaTargetGenerator::~cmNinjaTargetGenerator() = default; -cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const +cmGeneratedFileStream& cmNinjaTargetGenerator::GetImplFileStream( + const std::string& config) const +{ + return *this->GetGlobalGenerator()->GetImplFileStream(config); +} + +cmGeneratedFileStream& cmNinjaTargetGenerator::GetCommonFileStream() const { - return *this->GetGlobalGenerator()->GetBuildFileStream(); + return *this->GetGlobalGenerator()->GetCommonFileStream(); } cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const @@ -84,17 +92,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 +127,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 +139,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 +151,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 +163,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 +179,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 +199,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 +246,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 +272,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 +296,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 +311,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( } cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); + this->GeneratorTarget->GetLinkInformation(config); if (!cli) { return cmNinjaDeps(); } @@ -303,8 +322,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 +330,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 +351,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 +359,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 +396,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 +418,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 +452,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 +482,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 +533,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 +548,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 +628,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 +652,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"; @@ -737,7 +761,13 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) } if (tidy && *tidy) { run_iwyu += " --tidy="; - run_iwyu += this->GetLocalGenerator()->EscapeForShell(tidy); + const char* driverMode = this->Makefile->GetDefinition( + "CMAKE_" + lang + "_CLANG_TIDY_DRIVER_MODE"); + if (!(driverMode && *driverMode)) { + driverMode = lang == "C" ? "gcc" : "g++"; + } + run_iwyu += this->GetLocalGenerator()->EscapeForShell( + cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode)); } if (cpplint && *cpplint) { run_iwyu += " --cpplint="; @@ -788,50 +818,54 @@ 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->GetImplFileStream(fileConfig)); + this->GetImplFileStream(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->Configs[fileConfig].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->Configs[fileConfig].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); } } } @@ -839,19 +873,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(), @@ -877,26 +911,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir)); } - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(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 @@ -907,46 +942,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->GetImplFileStream(fileConfig), + build); } - this->GetBuildFileStream() << "\n"; + this->GetImplFileStream(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); @@ -962,11 +1002,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); @@ -994,11 +1034,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); @@ -1007,13 +1049,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)); } } @@ -1034,7 +1074,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 @@ -1054,10 +1094,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"; @@ -1115,7 +1155,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags( sourceDirectory, this->GeneratorTarget, language, false, false, - this->GetConfigName()); + config); vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"]; } @@ -1139,17 +1179,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->GetImplFileStream(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; } @@ -1164,14 +1206,21 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), vars); - this->SetMsvcTargetPdbVariable(vars); + if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + if (source->GetFullPath() == pchSource) { + this->addPoolNinjaVariable("JOB_POOL_PRECOMPILE_HEADER", + this->GetGeneratorTarget(), 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(), + this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig), objBuild, commandLineLengthLimit); } @@ -1182,11 +1231,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->GetImplFileStream(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; @@ -1214,7 +1265,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. @@ -1223,22 +1274,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; @@ -1251,10 +1302,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); @@ -1275,7 +1326,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( @@ -1350,27 +1401,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 { @@ -1393,7 +1451,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()) { @@ -1401,7 +1459,18 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( } std::string macdir = - this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc); + this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc, + config); + + // Reject files that collide with files from the Ninja file's native config. + if (config != this->FileConfig) { + std::string nativeMacdir = + this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory( + pkgloc, this->FileConfig); + if (macdir == nativeMacdir) { + return; + } + } // Get the input file location. std::string input = source.GetFullPath(); @@ -1413,11 +1482,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, this->FileConfig); // 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 4627bcd..8678dc3 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -9,6 +9,7 @@ #include <memory> #include <set> #include <string> +#include <utility> #include <vector> #include "cm_jsoncpp_value.h" @@ -38,16 +39,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& GetImplFileStream(const std::string& config) const; + cmGeneratedFileStream& GetCommonFileStream() const; cmGeneratedFileStream& GetRulesFileStream() const; cmGeneratorTarget* GetGeneratorTarget() const @@ -64,15 +66,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 +87,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 +111,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 +163,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; @@ -150,19 +174,22 @@ protected: struct MacOSXContentGeneratorType : cmOSXBundleGenerator::MacOSXContentGeneratorType { - MacOSXContentGeneratorType(cmNinjaTargetGenerator* g) + MacOSXContentGeneratorType(cmNinjaTargetGenerator* g, + std::string fileConfig) : Generator(g) + , FileConfig(std::move(fileConfig)) { } - 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; + std::string FileConfig; }; friend struct MacOSXContentGeneratorType; - std::unique_ptr<MacOSXContentGeneratorType> MacOSXContentGenerator; // Properly initialized by sub-classes. std::unique_ptr<cmOSXBundleGenerator> OSXBundleGenerator; std::set<std::string> MacContentFolders; @@ -174,14 +201,21 @@ 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::unique_ptr<MacOSXContentGeneratorType> MacOSXContentGenerator; + }; + + std::map<std::string, ByConfig> Configs; }; #endif // ! cmNinjaTargetGenerator_h diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 5259037..a42d65d 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->GetImplFileStream(config), phonyAlias); } } diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h index 01cc459..ca3f0a4 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 a6f4e51..382b563 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 3dea6cc..232be48 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 073222c..0369af0 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 23c5145..8ce53e0 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 e602a6d..1c6fad1 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 349a069..6583ab5 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 e093be0..147f97f 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 92c80bb..1366ff0 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -290,7 +290,22 @@ 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) \ + SELECT(POLICY, CMP0102, \ + "mark_as_advanced() does nothing if a cache entry does not exist.", \ + 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 +334,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 7bb5209..a25fd42 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/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index a3d4946..d4b3552 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -20,11 +20,11 @@ void cmPropertyMap::SetProperty(const std::string& name, const char* value) Map_[name] = value; } -void cmPropertyMap::AppendProperty(const std::string& name, const char* value, - bool asString) +void cmPropertyMap::AppendProperty(const std::string& name, + const std::string& value, bool asString) { // Skip if nothing to append. - if (!value || !*value) { + if (value.empty()) { return; } diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index 9aed349..bea4372 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -27,7 +27,7 @@ public: void SetProperty(const std::string& name, const char* value); //! Append to the property value - void AppendProperty(const std::string& name, const char* value, + void AppendProperty(const std::string& name, const std::string& value, bool asString = false); //! Get the property value diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index eb7c900..d5891c4 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 ef6b886..db5a8ba 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 806725a..2f6e581 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 5eb04f7..43e159c 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" @@ -355,24 +354,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 +747,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 +788,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 +825,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 +869,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 @@ -865,7 +882,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() // The reason is that their file names might be discovered from source files // at generation time. if (this->MocOrUicEnabled()) { - for (cmSourceFile* sf : this->Makefile->GetSourceFiles()) { + for (const auto& sf : this->Makefile->GetSourceFiles()) { // sf->GetExtension() is only valid after sf->ResolveFullPath() ... // Since we're iterating over source files that might be not in the // target we need to check for path errors (not existing files). @@ -877,19 +894,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 (!cmContains(this->AutogenTarget.Headers, sf)) { - auto muf = makeMUFile(sf, fullPath, false); + if (cm->IsHeaderExtension(extLower)) { + if (!cmContains(this->AutogenTarget.Headers, sf.get())) { + auto muf = makeMUFile(sf.get(), 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)) { - auto muf = makeMUFile(sf, fullPath, false); + if (!cmContains(this->AutogenTarget.Sources, sf.get())) { + auto muf = makeMUFile(sf.get(), 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 +963,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 +1090,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 +1136,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); @@ -1119,16 +1171,61 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() } } + std::vector<std::string> dependencies( + this->AutogenTarget.DependFiles.begin(), + this->AutogenTarget.DependFiles.end()); + + const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) && + this->GlobalGen->GetName().find("Ninja") != std::string::npos; + if (useNinjaDepfile) { + // Create a custom command that generates a timestamp file and + // has a depfile assigned. The depfile is created by JobDepFilesMergeT. + + // Add additional autogen target dependencies + for (const cmTarget* t : this->AutogenTarget.DependTargets) { + dependencies.push_back(t->GetName()); + } + const char timestampFileName[] = "timestamp"; + const std::string outputFile = + cmStrCat(this->Dir.Build, "/", timestampFileName); + this->AutogenTarget.DepFile = cmStrCat(this->Dir.Build, "/deps"); + auto relativeBinaryDir = cmSystemTools::RelativePath( + this->LocalGen->GetBinaryDirectory(), + this->LocalGen->GetCurrentBinaryDirectory()); + if (!relativeBinaryDir.empty()) { + relativeBinaryDir = cmStrCat(relativeBinaryDir, "/"); + } + this->AutogenTarget.DepFileRuleName = + cmStrCat(relativeBinaryDir, this->GenTarget->GetName(), "_autogen/", + timestampFileName); + commandLines.push_back(cmMakeCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile })); + + this->AddGeneratedSource(outputFile, this->Moc); + const std::string no_main_dependency; + this->LocalGen->AddCustomCommandToOutput( + outputFile, dependencies, no_main_dependency, commandLines, + autogenComment.c_str(), this->Dir.Work.c_str(), /*replace=*/false, + /*escapeOldStyle=*/false, + /*uses_terminal=*/false, + /*command_expand_lists=*/false, this->AutogenTarget.DepFile); + + // Alter variables for the autogen target which now merely wraps the + // custom command + dependencies.clear(); + dependencies.push_back(outputFile); + commandLines.clear(); + autogenComment.clear(); + } + // Create autogen target - cmTarget* autogenTarget = this->Makefile->AddUtilityCommand( - this->AutogenTarget.Name, cmCommandOrigin::Generator, 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()); + cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand( + this->AutogenTarget.Name, true, this->Dir.Work.c_str(), + /*byproducts=*/autogenProvides, + /*depends=*/dependencies, 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) { @@ -1136,14 +1233,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() autogenTarget->AddUtility(depName.Value, this->Makefile); } } - // Add additional autogen target dependencies to autogen target - for (cmTarget* depTarget : this->AutogenTarget.DependTargets) { - autogenTarget->AddUtility(depTarget->GetName(), this->Makefile); + if (!useNinjaDepfile) { + // Add additional autogen target dependencies to autogen target + for (cmTarget* depTarget : this->AutogenTarget.DependTargets) { + autogenTarget->AddUtility(depTarget->GetName(), this->Makefile); + } } // 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 @@ -1205,17 +1304,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, @@ -1244,7 +1343,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()); @@ -1356,12 +1455,15 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() info.SetConfig("INCLUDE_DIR", this->Dir.Include); info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major); + info.SetUInt("QT_VERSION_MINOR", this->QtVersion.Minor); info.Set("QT_MOC_EXECUTABLE", this->Moc.Executable); info.Set("QT_UIC_EXECUTABLE", this->Uic.Executable); info.Set("CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand()); info.SetConfig("SETTINGS_FILE", this->AutogenTarget.SettingsFile); info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile); + info.Set("DEP_FILE", this->AutogenTarget.DepFile); + info.Set("DEP_FILE_RULE_NAME", this->AutogenTarget.DepFileRuleName); info.SetArray("HEADER_EXTENSIONS", this->Makefile->GetCMakeInstance()->GetHeaderExtensions()); info.SetArrayArray( @@ -1528,8 +1630,8 @@ void 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, @@ -1632,21 +1734,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 d55259c..48ec1a0 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -160,6 +160,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; @@ -189,10 +191,13 @@ private: bool DependOrigin = false; std::set<std::string> DependFiles; std::set<cmTarget*> DependTargets; + std::string DepFile; + std::string DepFileRuleName; // Sources to process 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 f8b8981..893bd6b 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -16,15 +16,17 @@ #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 "cmGccDepfileReader.h" +#include "cmGccDepfileReaderTypes.h" #include "cmGeneratedFileStream.h" #include "cmQtAutoGen.h" #include "cmQtAutoGenerator.h" @@ -170,7 +172,7 @@ public: // -- Attributes // - Config bool MultiConfig = false; - unsigned int QtVersionMajor = 4; + IntegerVersion QtVersion = { 4, 0 }; unsigned int ThreadCount = 0; // - Directories std::string AutogenBuildDir; @@ -179,6 +181,8 @@ public: std::string CMakeExecutable; cmFileTime CMakeExecutableTime; std::string ParseCacheFile; + std::string DepFile; + std::string DepFileRuleName; std::vector<std::string> HeaderExtensions; }; @@ -216,6 +220,7 @@ public: bool SettingsChanged = false; bool RelaxedMode = false; bool PathPrefix = false; + bool CanOutputDependencies = false; cmFileTime ExecutableTime; std::string Executable; std::string CompFileAbs; @@ -485,8 +490,17 @@ public: class JobCompileMocT : public JobCompileT { public: - using JobCompileT::JobCompileT; + JobCompileMocT(MappingHandleT uicMapping, + std::unique_ptr<std::string> reason, + ParseCacheT::FileHandleT cacheEntry) + : JobCompileT(std::move(uicMapping), std::move(reason)) + , CacheEntry(std::move(cacheEntry)) + { + } void Process() override; + + protected: + ParseCacheT::FileHandleT CacheEntry; }; /** uic compiles a file. */ @@ -504,6 +518,12 @@ public: void Process() override; }; + class JobDepFilesMergeT : public JobFenceT + { + private: + void Process() override; + }; + /** @brief The last job. */ class JobFinishT : public JobFenceT { @@ -546,6 +566,9 @@ private: void Abort(bool error); // -- Generation bool CreateDirectories(); + // -- Support for depfiles + static std::vector<std::string> dependenciesFromDepFile( + const char* filePath); private: // -- Settings @@ -808,9 +831,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, @@ -951,7 +974,7 @@ void cmQtAutoMocUicT::JobParseT::MocMacro() void cmQtAutoMocUicT::JobParseT::MocDependecies() { - if (MocConst().DependFilters.empty()) { + if (MocConst().DependFilters.empty() || MocConst().CanOutputDependencies) { return; } @@ -1674,8 +1697,13 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Generate(MappingHandleT const& mapping, if (Probe(*mapping, reason.get())) { // Register the parent directory for creation MocEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile)); + // Fetch the cache entry for the source file + std::string const& sourceFile = mapping->SourceFile->FileName; + ParseCacheT::GetOrInsertT cacheEntry = + BaseEval().ParseCache.GetOrInsert(sourceFile); // Add moc job - Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(mapping, std::move(reason)); + Gen()->WorkerPool().EmplaceJob<JobCompileMocT>( + mapping, std::move(reason), std::move(cacheEntry.first)); // Check if a moc job for a mocs_compilation.cpp entry was generated if (compFile) { MocEval().CompUpdated = true; @@ -1779,6 +1807,14 @@ cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency( std::string const& sourceDir, std::string const& includeString) const { using ResPair = std::pair<std::string, cmFileTime>; + // moc's dependency file contains absolute paths + if (MocConst().CanOutputDependencies) { + ResPair res{ includeString, {} }; + if (res.second.Load(res.first)) { + return res; + } + return {}; + } // Search in vicinity of the source { ResPair res{ sourceDir + includeString, {} }; @@ -1898,6 +1934,11 @@ void cmQtAutoMocUicT::JobProbeDepsFinishT::Process() Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>(); } + if (!BaseConst().DepFile.empty()) { + // Add job to merge dep files + Gen()->WorkerPool().EmplaceJob<JobDepFilesMergeT>(); + } + // Add finish job Gen()->WorkerPool().EmplaceJob<JobFinishT>(); } @@ -1916,9 +1957,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 +1987,10 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() } } // Add extra options - cmAppend(cmd, MocConst().OptionsExtra); + cm::append(cmd, MocConst().OptionsExtra); + if (MocConst().CanOutputDependencies) { + cmd.emplace_back("--output-dep-file"); + } // Add output file cmd.emplace_back("-o"); cmd.push_back(outputFile); @@ -1956,12 +2000,7 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() // Execute moc command cmWorkerPool::ProcessResultT result; - if (RunProcess(GenT::MOC, result, cmd, Reason.get())) { - // Moc command success. Print moc output. - if (!result.StdOut.empty()) { - Log().Info(GenT::MOC, result.StdOut); - } - } else { + if (!RunProcess(GenT::MOC, result, cmd, Reason.get())) { // Moc command failed std::string includers; if (!Mapping->IncluderFiles.empty()) { @@ -1976,6 +2015,28 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() MessagePath(outputFile), '\n', includers, result.ErrorMessage), cmd, result.StdOut); + return; + } + + // Moc command success. Print moc output. + if (!result.StdOut.empty()) { + Log().Info(GenT::MOC, result.StdOut); + } + + // Extract dependencies from the dep file moc generated for us + if (MocConst().CanOutputDependencies) { + const std::string depfile = outputFile + ".d"; + if (Log().Verbose()) { + Log().Info(GenT::MOC, + "Reading dependencies from " + MessagePath(depfile)); + } + if (!cmSystemTools::FileExists(depfile)) { + Log().Warning(GenT::MOC, + "Dependency file " + MessagePath(depfile) + + " does not exist."); + return; + } + CacheEntry->Moc.Depends = dependenciesFromDepFile(depfile.c_str()); } } @@ -1992,9 +2053,9 @@ void cmQtAutoMocUicT::JobCompileUicT::Process() auto optionIt = UicConst().UiFiles.find(sourceFile); if (optionIt != UicConst().UiFiles.end()) { UicMergeOptions(allOpts, optionIt->second.Options, - (BaseConst().QtVersionMajor == 5)); + (BaseConst().QtVersion.Major == 5)); } - cmAppend(cmd, allOpts); + cm::append(cmd, allOpts); } cmd.emplace_back("-o"); cmd.emplace_back(outputFile); @@ -2067,6 +2128,106 @@ void cmQtAutoMocUicT::JobMocsCompilationT::Process() } } +/* + * Escapes paths for Ninja depfiles. + * This is a re-implementation of what moc does when writing depfiles. + */ +std::string escapeDependencyPath(cm::string_view path) +{ + std::string escapedPath; + escapedPath.reserve(path.size()); + const size_t s = path.size(); + int backslashCount = 0; + for (size_t i = 0; i < s; ++i) { + if (path[i] == '\\') { + ++backslashCount; + } else { + if (path[i] == '$') { + escapedPath.push_back('$'); + } else if (path[i] == '#') { + escapedPath.push_back('\\'); + } else if (path[i] == ' ') { + // Double the amount of written backslashes, + // and add one more to escape the space. + while (backslashCount-- >= 0) { + escapedPath.push_back('\\'); + } + } + backslashCount = 0; + } + escapedPath.push_back(path[i]); + } + return escapedPath; +} + +void cmQtAutoMocUicT::JobDepFilesMergeT::Process() +{ + if (Log().Verbose()) { + Log().Info(GenT::MOC, "Merging MOC dependencies"); + } + auto processDepFile = + [](const std::string& mocOutputFile) -> std::vector<std::string> { + std::string f = mocOutputFile + ".d"; + if (!cmSystemTools::FileExists(f)) { + return {}; + } + return dependenciesFromDepFile(f.c_str()); + }; + + std::vector<std::string> dependencies; + ParseCacheT& parseCache = BaseEval().ParseCache; + auto processMappingEntry = [&](const MappingMapT::value_type& m) { + auto cacheEntry = parseCache.GetOrInsert(m.first); + if (cacheEntry.first->Moc.Depends.empty()) { + cacheEntry.first->Moc.Depends = processDepFile(m.second->OutputFile); + } + dependencies.insert(dependencies.end(), + cacheEntry.first->Moc.Depends.begin(), + cacheEntry.first->Moc.Depends.end()); + }; + + std::for_each(MocEval().HeaderMappings.begin(), + MocEval().HeaderMappings.end(), processMappingEntry); + std::for_each(MocEval().SourceMappings.begin(), + MocEval().SourceMappings.end(), processMappingEntry); + + // Remove duplicates to make the depfile smaller + std::sort(dependencies.begin(), dependencies.end()); + dependencies.erase(std::unique(dependencies.begin(), dependencies.end()), + dependencies.end()); + + // Add form files + for (const auto& uif : UicEval().UiFiles) { + dependencies.push_back(uif.first); + } + + // Write the file + cmsys::ofstream ofs; + ofs.open(BaseConst().DepFile.c_str(), + (std::ios::out | std::ios::binary | std::ios::trunc)); + if (!ofs) { + LogError(GenT::GEN, + cmStrCat("Cannot open ", MessagePath(BaseConst().DepFile), + " for writing.")); + return; + } + ofs << BaseConst().DepFileRuleName << ": \\" << std::endl; + for (const std::string& file : dependencies) { + ofs << '\t' << escapeDependencyPath(file) << " \\" << std::endl; + if (!ofs.good()) { + LogError(GenT::GEN, + cmStrCat("Writing depfile", MessagePath(BaseConst().DepFile), + " failed.")); + return; + } + } + + // Add the CMake executable to re-new cache data if necessary. + // Also, this is the last entry, so don't add a backslash. + ofs << '\t' << escapeDependencyPath(BaseConst().CMakeExecutable) + << std::endl; +} + void cmQtAutoMocUicT::JobFinishT::Process() { Gen()->AbortSuccess(); @@ -2082,7 +2243,8 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) { // -- Required settings if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) || - !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) || + !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersion.Major, true) || + !info.GetUInt("QT_VERSION_MINOR", BaseConst_.QtVersion.Minor, true) || !info.GetUInt("PARALLEL", BaseConst_.ThreadCount, false) || !info.GetString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) || !info.GetStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir, @@ -2090,6 +2252,9 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) !info.GetString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) || !info.GetStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile, true) || + !info.GetString("DEP_FILE", BaseConst_.DepFile, false) || + !info.GetString("DEP_FILE_RULE_NAME", BaseConst_.DepFileRuleName, + false) || !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) || !info.GetArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) || !info.GetString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) || @@ -2143,8 +2308,10 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) MocConst_.MacroFilters.emplace_back( item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]")); } - // Dependency filters - { + // Can moc output dependencies or do we need to setup dependency filters? + if (BaseConst_.QtVersion >= IntegerVersion(5, 15)) { + MocConst_.CanOutputDependencies = true; + } else { Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS"); if (!val.isArray()) { return info.LogError("MOC_DEPEND_FILTERS JSON value is not an array."); @@ -2660,6 +2827,19 @@ bool cmQtAutoMocUicT::CreateDirectories() return true; } +std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile( + const char* filePath) +{ + cmGccDepfileContent content = cmReadGccDepfile(filePath); + if (content.empty()) { + return {}; + } + + // Moc outputs a depfile with exactly one rule. + // Discard the rule and return the dependencies. + return content.front().paths; +} + void cmQtAutoMocUicT::Abort(bool error) { if (error) { diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx index 3af81ad..08eb4b5 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/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index 0a1d109..5ab1b3a 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -85,6 +85,11 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( return replaceValues.ObjectsQuoted; } } + if (replaceValues.AIXExports) { + if (variable == "AIX_EXPORTS") { + return replaceValues.AIXExports; + } + } if (replaceValues.Defines && variable == "DEFINES") { return replaceValues.Defines; } diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index 8f36196..09e8a3b 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -36,6 +36,7 @@ public: const char* TargetVersionMajor; const char* TargetVersionMinor; const char* Language; + const char* AIXExports; const char* Objects; const char* Target; const char* LinkLibraries; diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h index c8bb1ab..7d676c9 100644 --- a/Source/cmScriptGenerator.h +++ b/Source/cmScriptGenerator.h @@ -71,7 +71,7 @@ protected: std::string CreateConfigTest(const std::string& config); std::string CreateConfigTest(std::vector<std::string> const& configs); - std::string CreateComponentTest(const char* component); + std::string CreateComponentTest(const std::string& component); // Information shared by most generator types. std::string RuntimeConfigVariable; diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index d15ce57..766d347 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -181,7 +181,13 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths, const char* arch = this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); if (arch && *arch) { - this->AddPathInternal(dir + subdir + "/" + arch, base); + if (this->FC->Makefile->IsDefinitionSet("CMAKE_SYSROOT") && + this->FC->Makefile->IsDefinitionSet( + "CMAKE_PREFIX_LIBRARY_ARCHITECTURE")) { + this->AddPathInternal(cmStrCat('/', arch, dir, subdir), base); + } else { + this->AddPathInternal(cmStrCat(dir, subdir, '/', arch), base); + } } } std::string add = dir + subdir; diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h index 2a576ed..3ecc73b 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 56003df..1d4ea01 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 8c3a4cb..5e2a146 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/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 112d832..3705727 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -194,9 +194,8 @@ namespace { bool HandleGlobalMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, - const std::string& propertyValue, - const bool appendAsString, const bool appendMode, - const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { if (!names.empty()) { status.SetError("given names for GLOBAL scope."); @@ -205,14 +204,14 @@ bool HandleGlobalMode(cmExecutionStatus& status, // Set or append the property. cmake* cm = status.GetMakefile().GetCMakeInstance(); - const char* value = propertyValue.c_str(); - if (remove) { - value = nullptr; - } if (appendMode) { - cm->AppendProperty(propertyName, value ? value : "", appendAsString); + cm->AppendProperty(propertyName, propertyValue, appendAsString); } else { - cm->SetProperty(propertyName, value); + if (remove) { + cm->SetProperty(propertyName, nullptr); + } else { + cm->SetProperty(propertyName, propertyValue.c_str()); + } } return true; @@ -221,9 +220,8 @@ bool HandleGlobalMode(cmExecutionStatus& status, bool HandleDirectoryMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, - const std::string& propertyValue, - const bool appendAsString, const bool appendMode, - const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { if (names.size() > 1) { status.SetError("allows at most one name for DIRECTORY scope."); @@ -258,14 +256,14 @@ bool HandleDirectoryMode(cmExecutionStatus& status, } // Set or append the property. - const char* value = propertyValue.c_str(); - if (remove) { - value = nullptr; - } if (appendMode) { - mf->AppendProperty(propertyName, value ? value : "", appendAsString); + mf->AppendProperty(propertyName, propertyValue, appendAsString); } else { - mf->SetProperty(propertyName, value); + if (remove) { + mf->SetProperty(propertyName, nullptr); + } else { + mf->SetProperty(propertyName, propertyValue.c_str()); + } } return true; @@ -274,9 +272,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status, bool HandleTargetMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, - const std::string& propertyValue, - const bool appendAsString, const bool appendMode, - const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { for (std::string const& name : names) { if (status.GetMakefile().IsAlias(name)) { @@ -300,18 +297,18 @@ bool HandleTargetMode(cmExecutionStatus& status, bool HandleTarget(cmTarget* target, cmMakefile& makefile, const std::string& propertyName, - const std::string& propertyValue, const bool appendAsString, - const bool appendMode, const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { // Set or append the property. - const char* value = propertyValue.c_str(); - if (remove) { - value = nullptr; - } if (appendMode) { - target->AppendProperty(propertyName, value, appendAsString); + target->AppendProperty(propertyName, propertyValue, appendAsString); } else { - target->SetProperty(propertyName, value); + if (remove) { + target->SetProperty(propertyName, nullptr); + } else { + target->SetProperty(propertyName, propertyValue.c_str()); + } } // Check the resulting value. @@ -323,9 +320,8 @@ bool HandleTarget(cmTarget* target, cmMakefile& makefile, bool HandleSourceMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, - const std::string& propertyValue, - const bool appendAsString, const bool appendMode, - const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { for (std::string const& name : names) { // Get the source file. @@ -344,28 +340,26 @@ bool HandleSourceMode(cmExecutionStatus& status, } bool HandleSource(cmSourceFile* sf, const std::string& propertyName, - const std::string& propertyValue, const bool appendAsString, - const bool appendMode, const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { // Set or append the property. - const char* value = propertyValue.c_str(); - if (remove) { - value = nullptr; - } - if (appendMode) { - sf->AppendProperty(propertyName, value, appendAsString); + sf->AppendProperty(propertyName, propertyValue, appendAsString); } else { - sf->SetProperty(propertyName, value); + if (remove) { + sf->SetProperty(propertyName, nullptr); + } else { + sf->SetProperty(propertyName, propertyValue.c_str()); + } } return true; } bool HandleTestMode(cmExecutionStatus& status, std::set<std::string>& names, const std::string& propertyName, - const std::string& propertyValue, - const bool appendAsString, const bool appendMode, - const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { // Look for tests with all names given. std::set<std::string>::iterator next; @@ -396,18 +390,18 @@ bool HandleTestMode(cmExecutionStatus& status, std::set<std::string>& names, } bool HandleTest(cmTest* test, const std::string& propertyName, - const std::string& propertyValue, const bool appendAsString, - const bool appendMode, const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { // Set or append the property. - const char* value = propertyValue.c_str(); - if (remove) { - value = nullptr; - } if (appendMode) { - test->AppendProperty(propertyName, value, appendAsString); + test->AppendProperty(propertyName, propertyValue, appendAsString); } else { - test->SetProperty(propertyName, value); + if (remove) { + test->SetProperty(propertyName, nullptr); + } else { + test->SetProperty(propertyName, propertyValue.c_str()); + } } return true; @@ -416,9 +410,8 @@ bool HandleTest(cmTest* test, const std::string& propertyName, bool HandleCacheMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, - const std::string& propertyValue, - const bool appendAsString, const bool appendMode, - const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { if (propertyName == "ADVANCED") { if (!remove && !cmIsOn(propertyValue) && !cmIsOff(propertyValue)) { @@ -463,9 +456,8 @@ bool HandleCacheMode(cmExecutionStatus& status, bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile, const std::string& propertyName, - const std::string& propertyValue, - const bool appendAsString, const bool appendMode, - const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { // Set or append the property. const char* value = propertyValue.c_str(); @@ -486,9 +478,8 @@ bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile, bool HandleInstallMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, - const std::string& propertyValue, - const bool appendAsString, const bool appendMode, - const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { cmake* cm = status.GetMakefile().GetCMakeInstance(); @@ -510,8 +501,8 @@ bool HandleInstallMode(cmExecutionStatus& status, bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile, const std::string& propertyName, - const std::string& propertyValue, const bool appendAsString, - const bool appendMode, const bool remove) + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove) { // Set or append the property. const char* value = propertyValue.c_str(); diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index 8d917db..cd0fa40 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 de61eda..2e7aeca 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.cxx b/Source/cmSourceFile.cxx index 2a345eb..fd9cacd 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -128,7 +128,7 @@ bool cmSourceFile::FindFullPath(std::string* error) // The file is not generated. It must exist on disk. cmMakefile const* makefile = this->Location.GetMakefile(); // Location path - std::string const lPath = this->Location.GetFullPath(); + std::string const& lPath = this->Location.GetFullPath(); // List of extension lists std::array<std::vector<std::string> const*, 2> const extsLists = { { &makefile->GetCMakeInstance()->GetSourceExtensions(), @@ -145,7 +145,7 @@ bool cmSourceFile::FindFullPath(std::string* error) return true; } // Try full path with extension - for (auto exts : extsLists) { + for (auto& exts : extsLists) { for (std::string const& ext : *exts) { if (!ext.empty()) { std::string extPath = cmStrCat(fullPath, '.', ext); @@ -260,21 +260,21 @@ void cmSourceFile::SetProperty(const std::string& prop, const char* value) } } -void cmSourceFile::AppendProperty(const std::string& prop, const char* value, - bool asString) +void cmSourceFile::AppendProperty(const std::string& prop, + const std::string& value, bool asString) { if (prop == propINCLUDE_DIRECTORIES) { - if (value && *value) { + if (!value.empty()) { cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); this->IncludeDirectories.emplace_back(value, lfbt); } } else if (prop == propCOMPILE_OPTIONS) { - if (value && *value) { + if (!value.empty()) { cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); this->CompileOptions.emplace_back(value, lfbt); } } else if (prop == propCOMPILE_DEFINITIONS) { - if (value && *value) { + if (!value.empty()) { cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); this->CompileDefinitions.emplace_back(value, lfbt); } diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 82a3625..e22829f 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -42,7 +42,7 @@ public: //! Set/Get a property of this source file void SetProperty(const std::string& prop, const char* value); - void AppendProperty(const std::string& prop, const char* value, + void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); //! Might return a nullptr if the property is not set or invalid const char* GetProperty(const std::string& prop) const; @@ -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/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index df702b0..5f807b8 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -31,7 +31,8 @@ cmSourceFileLocation::cmSourceFileLocation(cmMakefile const* mf, this->AmbiguousExtension = true; this->Directory = cmSystemTools::GetFilenamePath(name); if (cmSystemTools::FileIsFullPath(this->Directory)) { - this->Directory = cmSystemTools::CollapseFullPath(this->Directory); + this->Directory = cmSystemTools::CollapseFullPath( + this->Directory, mf->GetHomeOutputDirectory()); } this->Name = cmSystemTools::GetFilenameName(name); if (kind == cmSourceFileLocationKind::Known) { diff --git a/Source/cmState.cxx b/Source/cmState.cxx index f9b5ed1..0ce8dd7 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() @@ -562,8 +557,8 @@ void cmState::SetGlobalProperty(const std::string& prop, const char* value) this->GlobalProperties.SetProperty(prop, value); } -void cmState::AppendGlobalProperty(const std::string& prop, const char* value, - bool asString) +void cmState::AppendGlobalProperty(const std::string& prop, + const std::string& value, bool asString) { this->GlobalProperties.AppendProperty(prop, value, asString); } @@ -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 a7ca015..817046f 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, @@ -166,7 +168,7 @@ public: std::vector<std::string> GetCommandNames() const; void SetGlobalProperty(const std::string& prop, const char* value); - void AppendGlobalProperty(const std::string& prop, const char* value, + void AppendGlobalProperty(const std::string& prop, const std::string& value, bool asString = false); const char* GetGlobalProperty(const std::string& prop); bool GetGlobalPropertyAsBool(const std::string& prop); @@ -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 1262f53..4f003ed 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" @@ -520,7 +521,7 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value, } void cmStateDirectory::AppendProperty(const std::string& prop, - const char* value, bool asString, + const std::string& value, bool asString, cmListFileBacktrace const& lfbt) { if (prop == "INCLUDE_DIRECTORIES") { @@ -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/cmStateDirectory.h b/Source/cmStateDirectory.h index fe15563..53a2d54 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -84,7 +84,7 @@ public: void SetProperty(const std::string& prop, const char* value, cmListFileBacktrace const& lfbt); - void AppendProperty(const std::string& prop, const char* value, + void AppendProperty(const std::string& prop, const std::string& value, bool asString, cmListFileBacktrace const& lfbt); const char* GetProperty(const std::string& prop) const; const char* GetProperty(const std::string& prop, bool chain) const; diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 645907c..832e74e 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/cmString.hxx b/Source/cmString.hxx index 073f4c9..9e91986 100644 --- a/Source/cmString.hxx +++ b/Source/cmString.hxx @@ -88,18 +88,6 @@ struct IntoString<std::string> : std::true_type }; template <> -struct IntoString<string_view> : std::true_type -{ - static std::string into_string(string_view s) { return std::string(s); } -}; - -template <> -struct IntoString<static_string_view> : std::true_type -{ - static string_view into_string(static_string_view s) { return s; } -}; - -template <> struct IntoString<char> : std::true_type { static std::string into_string(char const& c) { return std::string(1, c); } @@ -239,6 +227,25 @@ public: { } + /** + * Construct via static_string_view constructor. + * explicit is required to avoid ambiguous overloaded operators (i.e ==, + * etc...) with the ones provided by string_view. + */ + explicit String(static_string_view s) + : String(s, Private()) + { + } + /** + * Construct via string_view constructor. + * explicit is required to avoid ambiguous overloaded operators (i.e ==, + * etc...) with the ones provided by string_view. + */ + explicit String(string_view s) + : String(std::string(s), Private()) + { + } + /** Construct via std::string initializer list constructor. */ String(std::initializer_list<char> il) : String(std::string(il)) @@ -306,6 +313,17 @@ public: This shares ownership of the other string's buffer. */ String& operator=(String const&) noexcept = default; + String& operator=(static_string_view s) + { + *this = String(s); + return *this; + } + String& operator=(string_view s) + { + *this = String(s); + return *this; + } + /** Assign from any type implementing the IntoString trait. */ template <typename T> typename // NOLINT(*) @@ -328,6 +346,7 @@ public: /** Return a view of the string. */ string_view view() const noexcept { return view_; } + operator string_view() const noexcept { return this->view(); } /** Return true if the instance is an empty stringn or null string. */ bool empty() const noexcept { return view_.empty(); } @@ -638,58 +657,155 @@ private: string_view view_; }; -template <typename L, typename R> -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, - bool>::type -operator==(L&& l, R&& r) +/** + * Trait for comparable types. + */ +template <typename T> +struct IsComparable : std::false_type +{ +}; + +template <typename T> +struct IsComparable<T&> : IsComparable<T> +{ +}; + +template <typename T> +struct IsComparable<T const> : IsComparable<T> +{ +}; + +template <typename T> +struct IsComparable<T const*> : IsComparable<T*> +{ +}; + +template <typename T, std::string::size_type N> +struct IsComparable<T const[N]> : IsComparable<T[N]> +{ +}; + +template <> +struct IsComparable<char*> : std::true_type { - return (AsStringView<L>::view(std::forward<L>(l)) == - AsStringView<R>::view(std::forward<R>(r))); +}; + +template <std::string::size_type N> +struct IsComparable<char[N]> : std::true_type +{ +}; + +template <> +struct IsComparable<std::string> : std::true_type +{ +}; + +template <> +struct IsComparable<char> : std::true_type +{ +}; + +/** comparison operators */ +inline bool operator==(const String& l, const String& r) +{ + return l.view() == r.view(); +} +template <typename L> +typename std::enable_if<IsComparable<L>::value, bool>::type operator==( + L&& l, const String& r) +{ + return AsStringView<L>::view(std::forward<L>(l)) == r.view(); +} +template <typename R> +typename std::enable_if<IsComparable<R>::value, bool>::type operator==( + const String& l, R&& r) +{ + return l.view() == AsStringView<R>::view(std::forward<R>(r)); } -template <typename L, typename R> -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, - bool>::type -operator!=(L&& l, R&& r) +inline bool operator!=(const String& l, const String& r) +{ + return l.view() != r.view(); +} +template <typename L> +typename std::enable_if<IsComparable<L>::value, bool>::type operator!=( + L&& l, const String& r) { - return (AsStringView<L>::view(std::forward<L>(l)) != - AsStringView<R>::view(std::forward<R>(r))); + return AsStringView<L>::view(std::forward<L>(l)) != r.view(); +} +template <typename R> +typename std::enable_if<IsComparable<R>::value, bool>::type operator!=( + const String& l, R&& r) +{ + return l.view() != AsStringView<R>::view(std::forward<R>(r)); } -template <typename L, typename R> -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, - bool>::type -operator<(L&& l, R&& r) +inline bool operator<(const String& l, const String& r) { - return (AsStringView<L>::view(std::forward<L>(l)) < - AsStringView<R>::view(std::forward<R>(r))); + return l.view() < r.view(); +} +template <typename L> +typename std::enable_if<IsComparable<L>::value, bool>::type operator<( + L&& l, const String& r) +{ + return AsStringView<L>::view(std::forward<L>(l)) < r.view(); +} +template <typename R> +typename std::enable_if<IsComparable<R>::value, bool>::type operator<( + const String& l, R&& r) +{ + return l.view() < AsStringView<R>::view(std::forward<R>(r)); } -template <typename L, typename R> -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, - bool>::type -operator<=(L&& l, R&& r) +inline bool operator<=(const String& l, const String& r) +{ + return l.view() <= r.view(); +} +template <typename L> +typename std::enable_if<IsComparable<L>::value, bool>::type operator<=( + L&& l, const String& r) +{ + return AsStringView<L>::view(std::forward<L>(l)) <= r.view(); +} +template <typename R> +typename std::enable_if<IsComparable<R>::value, bool>::type operator<=( + const String& l, R&& r) { - return (AsStringView<L>::view(std::forward<L>(l)) <= - AsStringView<R>::view(std::forward<R>(r))); + return l.view() <= AsStringView<R>::view(std::forward<R>(r)); } -template <typename L, typename R> -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, - bool>::type -operator>(L&& l, R&& r) +inline bool operator>(const String& l, const String& r) +{ + return l.view() > r.view(); +} +template <typename L> +typename std::enable_if<IsComparable<L>::value, bool>::type operator>( + L&& l, const String& r) +{ + return AsStringView<L>::view(std::forward<L>(l)) > r.view(); +} +template <typename R> +typename std::enable_if<IsComparable<R>::value, bool>::type operator>( + const String& l, R&& r) { - return (AsStringView<L>::view(std::forward<L>(l)) > - AsStringView<R>::view(std::forward<R>(r))); + return l.view() > AsStringView<R>::view(std::forward<R>(r)); } -template <typename L, typename R> -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value, - bool>::type -operator>=(L&& l, R&& r) +inline bool operator>=(const String& l, const String& r) +{ + return l.view() >= r.view(); +} +template <typename L> +typename std::enable_if<IsComparable<L>::value, bool>::type operator>=( + L&& l, const String& r) +{ + return AsStringView<L>::view(std::forward<L>(l)) >= r.view(); +} +template <typename R> +typename std::enable_if<IsComparable<R>::value, bool>::type operator>=( + const String& l, R&& r) { - return (AsStringView<L>::view(std::forward<L>(l)) >= - AsStringView<R>::view(std::forward<R>(r))); + return l.view() >= AsStringView<R>::view(std::forward<R>(r)); } std::ostream& operator<<(std::ostream& os, String const& s); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index c4a4220..9127c50 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 80986fc..d0b6f10 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" @@ -38,13 +39,13 @@ #include "cmake.h" template <> -const char* cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>( +const std::string& cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>( cmTarget const* tgt) { static std::string loc; if (tgt->IsImported()) { loc = tgt->ImportedGetFullPath("", cmStateEnums::RuntimeBinaryArtifact); - return loc.c_str(); + return loc; } cmGlobalGenerator* gg = tgt->GetGlobalGenerator(); @@ -53,18 +54,18 @@ const char* cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>( } cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName()); loc = gt->GetLocationForBuild(); - return loc.c_str(); + return loc; } template <> -const char* cmTargetPropertyComputer::ComputeLocation<cmTarget>( +const std::string& cmTargetPropertyComputer::ComputeLocation<cmTarget>( cmTarget const* tgt, const std::string& config) { static std::string loc; if (tgt->IsImported()) { loc = tgt->ImportedGetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); - return loc.c_str(); + return loc; } cmGlobalGenerator* gg = tgt->GetGlobalGenerator(); @@ -73,7 +74,7 @@ const char* cmTargetPropertyComputer::ComputeLocation<cmTarget>( } cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName()); loc = gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); - return loc.c_str(); + return loc; } template <> @@ -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 = @@ -355,9 +358,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("CUDA_COMPILER_LAUNCHER"); initProp("CUDA_SEPARABLE_COMPILATION"); initProp("CUDA_RESOLVE_DEVICE_SYMBOLS"); + initProp("CUDA_RUNTIME_LIBRARY"); 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"); @@ -373,6 +376,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"); @@ -382,11 +386,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"); } @@ -437,30 +444,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 && @@ -484,6 +491,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, } if (impl->TargetType == cmStateEnums::SHARED_LIBRARY || impl->TargetType == cmStateEnums::EXECUTABLE) { + initProp("AIX_EXPORT_ALL_SYMBOLS"); initProp("WINDOWS_EXPORT_ALL_SYMBOLS"); } @@ -507,14 +515,15 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->GetType() != cmStateEnums::UTILITY) { initProp("JOB_POOL_COMPILE"); initProp("JOB_POOL_LINK"); + initProp("JOB_POOL_PRECOMPILE_HEADER"); } if (impl->TargetType <= cmStateEnums::UTILITY) { + initProp("DOTNET_TARGET_FRAMEWORK"); 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 @@ -932,14 +941,7 @@ cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries() return impl->OriginalLinkLibraries; } -void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib, - cmTargetLinkLibraryType llt) -{ - this->AddLinkLibrary(mf, lib, lib, llt); -} - void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, - std::string const& libRef, cmTargetLinkLibraryType llt) { cmTarget* tgt = mf.FindTargetToUse(lib); @@ -948,14 +950,13 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, const std::string libName = (isNonImportedTarget && llt != GENERAL_LibraryType) - ? targetNameGenex(libRef) - : libRef; - this->AppendProperty( - "LINK_LIBRARIES", - this->GetDebugGeneratorExpressions(libName, llt).c_str()); + ? targetNameGenex(lib) + : lib; + this->AppendProperty("LINK_LIBRARIES", + this->GetDebugGeneratorExpressions(libName, llt)); } - if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef || + if (cmGeneratorExpression::Find(lib) != std::string::npos || (tgt && (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY || tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) || @@ -1286,9 +1287,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")); @@ -1298,8 +1299,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) } } -void cmTarget::AppendProperty(const std::string& prop, const char* value, - bool asString) +void cmTarget::AppendProperty(const std::string& prop, + const std::string& value, bool asString) { if (!cmTargetPropertyComputer::PassesWhitelist( this->GetType(), prop, impl->Makefile->GetMessenger(), @@ -1334,37 +1335,37 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, return; } if (prop == "INCLUDE_DIRECTORIES") { - if (value && *value) { + if (!value.empty()) { impl->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->IncludeDirectoriesBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_OPTIONS") { - if (value && *value) { + if (!value.empty()) { impl->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->CompileOptionsBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_FEATURES") { - if (value && *value) { + if (!value.empty()) { impl->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->CompileFeaturesBacktraces.push_back(lfbt); } } else if (prop == "COMPILE_DEFINITIONS") { - if (value && *value) { + if (!value.empty()) { impl->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->CompileDefinitionsBacktraces.push_back(lfbt); } } else if (prop == "LINK_OPTIONS") { - if (value && *value) { + if (!value.empty()) { impl->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->LinkOptionsBacktraces.push_back(lfbt); } } else if (prop == "LINK_DIRECTORIES") { - if (value && *value) { + if (!value.empty()) { impl->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->LinkDirectoriesBacktraces.push_back(lfbt); @@ -1378,13 +1379,13 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; } - if (value && *value) { + if (!value.empty()) { impl->PrecompileHeadersEntries.emplace_back(value); cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->PrecompileHeadersBacktraces.push_back(lfbt); } } else if (prop == "LINK_LIBRARIES") { - if (value && *value) { + if (!value.empty()) { cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->LinkImplementationPropertyEntries.emplace_back(value); impl->LinkImplementationPropertyBacktraces.push_back(lfbt); @@ -1423,7 +1424,7 @@ void cmTarget::AppendBuildInterfaceIncludes() dirs += impl->Makefile->GetCurrentSourceDirectory(); if (!dirs.empty()) { this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", - ("$<BUILD_INTERFACE:" + dirs + ">").c_str()); + ("$<BUILD_INTERFACE:" + dirs + ">")); } } } @@ -1558,8 +1559,12 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, cmMakefile* context) { - std::vector<cmTarget*> targets = context->GetOwnedImportedTargets(); - auto it = std::find(targets.begin(), targets.end(), target); + const auto& targets = context->GetOwnedImportedTargets(); + auto it = + std::find_if(targets.begin(), targets.end(), + [&](const std::unique_ptr<cmTarget>& importTarget) -> bool { + return target == importTarget.get(); + }); if (it == targets.end()) { std::ostringstream e; e << "Attempt to promote imported target \"" << target->GetName() @@ -1801,6 +1806,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 65a1ce3..d4cca23 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; @@ -110,10 +110,8 @@ public: //! Clear the dependency information recorded for this target, if any. void ClearDependencyInformation(cmMakefile& mf); - void AddLinkLibrary(cmMakefile& mf, const std::string& lib, - cmTargetLinkLibraryType llt); void AddLinkLibrary(cmMakefile& mf, std::string const& lib, - std::string const& libRef, cmTargetLinkLibraryType llt); + cmTargetLinkLibraryType llt); enum TLLSignature { @@ -164,7 +162,11 @@ public: //! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); - void AppendProperty(const std::string& prop, const char* value, + void SetProperty(const std::string& prop, const std::string& value) + { + SetProperty(prop, value.c_str()); + } + void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); //! Might return a nullptr if the property is not set or invalid const char* GetProperty(const std::string& prop) const; @@ -186,6 +188,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 edee167..b56b245 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 e39b726..dee2c10 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 95b69f3..35635b9 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 0d2383a..df751da 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -3,7 +3,10 @@ #include "cmTargetLinkLibrariesCommand.h" #include <cstring> +#include <memory> #include <sstream> +#include <unordered_set> +#include <utility> #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" @@ -34,15 +37,30 @@ enum ProcessingState const char* LinkLibraryTypeNames[3] = { "general", "debug", "optimized" }; +struct TLL +{ + cmMakefile& Makefile; + cmTarget* Target; + bool WarnRemoteInterface = false; + bool RejectRemoteLinking = false; + bool EncodeRemoteReference = false; + std::string DirectoryId; + std::unordered_set<std::string> Props; + + TLL(cmMakefile& mf, cmTarget* target); + ~TLL(); + + bool HandleLibrary(ProcessingState currentProcessingState, + const std::string& lib, cmTargetLinkLibraryType llt); + void AppendProperty(std::string const& prop, std::string const& value); + void AffectsProperty(std::string const& prop); +}; + } // namespace static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left, int right); -static bool HandleLibrary(cmMakefile& mf, cmTarget* target, - ProcessingState currentProcessingState, - const std::string& lib, cmTargetLinkLibraryType llt); - bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -64,11 +82,9 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, cmTarget* target = mf.GetCMakeInstance()->GetGlobalGenerator()->FindTarget(args[0]); if (!target) { - const std::vector<cmTarget*>& importedTargets = - mf.GetOwnedImportedTargets(); - for (cmTarget* importedTarget : importedTargets) { + for (const auto& importedTarget : mf.GetOwnedImportedTargets()) { if (importedTarget->GetName() == args[0]) { - target = importedTarget; + target = importedTarget.get(); break; } } @@ -149,6 +165,8 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, return true; } + TLL tll(mf, target); + // Keep track of link configuration specifiers. cmTargetLinkLibraryType llt = GENERAL_LibraryType; bool haveLLT = false; @@ -247,7 +265,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, } else if (haveLLT) { // The link type was specified by the previous argument. haveLLT = false; - if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) { + if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) { return false; } } else { @@ -268,7 +286,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, llt = OPTIMIZED_LibraryType; } } - if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) { + if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) { return false; } } @@ -311,21 +329,48 @@ static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left, "\" instead of a library name. The first specifier will be ignored.")); } -static bool HandleLibrary(cmMakefile& mf, cmTarget* target, - ProcessingState currentProcessingState, - const std::string& lib, cmTargetLinkLibraryType llt) +namespace { + +TLL::TLL(cmMakefile& mf, cmTarget* target) + : Makefile(mf) + , Target(target) +{ + if (&this->Makefile != this->Target->GetMakefile()) { + // The LHS target was created in another directory. + switch (this->Makefile.GetPolicyStatus(cmPolicies::CMP0079)) { + case cmPolicies::WARN: + this->WarnRemoteInterface = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + this->RejectRemoteLinking = true; + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + this->EncodeRemoteReference = true; + break; + } + } + if (this->EncodeRemoteReference) { + cmDirectoryId const dirId = this->Makefile.GetDirectoryId(); + this->DirectoryId = cmStrCat(CMAKE_DIRECTORY_ID_SEP, dirId.String); + } +} + +bool TLL::HandleLibrary(ProcessingState currentProcessingState, + const std::string& lib, cmTargetLinkLibraryType llt) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY && + if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && currentProcessingState != ProcessingKeywordLinkInterface) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, "INTERFACE library can only be used with the INTERFACE keyword of " "target_link_libraries"); return false; } - if (target->IsImported() && + if (this->Target->IsImported() && currentProcessingState != ProcessingKeywordLinkInterface) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, "IMPORTED library can only be used with the INTERFACE keyword of " "target_link_libraries"); @@ -340,11 +385,12 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, currentProcessingState == ProcessingKeywordLinkInterface) ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature; - if (!target->PushTLLCommandTrace(sig, mf.GetExecutionContext())) { + if (!this->Target->PushTLLCommandTrace( + sig, this->Makefile.GetExecutionContext())) { std::ostringstream e; const char* modal = nullptr; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (mf.GetPolicyStatus(cmPolicies::CMP0023)) { + switch (this->Makefile.GetPolicyStatus(cmPolicies::CMP0023)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n"; modal = "should"; @@ -365,73 +411,38 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, e << "The " << existingSig << " signature for target_link_libraries has " "already been used with the target \"" - << target->GetName() + << this->Target->GetName() << "\". All uses of target_link_libraries with a target " << modal << " be either all-keyword or all-plain.\n"; - target->GetTllSignatureTraces(e, - sig == cmTarget::KeywordTLLSignature - ? cmTarget::PlainTLLSignature - : cmTarget::KeywordTLLSignature); - mf.IssueMessage(messageType, e.str()); + this->Target->GetTllSignatureTraces(e, + sig == cmTarget::KeywordTLLSignature + ? cmTarget::PlainTLLSignature + : cmTarget::KeywordTLLSignature); + this->Makefile.IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } } } - bool warnRemoteInterface = false; - bool rejectRemoteLinking = false; - bool encodeRemoteReference = false; - if (&mf != target->GetMakefile()) { - // The LHS target was created in another directory. - switch (mf.GetPolicyStatus(cmPolicies::CMP0079)) { - case cmPolicies::WARN: - warnRemoteInterface = true; - CM_FALLTHROUGH; - case cmPolicies::OLD: - rejectRemoteLinking = true; - break; - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::NEW: - encodeRemoteReference = true; - break; - } - } - - std::string libRef; - if (encodeRemoteReference && !cmSystemTools::FileIsFullPath(lib)) { - // This is a library name added by a caller that is not in the - // same directory as the target was created. Add a suffix to - // the name to tell ResolveLinkItem to look up the name in the - // caller's directory. - cmDirectoryId const dirId = mf.GetDirectoryId(); - libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String; - } else { - // This is an absolute path or a library name added by a caller - // in the same directory as the target was created. We can use - // the original name directly. - libRef = lib; - } - // Handle normal case where the command was called with another keyword than // INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES" // property of the target on the LHS shall be populated.) if (currentProcessingState != ProcessingKeywordLinkInterface && currentProcessingState != ProcessingPlainLinkInterface) { - if (rejectRemoteLinking) { - mf.IssueMessage( + if (this->RejectRemoteLinking) { + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, cmStrCat("Attempt to add link library \"", lib, "\" to target \"", - target->GetName(), + this->Target->GetName(), "\" which is not built in this " "directory.\nThis is allowed only when policy CMP0079 " "is set to NEW.")); return false; } - cmTarget* tgt = mf.GetGlobalGenerator()->FindTarget(lib); + cmTarget* tgt = this->Makefile.GetGlobalGenerator()->FindTarget(lib); if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) && (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) && @@ -439,7 +450,7 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) && (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) && !tgt->IsExecutableWithExports()) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, cmStrCat( "Target \"", lib, "\" of type ", @@ -449,15 +460,16 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, "executables with the ENABLE_EXPORTS property set.")); } - target->AddLinkLibrary(mf, lib, libRef, llt); + this->AffectsProperty("LINK_LIBRARIES"); + this->Target->AddLinkLibrary(this->Makefile, lib, llt); } - if (warnRemoteInterface) { - mf.IssueMessage( + if (this->WarnRemoteInterface) { + this->Makefile.IssueMessage( MessageType::AUTHOR_WARNING, cmStrCat( cmPolicies::GetPolicyWarning(cmPolicies::CMP0079), "\nTarget\n ", - target->GetName(), + this->Target->GetName(), "\nis not created in this " "directory. For compatibility with older versions of CMake, link " "library\n ", @@ -472,15 +484,15 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // STATIC library.) if (currentProcessingState == ProcessingKeywordPrivateInterface || currentProcessingState == ProcessingPlainPrivateInterface) { - if (target->GetType() == cmStateEnums::STATIC_LIBRARY || - target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY || + this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { std::string configLib = - target->GetDebugGeneratorExpressions(libRef, llt); + this->Target->GetDebugGeneratorExpressions(lib, llt); if (cmGeneratorExpression::IsValidTargetName(lib) || cmGeneratorExpression::Find(lib) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } - target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib.c_str()); + this->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib); } return true; } @@ -488,9 +500,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()); + this->AppendProperty("INTERFACE_LINK_LIBRARIES", + this->Target->GetDebugGeneratorExpressions(lib, llt)); // Stop processing if called without any keyword. if (currentProcessingState == ProcessingLinkLibraries) { @@ -498,13 +509,13 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, } // Stop processing if policy CMP0022 is set to NEW. const cmPolicies::PolicyStatus policy22Status = - target->GetPolicyStatusCMP0022(); + this->Target->GetPolicyStatusCMP0022(); if (policy22Status != cmPolicies::OLD && policy22Status != cmPolicies::WARN) { return true; } // Stop processing if called with an INTERFACE library on the LHS. - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { return true; } @@ -514,7 +525,7 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, { // Get the list of configurations considered to be DEBUG. std::vector<std::string> debugConfigs = - mf.GetCMakeInstance()->GetDebugConfigs(); + this->Makefile.GetCMakeInstance()->GetDebugConfigs(); std::string prop; // Include this library in the link interface for the target. @@ -522,22 +533,49 @@ 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()); + this->AppendProperty(prop, lib); } } if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) { // Put in the non-DEBUG configuration interfaces. - target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.c_str()); + this->AppendProperty("LINK_INTERFACE_LIBRARIES", lib); // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - if (!target->GetProperty(prop)) { - target->SetProperty(prop, ""); + if (!this->Target->GetProperty(prop)) { + this->Target->SetProperty(prop, ""); } } } } return true; } + +void TLL::AppendProperty(std::string const& prop, std::string const& value) +{ + this->AffectsProperty(prop); + this->Target->AppendProperty(prop, value); +} + +void TLL::AffectsProperty(std::string const& prop) +{ + if (!this->EncodeRemoteReference) { + return; + } + // Add a wrapper to the expression to tell LookupLinkItems to look up + // names in the caller's directory. + if (this->Props.insert(prop).second) { + this->Target->AppendProperty(prop, this->DirectoryId); + } +} + +TLL::~TLL() +{ + for (std::string const& prop : this->Props) { + this->Target->AppendProperty(prop, CMAKE_DIRECTORY_ID_SEP); + } +} + +} // namespace diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx index c6e2e5c..0670bd9 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 bbc1e16..0de8d6d 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 baab8da..f37995c 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/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index 3b11acd..df34f18 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -46,10 +46,10 @@ private: cmListFileBacktrace const& context); template <typename Target> - static const char* ComputeLocationForBuild(Target const* tgt); + static const std::string& ComputeLocationForBuild(Target const* tgt); template <typename Target> - static const char* ComputeLocation(Target const* tgt, - std::string const& config); + static const std::string& ComputeLocation(Target const* tgt, + std::string const& config); template <typename Target> static const char* GetLocation(Target const* tgt, std::string const& prop, @@ -71,7 +71,7 @@ private: context)) { return nullptr; } - return ComputeLocationForBuild(tgt); + return ComputeLocationForBuild(tgt).c_str(); } // Support "LOCATION_<CONFIG>". @@ -82,7 +82,7 @@ private: return nullptr; } std::string configName = prop.substr(9); - return ComputeLocation(tgt, configName); + return ComputeLocation(tgt, configName).c_str(); } // Support "<CONFIG>_LOCATION". @@ -95,7 +95,7 @@ private: context)) { return nullptr; } - return ComputeLocation(tgt, configName); + return ComputeLocation(tgt, configName).c_str(); } } } diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index c2e0b28..a1fbc9b 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/cmTest.cxx b/Source/cmTest.cxx index d5c61c1..3b731cc 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -55,7 +55,7 @@ void cmTest::SetProperty(const std::string& prop, const char* value) this->Properties.SetProperty(prop, value); } -void cmTest::AppendProperty(const std::string& prop, const char* value, +void cmTest::AppendProperty(const std::string& prop, const std::string& value, bool asString) { this->Properties.AppendProperty(prop, value, asString); diff --git a/Source/cmTest.h b/Source/cmTest.h index dd246c4..72d4ed9 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -35,7 +35,7 @@ public: //! Set/Get a property of this source file void SetProperty(const std::string& prop, const char* value); - void AppendProperty(const std::string& prop, const char* value, + void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); const char* GetProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx index 4995da9..35e1c8c 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 e4b3b7c..6c418ed 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 f2c8f3c..35b9a1d 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 7e8e610..6b45442 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -6,6 +6,7 @@ #include <set> #include <cm/memory> +#include <cm/vector> #include "windows.h" @@ -52,7 +53,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 +61,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 +72,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 +104,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 +127,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 +270,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 +278,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 +331,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 +373,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"); @@ -488,23 +484,33 @@ void cmVisualStudio10TargetGenerator::Generate() } e1.Element("ProjectName", projLabel); { - // TODO: add deprecation warning for VS_* property? - const char* targetFrameworkVersion = - this->GeneratorTarget->GetProperty( - "VS_DOTNET_TARGET_FRAMEWORK_VERSION"); - if (!targetFrameworkVersion) { - targetFrameworkVersion = this->GeneratorTarget->GetProperty( - "DOTNET_TARGET_FRAMEWORK_VERSION"); - } - if (!targetFrameworkVersion && this->ProjectType == csproj && - this->GlobalGenerator->TargetsWindowsCE() && - this->GlobalGenerator->GetVersion() == - cmGlobalVisualStudioGenerator::VS12) { - // VS12 .NETCF default to .NET framework 3.9 - targetFrameworkVersion = "v3.9"; - } - if (targetFrameworkVersion) { - e1.Element("TargetFrameworkVersion", targetFrameworkVersion); + const char* targetFramework = + this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK"); + if (targetFramework) { + if (std::strchr(targetFramework, ';') != nullptr) { + e1.Element("TargetFrameworks", targetFramework); + } else { + e1.Element("TargetFramework", targetFramework); + } + } else { + // TODO: add deprecation warning for VS_* property? + const char* targetFrameworkVersion = + this->GeneratorTarget->GetProperty( + "VS_DOTNET_TARGET_FRAMEWORK_VERSION"); + if (!targetFrameworkVersion) { + targetFrameworkVersion = this->GeneratorTarget->GetProperty( + "DOTNET_TARGET_FRAMEWORK_VERSION"); + } + if (!targetFrameworkVersion && this->ProjectType == csproj && + this->GlobalGenerator->TargetsWindowsCE() && + this->GlobalGenerator->GetVersion() == + cmGlobalVisualStudioGenerator::VS12) { + // VS12 .NETCF default to .NET framework 3.9 + targetFrameworkVersion = "v3.9"; + } + if (targetFrameworkVersion) { + e1.Element("TargetFrameworkVersion", targetFrameworkVersion); + } } if (this->ProjectType == vcxproj && this->GlobalGenerator->TargetsWindowsCE()) { @@ -543,6 +549,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 +568,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 +687,8 @@ void cmVisualStudio10TargetGenerator::Generate() this->WritePlatformExtensions(e1); } + + this->WriteDotNetDocumentationFile(e0); Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros"); this->WriteWinRTPackageCertificateKeyFile(e0); this->WritePathAndIncrementalLinkOptions(e0); @@ -906,7 +919,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 +1025,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); } } } @@ -1430,6 +1455,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( std::string comment = lg->ConstructComment(ccg); comment = cmVS10EscapeComment(comment); std::string script = lg->ConstructScript(ccg); + bool symbolic = false; // input files for custom command std::stringstream additional_inputs; { @@ -1456,6 +1482,12 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( ConvertToWindowsSlash(dep); additional_inputs << sep << dep; sep = ";"; + if (!symbolic) { + if (cmSourceFile* sf = this->Makefile->GetSource( + dep, cmSourceFileLocationKind::Known)) { + symbolic = sf->GetPropertyAsBool("SYMBOLIC"); + } + } } } if (this->ProjectType != csproj) { @@ -1464,7 +1496,6 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( } // output files for custom command std::stringstream outputs; - bool symbolic = false; { const char* sep = ""; for (std::string const& o : ccg.GetOutputs()) { @@ -1592,8 +1623,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 +1762,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); @@ -2618,9 +2648,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); @@ -2784,6 +2814,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( case csproj: this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName, "CSharp"); + cm::erase_if(targetDefines, [](std::string const& def) { + return def.find('=') != std::string::npos; + }); break; } clOptions.AddDefines(targetDefines); @@ -2812,10 +2845,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 || @@ -2823,7 +2854,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"); } @@ -3620,18 +3652,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( this->AddLibraries(cli, libVec, vsTargetVec, config); if (cmContains(linkClosure->Languages, "CUDA") && this->CudaOptions[config] != nullptr) { - switch (this->CudaOptions[config]->GetCudaRuntime()) { - case cmVisualStudioGeneratorOptions::CudaRuntimeStatic: - libVec.push_back("cudadevrt.lib"); - libVec.push_back("cudart_static.lib"); - break; - case cmVisualStudioGeneratorOptions::CudaRuntimeShared: - libVec.push_back("cudadevrt.lib"); - libVec.push_back("cudart.lib"); - break; - case cmVisualStudioGeneratorOptions::CudaRuntimeNone: - break; - } + this->CudaOptions[config]->FixCudaRuntime(this->GeneratorTarget); } std::string standardLibsVar = cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES"); @@ -4021,8 +4042,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; @@ -4094,6 +4115,9 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) e2.Element("Project", "{" + this->GlobalGenerator->GetGUID(name) + "}"); e2.Element("Name", name); this->WriteDotNetReferenceCustomTags(e2, name); + if (dt->IsCSharpOnly() || cmHasLiteralSuffix(path, "csproj")) { + e2.Element("SkipGetTargetFrameworkProperties", "true"); + } // Don't reference targets that don't produce any output. if (dt->GetManagedType("") == cmGeneratorTarget::ManagedType::Undefined) { @@ -4841,7 +4865,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 a18a33d..30027c9 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 1139aa9..4004b66 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -3,6 +3,8 @@ #include <cm/iterator> #include "cmAlgorithms.h" +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" #include "cmLocalVisualStudioGenerator.h" #include "cmOutputConverter.h" #include "cmSystemTools.h" @@ -149,25 +151,33 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const return false; } -cmVisualStudioGeneratorOptions::CudaRuntime -cmVisualStudioGeneratorOptions::GetCudaRuntime() const +void cmVisualStudioGeneratorOptions::FixCudaRuntime(cmGeneratorTarget* target) { std::map<std::string, FlagValue>::const_iterator i = this->FlagMap.find("CudaRuntime"); - if (i != this->FlagMap.end() && i->second.size() == 1) { - std::string const& cudaRuntime = i->second[0]; - if (cudaRuntime == "Static") { - return CudaRuntimeStatic; - } - if (cudaRuntime == "Shared") { - return CudaRuntimeShared; - } - if (cudaRuntime == "None") { - return CudaRuntimeNone; + if (i == this->FlagMap.end()) { + // User didn't provide am override so get the property value + const char* runtimeLibraryValue = + target->GetProperty("CUDA_RUNTIME_LIBRARY"); + if (runtimeLibraryValue) { + std::string cudaRuntime = + cmSystemTools::UpperCase(cmGeneratorExpression::Evaluate( + runtimeLibraryValue, this->LocalGenerator, this->Configuration, + target)); + if (cudaRuntime == "STATIC") { + this->AddFlag("CudaRuntime", "Static"); + } + if (cudaRuntime == "SHARED") { + this->AddFlag("CudaRuntime", "Shared"); + } + if (cudaRuntime == "NONE") { + this->AddFlag("CudaRuntime", "None"); + } + } else { + // nvcc default is static + this->AddFlag("CudaRuntime", "Static"); } } - // nvcc default is static - return CudaRuntimeStatic; } void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() @@ -431,7 +441,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( if (this->Defines.empty()) { return; } - const char* tag = "PreprocessorDefinitions"; + std::string tag = "PreprocessorDefinitions"; if (lang == "CUDA") { tag = "Defines"; } @@ -473,7 +483,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 +538,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 560593e..b335694 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -13,6 +13,7 @@ #include "cmIDEOptions.h" class cmLocalVisualStudioGenerator; +class cmGeneratorTarget; using cmVS7FlagTable = cmIDEFlagTable; @@ -61,15 +62,8 @@ public: bool UsingUnicode() const; bool UsingSBCS() const; - enum CudaRuntime - { - CudaRuntimeStatic, - CudaRuntimeShared, - CudaRuntimeNone - }; - CudaRuntime GetCudaRuntime() const; - void FixCudaCodeGeneration(); + void FixCudaRuntime(cmGeneratorTarget* target); void FixManifestUACFlags(); @@ -86,7 +80,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 afc95f5..b34c2f6 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 dff5e35..da40856 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 f63a264..5fa40d5 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")) { @@ -393,7 +389,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) } } cmsys::RegularExpression regex( - cmsys::Glob::PatternToRegex(entryPattern, true, true).c_str()); + cmsys::Glob::PatternToRegex(entryPattern, true, true)); // go through all cache entries and collect the vars which will be // removed std::vector<std::string> entriesToDelete; @@ -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; } @@ -676,6 +663,8 @@ void cmake::SetArgs(const std::vector<std::string>& args) } else if ((i < args.size() - 1) && (arg.find("--check-stamp-list", 0) == 0)) { this->CheckStampList = args[++i]; + } else if (arg == "--regenerate-during-build") { + this->RegenerateDuringBuild = true; } #if defined(CMAKE_HAVE_VS_GENERATORS) else if ((i < args.size() - 1) && @@ -735,6 +724,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 +736,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 +826,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 +838,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 +895,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 +926,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 +1106,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 +1155,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 +1179,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 +1197,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 +1249,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 +1271,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 +1634,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 +1655,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 +1710,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 +1728,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 +1759,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 +1831,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 +1985,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 +2091,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 +2231,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 +2357,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 +2365,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 } @@ -2307,7 +2376,7 @@ void cmake::SetProperty(const std::string& prop, const char* value) this->State->SetGlobalProperty(prop, value); } -void cmake::AppendProperty(const std::string& prop, const char* value, +void cmake::AppendProperty(const std::string& prop, const std::string& value, bool asString) { this->State->AppendGlobalProperty(prop, value, asString); @@ -2376,12 +2445,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 +2662,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 +2767,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 +2799,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 687c105..35425ec 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, @@ -344,7 +359,7 @@ public: //! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); - void AppendProperty(const std::string& prop, const char* value, + void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); const char* GetProperty(const std::string& prop); bool GetPropertyAsBool(const std::string& prop); @@ -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; } @@ -499,11 +547,14 @@ public: } cmStateSnapshot GetCurrentSnapshot() const { return this->CurrentSnapshot; } + bool GetRegenerateDuringBuild() const { return this->RegenerateDuringBuild; } + 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 +564,6 @@ protected: void AddDefaultGenerators(); void AddDefaultExtraGenerators(); - cmGlobalGenerator* GlobalGenerator = nullptr; std::map<std::string, DiagLevel> DiagLevels; std::string GeneratorInstance; std::string GeneratorPlatform; @@ -549,8 +599,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; @@ -571,6 +623,7 @@ private: FileExtensions FortranFileExtensions; bool ClearBuildSystem = false; bool DebugTryCompile = false; + bool RegenerateDuringBuild = false; std::unique_ptr<cmFileTimeCache> FileTimeCache; std::string GraphVizFile; InstalledFilesMap InstalledFiles; @@ -587,6 +640,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 +773,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 6d3e6ee..5579ae1 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 d05e3c8..67c776e 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 0d65902..fbdf75a 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." }, @@ -141,6 +144,8 @@ static const char* cmDocumentationOptions[][2] = { { "--http1.0", "Submit using HTTP 1.0." }, { "--no-compress-output", "Do not compress test output when submitting." }, { "--print-labels", "Print all available test labels." }, + { "--no-tests=<[error|ignore]>", + "Regard no tests found either as 'error' or 'ignore' it." }, { nullptr, nullptr } }; @@ -161,7 +166,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 760221b..c07f0f3 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 b067521..75a2d4d 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 4593c92..5cad934 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 d79bbdf..b424488 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 df7eb45..d11db88 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 ce4d6ef..39873e6 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 4dd2461..c9515ee 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. */ |