diff options
Diffstat (limited to 'Source')
59 files changed, 1133 insertions, 955 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 7cd07a8..2ff6c8c 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -493,8 +493,6 @@ set(SRCS cmCreateTestSourceList.h cmDefinePropertyCommand.cxx cmDefinePropertyCommand.h - cmDisallowedCommand.cxx - cmDisallowedCommand.h cmEnableLanguageCommand.cxx cmEnableLanguageCommand.h cmEnableTestingCommand.cxx @@ -656,6 +654,8 @@ set(SRCS cmTargetLinkDirectoriesCommand.h cmTargetLinkLibrariesCommand.cxx cmTargetLinkLibrariesCommand.h + cmTargetPrecompileHeadersCommand.cxx + cmTargetPrecompileHeadersCommand.h cmTargetPropCommandBase.cxx cmTargetPropCommandBase.h cmTargetSourcesCommand.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f72c20b..1b06e45 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 15) -set(CMake_VERSION_PATCH 20190827) +set(CMake_VERSION_PATCH 20190829) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 8f13d0e..d1ffcef 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -39,24 +39,31 @@ int cmCPackIFWGenerator::PackageFiles() // Run repogen if (!this->Installer.RemoteRepositories.empty()) { - std::string ifwCmd = this->RepoGen; + std::vector<std::string> ifwCmd; + std::string ifwArg; + + ifwCmd.emplace_back(this->RepoGen); if (this->IsVersionLess("2.0.0")) { - ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + ifwCmd.emplace_back("-c"); + ifwCmd.emplace_back(this->toplevel + "/config/config.xml"); } - ifwCmd += " -p " + this->toplevel + "/packages"; + ifwCmd.emplace_back("-p"); + ifwCmd.emplace_back(this->toplevel + "/packages"); if (!this->PkgsDirsVector.empty()) { for (std::string const& it : this->PkgsDirsVector) { - ifwCmd += " -p " + it; + ifwCmd.emplace_back("-p"); + ifwCmd.emplace_back(it); } } if (!this->RepoDirsVector.empty()) { if (!this->IsVersionLess("3.1")) { for (std::string const& rd : this->RepoDirsVector) { - ifwCmd += " --repository " + rd; + ifwCmd.emplace_back("--repository"); + ifwCmd.emplace_back(rd); } } else { cmCPackIFWLogger(WARNING, @@ -69,18 +76,21 @@ int cmCPackIFWGenerator::PackageFiles() } if (!this->OnlineOnly && !this->DownloadedPackages.empty()) { - ifwCmd += " -i "; + ifwCmd.emplace_back("-i"); std::set<cmCPackIFWPackage*>::iterator it = this->DownloadedPackages.begin(); - ifwCmd += (*it)->Name; + ifwArg = (*it)->Name; ++it; while (it != this->DownloadedPackages.end()) { - ifwCmd += "," + (*it)->Name; + ifwArg += "," + (*it)->Name; ++it; } + ifwCmd.emplace_back(ifwArg); } - ifwCmd += " " + this->toplevel + "/repository"; - cmCPackIFWLogger(VERBOSE, "Execute: " << ifwCmd << std::endl); + ifwCmd.emplace_back(this->toplevel + "/repository"); + cmCPackIFWLogger(VERBOSE, + "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd) + << std::endl); std::string output; int retVal = 1; cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl); @@ -89,14 +99,15 @@ int cmCPackIFWGenerator::PackageFiles() cmDuration::zero()); if (!res || retVal) { cmGeneratedFileStream ofs(ifwTmpFile); - ofs << "# Run command: " << ifwCmd << std::endl + ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd) + << std::endl << "# Output:" << std::endl << output << std::endl; - cmCPackIFWLogger(ERROR, - "Problem running IFW command: " - << ifwCmd << std::endl - << "Please check " << ifwTmpFile << " for errors" - << std::endl); + cmCPackIFWLogger( + ERROR, + "Problem running IFW command: " + << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl + << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl); return 0; } @@ -104,46 +115,55 @@ int cmCPackIFWGenerator::PackageFiles() !this->Repository.PatchUpdatesXml()) { cmCPackIFWLogger(WARNING, "Problem patch IFW \"Updates\" " - << "file: " - << this->toplevel + "/repository/Updates.xml" - << std::endl); + << "file: \"" << this->toplevel + << "/repository/Updates.xml\"" << std::endl); } cmCPackIFWLogger(OUTPUT, - "- repository: " << this->toplevel - << "/repository generated" << std::endl); + "- repository: \"" << this->toplevel + << "/repository\" generated" + << std::endl); } // Run binary creator { - std::string ifwCmd = - cmStrCat(this->BinCreator, " -c ", this->toplevel, "/config/config.xml"); + std::vector<std::string> ifwCmd; + std::string ifwArg; + + ifwCmd.emplace_back(this->BinCreator); + + ifwCmd.emplace_back("-c"); + ifwCmd.emplace_back(this->toplevel + "/config/config.xml"); if (!this->Installer.Resources.empty()) { - ifwCmd += " -r "; + ifwCmd.emplace_back("-r"); std::vector<std::string>::iterator it = this->Installer.Resources.begin(); std::string path = this->toplevel + "/resources/"; - ifwCmd += path + *it; + ifwArg = path + *it; ++it; while (it != this->Installer.Resources.end()) { - ifwCmd += "," + path + *it; + ifwArg += "," + path + *it; ++it; } + ifwCmd.emplace_back(ifwArg); } - ifwCmd += " -p " + this->toplevel + "/packages"; + ifwCmd.emplace_back("-p"); + ifwCmd.emplace_back(this->toplevel + "/packages"); if (!this->PkgsDirsVector.empty()) { for (std::string const& it : this->PkgsDirsVector) { - ifwCmd += " -p " + it; + ifwCmd.emplace_back("-p"); + ifwCmd.emplace_back(it); } } if (!this->RepoDirsVector.empty()) { if (!this->IsVersionLess("3.1")) { for (std::string const& rd : this->RepoDirsVector) { - ifwCmd += " --repository " + rd; + ifwCmd.emplace_back("--repository"); + ifwCmd.emplace_back(rd); } } else { cmCPackIFWLogger(WARNING, @@ -156,44 +176,48 @@ int cmCPackIFWGenerator::PackageFiles() } if (this->OnlineOnly) { - ifwCmd += " --online-only"; + ifwCmd.emplace_back("--online-only"); } else if (!this->DownloadedPackages.empty() && !this->Installer.RemoteRepositories.empty()) { - ifwCmd += " -e "; + ifwCmd.emplace_back("-e"); std::set<cmCPackIFWPackage*>::iterator it = this->DownloadedPackages.begin(); - ifwCmd += (*it)->Name; + ifwArg = (*it)->Name; ++it; while (it != this->DownloadedPackages.end()) { - ifwCmd += "," + (*it)->Name; + ifwArg += "," + (*it)->Name; ++it; } + ifwCmd.emplace_back(ifwArg); } else if (!this->DependentPackages.empty()) { - ifwCmd += " -i "; + ifwCmd.emplace_back("-i"); + ifwArg.clear(); // Binary std::set<cmCPackIFWPackage*>::iterator bit = this->BinaryPackages.begin(); while (bit != this->BinaryPackages.end()) { - ifwCmd += (*bit)->Name + ","; + ifwArg += (*bit)->Name + ","; ++bit; } // Depend DependenceMap::iterator it = this->DependentPackages.begin(); - ifwCmd += it->second.Name; + ifwArg += it->second.Name; ++it; while (it != this->DependentPackages.end()) { - ifwCmd += "," + it->second.Name; + ifwArg += "," + it->second.Name; ++it; } + ifwCmd.emplace_back(ifwArg); } // TODO: set correct name for multipackages if (!this->packageFileNames.empty()) { - ifwCmd += " " + this->packageFileNames[0]; + ifwCmd.emplace_back(this->packageFileNames[0]); } else { - ifwCmd += " installer"; - ifwCmd += this->OutputExtension; + ifwCmd.emplace_back("installer" + this->OutputExtension); } - cmCPackIFWLogger(VERBOSE, "Execute: " << ifwCmd << std::endl); + cmCPackIFWLogger(VERBOSE, + "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd) + << std::endl); std::string output; int retVal = 1; cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl); @@ -202,14 +226,15 @@ int cmCPackIFWGenerator::PackageFiles() cmDuration::zero()); if (!res || retVal) { cmGeneratedFileStream ofs(ifwTmpFile); - ofs << "# Run command: " << ifwCmd << std::endl + ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd) + << std::endl << "# Output:" << std::endl << output << std::endl; - cmCPackIFWLogger(ERROR, - "Problem running IFW command: " - << ifwCmd << std::endl - << "Please check " << ifwTmpFile << " for errors" - << std::endl); + cmCPackIFWLogger( + ERROR, + "Problem running IFW command: " + << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl + << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl); return 0; } } diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index ead16d2..702b743 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -78,6 +78,7 @@ #include "cmTargetCompileOptionsCommand.h" #include "cmTargetIncludeDirectoriesCommand.h" #include "cmTargetLinkLibrariesCommand.h" +#include "cmTargetPrecompileHeadersCommand.h" #include "cmTargetSourcesCommand.h" #include "cmTryCompileCommand.h" #include "cmTryRunCommand.h" @@ -208,8 +209,7 @@ void GetScriptingCommands(cmState* state) "build_name", cmBuildNameCommand, cmPolicies::CMP0036, "The build_name command should not be called; see CMP0036."); state->AddDisallowedCommand( - "use_mangled_mesa", cm::make_unique<cmUseMangledMesaCommand>(), - cmPolicies::CMP0030, + "use_mangled_mesa", cmUseMangledMesaCommand, cmPolicies::CMP0030, "The use_mangled_mesa command should not be called; see CMP0030."); #endif @@ -277,6 +277,9 @@ void GetProjectCommands(cmState* state) state->AddBuiltinCommand("try_compile", cm::make_unique<cmTryCompileCommand>()); state->AddBuiltinCommand("try_run", cm::make_unique<cmTryRunCommand>()); + state->AddBuiltinCommand( + "target_precompile_headers", + cm::make_unique<cmTargetPrecompileHeadersCommand>()); #if !defined(CMAKE_BOOTSTRAP) state->AddBuiltinCommand("add_compile_definitions", @@ -310,29 +313,24 @@ void GetProjectCommands(cmState* state) cm::make_unique<cmSourceGroupCommand>()); state->AddDisallowedCommand( - "export_library_dependencies", - cm::make_unique<cmExportLibraryDependenciesCommand>(), cmPolicies::CMP0033, + "export_library_dependencies", cmExportLibraryDependenciesCommand, + cmPolicies::CMP0033, "The export_library_dependencies command should not be called; " "see CMP0033."); state->AddDisallowedCommand( - "load_command", cm::make_unique<cmLoadCommandCommand>(), - cmPolicies::CMP0031, + "load_command", cmLoadCommandCommand, cmPolicies::CMP0031, "The load_command command should not be called; see CMP0031."); state->AddDisallowedCommand( - "output_required_files", cm::make_unique<cmOutputRequiredFilesCommand>(), - cmPolicies::CMP0032, + "output_required_files", cmOutputRequiredFilesCommand, cmPolicies::CMP0032, "The output_required_files command should not be called; see CMP0032."); state->AddDisallowedCommand( - "subdir_depends", cm::make_unique<cmSubdirDependsCommand>(), - cmPolicies::CMP0029, + "subdir_depends", cmSubdirDependsCommand, cmPolicies::CMP0029, "The subdir_depends command should not be called; see CMP0029."); state->AddDisallowedCommand( - "utility_source", cm::make_unique<cmUtilitySourceCommand>(), - cmPolicies::CMP0034, + "utility_source", cmUtilitySourceCommand, cmPolicies::CMP0034, "The utility_source command should not be called; see CMP0034."); state->AddDisallowedCommand( - "variable_requires", cm::make_unique<cmVariableRequiresCommand>(), - cmPolicies::CMP0035, + "variable_requires", cmVariableRequiresCommand, cmPolicies::CMP0035, "The variable_requires command should not be called; see CMP0035."); #endif } diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx deleted file mode 100644 index aa1f90b..0000000 --- a/Source/cmDisallowedCommand.cxx +++ /dev/null @@ -1,29 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmDisallowedCommand.h" - -#include "cmMakefile.h" -#include "cmMessageType.h" - -class cmExecutionStatus; - -bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) -{ - switch (this->Makefile->GetPolicyStatus(this->Policy)) { - case cmPolicies::WARN: - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, - cmPolicies::GetPolicyWarning(this->Policy)); - break; - case cmPolicies::OLD: - break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, this->Message); - return true; - } - - this->Command->SetExecutionStatus(this->GetExecutionStatus()); - return this->Command->InitialPass(args, status); -} diff --git a/Source/cmDisallowedCommand.h b/Source/cmDisallowedCommand.h deleted file mode 100644 index e07f255..0000000 --- a/Source/cmDisallowedCommand.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDisallowedCommand_h -#define cmDisallowedCommand_h - -#include "cmConfigure.h" // IWYU pragma: keep - -#include <string> -#include <utility> -#include <vector> - -#include "cm_memory.hxx" - -#include "cmCommand.h" -#include "cmPolicies.h" - -class cmExecutionStatus; - -class cmDisallowedCommand : public cmCommand -{ -public: - cmDisallowedCommand(std::unique_ptr<cmCommand> command, - cmPolicies::PolicyID policy, const char* message) - : Command(std::move(command)) - , Policy(policy) - , Message(message) - { - } - - ~cmDisallowedCommand() override = default; - - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmDisallowedCommand>(this->Command->Clone(), - this->Policy, this->Message); - } - - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - std::unique_ptr<cmCommand> Command; - cmPolicies::PolicyID Policy; - const char* Message; -}; - -#endif diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 8a1a305..9f0396b 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -91,6 +91,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gte, cmGeneratorExpression::BuildInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gte, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte, cmGeneratorExpression::BuildInterface, properties, missingTargets); diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index 81237db..bab394a 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -8,6 +8,7 @@ #include "cm_memory.hxx" +#include "cmExecutionStatus.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -18,8 +19,6 @@ #include "cmTargetLinkLibraryType.h" #include "cmake.h" -class cmExecutionStatus; - static void FinalAction(cmMakefile& makefile, std::string const& filename, bool append) { @@ -140,19 +139,20 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename, fout << "endif()\n"; } -bool cmExportLibraryDependenciesCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } std::string const& filename = args[0]; bool const append = args.size() > 1 && args[1] == "APPEND"; - this->Makefile->AddFinalAction([filename, append](cmMakefile& makefile) { - FinalAction(makefile, filename, append); - }); + status.GetMakefile().AddFinalAction( + [filename, append](cmMakefile& makefile) { + FinalAction(makefile, filename, append); + }); return true; } diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h index 4817162..230c906 100644 --- a/Source/cmExportLibraryDependenciesCommand.h +++ b/Source/cmExportLibraryDependenciesCommand.h @@ -8,21 +8,9 @@ #include <string> #include <vector> -#include "cm_memory.hxx" - -#include "cmCommand.h" - class cmExecutionStatus; -class cmExportLibraryDependenciesCommand : public cmCommand -{ -public: - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmExportLibraryDependenciesCommand>(); - } - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index d8a1a49..487d0de 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -365,7 +365,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // check whether it is a C/C++/CUDA implementation file bool isCFile = false; - std::string lang = s->GetLanguage(); + std::string lang = s->GetOrDetermineLanguage(); if (lang == "C" || lang == "CXX" || lang == "CUDA") { std::string const& srcext = s->GetExtension(); isCFile = cm->IsSourceExtension(srcext); diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 33f5157..6f4472b 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -342,7 +342,7 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject( cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* gtgt) { std::string flags; - std::string language = source->GetLanguage(); + std::string language = source->GetOrDetermineLanguage(); if (language.empty()) { language = "C"; } @@ -377,7 +377,7 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( { std::set<std::string> defines; cmMakefile* makefile = lg->GetMakefile(); - const std::string& language = source->GetLanguage(); + const std::string& language = source->GetOrDetermineLanguage(); const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, language); @@ -410,7 +410,7 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes( { std::vector<std::string> includes; cmMakefile* makefile = lg->GetMakefile(); - const std::string& language = source->GetLanguage(); + const std::string& language = source->GetOrDetermineLanguage(); const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target, language); diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index e4b7670..08db7c7 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -837,7 +837,7 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) { CompileData fd; - fd.Language = sf->GetLanguage(); + fd.Language = sf->GetOrDetermineLanguage(); if (fd.Language.empty()) { return fd; } diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 191d7bb..cdc5f63 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -145,7 +145,7 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) // look for old style // FIND_*(VAR name path1 path2 ...) - if (!newStyle) { + if (!newStyle && !this->Names.empty()) { // All the short-hand arguments have been recorded as names. std::vector<std::string> shortArgs = this->Names; this->Names.clear(); // clear out any values in Names diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 6d7d6ef..b72a40f 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -29,7 +29,8 @@ class cmGeneratorTarget; SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES) \ SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS) \ SELECT(F, EvaluatingLinkDirectories, LINK_DIRECTORIES) \ - SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS) + SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS) \ + SELECT(F, EvaluatingPrecompileHeaders, PRECOMPILE_HEADERS) #define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \ CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 3048c5f..cc37232 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -21,6 +21,7 @@ #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" #include "cmCustomCommandLines.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionDAGChecker.h" @@ -278,6 +279,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) , DebugCompileDefinitionsDone(false) , DebugLinkOptionsDone(false) , DebugLinkDirectoriesDone(false) + , DebugPrecompileHeadersDone(false) , DebugSourcesDone(false) , LinkImplementationLanguageIsContextDependent(true) , UtilityItemsDone(false) @@ -312,6 +314,10 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) t->GetLinkDirectoriesBacktraces(), this->LinkDirectoriesEntries); + CreatePropertyGeneratorExpressions(t->GetPrecompileHeadersEntries(), + t->GetPrecompileHeadersBacktraces(), + this->PrecompileHeadersEntries); + CreatePropertyGeneratorExpressions(t->GetSourceEntries(), t->GetSourceBacktraces(), this->SourceEntries, true); @@ -327,6 +333,7 @@ cmGeneratorTarget::~cmGeneratorTarget() cmDeleteAll(this->CompileDefinitionsEntries); cmDeleteAll(this->LinkOptionsEntries); cmDeleteAll(this->LinkDirectoriesEntries); + cmDeleteAll(this->PrecompileHeadersEntries); cmDeleteAll(this->SourceEntries); cmDeleteAll(this->LinkInformation); } @@ -1593,7 +1600,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, kind = SourceKindHeader; } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { kind = SourceKindExternalObject; - } else if (!sf->GetLanguage().empty()) { + } else if (!sf->GetOrDetermineLanguage().empty()) { kind = SourceKindObjectSource; } else if (ext == "def") { kind = SourceKindModuleDefinition; @@ -3312,6 +3319,152 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( return list; } +std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders( + const std::string& config, const std::string& language) const +{ + std::unordered_set<std::string> uniqueOptions; + + cmGeneratorExpressionDAGChecker dagChecker(this, "PRECOMPILE_HEADERS", + nullptr, nullptr); + + std::vector<std::string> debugProperties; + const char* debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) { + cmExpandList(debugProp, debugProperties); + } + + bool debugDefines = !this->DebugPrecompileHeadersDone && + std::find(debugProperties.begin(), debugProperties.end(), + "PRECOMPILE_HEADERS") != debugProperties.end(); + + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { + this->DebugPrecompileHeadersDone = true; + } + + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->PrecompileHeadersEntries); + + AddInterfaceEntries(this, config, "INTERFACE_PRECOMPILE_HEADERS", language, + &dagChecker, entries); + + std::vector<BT<std::string>> list; + processOptions(this, entries, list, uniqueOptions, debugDefines, + "precompile headers", OptionsParse::None); + + return list; +} + +std::string cmGeneratorTarget::GetPchHeader(const std::string& config, + const std::string& language) const +{ + if (language != "C" && language != "CXX") { + return std::string(); + } + if (this->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) { + return std::string(); + } + const auto inserted = + this->PchHeaders.insert(std::make_pair(language + config, "")); + if (inserted.second) { + const std::vector<BT<std::string>> headers = + this->GetPrecompileHeaders(config, language); + if (headers.empty()) { + return std::string(); + } + std::string& filename = inserted.first->second; + + if (this->GetGlobalGenerator()->IsMultiConfig()) { + filename = + cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), "/"); + } else { + // For GCC we need to have the header file .h[xx] + // next to the .h[xx].gch file + filename = this->ObjectDirectory; + } + + filename = cmStrCat(filename, "CMakeFiles/", this->GetName(), + ".dir/cmake_pch", ((language == "C") ? ".h" : ".hxx")); + + const std::string filename_tmp = cmStrCat(filename, ".tmp"); + { + auto pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); + auto pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE"); + + cmGeneratedFileStream file( + filename_tmp, false, + this->GetGlobalGenerator()->GetMakefileEncoding()); + file << "/* generated by CMake */\n\n"; + if (pchPrologue) { + file << pchPrologue << "\n"; + } + if (this->GetGlobalGenerator()->IsXcode()) { + file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n"; + } + if (language == "CXX") { + file << "#ifdef __cplusplus\n"; + } + for (auto const& header_bt : headers) { + if (header_bt.Value.empty()) { + continue; + } + if (header_bt.Value[0] == '<' || header_bt.Value[0] == '"') { + file << "#include " << header_bt.Value << "\n"; + } else { + file << "#include \"" << header_bt.Value << "\"\n"; + } + } + if (language == "CXX") { + file << "#endif // __cplusplus\n"; + } + if (this->GetGlobalGenerator()->IsXcode()) { + file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n"; + } + if (pchEpilogue) { + file << pchEpilogue << "\n"; + } + } + cmSystemTools::CopyFileIfDifferent(filename_tmp, filename); + cmSystemTools::RemoveFile(filename_tmp); + } + return inserted.first->second; +} + +std::string cmGeneratorTarget::GetPchSource(const std::string& config, + const std::string& language) const +{ + if (language != "C" && language != "CXX") { + return std::string(); + } + const auto inserted = + this->PchSources.insert(std::make_pair(language + config, "")); + if (inserted.second) { + const std::string pchHeader = this->GetPchHeader(config, language); + if (pchHeader.empty()) { + return std::string(); + } + std::string& filename = inserted.first->second; + filename = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + "/CMakeFiles/", this->GetName(), ".dir/cmake_pch"); + + // For GCC the source extension will be tranformed into .h[xx].gch + if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) { + filename += ((language == "C") ? ".h.c" : ".hxx.cxx"); + } else { + filename += ((language == "C") ? ".c" : ".cxx"); + } + const std::string filename_tmp = cmStrCat(filename, ".tmp"); + { + cmGeneratedFileStream file(filename_tmp); + file << "/* generated by CMake */\n"; + } + cmSystemTools::CopyFileIfDifferent(filename_tmp, filename); + cmSystemTools::RemoveFile(filename_tmp); + } + return inserted.first->second; +} + void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -6055,7 +6208,7 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages, std::vector<cmSourceFile*> sourceFiles; this->GetSourceFiles(sourceFiles, config); for (cmSourceFile* src : sourceFiles) { - const std::string& lang = src->GetLanguage(); + const std::string& lang = src->GetOrDetermineLanguage(); if (!lang.empty()) { languages.insert(lang); } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 3874738..4701071 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -455,6 +455,14 @@ public: std::vector<BT<std::string>> GetLinkDepends( std::string const& config, std::string const& language) const; + std::vector<BT<std::string>> GetPrecompileHeaders( + const std::string& config, const std::string& language) const; + + std::string GetPchHeader(const std::string& config, + const std::string& language) const; + std::string GetPchSource(const std::string& config, + const std::string& language) const; + bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config, const std::string& language) const; @@ -867,8 +875,11 @@ private: std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; std::vector<TargetPropertyEntry*> LinkOptionsEntries; std::vector<TargetPropertyEntry*> LinkDirectoriesEntries; + std::vector<TargetPropertyEntry*> PrecompileHeadersEntries; std::vector<TargetPropertyEntry*> SourceEntries; mutable std::set<std::string> LinkImplicitNullProperties; + mutable std::map<std::string, std::string> PchHeaders; + mutable std::map<std::string, std::string> PchSources; void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, @@ -922,6 +933,7 @@ private: mutable bool DebugCompileDefinitionsDone; mutable bool DebugLinkOptionsDone; mutable bool DebugLinkDirectoriesDone; + mutable bool DebugPrecompileHeadersDone; mutable bool DebugSourcesDone; mutable bool LinkImplementationLanguageIsContextDependent; mutable bool UtilityItemsDone; diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index a16076d..5c1c8a5 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -24,10 +24,6 @@ bool cmGetSourceFilePropertyCommand::InitialPass( sf = this->Makefile->CreateSource(file); } if (sf) { - if (args[2] == "LANGUAGE") { - this->Makefile->AddDefinition(var, sf->GetLanguage()); - return true; - } const char* prop = nullptr; if (!args[2].empty()) { prop = sf->GetPropertyForUser(args[2]); diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index cbab329..e4cd73f 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -110,6 +110,13 @@ public: bool IsIncludeExternalMSProjectSupported() const override { return true; } + /** Get encoding used by generator for generated source files + */ + codecvt::Encoding GetMakefileEncoding() const override + { + return codecvt::ANSI; + } + class TargetSet : public std::set<cmGeneratorTarget const*> { }; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index a204fe0..427ab44 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2374,6 +2374,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION", this->CreateString(vso.str())); } + + // Precompile Headers + std::string pchHeader = gtgt->GetPchHeader(configName, llang); + if (!pchHeader.empty()) { + buildSettings->AddAttribute("GCC_PREFIX_HEADER", + this->CreateString(pchHeader)); + buildSettings->AddAttribute("GCC_PRECOMPILE_PREFIX_HEADER", + this->CreateString("YES")); + } + // put this last so it can override existing settings // Convert "XCODE_ATTRIBUTE_*" properties directly. { @@ -2829,6 +2839,8 @@ bool cmGlobalXCodeGenerator::CreateGroups( continue; } + generator->AddPchDependencies(gtgt, ""); + auto addSourceToGroup = [this, mf, gtgt, &sourceGroups](std::string const& source) { cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups); diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index b8eed13..4948b01 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -264,7 +264,7 @@ static Json::Value DumpSourceFilesList( std::unordered_map<LanguageData, std::vector<std::string>> fileGroups; for (cmSourceFile* file : files) { LanguageData fileData; - fileData.Language = file->GetLanguage(); + fileData.Language = file->GetOrDetermineLanguage(); if (!fileData.Language.empty()) { const LanguageData& ld = languageDataMap.at(fileData.Language); cmLocalGenerator* lg = target->GetLocalGenerator(); diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 180e65b..f650eb1 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -14,14 +14,14 @@ #include "cmCPluginAPI.cxx" #include "cmCPluginAPI.h" +#include "cmCommand.h" #include "cmDynamicLoader.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - #ifdef __QNX__ # include <malloc.h> /* for malloc/free on QNX */ #endif @@ -175,8 +175,8 @@ bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args, } // namespace // cmLoadCommandCommand -bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmLoadCommandCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { return true; @@ -185,13 +185,13 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, // Construct a variable to report what file was loaded, if any. // Start by removing the definition in case of failure. std::string reportVar = cmStrCat("CMAKE_LOADED_COMMAND_", args[0]); - this->Makefile->RemoveDefinition(reportVar); + status.GetMakefile().RemoveDefinition(reportVar); // the file must exist std::string moduleName = cmStrCat( - this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX"), "cm", - args[0], - this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX")); + status.GetMakefile().GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX"), + "cm", args[0], + status.GetMakefile().GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX")); // search for the file std::vector<std::string> path; @@ -209,7 +209,7 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, if (fullPath.empty()) { std::ostringstream e; e << "Attempt to load command failed from file \"" << moduleName << "\""; - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -224,12 +224,12 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, err += " Additional error info is:\n"; err += error; } - this->SetError(err); + status.SetError(err); return false; } // Report what file was loaded for this command. - this->Makefile->AddDefinition(reportVar, fullPath); + status.GetMakefile().AddDefinition(reportVar, fullPath); // find the init function std::string initFuncName = args[0] + "Init"; @@ -243,12 +243,12 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, // if the symbol is found call it to set the name on the // function blocker if (initFunction) { - this->Makefile->GetState()->AddScriptedCommand( + status.GetMakefile().GetState()->AddScriptedCommand( args[0], cmLegacyCommandWrapper(cm::make_unique<cmLoadedCommand>(initFunction))); return true; } - this->SetError("Attempt to load command failed. " - "No init function found."); + status.SetError("Attempt to load command failed. " + "No init function found."); return false; } diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h index d81cefb..f5fd754 100644 --- a/Source/cmLoadCommandCommand.h +++ b/Source/cmLoadCommandCommand.h @@ -8,21 +8,9 @@ #include <string> #include <vector> -#include "cm_memory.hxx" - -#include "cmCommand.h" - class cmExecutionStatus; -class cmLoadCommandCommand : public cmCommand -{ -public: - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmLoadCommandCommand>(); - } - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmLoadCommandCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 2e40543..7177694 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -18,6 +18,7 @@ #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" +#include "cmSourceFileLocationKind.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" @@ -37,6 +38,7 @@ #include <algorithm> #include <assert.h> +#include <functional> #include <initializer_list> #include <iterator> #include <memory> @@ -2124,6 +2126,82 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags, this->AppendFlags(flags, this->EscapeForShell(rawFlag)); } +void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, + const std::string& config) +{ + const std::string lang = target->GetLinkerLanguage(config); + const std::string buildType = cmSystemTools::UpperCase(config); + const std::string pchSource = target->GetPchSource(config, lang); + const std::string pchHeader = target->GetPchHeader(config, lang); + + if (pchSource.empty() || pchHeader.empty()) { + return; + } + + const std::string createOptVar = + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_CREATE_PCH"); + std::string createOptionList = + this->Makefile->GetSafeDefinition(createOptVar); + + const std::string useOptVar = + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_USE_PCH"); + std::string useOptionList = this->Makefile->GetSafeDefinition(useOptVar); + + const std::string pchExtension = + this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); + + if (createOptionList.empty() || useOptionList.empty() || + pchExtension.empty()) { + return; + } + + auto pch_sf = this->Makefile->GetOrCreateSource( + pchSource, false, cmSourceFileLocationKind::Known); + std::string pchFile = pchHeader; + + if (!this->GetGlobalGenerator()->IsXcode()) { + // Exclude the pch files from linking + if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { + cmSystemTools::ReplaceString(pchFile, (lang == "C" ? ".h" : ".hxx"), + pchExtension); + pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); + } else { + pchFile += pchExtension; + pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); + } + + target->AddSource(pchSource, true); + + for (auto& str : { std::ref(useOptionList), std::ref(createOptionList) }) { + cmSystemTools::ReplaceString(str, "<PCH_HEADER>", pchHeader); + cmSystemTools::ReplaceString(str, "<PCH_FILE>", pchFile); + } + } + + pch_sf->SetProperty("COMPILE_OPTIONS", createOptionList.c_str()); + + std::vector<cmSourceFile*> sources; + target->GetSourceFiles(sources, buildType); + for (cmSourceFile* sf : sources) { + if (pch_sf == sf || sf->GetLanguage() != lang) { + continue; + } + + if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { + if (this->GetGlobalGenerator()->IsXcode()) { + sf->SetProperty("COMPILE_DEFINITIONS", + "CMAKE_SKIP_PRECOMPILE_HEADERS"); + } + continue; + } + + if (!this->GetGlobalGenerator()->IsXcode()) { + sf->SetProperty("OBJECT_DEPENDS", pchFile.c_str()); + sf->SetProperty("COMPILE_OPTIONS", useOptionList.c_str()); + } + } +} + void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, @@ -2716,6 +2794,11 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( } } + const char* pchExtension = source.GetProperty("PCH_EXTENSION"); + if (pchExtension) { + customOutputExtension = pchExtension; + } + // Remove the source extension if it is to be replaced. if (replaceExt || customOutputExtension) { keptSourceExtension = false; diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 455e491..f63fe0f 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -124,6 +124,8 @@ public: virtual void AppendFlags(std::string& flags, const char* newFlags) const; virtual void AppendFlagEscape(std::string& flags, const std::string& rawFlag) const; + void AddPchDependencies(cmGeneratorTarget* target, + const std::string& config); void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, const std::string& lang); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 2c91974..795cee4 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1320,6 +1320,8 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, const std::string& libName, cmGeneratorTarget* target) { + this->AddPchDependencies(target, ""); + std::vector<std::string> configs; this->Makefile->GetConfigurations(configs); diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 7bc05b1..bebd5c4 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -40,6 +40,8 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); + + this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator() = diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 252279f..4244402 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -42,6 +42,8 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); + + this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileLibraryTargetGenerator::~cmMakefileLibraryTargetGenerator() = diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index f99fe4e..90d8ea9 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -239,10 +239,15 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->GeneratorTarget->GetExtraSources(extraSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator); + const char* pchExtension = + this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { - this->ExternalObjects.push_back(sf->GetFullPath()); + auto const& objectFileName = sf->GetFullPath(); + if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + this->ExternalObjects.push_back(objectFileName); + } } std::vector<cmSourceFile const*> objectSources; this->GeneratorTarget->GetObjectSources(objectSources, config); @@ -1238,7 +1243,14 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( if (!lineContinue) { lineContinue = "\\"; } + + const char* pchExtension = + this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + for (std::string const& obj : this->Objects) { + if (cmSystemTools::StringEndsWith(obj, pchExtension)) { + continue; + } *this->BuildFileStream << " " << lineContinue << "\n"; *this->BuildFileStream << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( @@ -1331,10 +1343,16 @@ private: void cmMakefileTargetGenerator::WriteObjectsStrings( std::vector<std::string>& objStrings, std::string::size_type limit) { + const char* pchExtension = + this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmMakefileTargetGeneratorObjectStrings helper( objStrings, this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit); for (std::string const& obj : this->Objects) { + if (cmSystemTools::StringEndsWith(obj, pchExtension)) { + continue; + } helper.Feed(obj); } for (std::string const& obj : this->ExternalObjects) { diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 8ed6be5..556191f 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -25,6 +25,8 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator( this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); + + this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() = diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 17a5527..0e3aa3a 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -59,6 +59,8 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target, this->GetConfigName()); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); + + GetLocalGenerator()->AddPchDependencies(target, this->GetConfigName()); } cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 3d3d80d..29e8b74 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -790,10 +790,16 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() extraSources, this->MacOSXContentGenerator.get()); } { + const char* pchExtension = + GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); + std::vector<cmSourceFile const*> externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { - this->Objects.push_back(this->GetSourceFilePath(sf)); + const auto objectFileName = this->GetSourceFilePath(sf); + if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + this->Objects.push_back(objectFileName); + } } } @@ -955,8 +961,12 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]); objBuild.Outputs.push_back(objectFileName); - // Add this object to the list of object files. - this->Objects.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); + } objBuild.ExplicitDeps.push_back(sourceFileName); diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index dbb7111..3d8ebc3 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -5,9 +5,12 @@ #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" #include <map> +#include <set> +#include <stdio.h> #include <utility> #include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmSourceFile.h" @@ -15,8 +18,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" -class cmExecutionStatus; - +namespace { /** \class cmDependInformation * \brief Store dependency information for a single source file. * @@ -452,43 +454,47 @@ protected: DirectoryToFileToPathMapType DirectoryToFileToPathMap; }; +void ListDependencies(cmDependInformation const* info, FILE* fout, + std::set<cmDependInformation const*>* visited); +} + // cmOutputRequiredFilesCommand -bool cmOutputRequiredFilesCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmOutputRequiredFilesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } // store the arg for final pass - this->File = args[0]; - this->OutputFile = args[1]; + const std::string& file = args[0]; + const std::string& outputFile = args[1]; // compute the list of files cmLBDepend md; - md.SetMakefile(this->Makefile); - md.AddSearchPath(this->Makefile->GetCurrentSourceDirectory()); + md.SetMakefile(&status.GetMakefile()); + md.AddSearchPath(status.GetMakefile().GetCurrentSourceDirectory()); // find the depends for a file - const cmDependInformation* info = md.FindDependencies(this->File.c_str()); + const cmDependInformation* info = md.FindDependencies(file.c_str()); if (info) { // write them out - FILE* fout = cmsys::SystemTools::Fopen(this->OutputFile, "w"); + FILE* fout = cmsys::SystemTools::Fopen(outputFile, "w"); if (!fout) { - this->SetError(cmStrCat("Can not open output file: ", this->OutputFile)); + status.SetError(cmStrCat("Can not open output file: ", outputFile)); return false; } std::set<cmDependInformation const*> visited; - this->ListDependencies(info, fout, &visited); + ListDependencies(info, fout, &visited); fclose(fout); } return true; } -void cmOutputRequiredFilesCommand::ListDependencies( - cmDependInformation const* info, FILE* fout, - std::set<cmDependInformation const*>* visited) +namespace { +void ListDependencies(cmDependInformation const* info, FILE* fout, + std::set<cmDependInformation const*>* visited) { // add info to the visited set visited->insert(info); @@ -503,7 +509,8 @@ void cmOutputRequiredFilesCommand::ListDependencies( fprintf(fout, "%s\n", d->FullPath.c_str()); } } - this->ListDependencies(d, fout, visited); + ListDependencies(d, fout, visited); } } } +} diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h index faffabd..4c11894 100644 --- a/Source/cmOutputRequiredFilesCommand.h +++ b/Source/cmOutputRequiredFilesCommand.h @@ -5,34 +5,12 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <set> -#include <stdio.h> #include <string> #include <vector> -#include "cm_memory.hxx" - -#include "cmCommand.h" - -class cmDependInformation; class cmExecutionStatus; -class cmOutputRequiredFilesCommand : public cmCommand -{ -public: - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmOutputRequiredFilesCommand>(); - } - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - - void ListDependencies(cmDependInformation const* info, FILE* fout, - std::set<cmDependInformation const*>* visited); - -private: - std::string File; - std::string OutputFile; -}; +bool cmOutputRequiredFilesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 9d29e5c..d890f8e 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -12,6 +12,7 @@ #include <algorithm> #include <array> +#include <initializer_list> #include <sstream> #include <utility> @@ -21,7 +22,7 @@ /// @arg valueOpts list of options that accept a value void MergeOptions(std::vector<std::string>& baseOpts, std::vector<std::string> const& newOpts, - std::vector<std::string> const& valueOpts, bool isQt5) + std::initializer_list<cm::string_view> valueOpts, bool isQt5) { typedef std::vector<std::string>::iterator Iter; typedef std::vector<std::string>::const_iterator CIter; @@ -75,102 +76,74 @@ void MergeOptions(std::vector<std::string>& baseOpts, unsigned int const cmQtAutoGen::ParallelMax = 64; std::string const cmQtAutoGen::ListSep = "<<<S>>>"; -std::string const& cmQtAutoGen::GeneratorName(GenT genType) +cm::string_view cmQtAutoGen::GeneratorName(GenT genType) { - static const std::string AutoGen("AutoGen"); - static const std::string AutoMoc("AutoMoc"); - static const std::string AutoUic("AutoUic"); - static const std::string AutoRcc("AutoRcc"); - switch (genType) { case GenT::GEN: - return AutoGen; + return "AutoGen"; case GenT::MOC: - return AutoMoc; + return "AutoMoc"; case GenT::UIC: - return AutoUic; + return "AutoUic"; case GenT::RCC: - return AutoRcc; + return "AutoRcc"; } - return AutoGen; + return "AutoGen"; } -std::string const& cmQtAutoGen::GeneratorNameUpper(GenT genType) +cm::string_view cmQtAutoGen::GeneratorNameUpper(GenT genType) { - static const std::string AUTOGEN("AUTOGEN"); - static const std::string AUTOMOC("AUTOMOC"); - static const std::string AUTOUIC("AUTOUIC"); - static const std::string AUTORCC("AUTORCC"); - switch (genType) { case GenT::GEN: - return AUTOGEN; + return "AUTOGEN"; case GenT::MOC: - return AUTOMOC; + return "AUTOMOC"; case GenT::UIC: - return AUTOUIC; + return "AUTOUIC"; case GenT::RCC: - return AUTORCC; + return "AUTORCC"; } - return AUTOGEN; + return "AUTOGEN"; } std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc) { - std::string res; - std::vector<std::string> lst; + std::array<cm::string_view, 3> lst; + decltype(lst)::size_type num = 0; if (moc) { - lst.emplace_back("AUTOMOC"); + lst.at(num++) = "AUTOMOC"; } if (uic) { - lst.emplace_back("AUTOUIC"); + lst.at(num++) = "AUTOUIC"; } if (rcc) { - lst.emplace_back("AUTORCC"); + lst.at(num++) = "AUTORCC"; } - switch (lst.size()) { + switch (num) { case 1: - res += lst.at(0); - break; + return std::string(lst[0]); case 2: - res += lst.at(0); - res += " and "; - res += lst.at(1); - break; + return cmStrCat(lst[0], " and ", lst[1]); case 3: - res += lst.at(0); - res += ", "; - res += lst.at(1); - res += " and "; - res += lst.at(2); - break; + return cmStrCat(lst[0], ", ", lst[1], " and ", lst[2]); default: break; } - return res; + return std::string(); } -std::string cmQtAutoGen::Quoted(std::string const& text) +std::string cmQtAutoGen::Quoted(cm::string_view text) { - const std::array<std::pair<const char*, const char*>, 9> replaces = { - { { "\\", "\\\\" }, - { "\"", "\\\"" }, - { "\a", "\\a" }, - { "\b", "\\b" }, - { "\f", "\\f" }, - { "\n", "\\n" }, - { "\r", "\\r" }, - { "\t", "\\t" }, - { "\v", "\\v" } } - }; + static std::initializer_list<std::pair<const char*, const char*>> const + replacements = { { "\\", "\\\\" }, { "\"", "\\\"" }, { "\a", "\\a" }, + { "\b", "\\b" }, { "\f", "\\f" }, { "\n", "\\n" }, + { "\r", "\\r" }, { "\t", "\\t" }, { "\v", "\\v" } }; - std::string res = text; - for (auto const& pair : replaces) { + std::string res(text); + for (auto const& pair : replacements) { cmSystemTools::ReplaceString(res, pair.first, pair.second); } - res = '"' + res; - res += '"'; - return res; + return cmStrCat('"', res, '"'); } std::string cmQtAutoGen::QuotedCommand(std::vector<std::string> const& command) @@ -191,37 +164,31 @@ std::string cmQtAutoGen::QuotedCommand(std::vector<std::string> const& command) return res; } -std::string cmQtAutoGen::SubDirPrefix(std::string const& filename) +std::string cmQtAutoGen::SubDirPrefix(cm::string_view filename) { - std::string::size_type slash_pos = filename.rfind('/'); - if (slash_pos == std::string::npos) { + auto slashPos = filename.rfind('/'); + if (slashPos == cm::string_view::npos) { return std::string(); } - return filename.substr(0, slash_pos + 1); + return std::string(filename.substr(0, slashPos + 1)); } -std::string cmQtAutoGen::AppendFilenameSuffix(std::string const& filename, - std::string const& suffix) +std::string cmQtAutoGen::AppendFilenameSuffix(cm::string_view filename, + cm::string_view suffix) { - std::string res; - auto pos = filename.rfind('.'); - if (pos != std::string::npos) { - const auto it_dot = filename.begin() + pos; - res.assign(filename.begin(), it_dot); - res.append(suffix); - res.append(it_dot, filename.end()); - } else { - res = filename; - res.append(suffix); + auto dotPos = filename.rfind('.'); + if (dotPos == cm::string_view::npos) { + return cmStrCat(filename, suffix); } - return res; + return cmStrCat(filename.substr(0, dotPos), suffix, + filename.substr(dotPos, filename.size() - dotPos)); } void cmQtAutoGen::UicMergeOptions(std::vector<std::string>& baseOpts, std::vector<std::string> const& newOpts, bool isQt5) { - static std::vector<std::string> const valueOpts = { + static std::initializer_list<cm::string_view> const valueOpts = { "tr", "translate", "postfix", "generator", "include", // Since Qt 5.3 "g" @@ -233,9 +200,9 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts, std::vector<std::string> const& newOpts, bool isQt5) { - static std::vector<std::string> const valueOpts = { "name", "root", - "compress", - "threshold" }; + static std::initializer_list<cm::string_view> const valueOpts = { + "name", "root", "compress", "threshold" + }; MergeOptions(baseOpts, newOpts, valueOpts, isQt5); } @@ -349,9 +316,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, // Log command if (verbose) { - std::string msg = - cmStrCat("Running command:\n", QuotedCommand(cmd), '\n'); - cmSystemTools::Stdout(msg); + cmSystemTools::Stdout( + cmStrCat("Running command:\n", QuotedCommand(cmd), '\n')); } result = cmSystemTools::RunSingleCommand( @@ -362,12 +328,10 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, error = cmStrCat("The rcc list process failed for ", Quoted(qrcFile), '\n'); if (!rccStdOut.empty()) { - error += rccStdOut; - error += "\n"; + error += cmStrCat(rccStdOut, '\n'); } if (!rccStdErr.empty()) { - error += rccStdErr; - error += "\n"; + error += cmStrCat(rccStdErr, '\n'); } return false; } diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 619fff1..939ceb3 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cm_string_view.hxx" + #include <memory> #include <string> #include <vector> @@ -66,24 +68,24 @@ public: public: /// @brief Returns the generator name - static std::string const& GeneratorName(GenT genType); + static cm::string_view GeneratorName(GenT genType); /// @brief Returns the generator name in upper case - static std::string const& GeneratorNameUpper(GenT genType); + static cm::string_view GeneratorNameUpper(GenT genType); /// @brief Returns a string with the requested tool names static std::string Tools(bool moc, bool uic, bool rcc); /// @brief Returns the string escaped and enclosed in quotes - static std::string Quoted(std::string const& text); + static std::string Quoted(cm::string_view text); static std::string QuotedCommand(std::vector<std::string> const& command); /// @brief Returns the parent directory of the file with a "/" suffix - static std::string SubDirPrefix(std::string const& filename); + static std::string SubDirPrefix(cm::string_view filename); /// @brief Appends the suffix to the filename before the last dot - static std::string AppendFilenameSuffix(std::string const& filename, - std::string const& suffix); + static std::string AppendFilenameSuffix(cm::string_view filename, + cm::string_view suffix); /// @brief Merges newOpts into baseOpts static void UicMergeOptions(std::vector<std::string>& baseOpts, diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index c355a5f..bd96c08 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -29,8 +29,8 @@ #include "cmsys/SystemInformation.hxx" #include <algorithm> -#include <array> #include <deque> +#include <initializer_list> #include <map> #include <set> #include <string> @@ -396,13 +396,13 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // CMAKE_AUTOMOC_RELAXED_MODE deprecation warning if (this->Moc.Enabled) { - if (cmIsOn(makefile->GetDefinition("CMAKE_AUTOMOC_RELAXED_MODE"))) { - std::string msg = + if (makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE")) { + makefile->IssueMessage( + MessageType::AUTHOR_WARNING, cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is " "deprecated an will be removed in the future. Consider " "disabling it and converting the target ", - this->Target->GetName(), " to regular mode."); - makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); + this->Target->GetName(), " to regular mode.")); } } } @@ -696,7 +696,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::vector<MUFileHandle> extraHeaders; extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2); // Header search suffixes and extensions - std::array<std::string, 2> const suffixes{ { "", "_p" } }; + static std::initializer_list<cm::string_view> const suffixes{ "", "_p" }; auto const& exts = cm->GetHeaderExtensions(); // Scan through sources for (auto const& pair : this->AutogenTarget.Sources) { @@ -708,7 +708,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() cmStrCat(cmQtAutoGen::SubDirPrefix(srcPath), cmSystemTools::GetFilenameWithoutLastExtension(srcPath)); for (auto const& suffix : suffixes) { - std::string const suffixedPath = basePath + suffix; + std::string const suffixedPath = cmStrCat(basePath, suffix); for (auto const& ext : exts) { std::string fullPath = cmStrCat(suffixedPath, '.', ext); @@ -814,33 +814,31 @@ bool cmQtAutoGenInitializer::InitScanFiles() this->AutogenTarget.DependFiles.insert(muf->RealPath); } } else if (this->CMP0071Warn) { - std::string msg = - cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0071), '\n'); - std::string property; + cm::string_view property; if (this->Moc.Enabled && this->Uic.Enabled) { - property = kw.SKIP_AUTOGEN; + property = "SKIP_AUTOGEN"; } else if (this->Moc.Enabled) { - property = kw.SKIP_AUTOMOC; + property = "SKIP_AUTOMOC"; } else if (this->Uic.Enabled) { - property = kw.SKIP_AUTOUIC; + property = "SKIP_AUTOUIC"; } - msg += "For compatibility, CMake is excluding the GENERATED source " - "file(s):\n"; + std::string files; for (MUFile* muf : this->AutogenTarget.FilesGenerated) { - msg += " "; - msg += Quoted(muf->RealPath); - msg += '\n'; + files += cmStrCat(" ", Quoted(muf->RealPath), '\n'); } - msg += "from processing by "; - msg += cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false); - msg += ". If any of the files should be processed, set CMP0071 to NEW. " - "If any of the files should not be processed, " - "explicitly exclude them by setting the source file property "; - msg += property; - msg += ":\n set_property(SOURCE file.h PROPERTY "; - msg += property; - msg += " ON)\n"; - makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); + makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + cmPolicies::GetPolicyWarning(cmPolicies::CMP0071), '\n', + "For compatibility, CMake is excluding the GENERATED source " + "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 CMP0071 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.h PROPERTY ", property, + " ON)\n")); } } @@ -867,20 +865,16 @@ bool cmQtAutoGenInitializer::InitScanFiles() for (Qrc& qrc : this->Rcc.Qrcs) { qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile); // RCC output file name - qrc.RccFile = cmStrCat(this->Dir.Build + "/", qrc.PathChecksum, - "/qrc_", qrc.QrcName, ".cpp"); + qrc.RccFile = cmStrCat(this->Dir.Build, '/', qrc.PathChecksum, "/qrc_", + qrc.QrcName, ".cpp"); { - std::string base = cmStrCat(this->Dir.Info, "/RCC", qrc.QrcName); - if (!qrc.Unique) { - base += qrc.PathChecksum; - } - + cm::string_view const baseSuffix = + qrc.Unique ? cm::string_view() : cm::string_view(qrc.PathChecksum); + std::string const base = + cmStrCat(this->Dir.Info, "/RCC", qrc.QrcName, baseSuffix); qrc.LockFile = cmStrCat(base, ".lock"); - qrc.InfoFile = cmStrCat(base, "Info.cmake"); - qrc.SettingsFile = cmStrCat(base, "Settings.txt"); - if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { qrc.ConfigSettingsFile[cfg] = @@ -900,7 +894,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() // Replace '-' with '_'. The former is not valid for symbol names. std::replace(name.begin(), name.end(), '-', '_'); if (!qrc.Unique) { - name += cmStrCat("_", qrc.PathChecksum); + name += cmStrCat('_', qrc.PathChecksum); } std::vector<std::string> nameOpts; nameOpts.emplace_back("-name"); @@ -1131,8 +1125,7 @@ bool cmQtAutoGenInitializer::InitRccTargets() { ccName = cmStrCat(this->Target->GetName(), "_arcc_", qrc.QrcName); if (!qrc.Unique) { - ccName += "_"; - ccName += qrc.PathChecksum; + ccName += cmStrCat('_', qrc.PathChecksum); } cmTarget* autoRccTarget = makefile->AddUtilityCommand( @@ -1274,7 +1267,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() if (muf->MocIt || muf->UicIt) { headers.emplace_back(muf->RealPath); headersFlags.emplace_back( - cmStrCat(muf->MocIt ? "M" : "m", muf->UicIt ? "U" : "u")); + cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u')); } } } @@ -1283,19 +1276,17 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() cmFilePathChecksum const fpathCheckSum(makefile); std::unordered_set<std::string> emitted; for (std::string const& hdr : headers) { - std::string basePath = + std::string const basePath = cmStrCat(fpathCheckSum.getPart(hdr), "/moc_", cmSystemTools::GetFilenameWithoutLastExtension(hdr)); - for (int ii = 1; ii != 1024; ++ii) { - std::string path = basePath; - if (ii > 1) { - path += cmStrCat("_", ii); - } - path += ".cpp"; + std::string suffix; + for (int ii = 0; ii != 1024; ++ii) { + std::string path = cmStrCat(basePath, suffix, ".cpp"); if (emitted.emplace(path).second) { headersBuildPaths.emplace_back(std::move(path)); break; } + suffix = cmStrCat('_', ii + 1); } } } @@ -1329,7 +1320,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() if (muf->MocIt || muf->UicIt) { sources.emplace_back(muf->RealPath); sourcesFlags.emplace_back( - cmStrCat(muf->MocIt ? "M" : "m", muf->UicIt ? "U" : "u")); + cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u')); } } } @@ -1454,7 +1445,7 @@ bool cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, } bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, - std::string const& genNameUpper) + cm::string_view genNameUpper) { cmMakefile* makefile = this->Target->Target->GetMakefile(); cmSourceGroup* sourceGroup = nullptr; @@ -1464,13 +1455,14 @@ bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, std::string groupName; { // Prefer generator specific source group name - std::array<std::string, 2> props{ { genNameUpper + "_SOURCE_GROUP", - "AUTOGEN_SOURCE_GROUP" } }; - for (std::string& prop : props) { + std::initializer_list<std::string> const props{ + cmStrCat(genNameUpper, "_SOURCE_GROUP"), "AUTOGEN_SOURCE_GROUP" + }; + for (std::string const& prop : props) { const char* propName = makefile->GetState()->GetGlobalProperty(prop); if ((propName != nullptr) && (*propName != '\0')) { groupName = propName; - property = std::move(prop); + property = prop; break; } } @@ -1512,11 +1504,16 @@ static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions( cmGeneratorTarget const* target) { // Qt version variable prefixes - static std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core", - "QT" } }; + static std::initializer_list< + std::pair<cm::string_view, cm::string_view>> const keys{ + { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" }, + { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" }, + { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" }, + }; std::vector<cmQtAutoGen::IntegerVersion> result; - result.reserve(prefixes.size() * 2); + result.reserve(keys.size() * 2); + // Adds a version to the result (nullptr safe) auto addVersion = [&result](const char* major, const char* minor) { cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major), @@ -1525,18 +1522,19 @@ static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions( result.emplace_back(ver); } }; + cmMakefile* makefile = target->Target->GetMakefile(); // Read versions from variables - for (const std::string& prefix : prefixes) { - addVersion(makefile->GetDefinition(prefix + "_VERSION_MAJOR"), - makefile->GetDefinition(prefix + "_VERSION_MINOR")); + for (auto const& keyPair : keys) { + addVersion(makefile->GetDefinition(std::string(keyPair.first)), + makefile->GetDefinition(std::string(keyPair.second))); } // Read versions from directory properties - for (const std::string& prefix : prefixes) { - addVersion(makefile->GetProperty(prefix + "_VERSION_MAJOR"), - makefile->GetProperty(prefix + "_VERSION_MINOR")); + for (auto const& keyPair : keys) { + addVersion(makefile->GetProperty(std::string(keyPair.first)), + makefile->GetProperty(std::string(keyPair.second))); } return result; @@ -1580,7 +1578,7 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, // Custom executable { - std::string const prop = genVars.GenNameUpper + "_EXECUTABLE"; + std::string const prop = cmStrCat(genVars.GenNameUpper, "_EXECUTABLE"); std::string const val = this->Target->Target->GetSafeProperty(prop); if (!val.empty()) { // Evaluate generator expression @@ -1607,15 +1605,15 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, // Find executable target { // Find executable target name - std::string targetName; + cm::string_view prefix; if (this->QtVersion.Major == 4) { - targetName = "Qt4::"; + prefix = "Qt4::"; } else if (this->QtVersion.Major == 5) { - targetName = "Qt5::"; + prefix = "Qt5::"; } else if (this->QtVersion.Major == 6) { - targetName = "Qt6::"; + prefix = "Qt6::"; } - targetName += executable; + std::string const targetName = cmStrCat(prefix, executable); // Find target cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 7d72cad..65666a6 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -63,7 +63,7 @@ public: bool Enabled = false; // Generator type/name GenT Gen; - std::string const& GenNameUpper; + cm::string_view GenNameUpper; // Executable std::string ExecutableTargetName; cmGeneratorTarget* ExecutableTarget = nullptr; @@ -145,7 +145,7 @@ private: bool AddGeneratedSource(std::string const& filename, GenVarsT const& genVars, bool prepend = false); bool AddToSourceGroup(std::string const& fileName, - std::string const& genNameUpper); + cm::string_view genNameUpper); void AddCleanFile(std::string const& fileName); bool GetQtExecutable(GenVarsT& genVars, const std::string& executable, diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 90361a9..3bcc1c9 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -58,18 +58,16 @@ void cmQtAutoGenerator::Logger::SetColorOutput(bool value) ColorOutput_ = value; } -std::string cmQtAutoGenerator::Logger::HeadLine(std::string const& title) +std::string cmQtAutoGenerator::Logger::HeadLine(cm::string_view title) { - return cmStrCat(title, "\n", std::string(title.size(), '-'), "\n"); + return cmStrCat(title, '\n', std::string(title.size(), '-'), '\n'); } void cmQtAutoGenerator::Logger::Info(GenT genType, - std::string const& message) const + cm::string_view message) const { - std::string msg = cmStrCat(GeneratorName(genType), ": ", message); - if (msg.back() != '\n') { - msg.push_back('\n'); - } + std::string msg = cmStrCat(GeneratorName(genType), ": ", message, + cmHasSuffix(message, '\n') ? "" : "\n"); { std::lock_guard<std::mutex> lock(Mutex_); cmSystemTools::Stdout(msg); @@ -77,23 +75,18 @@ void cmQtAutoGenerator::Logger::Info(GenT genType, } void cmQtAutoGenerator::Logger::Warning(GenT genType, - std::string const& message) const + cm::string_view message) const { std::string msg; if (message.find('\n') == std::string::npos) { // Single line message - msg += GeneratorName(genType); - msg += " warning: "; + msg = cmStrCat(GeneratorName(genType), " warning: ", message, + cmHasSuffix(message, '\n') ? "\n" : "\n\n"); } else { // Multi line message - msg += HeadLine(GeneratorName(genType) + " warning"); - } - // Message - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); + msg = cmStrCat(HeadLine(cmStrCat(GeneratorName(genType), " warning")), + message, cmHasSuffix(message, '\n') ? "\n" : "\n\n"); } - msg.push_back('\n'); { std::lock_guard<std::mutex> lock(Mutex_); cmSystemTools::Stdout(msg); @@ -101,22 +94,18 @@ void cmQtAutoGenerator::Logger::Warning(GenT genType, } void cmQtAutoGenerator::Logger::WarningFile(GenT genType, - std::string const& filename, - std::string const& message) const + cm::string_view filename, + cm::string_view message) const { - Warning(genType, cmStrCat(" ", Quoted(filename), "\n", message)); + Warning(genType, cmStrCat(" ", Quoted(filename), '\n', message)); } void cmQtAutoGenerator::Logger::Error(GenT genType, - std::string const& message) const + cm::string_view message) const { - std::string msg = HeadLine(GeneratorName(genType) + " error"); - // Message - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); + std::string msg = + cmStrCat(HeadLine(cmStrCat(GeneratorName(genType), " error")), message, + cmHasSuffix(message, '\n') ? "\n" : "\n\n"); { std::lock_guard<std::mutex> lock(Mutex_); cmSystemTools::Stderr(msg); @@ -124,36 +113,22 @@ void cmQtAutoGenerator::Logger::Error(GenT genType, } void cmQtAutoGenerator::Logger::ErrorFile(GenT genType, - std::string const& filename, - std::string const& message) const + cm::string_view filename, + cm::string_view message) const { Error(genType, cmStrCat(" ", Quoted(filename), '\n', message)); } void cmQtAutoGenerator::Logger::ErrorCommand( - GenT genType, std::string const& message, + GenT genType, cm::string_view message, std::vector<std::string> const& command, std::string const& output) const { - std::string msg; - msg.push_back('\n'); - msg += HeadLine(GeneratorName(genType) + " subprocess error"); - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - msg += HeadLine("Command"); - msg += QuotedCommand(command); - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - msg += HeadLine("Output"); - msg += output; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); + std::string msg = cmStrCat( + '\n', HeadLine(cmStrCat(GeneratorName(genType), " subprocess error")), + message, cmHasSuffix(message, '\n') ? "\n" : "\n\n"); + msg += cmStrCat(HeadLine("Command"), QuotedCommand(command), "\n\n"); + msg += cmStrCat(HeadLine("Output"), output, + cmHasSuffix(output, '\n') ? "\n" : "\n\n"); { std::lock_guard<std::mutex> lock(Mutex_); cmSystemTools::Stderr(msg); diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index ff4c4c9..4b8b0b7 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -7,6 +7,7 @@ #include "cmFileTime.h" #include "cmQtAutoGen.h" +#include "cm_string_view.hxx" #include <mutex> #include <string> @@ -41,21 +42,21 @@ public: bool ColorOutput() const { return this->ColorOutput_; } void SetColorOutput(bool value); // -- Log info - void Info(GenT genType, std::string const& message) const; + void Info(GenT genType, cm::string_view message) const; // -- Log warning - void Warning(GenT genType, std::string const& message) const; - void WarningFile(GenT genType, std::string const& filename, - std::string const& message) const; + void Warning(GenT genType, cm::string_view message) const; + void WarningFile(GenT genType, cm::string_view filename, + cm::string_view message) const; // -- Log error - void Error(GenT genType, std::string const& message) const; - void ErrorFile(GenT genType, std::string const& filename, - std::string const& message) const; - void ErrorCommand(GenT genType, std::string const& message, + void Error(GenT genType, cm::string_view message) const; + void ErrorFile(GenT genType, cm::string_view filename, + cm::string_view message) const; + void ErrorCommand(GenT genType, cm::string_view message, std::vector<std::string> const& command, std::string const& output) const; private: - static std::string HeadLine(std::string const& title); + static std::string HeadLine(cm::string_view title); private: mutable std::mutex Mutex_; diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index df190a1..84359f2 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -3,10 +3,9 @@ #include "cmQtAutoMocUic.h" #include <algorithm> -#include <array> +#include <initializer_list> #include <list> #include <set> -#include <sstream> #include <utility> #include "cm_memory.hxx" @@ -233,22 +232,21 @@ bool cmQtAutoMocUic::UicSettingsT::skipped(std::string const& fileName) const } void cmQtAutoMocUic::JobT::LogError(GenT genType, - std::string const& message) const + cm::string_view message) const { Gen()->AbortError(); Gen()->Log().Error(genType, message); } -void cmQtAutoMocUic::JobT::LogFileError(GenT genType, - std::string const& filename, - std::string const& message) const +void cmQtAutoMocUic::JobT::LogFileError(GenT genType, cm::string_view filename, + cm::string_view message) const { Gen()->AbortError(); Gen()->Log().ErrorFile(genType, filename, message); } void cmQtAutoMocUic::JobT::LogCommandError( - GenT genType, std::string const& message, + GenT genType, cm::string_view message, std::vector<std::string> const& command, std::string const& output) const { Gen()->AbortError(); @@ -262,16 +260,14 @@ bool cmQtAutoMocUic::JobT::RunProcess(GenT genType, { // Log command if (Log().Verbose()) { - std::string msg; - if ((infoMessage != nullptr) && !infoMessage->empty()) { - msg = *infoMessage; - if (msg.back() != '\n') { - msg += '\n'; - } + cm::string_view info; + if (infoMessage != nullptr) { + info = *infoMessage; } - msg += QuotedCommand(command); - msg += '\n'; - Log().Info(genType, msg); + Log().Info(genType, + cmStrCat(info, + info.empty() || cmHasSuffix(info, '\n') ? "" : "\n", + QuotedCommand(command), '\n')); } return cmWorkerPool::JobT::RunProcess(result, command, BaseConst().AutogenBuildDir); @@ -302,10 +298,11 @@ void cmQtAutoMocUic::JobMocPredefsT::Process() } // Execute command if (!RunProcess(GenT::MOC, result, cmd, reason.get())) { - std::string msg = - cmStrCat("The content generation command for ", - Quoted(predefsFileRel), " failed.\n", result.ErrorMessage); - LogCommandError(GenT::MOC, msg, cmd, result.StdOut); + LogCommandError(GenT::MOC, + cmStrCat("The content generation command for ", + Quoted(predefsFileRel), " failed.\n", + result.ErrorMessage), + cmd, result.StdOut); return; } } @@ -313,9 +310,8 @@ void cmQtAutoMocUic::JobMocPredefsT::Process() // (Re)write predefs file only on demand if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) { if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) { - std::string msg = - cmStrCat("Writing ", Quoted(predefsFileRel), " failed."); - LogFileError(GenT::MOC, predefsFileAbs, msg); + LogFileError(GenT::MOC, predefsFileAbs, + cmStrCat("Writing ", Quoted(predefsFileRel), " failed.")); return; } } else { @@ -324,9 +320,9 @@ void cmQtAutoMocUic::JobMocPredefsT::Process() Log().Info(GenT::MOC, "Touching " + Quoted(predefsFileRel)); } if (!cmSystemTools::Touch(predefsFileAbs, false)) { - std::string msg = - cmStrCat("Touching ", Quoted(predefsFileAbs), " failed."); - LogFileError(GenT::MOC, predefsFileAbs, msg); + LogFileError( + GenT::MOC, predefsFileAbs, + cmStrCat("Touching ", Quoted(predefsFileAbs), " failed.")); return; } } @@ -654,14 +650,12 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( // Check if this source needs to be moc processed but doesn't. if (!sourceIncludesDotMoc && !parseData.Macro.empty() && !(relaxedMode && sourceIncludesMocUnderscore)) { - { - std::string emsg = - cmStrCat("The file contains a ", Quoted(parseData.Macro), - " macro, but does not include ", Quoted(sourceBase + ".moc"), - "!\nConsider to\n - add #include \"", sourceBase, - ".moc\"\n - enable SKIP_AUTOMOC for this file"); - LogFileError(GenT::MOC, sourceFile.FileName, emsg); - } + LogFileError(GenT::MOC, sourceFile.FileName, + cmStrCat("The file contains a ", Quoted(parseData.Macro), + " macro, but does not include ", + Quoted(sourceBase + ".moc"), + "!\nConsider to\n - add #include \"", sourceBase, + ".moc\"\n - enable SKIP_AUTOMOC for this file")); return false; } @@ -670,14 +664,12 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( std::string const headerBase = incKey.Dir + incKey.Base; SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase); if (!header) { - { - std::string msg = - cmStrCat("The file includes the moc file ", Quoted(incKey.Key), - ",\nbut the header could not be found " - "in the following locations\n", - MocMessageTestHeaders(headerBase)); - LogFileError(GenT::MOC, sourceFile.FileName, msg); - } + LogFileError(GenT::MOC, sourceFile.FileName, + cmStrCat("The file includes the moc file ", + Quoted(incKey.Key), + ",\nbut the header could not be found " + "in the following locations\n", + MocMessageTestHeaders(headerBase))); return false; } // The include might be handled differently in relaxed mode @@ -688,18 +680,19 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( // be generated from <BASE>.cpp instead of <BASE>.h, because otherwise // it won't build. But warn, since this is not how it is supposed to be // used. This is for KDE4 compatibility. - { - // Issue a warning - std::string msg = cmStrCat( - "The file contains a ", Quoted(parseData.Macro), - " macro, but does not include ", Quoted(sourceBase + ".moc"), - ".\nInstead it includes ", Quoted(incKey.Key), - ".\nRunning moc on the source\n ", Quoted(sourceFile.FileName), - "!\nBetter include ", Quoted(sourceBase + ".moc"), - " for compatibility with regular mode.\n", - "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"); - Log().WarningFile(GenT::MOC, sourceFile.FileName, msg); - } + + // Issue a warning + Log().WarningFile( + GenT::MOC, sourceFile.FileName, + cmStrCat("The file contains a ", Quoted(parseData.Macro), + " macro, but does not include ", Quoted(sourceBase + ".moc"), + ".\nInstead it includes ", Quoted(incKey.Key), + ".\nRunning moc on the source\n ", + Quoted(sourceFile.FileName), "!\nBetter include ", + Quoted(sourceBase + ".moc"), + " for compatibility with regular mode.\n", + "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n")); + // Create mapping if (!MocRegisterIncluded(incKey.Key, source, source, false)) { return false; @@ -735,13 +728,13 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( std::string const headerBase = incKey.Dir + incKey.Base; SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase); if (!header) { - std::string msg = + LogFileError( + GenT::MOC, sourceFile.FileName, cmStrCat("The file includes the moc file ", Quoted(incKey.Key), ",\nwhich seems to be the moc file from a different source " "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header" "could not be found in the following locations\n", - MocMessageTestHeaders(headerBase)); - LogFileError(GenT::MOC, sourceFile.FileName, msg); + MocMessageTestHeaders(headerBase))); return false; } // Check if header is skipped @@ -750,23 +743,25 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( } // Issue a warning if (ownMoc && parseData.Macro.empty()) { - std::string msg = cmStrCat( - "The file includes the moc file ", Quoted(incKey.Key), - ", but does not contain a\n", MocConst().MacrosString(), - " macro.\nRunning moc on the header\n ", Quoted(header->FileName), - "!\nBetter include ", Quoted("moc_" + incKey.Base + ".cpp"), - " for a compatibility with regular mode.\n", - "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"); - Log().WarningFile(GenT::MOC, sourceFile.FileName, msg); + Log().WarningFile( + GenT::MOC, sourceFile.FileName, + cmStrCat("The file includes the moc file ", Quoted(incKey.Key), + ", but does not contain a\n", MocConst().MacrosString(), + " macro.\nRunning moc on the header\n ", + Quoted(header->FileName), "!\nBetter include ", + Quoted("moc_" + incKey.Base + ".cpp"), + " for a compatibility with regular mode.\n", + "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n")); } else { - std::string msg = cmStrCat( - "The file includes the moc file ", Quoted(incKey.Key), - " instead of ", Quoted("moc_" + incKey.Base + ".cpp"), - ".\nRunning moc on the header\n ", Quoted(header->FileName), - "!\nBetter include ", Quoted("moc_" + incKey.Base + ".cpp"), - " for compatibility with regular mode.\n", - "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"); - Log().WarningFile(GenT::MOC, sourceFile.FileName, msg); + Log().WarningFile( + GenT::MOC, sourceFile.FileName, + cmStrCat("The file includes the moc file ", Quoted(incKey.Key), + " instead of ", Quoted("moc_" + incKey.Base + ".cpp"), + ".\nRunning moc on the header\n ", + Quoted(header->FileName), "!\nBetter include ", + Quoted("moc_" + incKey.Base + ".cpp"), + " for compatibility with regular mode.\n", + "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n")); } // Create mapping if (!MocRegisterIncluded(incKey.Key, source, std::move(header), true)) { @@ -780,20 +775,22 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( bool const ownMoc = (incKey.Base == sourceBase); if (!ownMoc) { // Don't allow <BASE>.moc include other than own in regular mode - std::string msg = cmStrCat( - "The file includes the moc file ", Quoted(incKey.Key), - ",\nwhich seems to be the moc file from a different " - "source file.\nThis is not supported. Include ", - Quoted(sourceBase + ".moc"), " to run moc on this source file."); - LogFileError(GenT::MOC, sourceFile.FileName, msg); + LogFileError( + GenT::MOC, sourceFile.FileName, + cmStrCat("The file includes the moc file ", Quoted(incKey.Key), + ",\nwhich seems to be the moc file from a different " + "source file.\nThis is not supported. Include ", + Quoted(sourceBase + ".moc"), + " to run moc on this source file.")); return false; } // Accept but issue a warning if moc isn't required if (parseData.Macro.empty()) { - std::string msg = cmStrCat( - "The file includes the moc file ", Quoted(incKey.Key), - ", but does not contain a ", MocConst().MacrosString(), " macro."); - Log().WarningFile(GenT::MOC, sourceFile.FileName, msg); + Log().WarningFile(GenT::MOC, sourceFile.FileName, + cmStrCat("The file includes the moc file ", + Quoted(incKey.Key), + ", but does not contain a ", + MocConst().MacrosString(), " macro.")); } // Create mapping if (!MocRegisterIncluded(incKey.Key, source, source, false)) { @@ -864,19 +861,16 @@ cmQtAutoMocUic::SourceFileHandleT cmQtAutoMocUic::JobEvaluateT::MocFindHeader( } std::string cmQtAutoMocUic::JobEvaluateT::MocMessageTestHeaders( - std::string const& fileBase) const + cm::string_view fileBase) const { - std::ostringstream res; - { - std::string exts = - cmStrCat(".{", cmJoin(BaseConst().HeaderExtensions, ","), - '}'); // Compose result string - res << " " << fileBase << exts << '\n'; - for (std::string const& path : MocConst().IncludePaths) { - res << " " << path << '/' << fileBase << exts << '\n'; - } + std::string const exts = + cmStrCat(".{", cmJoin(BaseConst().HeaderExtensions, ","), '}'); + // Compose result string + std::string res = cmStrCat(" ", fileBase, exts, '\n'); + for (std::string const& path : MocConst().IncludePaths) { + res += cmStrCat(" ", path, '/', fileBase, exts, '\n'); } - return res.str(); + return res; } bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded( @@ -888,26 +882,24 @@ bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded( if (handle) { // Check if the output file would be generated from different source files if (handle->SourceFile != sourceFileHandle) { - std::string msg = cmStrCat("The source files\n ", - Quoted(includerFileHandle->FileName), '\n'); + std::string files = + cmStrCat(" ", Quoted(includerFileHandle->FileName), '\n'); for (auto const& item : handle->IncluderFiles) { - msg += " "; - msg += Quoted(item->FileName); - msg += '\n'; - } - msg += "contain the same include string "; - msg += Quoted(includeString); - msg += ", but\nthe moc file would be generated from different " - "source files\n "; - msg += Quoted(sourceFileHandle->FileName); - msg += " and\n "; - msg += Quoted(handle->SourceFile->FileName); - msg += ".\nConsider to\n" - " - not include the \"moc_<NAME>.cpp\" file\n" - " - add a directory prefix to a \"<NAME>.moc\" include " - "(e.g \"sub/<NAME>.moc\")\n" - " - rename the source file(s)\n"; - LogError(GenT::MOC, msg); + files += cmStrCat(" ", Quoted(item->FileName), '\n'); + } + LogError( + GenT::MOC, + cmStrCat("The source files\n", files, + "contain the same include string ", Quoted(includeString), + ", but\nthe moc file would be generated from different " + "source files\n ", + Quoted(sourceFileHandle->FileName), " and\n ", + Quoted(handle->SourceFile->FileName), + ".\nConsider to\n" + " - not include the \"moc_<NAME>.cpp\" file\n" + " - add a directory prefix to a \"<NAME>.moc\" include " + "(e.g \"sub/<NAME>.moc\")\n" + " - rename the source file(s)\n")); return false; } @@ -921,7 +913,7 @@ bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded( handle->IncludeString = includeString; handle->IncluderFiles.emplace_back(std::move(includerFileHandle)); handle->SourceFile = std::move(sourceFileHandle); - handle->OutputFile += Gen()->AbsoluteIncludePath(includeString); + handle->OutputFile = Gen()->AbsoluteIncludePath(includeString); // Register mapping in sources/headers map MocRegisterMapping(handle, sourceIsHeader); @@ -957,7 +949,7 @@ bool cmQtAutoMocUic::JobEvaluateT::UicEval(SourceFileMapT const& fileMap) } bool cmQtAutoMocUic::JobEvaluateT::UicEvalFile( - SourceFileHandleT sourceFileHandle) + SourceFileHandleT const& sourceFileHandle) { SourceFileT const& sourceFile = *sourceFileHandle; auto const& Include = sourceFile.ParseData->Uic.Include; @@ -975,7 +967,7 @@ bool cmQtAutoMocUic::JobEvaluateT::UicEvalFile( } // Register mapping if (!UicRegisterMapping(incKey.Key, std::move(uiFileHandle), - std::move(sourceFileHandle))) { + sourceFileHandle)) { return false; } } @@ -993,26 +985,25 @@ bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping( MappingHandleT const& handle = it->second; if (handle->SourceFile != uiFileHandle) { // The output file already gets generated - from a different .ui file! - std::string msg = cmStrCat("The source files\n ", - Quoted(includerFileHandle->FileName), '\n'); + std::string files = + cmStrCat(" ", Quoted(includerFileHandle->FileName), '\n'); for (auto const& item : handle->IncluderFiles) { - msg += " "; - msg += Quoted(item->FileName); - msg += '\n'; - } - msg += "contain the same include string "; - msg += Quoted(includeString); - msg += ", but\nthe uic file would be generated from different " - "user interface files\n "; - msg += Quoted(uiFileHandle->FileName); - msg += " and\n "; - msg += Quoted(handle->SourceFile->FileName); - msg += ".\nConsider to\n" - " - add a directory prefix to a \"ui_<NAME>.h\" include " - "(e.g \"sub/ui_<NAME>.h\")\n" - " - rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" " - "include(s)\n"; - LogError(GenT::UIC, msg); + files += cmStrCat(" ", Quoted(item->FileName), '\n'); + } + LogError( + GenT::UIC, + cmStrCat( + "The source files\n", files, "contain the same include string ", + Quoted(includeString), + ", but\nthe uic file would be generated from different " + "user interface files\n ", + Quoted(uiFileHandle->FileName), " and\n ", + Quoted(handle->SourceFile->FileName), + ".\nConsider to\n" + " - add a directory prefix to a \"ui_<NAME>.h\" include " + "(e.g \"sub/ui_<NAME>.h\")\n" + " - rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" " + "include(s)\n")); return false; } // Add includer file to existing mapping @@ -1023,7 +1014,7 @@ bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping( handle->IncludeString = includeString; handle->IncluderFiles.emplace_back(std::move(includerFileHandle)); handle->SourceFile = std::move(uiFileHandle); - handle->OutputFile += Gen()->AbsoluteIncludePath(includeString); + handle->OutputFile = Gen()->AbsoluteIncludePath(includeString); // Register mapping Includes.emplace(includeString, std::move(handle)); } @@ -1080,16 +1071,15 @@ cmQtAutoMocUic::JobEvaluateT::UicFindIncludedUi( // Log error { - std::string msg = - cmStrCat("The file includes the uic file ", Quoted(incKey.Key), - ",\nbut the user interface file ", Quoted(searchFileName), - "\ncould not be found in the following locations\n"); + std::string files; for (std::string const& testFile : testFiles) { - msg += " "; - msg += Quoted(testFile); - msg += '\n'; + files += cmStrCat(" ", Quoted(testFile), '\n'); } - LogFileError(GenT::UIC, sourceFile, msg); + LogFileError( + GenT::UIC, sourceFile, + cmStrCat("The file includes the uic file ", Quoted(incKey.Key), + ",\nbut the user interface file ", Quoted(searchFileName), + "\ncould not be found in the following locations\n", files)); } return SourceFileHandleT(); @@ -1257,9 +1247,7 @@ cmQtAutoMocUic::JobGenerateT::MocFindDependency( } // Search in include directories for (std::string const& includePath : MocConst().IncludePaths) { - ResPair res{ includePath, {} }; - res.first += '/'; - res.first += includeString; + ResPair res{ cmStrCat(includePath, '/', includeString), {} }; if (res.second.Load(res.first)) { return res; } @@ -1366,21 +1354,19 @@ void cmQtAutoMocUic::JobMocT::Process() } } else { // Moc command failed - std::string msg = - cmStrCat("The moc process failed to compile\n ", Quoted(sourceFile), - "\ninto\n ", Quoted(outputFile)); - if (Mapping->IncluderFiles.empty()) { - msg += ".\n"; - } else { - msg += "\nincluded by\n"; + std::string includers; + if (!Mapping->IncluderFiles.empty()) { + includers = "included by\n"; for (auto const& item : Mapping->IncluderFiles) { - msg += " "; - msg += Quoted(item->FileName); - msg += '\n'; + includers += cmStrCat(" ", Quoted(item->FileName), '\n'); } } - msg += result.ErrorMessage; - LogCommandError(GenT::MOC, msg, cmd, result.StdOut); + LogCommandError(GenT::MOC, + cmStrCat("The moc process failed to compile\n ", + Quoted(sourceFile), "\ninto\n ", + Quoted(outputFile), '\n', includers, + result.ErrorMessage), + cmd, result.StdOut); } } @@ -1414,16 +1400,16 @@ void cmQtAutoMocUic::JobUicT::Process() } } else { // Uic command failed - std::string msg = - cmStrCat("The uic process failed to compile\n ", Quoted(sourceFile), - "\ninto\n ", Quoted(outputFile), "\nincluded by\n"); + std::string includers; for (auto const& item : Mapping->IncluderFiles) { - msg += " "; - msg += Quoted(item->FileName); - msg += '\n'; + includers += cmStrCat(" ", Quoted(item->FileName), '\n'); } - msg += result.ErrorMessage; - LogCommandError(GenT::UIC, msg, cmd, result.StdOut); + LogCommandError(GenT::UIC, + cmStrCat("The uic process failed to compile\n ", + Quoted(sourceFile), "\ninto\n ", + Quoted(outputFile), "\nincluded by\n", includers, + result.ErrorMessage), + cmd, result.StdOut); } } @@ -1436,19 +1422,14 @@ void cmQtAutoMocUic::JobMocsCompilationT::Process() if (MocEval().CompFiles.empty()) { // Placeholder content content += "// No files found that require moc or the moc files are " - "included\n"; - content += "enum some_compilers { need_more_than_nothing };\n"; + "included\n" + "enum some_compilers { need_more_than_nothing };\n"; } else { // Valid content - char const clampB = BaseConst().MultiConfig ? '<' : '"'; - char const clampE = BaseConst().MultiConfig ? '>' : '"'; - for (std::string const& mocfile : MocEval().CompFiles) { - content += "#include "; - content += clampB; - content += mocfile; - content += clampE; - content += '\n'; - } + const bool mc = BaseConst().MultiConfig; + cm::string_view const wrapFront = mc ? "#include <" : "#include \""; + cm::string_view const wrapBack = mc ? ">\n" : "\"\n"; + content += cmWrap(wrapFront, MocEval().CompFiles, wrapBack, ""); } std::string const& compAbs = MocConst().CompFileAbs; @@ -1484,22 +1465,21 @@ cmQtAutoMocUic::~cmQtAutoMocUic() = default; bool cmQtAutoMocUic::Init(cmMakefile* makefile) { // Utility lambdas - auto InfoGet = [makefile](const char* key) { - return makefile->GetSafeDefinition(key); + auto InfoGet = [makefile](cm::string_view key) { + return makefile->GetSafeDefinition(std::string(key)); }; - auto InfoGetBool = [makefile](const char* key) { - return makefile->IsOn(key); + auto InfoGetBool = [makefile](cm::string_view key) { + return makefile->IsOn(std::string(key)); }; - auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> { - std::vector<std::string> list = - cmExpandedList(makefile->GetSafeDefinition(key)); - return list; + auto InfoGetList = + [makefile](cm::string_view key) -> std::vector<std::string> { + return cmExpandedList(makefile->GetSafeDefinition(std::string(key))); }; auto InfoGetLists = - [makefile](const char* key) -> std::vector<std::vector<std::string>> { + [makefile](cm::string_view key) -> std::vector<std::vector<std::string>> { std::vector<std::vector<std::string>> lists; { - std::string const value = makefile->GetSafeDefinition(key); + std::string const value = makefile->GetSafeDefinition(std::string(key)); std::string::size_type pos = 0; while (pos < value.size()) { std::string::size_type next = value.find(ListSep, pos); @@ -1517,38 +1497,30 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) } return lists; }; - auto InfoGetConfig = [makefile, this](const char* key) -> std::string { - const char* valueConf = nullptr; - { - std::string keyConf = cmStrCat(key, '_', InfoConfig()); - valueConf = makefile->GetDefinition(keyConf); - } - if (valueConf == nullptr) { - return makefile->GetSafeDefinition(key); + auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string { + if (const char* valueConf = + makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) { + return std::string(valueConf); } - return std::string(valueConf); + return makefile->GetSafeDefinition(std::string(key)); }; auto InfoGetConfigList = - [&InfoGetConfig](const char* key) -> std::vector<std::string> { - std::vector<std::string> list = cmExpandedList(InfoGetConfig(key)); - return list; + [&InfoGetConfig](cm::string_view key) -> std::vector<std::string> { + return cmExpandedList(InfoGetConfig(key)); }; - auto LogInfoError = [this](std::string const& msg) -> bool { - std::ostringstream err; - err << "In " << Quoted(this->InfoFile()) << ":\n" << msg; - this->Log().Error(GenT::GEN, err.str()); + auto LogInfoError = [this](cm::string_view msg) -> bool { + this->Log().Error(GenT::GEN, + cmStrCat("In ", Quoted(this->InfoFile()), ":\n", msg)); return false; }; - auto MatchSizes = [&LogInfoError](const char* keyA, const char* keyB, + auto MatchSizes = [&LogInfoError](cm::string_view keyA, cm::string_view keyB, std::size_t sizeA, std::size_t sizeB) -> bool { if (sizeA == sizeB) { return true; } - std::ostringstream err; - err << "Lists sizes mismatch " << keyA << '(' << sizeA << ") " << keyB - << '(' << sizeB << ')'; - return LogInfoError(err.str()); + return LogInfoError(cmStrCat("Lists sizes mismatch ", keyA, '(', sizeA, + ") ", keyB, '(', sizeB, ')')); }; // -- Read info file @@ -1590,10 +1562,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) return LogInfoError("CMake executable file name missing."); } if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) { - std::string error = - cmStrCat("The CMake executable ", Quoted(BaseConst_.CMakeExecutable), - " does not exist."); - return LogInfoError(error); + return LogInfoError(cmStrCat("The CMake executable ", + Quoted(BaseConst_.CMakeExecutable), + " does not exist.")); } BaseConst_.ParseCacheFile = InfoGetConfig("AM_PARSE_CACHE_FILE"); if (BaseConst_.ParseCacheFile.empty()) { @@ -1620,10 +1591,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) MocConst_.Enabled = true; // Load the executable file time if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) { - std::string error = - cmStrCat("The moc executable ", Quoted(MocConst_.Executable), - " does not exist."); - return LogInfoError(error); + return LogInfoError(cmStrCat("The moc executable ", + Quoted(MocConst_.Executable), + " does not exist.")); } for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) { MocConst_.SkipList.insert(std::move(sfl)); @@ -1639,12 +1609,11 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) { auto addFilter = [this, &LogInfoError](std::string const& key, std::string const& exp) -> bool { - auto filterErr = [&LogInfoError, &key, &exp](const char* err) -> bool { - std::ostringstream ferr; - ferr << "AUTOMOC_DEPEND_FILTERS: " << err << '\n'; - ferr << " Key: " << Quoted(key) << '\n'; - ferr << " Exp: " << Quoted(exp) << '\n'; - return LogInfoError(ferr.str()); + auto filterErr = [&LogInfoError, &key, + &exp](cm::string_view err) -> bool { + return LogInfoError(cmStrCat("AUTOMOC_DEPEND_FILTERS: ", err, '\n', + " Key: ", Quoted(key), '\n', + " Exp: ", Quoted(exp), '\n')); }; if (key.empty()) { return filterErr("Key is empty"); @@ -1688,10 +1657,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) UicConst_.Enabled = true; // Load the executable file time if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) { - std::string error = - cmStrCat("The uic executable ", Quoted(UicConst_.Executable), - " does not exist."); - return LogInfoError(error); + return LogInfoError(cmStrCat("The uic executable ", + Quoted(UicConst_.Executable), + " does not exist.")); } for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) { UicConst_.SkipList.insert(std::move(sfl)); @@ -1699,8 +1667,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) UicConst_.SearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS"); UicConst_.TargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS"); { - const char* keyFiles = "AM_UIC_OPTIONS_FILES"; - const char* keyOpts = "AM_UIC_OPTIONS_OPTIONS"; + cm::string_view const keyFiles = "AM_UIC_OPTIONS_FILES"; + cm::string_view const keyOpts = "AM_UIC_OPTIONS_OPTIONS"; auto sources = InfoGetList(keyFiles); auto options = InfoGetLists(keyOpts); if (!MatchSizes(keyFiles, keyOpts, sources.size(), options.size())) { @@ -1742,8 +1710,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) // Headers { // Get file lists - const char* keyFiles = "AM_HEADERS"; - const char* keyFlags = "AM_HEADERS_FLAGS"; + cm::string_view const keyFiles = "AM_HEADERS"; + cm::string_view const keyFlags = "AM_HEADERS_FLAGS"; std::vector<std::string> files = InfoGetList(keyFiles); std::vector<std::string> flags = InfoGetList(keyFlags); std::vector<std::string> builds; @@ -1751,7 +1719,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) return false; } if (MocConst().Enabled) { - const char* keyPaths = "AM_HEADERS_BUILD_PATHS"; + cm::string_view const keyPaths = "AM_HEADERS_BUILD_PATHS"; builds = InfoGetList(keyPaths); if (!MatchSizes(keyFiles, keyPaths, files.size(), builds.size())) { return false; @@ -1778,8 +1746,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) // Sources { - const char* keyFiles = "AM_SOURCES"; - const char* keyFlags = "AM_SOURCES_FLAGS"; + cm::string_view const keyFiles = "AM_SOURCES"; + cm::string_view const keyFlags = "AM_SOURCES_FLAGS"; std::vector<std::string> files = InfoGetList(keyFiles); std::vector<std::string> flags = InfoGetList(keyFlags); if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) { @@ -1807,12 +1775,12 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) // Moc predefs file if (!MocConst_.PredefsCmd.empty()) { - MocConst_.PredefsFileRel = "moc_predefs"; if (BaseConst_.MultiConfig) { - MocConst_.PredefsFileRel += '_'; - MocConst_.PredefsFileRel += InfoConfig(); + MocConst_.PredefsFileRel = + cmStrCat("moc_predefs_", InfoConfig(), ".h"); + } else { + MocConst_.PredefsFileRel = "moc_predefs.h"; } - MocConst_.PredefsFileRel += ".h"; MocConst_.PredefsFileAbs = AbsoluteBuildPath(MocConst().PredefsFileRel); } @@ -1825,14 +1793,14 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) MocConst_.IncludePaths.reserve(includes.size()); // Append project directories only { - std::array<std::string const*, 2> const movePaths = { - { &BaseConst().ProjectBinaryDir, &BaseConst().ProjectSourceDir } + std::initializer_list<cm::string_view> const movePaths = { + BaseConst().ProjectBinaryDir, BaseConst().ProjectSourceDir }; - for (std::string const* ppath : movePaths) { + for (cm::string_view const& ppath : movePaths) { std::list<std::string>::iterator it = includes.begin(); while (it != includes.end()) { std::string const& path = *it; - if (cmHasPrefix(path, *ppath)) { + if (cmHasPrefix(path, ppath)) { MocConst_.IncludePaths.push_back(path); it = includes.erase(it); } else { @@ -1944,22 +1912,19 @@ void cmQtAutoMocUic::SettingsFileRead() // Compose current settings strings { cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256); - std::string const sep(";"); - auto cha = [&cryptoHash, &sep](std::string const& value) { + auto cha = [&cryptoHash](cm::string_view value) { cryptoHash.Append(value); - cryptoHash.Append(sep); + cryptoHash.Append(";"); }; if (MocConst_.Enabled) { cryptoHash.Initialize(); cha(MocConst().Executable); - for (auto const& value : MocConst().AllOptions) { - cha(value); - } + std::for_each(MocConst().AllOptions.begin(), MocConst().AllOptions.end(), + cha); cha(BaseConst().IncludeProjectDirsBefore ? "TRUE" : "FALSE"); - for (auto const& value : MocConst().PredefsCmd) { - cha(value); - } + std::for_each(MocConst().PredefsCmd.begin(), MocConst().PredefsCmd.end(), + cha); for (auto const& filter : MocConst().DependFilters) { cha(filter.Key); } @@ -1972,14 +1937,11 @@ void cmQtAutoMocUic::SettingsFileRead() if (UicConst().Enabled) { cryptoHash.Initialize(); cha(UicConst().Executable); - for (auto const& value : UicConst().TargetOptions) { - cha(value); - } + std::for_each(UicConst().TargetOptions.begin(), + UicConst().TargetOptions.end(), cha); for (const auto& item : UicConst().Options) { cha(item.first); - for (auto const& svalue : item.second) { - cha(svalue); - } + std::for_each(item.second.begin(), item.second.end(), cha); } SettingsStringUic_ = cryptoHash.FinalizeHex(); } @@ -2027,13 +1989,10 @@ bool cmQtAutoMocUic::SettingsFileWrite() // Compose settings file content std::string content; { - auto SettingAppend = [&content](const char* key, - std::string const& value) { + auto SettingAppend = [&content](cm::string_view key, + cm::string_view value) { if (!value.empty()) { - content += key; - content += ':'; - content += value; - content += '\n'; + content += cmStrCat(key, ':', value, '\n'); } }; SettingAppend("moc", SettingsStringMoc_); @@ -2054,7 +2013,7 @@ bool cmQtAutoMocUic::SettingsFileWrite() void cmQtAutoMocUic::ParseCacheRead() { - const char* reason = nullptr; + cm::string_view reason; // Don't read the cache if it is invalid if (!BaseEval().ParseCacheTime.Load(BaseConst().ParseCacheFile)) { reason = "Refreshing parse cache because it doesn't exist."; @@ -2066,7 +2025,7 @@ void cmQtAutoMocUic::ParseCacheRead() "Refreshing parse cache because it is older than the CMake executable."; } - if (reason != nullptr) { + if (!reason.empty()) { // Don't read but refresh the complete parse cache if (Log().Verbose()) { Log().Info(GenT::GEN, reason); @@ -2115,19 +2074,13 @@ void cmQtAutoMocUic::Abort(bool error) } std::string cmQtAutoMocUic::AbsoluteBuildPath( - std::string const& relativePath) const + cm::string_view relativePath) const { - std::string res(BaseConst().AutogenBuildDir); - res += '/'; - res += relativePath; - return res; + return cmStrCat(BaseConst().AutogenBuildDir, '/', relativePath); } std::string cmQtAutoMocUic::AbsoluteIncludePath( - std::string const& relativePath) const + cm::string_view relativePath) const { - std::string res(BaseConst().AutogenIncludeDir); - res += '/'; - res += relativePath; - return res; + return cmStrCat(BaseConst().AutogenIncludeDir, '/', relativePath); } diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h index dc18328..f676c57 100644 --- a/Source/cmQtAutoMocUic.h +++ b/Source/cmQtAutoMocUic.h @@ -9,6 +9,7 @@ #include "cmQtAutoGen.h" #include "cmQtAutoGenerator.h" #include "cmWorkerPool.h" +#include "cm_string_view.hxx" #include "cmsys/RegularExpression.hxx" #include <atomic> @@ -333,10 +334,10 @@ public: UicEvalT& UicEval() const { return Gen()->UicEval(); } // -- Error logging with automatic abort - void LogError(GenT genType, std::string const& message) const; - void LogFileError(GenT genType, std::string const& filename, - std::string const& message) const; - void LogCommandError(GenT genType, std::string const& message, + void LogError(GenT genType, cm::string_view message) const; + void LogFileError(GenT genType, cm::string_view filename, + cm::string_view message) const; + void LogCommandError(GenT genType, cm::string_view message, std::vector<std::string> const& command, std::string const& output) const; @@ -429,7 +430,7 @@ public: SourceFileHandleT MocFindIncludedHeader( std::string const& includerDir, std::string const& includeBase) const; SourceFileHandleT MocFindHeader(std::string const& basePath) const; - std::string MocMessageTestHeaders(std::string const& fileBase) const; + std::string MocMessageTestHeaders(cm::string_view fileBase) const; bool MocRegisterIncluded(std::string const& includeString, SourceFileHandleT includerFileHandle, SourceFileHandleT sourceFileHandle, @@ -439,7 +440,7 @@ public: // -- Uic bool UicEval(SourceFileMapT const& fileMap); - bool UicEvalFile(SourceFileHandleT sourceFileHandle); + bool UicEvalFile(SourceFileHandleT const& sourceFileHandle); SourceFileHandleT UicFindIncludedUi(std::string const& sourceFile, std::string const& sourceDir, IncludeKeyT const& incKey) const; @@ -531,8 +532,8 @@ public: void AbortSuccess() { Abort(false); } // -- Utility - std::string AbsoluteBuildPath(std::string const& relativePath) const; - std::string AbsoluteIncludePath(std::string const& relativePath) const; + std::string AbsoluteBuildPath(cm::string_view relativePath) const; + std::string AbsoluteIncludePath(cm::string_view relativePath) const; template <class JOBTYPE> void CreateParseJobs(SourceFileMapT const& sourceMap); diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx index cc1a290..e931346 100644 --- a/Source/cmQtAutoRcc.cxx +++ b/Source/cmQtAutoRcc.cxx @@ -1,9 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoRcc.h" -#include "cmQtAutoGen.h" - -#include <sstream> #include "cmAlgorithms.h" #include "cmCryptoHash.h" @@ -11,10 +8,12 @@ #include "cmFileLockResult.h" #include "cmMakefile.h" #include "cmProcessOutput.h" +#include "cmQtAutoGen.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cm_string_view.hxx" -// -- Class methods +#include <algorithm> cmQtAutoRcc::cmQtAutoRcc() = default; @@ -23,36 +22,27 @@ cmQtAutoRcc::~cmQtAutoRcc() = default; bool cmQtAutoRcc::Init(cmMakefile* makefile) { // -- Utility lambdas - auto InfoGet = [makefile](std::string const& key) { - return makefile->GetSafeDefinition(key); + auto InfoGet = [makefile](cm::string_view key) { + return makefile->GetSafeDefinition(std::string(key)); }; auto InfoGetList = - [makefile](std::string const& key) -> std::vector<std::string> { - std::vector<std::string> list = - cmExpandedList(makefile->GetSafeDefinition(key)); - return list; + [makefile](cm::string_view key) -> std::vector<std::string> { + return cmExpandedList(makefile->GetSafeDefinition(std::string(key))); }; - auto InfoGetConfig = [makefile, - this](std::string const& key) -> std::string { - const char* valueConf = nullptr; - { - std::string keyConf = cmStrCat(key, '_', InfoConfig()); - valueConf = makefile->GetDefinition(keyConf); + auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string { + if (const char* valueConf = + makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) { + return std::string(valueConf); } - if (valueConf == nullptr) { - return makefile->GetSafeDefinition(key); - } - return std::string(valueConf); + return makefile->GetSafeDefinition(std::string(key)); }; auto InfoGetConfigList = - [&InfoGetConfig](std::string const& key) -> std::vector<std::string> { - std::vector<std::string> list = cmExpandedList(InfoGetConfig(key)); - return list; + [&InfoGetConfig](cm::string_view key) -> std::vector<std::string> { + return cmExpandedList(InfoGetConfig(key)); }; - auto LogInfoError = [this](std::string const& msg) -> bool { - std::ostringstream err; - err << "In " << Quoted(this->InfoFile()) << ":\n" << msg; - this->Log().Error(GenT::RCC, err.str()); + auto LogInfoError = [this](cm::string_view msg) -> bool { + this->Log().Error(GenT::RCC, + cmStrCat("In ", Quoted(this->InfoFile()), ":\n", msg)); return false; }; @@ -79,9 +69,8 @@ bool cmQtAutoRcc::Init(cmMakefile* makefile) // - Rcc executable RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE"); if (!RccExecutableTime_.Load(RccExecutable_)) { - std::string error = cmStrCat("The rcc executable ", Quoted(RccExecutable_), - " does not exist."); - return LogInfoError(error); + return LogInfoError(cmStrCat("The rcc executable ", Quoted(RccExecutable_), + " does not exist.")); } RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS"); @@ -169,25 +158,27 @@ bool cmQtAutoRcc::Process() std::string cmQtAutoRcc::MultiConfigOutput() const { - static std::string const suffix = "_CMAKE_"; - std::string res = cmStrCat(RccPathChecksum_, '/', - AppendFilenameSuffix(RccFileName_, suffix)); - return res; + return cmStrCat(RccPathChecksum_, '/', + AppendFilenameSuffix(RccFileName_, "_CMAKE_")); } bool cmQtAutoRcc::SettingsFileRead() { // Compose current settings strings { - cmCryptoHash crypt(cmCryptoHash::AlgoSHA256); - std::string const sep(" ~~~ "); - { - std::string str = - cmStrCat(RccExecutable_, sep, cmJoin(RccListOptions_, ";"), sep, - QrcFile_, sep, RccPathChecksum_, sep, RccFileName_, sep, - cmJoin(Options_, ";"), sep, cmJoin(Inputs_, ";"), sep); - SettingsString_ = crypt.HashString(str); - } + cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256); + auto cha = [&cryptoHash](cm::string_view value) { + cryptoHash.Append(value); + cryptoHash.Append(";"); + }; + cha(RccExecutable_); + std::for_each(RccListOptions_.begin(), RccListOptions_.end(), cha); + cha(QrcFile_); + cha(RccPathChecksum_); + cha(RccFileName_); + std::for_each(Options_.begin(), Options_.end(), cha); + std::for_each(Inputs_.begin(), Inputs_.end(), cha); + SettingsString_ = cryptoHash.FinalizeHex(); } // Make sure the settings file exists @@ -272,10 +263,9 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate) { // Test if the rcc input file exists if (!QrcFileTime_.Load(QrcFile_)) { - std::string error; - error = - cmStrCat("The resources file ", Quoted(QrcFile_), " does not exist"); - Log().ErrorFile(GenT::RCC, QrcFile_, error); + Log().ErrorFile( + GenT::RCC, QrcFile_, + cmStrCat("The resources file ", Quoted(QrcFile_), " does not exist")); return false; } @@ -342,10 +332,9 @@ bool cmQtAutoRcc::TestResources(bool& generate) // Check if the resource file exists cmFileTime fileTime; if (!fileTime.Load(resFile)) { - std::string error; - error = cmStrCat("Could not find the resource file\n ", Quoted(resFile), - '\n'); - Log().ErrorFile(GenT::RCC, QrcFile_, error); + Log().ErrorFile(GenT::RCC, QrcFile_, + cmStrCat("Could not find the resource file\n ", + Quoted(resFile), '\n')); return false; } // Check if the resource file is newer than the rcc output file @@ -367,10 +356,9 @@ bool cmQtAutoRcc::TestInfoFile() // Test if the rcc output file is older than the info file if (RccFileTime_.Older(InfoFileTime())) { if (Log().Verbose()) { - std::string reason = - cmStrCat("Touching ", Quoted(RccFileOutput_), - " because it is older than ", Quoted(InfoFile())); - Log().Info(GenT::RCC, reason); + Log().Info(GenT::RCC, + cmStrCat("Touching ", Quoted(RccFileOutput_), + " because it is older than ", Quoted(InfoFile()))); } // Touch build file if (!cmSystemTools::Touch(RccFileOutput_, false)) { @@ -402,13 +390,9 @@ bool cmQtAutoRcc::GenerateRcc() // Log reason and command if (Log().Verbose()) { - std::string msg = Reason; - if (!msg.empty() && (msg.back() != '\n')) { - msg += '\n'; - } - msg += QuotedCommand(cmd); - msg += '\n'; - Log().Info(GenT::RCC, msg); + Log().Info(GenT::RCC, + cmStrCat(Reason, cmHasSuffix(Reason, '\n') ? "" : "\n", + QuotedCommand(cmd), '\n')); } std::string rccStdOut; @@ -419,12 +403,11 @@ bool cmQtAutoRcc::GenerateRcc() cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); if (!result || (retVal != 0)) { // rcc process failed - { - std::string err = - cmStrCat("The rcc process failed to compile\n ", Quoted(QrcFile_), - "\ninto\n ", Quoted(RccFileOutput_)); - Log().ErrorCommand(GenT::RCC, err, cmd, rccStdOut + rccStdErr); - } + Log().ErrorCommand(GenT::RCC, + cmStrCat("The rcc process failed to compile\n ", + Quoted(QrcFile_), "\ninto\n ", + Quoted(RccFileOutput_)), + cmd, rccStdOut + rccStdErr); cmSystemTools::RemoveFile(RccFileOutput_); return false; } diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index a6d2807..5d738d5 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -45,11 +45,13 @@ std::string cmSourceFile::GetObjectLibrary() const return this->ObjectLibrary; } -std::string cmSourceFile::GetLanguage() +std::string const& cmSourceFile::GetOrDetermineLanguage() { // If the language was set explicitly by the user then use it. if (const char* lang = this->GetProperty(propLANGUAGE)) { - return lang; + // Assign to member in order to return a reference. + this->Language = lang; + return this->Language; } // Perform computation needed to get the language if necessary. @@ -72,8 +74,8 @@ std::string cmSourceFile::GetLanguage() } } - // Now try to determine the language. - return static_cast<cmSourceFile const*>(this)->GetLanguage(); + // Use the language determined from the file extension. + return this->Language; } std::string cmSourceFile::GetLanguage() const @@ -83,13 +85,8 @@ std::string cmSourceFile::GetLanguage() const return lang; } - // If the language was determined from the source file extension use it. - if (!this->Language.empty()) { - return this->Language; - } - - // The language is not known. - return ""; + // Use the language determined from the file extension. + return this->Language; } cmSourceFileLocation const& cmSourceFile::GetLocation() const @@ -275,6 +272,13 @@ const char* cmSourceFile::GetPropertyForUser(const std::string& prop) this->GetFullPath(); } + // Similarly, LANGUAGE can be determined by the file extension + // if it is requested by the user. + if (prop == propLANGUAGE) { + // The c_str pointer is valid until `this->Language` is modified. + return this->GetOrDetermineLanguage().c_str(); + } + // Perform the normal property lookup. return this->GetProperty(prop); } diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index edad4c7..ccd5b62 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -88,7 +88,7 @@ public: /** * Get the language of the compiler to use for this source file. */ - std::string GetLanguage(); + std::string const& GetOrDetermineLanguage(); std::string GetLanguage() const; /** diff --git a/Source/cmState.cxx b/Source/cmState.cxx index b6f1808..902287c 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -14,7 +14,6 @@ #include "cmCacheManager.h" #include "cmCommand.h" #include "cmDefinitions.h" -#include "cmDisallowedCommand.h" #include "cmExecutionStatus.h" #include "cmGlobVerificationManager.h" #include "cmListFileCache.h" @@ -485,16 +484,6 @@ void cmState::AddDisallowedCommand(std::string const& name, }); } -void cmState::AddDisallowedCommand(std::string const& name, - std::unique_ptr<cmCommand> command, - cmPolicies::PolicyID policy, - const char* message) -{ - this->AddBuiltinCommand( - name, - cm::make_unique<cmDisallowedCommand>(std::move(command), policy, message)); -} - void cmState::AddUnexpectedCommand(std::string const& name, const char* error) { this->AddBuiltinCommand( diff --git a/Source/cmState.h b/Source/cmState.h index 937ab61..a7ca015 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -159,9 +159,6 @@ public: void AddBuiltinCommand(std::string const& name, BuiltinCommand command); void AddDisallowedCommand(std::string const& name, BuiltinCommand command, cmPolicies::PolicyID policy, const char* message); - void AddDisallowedCommand(std::string const& name, - std::unique_ptr<cmCommand> command, - cmPolicies::PolicyID policy, const char* message); void AddUnexpectedCommand(std::string const& name, const char* error); void AddScriptedCommand(std::string const& name, Command command); void RemoveBuiltinCommand(std::string const& name); diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx index 0bb2c0a..496c60d 100644 --- a/Source/cmSubdirDependsCommand.cxx +++ b/Source/cmSubdirDependsCommand.cxx @@ -4,8 +4,8 @@ class cmExecutionStatus; -bool cmSubdirDependsCommand::InitialPass(std::vector<std::string> const&, - cmExecutionStatus&) +bool cmSubdirDependsCommand(std::vector<std::string> const&, + cmExecutionStatus&) { return true; } diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h index 64c28b9..bf99bd1 100644 --- a/Source/cmSubdirDependsCommand.h +++ b/Source/cmSubdirDependsCommand.h @@ -8,21 +8,9 @@ #include <string> #include <vector> -#include "cm_memory.hxx" - -#include "cmCommand.h" - class cmExecutionStatus; -class cmSubdirDependsCommand : public cmCommand -{ -public: - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmSubdirDependsCommand>(); - } - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmSubdirDependsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 5311d38..2a09b43 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -190,6 +190,8 @@ public: std::vector<cmListFileBacktrace> CompileFeaturesBacktraces; std::vector<std::string> CompileDefinitionsEntries; std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces; + std::vector<std::string> PrecompileHeadersEntries; + std::vector<cmListFileBacktrace> PrecompileHeadersBacktraces; std::vector<std::string> SourceEntries; std::vector<cmListFileBacktrace> SourceBacktraces; std::vector<std::string> LinkOptionsEntries; @@ -349,6 +351,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("Swift_LANGUAGE_VERSION"); initProp("Swift_MODULE_DIRECTORY"); initProp("VS_JUST_MY_CODE_DEBUGGING"); + initProp("DISABLE_PRECOMPILE_HEADERS"); #ifdef __APPLE__ if (this->GetGlobalGenerator()->IsXcode()) { initProp("XCODE_GENERATE_SCHEME"); @@ -1018,6 +1021,16 @@ cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const return cmMakeRange(impl->CompileDefinitionsBacktraces); } +cmStringRange cmTarget::GetPrecompileHeadersEntries() const +{ + return cmMakeRange(impl->PrecompileHeadersEntries); +} + +cmBacktraceRange cmTarget::GetPrecompileHeadersBacktraces() const +{ + return cmMakeRange(impl->PrecompileHeadersBacktraces); +} + cmStringRange cmTarget::GetSourceEntries() const { return cmMakeRange(impl->SourceEntries); @@ -1069,6 +1082,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(COMPILE_FEATURES); MAKE_STATIC_PROP(COMPILE_OPTIONS); + MAKE_STATIC_PROP(PRECOMPILE_HEADERS); MAKE_STATIC_PROP(CUDA_PTX_COMPILATION); MAKE_STATIC_PROP(EXPORT_NAME); MAKE_STATIC_PROP(IMPORTED_GLOBAL); @@ -1167,6 +1181,14 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->LinkDirectoriesBacktraces.push_back(lfbt); } + } else if (prop == propPRECOMPILE_HEADERS) { + impl->PrecompileHeadersEntries.clear(); + impl->PrecompileHeadersBacktraces.clear(); + if (value) { + impl->PrecompileHeadersEntries.emplace_back(value); + cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); + impl->PrecompileHeadersBacktraces.push_back(lfbt); + } } else if (prop == propLINK_LIBRARIES) { impl->LinkImplementationPropertyEntries.clear(); impl->LinkImplementationPropertyBacktraces.clear(); @@ -1283,6 +1305,12 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->LinkDirectoriesBacktraces.push_back(lfbt); } + } else if (prop == "PRECOMPILE_HEADERS") { + if (value && *value) { + impl->PrecompileHeadersEntries.emplace_back(value); + cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); + impl->PrecompileHeadersBacktraces.push_back(lfbt); + } } else if (prop == "LINK_LIBRARIES") { if (value && *value) { cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); @@ -1394,6 +1422,13 @@ void cmTarget::InsertLinkDirectory(std::string const& entry, impl->LinkDirectoriesBacktraces.insert(btPosition, bt); } +void cmTarget::InsertPrecompileHeader(std::string const& entry, + cmListFileBacktrace const& bt) +{ + impl->PrecompileHeadersEntries.push_back(entry); + impl->PrecompileHeadersBacktraces.push_back(bt); +} + static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, const char* value, cmMakefile* context, @@ -1514,6 +1549,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(LINK_OPTIONS); MAKE_STATIC_PROP(LINK_DIRECTORIES); + MAKE_STATIC_PROP(PRECOMPILE_HEADERS); MAKE_STATIC_PROP(IMPORTED); MAKE_STATIC_PROP(IMPORTED_GLOBAL); MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); @@ -1529,6 +1565,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const propCOMPILE_FEATURES, propCOMPILE_OPTIONS, propCOMPILE_DEFINITIONS, + propPRECOMPILE_HEADERS, propLINK_OPTIONS, propLINK_DIRECTORIES, propIMPORTED, @@ -1617,6 +1654,15 @@ const char* cmTarget::GetProperty(const std::string& prop) const output = cmJoin(impl->Utilities, ";"); return output.c_str(); } + if (prop == propPRECOMPILE_HEADERS) { + if (impl->PrecompileHeadersEntries.empty()) { + return nullptr; + } + + static std::string output; + output = cmJoin(impl->PrecompileHeadersEntries, ";"); + return output.c_str(); + } if (prop == propIMPORTED) { return this->IsImported() ? "TRUE" : "FALSE"; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 2b75879..783c278 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -216,6 +216,8 @@ public: cmListFileBacktrace const& bt, bool before = false); void InsertLinkDirectory(std::string const& entry, cmListFileBacktrace const& bt, bool before = false); + void InsertPrecompileHeader(std::string const& entry, + cmListFileBacktrace const& bt); void AppendBuildInterfaceIncludes(); @@ -237,6 +239,9 @@ public: cmStringRange GetCompileDefinitionsEntries() const; cmBacktraceRange GetCompileDefinitionsBacktraces() const; + cmStringRange GetPrecompileHeadersEntries() const; + cmBacktraceRange GetPrecompileHeadersBacktraces() const; + cmStringRange GetSourceEntries() const; cmBacktraceRange GetSourceBacktraces() const; diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx new file mode 100644 index 0000000..30cf1be --- /dev/null +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -0,0 +1,36 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmTargetPrecompileHeadersCommand.h" + +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" +#include "cmTarget.h" + +bool cmTargetPrecompileHeadersCommand::InitialPass( + std::vector<std::string> const& args, cmExecutionStatus&) +{ + return this->HandleArguments(args, "PRECOMPILE_HEADERS"); +} + +void cmTargetPrecompileHeadersCommand::HandleMissingTarget( + const std::string& name) +{ + const std::string e = + cmStrCat("Cannot specify precompile headers for target \"", name, + "\" which is not built by this project."); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); +} + +std::string cmTargetPrecompileHeadersCommand::Join( + const std::vector<std::string>& content) +{ + return cmJoin(content, ";"); +} + +bool cmTargetPrecompileHeadersCommand::HandleDirectContent( + cmTarget* tgt, const std::vector<std::string>& content, bool, bool) +{ + tgt->AppendProperty("PRECOMPILE_HEADERS", this->Join(content).c_str()); + return true; +} diff --git a/Source/cmTargetPrecompileHeadersCommand.h b/Source/cmTargetPrecompileHeadersCommand.h new file mode 100644 index 0000000..1ddf2af --- /dev/null +++ b/Source/cmTargetPrecompileHeadersCommand.h @@ -0,0 +1,41 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmTargetPrecompileHeadersCommand_h +#define cmTargetPrecompileHeadersCommand_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> +#include <vector> + +#include "cm_memory.hxx" + +#include "cmCommand.h" + +#include "cmTargetPropCommandBase.h" + +class cmExecutionStatus; +class cmTarget; + +class cmTargetPrecompileHeadersCommand : public cmTargetPropCommandBase +{ +public: + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetPrecompileHeadersCommand>(); + } + + bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus& status) override; + +private: + void HandleMissingTarget(const std::string& name) override; + + bool HandleDirectContent(cmTarget* tgt, + const std::vector<std::string>& content, + bool prepend, bool system) override; + + std::string Join(const std::vector<std::string>& content) override; +}; + +#endif diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 3d83760..cfc00e8 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -5,26 +5,30 @@ #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" +#include "cmExecutionStatus.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; +namespace { +void CopyAndFullPathMesaHeader(const std::string& source, + const std::string& outdir); +} -bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmUseMangledMesaCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { // expected two arguments: // argument one: the full path to gl_mangle.h // argument two : directory for output of edited headers if (args.size() != 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } const std::string& inputDir = args[0]; std::string glh = cmStrCat(inputDir, "/gl.h"); if (!cmSystemTools::FileExists(glh)) { std::string e = cmStrCat("Bad path to Mesa, could not find: ", glh, ' '); - this->SetError(e); + status.SetError(e); return false; } const std::string& destDir = args[1]; @@ -37,14 +41,15 @@ bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::MakeDirectory(destDir); for (std::string const& f : files) { std::string path = cmStrCat(inputDir, '/', f); - this->CopyAndFullPathMesaHeader(path, destDir); + CopyAndFullPathMesaHeader(path, destDir); } return true; } -void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader( - const std::string& source, const std::string& outdir) +namespace { +void CopyAndFullPathMesaHeader(const std::string& source, + const std::string& outdir) { std::string dir; std::string file; @@ -96,3 +101,4 @@ void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader( cmSystemTools::CopyFileIfDifferent(tempOutputFile, outFile); cmSystemTools::RemoveFile(tempOutputFile); } +} diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h index 1c01596..215e4a3 100644 --- a/Source/cmUseMangledMesaCommand.h +++ b/Source/cmUseMangledMesaCommand.h @@ -8,25 +8,9 @@ #include <string> #include <vector> -#include "cm_memory.hxx" - -#include "cmCommand.h" - class cmExecutionStatus; -class cmUseMangledMesaCommand : public cmCommand -{ -public: - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmUseMangledMesaCommand>(); - } - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -protected: - void CopyAndFullPathMesaHeader(const std::string& source, - const std::string& outdir); -}; +bool cmUseMangledMesaCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index d255b67..25fe4ad 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -4,20 +4,19 @@ #include <string.h> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmUtilitySourceCommand -bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmUtilitySourceCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } @@ -25,15 +24,15 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, // The first argument is the cache entry name. std::string const& cacheEntry = *arg++; - const char* cacheValue = this->Makefile->GetDefinition(cacheEntry); + const char* cacheValue = status.GetMakefile().GetDefinition(cacheEntry); // If it exists already and appears up to date then we are done. If // the string contains "(IntDir)" but that is not the // CMAKE_CFG_INTDIR setting then the value is out of date. std::string const& intDir = - this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR"); + status.GetMakefile().GetRequiredDefinition("CMAKE_CFG_INTDIR"); bool haveCacheValue = false; - if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING")) { + if (status.GetMakefile().IsOn("CMAKE_CROSSCOMPILING")) { haveCacheValue = (cacheValue != nullptr); if (!haveCacheValue) { std::string msg = cmStrCat( @@ -44,7 +43,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::Message(msg, "Warning"); } } else { - cmState* state = this->Makefile->GetState(); + cmState* state = status.GetMakefile().GetState(); haveCacheValue = (cacheValue && (strstr(cacheValue, "(IntDir)") == nullptr || (intDir == "$(IntDir)")) && @@ -63,7 +62,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, // The third argument specifies the relative directory of the source // of the utility. std::string const& relativeSource = *arg++; - std::string utilitySource = this->Makefile->GetCurrentSourceDirectory(); + std::string utilitySource = status.GetMakefile().GetCurrentSourceDirectory(); utilitySource = utilitySource + "/" + relativeSource; // If the directory doesn't exist, the source has not been included. @@ -81,11 +80,12 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, // The source exists. const std::string& cmakeCFGout = - this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR"); - std::string utilityDirectory = this->Makefile->GetCurrentBinaryDirectory(); + status.GetMakefile().GetRequiredDefinition("CMAKE_CFG_INTDIR"); + std::string utilityDirectory = + status.GetMakefile().GetCurrentBinaryDirectory(); std::string exePath; - if (this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH")) { - exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"); + if (status.GetMakefile().GetDefinition("EXECUTABLE_OUTPUT_PATH")) { + exePath = status.GetMakefile().GetDefinition("EXECUTABLE_OUTPUT_PATH"); } if (!exePath.empty()) { utilityDirectory = exePath; @@ -95,21 +95,22 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, // Construct the cache entry for the executable's location. std::string utilityExecutable = utilityDirectory + "/" + cmakeCFGout + "/" + - utilityName + this->Makefile->GetDefinition("CMAKE_EXECUTABLE_SUFFIX"); + utilityName + + status.GetMakefile().GetDefinition("CMAKE_EXECUTABLE_SUFFIX"); // make sure we remove any /./ in the name cmSystemTools::ReplaceString(utilityExecutable, "/./", "/"); // Enter the value into the cache. - this->Makefile->AddCacheDefinition(cacheEntry, utilityExecutable.c_str(), - "Path to an internal program.", - cmStateEnums::FILEPATH); + status.GetMakefile().AddCacheDefinition( + cacheEntry, utilityExecutable.c_str(), "Path to an internal program.", + cmStateEnums::FILEPATH); // add a value into the cache that maps from the // full path to the name of the project cmSystemTools::ConvertToUnixSlashes(utilityExecutable); - this->Makefile->AddCacheDefinition(utilityExecutable, utilityName.c_str(), - "Executable to project name.", - cmStateEnums::INTERNAL); + status.GetMakefile().AddCacheDefinition( + utilityExecutable, utilityName.c_str(), "Executable to project name.", + cmStateEnums::INTERNAL); return true; } diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h index cef7fed..934d539 100644 --- a/Source/cmUtilitySourceCommand.h +++ b/Source/cmUtilitySourceCommand.h @@ -8,21 +8,9 @@ #include <string> #include <vector> -#include "cm_memory.hxx" - -#include "cmCommand.h" - class cmExecutionStatus; -class cmUtilitySourceCommand : public cmCommand -{ -public: - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmUtilitySourceCommand>(); - } - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmUtilitySourceCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index c44eeca..6b93c63 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -2,33 +2,32 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVariableRequiresCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmLibraryCommand -bool cmVariableRequiresCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmVariableRequiresCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } std::string const& testVariable = args[0]; - if (!this->Makefile->IsOn(testVariable)) { + if (!status.GetMakefile().IsOn(testVariable)) { return true; } std::string const& resultVariable = args[1]; bool requirementsMet = true; std::string notSet; bool hasAdvanced = false; - cmState* state = this->Makefile->GetState(); + cmState* state = status.GetMakefile().GetState(); for (unsigned int i = 2; i < args.size(); ++i) { - if (!this->Makefile->IsOn(args[i])) { + if (!status.GetMakefile().IsOn(args[i])) { requirementsMet = false; notSet += args[i]; notSet += "\n"; @@ -38,12 +37,12 @@ bool cmVariableRequiresCommand::InitialPass( } } } - const char* reqVar = this->Makefile->GetDefinition(resultVariable); + const char* reqVar = status.GetMakefile().GetDefinition(resultVariable); // if reqVar is unset, then set it to requirementsMet // if reqVar is set to true, but requirementsMet is false , then // set reqVar to false. - if (!reqVar || (!requirementsMet && this->Makefile->IsOn(reqVar))) { - this->Makefile->AddDefinitionBool(resultVariable, requirementsMet); + if (!reqVar || (!requirementsMet && status.GetMakefile().IsOn(reqVar))) { + status.GetMakefile().AddDefinitionBool(resultVariable, requirementsMet); } if (!requirementsMet) { diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h index 38e7490..fb0520e 100644 --- a/Source/cmVariableRequiresCommand.h +++ b/Source/cmVariableRequiresCommand.h @@ -8,21 +8,9 @@ #include <string> #include <vector> -#include "cm_memory.hxx" - -#include "cmCommand.h" - class cmExecutionStatus; -class cmVariableRequiresCommand : public cmCommand -{ -public: - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmVariableRequiresCommand>(); - } - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmVariableRequiresCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 13f6295..b4f05c7 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -249,6 +249,8 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator( this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() == this->Makefile->GetCurrentBinaryDirectory()); + + this->LocalGenerator->AddPchDependencies(target, ""); } cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() @@ -1115,7 +1117,10 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) std::string configType; if (const char* vsConfigurationType = this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) { - configType = vsConfigurationType; + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(vsConfigurationType); + configType = cge->Evaluate(this->LocalGenerator, c); } else { switch (this->GeneratorTarget->GetType()) { case cmStateEnums::SHARED_LIBRARY: @@ -2145,6 +2150,9 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) { this->OutputSourceSpecificFlags(e2, si.Source); } + if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { + e2.Element("PrecompiledHeader", "NotUsing"); + } if (!exclude_configs.empty()) { this->WriteExcludeFromBuild(e2, exclude_configs); } @@ -2626,6 +2634,13 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->IPOEnabledConfigurations.insert(configName); } + // Precompile Headers + std::string pchHeader = + this->GeneratorTarget->GetPchHeader(configName, linkLanguage); + if (this->MSTools && vcxproj == this->ProjectType && pchHeader.empty()) { + clOptions.AddFlag("PrecompiledHeader", "NotUsing"); + } + // Get preprocessor definitions for this directory. std::string defineFlags = this->Makefile->GetDefineFlags(); if (this->MSTools) { @@ -2641,7 +2656,6 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( // replace this setting with "true" below. clOptions.AddFlag("UseFullPaths", "false"); } - clOptions.AddFlag("PrecompiledHeader", "NotUsing"); clOptions.AddFlag("AssemblerListingLocation", "$(IntDir)"); } } |