From 3bc63e99e44b3ef82c19d018f939ea839882a131 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 14 Nov 2019 11:38:35 -0500 Subject: Refactor: Prepare Ninja generator for multi-config --- Source/cmCommonTargetGenerator.cxx | 51 ++-- Source/cmCommonTargetGenerator.h | 26 +- Source/cmGlobalNinjaGenerator.cxx | 55 +++-- Source/cmGlobalNinjaGenerator.h | 11 +- Source/cmLocalCommonGenerator.cxx | 10 +- Source/cmLocalCommonGenerator.h | 8 +- Source/cmLocalNinjaGenerator.cxx | 52 ++-- Source/cmLocalNinjaGenerator.h | 15 +- Source/cmLocalUnixMakefileGenerator3.cxx | 22 +- Source/cmLocalUnixMakefileGenerator3.h | 2 + Source/cmMakefileExecutableTargetGenerator.cxx | 55 +++-- Source/cmMakefileLibraryTargetGenerator.cxx | 92 +++---- Source/cmMakefileTargetGenerator.cxx | 123 ++++++---- Source/cmMakefileTargetGenerator.h | 8 +- Source/cmMakefileUtilityTargetGenerator.cxx | 3 +- Source/cmNinjaNormalTargetGenerator.cxx | 321 ++++++++++++++----------- Source/cmNinjaNormalTargetGenerator.h | 24 +- Source/cmNinjaTargetGenerator.cxx | 138 ++++++----- Source/cmNinjaTargetGenerator.h | 37 +-- Source/cmNinjaUtilityTargetGenerator.cxx | 19 +- Source/cmNinjaUtilityTargetGenerator.h | 4 +- Source/cmOSXBundleGenerator.cxx | 71 +++--- Source/cmOSXBundleGenerator.h | 21 +- 23 files changed, 641 insertions(+), 527 deletions(-) diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 19a096b..6c7d9e8 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -25,27 +25,29 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) static_cast(gt->LocalGenerator)) , GlobalCommonGenerator(static_cast( gt->LocalGenerator->GetGlobalGenerator())) - , ConfigName(LocalCommonGenerator->GetConfigName()) + , ConfigNames(LocalCommonGenerator->GetConfigNames()) { } cmCommonTargetGenerator::~cmCommonTargetGenerator() = default; -std::string const& cmCommonTargetGenerator::GetConfigName() const +std::vector const& cmCommonTargetGenerator::GetConfigNames() const { - return this->ConfigName; + return this->ConfigNames; } -const char* cmCommonTargetGenerator::GetFeature(const std::string& feature) +const char* cmCommonTargetGenerator::GetFeature(const std::string& feature, + const std::string& config) { - return this->GeneratorTarget->GetFeature(feature, this->ConfigName); + return this->GeneratorTarget->GetFeature(feature, config); } void cmCommonTargetGenerator::AddModuleDefinitionFlag( - cmLinkLineComputer* linkLineComputer, std::string& flags) + cmLinkLineComputer* linkLineComputer, std::string& flags, + const std::string& config) { cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + this->GeneratorTarget->GetModuleDefinitionInfo(config); if (!mdi || mdi->DefFile.empty()) { return; } @@ -94,14 +96,15 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags( } } -std::string cmCommonTargetGenerator::GetFlags(const std::string& l) +std::string cmCommonTargetGenerator::GetFlags(const std::string& l, + const std::string& config) { auto i = this->FlagsByLanguage.find(l); if (i == this->FlagsByLanguage.end()) { std::string flags; - this->LocalCommonGenerator->GetTargetCompileFlags( - this->GeneratorTarget, this->ConfigName, l, flags); + this->LocalCommonGenerator->GetTargetCompileFlags(this->GeneratorTarget, + config, l, flags); ByLanguageMap::value_type entry(l, flags); i = this->FlagsByLanguage.insert(entry).first; @@ -109,13 +112,14 @@ std::string cmCommonTargetGenerator::GetFlags(const std::string& l) return i->second; } -std::string cmCommonTargetGenerator::GetDefines(const std::string& l) +std::string cmCommonTargetGenerator::GetDefines(const std::string& l, + const std::string& config) { auto i = this->DefinesByLanguage.find(l); if (i == this->DefinesByLanguage.end()) { std::set defines; - this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, - this->ConfigName, l, defines); + this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, config, + l, defines); std::string definesString; this->LocalCommonGenerator->JoinDefines(defines, definesString, l); @@ -126,25 +130,26 @@ std::string cmCommonTargetGenerator::GetDefines(const std::string& l) return i->second; } -std::string cmCommonTargetGenerator::GetIncludes(std::string const& l) +std::string cmCommonTargetGenerator::GetIncludes(std::string const& l, + const std::string& config) { auto i = this->IncludesByLanguage.find(l); if (i == this->IncludesByLanguage.end()) { std::string includes; - this->AddIncludeFlags(includes, l); + this->AddIncludeFlags(includes, l, config); ByLanguageMap::value_type entry(l, includes); i = this->IncludesByLanguage.insert(entry).first; } return i->second; } -std::vector cmCommonTargetGenerator::GetLinkedTargetDirectories() - const +std::vector cmCommonTargetGenerator::GetLinkedTargetDirectories( + const std::string& config) const { std::vector dirs; std::set emitted; if (cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->ConfigName)) { + this->GeneratorTarget->GetLinkInformation(config)) { cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); for (auto const& item : items) { cmGeneratorTarget const* linkee = item.Target; @@ -165,15 +170,15 @@ std::vector cmCommonTargetGenerator::GetLinkedTargetDirectories() return dirs; } -std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const +std::string cmCommonTargetGenerator::ComputeTargetCompilePDB( + const std::string& config) const { std::string compilePdbPath; if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) { return compilePdbPath; } - compilePdbPath = - this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName()); + compilePdbPath = this->GeneratorTarget->GetCompilePDBPath(config); if (compilePdbPath.empty()) { // Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`. // A trailing slash tells the toolchain to add its default file name. @@ -188,10 +193,10 @@ std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const return compilePdbPath; } -std::string cmCommonTargetGenerator::GetManifests() +std::string cmCommonTargetGenerator::GetManifests(const std::string& config) { std::vector manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, config); std::vector manifests; manifests.reserve(manifest_srcs.size()); diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 17792d6..37b6880 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -25,42 +25,44 @@ public: cmCommonTargetGenerator(cmGeneratorTarget* gt); virtual ~cmCommonTargetGenerator(); - std::string const& GetConfigName() const; + std::vector const& GetConfigNames() const; protected: // Feature query methods. - const char* GetFeature(const std::string& feature); + const char* GetFeature(const std::string& feature, + const std::string& config); // Helper to add flag for windows .def file. void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer, - std::string& flags); + std::string& flags, const std::string& config); cmGeneratorTarget* GeneratorTarget; cmMakefile* Makefile; cmLocalCommonGenerator* LocalCommonGenerator; cmGlobalCommonGenerator* GlobalCommonGenerator; - std::string ConfigName; + std::vector ConfigNames; void AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source); - virtual void AddIncludeFlags(std::string& flags, - std::string const& lang) = 0; + virtual void AddIncludeFlags(std::string& flags, std::string const& lang, + const std::string& config) = 0; void AppendOSXVerFlag(std::string& flags, const std::string& lang, const char* name, bool so); using ByLanguageMap = std::map; - std::string GetFlags(const std::string& l); + std::string GetFlags(const std::string& l, const std::string& config); ByLanguageMap FlagsByLanguage; - std::string GetDefines(const std::string& l); + std::string GetDefines(const std::string& l, const std::string& config); ByLanguageMap DefinesByLanguage; - std::string GetIncludes(std::string const& l); + std::string GetIncludes(std::string const& l, const std::string& config); ByLanguageMap IncludesByLanguage; - std::string GetManifests(); + std::string GetManifests(const std::string& config); - std::vector GetLinkedTargetDirectories() const; - std::string ComputeTargetCompilePDB() const; + std::vector GetLinkedTargetDirectories( + const std::string& config) const; + std::string ComputeTargetCompilePDB(const std::string& config) const; }; #endif diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 3500007..87fd958 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -916,11 +916,8 @@ std::string OrderDependsTargetForTarget(cmGeneratorTarget const* target) void cmGlobalNinjaGenerator::AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, - cmNinjaTargetDepends depends) + const std::string& config, cmNinjaTargetDepends depends) { - std::string configName = - target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); - // for frameworks, we want the real name, not smple name // frameworks always appear versioned, and the build.ninja // will always attempt to manage symbolic links instead @@ -939,7 +936,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( // FALLTHROUGH case cmStateEnums::EXECUTABLE: { outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath( - configName, cmStateEnums::RuntimeBinaryArtifact, realname))); + config, cmStateEnums::RuntimeBinaryArtifact, realname))); break; } case cmStateEnums::OBJECT_LIBRARY: { @@ -965,7 +962,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( void cmGlobalNinjaGenerator::AppendTargetDepends( cmGeneratorTarget const* target, cmNinjaDeps& outputs, - cmNinjaTargetDepends depends) + const std::string& config, cmNinjaTargetDepends depends) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { // These depend only on other CMake-provided targets, e.g. "all". @@ -982,7 +979,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - this->AppendTargetOutputs(targetDep, outs, depends); + this->AppendTargetOutputs(targetDep, outs, config, depends); } std::sort(outs.begin(), outs.end()); cmAppend(outputs, outs); @@ -990,15 +987,17 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( } void cmGlobalNinjaGenerator::AppendTargetDependsClosure( - cmGeneratorTarget const* target, cmNinjaDeps& outputs) + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config) { cmNinjaOuts outs; - this->AppendTargetDependsClosure(target, outs, true); + this->AppendTargetDependsClosure(target, outs, config, true); cmAppend(outputs, outs); } void cmGlobalNinjaGenerator::AppendTargetDependsClosure( - cmGeneratorTarget const* target, cmNinjaOuts& outputs, bool omit_self) + cmGeneratorTarget const* target, cmNinjaOuts& outputs, + const std::string& config, bool omit_self) { // try to locate the target in the cache @@ -1019,7 +1018,7 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( } // Collect the dependent targets for _this_ target - this->AppendTargetDependsClosure(dep_target, this_outs, false); + this->AppendTargetDependsClosure(dep_target, this_outs, config, false); } find = this->TargetDependsClosures.emplace_hint(find, target, std::move(this_outs)); @@ -1032,17 +1031,18 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( // finally generate the outputs of the target itself, if applicable cmNinjaDeps outs; if (!omit_self) { - this->AppendTargetOutputs(target, outs); + this->AppendTargetOutputs(target, outs, config); } outputs.insert(outs.begin(), outs.end()); } void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias, - cmGeneratorTarget* target) + cmGeneratorTarget* target, + const std::string& config) { std::string buildAlias = this->NinjaOutputPath(alias); cmNinjaDeps outputs; - this->AppendTargetOutputs(target, outputs); + this->AppendTargetOutputs(target, outputs, config); // Mark the target's outputs as ambiguous to ensure that no other target uses // the output as an alias. for (std::string const& output : outputs) { @@ -1079,11 +1079,19 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) // Outputs build.Outputs[0] = ta.first; - // Explicit depdendencies - build.ExplicitDeps.clear(); - this->AppendTargetOutputs(ta.second, build.ExplicitDeps); - // Write - this->WriteBuild(os, build); + + std::vector configs; + ta.second->Makefile->GetConfigurations(configs); + if (configs.empty()) { + configs.emplace_back(); + } + for (auto const& config : configs) { + // Explicit dependencies + build.ExplicitDeps.clear(); + this->AppendTargetOutputs(ta.second, build.ExplicitDeps, config); + // Write + this->WriteBuild(os, build); + } } } @@ -1107,7 +1115,14 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) this->ConvertToNinjaPath(currentBinaryDir + "/all")); for (DirectoryTarget::Target const& t : dt.Targets) { if (!t.ExcludeFromAll) { - this->AppendTargetOutputs(t.GT, build.ExplicitDeps); + std::vector configs; + dt.LG->GetMakefile()->GetConfigurations(configs, true); + if (configs.empty()) { + configs.emplace_back(); + } + for (auto const& config : configs) { + this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config); + } } } for (DirectoryTarget::Dir const& d : dt.Children) { diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 41b41ac..a725018 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -287,18 +287,23 @@ public: void AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDepends( cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDependsClosure(cmGeneratorTarget const* target, - cmNinjaDeps& outputs); + cmNinjaDeps& outputs, + const std::string& config); void AppendTargetDependsClosure(cmGeneratorTarget const* target, - cmNinjaOuts& outputs, bool omit_self); + cmNinjaOuts& outputs, + const std::string& config, bool omit_self); int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; } - void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target); + void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target, + const std::string& config); void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index f86955d..025ef7e 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -17,13 +17,9 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, : cmLocalGenerator(gg, mf) , WorkingDirectory(std::move(wd)) { - // Store the configuration name that will be generated. - if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { - // Use the build type given by the user. - this->ConfigName = config; - } else { - // No configuration type given. - this->ConfigName.clear(); + this->Makefile->GetConfigurations(this->ConfigNames); + if (this->ConfigNames.empty()) { + this->ConfigNames.emplace_back(); } } diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index eaef6ab..378ca63 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -7,6 +7,7 @@ #include #include +#include #include "cmLocalGenerator.h" @@ -25,7 +26,10 @@ public: std::string wd); ~cmLocalCommonGenerator() override; - std::string const& GetConfigName() const { return this->ConfigName; } + std::vector const& GetConfigNames() const + { + return this->ConfigNames; + } std::string GetWorkingDirectory() const { return this->WorkingDirectory; } @@ -39,7 +43,7 @@ public: protected: std::string WorkingDirectory; - std::string ConfigName; + std::vector ConfigNames; friend class cmCommonTargetGenerator; }; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index ea500ac..96ee759 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -88,12 +88,16 @@ void cmLocalNinjaGenerator::Generate() } auto tg = cmNinjaTargetGenerator::New(target.get()); if (tg) { - tg->Generate(); + for (auto const& config : this->GetConfigNames()) { + tg->Generate(config); + } } } - this->WriteCustomCommandBuildStatements(); - this->AdditionalCleanFiles(); + for (auto const& config : this->GetConfigNames()) { + this->WriteCustomCommandBuildStatements(config); + this->AdditionalCleanFiles(config); + } } // TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it. @@ -175,7 +179,8 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); os << "# Project: " << this->GetProjectName() << std::endl - << "# Configuration: " << this->ConfigName << std::endl; + << "# Configurations: " << cmJoin(this->GetConfigNames(), ", ") + << std::endl; cmGlobalNinjaGenerator::WriteDivider(os); } @@ -263,25 +268,29 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) } void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target, - cmNinjaDeps& outputs) + cmNinjaDeps& outputs, + const std::string& config) { - this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs); + this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs, + config); } void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs, + const std::string& config, cmNinjaTargetDepends depends) { - this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, + this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, config, depends); } void cmLocalNinjaGenerator::AppendCustomCommandDeps( - cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps) + cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps, + const std::string& config) { for (std::string const& i : ccg.GetDepends()) { std::string dep; - if (this->GetRealDependency(i, this->GetConfigName(), dep)) { + if (this->GetRealDependency(i, config, dep)) { ninjaDeps.push_back( this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep)); } @@ -446,14 +455,15 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines( } void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( - cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps) + cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps, + const std::string& config) { cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator(); if (gg->SeenCustomCommand(cc)) { return; } - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this); + cmCustomCommandGenerator ccg(*cc, config, this); const std::vector& outputs = ccg.GetOutputs(); const std::vector& byproducts = ccg.GetByproducts(); @@ -484,7 +494,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( } cmNinjaDeps ninjaDeps; - this->AppendCustomCommandDeps(ccg, ninjaDeps); + this->AppendCustomCommandDeps(ccg, ninjaDeps, config); std::vector cmdLines; this->AppendCustomCommandLines(ccg, cmdLines); @@ -524,7 +534,8 @@ void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc, ins.first->second.insert(target); } -void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() +void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements( + const std::string& config) { for (cmCustomCommand const* customCommand : this->CustomCommands) { auto i = this->CustomCommandTargets.find(customCommand); @@ -542,15 +553,16 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() auto j = i->second.begin(); assert(j != i->second.end()); std::vector ccTargetDeps; - this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, - ccTargetDeps); + this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure( + *j, ccTargetDeps, config); std::sort(ccTargetDeps.begin(), ccTargetDeps.end()); ++j; for (; j != i->second.end(); ++j) { std::vector jDeps; std::vector depsIntersection; - this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps); + this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps, + config); std::sort(jDeps.begin(), jDeps.end()); std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(), jDeps.begin(), jDeps.end(), @@ -558,7 +570,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() ccTargetDeps = depsIntersection; } - this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps); + this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps, config); } } @@ -599,15 +611,13 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( return launcher; } -void cmLocalNinjaGenerator::AdditionalCleanFiles() +void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config) { if (const char* prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { std::vector cleanFiles; { - cmExpandList(cmGeneratorExpression::Evaluate( - prop_value, this, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), + cmExpandList(cmGeneratorExpression::Evaluate(prop_value, this, config), cleanFiles); } std::string const& binaryDir = this->GetCurrentBinaryDirectory(); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index f64534c..6f68a83 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -64,9 +64,10 @@ public: std::string const& customStep = std::string(), cmGeneratorTarget const* target = nullptr) const; - void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs); + void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs, + const std::string& config); void AppendTargetDepends( - cmGeneratorTarget* target, cmNinjaDeps& outputs, + cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AddCustomCommandTarget(cmCustomCommand const* cc, @@ -74,7 +75,8 @@ public: void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg, std::vector& cmdLines); void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg, - cmNinjaDeps& ninjaDeps); + cmNinjaDeps& ninjaDeps, + const std::string& config); protected: std::string ConvertToIncludeReference( @@ -94,9 +96,10 @@ private: void WritePools(std::ostream& os); void WriteCustomCommandBuildStatement(cmCustomCommand const* cc, - const cmNinjaDeps& orderOnlyDeps); + const cmNinjaDeps& orderOnlyDeps, + const std::string& config); - void WriteCustomCommandBuildStatements(); + void WriteCustomCommandBuildStatements(const std::string& config); std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg); @@ -104,7 +107,7 @@ private: std::string const& customStep, cmGeneratorTarget const* target) const; - void AdditionalCleanFiles(); + void AdditionalCleanFiles(const std::string& config); std::string HomeRelativeOutputPath; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 61cf9e9..2912604 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -3,6 +3,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include +#include #include #include #include @@ -106,6 +107,13 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3( cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() = default; +std::string cmLocalUnixMakefileGenerator3::GetConfigName() const +{ + auto const& configNames = this->GetConfigNames(); + assert(configNames.size() == 1); + return configNames.front(); +} + void cmLocalUnixMakefileGenerator3::Generate() { // Record whether some options are enabled to avoid checking many @@ -162,7 +170,7 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles( continue; } std::vector objectSources; - gt->GetObjectSources(objectSources, this->ConfigName); + gt->GetObjectSources(objectSources, this->GetConfigName()); // Compute full path to object file directory for this target. std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->GetTargetDirectory(gt.get()), '/'); @@ -401,7 +409,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( // Add a local name for the rule to relink the target before // installation. - if (target->NeedRelinkBeforeInstall(this->ConfigName)) { + if (target->NeedRelinkBeforeInstall(this->GetConfigName())) { makeTargetName = cmStrCat( this->GetRelativeTargetDirectory(target.get()), "/preinstall"); localName = cmStrCat(target->GetName(), "/preinstall"); @@ -858,7 +866,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepends( std::vector& depends, const std::vector& ccs) { for (cmCustomCommand const& cc : ccs) { - cmCustomCommandGenerator ccg(cc, this->ConfigName, this); + cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this); this->AppendCustomDepend(depends, ccg); } } @@ -869,7 +877,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepend( for (std::string const& d : ccg.GetDepends()) { // Lookup the real name of the dependency in case it is a CMake target. std::string dep; - if (this->GetRealDependency(d, this->ConfigName, dep)) { + if (this->GetRealDependency(d, this->GetConfigName(), dep)) { depends.push_back(std::move(dep)); } } @@ -880,7 +888,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommands( cmGeneratorTarget* target, std::string const& relative) { for (cmCustomCommand const& cc : ccs) { - cmCustomCommandGenerator ccg(cc, this->ConfigName, this); + cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this); this->AppendCustomCommand(commands, ccg, target, relative, true); } } @@ -1839,7 +1847,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( // Build a list of preprocessor definitions for the target. std::set defines; - this->GetTargetDefines(target, this->ConfigName, implicitLang.first, + this->GetTargetDefines(target, this->GetConfigName(), implicitLang.first, defines); if (!defines.empty()) { /* clang-format off */ @@ -1863,7 +1871,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( std::vector includes; this->GetIncludeDirectories(includes, target, implicitLang.first, - this->ConfigName); + this->GetConfigName()); std::string binaryDir = this->GetState()->GetBinaryDirectory(); if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) { std::string const& sourceDir = this->GetState()->GetSourceDirectory(); diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index f12ae8b..1629e63 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -33,6 +33,8 @@ public: cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf); ~cmLocalUnixMakefileGenerator3() override; + std::string GetConfigName() const; + void ComputeHomeRelativeOutputPath() override; /** diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 40265ff..ff8682c 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -35,10 +35,9 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( { this->CustomCommandDriver = OnDepends; this->TargetNames = - this->GeneratorTarget->GetExecutableNames(this->ConfigName); + this->GeneratorTarget->GetExecutableNames(this->GetConfigName()); - this->OSXBundleGenerator = - cm::make_unique(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } @@ -64,7 +63,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles() // write the link rules this->WriteExecutableRule(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteExecutableRule(true); } @@ -85,7 +84,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( { #ifndef CMAKE_BOOTSTRAP const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (!requiresDeviceLinking) { return; } @@ -141,10 +140,10 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( // Add language feature flags. this->LocalGenerator->AddLanguageFlagsForLinking( - flags, this->GeneratorTarget, linkLanguage, this->ConfigName); + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); - this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddArchitectureFlags( + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); // Add target-specific linker flags. this->GetTargetLinkFlags(linkFlags, linkLanguage); @@ -213,7 +212,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), output); - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); std::string targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB, cmOutputConverter::SHELL); @@ -287,12 +287,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Get the name of the executable to generate. cmGeneratorTarget::Names targetNames = - this->GeneratorTarget->GetExecutableNames(this->ConfigName); + this->GeneratorTarget->GetExecutableNames(this->GetConfigName()); // Construct the full path version of the names. - std::string outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + std::string outpath = + this->GeneratorTarget->GetDirectory(this->GetConfigName()); if (this->GeneratorTarget->IsAppBundleOnApple()) { - this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath); + this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath, + this->GetConfigName()); } outpath += '/'; std::string outpathImp; @@ -308,18 +310,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) cmSystemTools::MakeDirectory(outpath); if (!targetNames.ImportLibrary.empty()) { outpathImp = this->GeneratorTarget->GetDirectory( - this->ConfigName, cmStateEnums::ImportLibraryArtifact); + this->GetConfigName(), cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp); outpathImp += '/'; } } std::string compilePdbOutputPath = - this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(compilePdbOutputPath); std::string pdbOutputPath = - this->GeneratorTarget->GetPDBDirectory(this->ConfigName); + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(pdbOutputPath); pdbOutputPath += '/'; @@ -347,7 +349,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Get the language to use for linking this executable. std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); // Make sure we have a link language. if (linkLanguage.empty()) { @@ -380,7 +382,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add flags to create an executable. this->LocalGenerator->AddConfigVariableFlags( - linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->ConfigName); + linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GetConfigName()); if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) { this->LocalGenerator->AppendFlags( @@ -409,10 +411,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add language feature flags. this->LocalGenerator->AddLanguageFlagsForLinking( - flags, this->GeneratorTarget, linkLanguage, this->ConfigName); + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); - this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddArchitectureFlags( + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); // Add target-specific linker flags. this->GetTargetLinkFlags(linkFlags, linkLanguage); @@ -423,11 +425,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory())); - this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags, + this->GetConfigName()); } - this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget, - this->ConfigName, linkLanguage); + this->LocalGenerator->AppendIPOLinkerFlags( + linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); // Construct a list of files associated with this executable that // may need to be cleaned. @@ -451,7 +454,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS( - this->ConfigName, targetFullPathImport, implib)) { + this->GetConfigName(), targetFullPathImport, implib)) { exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } @@ -479,7 +482,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Construct the main link rule. std::vector real_link_commands; std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( - linkLanguage, this->ConfigName); + linkLanguage, this->GetConfigName()); std::string linkRule = this->GetLinkRule(linkRuleVar); std::vector commands1; cmExpandList(linkRule, real_link_commands); @@ -536,7 +539,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // maybe create .def file from list of objects this->GenDefFile(real_link_commands); - std::string manifests = this->GetManifests(); + std::string manifests = this->GetManifests(this->GetConfigName()); cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 54a6606..872521c 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -36,11 +36,10 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( this->CustomCommandDriver = OnDepends; if (this->GeneratorTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) { this->TargetNames = - this->GeneratorTarget->GetLibraryNames(this->ConfigName); + this->GeneratorTarget->GetLibraryNames(this->GetConfigName()); } - this->OSXBundleGenerator = - cm::make_unique(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } @@ -69,14 +68,16 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() break; case cmStateEnums::SHARED_LIBRARY: this->WriteSharedLibraryRules(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall( + this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteSharedLibraryRules(true); } break; case cmStateEnums::MODULE_LIBRARY: this->WriteModuleLibraryRules(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall( + this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteModuleLibraryRules(true); } @@ -126,21 +127,21 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules() void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, false); } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( - linkLanguage, this->ConfigName); + linkLanguage, this->GetConfigName()); std::string extraFlags; this->LocalGenerator->GetStaticLibraryFlags( - extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage, + extraFlags, cmSystemTools::UpperCase(this->GetConfigName()), linkLanguage, this->GeneratorTarget); this->WriteLibraryRules(linkRuleVar, extraFlags, false); } @@ -154,7 +155,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) if (!relink) { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); @@ -162,21 +163,22 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->GetConfigName()); std::unique_ptr linkLineComputer( this->CreateLinkLineComputer( this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory())); - this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, + this->GetConfigName()); if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed"); @@ -188,7 +190,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) { if (!relink) { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); @@ -196,21 +198,22 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_MODULE"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->GetConfigName()); std::unique_ptr linkLineComputer( this->CreateLinkLineComputer( this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory())); - this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, + this->GetConfigName()); this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } @@ -218,14 +221,14 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) { std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_MACOSX_FRAMEWORK"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->GetConfigName()); this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } @@ -331,7 +334,8 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), output); - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); std::string targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB, cmOutputConverter::SHELL); @@ -347,7 +351,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // Add language-specific flags. std::string langFlags; this->LocalGenerator->AddLanguageFlagsForLinking( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); vars.LanguageCompileFlags = langFlags.c_str(); @@ -420,7 +424,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Get the language to use for linking this library. std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); // Make sure we have a link language. if (linkLanguage.empty()) { @@ -439,8 +443,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Create set of linking flags. std::string linkFlags; this->LocalGenerator->AppendFlags(linkFlags, extraFlags); - this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget, - this->ConfigName, linkLanguage); + this->LocalGenerator->AppendIPOLinkerFlags( + linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); // Add OSX version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -450,20 +454,20 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } // Construct the name of the library. - this->GeneratorTarget->GetLibraryNames(this->ConfigName); + this->GeneratorTarget->GetLibraryNames(this->GetConfigName()); // Construct the full path version of the names. std::string outpath; std::string outpathImp; if (this->GeneratorTarget->IsFrameworkOnApple()) { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output, - outpath); + outpath, this->GetConfigName()); outpath += '/'; } else if (this->GeneratorTarget->IsCFBundleOnApple()) { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); - this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, - outpath); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); + this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, outpath, + this->GetConfigName()); outpath += '/'; } else if (relink) { outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), @@ -474,23 +478,23 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( outpathImp = outpath; } } else { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(outpath); outpath += '/'; if (!this->TargetNames.ImportLibrary.empty()) { outpathImp = this->GeneratorTarget->GetDirectory( - this->ConfigName, cmStateEnums::ImportLibraryArtifact); + this->GetConfigName(), cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp); outpathImp += '/'; } } std::string compilePdbOutputPath = - this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(compilePdbOutputPath); std::string pdbOutputPath = - this->GeneratorTarget->GetPDBDirectory(this->ConfigName); + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(pdbOutputPath); pdbOutputPath += "/"; @@ -586,7 +590,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS( - this->ConfigName, targetFullPathImport, implib)) { + this->GetConfigName(), targetFullPathImport, implib)) { libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } @@ -638,7 +642,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_CREATE"); arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arCreateVar, linkLanguage, this->ConfigName); + arCreateVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) { cmExpandList(rule, archiveCreateCommands); @@ -647,7 +651,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_APPEND"); arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arAppendVar, linkLanguage, this->ConfigName); + arAppendVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) { cmExpandList(rule, archiveAppendCommands); @@ -656,7 +660,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_FINISH"); arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arFinishVar, linkLanguage, this->ConfigName); + arFinishVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) { cmExpandList(rule, archiveFinishCommands); @@ -726,7 +730,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // maybe create .def file from list of objects this->GenDefFile(real_link_commands); - std::string manifests = this->GetManifests(); + std::string manifests = this->GetManifests(this->GetConfigName()); cmRulePlaceholderExpander::RuleVariables vars; vars.TargetPDB = targetOutPathPDB.c_str(); @@ -771,7 +775,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); - if (this->GeneratorTarget->HasSOName(this->ConfigName)) { + if (this->GeneratorTarget->HasSOName(this->GetConfigName())) { vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage); vars.TargetSOName = this->TargetNames.SharedObject.c_str(); } @@ -783,8 +787,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string install_name_dir; if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY) { // Get the install_name directory for the build tree. - install_name_dir = - this->GeneratorTarget->GetInstallNameDirForBuildTree(this->ConfigName); + install_name_dir = this->GeneratorTarget->GetInstallNameDirForBuildTree( + this->GetConfigName()); // Set the rule variable replacement value. if (install_name_dir.empty()) { @@ -800,10 +804,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Add language-specific flags. std::string langFlags; this->LocalGenerator->AddLanguageFlagsForLinking( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); this->LocalGenerator->AddArchitectureFlags( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); vars.LanguageCompileFlags = langFlags.c_str(); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 767f4e0..436503b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileTargetGenerator.h" +#include #include #include #include @@ -85,6 +86,13 @@ cmMakefileTargetGenerator* cmMakefileTargetGenerator::New( return result; } +std::string cmMakefileTargetGenerator::GetConfigName() +{ + auto const& configNames = this->LocalGenerator->GetConfigNames(); + assert(configNames.size() == 1); + return configNames.front(); +} + void cmMakefileTargetGenerator::GetTargetLinkFlags( std::string& flags, const std::string& linkLanguage) { @@ -92,17 +100,18 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags( flags, this->GeneratorTarget->GetSafeProperty("LINK_FLAGS")); std::string linkFlagsConfig = - cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->ConfigName)); + cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->GetConfigName())); this->LocalGenerator->AppendFlags( flags, this->GeneratorTarget->GetSafeProperty(linkFlagsConfig)); std::vector opts; - this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage); + this->GeneratorTarget->GetLinkOptions(opts, this->GetConfigName(), + linkLanguage); // LINK_OPTIONS are escaped. this->LocalGenerator->AppendCompileOptions(flags, opts); this->LocalGenerator->AppendPositionIndependentLinkerFlags( - flags, this->GeneratorTarget, this->ConfigName, linkLanguage); + flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); } void cmMakefileTargetGenerator::CreateRuleFile() @@ -154,10 +163,10 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() auto evaluatedFiles = [this](const char* prop_value) -> std::vector { std::vector files; - cmExpandList( - cmGeneratorExpression::Evaluate(prop_value, this->LocalGenerator, - this->ConfigName, this->GeneratorTarget), - files); + cmExpandList(cmGeneratorExpression::Evaluate( + prop_value, this->LocalGenerator, this->GetConfigName(), + this->GeneratorTarget), + files); return files; }; @@ -187,12 +196,13 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // First generate the object rule files. Save a list of all object // files for this target. std::vector customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName); + this->GeneratorTarget->GetCustomCommands(customCommands, + this->GetConfigName()); std::string currentBinDir = this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmSourceFile const* sf : customCommands) { - cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), this->ConfigName, - this->LocalGenerator); + cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), + this->GetConfigName(), this->LocalGenerator); this->GenerateCustomRuleFile(ccg); if (clean) { const std::vector& outputs = ccg.GetOutputs(); @@ -220,7 +230,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->GeneratorTarget->GetPostBuildCommands()); for (const auto& be : buildEventCommands) { - cmCustomCommandGenerator beg(be, this->ConfigName, this->LocalGenerator); + cmCustomCommandGenerator beg(be, this->GetConfigName(), + this->LocalGenerator); const std::vector& byproducts = beg.GetByproducts(); for (std::string const& byproduct : byproducts) { this->CleanFiles.insert( @@ -230,17 +241,19 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } std::vector headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName); + this->GeneratorTarget->GetHeaderSources(headerSources, + this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - headerSources, this->MacOSXContentGenerator); + headerSources, this->MacOSXContentGenerator, this->GetConfigName()); std::vector extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName); + this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - extraSources, this->MacOSXContentGenerator); + extraSources, this->MacOSXContentGenerator, this->GetConfigName()); const char* pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects, this->ConfigName); + this->GeneratorTarget->GetExternalObjects(externalObjects, + this->GetConfigName()); for (cmSourceFile const* sf : externalObjects) { auto const& objectFileName = sf->GetFullPath(); if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { @@ -248,7 +261,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } std::vector objectSources; - this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName); + this->GeneratorTarget->GetObjectSources(objectSources, + this->GetConfigName()); for (cmSourceFile const* sf : objectSources) { // Generate this object file's rule file. this->WriteObjectRuleFiles(*sf); @@ -334,9 +348,9 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() } for (std::string const& language : languages) { - std::string flags = this->GetFlags(language); - std::string defines = this->GetDefines(language); - std::string includes = this->GetIncludes(language); + std::string flags = this->GetFlags(language, this->GetConfigName()); + std::string defines = this->GetDefines(language, this->GetConfigName()); + std::string includes = this->GetIncludes(language, this->GetConfigName()); // Escape comment characters so they do not terminate assignment. cmSystemTools::ReplaceString(flags, "#", "\\#"); cmSystemTools::ReplaceString(defines, "#", "\\#"); @@ -348,7 +362,7 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() } void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( - cmSourceFile const& source, const char* pkgloc) + cmSourceFile const& source, const char* pkgloc, const std::string& config) { // Skip OS X content when not building a Framework or Bundle. if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { @@ -356,7 +370,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( } std::string macdir = - this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc); + this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc, + config); // Get the input file location. std::string const& input = source.GetFullPath(); @@ -451,7 +466,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // generate the depend scanning rule this->WriteObjectDependRules(source, depends); - std::string config = this->LocalGenerator->GetConfigName(); + std::string config = this->GetConfigName(); std::string configUpper = cmSystemTools::UpperCase(config); // Add precompile headers dependencies @@ -593,16 +608,17 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( { std::string targetFullPathReal; std::string targetFullPathPDB; - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE || this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { targetFullPathReal = this->GeneratorTarget->GetFullPath( - this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true); - targetFullPathPDB = - cmStrCat(this->GeneratorTarget->GetPDBDirectory(this->ConfigName), '/', - this->GeneratorTarget->GetPDBName(this->ConfigName)); + this->GetConfigName(), cmStateEnums::RuntimeBinaryArtifact, true); + targetFullPathPDB = cmStrCat( + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/', + this->GeneratorTarget->GetPDBName(this->GetConfigName())); } targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( @@ -708,13 +724,15 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string workingDirectory = cmSystemTools::CollapseFullPath( this->LocalGenerator->GetCurrentBinaryDirectory()); compileCommand.replace(compileCommand.find(langFlags), langFlags.size(), - this->GetFlags(lang)); + this->GetFlags(lang, this->GetConfigName())); std::string langDefines = std::string("$(") + lang + "_DEFINES)"; compileCommand.replace(compileCommand.find(langDefines), - langDefines.size(), this->GetDefines(lang)); + langDefines.size(), + this->GetDefines(lang, this->GetConfigName())); std::string langIncludes = std::string("$(") + lang + "_INCLUDES)"; compileCommand.replace(compileCommand.find(langIncludes), - langIncludes.size(), this->GetIncludes(lang)); + langIncludes.size(), + this->GetIncludes(lang, this->GetConfigName())); const char* eliminate[] = { this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"), @@ -1068,7 +1086,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() << "# Targets to which this target links.\n" << "set(CMAKE_TARGET_LINKED_INFO_FILES\n"; /* clang-format on */ - std::vector dirs = this->GetLinkedTargetDirectories(); + std::vector dirs = + this->GetLinkedTargetDirectories(this->GetConfigName()); for (std::string const& d : dirs) { *this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n"; } @@ -1171,7 +1190,7 @@ void cmMakefileTargetGenerator::DriveCustomCommands( sources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (cmSourceFile* source : sources) { if (cmCustomCommand* cc = source->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->ConfigName, + cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->LocalGenerator); cmAppend(depends, ccg.GetOutputs()); } @@ -1429,7 +1448,7 @@ void cmMakefileTargetGenerator::AppendTargetDepends( } // Loop over all library dependencies. - const std::string& cfg = this->LocalGenerator->GetConfigName(); + const std::string& cfg = this->GetConfigName(); if (cmComputeLinkInformation* cli = this->GeneratorTarget->GetLinkInformation(cfg)) { cmAppend(depends, cli->GetDepends()); @@ -1474,13 +1493,13 @@ void cmMakefileTargetGenerator::AppendLinkDepends( // Add a dependency on user-specified manifest files, if any. std::vector manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, this->GetConfigName()); for (cmSourceFile const* manifest_src : manifest_srcs) { depends.push_back(manifest_src->GetFullPath()); } // Add user-specified dependencies. - this->GeneratorTarget->GetLinkDepends(depends, this->ConfigName, + this->GeneratorTarget->GetLinkDepends(depends, this->GetConfigName(), linkLanguage); } @@ -1488,10 +1507,11 @@ std::string cmMakefileTargetGenerator::GetLinkRule( const std::string& linkRuleVar) { std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar); - if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) { - std::string ruleVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_GNUtoMS_RULE"); + if (this->GeneratorTarget->HasImplibGNUtoMS(this->GetConfigName())) { + std::string ruleVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_GNUtoMS_RULE"); if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { linkRule += rule; } @@ -1630,7 +1650,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs( std::string frameworkPath; std::string linkPath; cmComputeLinkInformation* pcli = - this->GeneratorTarget->GetLinkInformation(this->ConfigName); + this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); linkLibs = frameworkPath + linkPath + linkLibs; @@ -1638,9 +1658,10 @@ void cmMakefileTargetGenerator::CreateLinkLibs( if (useResponseFile && linkLibs.find_first_not_of(' ') != std::string::npos) { // Lookup the response file reference flag. - std::string responseFlagVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_RESPONSE_FILE_LINK_FLAG"); + std::string responseFlagVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_RESPONSE_FILE_LINK_FLAG"); const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); if (!responseFlag) { responseFlag = "@"; @@ -1675,9 +1696,10 @@ void cmMakefileTargetGenerator::CreateObjectLists( this->WriteObjectsStrings(object_strings, responseFileLimit); // Lookup the response file reference flag. - std::string responseFlagVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_RESPONSE_FILE_LINK_FLAG"); + std::string responseFlagVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_RESPONSE_FILE_LINK_FLAG"); const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); if (!responseFlag) { responseFlag = "@"; @@ -1716,7 +1738,8 @@ void cmMakefileTargetGenerator::CreateObjectLists( } void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, - const std::string& lang) + const std::string& lang, + const std::string& /*config*/) { std::string responseVar = cmStrCat("CMAKE_", lang, "_USE_RESPONSE_FILE_FOR_INCLUDES"); @@ -1724,11 +1747,11 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, std::vector includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - lang, this->ConfigName); + lang, this->GetConfigName()); std::string includeFlags = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, lang, false, useResponseFile, - this->ConfigName); + this->GetConfigName()); if (includeFlags.empty()) { return; } diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 7b9c7a5..710ef89 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -52,6 +52,8 @@ public: cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; } + std::string GetConfigName(); + protected: void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage); @@ -81,7 +83,8 @@ protected: { } - void operator()(cmSourceFile const& source, const char* pkgloc) override; + void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) override; private: cmMakefileTargetGenerator* Generator; @@ -163,7 +166,8 @@ protected: /** Add commands for generate def files */ void GenDefFile(std::vector& real_link_commands); - void AddIncludeFlags(std::string& flags, const std::string& lang) override; + void AddIncludeFlags(std::string& flags, const std::string& lang, + const std::string& config) override; virtual void CloseFileStreams(); cmLocalUnixMakefileGenerator3* LocalGenerator; diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 1625e4f..6c18e48 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -22,8 +22,7 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator( : cmMakefileTargetGenerator(target) { this->CustomCommandDriver = OnUtility; - this->OSXBundleGenerator = - cm::make_unique(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 72bef21..5601a33 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -41,33 +41,25 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( cmGeneratorTarget* target) : cmNinjaTargetGenerator(target) - , TargetLinkLanguage("") { - this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName()); - if (target->GetType() == cmStateEnums::EXECUTABLE) { - this->TargetNames = this->GetGeneratorTarget()->GetExecutableNames( - GetLocalGenerator()->GetConfigName()); - } else { - this->TargetNames = this->GetGeneratorTarget()->GetLibraryNames( - GetLocalGenerator()->GetConfigName()); - } - if (target->GetType() != cmStateEnums::OBJECT_LIBRARY) { // on Windows the output dir is already needed at compile time // ensure the directory exists (OutDir test) - EnsureDirectoryExists(target->GetDirectory(this->GetConfigName())); + for (auto const& config : this->GetConfigNames()) { + EnsureDirectoryExists(target->GetDirectory(config)); + } } - this->OSXBundleGenerator = - cm::make_unique(target, this->GetConfigName()); + this->OSXBundleGenerator = cm::make_unique(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default; -void cmNinjaNormalTargetGenerator::Generate() +void cmNinjaNormalTargetGenerator::Generate(const std::string& config) { - if (this->TargetLinkLanguage.empty()) { + std::string lang = this->GeneratorTarget->GetLinkerLanguage(config); + if (this->TargetLinkLanguage(config).empty()) { cmSystemTools::Error("CMake can not determine linker language for " "target: " + this->GetGeneratorTarget()->GetName()); @@ -75,25 +67,26 @@ void cmNinjaNormalTargetGenerator::Generate() } // Write the rules for each language. - this->WriteLanguagesRules(); + this->WriteLanguagesRules(config); // Write the build statements - this->WriteObjectBuildStatements(); + this->WriteObjectBuildStatements(config); if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) { - this->WriteObjectLibStatement(); + this->WriteObjectLibStatement(config); } else { // If this target has cuda language link inputs, and we need to do // device linking - this->WriteDeviceLinkStatement(); - this->WriteLinkStatement(); + this->WriteDeviceLinkStatement(config); + this->WriteLinkStatement(config); } // Find ADDITIONAL_CLEAN_FILES - this->AdditionalCleanFiles(); + this->AdditionalCleanFiles(config); } -void cmNinjaNormalTargetGenerator::WriteLanguagesRules() +void cmNinjaNormalTargetGenerator::WriteLanguagesRules( + const std::string& config) { #ifdef NINJA_GEN_VERBOSE_FILES cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream()); @@ -106,8 +99,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() // Write rules for languages compiled in this target. std::set languages; std::vector sourceFiles; - this->GetGeneratorTarget()->GetObjectSources( - sourceFiles, this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE")); + this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config); for (cmSourceFile const* sf : sourceFiles) { std::string const lang = sf->GetLanguage(); if (!lang.empty()) { @@ -139,18 +131,20 @@ const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const } } -std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule() const +std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule( + const std::string& config) const { - return this->TargetLinkLanguage + "_" + + return this->TargetLinkLanguage(config) + "_" + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + "_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName( this->GetGeneratorTarget()->GetName()); } -std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule() const +std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule( + const std::string& config) const { - return this->TargetLinkLanguage + "_" + + return this->TargetLinkLanguage(config) + "_" + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + "_DEVICE_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName( @@ -165,9 +159,10 @@ struct cmNinjaRemoveNoOpCommands } }; -void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) +void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule( + bool useResponseFile, const std::string& config) { - cmNinjaRule rule(this->LanguageLinkerDeviceRule()); + cmNinjaRule rule(this->LanguageLinkerDeviceRule(config)); if (!this->GetGlobalGenerator()->HasRule(rule.Name)) { cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); @@ -241,30 +236,34 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); // Write the linker rule with response file if needed. - rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), '.'); - rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), " $TARGET_FILE"); + rule.Comment = + cmStrCat("Rule for linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), '.'); + rule.Description = + cmStrCat("Linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), " $TARGET_FILE"); rule.Restat = "$RESTAT"; this->GetGlobalGenerator()->AddRule(rule); } } -void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) +void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, + const std::string& config) { cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType(); - std::string linkRuleName = this->LanguageLinkerRule(); + std::string linkRuleName = this->LanguageLinkerRule(config); if (!this->GetGlobalGenerator()->HasRule(linkRuleName)) { cmNinjaRule rule(std::move(linkRuleName)); cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(targetType); - vars.Language = this->TargetLinkLanguage.c_str(); + std::string lang = this->TargetLinkLanguage(config); + vars.Language = config.c_str(); - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { vars.SwiftLibraryName = "$SWIFT_LIBRARY_NAME"; vars.SwiftModule = "$SWIFT_MODULE"; vars.SwiftModuleName = "$SWIFT_MODULE_NAME"; @@ -278,7 +277,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) std::string responseFlag; - std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage); + std::string cmakeVarLang = + cmStrCat("CMAKE_", this->TargetLinkLanguage(config)); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; @@ -286,7 +286,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) if (flag) { responseFlag = flag; - } else if (this->TargetLinkLanguage != "CUDA") { + } else if (this->TargetLinkLanguage(config) != "CUDA") { responseFlag = "@"; } @@ -304,7 +304,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) rule.RspContent = "$in_newline"; } rule.RspContent += " $LINK_PATH $LINK_LIBRARIES"; - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { vars.SwiftSources = responseFlag.c_str(); } else { vars.Objects = responseFlag.c_str(); @@ -359,7 +359,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) this->GetLocalGenerator()->CreateRulePlaceholderExpander()); // Rule for linking library/executable. - std::vector linkCmds = this->ComputeLinkCmd(); + std::vector linkCmds = this->ComputeLinkCmd(config); for (std::string& linkCmd : linkCmds) { linkCmd = cmStrCat(launcher, linkCmd); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), @@ -374,15 +374,18 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); // Write the linker rule with response file if needed. - rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), '.'); - rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), " $TARGET_FILE"); + rule.Comment = + cmStrCat("Rule for linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), '.'); + rule.Description = + cmStrCat("Linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), " $TARGET_FILE"); rule.Restat = "$RESTAT"; this->GetGlobalGenerator()->AddRule(rule); } - if (this->TargetNames.Output != this->TargetNames.Real && + auto const tgtNames = this->TargetNames(config); + if (tgtNames.Output != tgtNames.Real && !this->GetGeneratorTarget()->IsFrameworkOnApple()) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -441,7 +444,8 @@ std::vector cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd() return linkCmds; } -std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() +std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd( + const std::string& config) { std::vector linkCmds; cmMakefile* mf = this->GetMakefile(); @@ -450,14 +454,14 @@ std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() // this occurs when things like IPO is enabled, and we need to use the // CMAKE__CREATE_STATIC_LIBRARY_IPO define instead. std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable( - this->TargetLinkLanguage, this->GetConfigName()); + this->TargetLinkLanguage(config), config); const char* linkCmd = mf->GetDefinition(linkCmdVar); if (linkCmd) { std::string linkCmdStr = linkCmd; - if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) { - std::string ruleVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_GNUtoMS_RULE"); + if (this->GetGeneratorTarget()->HasImplibGNUtoMS(config)) { + std::string ruleVar = + cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(config), + "_GNUtoMS_RULE"); if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { linkCmdStr += rule; } @@ -469,9 +473,8 @@ std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), " -E __run_co_compile --lwyu="); cmGeneratorTarget& gt = *this->GetGeneratorTarget(); - const std::string cfgName = this->GetConfigName(); std::string targetOutputReal = this->ConvertToNinjaPath( - gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, + gt.GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, /*realname=*/true)); cmakeCommand += targetOutputReal; linkCmds.push_back(std::move(cmakeCommand)); @@ -490,21 +493,21 @@ std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() } // TODO: Use ARCHIVE_APPEND for archives over a certain size. { - std::string linkCmdVar = - cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_CREATE"); + std::string linkCmdVar = cmStrCat( + "CMAKE_", this->TargetLinkLanguage(config), "_ARCHIVE_CREATE"); linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); + linkCmdVar, this->TargetLinkLanguage(config), config); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmExpandList(linkCmd, linkCmds); } { - std::string linkCmdVar = - cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_FINISH"); + std::string linkCmdVar = cmStrCat( + "CMAKE_", this->TargetLinkLanguage(config), "_ARCHIVE_FINISH"); linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); + linkCmdVar, this->TargetLinkLanguage(config), config); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmExpandList(linkCmd, linkCmds); @@ -535,7 +538,8 @@ std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() return std::vector(); } -void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() +void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( + const std::string& config) { cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); if (!globalGen->GetLanguageEnabled("CUDA")) { @@ -545,7 +549,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() cmGeneratorTarget* genTarget = this->GetGeneratorTarget(); bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->GetLocalGenerator(), this->ConfigName); + *this->GeneratorTarget, *this->GetLocalGenerator(), config); if (!requiresDeviceLinking) { return; } @@ -558,12 +562,11 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() std::string const& objExt = this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); - std::string const cfgName = this->GetConfigName(); std::string const targetOutputReal = ConvertToNinjaPath( genTarget->ObjectDirectory + "cmake_device_link" + objExt); std::string const targetOutputImplib = ConvertToNinjaPath( - genTarget->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); + genTarget->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); this->DeviceLinkObject = targetOutputReal; @@ -575,7 +578,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() << " target " << this->GetTargetName() << "\n\n"; // Compute the comment. - cmNinjaBuild build(this->LanguageLinkerDeviceRule()); + cmNinjaBuild build(this->LanguageLinkerDeviceRule(config)); build.Comment = cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal); @@ -585,13 +588,14 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() build.Outputs.push_back(targetOutputReal); // Compute specific libraries to link with. build.ExplicitDeps = this->GetObjects(); - build.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); + build.ImplicitDeps = + this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); std::string frameworkPath; std::string linkPath; - std::string createRule = genTarget->GetCreateRuleVariable( - this->TargetLinkLanguage, this->GetConfigName()); + std::string createRule = + genTarget->GetCreateRuleVariable(this->TargetLinkLanguage(config), config); const bool useWatcomQuote = this->GetMakefile()->IsOn(createRule + "_USE_WATCOM_QUOTE"); cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator(); @@ -607,15 +611,15 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() linkLineComputer->SetUseWatcomQuote(useWatcomQuote); localGen.GetTargetFlags( - linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"], - vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget); + linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"], + vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget); this->addPoolNinjaVariable("JOB_POOL_LINK", genTarget, vars); vars["LINK_FLAGS"] = cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); - vars["MANIFESTS"] = this->GetManifests(); + vars["MANIFESTS"] = this->GetManifests(config); vars["LINK_PATH"] = frameworkPath + linkPath; @@ -624,24 +628,25 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // code between the Makefile executable and library generators. if (targetType == cmStateEnums::EXECUTABLE) { std::string t = vars["FLAGS"]; - localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, config); vars["FLAGS"] = t; } else { std::string t = vars["ARCH_FLAGS"]; - localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, config); vars["ARCH_FLAGS"] = t; t.clear(); localGen.AddLanguageFlagsForLinking(t, genTarget, cudaLinkLanguage, - cfgName); + config); vars["LANGUAGE_COMPILE_FLAGS"] = t; } - if (genTarget->HasSOName(cfgName)) { + auto const tgtNames = this->TargetNames(config); + if (genTarget->HasSOName(config)) { vars["SONAME_FLAG"] = - this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage); - vars["SONAME"] = this->TargetNames.SharedObject; + this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage(config)); + vars["SONAME"] = tgtNames.SharedObject; if (targetType == cmStateEnums::SHARED_LIBRARY) { std::string install_dir = - this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName); + this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(config); if (!install_dir.empty()) { vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat( install_dir, cmOutputConverter::SHELL); @@ -649,7 +654,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() } } - if (!this->TargetNames.ImportLibrary.empty()) { + if (!tgtNames.ImportLibrary.empty()) { const std::string impLibPath = localGen.ConvertToOutputFormat( targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; @@ -661,7 +666,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL); EnsureDirectoryExists(objPath); - this->SetMsvcTargetPdbVariable(vars); + this->SetMsvcTargetPdbVariable(vars, config); if (globalGen->IsGCCOnWindows()) { // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) @@ -675,55 +680,56 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // do not check if the user has explicitly forced a response file. int const commandLineLengthLimit = static_cast(cmSystemTools::CalculateCommandLineLengthLimit()) - - globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule()); + globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule(config)); build.RspFile = this->ConvertToNinjaPath(std::string("CMakeFiles/") + genTarget->GetName() + ".rsp"); // Gather order-only dependencies. this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(), - build.OrderOnlyDeps); + build.OrderOnlyDeps, config); // Write the build statement for this target. bool usedResponseFile = false; globalGen->WriteBuild(this->GetBuildFileStream(), build, commandLineLengthLimit, &usedResponseFile); - this->WriteDeviceLinkRule(usedResponseFile); + this->WriteDeviceLinkRule(usedResponseFile, config); } -void cmNinjaNormalTargetGenerator::WriteLinkStatement() +void cmNinjaNormalTargetGenerator::WriteLinkStatement( + const std::string& config) { cmMakefile* mf = this->GetMakefile(); cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); cmGeneratorTarget* gt = this->GetGeneratorTarget(); - const std::string cfgName = this->GetConfigName(); - std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(cfgName)); + std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(config)); std::string targetOutputReal = ConvertToNinjaPath( - gt->GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, + gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, /*realname=*/true)); std::string targetOutputImplib = ConvertToNinjaPath( - gt->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); + gt->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); + auto const tgtNames = this->TargetNames(config); if (gt->IsAppBundleOnApple()) { // Create the app bundle - std::string outpath = gt->GetDirectory(cfgName); - this->OSXBundleGenerator->CreateAppBundle(this->TargetNames.Output, - outpath); + std::string outpath = gt->GetDirectory(config); + this->OSXBundleGenerator->CreateAppBundle(tgtNames.Output, outpath, + config); // Calculate the output path - targetOutput = cmStrCat(outpath, '/', this->TargetNames.Output); + targetOutput = cmStrCat(outpath, '/', tgtNames.Output); targetOutput = this->ConvertToNinjaPath(targetOutput); - targetOutputReal = cmStrCat(outpath, '/', this->TargetNames.Real); + targetOutputReal = cmStrCat(outpath, '/', tgtNames.Real); targetOutputReal = this->ConvertToNinjaPath(targetOutputReal); } else if (gt->IsFrameworkOnApple()) { // Create the library framework. - this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output, - gt->GetDirectory(cfgName)); + this->OSXBundleGenerator->CreateFramework( + tgtNames.Output, gt->GetDirectory(config), config); } else if (gt->IsCFBundleOnApple()) { // Create the core foundation bundle. - this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, - gt->GetDirectory(cfgName)); + this->OSXBundleGenerator->CreateCFBundle(tgtNames.Output, + gt->GetDirectory(config), config); } // Write comments. @@ -733,7 +739,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() << "# Link build statements for " << cmState::GetTargetTypeName(targetType) << " target " << this->GetTargetName() << "\n\n"; - cmNinjaBuild linkBuild(this->LanguageLinkerRule()); + cmNinjaBuild linkBuild(this->LanguageLinkerRule(config)); cmNinjaVars& vars = linkBuild.Variables; // Compute the comment. @@ -743,10 +749,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Compute outputs. linkBuild.Outputs.push_back(targetOutputReal); - if (this->TargetLinkLanguage == "Swift") { - vars["SWIFT_LIBRARY_NAME"] = [this]() -> std::string { + if (this->TargetLinkLanguage(config) == "Swift") { + vars["SWIFT_LIBRARY_NAME"] = [this, config]() -> std::string { cmGeneratorTarget::Names targetNames = - this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName()); + this->GetGeneratorTarget()->GetLibraryNames(config); return targetNames.Base; }(); @@ -782,12 +788,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() "/output-file-map.json"), cmOutputConverter::SHELL); - vars["SWIFT_SOURCES"] = [this]() -> std::string { + vars["SWIFT_SOURCES"] = [this, config]() -> std::string { std::vector sources; std::stringstream oss; - this->GetGeneratorTarget()->GetObjectSources(sources, - this->GetConfigName()); + this->GetGeneratorTarget()->GetObjectSources(sources, config); cmLocalGenerator const* LocalGen = this->GetLocalGenerator(); for (const auto& source : sources) { oss << " " @@ -801,15 +806,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Since we do not perform object builds, compute the // defines/flags/includes here so that they can be passed along // appropriately. - vars["DEFINES"] = this->GetDefines("Swift"); - vars["FLAGS"] = this->GetFlags("Swift"); - vars["INCLUDES"] = this->GetIncludes("Swift"); + vars["DEFINES"] = this->GetDefines("Swift", config); + vars["FLAGS"] = this->GetFlags("Swift", config); + vars["INCLUDES"] = this->GetIncludes("Swift", config); } // Compute specific libraries to link with. - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { std::vector sources; - gt->GetObjectSources(sources, this->GetConfigName()); + gt->GetObjectSources(sources, config); for (const auto& source : sources) { linkBuild.Outputs.push_back( this->ConvertToNinjaPath(this->GetObjectFilePath(source))); @@ -821,7 +826,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } else { linkBuild.ExplicitDeps = this->GetObjects(); } - linkBuild.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); + linkBuild.ImplicitDeps = + this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); if (!this->DeviceLinkObject.empty()) { linkBuild.ExplicitDeps.push_back(this->DeviceLinkObject); @@ -831,7 +837,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string linkPath; std::string createRule = - gt->GetCreateRuleVariable(this->TargetLinkLanguage, this->GetConfigName()); + gt->GetCreateRuleVariable(this->TargetLinkLanguage(config), config); bool useWatcomQuote = mf->IsOn(createRule + "_USE_WATCOM_QUOTE"); cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator(); @@ -844,26 +850,28 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() this->GetLocalGenerator()->GetStateSnapshot().GetDirectory())); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); - localGen.GetTargetFlags(linkLineComputer.get(), this->GetConfigName(), + localGen.GetTargetFlags(linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, gt); // Add OS X version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { - this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage, - "COMPATIBILITY", true); - this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage, - "CURRENT", false); + this->AppendOSXVerFlag(vars["LINK_FLAGS"], + this->TargetLinkLanguage(config), "COMPATIBILITY", + true); + this->AppendOSXVerFlag(vars["LINK_FLAGS"], + this->TargetLinkLanguage(config), "CURRENT", false); } this->addPoolNinjaVariable("JOB_POOL_LINK", gt, vars); - this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]); + this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], + config); vars["LINK_FLAGS"] = cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); - vars["MANIFESTS"] = this->GetManifests(); + vars["MANIFESTS"] = this->GetManifests(config); vars["LINK_PATH"] = frameworkPath + linkPath; std::string lwyuFlags; @@ -876,23 +884,26 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // code between the Makefile executable and library generators. if (targetType == cmStateEnums::EXECUTABLE) { std::string t = vars["FLAGS"]; - localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config), + config); t += lwyuFlags; vars["FLAGS"] = t; } else { std::string t = vars["ARCH_FLAGS"]; - localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config), + config); vars["ARCH_FLAGS"] = t; t.clear(); t += lwyuFlags; - localGen.AddLanguageFlagsForLinking(t, gt, TargetLinkLanguage, cfgName); + localGen.AddLanguageFlagsForLinking( + t, gt, this->TargetLinkLanguage(config), config); vars["LANGUAGE_COMPILE_FLAGS"] = t; } - if (gt->HasSOName(cfgName)) { - vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage); - vars["SONAME"] = this->TargetNames.SharedObject; + if (gt->HasSOName(config)) { + vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage(config)); + vars["SONAME"] = tgtNames.SharedObject; if (targetType == cmStateEnums::SHARED_LIBRARY) { - std::string install_dir = gt->GetInstallNameDirForBuildTree(cfgName); + std::string install_dir = gt->GetInstallNameDirForBuildTree(config); if (!install_dir.empty()) { vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat( install_dir, cmOutputConverter::SHELL); @@ -902,17 +913,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() cmNinjaDeps byproducts; - if (!this->TargetNames.ImportLibrary.empty()) { + if (!tgtNames.ImportLibrary.empty()) { const std::string impLibPath = localGen.ConvertToOutputFormat( targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; EnsureParentDirectoryExists(impLibPath); - if (gt->HasImportLibrary(cfgName)) { + if (gt->HasImportLibrary(config)) { byproducts.push_back(targetOutputImplib); } } - if (!this->SetMsvcTargetPdbVariable(vars)) { + if (!this->SetMsvcTargetPdbVariable(vars, config)) { // It is common to place debug symbols at a specific place, // so we need a plain target name in the rule available. std::string prefix; @@ -953,7 +964,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() for (unsigned i = 0; i != 3; ++i) { for (cmCustomCommand const& cc : *cmdLists[i]) { - cmCustomCommandGenerator ccg(cc, cfgName, this->GetLocalGenerator()); + cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator()); localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); std::vector const& ccByproducts = ccg.GetByproducts(); std::transform(ccByproducts.begin(), ccByproducts.end(), @@ -963,7 +974,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // maybe create .def file from list of objects cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - gt->GetModuleDefinitionInfo(this->GetConfigName()); + gt->GetModuleDefinitionInfo(config); if (mdi && mdi->DefFileGenerated) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -1024,7 +1035,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() symlinkVars["POST_BUILD"] = postBuildCmdLine; } - std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage); + std::string cmakeVarLang = + cmStrCat("CMAKE_", this->TargetLinkLanguage(config)); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; @@ -1032,8 +1044,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar); bool const lang_supports_response = - !(this->TargetLinkLanguage == "RC" || - (this->TargetLinkLanguage == "CUDA" && !flag)); + !(this->TargetLinkLanguage(config) == "RC" || + (this->TargetLinkLanguage(config) == "CUDA" && !flag)); int commandLineLengthLimit = -1; if (!lang_supports_response || !this->ForceResponseFile()) { commandLineLengthLimit = @@ -1045,18 +1057,19 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() gt->GetName() + ".rsp"); // Gather order-only dependencies. - this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps); + this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps, + config); // Add order-only dependencies on versioning symlinks of shared libs we link. if (!this->GeneratorTarget->IsDLLPlatform()) { if (cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->GetConfigName())) { + this->GeneratorTarget->GetLinkInformation(config)) { for (auto const& item : cli->GetItems()) { if (item.Target && item.Target->GetType() == cmStateEnums::SHARED_LIBRARY && !item.Target->IsFrameworkOnApple()) { - std::string const& lib = this->ConvertToNinjaPath( - item.Target->GetFullPath(this->GetConfigName())); + std::string const& lib = + this->ConvertToNinjaPath(item.Target->GetFullPath(config)); if (std::find(linkBuild.ImplicitDeps.begin(), linkBuild.ImplicitDeps.end(), lib) == linkBuild.ImplicitDeps.end()) { @@ -1079,7 +1092,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() bool usedResponseFile = false; globalGen->WriteBuild(this->GetBuildFileStream(), linkBuild, commandLineLengthLimit, &usedResponseFile); - this->WriteLinkRule(usedResponseFile); + this->WriteLinkRule(usedResponseFile, config); if (symlinkNeeded) { if (targetType == cmStateEnums::EXECUTABLE) { @@ -1094,7 +1107,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() build.Comment = "Create library symlink " + targetOutput; std::string const soName = this->ConvertToNinjaPath( - this->GetTargetFilePath(this->TargetNames.SharedObject)); + this->GetTargetFilePath(tgtNames.SharedObject, config)); // If one link has to be created. if (targetOutputReal == soName || targetOutput == soName) { symlinkVars["SONAME"] = @@ -1113,23 +1126,39 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } // Add aliases for the file name and the target name. - globalGen->AddTargetAlias(this->TargetNames.Output, gt); - globalGen->AddTargetAlias(this->GetTargetName(), gt); + globalGen->AddTargetAlias(tgtNames.Output, gt, config); + globalGen->AddTargetAlias(this->GetTargetName(), gt, config); } -void cmNinjaNormalTargetGenerator::WriteObjectLibStatement() +void cmNinjaNormalTargetGenerator::WriteObjectLibStatement( + const std::string& config) { // Write a phony output that depends on all object files. { cmNinjaBuild build("phony"); build.Comment = "Object library " + this->GetTargetName(); this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(), - build.Outputs); + build.Outputs, config); build.ExplicitDeps = this->GetObjects(); this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); } // Add aliases for the target name. - this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), - this->GetGeneratorTarget()); + this->GetGlobalGenerator()->AddTargetAlias( + this->GetTargetName(), this->GetGeneratorTarget(), config); +} + +cmGeneratorTarget::Names cmNinjaNormalTargetGenerator::TargetNames( + const std::string& config) const +{ + if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { + return this->GeneratorTarget->GetExecutableNames(config); + } + return this->GeneratorTarget->GetLibraryNames(config); +} + +std::string cmNinjaNormalTargetGenerator::TargetLinkLanguage( + const std::string& config) const +{ + return this->GeneratorTarget->GetLinkerLanguage(config); } diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index ebc1268..a3e7e5b 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -17,30 +17,30 @@ public: cmNinjaNormalTargetGenerator(cmGeneratorTarget* target); ~cmNinjaNormalTargetGenerator() override; - void Generate() override; + void Generate(const std::string& config) override; private: - std::string LanguageLinkerRule() const; - std::string LanguageLinkerDeviceRule() const; + std::string LanguageLinkerRule(const std::string& config) const; + std::string LanguageLinkerDeviceRule(const std::string& config) const; const char* GetVisibleTypeName() const; - void WriteLanguagesRules(); + void WriteLanguagesRules(const std::string& config); - void WriteLinkRule(bool useResponseFile); - void WriteDeviceLinkRule(bool useResponseFile); + void WriteLinkRule(bool useResponseFile, const std::string& config); + void WriteDeviceLinkRule(bool useResponseFile, const std::string& config); - void WriteLinkStatement(); - void WriteDeviceLinkStatement(); + void WriteLinkStatement(const std::string& config); + void WriteDeviceLinkStatement(const std::string& config); - void WriteObjectLibStatement(); + void WriteObjectLibStatement(const std::string& config); - std::vector ComputeLinkCmd(); + std::vector ComputeLinkCmd(const std::string& config); std::vector ComputeDeviceLinkCmd(); private: // Target name info. - cmGeneratorTarget::Names TargetNames; - std::string TargetLinkLanguage; + cmGeneratorTarget::Names TargetNames(const std::string& config) const; + std::string TargetLinkLanguage(const std::string& config) const; std::string DeviceLinkObject; }; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 919a5db..0e44e2d 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -138,10 +138,10 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget() // void cmMakefileTargetGenerator::WriteTargetLanguageFlags() // Refactor it. std::string cmNinjaTargetGenerator::ComputeFlagsForObject( - cmSourceFile const* source, const std::string& language) + cmSourceFile const* source, const std::string& language, + const std::string& config) { - std::string flags = this->GetFlags(language); - const std::string configName = this->LocalGenerator->GetConfigName(); + std::string flags = this->GetFlags(language, config); // Add Fortran format flags. if (language == "Fortran") { @@ -150,7 +150,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add source file specific flags. cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, configName, this->GeneratorTarget, language); + this->LocalGenerator, config, this->GeneratorTarget, language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) { @@ -166,16 +166,16 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add precompile headers compile options. const std::string pchSource = - this->GeneratorTarget->GetPchSource(configName, language); + this->GeneratorTarget->GetPchSource(config, language); if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { std::string pchOptions; if (source->GetFullPath() == pchSource) { - pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions( - configName, language); + pchOptions = + this->GeneratorTarget->GetPchCreateCompileOptions(config, language); } else { pchOptions = - this->GeneratorTarget->GetPchUseCompileOptions(configName, language); + this->GeneratorTarget->GetPchUseCompileOptions(config, language); } this->LocalGenerator->AppendCompileOptions( @@ -186,16 +186,17 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( } void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, - std::string const& language) + std::string const& language, + const std::string& config) { std::vector includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - language, this->GetConfigName()); + language, config); // Add include directory flags. std::string includeFlags = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, language, language == "RC", // full include paths for RC needed by cmcldeps - false, this->GetConfigName()); + false, config); if (this->GetGlobalGenerator()->IsGCCOnWindows()) { std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/'); } @@ -232,10 +233,10 @@ bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const // TODO: Refactor with // void cmMakefileTargetGenerator::WriteTargetLanguageFlags(). std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, - const std::string& language) + const std::string& language, + const std::string& config) { std::set defines; - const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( this->LocalGenerator, config, this->GeneratorTarget, language); @@ -253,17 +254,17 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS)); } - std::string definesString = this->GetDefines(language); + std::string definesString = this->GetDefines(language, config); this->LocalGenerator->JoinDefines(defines, definesString, language); return definesString; } std::string cmNinjaTargetGenerator::ComputeIncludes( - cmSourceFile const* source, const std::string& language) + cmSourceFile const* source, const std::string& language, + const std::string& config) { std::vector includes; - const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( this->LocalGenerator, config, this->GeneratorTarget, language); @@ -277,13 +278,13 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( std::string includesString = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, language, true, false, config); this->LocalGenerator->AppendFlags(includesString, - this->GetIncludes(language)); + this->GetIncludes(language, config)); return includesString; } cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( - const std::string& linkLanguage) const + const std::string& linkLanguage, const std::string& config) const { // Static libraries never depend on other targets for linking. if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -292,7 +293,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( } cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); + this->GeneratorTarget->GetLinkInformation(config); if (!cli) { return cmNinjaDeps(); } @@ -303,8 +304,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( // Add a dependency on the link definitions file, if any. if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - this->GeneratorTarget->GetModuleDefinitionInfo( - this->GetConfigName())) { + this->GeneratorTarget->GetModuleDefinitionInfo(config)) { for (cmSourceFile const* src : mdi->Sources) { result.push_back(this->ConvertToNinjaPath(src->GetFullPath())); } @@ -312,15 +312,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( // Add a dependency on user-specified manifest files, if any. std::vector manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, config); for (cmSourceFile const* manifest_src : manifest_srcs) { result.push_back(this->ConvertToNinjaPath(manifest_src->GetFullPath())); } // Add user-specified dependencies. std::vector linkDeps; - this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName, - linkLanguage); + this->GeneratorTarget->GetLinkDepends(linkDeps, config, linkLanguage); std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result), MapToNinjaPath()); @@ -407,16 +406,17 @@ std::string cmNinjaTargetGenerator::GetTargetDependInfoPath( return path; } -std::string cmNinjaTargetGenerator::GetTargetOutputDir() const +std::string cmNinjaTargetGenerator::GetTargetOutputDir( + const std::string& config) const { - std::string dir = this->GeneratorTarget->GetDirectory(this->GetConfigName()); + std::string dir = this->GeneratorTarget->GetDirectory(config); return ConvertToNinjaPath(dir); } std::string cmNinjaTargetGenerator::GetTargetFilePath( - const std::string& name) const + const std::string& name, const std::string& config) const { - std::string path = this->GetTargetOutputDir(); + std::string path = this->GetTargetOutputDir(config); if (path.empty() || path == ".") { return name; } @@ -430,21 +430,21 @@ std::string cmNinjaTargetGenerator::GetTargetName() const return this->GeneratorTarget->GetName(); } -bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const +bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable( + cmNinjaVars& vars, const std::string& config) const { cmMakefile* mf = this->GetMakefile(); if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") || mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") || mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) { std::string pdbPath; - std::string compilePdbPath = this->ComputeTargetCompilePDB(); + std::string compilePdbPath = this->ComputeTargetCompilePDB(config); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE || this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { - pdbPath = cmStrCat( - this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/', - this->GeneratorTarget->GetPDBName(this->GetConfigName())); + pdbPath = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config), '/', + this->GeneratorTarget->GetPDBName(config)); } vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -787,7 +787,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetGlobalGenerator()->AddRule(rule); } -void cmNinjaTargetGenerator::WriteObjectBuildStatements() +void cmNinjaTargetGenerator::WriteObjectBuildStatements( + const std::string& config) { // Write comments. cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); @@ -798,7 +799,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() { std::vector customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName); + this->GeneratorTarget->GetCustomCommands(customCommands, config); for (cmSourceFile const* sf : customCommands) { cmCustomCommand const* cc = sf->GetCustomCommand(); this->GetLocalGenerator()->AddCustomCommandTarget( @@ -810,23 +811,22 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() } { std::vector headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName); + this->GeneratorTarget->GetHeaderSources(headerSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - headerSources, this->MacOSXContentGenerator.get()); + headerSources, this->MacOSXContentGenerator.get(), config); } { std::vector extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName); + this->GeneratorTarget->GetExtraSources(extraSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - extraSources, this->MacOSXContentGenerator.get()); + extraSources, this->MacOSXContentGenerator.get(), config); } { const char* pchExtension = GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects, - this->ConfigName); + this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { const auto objectFileName = this->GetSourceFilePath(sf); if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { @@ -842,15 +842,14 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps; this->GetLocalGenerator()->AppendTargetDepends( - this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering); + this->GeneratorTarget, orderOnlyDeps, config, DependOnTargetOrdering); // Add order-only dependencies on other files associated with the target. cmAppend(orderOnlyDeps, this->ExtraFiles); // Add order-only dependencies on custom command outputs. for (cmCustomCommand const* cc : this->CustomCommands) { - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), - this->GetLocalGenerator()); + cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator()); const std::vector& ccoutputs = ccg.GetOutputs(); const std::vector& ccbyproducts = ccg.GetByproducts(); std::transform(ccoutputs.begin(), ccoutputs.end(), @@ -881,9 +880,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() { std::vector objectSources; - this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName); + this->GeneratorTarget->GetObjectSources(objectSources, config); for (cmSourceFile const* sf : objectSources) { - this->WriteObjectBuildStatement(sf); + this->WriteObjectBuildStatement(sf, config); } } @@ -895,7 +894,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() build.Outputs.push_back(this->GetDyndepFilePath(language)); build.ExplicitDeps = ddiFiles; - this->WriteTargetDependInfo(language); + this->WriteTargetDependInfo(language, config); // Make sure dyndep files for all our dependencies have already // been generated so that the 'Modules.json' files they @@ -905,8 +904,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() // our dependencies produces them. Fixing this will require // refactoring the Ninja generator to generate targets in // dependency order so that we can collect the needed information. - this->GetLocalGenerator()->AppendTargetDepends( - this->GeneratorTarget, build.OrderOnlyDeps, DependOnTargetArtifact); + this->GetLocalGenerator()->AppendTargetDepends(this->GeneratorTarget, + build.OrderOnlyDeps, config, + DependOnTargetArtifact); this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); } @@ -937,7 +937,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() } void cmNinjaTargetGenerator::WriteObjectBuildStatement( - cmSourceFile const* source) + cmSourceFile const* source, const std::string& config) { std::string const language = source->GetLanguage(); std::string const sourceFileName = @@ -963,9 +963,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( cmNinjaBuild objBuild(this->LanguageCompilerRule(language)); cmNinjaVars& vars = objBuild.Variables; - vars["FLAGS"] = this->ComputeFlagsForObject(source, language); - vars["DEFINES"] = this->ComputeDefines(source, language); - vars["INCLUDES"] = this->ComputeIncludes(source, language); + vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config); + vars["DEFINES"] = this->ComputeDefines(source, language, config); + vars["INCLUDES"] = this->ComputeIncludes(source, language, config); if (!this->NeedDepTypeMSVC(language)) { bool replaceExt(false); @@ -1006,13 +1006,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::vector depList; const std::string pchSource = - this->GeneratorTarget->GetPchSource(this->GetConfigName(), language); + this->GeneratorTarget->GetPchSource(config, language); if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { - depList.push_back( - this->GeneratorTarget->GetPchHeader(this->GetConfigName(), language)); + depList.push_back(this->GeneratorTarget->GetPchHeader(config, language)); if (source->GetFullPath() != pchSource) { - depList.push_back( - this->GeneratorTarget->GetPchFile(this->GetConfigName(), language)); + depList.push_back(this->GeneratorTarget->GetPchFile(config, language)); } } @@ -1114,7 +1112,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags( sourceDirectory, this->GeneratorTarget, language, false, false, - this->GetConfigName()); + config); vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"]; } @@ -1163,7 +1161,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), vars); - this->SetMsvcTargetPdbVariable(vars); + this->SetMsvcTargetPdbVariable(vars, config); objBuild.RspFile = objectFileName + ".rsp"; @@ -1185,7 +1183,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } } -void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) +void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, + const std::string& config) { Json::Value tdi(Json::objectValue); tdi["language"] = lang; @@ -1213,7 +1212,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) Json::Value& tdi_include_dirs = tdi["include-dirs"] = Json::arrayValue; std::vector includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - lang, this->GetConfigName()); + lang, config); for (std::string const& i : includes) { // Convert the include directories the same way we do for -I flags. // See upstream ninja issue 1251. @@ -1222,7 +1221,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] = Json::arrayValue; - for (std::string const& l : this->GetLinkedTargetDirectories()) { + for (std::string const& l : this->GetLinkedTargetDirectories(config)) { tdi_linked_target_dirs.append(l); } @@ -1349,16 +1348,14 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName); } -void cmNinjaTargetGenerator::AdditionalCleanFiles() +void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config) { if (const char* prop_value = this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmLocalNinjaGenerator* lg = this->LocalGenerator; std::vector cleanFiles; - cmExpandList(cmGeneratorExpression::Evaluate( - prop_value, lg, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"), - this->GeneratorTarget), + cmExpandList(cmGeneratorExpression::Evaluate(prop_value, lg, config, + this->GeneratorTarget), cleanFiles); std::string const& binaryDir = lg->GetCurrentBinaryDirectory(); cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator(); @@ -1392,7 +1389,7 @@ void cmNinjaTargetGenerator::EnsureParentDirectoryExists( } void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( - cmSourceFile const& source, const char* pkgloc) + cmSourceFile const& source, const char* pkgloc, const std::string& config) { // Skip OS X content when not building a Framework or Bundle. if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { @@ -1400,7 +1397,8 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( } std::string macdir = - this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc); + this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc, + config); // Get the input file location. std::string input = source.GetFullPath(); diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 4627bcd..4db23f5 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -38,14 +38,14 @@ public: /// Destructor. ~cmNinjaTargetGenerator() override; - virtual void Generate() = 0; + virtual void Generate(const std::string& config) = 0; std::string GetTargetName() const; bool NeedDepTypeMSVC(const std::string& lang) const; protected: - bool SetMsvcTargetPdbVariable(cmNinjaVars&) const; + bool SetMsvcTargetPdbVariable(cmNinjaVars&, const std::string& config) const; cmGeneratedFileStream& GetBuildFileStream() const; cmGeneratedFileStream& GetRulesFileStream() const; @@ -82,15 +82,19 @@ protected: * by LanguageFlagsVarName(). */ std::string ComputeFlagsForObject(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); - void AddIncludeFlags(std::string& flags, std::string const& lang) override; + void AddIncludeFlags(std::string& flags, std::string const& lang, + const std::string& config) override; std::string ComputeDefines(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); std::string ComputeIncludes(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); std::string ConvertToNinjaPath(const std::string& path) const { @@ -102,7 +106,8 @@ protected: } /// @return the list of link dependency for the given target @a target. - cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage) const; + cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage, + const std::string& config) const; /// @return the source file path for the given @a source. std::string GetSourceFilePath(cmSourceFile const* source) const; @@ -120,16 +125,19 @@ protected: std::string GetTargetDependInfoPath(std::string const& lang) const; /// @return the file path where the target named @a name is generated. - std::string GetTargetFilePath(const std::string& name) const; + std::string GetTargetFilePath(const std::string& name, + const std::string& config) const; /// @return the output path for the target. - virtual std::string GetTargetOutputDir() const; + virtual std::string GetTargetOutputDir(const std::string& config) const; void WriteLanguageRules(const std::string& language); void WriteCompileRule(const std::string& language); - void WriteObjectBuildStatements(); - void WriteObjectBuildStatement(cmSourceFile const* source); - void WriteTargetDependInfo(std::string const& lang); + void WriteObjectBuildStatements(const std::string& config); + void WriteObjectBuildStatement(cmSourceFile const* source, + const std::string& config); + void WriteTargetDependInfo(std::string const& lang, + const std::string& config); void EmitSwiftDependencyInfo(cmSourceFile const* source); @@ -139,7 +147,7 @@ protected: std::string const& objectFileDir, std::string const& flags, std::string const& defines, std::string const& includes); - void AdditionalCleanFiles(); + void AdditionalCleanFiles(const std::string& config); cmNinjaDeps GetObjects() const { return this->Objects; } @@ -155,7 +163,8 @@ protected: { } - void operator()(cmSourceFile const& source, const char* pkgloc) override; + void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) override; private: cmNinjaTargetGenerator* Generator; diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 5259037..0592f34 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -15,7 +15,6 @@ #include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" #include "cmLocalNinjaGenerator.h" -#include "cmMakefile.h" #include "cmNinjaTypes.h" #include "cmOutputConverter.h" #include "cmSourceFile.h" @@ -31,7 +30,7 @@ cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() = default; -void cmNinjaUtilityTargetGenerator::Generate() +void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) { cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator(); cmLocalNinjaGenerator* lg = this->GetLocalGenerator(); @@ -55,8 +54,8 @@ void cmNinjaUtilityTargetGenerator::Generate() for (std::vector const* cmdList : cmdLists) { for (cmCustomCommand const& ci : *cmdList) { - cmCustomCommandGenerator ccg(ci, this->GetConfigName(), lg); - lg->AppendCustomCommandDeps(ccg, deps); + cmCustomCommandGenerator ccg(ci, config, lg); + lg->AppendCustomCommandDeps(ccg, deps, config); lg->AppendCustomCommandLines(ccg, commands); std::vector const& ccByproducts = ccg.GetByproducts(); std::transform(ccByproducts.begin(), ccByproducts.end(), @@ -69,13 +68,11 @@ void cmNinjaUtilityTargetGenerator::Generate() } { - std::string const& config = - this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); std::vector sources; genTarget->GetSourceFiles(sources, config); for (cmSourceFile const* source : sources) { if (cmCustomCommand const* cc = source->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), lg); + cmCustomCommandGenerator ccg(*cc, config, lg); lg->AddCustomCommandTarget(cc, genTarget); // Depend on all custom command outputs. @@ -89,8 +86,8 @@ void cmNinjaUtilityTargetGenerator::Generate() } } - lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs); - lg->AppendTargetDepends(genTarget, deps); + lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs, config); + lg->AppendTargetDepends(genTarget, deps, config); if (commands.empty()) { phonyBuild.Comment = "Utility command for " + this->GetTargetName(); @@ -137,12 +134,12 @@ void cmNinjaUtilityTargetGenerator::Generate() } // Find ADDITIONAL_CLEAN_FILES - this->AdditionalCleanFiles(); + this->AdditionalCleanFiles(config); // Add an alias for the logical target name regardless of what directory // contains it. Skip this for GLOBAL_TARGET because they are meant to // be per-directory and have one at the top-level anyway. if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { - gg->AddTargetAlias(this->GetTargetName(), genTarget); + gg->AddTargetAlias(this->GetTargetName(), genTarget, config); } } diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h index 01cc459..ca3f0a4 100644 --- a/Source/cmNinjaUtilityTargetGenerator.h +++ b/Source/cmNinjaUtilityTargetGenerator.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include + #include "cmNinjaTargetGenerator.h" class cmGeneratorTarget; @@ -15,7 +17,7 @@ public: cmNinjaUtilityTargetGenerator(cmGeneratorTarget* target); ~cmNinjaUtilityTargetGenerator() override; - void Generate() override; + void Generate(const std::string& config) override; }; #endif // ! cmNinjaUtilityTargetGenerator_h diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index a6f4e51..382b563 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -3,7 +3,6 @@ #include "cmOSXBundleGenerator.h" #include -#include #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" @@ -15,12 +14,10 @@ class cmSourceFile; -cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target, - std::string configName) +cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target) : GT(target) , Makefile(target->Target->GetMakefile()) , LocalGenerator(target->GetLocalGenerator()) - , ConfigName(std::move(configName)) , MacContentFolders(nullptr) { if (this->MustSkip()) { @@ -34,34 +31,34 @@ bool cmOSXBundleGenerator::MustSkip() } void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, - std::string& outpath) + std::string& outpath, + const std::string& config) { if (this->MustSkip()) { return; } // Compute bundle directory names. - std::string out = - cmStrCat(outpath, '/', - this->GT->GetAppBundleDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel)); + std::string out = cmStrCat( + outpath, '/', + this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::FullLevel)); cmSystemTools::MakeDirectory(out); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = - cmStrCat(outpath, '/', - this->GT->GetAppBundleDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - "/Info.plist"); + std::string plist = cmStrCat( + outpath, '/', + this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::ContentLevel), + "/Info.plist"); this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist); this->Makefile->AddCMakeOutputFile(plist); outpath = out; } void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, - const std::string& outpath) + const std::string& outpath, + const std::string& config) { if (this->MustSkip()) { return; @@ -70,15 +67,13 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, assert(this->MacContentFolders); // Compute the location of the top-level foo.framework directory. - std::string contentdir = - cmStrCat(outpath, '/', - this->GT->GetFrameworkDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - '/'); + std::string contentdir = cmStrCat( + outpath, '/', + this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::ContentLevel), + '/'); std::string newoutpath = outpath + "/" + - this->GT->GetFrameworkDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel); + this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel); std::string frameworkVersion = this->GT->GetFrameworkVersion(); @@ -156,27 +151,26 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, } void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, - const std::string& root) + const std::string& root, + const std::string& config) { if (this->MustSkip()) { return; } // Compute bundle directory names. - std::string out = - cmStrCat(root, '/', - this->GT->GetCFBundleDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel)); + std::string out = cmStrCat( + root, '/', + this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel)); cmSystemTools::MakeDirectory(out); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = - cmStrCat(root, '/', - this->GT->GetCFBundleDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - "/Info.plist"); + std::string plist = cmStrCat( + root, '/', + this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel), + "/Info.plist"); std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist); this->Makefile->AddCMakeOutputFile(plist); @@ -184,7 +178,7 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, void cmOSXBundleGenerator::GenerateMacOSXContentStatements( std::vector const& sources, - MacOSXContentGeneratorType* generator) + MacOSXContentGeneratorType* generator, const std::string& config) { if (this->MustSkip()) { return; @@ -194,20 +188,19 @@ void cmOSXBundleGenerator::GenerateMacOSXContentStatements( cmGeneratorTarget::SourceFileFlags tsFlags = this->GT->GetTargetSourceFileFlags(source); if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) { - (*generator)(*source, tsFlags.MacFolder); + (*generator)(*source, tsFlags.MacFolder, config); } } } std::string cmOSXBundleGenerator::InitMacOSXContentDirectory( - const char* pkgloc) + const char* pkgloc, const std::string& config) { // Construct the full path to the content subdirectory. - std::string macdir = - cmStrCat(this->GT->GetMacContentDirectory( - this->ConfigName, cmStateEnums::RuntimeBinaryArtifact), - '/', pkgloc); + std::string macdir = cmStrCat(this->GT->GetMacContentDirectory( + config, cmStateEnums::RuntimeBinaryArtifact), + '/', pkgloc); cmSystemTools::MakeDirectory(macdir); // Record use of this content location. Only the first level diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 3dea6cc..232be48 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -17,29 +17,33 @@ class cmSourceFile; class cmOSXBundleGenerator { public: - cmOSXBundleGenerator(cmGeneratorTarget* target, std::string configName); + cmOSXBundleGenerator(cmGeneratorTarget* target); // create an app bundle at a given root, and return // the directory within the bundle that contains the executable - void CreateAppBundle(const std::string& targetName, std::string& root); + void CreateAppBundle(const std::string& targetName, std::string& root, + const std::string& config); // create a framework at a given root - void CreateFramework(const std::string& targetName, const std::string& root); + void CreateFramework(const std::string& targetName, const std::string& root, + const std::string& config); // create a cf bundle at a given root - void CreateCFBundle(const std::string& targetName, const std::string& root); + void CreateCFBundle(const std::string& targetName, const std::string& root, + const std::string& config); struct MacOSXContentGeneratorType { virtual ~MacOSXContentGeneratorType() = default; - virtual void operator()(cmSourceFile const& source, - const char* pkgloc) = 0; + virtual void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) = 0; }; void GenerateMacOSXContentStatements( std::vector const& sources, - MacOSXContentGeneratorType* generator); - std::string InitMacOSXContentDirectory(const char* pkgloc); + MacOSXContentGeneratorType* generator, const std::string& config); + std::string InitMacOSXContentDirectory(const char* pkgloc, + const std::string& config); void SetMacContentFolders(std::set* macContentFolders) { @@ -53,7 +57,6 @@ private: cmGeneratorTarget* GT; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; - std::string ConfigName; std::set* MacContentFolders; }; -- cgit v0.12 From 5a8a9f72293ab1b3fd768ff40e5fb1f07cdb7dd2 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 15 Nov 2019 13:01:36 -0500 Subject: Ninja: Add multi-config variant Co-Authored-by: vector-of-bool --- Source/cmCommonTargetGenerator.cxx | 25 +- Source/cmCommonTargetGenerator.h | 14 +- Source/cmCustomCommandGenerator.cxx | 8 +- Source/cmExportTryCompileFileGenerator.cxx | 3 +- Source/cmGeneratorTarget.cxx | 10 +- Source/cmGeneratorTarget.h | 1 + Source/cmGlobalGenerator.cxx | 4 +- Source/cmGlobalGenerator.h | 6 + Source/cmGlobalNinjaGenerator.cxx | 601 ++++++++++++++++----- Source/cmGlobalNinjaGenerator.h | 186 ++++++- Source/cmLinkLineComputer.cxx | 30 +- Source/cmLinkLineComputer.h | 2 + Source/cmLocalGenerator.cxx | 9 +- Source/cmLocalGenerator.h | 1 + Source/cmLocalNinjaGenerator.cxx | 91 +++- Source/cmLocalNinjaGenerator.h | 9 +- Source/cmMakefile.cxx | 5 +- Source/cmNinjaNormalTargetGenerator.cxx | 156 ++++-- Source/cmNinjaNormalTargetGenerator.h | 3 +- Source/cmNinjaTargetGenerator.cxx | 202 ++++--- Source/cmNinjaTargetGenerator.h | 67 ++- Source/cmNinjaUtilityTargetGenerator.cxx | 36 +- Source/cmOutputConverter.cxx | 23 +- Source/cmOutputConverter.h | 9 +- Source/cmQtAutoGenInitializer.cxx | 13 +- Source/cmState.cxx | 10 + Source/cmState.h | 3 + Source/cmTarget.cxx | 9 +- Source/cmTarget.h | 3 +- Source/cmake.cxx | 1 + Tests/CMakeLists.txt | 7 +- .../CPackComponentsDEB/RunCPackVerifyResult.cmake | 2 +- Tests/FortranModules/Executable/CMakeLists.txt | 2 +- Tests/IncludeDirectories/CMakeLists.txt | 2 +- Tests/InterfaceLibrary/CMakeLists.txt | 8 +- Tests/LinkDirectory/External/CMakeLists.txt | 14 +- Tests/OutDir/CMakeLists.txt | 4 +- Tests/OutDir/OutDir.cmake | 6 +- Tests/RunCMake/CMakeLists.txt | 2 +- Tests/RunCMake/CPack/CPackTestHelpers.cmake | 2 +- .../CPack/tests/EXTERNAL/expected-json-1.0.txt | 3 +- Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake | 2 +- Tests/RunCMake/FileAPI/check_index.py | 2 +- Tests/RunCMake/FileAPI/codemodel-v2-check.py | 24 +- Tests/RunCMake/Ninja/RunCMakeTest.cmake | 3 + Tests/RunCMake/RuntimePath/Relative.cmake | 17 +- Tests/RunCMake/RuntimePath/RunCMakeTest.cmake | 12 +- .../RuntimePath/SymlinkImplicitCheck.cmake | 2 +- .../add_link_options/LINKER_expansion-list.cmake | 2 +- .../CTestScriptVariableCommandLine-stderr.txt | 3 +- Tests/RunCMake/file/RunCMakeTest.cmake | 4 +- Tests/RunCMake/get_property/RunCMakeTest.cmake | 2 +- .../TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt | 4 +- .../target_link_options/LINKER_expansion.cmake | 11 +- 54 files changed, 1264 insertions(+), 416 deletions(-) diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 6c7d9e8..9106e70 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -99,15 +99,15 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags( std::string cmCommonTargetGenerator::GetFlags(const std::string& l, const std::string& config) { - auto i = this->FlagsByLanguage.find(l); - if (i == this->FlagsByLanguage.end()) { + auto i = this->Configs[config].FlagsByLanguage.find(l); + if (i == this->Configs[config].FlagsByLanguage.end()) { std::string flags; this->LocalCommonGenerator->GetTargetCompileFlags(this->GeneratorTarget, config, l, flags); ByLanguageMap::value_type entry(l, flags); - i = this->FlagsByLanguage.insert(entry).first; + i = this->Configs[config].FlagsByLanguage.insert(entry).first; } return i->second; } @@ -115,8 +115,8 @@ std::string cmCommonTargetGenerator::GetFlags(const std::string& l, std::string cmCommonTargetGenerator::GetDefines(const std::string& l, const std::string& config) { - auto i = this->DefinesByLanguage.find(l); - if (i == this->DefinesByLanguage.end()) { + auto i = this->Configs[config].DefinesByLanguage.find(l); + if (i == this->Configs[config].DefinesByLanguage.end()) { std::set defines; this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, config, l, defines); @@ -125,7 +125,7 @@ std::string cmCommonTargetGenerator::GetDefines(const std::string& l, this->LocalCommonGenerator->JoinDefines(defines, definesString, l); ByLanguageMap::value_type entry(l, definesString); - i = this->DefinesByLanguage.insert(entry).first; + i = this->Configs[config].DefinesByLanguage.insert(entry).first; } return i->second; } @@ -133,12 +133,12 @@ std::string cmCommonTargetGenerator::GetDefines(const std::string& l, std::string cmCommonTargetGenerator::GetIncludes(std::string const& l, const std::string& config) { - auto i = this->IncludesByLanguage.find(l); - if (i == this->IncludesByLanguage.end()) { + auto i = this->Configs[config].IncludesByLanguage.find(l); + if (i == this->Configs[config].IncludesByLanguage.end()) { std::string includes; this->AddIncludeFlags(includes, l, config); ByLanguageMap::value_type entry(l, includes); - i = this->IncludesByLanguage.insert(entry).first; + i = this->Configs[config].IncludesByLanguage.insert(entry).first; } return i->second; } @@ -182,7 +182,12 @@ std::string cmCommonTargetGenerator::ComputeTargetCompilePDB( if (compilePdbPath.empty()) { // Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`. // A trailing slash tells the toolchain to add its default file name. - compilePdbPath = this->GeneratorTarget->GetSupportDirectory() + "/"; + compilePdbPath = this->GeneratorTarget->GetSupportDirectory(); + if (this->GlobalCommonGenerator->IsMultiConfig()) { + compilePdbPath += "/"; + compilePdbPath += config; + } + compilePdbPath += "/"; if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) { // Match VS default for static libs: `$(IntDir)$(ProjectName).pdb`. compilePdbPath += this->GeneratorTarget->GetName(); diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 37b6880..2796470 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -51,18 +51,24 @@ protected: void AppendOSXVerFlag(std::string& flags, const std::string& lang, const char* name, bool so); - using ByLanguageMap = std::map; std::string GetFlags(const std::string& l, const std::string& config); - ByLanguageMap FlagsByLanguage; std::string GetDefines(const std::string& l, const std::string& config); - ByLanguageMap DefinesByLanguage; std::string GetIncludes(std::string const& l, const std::string& config); - ByLanguageMap IncludesByLanguage; std::string GetManifests(const std::string& config); std::vector GetLinkedTargetDirectories( const std::string& config) const; std::string ComputeTargetCompilePDB(const std::string& config) const; + +private: + using ByLanguageMap = std::map; + struct ByConfig + { + ByLanguageMap FlagsByLanguage; + ByLanguageMap DefinesByLanguage; + ByLanguageMap IncludesByLanguage; + }; + std::map Configs; }; #endif diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index c1f412d..955f03b 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -201,7 +201,9 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, if (this->OldStyle) { cmd += escapeForShellOldStyle(emulator[j]); } else { - cmd += this->LG->EscapeForShell(emulator[j], this->MakeVars); + cmd += + this->LG->EscapeForShell(emulator[j], this->MakeVars, false, false, + this->MakeVars && this->LG->IsNinjaMulti()); } } @@ -222,7 +224,9 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, if (this->OldStyle) { cmd += escapeForShellOldStyle(arg); } else { - cmd += this->LG->EscapeForShell(arg, this->MakeVars); + cmd += + this->LG->EscapeForShell(arg, this->MakeVars, false, false, + this->MakeVars && this->LG->IsNinjaMulti()); } } } diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index fafa51b..3df6a5c 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -70,7 +70,8 @@ std::string cmExportTryCompileFileGenerator::FindTargets( std::unique_ptr cge = ge.Parse(prop); cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE, - cmTarget::VisibilityNormal, tgt->Target->GetMakefile()); + cmTarget::VisibilityNormal, tgt->Target->GetMakefile(), + true); cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator()); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 94ce2e1..19d5b4d 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -649,6 +649,7 @@ void cmGeneratorTarget::ClearSourcesCache() this->KindedSourcesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; this->Objects.clear(); + this->VisitedConfigsForObjects.clear(); } void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before) @@ -738,7 +739,7 @@ void cmGeneratorTarget::GetObjectSources( { IMPLEMENT_VISIT(SourceKindObjectSource); - if (!this->Objects.empty()) { + if (this->VisitedConfigsForObjects.count(config)) { return; } @@ -747,16 +748,17 @@ void cmGeneratorTarget::GetObjectSources( } this->LocalGenerator->ComputeObjectFilenames(this->Objects, this); + this->VisitedConfigsForObjects.insert(config); } void cmGeneratorTarget::ComputeObjectMapping() { - if (!this->Objects.empty()) { + auto const& configs = this->Makefile->GetGeneratorConfigs(); + std::set configSet(configs.begin(), configs.end()); + if (configSet == this->VisitedConfigsForObjects) { return; } - std::vector const& configs = - this->Makefile->GetGeneratorConfigs(); for (std::string const& c : configs) { std::vector sourceFiles; this->GetObjectSources(sourceFiles, c); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 761e58a..eabd3fa9 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -767,6 +767,7 @@ private: }; using SourceEntriesType = std::map; SourceEntriesType SourceDepends; + mutable std::set VisitedConfigsForObjects; mutable std::map Objects; std::set ExplicitObjectName; mutable std::map> SystemIncludesCache; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 9840025..b27c3dc 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2476,6 +2476,7 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache( } GlobalTargetInfo gti; gti.Name = editCacheTargetName; + gti.PerConfig = false; cmCustomCommandLine singleLine; // Use generator preference for the edit_cache rule if it is defined. @@ -2510,6 +2511,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache( gti.Name = rebuildCacheTargetName; gti.Message = "Running CMake to regenerate build system..."; gti.UsesTerminal = true; + gti.PerConfig = false; cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCMakeCommand()); singleLine.push_back("-S$(CMAKE_SOURCE_DIR)"); @@ -2654,7 +2656,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, { // Package cmTarget target(gti.Name, cmStateEnums::GLOBAL_TARGET, - cmTarget::VisibilityNormal, mf); + cmTarget::VisibilityNormal, mf, gti.PerConfig); target.SetProperty("EXCLUDE_FROM_ALL", "TRUE"); std::vector no_outputs; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 952b51e..107df4d 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -479,6 +479,11 @@ public: int RecursionDepth; + virtual void GetQtAutoGenConfigs(std::vector& configs) const + { + configs.emplace_back("$"); + } + protected: // for a project collect all its targets by following depend // information, and also collect all the targets @@ -527,6 +532,7 @@ protected: std::vector Depends; std::string WorkingDir; bool UsesTerminal = false; + bool PerConfig = true; }; void CreateDefaultGlobalTargets(std::vector& targets); diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 87fd958..11dd705 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -115,6 +115,11 @@ std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit) std::string result = lit; cmSystemTools::ReplaceString(result, "$", "$$"); cmSystemTools::ReplaceString(result, "\n", "$\n"); + if (this->IsMultiConfig()) { + cmSystemTools::ReplaceString(result, + cmStrCat('$', this->GetCMakeCFGIntDir()), + this->GetCMakeCFGIntDir()); + } return result; } @@ -249,8 +254,8 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( const std::string& command, const std::string& description, const std::string& comment, const std::string& depfile, const std::string& job_pool, bool uses_terminal, bool restat, - const cmNinjaDeps& outputs, const cmNinjaDeps& explicitDeps, - const cmNinjaDeps& orderOnlyDeps) + const cmNinjaDeps& outputs, const std::string& config, + const cmNinjaDeps& explicitDeps, const cmNinjaDeps& orderOnlyDeps) { this->AddCustomCommandRule(); @@ -283,7 +288,11 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( if (!depfile.empty()) { vars["depfile"] = depfile; } - this->WriteBuild(*this->BuildFileStream, build); + if (config.empty()) { + this->WriteBuild(*this->GetCommonFileStream(), build); + } else { + this->WriteBuild(*this->GetConfigFileStream(config), build); + } } if (this->ComputingUnknownDependencies) { @@ -305,14 +314,15 @@ void cmGlobalNinjaGenerator::AddMacOSXContentRule() } void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(std::string input, - std::string output) + std::string output, + const std::string& config) { this->AddMacOSXContentRule(); { cmNinjaBuild build("COPY_OSX_CONTENT"); build.Outputs.push_back(std::move(output)); build.ExplicitDeps.push_back(std::move(input)); - this->WriteBuild(*this->BuildFileStream, build); + this->WriteBuild(*this->GetConfigFileStream(config), build); } } @@ -473,14 +483,16 @@ void cmGlobalNinjaGenerator::Generate() msg.str()); return; } - if (!this->OpenBuildFileStream()) { + if (!this->OpenBuildFileStreams()) { return; } if (!this->OpenRulesFileStream()) { return; } - this->TargetDependsClosures.clear(); + for (auto& it : this->Configs) { + it.second.TargetDependsClosures.clear(); + } this->InitOutputPathPrefix(); this->TargetAll = this->NinjaOutputPath("all"); @@ -496,19 +508,26 @@ void cmGlobalNinjaGenerator::Generate() this->cmGlobalGenerator::Generate(); this->WriteAssumedSourceDependencies(); - this->WriteTargetAliases(*this->BuildFileStream); - this->WriteFolderTargets(*this->BuildFileStream); - this->WriteUnknownExplicitDependencies(*this->BuildFileStream); - this->WriteBuiltinTargets(*this->BuildFileStream); + this->WriteTargetAliases(*this->GetCommonFileStream()); + this->WriteFolderTargets(*this->GetCommonFileStream()); + this->WriteUnknownExplicitDependencies(*this->GetCommonFileStream()); + this->WriteBuiltinTargets(*this->GetCommonFileStream()); if (cmSystemTools::GetErrorOccuredFlag()) { this->RulesFileStream->setstate(std::ios::failbit); - this->BuildFileStream->setstate(std::ios::failbit); + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + this->GetConfigFileStream(config)->setstate(std::ios::failbit); + } + this->GetCommonFileStream()->setstate(std::ios::failbit); } this->CloseCompileCommandsStream(); this->CloseRulesFileStream(); - this->CloseBuildFileStream(); + this->CloseBuildFileStreams(); + + if (!this->WriteDefaultBuildFile()) { + return; + } } bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) @@ -612,6 +631,17 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const void cmGlobalNinjaGenerator::EnableLanguage( std::vector const& langs, cmMakefile* mf, bool optional) { + if (this->IsMultiConfig()) { + if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { + mf->AddCacheDefinition( + "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", + "Semicolon separated list of supported configuration types, only " + "supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything " + "else will be ignored", + cmStateEnums::STRING); + } + } + this->cmGlobalGenerator::EnableLanguage(langs, mf, optional); for (std::string const& l : langs) { if (l == "NONE") { @@ -653,7 +683,7 @@ std::vector cmGlobalNinjaGenerator::GenerateBuildCommand( const std::string& makeProgram, const std::string& /*projectName*/, const std::string& /*projectDir*/, - std::vector const& targetNames, const std::string& /*config*/, + std::vector const& targetNames, const std::string& config, bool /*fast*/, int jobs, bool verbose, std::vector const& makeOptions) { @@ -669,6 +699,9 @@ cmGlobalNinjaGenerator::GenerateBuildCommand( makeCommand.Add("-j", std::to_string(jobs)); } + this->AppendNinjaFileArgument(makeCommand, + config.empty() ? "Debug" : config); + makeCommand.Add(makeOptions.begin(), makeOptions.end()); for (const auto& tname : targetNames) { if (!tname.empty()) { @@ -710,44 +743,53 @@ void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { // Compute full path to object file directory for this target. - std::string dir = - cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/', - gt->LocalGenerator->GetTargetDirectory(gt), '/'); + std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), + '/', gt->LocalGenerator->GetTargetDirectory(gt), + '/', this->GetCMakeCFGIntDir(), '/'); gt->ObjectDirectory = dir; } // Private methods -bool cmGlobalNinjaGenerator::OpenBuildFileStream() +bool cmGlobalNinjaGenerator::OpenBuildFileStreams() { - // Compute Ninja's build file path. - std::string buildFilePath = - cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', - cmGlobalNinjaGenerator::NINJA_BUILD_FILE); + if (!this->OpenFileStream(this->BuildFileStream, + cmGlobalNinjaGenerator::NINJA_BUILD_FILE)) { + return false; + } + + // Write a comment about this file. + *this->BuildFileStream + << "# This file contains all the build statements describing the\n" + << "# compilation DAG.\n\n"; + + return true; +} +bool cmGlobalNinjaGenerator::OpenFileStream( + std::unique_ptr& stream, const std::string& name) +{ // Get a stream where to generate things. - if (!this->BuildFileStream) { - this->BuildFileStream = cm::make_unique( - buildFilePath, false, this->GetMakefileEncoding()); - if (!(*this->BuildFileStream)) { + if (!stream) { + // Compute Ninja's build file path. + std::string path = + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', name); + stream = cm::make_unique( + path, false, this->GetMakefileEncoding()); + if (!(*stream)) { // An error message is generated by the constructor if it cannot // open the file. return false; } - } - - // Write the do not edit header. - this->WriteDisclaimer(*this->BuildFileStream); - // Write a comment about this file. - *this->BuildFileStream - << "# This file contains all the build statements describing the\n" - << "# compilation DAG.\n\n"; + // Write the do not edit header. + this->WriteDisclaimer(*stream); + } return true; } -void cmGlobalNinjaGenerator::CloseBuildFileStream() +void cmGlobalNinjaGenerator::CloseBuildFileStreams() { if (this->BuildFileStream) { this->BuildFileStream.reset(); @@ -758,25 +800,11 @@ void cmGlobalNinjaGenerator::CloseBuildFileStream() bool cmGlobalNinjaGenerator::OpenRulesFileStream() { - // Compute Ninja's build file path. - std::string rulesFilePath = - cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', - cmGlobalNinjaGenerator::NINJA_RULES_FILE); - - // Get a stream where to generate things. - if (!this->RulesFileStream) { - this->RulesFileStream = cm::make_unique( - rulesFilePath, false, this->GetMakefileEncoding()); - if (!(*this->RulesFileStream)) { - // An error message is generated by the constructor if it cannot - // open the file. - return false; - } + if (!this->OpenFileStream(this->RulesFileStream, + cmGlobalNinjaGenerator::NINJA_RULES_FILE)) { + return false; } - // Write the do not edit header. - this->WriteDisclaimer(*this->RulesFileStream); - // Write comment about this file. /* clang-format off */ *this->RulesFileStream @@ -834,9 +862,10 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath( .first->second; } -void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName) +void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName, + const std::string& config) { - this->AdditionalCleanFiles.emplace(std::move(fileName)); + this->Configs[config].AdditionalCleanFiles.emplace(std::move(fileName)); } void cmGlobalNinjaGenerator::AddCXXCompileCommand( @@ -904,14 +933,16 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies() "Assume dependencies for generated source file.", /*depfile*/ "", /*job_pool*/ "", /*uses_terminal*/ false, - /*restat*/ true, cmNinjaDeps(1, asd.first), + /*restat*/ true, cmNinjaDeps(1, asd.first), "", cmNinjaDeps(), orderOnlyDeps); } } -std::string OrderDependsTargetForTarget(cmGeneratorTarget const* target) +std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget( + cmGeneratorTarget const* target, const std::string& config) { - return "cmake_object_order_depends_target_" + target->GetName(); + return "cmake_object_order_depends_target_" + target->GetName() + "_" + + config; } void cmGlobalNinjaGenerator::AppendTargetOutputs( @@ -929,7 +960,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::MODULE_LIBRARY: { if (depends == DependOnTargetOrdering) { - outputs.push_back(OrderDependsTargetForTarget(target)); + outputs.push_back(OrderDependsTargetForTarget(target, config)); break; } } @@ -941,7 +972,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( } case cmStateEnums::OBJECT_LIBRARY: { if (depends == DependOnTargetOrdering) { - outputs.push_back(OrderDependsTargetForTarget(target)); + outputs.push_back(OrderDependsTargetForTarget(target, config)); break; } } @@ -951,7 +982,11 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( std::string path = target->GetLocalGenerator()->GetCurrentBinaryDirectory() + std::string("/") + target->GetName(); - outputs.push_back(this->ConvertToNinjaPath(path)); + std::string output = this->ConvertToNinjaPath(path); + if (target->Target->IsPerConfig()) { + output = this->BuildAlias(output, config); + } + outputs.push_back(output); break; } @@ -962,7 +997,8 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( void cmGlobalNinjaGenerator::AppendTargetDepends( cmGeneratorTarget const* target, cmNinjaDeps& outputs, - const std::string& config, cmNinjaTargetDepends depends) + const std::string& config, const std::string& fileConfig, + cmNinjaTargetDepends depends) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { // These depend only on other CMake-provided targets, e.g. "all". @@ -970,7 +1006,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( std::string d = target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + util.Value; - outputs.push_back(this->ConvertToNinjaPath(d)); + outputs.push_back(this->BuildAlias(this->ConvertToNinjaPath(d), config)); } } else { cmNinjaDeps outs; @@ -979,7 +1015,14 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - this->AppendTargetOutputs(targetDep, outs, config, depends); + // For some reason, object libraries show up as "utility" dependencies + // even though they're used for linking. Treat them as link dependencies. + if (targetDep.IsUtil() && + targetDep->GetType() != cmStateEnums::OBJECT_LIBRARY) { + this->AppendTargetOutputs(targetDep, outs, fileConfig, depends); + } else { + this->AppendTargetOutputs(targetDep, outs, config, depends); + } } std::sort(outs.begin(), outs.end()); cmAppend(outputs, outs); @@ -1001,9 +1044,10 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( { // try to locate the target in the cache - auto find = this->TargetDependsClosures.lower_bound(target); + auto find = this->Configs[config].TargetDependsClosures.lower_bound(target); - if (find == this->TargetDependsClosures.end() || find->first != target) { + if (find == this->Configs[config].TargetDependsClosures.end() || + find->first != target) { // We now calculate the closure outputs by inspecting the dependent // targets recursively. // For that we have to distinguish between a local result set that is only @@ -1020,8 +1064,8 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( // Collect the dependent targets for _this_ target this->AppendTargetDependsClosure(dep_target, this_outs, config, false); } - find = this->TargetDependsClosures.emplace_hint(find, target, - std::move(this_outs)); + find = this->Configs[config].TargetDependsClosures.emplace_hint( + find, target, std::move(this_outs)); } // now fill the outputs of the final result from the newly generated cache @@ -1040,21 +1084,39 @@ void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias, cmGeneratorTarget* target, const std::string& config) { - std::string buildAlias = this->NinjaOutputPath(alias); + std::string outputPath = this->NinjaOutputPath(alias); + std::string buildAlias = this->BuildAlias(outputPath, config); cmNinjaDeps outputs; this->AppendTargetOutputs(target, outputs, config); - // Mark the target's outputs as ambiguous to ensure that no other target uses - // the output as an alias. + // Mark the target's outputs as ambiguous to ensure that no other target + // uses the output as an alias. for (std::string const& output : outputs) { - TargetAliases[output] = nullptr; + this->TargetAliases[output].GeneratorTarget = nullptr; + for (const std::string& config2 : + this->Makefiles.front()->GetGeneratorConfigs()) { + this->Configs[config2].TargetAliases[output].GeneratorTarget = nullptr; + } } // Insert the alias into the map. If the alias was already present in the // map and referred to another target, mark it as ambiguous. - std::pair newAlias = - TargetAliases.insert(std::make_pair(buildAlias, target)); - if (newAlias.second && newAlias.first->second != target) { - newAlias.first->second = nullptr; + TargetAlias ta; + ta.GeneratorTarget = target; + ta.Config = config; + std::pair newAliasGlobal = + this->TargetAliases.insert(std::make_pair(buildAlias, ta)); + if (newAliasGlobal.second && + newAliasGlobal.first->second.GeneratorTarget != target) { + newAliasGlobal.first->second.GeneratorTarget = nullptr; + } + if (config != "all") { + std::pair newAliasConfig = + this->Configs[config].TargetAliases.insert( + std::make_pair(outputPath, ta)); + if (newAliasConfig.second && + newAliasConfig.first->second.GeneratorTarget != target) { + newAliasConfig.first->second.GeneratorTarget = nullptr; + } } } @@ -1064,10 +1126,10 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) os << "# Target aliases.\n\n"; cmNinjaBuild build("phony"); - build.Outputs.emplace_back(""); - for (auto const& ta : TargetAliases) { + build.Outputs.emplace_back(); + for (auto const& ta : this->TargetAliases) { // Don't write ambiguous aliases. - if (!ta.second) { + if (!ta.second.GeneratorTarget) { continue; } @@ -1077,20 +1139,41 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) continue; } - // Outputs - build.Outputs[0] = ta.first; - - std::vector configs; - ta.second->Makefile->GetConfigurations(configs); - if (configs.empty()) { - configs.emplace_back(); + build.Outputs.front() = ta.first; + build.ExplicitDeps.clear(); + if (ta.second.Config == "all") { + for (auto const& config : + ta.second.GeneratorTarget->Makefile->GetGeneratorConfigs()) { + this->AppendTargetOutputs(ta.second.GeneratorTarget, + build.ExplicitDeps, config); + } + } else { + this->AppendTargetOutputs(ta.second.GeneratorTarget, build.ExplicitDeps, + ta.second.Config); } - for (auto const& config : configs) { - // Explicit dependencies - build.ExplicitDeps.clear(); - this->AppendTargetOutputs(ta.second, build.ExplicitDeps, config); - // Write - this->WriteBuild(os, build); + this->WriteBuild(os, build); + } + + if (this->IsMultiConfig()) { + for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) { + for (auto const& ta : this->Configs[config].TargetAliases) { + // Don't write ambiguous aliases. + if (!ta.second.GeneratorTarget) { + continue; + } + + // Don't write alias if there is a already a custom command with + // matching output + if (this->HasCustomCommandOutput(ta.first)) { + continue; + } + + build.Outputs.front() = ta.first; + build.ExplicitDeps.clear(); + this->AppendTargetOutputs(ta.second.GeneratorTarget, + build.ExplicitDeps, config); + this->WriteBuild(*this->GetConfigFileStream(config), build); + } } } } @@ -1108,31 +1191,58 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); std::string const& currentBinaryDir = it.first; DirectoryTarget const& dt = it.second; + std::vector configs; + dt.LG->GetMakefile()->GetConfigurations(configs, true); + if (configs.empty()) { + configs.emplace_back(); + } // Setup target + cmNinjaDeps configDeps; build.Comment = "Folder: " + currentBinaryDir; - build.Outputs.emplace_back( - this->ConvertToNinjaPath(currentBinaryDir + "/all")); - for (DirectoryTarget::Target const& t : dt.Targets) { - if (!t.ExcludeFromAll) { - std::vector configs; - dt.LG->GetMakefile()->GetConfigurations(configs, true); - if (configs.empty()) { - configs.emplace_back(); - } - for (auto const& config : configs) { + build.Outputs.emplace_back(); + for (auto const& config : configs) { + build.ExplicitDeps.clear(); + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config); + configDeps.emplace_back(build.Outputs.front()); + for (DirectoryTarget::Target const& t : dt.Targets) { + if (!t.ExcludeFromAll) { this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config); } } + for (DirectoryTarget::Dir const& d : dt.Children) { + if (!d.ExcludeFromAll) { + build.ExplicitDeps.emplace_back(this->BuildAlias( + this->ConvertToNinjaPath(d.Path + "/all"), config)); + } + } + // Write target + this->WriteBuild(os, build); } - for (DirectoryTarget::Dir const& d : dt.Children) { - if (!d.ExcludeFromAll) { - build.ExplicitDeps.emplace_back( - this->ConvertToNinjaPath(d.Path + "/all")); + + // Add shortcut target + if (this->IsMultiConfig()) { + for (auto const& config : configs) { + build.ExplicitDeps = { this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config) }; + build.Outputs.front() = + this->ConvertToNinjaPath(currentBinaryDir + "/all"); + this->WriteBuild(*this->GetConfigFileStream(config), build); } } - // Write target - this->WriteBuild(os, build); + + // Add target for all configs + if (this->IsMultiConfig()) { + build.ExplicitDeps.clear(); + for (auto const& config : configs) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config)); + } + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), "all"); + this->WriteBuild(*this->GetCommonFileStream(), build); + } } } @@ -1265,10 +1375,13 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); os << "# Built-in targets\n\n"; - this->WriteTargetDefault(os); this->WriteTargetRebuildManifest(os); this->WriteTargetClean(os); this->WriteTargetHelp(os); + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + this->WriteTargetDefault(*this->GetConfigFileStream(config)); + } } void cmGlobalNinjaGenerator::WriteTargetDefault(std::ostream& os) @@ -1305,7 +1418,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) cmNinjaBuild reBuild("RERUN_CMAKE"); reBuild.Comment = "Re-run CMake if any of its inputs changed."; - reBuild.Outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); + this->AddRebuildManifestOutputs(reBuild.Outputs); for (const auto& localGen : this->LocalGenerators) { for (std::string const& fi : localGen->GetMakefile()->GetListFiles()) { @@ -1435,9 +1548,23 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake"; std::string cleanScriptAbs = cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel); + std::vector configs; + this->Makefiles[0]->GetConfigurations(configs, true); + if (configs.empty()) { + configs.emplace_back(); + } // Check if there are additional files to clean - if (this->AdditionalCleanFiles.empty()) { + bool empty = true; + for (auto const& config : configs) { + auto const it = this->Configs.find(config); + if (it != this->Configs.end() && + !it->second.AdditionalCleanFiles.empty()) { + empty = false; + break; + } + } + if (empty) { // Remove cmake clean script file if it exists cmSystemTools::RemoveFile(cleanScriptAbs); return false; @@ -1449,14 +1576,23 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) if (!fout) { return false; } - fout << "# Additional clean files\n\n"; - fout << "file(REMOVE_RECURSE\n"; - for (std::string const& acf : this->AdditionalCleanFiles) { - fout << " " - << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf)) - << '\n'; + fout << "# Additional clean files\ncmake_minimum_required(VERSION 3.16)\n"; + for (auto const& config : configs) { + auto const it = this->Configs.find(config); + if (it != this->Configs.end() && + !it->second.AdditionalCleanFiles.empty()) { + fout << "\nif(\"${CONFIG}\" STREQUAL \"\" OR \"${CONFIG}\" STREQUAL \"" + << config << "\")\n"; + fout << " file(REMOVE_RECURSE\n"; + for (std::string const& acf : it->second.AdditionalCleanFiles) { + fout << " " + << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf)) + << '\n'; + } + fout << " )\n"; + fout << "endif()\n"; + } } - fout << ")\n"; } // Register clean script file lgr->GetMakefile()->AddCMakeOutputFile(cleanScriptAbs); @@ -1465,7 +1601,7 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { cmNinjaRule rule("CLEAN_ADDITIONAL"); rule.Command = cmStrCat( - CMakeCmd(), " -P ", + CMakeCmd(), " -DCONFIG=$CONFIG -P ", lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel), cmOutputConverter::SHELL)); rule.Description = "Cleaning additional files..."; @@ -1477,9 +1613,19 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { cmNinjaBuild build("CLEAN_ADDITIONAL"); build.Comment = "Clean additional files."; - build.Outputs.push_back( - this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); - WriteBuild(os, build); + build.Outputs.emplace_back(); + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), config); + build.Variables["CONFIG"] = config; + WriteBuild(os, build); + } + if (this->IsMultiConfig()) { + build.Outputs.front() = + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()); + build.Variables["CONFIG"] = ""; + WriteBuild(os, build); + } } // Return success return true; @@ -1494,22 +1640,91 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) // Write rule { cmNinjaRule rule("CLEAN"); - rule.Command = NinjaCmd() + " -t clean"; + rule.Command = NinjaCmd() + " $FILE_ARG -t clean $TARGETS"; rule.Description = "Cleaning all built files..."; rule.Comment = "Rule for cleaning all built files."; WriteRule(*this->RulesFileStream, rule); } + auto const configs = this->Makefiles.front()->GetGeneratorConfigs(); + // Write build { cmNinjaBuild build("CLEAN"); build.Comment = "Clean all the built files."; - build.Outputs.push_back(this->NinjaOutputPath(this->GetCleanTargetName())); - if (additionalFiles) { - build.ExplicitDeps.push_back( - this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); + build.Outputs.emplace_back(); + + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), config); + if (this->IsMultiConfig()) { + build.Variables["TARGETS"] = + cmStrCat(this->BuildAlias(GetByproductsForCleanTargetName(), config), + " ", GetByproductsForCleanTargetName()); + } + build.ExplicitDeps.clear(); + if (additionalFiles) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), + config)); + } + for (auto const& fileConfig : configs) { + if (this->IsMultiConfig()) { + build.Variables["FILE_ARG"] = cmStrCat( + "-f ", cmGlobalNinjaMultiGenerator::GetNinjaFilename(fileConfig)); + } + this->WriteBuild(*this->GetConfigFileStream(fileConfig), build); + } + } + + if (this->IsMultiConfig()) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), "all"); + build.ExplicitDeps.clear(); + + if (additionalFiles) { + build.ExplicitDeps.push_back( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); + } + + build.Variables["TARGETS"] = ""; + + for (auto const& fileConfig : configs) { + build.Variables["FILE_ARG"] = cmStrCat( + "-f ", cmGlobalNinjaMultiGenerator::GetNinjaFilename(fileConfig)); + this->WriteBuild(*this->GetConfigFileStream(fileConfig), build); + } + } + } + + if (this->IsMultiConfig()) { + cmNinjaBuild build("phony"); + build.Outputs.emplace_back( + this->NinjaOutputPath(this->GetCleanTargetName())); + build.ExplicitDeps.emplace_back(); + + for (auto const& config : configs) { + build.ExplicitDeps.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), config); + this->WriteBuild(*this->GetConfigFileStream(config), build); } + } + + // Write byproducts + if (this->IsMultiConfig()) { + cmNinjaBuild build("phony"); + build.Comment = "Clean byproducts."; + build.Outputs.emplace_back( + this->ConvertToNinjaPath(GetByproductsForCleanTargetName())); + build.ExplicitDeps = this->ByproductsForCleanTarget; WriteBuild(os, build); + + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(GetByproductsForCleanTargetName()), config); + build.ExplicitDeps = this->Configs[config].ByproductsForCleanTarget; + WriteBuild(os, build); + } } } @@ -2016,3 +2231,137 @@ int cmcmd_cmake_ninja_dyndep(std::vector::const_iterator argBeg, } return 0; } + +void cmGlobalNinjaGenerator::AppendDirectoryForConfig( + const std::string& prefix, const std::string& config, + const std::string& suffix, std::string& dir) +{ + if (!config.empty() && this->IsMultiConfig()) { + dir += prefix; + dir += config; + dir += suffix; + } +} + +const char* cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE = "common.ninja"; +const char* cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION = ".ninja"; + +cmGlobalNinjaMultiGenerator::cmGlobalNinjaMultiGenerator(cmake* cm) + : cmGlobalNinjaGenerator(cm) +{ + cm->GetState()->SetIsGeneratorMultiConfig(true); + cm->GetState()->SetNinjaMulti(true); +} + +void cmGlobalNinjaMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) +{ + entry.Name = cmGlobalNinjaMultiGenerator::GetActualName(); + entry.Brief = "Generates build-.ninja files."; +} + +std::string cmGlobalNinjaMultiGenerator::ExpandCFGIntDir( + const std::string& str, const std::string& config) const +{ + std::string result = str; + cmSystemTools::ReplaceString(result, this->GetCMakeCFGIntDir(), config); + return result; +} + +bool cmGlobalNinjaMultiGenerator::OpenBuildFileStreams() +{ + if (!this->OpenFileStream(this->CommonFileStream, + cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE)) { + return false; + } + + // Write a comment about this file. + *this->CommonFileStream + << "# This file contains build statements common to all " + "configurations.\n\n"; + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + if (!this->OpenFileStream(this->ConfigFileStreams[config], + GetNinjaFilename(config))) { + return false; + } + + // Write a comment about this file. + *this->ConfigFileStreams[config] + << "# This file contains build statements specific to the \"" << config + << "\"\n# configuration.\n\n"; + } + + return true; +} + +void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams() +{ + if (this->CommonFileStream) { + this->CommonFileStream.reset(); + } else { + cmSystemTools::Error("Common file stream was not open."); + } + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + if (this->ConfigFileStreams[config]) { + this->ConfigFileStreams[config].reset(); + } else { + cmSystemTools::Error( + cmStrCat("Config file stream for \"", config, "\" was not open.")); + } + } +} + +void cmGlobalNinjaMultiGenerator::AppendNinjaFileArgument( + GeneratedMakeCommand& command, const std::string& config) const +{ + command.Add("-f"); + command.Add(GetNinjaFilename(config)); +} + +std::string cmGlobalNinjaMultiGenerator::GetNinjaFilename( + const std::string& config) +{ + return cmStrCat("build-", config, + cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION); +} + +void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs( + cmNinjaDeps& outputs) const +{ + for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) { + outputs.push_back(this->NinjaOutputPath(GetNinjaFilename(config))); + } + if (this->Makefiles.front()->GetDefinition( + "CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE")) { + outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); + } +} + +void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs( + std::vector& configs) const +{ + auto const oldSize = configs.size(); + this->Makefiles.front()->GetConfigurations(configs); + if (configs.size() == oldSize) { + configs.emplace_back(); + } +} + +bool cmGlobalNinjaMultiGenerator::WriteDefaultBuildFile() +{ + auto const* defaultConfig = this->Makefiles.front()->GetDefinition( + "CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE"); + if (defaultConfig) { + std::unique_ptr defaultStream; + if (!this->OpenFileStream(defaultStream, NINJA_BUILD_FILE)) { + return false; + } + *defaultStream << "# This file is a convenience file generated by\n" + << "# CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.\n\n" + << "include " << this->GetNinjaFilename(defaultConfig) + << "\n"; + } + + return true; +} diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index a725018..6ebb31d 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -22,6 +22,7 @@ #include "cmGlobalGeneratorFactory.h" #include "cmNinjaTypes.h" #include "cmPolicies.h" +#include "cmStringAlgorithms.h" class cmCustomCommand; class cmGeneratorTarget; @@ -73,7 +74,7 @@ public: static void WriteDivider(std::ostream& os); static std::string EncodeRuleName(std::string const& name); - static std::string EncodeLiteral(const std::string& lit); + std::string EncodeLiteral(const std::string& lit); std::string EncodePath(const std::string& path); cmLinkLineComputer* CreateLinkLineComputer( @@ -111,11 +112,12 @@ public: const std::string& command, const std::string& description, const std::string& comment, const std::string& depfile, const std::string& pool, bool uses_terminal, bool restat, - const cmNinjaDeps& outputs, + const cmNinjaDeps& outputs, const std::string& config, const cmNinjaDeps& explicitDeps = cmNinjaDeps(), const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps()); - void WriteMacOSXContentBuild(std::string input, std::string output); + void WriteMacOSXContentBuild(std::string input, std::string output, + const std::string& config); /** * Write a rule statement to @a os. @@ -205,7 +207,13 @@ public: } const char* GetCleanTargetName() const override { return "clean"; } - cmGeneratedFileStream* GetBuildFileStream() const + virtual cmGeneratedFileStream* GetConfigFileStream( + const std::string& /*config*/) const + { + return this->BuildFileStream.get(); + } + + virtual cmGeneratedFileStream* GetCommonFileStream() const { return this->BuildFileStream.get(); } @@ -232,12 +240,17 @@ public: MapToNinjaPathImpl MapToNinjaPath() { return { this }; } // -- Additional clean files - void AddAdditionalCleanFile(std::string fileName); + void AddAdditionalCleanFile(std::string fileName, const std::string& config); const char* GetAdditionalCleanTargetName() const { return "CMakeFiles/clean.additional"; } + static const char* GetByproductsForCleanTargetName() + { + return "CMakeFiles/cmake_byproducts_for_clean_target"; + } + void AddCXXCompileCommand(const std::string& commandLine, const std::string& sourceFile); @@ -261,9 +274,9 @@ public: /// Called when we have seen the given custom command. Returns true /// if we has seen it before. - bool SeenCustomCommand(cmCustomCommand const* cc) + bool SeenCustomCommand(cmCustomCommand const* cc, const std::string& config) { - return !this->CustomCommands.insert(cc).second; + return !this->Configs[config].CustomCommands.insert(cc).second; } /// Called when we have seen the given custom command output. @@ -285,13 +298,16 @@ public: ASD.insert(deps.begin(), deps.end()); } + static std::string OrderDependsTargetForTarget( + cmGeneratorTarget const* target, const std::string& config); + void AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, const std::string& config, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDepends( cmGeneratorTarget const* target, cmNinjaDeps& outputs, - const std::string& config, + const std::string& config, const std::string& fileConfig, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDependsClosure(cmGeneratorTarget const* target, cmNinjaDeps& outputs, @@ -300,6 +316,21 @@ public: cmNinjaOuts& outputs, const std::string& config, bool omit_self); + void AppendDirectoryForConfig(const std::string& prefix, + const std::string& config, + const std::string& suffix, + std::string& dir) override; + + virtual void AppendNinjaFileArgument(GeneratedMakeCommand& /*command*/, + const std::string& /*config*/) const + { + } + + virtual void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const + { + outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); + } + int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; } void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target, @@ -336,11 +367,39 @@ public: std::vector const& linked_target_dirs, std::string const& arg_lang); + virtual std::string BuildAlias(const std::string& alias, + const std::string& /*config*/) const + { + return alias; + } + + virtual std::string ConfigDirectory(const std::string& /*config*/) const + { + return ""; + } + + cmNinjaDeps& GetByproductsForCleanTarget() + { + return this->ByproductsForCleanTarget; + } + + cmNinjaDeps& GetByproductsForCleanTarget(const std::string& config) + { + return this->Configs[config].ByproductsForCleanTarget; + } + protected: void Generate() override; bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; } + virtual bool OpenBuildFileStreams(); + virtual void CloseBuildFileStreams(); + virtual bool WriteDefaultBuildFile() { return true; } + + bool OpenFileStream(std::unique_ptr& stream, + const std::string& name); + private: std::string GetEditCacheCommand() const override; bool FindMakeProgram(cmMakefile* mf) override; @@ -349,9 +408,6 @@ private: cmMakefile* mf) const override; bool CheckFortran(cmMakefile* mf) const; - bool OpenBuildFileStream(); - void CloseBuildFileStream(); - void CloseCompileCommandsStream(); bool OpenRulesFileStream(); @@ -396,9 +452,6 @@ private: bool UsingGCCOnWindows = false; - /// The set of custom commands we have seen. - std::set CustomCommands; - /// The set of custom command outputs we have seen. std::set CustomCommandOutputs; @@ -417,11 +470,14 @@ private: /// The mapping from source file to assumed dependencies. std::map> AssumedSourceDependencies; - using TargetAliasMap = std::map; + struct TargetAlias + { + cmGeneratorTarget* GeneratorTarget; + std::string Config; + }; + using TargetAliasMap = std::map; TargetAliasMap TargetAliases; - std::map TargetDependsClosures; - /// the local cache for calls to ConvertToNinjaPath mutable std::unordered_map ConvertToNinjaPathCache; @@ -439,7 +495,101 @@ private: std::string OutputPathPrefix; std::string TargetAll; std::string CMakeCacheFile; - std::set AdditionalCleanFiles; + + struct ByConfig + { + std::set AdditionalCleanFiles; + + /// The set of custom commands we have seen. + std::set CustomCommands; + + std::map TargetDependsClosures; + + TargetAliasMap TargetAliases; + + cmNinjaDeps ByproductsForCleanTarget; + }; + std::map Configs; + + cmNinjaDeps ByproductsForCleanTarget; +}; + +class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator +{ +public: + /// The default name of Ninja's common file. Typically: common.ninja. + static const char* NINJA_COMMON_FILE; + /// The default file extension to use for per-config Ninja files. + static const char* NINJA_FILE_EXTENSION; + + cmGlobalNinjaMultiGenerator(cmake* cm); + bool IsMultiConfig() const override { return true; } + static cmGlobalGeneratorFactory* NewFactory() + { + return new cmGlobalGeneratorSimpleFactory(); + } + + static void GetDocumentation(cmDocumentationEntry& entry); + + std::string GetName() const override + { + return cmGlobalNinjaMultiGenerator::GetActualName(); + } + + static std::string GetActualName() { return "Ninja Multi-Config"; } + + std::string BuildAlias(const std::string& alias, + const std::string& config) const override + { + if (config.empty()) { + return alias; + } + return cmStrCat(alias, ":", config); + } + + std::string ConfigDirectory(const std::string& config) const override + { + if (!config.empty()) { + return cmStrCat('/', config); + } + return ""; + } + + const char* GetCMakeCFGIntDir() const override { return "${CONFIGURATION}"; } + + std::string ExpandCFGIntDir(const std::string& str, + const std::string& config) const override; + + cmGeneratedFileStream* GetConfigFileStream( + const std::string& config) const override + { + return this->ConfigFileStreams.at(config).get(); + } + + cmGeneratedFileStream* GetCommonFileStream() const override + { + return this->CommonFileStream.get(); + } + + void AppendNinjaFileArgument(GeneratedMakeCommand& command, + const std::string& config) const override; + + static std::string GetNinjaFilename(const std::string& config); + + void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override; + + void GetQtAutoGenConfigs(std::vector& configs) const override; + + bool WriteDefaultBuildFile() override; + +protected: + bool OpenBuildFileStreams() override; + void CloseBuildFileStreams() override; + +private: + std::map> + ConfigFileStreams; + std::unique_ptr CommonFileStream; }; #endif // ! cmGlobalNinjaGenerator_h diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 0dc6236..4320010 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -23,6 +23,7 @@ cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, , OutputConverter(outputConverter) , ForResponse(false) , UseWatcomQuote(false) + , UseNinjaMulti(false) , Relink(false) { } @@ -34,6 +35,11 @@ void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote) this->UseWatcomQuote = useWatcomQuote; } +void cmLinkLineComputer::SetUseNinjaMulti(bool useNinjaMulti) +{ + this->UseNinjaMulti = useNinjaMulti; +} + void cmLinkLineComputer::SetForResponse(bool forResponse) { this->ForResponse = forResponse; @@ -106,10 +112,14 @@ void cmLinkLineComputer::ComputeLinkLibs( std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input) { - cmOutputConverter::OutputFormat shellFormat = (this->ForResponse) - ? cmOutputConverter::RESPONSE - : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE - : cmOutputConverter::SHELL); + cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL; + if (this->ForResponse) { + shellFormat = cmOutputConverter::RESPONSE; + } else if (this->UseWatcomQuote) { + shellFormat = cmOutputConverter::WATCOMQUOTE; + } else if (this->UseNinjaMulti) { + shellFormat = cmOutputConverter::NINJAMULTI; + } return this->OutputConverter->ConvertToOutputFormat(input, shellFormat); } @@ -117,10 +127,14 @@ std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input) std::string cmLinkLineComputer::ConvertToOutputForExisting( std::string const& input) { - cmOutputConverter::OutputFormat shellFormat = (this->ForResponse) - ? cmOutputConverter::RESPONSE - : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE - : cmOutputConverter::SHELL); + cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL; + if (this->ForResponse) { + shellFormat = cmOutputConverter::RESPONSE; + } else if (this->UseWatcomQuote) { + shellFormat = cmOutputConverter::WATCOMQUOTE; + } else if (this->UseNinjaMulti) { + shellFormat = cmOutputConverter::NINJAMULTI; + } return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat); } diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index f426976..df42468 100644 --- a/Source/cmLinkLineComputer.h +++ b/Source/cmLinkLineComputer.h @@ -28,6 +28,7 @@ public: cmLinkLineComputer& operator=(cmLinkLineComputer const&) = delete; void SetUseWatcomQuote(bool useWatcomQuote); + void SetUseNinjaMulti(bool useNinjaMulti); void SetForResponse(bool forResponse); void SetRelink(bool relink); @@ -69,6 +70,7 @@ protected: bool ForResponse; bool UseWatcomQuote; + bool UseNinjaMulti; bool Relink; }; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index e7494ee..87ff7cb 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2392,7 +2392,9 @@ void cmLocalGenerator::AppendFlags( void cmLocalGenerator::AppendFlagEscape(std::string& flags, const std::string& rawFlag) const { - this->AppendFlags(flags, this->EscapeForShell(rawFlag)); + this->AppendFlags( + flags, + this->EscapeForShell(rawFlag, false, false, false, this->IsNinjaMulti())); } void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) @@ -3207,6 +3209,11 @@ bool cmLocalGenerator::IsNMake() const return this->GetState()->UseNMake(); } +bool cmLocalGenerator::IsNinjaMulti() const +{ + return this->GetState()->UseNinjaMulti(); +} + std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( const cmSourceFile& source, std::string const& dir_max, bool* hasSourceExtension, char const* customOutputExtension) diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 8788c2f..b91d5f7 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -466,6 +466,7 @@ public: bool IsWatcomWMake() const; bool IsMinGWMake() const; bool IsNMake() const; + bool IsNinjaMulti() const; void IssueMessage(MessageType t, std::string const& text) const; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 96ee759..6967097 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -29,6 +29,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" #include "cmake.h" cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, @@ -61,7 +62,12 @@ void cmLocalNinjaGenerator::Generate() this->HomeRelativeOutputPath.clear(); } - this->WriteProcessedMakefile(this->GetBuildFileStream()); + if (this->GetGlobalGenerator()->IsMultiConfig()) { + for (auto const& config : this->GetConfigNames()) { + this->WriteProcessedMakefile(this->GetConfigFileStream(config)); + } + } + this->WriteProcessedMakefile(this->GetCommonFileStream()); #ifdef NINJA_GEN_VERBOSE_FILES this->WriteProcessedMakefile(this->GetRulesFileStream()); #endif @@ -88,8 +94,12 @@ void cmLocalNinjaGenerator::Generate() } auto tg = cmNinjaTargetGenerator::New(target.get()); if (tg) { - for (auto const& config : this->GetConfigNames()) { - tg->Generate(config); + if (target->Target->IsPerConfig()) { + for (auto const& config : this->GetConfigNames()) { + tg->Generate(config); + } + } else { + tg->Generate(""); } } } @@ -144,9 +154,15 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference( // Private methods. -cmGeneratedFileStream& cmLocalNinjaGenerator::GetBuildFileStream() const +cmGeneratedFileStream& cmLocalNinjaGenerator::GetConfigFileStream( + const std::string& config) const +{ + return *this->GetGlobalNinjaGenerator()->GetConfigFileStream(config); +} + +cmGeneratedFileStream& cmLocalNinjaGenerator::GetCommonFileStream() const { - return *this->GetGlobalNinjaGenerator()->GetBuildFileStream(); + return *this->GetGlobalNinjaGenerator()->GetCommonFileStream(); } cmGeneratedFileStream& cmLocalNinjaGenerator::GetRulesFileStream() const @@ -166,10 +182,22 @@ cmake* cmLocalNinjaGenerator::GetCMakeInstance() void cmLocalNinjaGenerator::WriteBuildFileTop() { - // For the build file. - this->WriteProjectHeader(this->GetBuildFileStream()); - this->WriteNinjaRequiredVersion(this->GetBuildFileStream()); - this->WriteNinjaFilesInclusion(this->GetBuildFileStream()); + this->WriteProjectHeader(this->GetCommonFileStream()); + + if (this->GetGlobalGenerator()->IsMultiConfig()) { + for (auto const& config : this->GetConfigNames()) { + auto& stream = this->GetConfigFileStream(config); + this->WriteProjectHeader(stream); + this->WriteNinjaRequiredVersion(stream); + this->WriteNinjaConfigurationVariable(stream, config); + this->WriteNinjaFilesInclusionConfig(stream); + } + } else { + this->WriteNinjaRequiredVersion(this->GetCommonFileStream()); + this->WriteNinjaConfigurationVariable(this->GetCommonFileStream(), + this->GetConfigNames().front()); + } + this->WriteNinjaFilesInclusionCommon(this->GetCommonFileStream()); // For the rule file. this->WriteProjectHeader(this->GetRulesFileStream()); @@ -211,6 +239,14 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) << std::endl; } +void cmLocalNinjaGenerator::WriteNinjaConfigurationVariable( + std::ostream& os, const std::string& config) +{ + cmGlobalNinjaGenerator::WriteVariable( + os, "CONFIGURATION", config, + "Set configuration variable for custom commands."); +} + void cmLocalNinjaGenerator::WritePools(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); @@ -240,7 +276,21 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) } } -void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os) +void cmLocalNinjaGenerator::WriteNinjaFilesInclusionConfig(std::ostream& os) +{ + cmGlobalNinjaGenerator::WriteDivider(os); + os << "# Include auxiliary files.\n" + << "\n"; + cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator(); + std::string const ninjaCommonFile = + ng->NinjaOutputPath(cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE); + std::string const commonFilePath = ng->EncodePath(ninjaCommonFile); + cmGlobalNinjaGenerator::WriteInclude(os, commonFilePath, + "Include common file."); + os << "\n"; +} + +void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); os << "# Include auxiliary files.\n" @@ -278,10 +328,11 @@ void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target, void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config, + const std::string& fileConfig, cmNinjaTargetDepends depends) { this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, config, - depends); + fileConfig, depends); } void cmLocalNinjaGenerator::AppendCustomCommandDeps( @@ -425,6 +476,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( void cmLocalNinjaGenerator::AppendCustomCommandLines( cmCustomCommandGenerator const& ccg, std::vector& cmdLines) { + auto* gg = this->GetGlobalNinjaGenerator(); + if (ccg.GetNumberOfCommands() > 0) { std::string wd = ccg.GetWorkingDirectory(); if (wd.empty()) { @@ -446,8 +499,10 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines( for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) { cmdLines.push_back(launcher + - this->ConvertToOutputFormat(ccg.GetCommand(i), - cmOutputConverter::SHELL)); + this->ConvertToOutputFormat( + ccg.GetCommand(i), + gg->IsMultiConfig() ? cmOutputConverter::NINJAMULTI + : cmOutputConverter::SHELL)); std::string& cmd = cmdLines.back(); ccg.AppendArguments(i, cmd); @@ -459,7 +514,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( const std::string& config) { cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator(); - if (gg->SeenCustomCommand(cc)) { + if (gg->SeenCustomCommand(cc, config)) { return; } @@ -505,7 +560,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( build.Outputs = std::move(ninjaOutputs); build.ExplicitDeps = std::move(ninjaDeps); build.OrderOnlyDeps = orderOnlyDeps; - gg->WriteBuild(this->GetBuildFileStream(), build); + gg->WriteBuild(this->GetConfigFileStream(config), build); } else { std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]); // Hash full path to make unique. @@ -517,8 +572,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( this->BuildCommandLine(cmdLines, customStep), this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(), - /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps, - orderOnlyDeps); + /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config, + ninjaDeps, orderOnlyDeps); } } @@ -625,7 +680,7 @@ void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config) for (std::string const& cleanFile : cleanFiles) { // Support relative paths gg->AddAdditionalCleanFile( - cmSystemTools::CollapseFullPath(cleanFile, binaryDir)); + cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config); } } } diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 6f68a83..0445879 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -68,6 +68,7 @@ public: const std::string& config); void AppendTargetDepends( cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config, + const std::string& fileConfig, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AddCustomCommandTarget(cmCustomCommand const* cc, @@ -85,13 +86,17 @@ protected: bool forceFullPaths = false) override; private: - cmGeneratedFileStream& GetBuildFileStream() const; + cmGeneratedFileStream& GetConfigFileStream(const std::string& config) const; + cmGeneratedFileStream& GetCommonFileStream() const; cmGeneratedFileStream& GetRulesFileStream() const; void WriteBuildFileTop(); void WriteProjectHeader(std::ostream& os); void WriteNinjaRequiredVersion(std::ostream& os); - void WriteNinjaFilesInclusion(std::ostream& os); + void WriteNinjaConfigurationVariable(std::ostream& os, + const std::string& config); + void WriteNinjaFilesInclusionConfig(std::ostream& os); + void WriteNinjaFilesInclusionCommon(std::ostream& os); void WriteProcessedMakefile(std::ostream& os); void WritePools(std::ostream& os); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ac494b4..6c5db75 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1992,7 +1992,8 @@ cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type, { auto it = this->Targets - .emplace(name, cmTarget(name, type, cmTarget::VisibilityNormal, this)) + .emplace(name, + cmTarget(name, type, cmTarget::VisibilityNormal, this, true)) .first; this->OrderedTargets.push_back(&it->second); this->GetGlobalGenerator()->IndexTarget(&it->second); @@ -4162,7 +4163,7 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name, new cmTarget(name, type, global ? cmTarget::VisibilityImportedGlobally : cmTarget::VisibilityImported, - this)); + this, true)); // Add to the set of available imported targets. this->ImportedTargets[name] = target.get(); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 5601a33..5a12855 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -70,7 +70,11 @@ void cmNinjaNormalTargetGenerator::Generate(const std::string& config) this->WriteLanguagesRules(config); // Write the build statements - this->WriteObjectBuildStatements(config); + bool firstForConfig = true; + for (auto const& fileConfig : this->GetConfigNames()) { + this->WriteObjectBuildStatements(config, fileConfig, firstForConfig); + firstForConfig = false; + } if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) { this->WriteObjectLibStatement(config); @@ -78,8 +82,14 @@ void cmNinjaNormalTargetGenerator::Generate(const std::string& config) // If this target has cuda language link inputs, and we need to do // device linking this->WriteDeviceLinkStatement(config); - this->WriteLinkStatement(config); + firstForConfig = true; + for (auto const& fileConfig : this->GetConfigNames()) { + this->WriteLinkStatement(config, fileConfig, firstForConfig); + firstForConfig = false; + } } + this->GetGlobalGenerator()->AddTargetAlias( + this->GetTargetName(), this->GetGeneratorTarget(), "all"); // Find ADDITIONAL_CLEAN_FILES this->AdditionalCleanFiles(config); @@ -107,7 +117,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules( } } for (std::string const& language : languages) { - this->WriteLanguageRules(language); + this->WriteLanguageRules(language, config); } } @@ -138,7 +148,8 @@ std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule( cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + "_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()); + this->GetGeneratorTarget()->GetName()) + + "_" + config; } std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule( @@ -148,7 +159,8 @@ std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule( cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + "_DEVICE_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()); + this->GetGeneratorTarget()->GetName()) + + "_" + config; } struct cmNinjaRemoveNoOpCommands @@ -571,11 +583,11 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( this->DeviceLinkObject = targetOutputReal; // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); + cmGlobalNinjaGenerator::WriteDivider(this->GetCommonFileStream()); const cmStateEnums::TargetType targetType = genTarget->GetType(); - this->GetBuildFileStream() << "# Device Link build statements for " - << cmState::GetTargetTypeName(targetType) - << " target " << this->GetTargetName() << "\n\n"; + this->GetCommonFileStream() << "# Device Link build statements for " + << cmState::GetTargetTypeName(targetType) + << " target " << this->GetTargetName() << "\n\n"; // Compute the comment. cmNinjaBuild build(this->LanguageLinkerDeviceRule(config)); @@ -587,7 +599,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( // Compute outputs. build.Outputs.push_back(targetOutputReal); // Compute specific libraries to link with. - build.ExplicitDeps = this->GetObjects(); + build.ExplicitDeps = this->GetObjects(config); build.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); @@ -609,6 +621,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(), globalGen)); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); + linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig()); localGen.GetTargetFlags( linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"], @@ -616,8 +629,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( this->addPoolNinjaVariable("JOB_POOL_LINK", genTarget, vars); - vars["LINK_FLAGS"] = - cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); + vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); vars["MANIFESTS"] = this->GetManifests(config); @@ -661,18 +673,21 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( EnsureParentDirectoryExists(impLibPath); } - const std::string objPath = GetGeneratorTarget()->GetSupportDirectory(); + const std::string objPath = + cmStrCat(GetGeneratorTarget()->GetSupportDirectory(), + globalGen->ConfigDirectory(config)); + vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL); EnsureDirectoryExists(objPath); this->SetMsvcTargetPdbVariable(vars, config); + std::string& linkLibraries = vars["LINK_LIBRARIES"]; + std::string& link_path = vars["LINK_PATH"]; if (globalGen->IsGCCOnWindows()) { // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) - std::string& linkLibraries = vars["LINK_LIBRARIES"]; std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); - std::string& link_path = vars["LINK_PATH"]; std::replace(link_path.begin(), link_path.end(), '\\', '/'); } @@ -686,18 +701,19 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( genTarget->GetName() + ".rsp"); // Gather order-only dependencies. - this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(), - build.OrderOnlyDeps, config); + this->GetLocalGenerator()->AppendTargetDepends( + this->GetGeneratorTarget(), build.OrderOnlyDeps, config, config); // Write the build statement for this target. bool usedResponseFile = false; - globalGen->WriteBuild(this->GetBuildFileStream(), build, + globalGen->WriteBuild(this->GetCommonFileStream(), build, commandLineLengthLimit, &usedResponseFile); this->WriteDeviceLinkRule(usedResponseFile, config); } void cmNinjaNormalTargetGenerator::WriteLinkStatement( - const std::string& config) + const std::string& config, const std::string& fileConfig, + bool firstForConfig) { cmMakefile* mf = this->GetMakefile(); cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); @@ -710,6 +726,27 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( std::string targetOutputImplib = ConvertToNinjaPath( gt->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); + if (config != fileConfig) { + if (targetOutput == ConvertToNinjaPath(gt->GetFullPath(fileConfig))) { + return; + } + if (targetOutputReal == + ConvertToNinjaPath(gt->GetFullPath(fileConfig, + cmStateEnums::RuntimeBinaryArtifact, + /*realname=*/true))) { + return; + } + if (!gt->GetFullName(config, cmStateEnums::ImportLibraryArtifact) + .empty() && + !gt->GetFullName(fileConfig, cmStateEnums::ImportLibraryArtifact) + .empty() && + targetOutputImplib == + ConvertToNinjaPath(gt->GetFullPath( + fileConfig, cmStateEnums::ImportLibraryArtifact))) { + return; + } + } + auto const tgtNames = this->TargetNames(config); if (gt->IsAppBundleOnApple()) { // Create the app bundle @@ -733,9 +770,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( } // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); + cmGlobalNinjaGenerator::WriteDivider(this->GetConfigFileStream(fileConfig)); const cmStateEnums::TargetType targetType = gt->GetType(); - this->GetBuildFileStream() + this->GetConfigFileStream(fileConfig) << "# Link build statements for " << cmState::GetTargetTypeName(targetType) << " target " << this->GetTargetName() << "\n\n"; @@ -748,6 +785,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( // Compute outputs. linkBuild.Outputs.push_back(targetOutputReal); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutputReal); + } if (this->TargetLinkLanguage(config) == "Swift") { vars["SWIFT_LIBRARY_NAME"] = [this, config]() -> std::string { @@ -817,14 +857,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( gt->GetObjectSources(sources, config); for (const auto& source : sources) { linkBuild.Outputs.push_back( - this->ConvertToNinjaPath(this->GetObjectFilePath(source))); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config))); linkBuild.ExplicitDeps.push_back( this->ConvertToNinjaPath(this->GetSourceFilePath(source))); } linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]); } else { - linkBuild.ExplicitDeps = this->GetObjects(); + linkBuild.ExplicitDeps = this->GetObjects(config); } linkBuild.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); @@ -849,6 +889,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( this->GetLocalGenerator(), this->GetLocalGenerator()->GetStateSnapshot().GetDirectory())); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); + linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig()); localGen.GetTargetFlags(linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"], @@ -868,8 +909,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], config); - vars["LINK_FLAGS"] = - cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); + vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); vars["MANIFESTS"] = this->GetManifests(config); @@ -920,6 +960,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( EnsureParentDirectoryExists(impLibPath); if (gt->HasImportLibrary(config)) { byproducts.push_back(targetOutputImplib); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back( + targetOutputImplib); + } } } @@ -938,16 +982,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( vars["TARGET_PDB"] = base + suffix + dbg_suffix; } - const std::string objPath = gt->GetSupportDirectory(); + const std::string objPath = + cmStrCat(gt->GetSupportDirectory(), globalGen->ConfigDirectory(config)); vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL); EnsureDirectoryExists(objPath); + std::string& linkLibraries = vars["LINK_LIBRARIES"]; + std::string& link_path = vars["LINK_PATH"]; if (globalGen->IsGCCOnWindows()) { // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) - std::string& linkLibraries = vars["LINK_LIBRARIES"]; std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); - std::string& link_path = vars["LINK_PATH"]; std::replace(link_path.begin(), link_path.end(), '\\', '/'); } @@ -958,17 +1003,24 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( std::vector preLinkCmdLines; std::vector postBuildCmdLines; - std::vector* cmdLineLists[3] = { &preLinkCmdLines, - &preLinkCmdLines, - &postBuildCmdLines }; - - for (unsigned i = 0; i != 3; ++i) { - for (cmCustomCommand const& cc : *cmdLists[i]) { - cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator()); - localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); - std::vector const& ccByproducts = ccg.GetByproducts(); - std::transform(ccByproducts.begin(), ccByproducts.end(), - std::back_inserter(byproducts), MapToNinjaPath()); + + if (config == fileConfig) { + std::vector* cmdLineLists[3] = { &preLinkCmdLines, + &preLinkCmdLines, + &postBuildCmdLines }; + + for (unsigned i = 0; i != 3; ++i) { + for (cmCustomCommand const& cc : *cmdLists[i]) { + cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator()); + localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); + std::vector const& ccByproducts = ccg.GetByproducts(); + std::transform(ccByproducts.begin(), ccByproducts.end(), + std::back_inserter(byproducts), MapToNinjaPath()); + std::transform( + ccByproducts.begin(), ccByproducts.end(), + std::back_inserter(globalGen->GetByproductsForCleanTarget()), + MapToNinjaPath()); + } } } @@ -1000,7 +1052,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( cmGeneratedFileStream fout(obj_list_file); if (mdi->WindowsExportAllSymbols) { - cmNinjaDeps objs = this->GetObjects(); + cmNinjaDeps objs = this->GetObjects(config); for (std::string const& obj : objs) { if (cmHasLiteralSuffix(obj, ".obj")) { fout << obj << "\n"; @@ -1058,7 +1110,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( // Gather order-only dependencies. this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps, - config); + config, fileConfig); // Add order-only dependencies on versioning symlinks of shared libs we link. if (!this->GeneratorTarget->IsDLLPlatform()) { @@ -1090,7 +1142,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( // Write the build statement for this target. bool usedResponseFile = false; - globalGen->WriteBuild(this->GetBuildFileStream(), linkBuild, + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), linkBuild, commandLineLengthLimit, &usedResponseFile); this->WriteLinkRule(usedResponseFile, config); @@ -1099,9 +1151,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( cmNinjaBuild build("CMAKE_SYMLINK_EXECUTABLE"); build.Comment = "Create executable symlink " + targetOutput; build.Outputs.push_back(targetOutput); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutput); + } build.ExplicitDeps.push_back(targetOutputReal); build.Variables = std::move(symlinkVars); - globalGen->WriteBuild(this->GetBuildFileStream(), build); + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), build); } else { cmNinjaBuild build("CMAKE_SYMLINK_LIBRARY"); build.Comment = "Create library symlink " + targetOutput; @@ -1116,12 +1171,18 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( } else { symlinkVars["SONAME"].clear(); build.Outputs.push_back(soName); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(soName); + } } build.Outputs.push_back(targetOutput); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutput); + } build.ExplicitDeps.push_back(targetOutputReal); build.Variables = std::move(symlinkVars); - globalGen->WriteBuild(this->GetBuildFileStream(), build); + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), build); } } @@ -1139,8 +1200,11 @@ void cmNinjaNormalTargetGenerator::WriteObjectLibStatement( build.Comment = "Object library " + this->GetTargetName(); this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(), build.Outputs, config); - build.ExplicitDeps = this->GetObjects(); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetLocalGenerator()->AppendTargetOutputs( + this->GetGeneratorTarget(), + this->GetGlobalGenerator()->GetByproductsForCleanTarget(config), config); + build.ExplicitDeps = this->GetObjects(config); + this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), build); } // Add aliases for the target name. diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index a3e7e5b..cda76d8 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -29,7 +29,8 @@ private: void WriteLinkRule(bool useResponseFile, const std::string& config); void WriteDeviceLinkRule(bool useResponseFile, const std::string& config); - void WriteLinkStatement(const std::string& config); + void WriteLinkStatement(const std::string& config, + const std::string& fileConfig, bool firstForConfig); void WriteDeviceLinkStatement(const std::string& config); void WriteObjectLibStatement(const std::string& config); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 0e44e2d..ee1163a 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -68,9 +68,15 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target) cmNinjaTargetGenerator::~cmNinjaTargetGenerator() = default; -cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const +cmGeneratedFileStream& cmNinjaTargetGenerator::GetConfigFileStream( + const std::string& config) const +{ + return *this->GetGlobalGenerator()->GetConfigFileStream(config); +} + +cmGeneratedFileStream& cmNinjaTargetGenerator::GetCommonFileStream() const { - return *this->GetGlobalGenerator()->GetBuildFileStream(); + return *this->GetGlobalGenerator()->GetCommonFileStream(); } cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const @@ -84,17 +90,19 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const } std::string cmNinjaTargetGenerator::LanguageCompilerRule( - const std::string& lang) const + const std::string& lang, const std::string& config) const { return lang + "_COMPILER__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } std::string cmNinjaTargetGenerator::LanguagePreprocessRule( - std::string const& lang) const + std::string const& lang, const std::string& config) const { return lang + "_PREPROCESS__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } bool cmNinjaTargetGenerator::NeedExplicitPreprocessing( @@ -117,10 +125,11 @@ bool cmNinjaTargetGenerator::CompilePreprocessedSourceWithDefines( } std::string cmNinjaTargetGenerator::LanguageDyndepRule( - const std::string& lang) const + const std::string& lang, const std::string& config) const { return lang + "_DYNDEP__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const @@ -128,9 +137,11 @@ bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const return lang == "Fortran"; } -std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget() +std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget( + const std::string& config) { - return "cmake_object_order_depends_target_" + this->GetTargetName(); + return cmGlobalNinjaGenerator::OrderDependsTargetForTarget( + this->GeneratorTarget, config); } // TODO: Most of the code is picked up from @@ -240,6 +251,11 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, cmGeneratorExpressionInterpreter genexInterpreter( this->LocalGenerator, config, this->GeneratorTarget, language); + // Seriously?? + if (this->GetGlobalGenerator()->IsMultiConfig()) { + defines.insert(cmStrCat("CMAKE_INTDIR=\"", config, '"')); + } + const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { this->LocalGenerator->AppendDefines( @@ -333,7 +349,7 @@ std::string cmNinjaTargetGenerator::GetSourceFilePath( } std::string cmNinjaTargetGenerator::GetObjectFilePath( - cmSourceFile const* source) const + cmSourceFile const* source, const std::string& config) const { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { @@ -341,13 +357,14 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath( } std::string const& objectName = this->GeneratorTarget->GetObjectName(source); path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += objectName; return path; } std::string cmNinjaTargetGenerator::GetPreprocessedFilePath( - cmSourceFile const* source) const + cmSourceFile const* source, const std::string& config) const { // Choose an extension to compile already-preprocessed source. std::string ppExt = source->GetExtension(); @@ -377,19 +394,21 @@ std::string cmNinjaTargetGenerator::GetPreprocessedFilePath( path += "/"; } path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += ppName; return path; } std::string cmNinjaTargetGenerator::GetDyndepFilePath( - std::string const& lang) const + std::string const& lang, const std::string& config) const { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { path += "/"; } path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += lang; path += ".dd"; @@ -397,12 +416,13 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath( } std::string cmNinjaTargetGenerator::GetTargetDependInfoPath( - std::string const& lang) const + std::string const& lang, const std::string& config) const { std::string path = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), - '/', lang, "DependInfo.json"); + this->GetGlobalGenerator()->ConfigDirectory(config), '/', lang, + "DependInfo.json"); return path; } @@ -460,15 +480,17 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable( return false; } -void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language) +void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language, + const std::string& config) { #ifdef NINJA_GEN_VERBOSE_FILES this->GetRulesFileStream() << "# Rules for language " << language << "\n\n"; #endif - this->WriteCompileRule(language); + this->WriteCompileRule(language, config); } -void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) +void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, + const std::string& config) { cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); @@ -509,7 +531,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetLocalGenerator()->CreateRulePlaceholderExpander()); std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat( - ConvertToNinjaPath(this->GetTargetDependInfoPath(lang)), + ConvertToNinjaPath(this->GetTargetDependInfoPath(lang, config)), cmLocalGenerator::SHELL); std::string launcher; @@ -524,7 +546,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); if (explicitPP) { - cmNinjaRule rule(this->LanguagePreprocessRule(lang)); + cmNinjaRule rule(this->LanguagePreprocessRule(lang, config)); // Explicit preprocessing always uses a depfile. rule.DepType = ""; // no deps= for multiple outputs rule.DepFile = "$DEP_FILE"; @@ -604,7 +626,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) if (needDyndep) { // Write the rule for ninja dyndep file generation. - cmNinjaRule rule(this->LanguageDyndepRule(lang)); + cmNinjaRule rule(this->LanguageDyndepRule(lang, config)); // Command line length is almost always limited -> use response file for // dyndep rules rule.RspFile = "$out.rsp"; @@ -628,7 +650,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetGlobalGenerator()->AddRule(rule); } - cmNinjaRule rule(this->LanguageCompilerRule(lang)); + cmNinjaRule rule(this->LanguageCompilerRule(lang, config)); // If using a response file, move defines, includes, and flags into it. if (!responseFlag.empty()) { rule.RspFile = "$RSP_FILE"; @@ -788,11 +810,12 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) } void cmNinjaTargetGenerator::WriteObjectBuildStatements( - const std::string& config) + const std::string& config, const std::string& fileConfig, + bool firstForConfig) { // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); - this->GetBuildFileStream() + cmGlobalNinjaGenerator::WriteDivider(this->GetConfigFileStream(fileConfig)); + this->GetConfigFileStream(fileConfig) << "# Object build statements for " << cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) << " target " << this->GetTargetName() << "\n\n"; @@ -806,7 +829,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( cc, this->GetGeneratorTarget()); // Record the custom commands for this target. The container is used // in WriteObjectBuildStatement when called in a loop below. - this->CustomCommands.push_back(cc); + this->Configs[config].CustomCommands.push_back(cc); } } { @@ -821,16 +844,17 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator.get(), config); } - { + if (firstForConfig) { const char* pchExtension = GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { - const auto objectFileName = this->GetSourceFilePath(sf); + auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir( + this->GetSourceFilePath(sf), config); if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { - this->Objects.push_back(objectFileName); + this->Configs[config].Objects.push_back(objectFileName); } } } @@ -838,17 +862,18 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( { cmNinjaBuild build("phony"); build.Comment = "Order-only phony target for " + this->GetTargetName(); - build.Outputs.push_back(this->OrderDependsTargetForTarget()); + build.Outputs.push_back(this->OrderDependsTargetForTarget(config)); cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps; this->GetLocalGenerator()->AppendTargetDepends( - this->GeneratorTarget, orderOnlyDeps, config, DependOnTargetOrdering); + this->GeneratorTarget, orderOnlyDeps, config, fileConfig, + DependOnTargetOrdering); // Add order-only dependencies on other files associated with the target. - cmAppend(orderOnlyDeps, this->ExtraFiles); + cmAppend(orderOnlyDeps, this->Configs[config].ExtraFiles); // Add order-only dependencies on custom command outputs. - for (cmCustomCommand const* cc : this->CustomCommands) { + for (cmCustomCommand const* cc : this->Configs[config].CustomCommands) { cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator()); const std::vector& ccoutputs = ccg.GetOutputs(); const std::vector& ccbyproducts = ccg.GetByproducts(); @@ -875,23 +900,24 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir)); } - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } { std::vector objectSources; this->GeneratorTarget->GetObjectSources(objectSources, config); for (cmSourceFile const* sf : objectSources) { - this->WriteObjectBuildStatement(sf, config); + this->WriteObjectBuildStatement(sf, config, fileConfig, firstForConfig); } } - for (auto const& langDDIFiles : this->DDIFiles) { + for (auto const& langDDIFiles : this->Configs[config].DDIFiles) { std::string const& language = langDDIFiles.first; cmNinjaDeps const& ddiFiles = langDDIFiles.second; - cmNinjaBuild build(this->LanguageDyndepRule(language)); - build.Outputs.push_back(this->GetDyndepFilePath(language)); + cmNinjaBuild build(this->LanguageDyndepRule(language, config)); + build.Outputs.push_back(this->GetDyndepFilePath(language, config)); build.ExplicitDeps = ddiFiles; this->WriteTargetDependInfo(language, config); @@ -904,48 +930,52 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( // our dependencies produces them. Fixing this will require // refactoring the Ninja generator to generate targets in // dependency order so that we can collect the needed information. - this->GetLocalGenerator()->AppendTargetDepends(this->GeneratorTarget, - build.OrderOnlyDeps, config, - DependOnTargetArtifact); + this->GetLocalGenerator()->AppendTargetDepends( + this->GeneratorTarget, build.OrderOnlyDeps, config, fileConfig, + DependOnTargetArtifact); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } - this->GetBuildFileStream() << "\n"; + this->GetConfigFileStream(fileConfig) << "\n"; - if (!this->SwiftOutputMap.empty()) { + if (!this->Configs[config].SwiftOutputMap.empty()) { std::string const mapFilePath = this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json"; - std::string const targetSwiftDepsPath = [this]() -> std::string { + std::string const targetSwiftDepsPath = [this, config]() -> std::string { cmGeneratorTarget const* target = this->GeneratorTarget; if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) { return name; } return this->ConvertToNinjaPath(target->GetSupportDirectory() + "/" + - target->GetName() + ".swiftdeps"); + config + "/" + target->GetName() + + ".swiftdeps"); }(); // build the global target dependencies // https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps Json::Value deps(Json::objectValue); deps["swift-dependencies"] = targetSwiftDepsPath; - this->SwiftOutputMap[""] = deps; + this->Configs[config].SwiftOutputMap[""] = deps; cmGeneratedFileStream output(mapFilePath); - output << this->SwiftOutputMap; + output << this->Configs[config].SwiftOutputMap; } } void cmNinjaTargetGenerator::WriteObjectBuildStatement( - cmSourceFile const* source, const std::string& config) + cmSourceFile const* source, const std::string& config, + const std::string& fileConfig, bool firstForConfig) { std::string const language = source->GetLanguage(); std::string const sourceFileName = language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source); - std::string const objectDir = - this->ConvertToNinjaPath(this->GeneratorTarget->GetSupportDirectory()); + std::string const objectDir = this->ConvertToNinjaPath( + cmStrCat(this->GeneratorTarget->GetSupportDirectory(), + this->GetGlobalGenerator()->ConfigDirectory(config))); std::string const objectFileName = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); @@ -961,7 +991,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( int const commandLineLengthLimit = ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0; - cmNinjaBuild objBuild(this->LanguageCompilerRule(language)); + cmNinjaBuild objBuild(this->LanguageCompilerRule(language, config)); cmNinjaVars& vars = objBuild.Variables; vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config); vars["DEFINES"] = this->ComputeDefines(source, language, config); @@ -993,11 +1023,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]); objBuild.Outputs.push_back(objectFileName); - const char* pchExtension = - this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); - if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { - // Add this object to the list of object files. - this->Objects.push_back(objectFileName); + if (firstForConfig) { + const char* pchExtension = + this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); + if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + // Add this object to the list of object files. + this->Configs[config].Objects.push_back(objectFileName); + } } objBuild.ExplicitDeps.push_back(sourceFileName); @@ -1031,7 +1063,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( MapToNinjaPath()); } - objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget()); + objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config)); // If the source file is GENERATED and does not have a custom command // (either attached to this source file or another one), assume that one of @@ -1051,10 +1083,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // For some cases we do an explicit preprocessor invocation. bool const explicitPP = this->NeedExplicitPreprocessing(language); if (explicitPP) { - cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language)); + cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language, config)); std::string const ppFileName = - this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source)); + this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config)); ppBuild.Outputs.push_back(ppFileName); ppBuild.RspFile = ppFileName + ".rsp"; @@ -1136,17 +1168,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string const ddiFile = objectFileName + ".ddi"; ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile; ppBuild.ImplicitOuts.push_back(ddiFile); - this->DDIFiles[language].push_back(ddiFile); + if (firstForConfig) { + this->Configs[config].DDIFiles[language].push_back(ddiFile); + } } this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), ppBuild.Variables); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), ppBuild, - commandLineLengthLimit); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), ppBuild, commandLineLengthLimit); } if (needDyndep) { - std::string const dyndep = this->GetDyndepFilePath(language); + std::string const dyndep = this->GetDyndepFilePath(language, config); objBuild.OrderOnlyDeps.push_back(dyndep); vars["dyndep"] = dyndep; } @@ -1166,10 +1200,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( objBuild.RspFile = objectFileName + ".rsp"; if (language == "Swift") { - this->EmitSwiftDependencyInfo(source); + this->EmitSwiftDependencyInfo(source, config); } else { - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), - objBuild, commandLineLengthLimit); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), objBuild, commandLineLengthLimit); } if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { @@ -1179,7 +1213,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::transform(build.Outputs.begin(), build.Outputs.end(), build.Outputs.begin(), MapToNinjaPath()); build.ExplicitDeps = objBuild.Outputs; - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } } @@ -1225,18 +1260,18 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, tdi_linked_target_dirs.append(l); } - std::string const tdin = this->GetTargetDependInfoPath(lang); + std::string const tdin = this->GetTargetDependInfoPath(lang, config); cmGeneratedFileStream tdif(tdin); tdif << tdi; } void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( - cmSourceFile const* source) + cmSourceFile const* source, const std::string& config) { std::string const sourceFilePath = this->ConvertToNinjaPath(this->GetSourceFilePath(source)); std::string const objectFilePath = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const swiftDepsPath = [source, objectFilePath]() -> std::string { if (const char* name = source->GetProperty("Swift_DEPENDENCIES_FILE")) { return name; @@ -1249,10 +1284,10 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( } return objectFilePath + ".dia"; }(); - std::string const makeDepsPath = [this, source]() -> std::string { + std::string const makeDepsPath = [this, source, config]() -> std::string { cmLocalNinjaGenerator const* local = this->GetLocalGenerator(); std::string const objectFileName = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); @@ -1273,7 +1308,7 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( entry["dependencies"] = makeDepsPath; entry["swift-dependencies"] = swiftDepsPath; entry["diagnostics"] = swiftDiaPath; - SwiftOutputMap[sourceFilePath] = entry; + this->Configs[config].SwiftOutputMap[sourceFilePath] = entry; } void cmNinjaTargetGenerator::ExportObjectCompileCommand( @@ -1362,11 +1397,20 @@ void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config) for (std::string const& cleanFile : cleanFiles) { // Support relative paths gg->AddAdditionalCleanFile( - cmSystemTools::CollapseFullPath(cleanFile, binaryDir)); + cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config); } } } +cmNinjaDeps cmNinjaTargetGenerator::GetObjects(const std::string& config) const +{ + auto const it = this->Configs.find(config); + if (it != this->Configs.end()) { + return it->second.Objects; + } + return {}; +} + void cmNinjaTargetGenerator::EnsureDirectoryExists( const std::string& path) const { @@ -1410,11 +1454,11 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( output = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output); // Write a build statement to copy the content into the bundle. - this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input, - output); + this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input, output, + config); // Add as a dependency to the target so that it gets called. - this->Generator->ExtraFiles.push_back(std::move(output)); + this->Generator->Configs[config].ExtraFiles.push_back(std::move(output)); } void cmNinjaTargetGenerator::addPoolNinjaVariable( diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 4db23f5..22dd7b8 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -47,7 +47,8 @@ public: protected: bool SetMsvcTargetPdbVariable(cmNinjaVars&, const std::string& config) const; - cmGeneratedFileStream& GetBuildFileStream() const; + cmGeneratedFileStream& GetConfigFileStream(const std::string& config) const; + cmGeneratedFileStream& GetCommonFileStream() const; cmGeneratedFileStream& GetRulesFileStream() const; cmGeneratorTarget* GetGeneratorTarget() const @@ -64,15 +65,18 @@ protected: cmMakefile* GetMakefile() const { return this->Makefile; } - std::string LanguageCompilerRule(const std::string& lang) const; - std::string LanguagePreprocessRule(std::string const& lang) const; + std::string LanguageCompilerRule(const std::string& lang, + const std::string& config) const; + std::string LanguagePreprocessRule(std::string const& lang, + const std::string& config) const; bool NeedExplicitPreprocessing(std::string const& lang) const; - std::string LanguageDyndepRule(std::string const& lang) const; + std::string LanguageDyndepRule(std::string const& lang, + const std::string& config) const; bool NeedDyndep(std::string const& lang) const; bool UsePreprocessedSource(std::string const& lang) const; bool CompilePreprocessedSourceWithDefines(std::string const& lang) const; - std::string OrderDependsTargetForTarget(); + std::string OrderDependsTargetForTarget(const std::string& config); std::string ComputeOrderDependsForTarget(); @@ -113,16 +117,20 @@ protected: std::string GetSourceFilePath(cmSourceFile const* source) const; /// @return the object file path for the given @a source. - std::string GetObjectFilePath(cmSourceFile const* source) const; + std::string GetObjectFilePath(cmSourceFile const* source, + const std::string& config) const; /// @return the preprocessed source file path for the given @a source. - std::string GetPreprocessedFilePath(cmSourceFile const* source) const; + std::string GetPreprocessedFilePath(cmSourceFile const* source, + const std::string& config) const; /// @return the dyndep file path for this target. - std::string GetDyndepFilePath(std::string const& lang) const; + std::string GetDyndepFilePath(std::string const& lang, + const std::string& config) const; /// @return the target dependency scanner info file path - std::string GetTargetDependInfoPath(std::string const& lang) const; + std::string GetTargetDependInfoPath(std::string const& lang, + const std::string& config) const; /// @return the file path where the target named @a name is generated. std::string GetTargetFilePath(const std::string& name, @@ -131,15 +139,22 @@ protected: /// @return the output path for the target. virtual std::string GetTargetOutputDir(const std::string& config) const; - void WriteLanguageRules(const std::string& language); - void WriteCompileRule(const std::string& language); - void WriteObjectBuildStatements(const std::string& config); + void WriteLanguageRules(const std::string& language, + const std::string& config); + void WriteCompileRule(const std::string& language, + const std::string& config); + void WriteObjectBuildStatements(const std::string& config, + const std::string& fileConfig, + bool firstForConfig); void WriteObjectBuildStatement(cmSourceFile const* source, - const std::string& config); + const std::string& config, + const std::string& fileConfig, + bool firstForConfig); void WriteTargetDependInfo(std::string const& lang, const std::string& config); - void EmitSwiftDependencyInfo(cmSourceFile const* source); + void EmitSwiftDependencyInfo(cmSourceFile const* source, + const std::string& config); void ExportObjectCompileCommand( std::string const& language, std::string const& sourceFileName, @@ -149,7 +164,7 @@ protected: void AdditionalCleanFiles(const std::string& config); - cmNinjaDeps GetObjects() const { return this->Objects; } + cmNinjaDeps GetObjects(const std::string& config) const; void EnsureDirectoryExists(const std::string& dir) const; void EnsureParentDirectoryExists(const std::string& path) const; @@ -183,14 +198,20 @@ protected: private: cmLocalNinjaGenerator* LocalGenerator; - /// List of object files for this target. - cmNinjaDeps Objects; - // Fortran Support - std::map DDIFiles; - // Swift Support - Json::Value SwiftOutputMap; - std::vector CustomCommands; - cmNinjaDeps ExtraFiles; + + struct ByConfig + { + /// List of object files for this target. + cmNinjaDeps Objects; + // Fortran Support + std::map DDIFiles; + // Swift Support + Json::Value SwiftOutputMap; + std::vector CustomCommands; + cmNinjaDeps ExtraFiles; + }; + + std::map Configs; }; #endif // ! cmNinjaTargetGenerator_h diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 0592f34..0cddb12 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -21,6 +21,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmGeneratorTarget* target) @@ -36,8 +37,12 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) cmLocalNinjaGenerator* lg = this->GetLocalGenerator(); cmGeneratorTarget* genTarget = this->GetGeneratorTarget(); + std::string configDir; + if (genTarget->Target->IsPerConfig()) { + configDir = gg->ConfigDirectory(config); + } std::string utilCommandName = - cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/", + cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles", configDir, "/", this->GetTargetName(), ".util"); utilCommandName = this->ConvertToNinjaPath(utilCommandName); @@ -86,13 +91,21 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) } } - lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs, config); - lg->AppendTargetDepends(genTarget, deps, config); + std::string outputConfig; + if (genTarget->Target->IsPerConfig()) { + outputConfig = config; + } + lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs, outputConfig); + if (genTarget->Target->GetType() != cmStateEnums::GLOBAL_TARGET) { + lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(), + config); + } + lg->AppendTargetDepends(genTarget, deps, config, config); if (commands.empty()) { phonyBuild.Comment = "Utility command for " + this->GetTargetName(); phonyBuild.ExplicitDeps = std::move(deps); - gg->WriteBuild(this->GetBuildFileStream(), phonyBuild); + gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); } else { std::string command = lg->BuildCommandLine(commands, "utility", this->GeneratorTarget); @@ -115,6 +128,7 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) lg->ConvertToOutputFormat(lg->GetBinaryDirectory(), cmOutputConverter::SHELL)); cmSystemTools::ReplaceString(command, "$(ARGS)", ""); + command = gg->ExpandCFGIntDir(command, config); if (command.find('$') != std::string::npos) { return; @@ -124,13 +138,18 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) gg->SeenCustomCommandOutput(util_output); } + std::string ccConfig; + if (genTarget->Target->IsPerConfig() && + genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { + ccConfig = config; + } gg->WriteCustomCommandBuild(command, desc, "Utility command for " + this->GetTargetName(), /*depfile*/ "", /*job_pool*/ "", uses_terminal, - /*restat*/ true, util_outputs, deps); + /*restat*/ true, util_outputs, ccConfig, deps); phonyBuild.ExplicitDeps.push_back(utilCommandName); - gg->WriteBuild(this->GetBuildFileStream(), phonyBuild); + gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); } // Find ADDITIONAL_CLEAN_FILES @@ -141,5 +160,10 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) // be per-directory and have one at the top-level anyway. if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { gg->AddTargetAlias(this->GetTargetName(), genTarget, config); + } else if (gg->IsMultiConfig() && genTarget->Target->IsPerConfig()) { + cmNinjaBuild phonyAlias("phony"); + gg->AppendTargetOutputs(genTarget, phonyAlias.Outputs, ""); + phonyAlias.ExplicitDeps = phonyBuild.Outputs; + gg->WriteBuild(this->GetConfigFileStream(config), phonyAlias); } } diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index e602a6d..1c6fad1 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -43,9 +43,10 @@ std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source, { std::string result(source); // Convert it to an output path. - if (output == SHELL || output == WATCOMQUOTE) { + if (output == SHELL || output == WATCOMQUOTE || output == NINJAMULTI) { result = this->ConvertDirectorySeparatorsForShell(source); - result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE); + result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE, + output == NINJAMULTI); } else if (output == RESPONSE) { result = this->EscapeForShell(result, false, false, false); } @@ -79,9 +80,9 @@ static bool cmOutputConverterIsShellOperator(cm::string_view str) return (shellOperators.count(str) != 0); } -std::string cmOutputConverter::EscapeForShell(cm::string_view str, - bool makeVars, bool forEcho, - bool useWatcomQuote) const +std::string cmOutputConverter::EscapeForShell( + cm::string_view str, bool makeVars, bool forEcho, bool useWatcomQuote, + bool unescapeNinjaConfiguration) const { // Do not escape shell operators. if (cmOutputConverterIsShellOperator(str)) { @@ -95,6 +96,9 @@ std::string cmOutputConverter::EscapeForShell(cm::string_view str, } else if (!this->LinkScriptShell) { flags |= Shell_Flag_Make; } + if (unescapeNinjaConfiguration) { + flags |= Shell_Flag_UnescapeNinjaConfiguration; + } if (makeVars) { flags |= Shell_Flag_AllowMakeVariables; } @@ -511,5 +515,14 @@ std::string cmOutputConverter::Shell__GetArgument(cm::string_view in, } } + if (flags & Shell_Flag_UnescapeNinjaConfiguration) { + std::string ninjaConfigReplace; + if (flags & Shell_Flag_IsUnix) { + ninjaConfigReplace += '\\'; + } + ninjaConfigReplace += "$${CONFIGURATION}"; + cmSystemTools::ReplaceString(out, ninjaConfigReplace, "${CONFIGURATION}"); + } + return out; } diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 349a069..6583ab5 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -22,6 +22,7 @@ public: { SHELL, WATCOMQUOTE, + NINJAMULTI, RESPONSE }; std::string ConvertToOutputFormat(cm::string_view source, @@ -70,12 +71,14 @@ public: /** The target shell quoting uses extra single Quotes for Watcom tools. */ Shell_Flag_WatcomQuote = (1 << 7), - Shell_Flag_IsUnix = (1 << 8) + Shell_Flag_IsUnix = (1 << 8), + + Shell_Flag_UnescapeNinjaConfiguration = (1 << 9), }; std::string EscapeForShell(cm::string_view str, bool makeVars = false, - bool forEcho = false, - bool useWatcomQuote = false) const; + bool forEcho = false, bool useWatcomQuote = false, + bool unescapeNinjaConfiguration = false) const; static std::string EscapeForCMake(cm::string_view str); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 42979af..fc65756 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1042,9 +1042,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() } // Compose command lines - cmCustomCommandLines commandLines = cmMakeSingleCommandLine( - { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", - this->AutogenTarget.InfoFile, "$" }); + // TODO: Refactor autogen to output a per-config mocs_compilation.cpp instead + // of fiddling with the include directories + std::vector configs; + this->GlobalGen->GetQtAutoGenConfigs(configs); + cmCustomCommandLines commandLines; + for (auto const& config : configs) { + commandLines.push_back(cmMakeCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", + this->AutogenTarget.InfoFile, config })); + } // Use PRE_BUILD on demand bool usePRE_BUILD = false; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index d337bd7..72f663d 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -715,6 +715,16 @@ bool cmState::UseMSYSShell() const return this->MSYSShell; } +void cmState::SetNinjaMulti(bool ninjaMulti) +{ + this->NinjaMulti = ninjaMulti; +} + +bool cmState::UseNinjaMulti() const +{ + return this->NinjaMulti; +} + unsigned int cmState::GetCacheMajorVersion() const { return this->CacheManager->GetCacheMajorVersion(); diff --git a/Source/cmState.h b/Source/cmState.h index a7ca015..cd871b9 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -190,6 +190,8 @@ public: bool UseNMake() const; void SetMSYSShell(bool mSYSShell); bool UseMSYSShell() const; + void SetNinjaMulti(bool ninjaMulti); + bool UseNinjaMulti() const; unsigned int GetCacheMajorVersion() const; unsigned int GetCacheMinorVersion() const; @@ -245,6 +247,7 @@ private: bool MinGWMake = false; bool NMake = false; bool MSYSShell = false; + bool NinjaMulti = false; Mode CurrentMode = Unknown; }; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index b9bf7a5..6441c0e 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -176,6 +176,7 @@ public: bool IsImportedTarget; bool ImportedGloballyVisible; bool BuildInterfaceIncludesAppended; + bool PerConfig; std::set> Utilities; std::vector PreBuildCommands; std::vector PreLinkCommands; @@ -213,7 +214,7 @@ public: }; cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, - Visibility vis, cmMakefile* mf) + Visibility vis, cmMakefile* mf, bool perConfig) : impl(cm::make_unique()) { assert(mf); @@ -229,6 +230,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, (vis == VisibilityImported || vis == VisibilityImportedGlobally); impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally; impl->BuildInterfaceIncludesAppended = false; + impl->PerConfig = perConfig; // Check whether this is a DLL platform. impl->IsDLLPlatform = @@ -1800,6 +1802,11 @@ bool cmTarget::IsImportedGloballyVisible() const return impl->ImportedGloballyVisible; } +bool cmTarget::IsPerConfig() const +{ + return impl->PerConfig; +} + const char* cmTarget::GetSuffixVariableInternal( cmStateEnums::ArtifactType artifact) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 65a1ce3..1bfa3ce 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -44,7 +44,7 @@ public: }; cmTarget(std::string const& name, cmStateEnums::TargetType type, - Visibility vis, cmMakefile* mf); + Visibility vis, cmMakefile* mf, bool perConfig); cmTarget(cmTarget const&) = delete; cmTarget(cmTarget&&) noexcept; @@ -186,6 +186,7 @@ public: bool IsImported() const; bool IsImportedGloballyVisible() const; + bool IsPerConfig() const; bool GetMappedConfig(std::string const& desired_config, const char** loc, const char** imp, std::string& suffix) const; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index c9fe963..6bfb37e 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1919,6 +1919,7 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory()); # endif this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory()); + this->Generators.push_back(cmGlobalNinjaMultiGenerator::NewFactory()); #endif #if defined(CMAKE_USE_WMAKE) this->Generators.push_back(cmGlobalWatcomWMakeGenerator::NewFactory()); diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 2c8340c..7dbfeca 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1134,8 +1134,8 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH foreach(CPackDEBConfiguration IN LISTS DEB_CONFIGURATIONS_TO_TEST) set(CPackRun_CPackDEBConfiguration "-DCPackDEBConfiguration=${CPackDEBConfiguration}") - add_test(${DEB_TEST_NAMES}-${CPackDEBConfiguration} - ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} + add_test(NAME ${DEB_TEST_NAMES}-${CPackDEBConfiguration} COMMAND + ${CMAKE_CTEST_COMMAND} -C $ --build-and-test "${CMake_SOURCE_DIR}/Tests/${DEB_TEST_NAMES}" "${CMake_BINARY_DIR}/Tests/${DEB_TEST_NAMES}/build${CPackGen}-${CPackDEBConfiguration}" @@ -1152,6 +1152,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "-D${DEB_TEST_NAMES}_BINARY_DIR:PATH=${CMake_BINARY_DIR}/Tests/${DEB_TEST_NAMES}/build${CPackGen}-${CPackDEBConfiguration}" "${CPackRun_CPackGen}" "${CPackRun_CPackDEBConfiguration}" + "-DCONFIG=$" -P "${CMake_SOURCE_DIR}/Tests/${DEB_TEST_NAMES}/RunCPackVerifyResult-${CPackDEBConfiguration}.cmake") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/${DEB_TEST_NAMES}/build${CPackGen}-${CPackDEBConfiguration}") endforeach() @@ -1868,7 +1869,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ADD_TEST_MACRO(CheckCompilerRelatedVariables CheckCompilerRelatedVariables) if("${CMAKE_GENERATOR}" MATCHES "Makefile" OR - "${CMAKE_GENERATOR}" MATCHES "Ninja") + "${CMAKE_GENERATOR}" MATCHES "^Ninja$") add_test(MakeClean ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/MakeClean" diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake index b172da2..3bc8d2a 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake @@ -45,7 +45,7 @@ function(run_cpack output_expected_file CPack_output_parent CPack_error_parent) message("config_args = ${run_cpack_deb_CONFIG_ARGS}") message("config_verbose = ${run_cpack_deb_CONFIG_VERBOSE}") - execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${run_cpack_deb_CONFIG_VERBOSE} -G ${CPackGen} ${run_cpack_deb_CONFIG_ARGS} + execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${run_cpack_deb_CONFIG_VERBOSE} -G ${CPackGen} -C "${CONFIG}" ${run_cpack_deb_CONFIG_ARGS} RESULT_VARIABLE CPack_result OUTPUT_VARIABLE CPack_output ERROR_VARIABLE CPack_error diff --git a/Tests/FortranModules/Executable/CMakeLists.txt b/Tests/FortranModules/Executable/CMakeLists.txt index de08d86..f31a3e6 100644 --- a/Tests/FortranModules/Executable/CMakeLists.txt +++ b/Tests/FortranModules/Executable/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(${Library_MODDIR}) include_directories(${External_BINARY_DIR}) -link_directories(${External_BINARY_DIR}) +link_directories(${External_BINARY_DIR}/${CMAKE_CFG_INTDIR}) add_executable(subdir_exe2 main.f90) target_link_libraries(subdir_exe2 subdir_mods subdir_mods2) diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt index 761c405..fa3309f 100644 --- a/Tests/IncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/CMakeLists.txt @@ -94,6 +94,6 @@ if (NOT incs STREQUAL ";/one/two") message(SEND_ERROR "Empty include_directories entry was not ignored.") endif() -if(NOT CMAKE_GENERATOR STREQUAL Xcode AND NOT CMAKE_GENERATOR STREQUAL Ninja) +if(NOT CMAKE_GENERATOR STREQUAL "Xcode" AND NOT CMAKE_GENERATOR MATCHES "Ninja") add_subdirectory(CMP0021) endif() diff --git a/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt index 954c02d..311ca2a 100644 --- a/Tests/InterfaceLibrary/CMakeLists.txt +++ b/Tests/InterfaceLibrary/CMakeLists.txt @@ -3,6 +3,12 @@ cmake_minimum_required(VERSION 2.8) project(InterfaceLibrary) +set(cfg_dir) +get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(_isMultiConfig) + set(cfg_dir /$) +endif() + add_library(iface_nodepends INTERFACE) target_compile_definitions(iface_nodepends INTERFACE IFACE_DEFINE) @@ -32,7 +38,7 @@ add_library(item_iface INTERFACE IMPORTED) set_property(TARGET item_iface PROPERTY IMPORTED_LIBNAME item_real) add_dependencies(item_iface item_real) get_property(item_iface_dependencies TARGET item_iface PROPERTY MANUALLY_ADDED_DEPENDENCIES) -link_directories(${CMAKE_CURRENT_BINARY_DIR}) +link_directories(${CMAKE_CURRENT_BINARY_DIR}${cfg_dir}) add_executable(InterfaceLibrary definetestexe.cpp) target_link_libraries(InterfaceLibrary diff --git a/Tests/LinkDirectory/External/CMakeLists.txt b/Tests/LinkDirectory/External/CMakeLists.txt index d2a1f9f..c877913 100644 --- a/Tests/LinkDirectory/External/CMakeLists.txt +++ b/Tests/LinkDirectory/External/CMakeLists.txt @@ -2,13 +2,19 @@ cmake_minimum_required(VERSION 2.8) project(LinkDirectoryExternal C) +set(cfg_dir) +get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(_isMultiConfig) + set(cfg_dir /$) +endif() + add_executable(myexe2 myexe.c) set_property(TARGET myexe2 PROPERTY OUTPUT_NAME LinkDirectory2) -target_link_directories(myexe2 PRIVATE lib "${CMAKE_CURRENT_SOURCE_DIR}/../lib") +target_link_directories(myexe2 PRIVATE lib${cfg_dir} "${CMAKE_CURRENT_SOURCE_DIR}/../lib${cfg_dir}") target_link_libraries(myexe2 PRIVATE mylibA mylibB) add_library (mylibs INTERFACE) -target_link_directories(mylibs INTERFACE lib "${CMAKE_CURRENT_SOURCE_DIR}/../lib") +target_link_directories(mylibs INTERFACE lib${cfg_dir} "${CMAKE_CURRENT_SOURCE_DIR}/../lib${cfg_dir}") target_link_libraries(mylibs INTERFACE mylibA mylibB) add_executable(myexe3 myexe.c) set_property(TARGET myexe3 PROPERTY OUTPUT_NAME LinkDirectory3) @@ -17,11 +23,11 @@ target_link_libraries(myexe3 PRIVATE mylibs) # Test CMP0015 OLD behavior: -L../lib cmake_policy(SET CMP0015 OLD) -link_directories(../lib) +link_directories(../lib${cfg_dir}) # Test CMP0015 NEW behavior: -L${CMAKE_CURRENT_SOURCE_DIR}/lib cmake_policy(SET CMP0015 NEW) -link_directories(lib) +link_directories(lib${cfg_dir}) add_executable(myexe myexe.c) set_property(TARGET myexe PROPERTY OUTPUT_NAME LinkDirectory) diff --git a/Tests/OutDir/CMakeLists.txt b/Tests/OutDir/CMakeLists.txt index 823ab08..8afe036 100644 --- a/Tests/OutDir/CMakeLists.txt +++ b/Tests/OutDir/CMakeLists.txt @@ -20,7 +20,7 @@ set(top "${OutDir_BINARY_DIR}") foreach(config ${configs}) foreach(type archive runtime library) string(TOUPPER "${type}" TYPE) - set(CMAKE_${TYPE}_OUTPUT_DIRECTORY_${config} "${top}/${type}") + set(CMAKE_${TYPE}_OUTPUT_DIRECTORY_${config} "${top}/${type}/$") file(REMOVE_RECURSE "${top}/${type}") endforeach() endforeach() @@ -29,7 +29,7 @@ add_subdirectory(../COnly COnly) add_custom_command( OUTPUT OutDir.h - COMMAND ${CMAKE_COMMAND} -Dtop=${top} -P ${OutDir_SOURCE_DIR}/OutDir.cmake + COMMAND ${CMAKE_COMMAND} -Dtop=${top} -Dcfg_dir=$ -P ${OutDir_SOURCE_DIR}/OutDir.cmake DEPENDS COnly ${OutDir_SOURCE_DIR}/OutDir.cmake ) include_directories(${top}) diff --git a/Tests/OutDir/OutDir.cmake b/Tests/OutDir/OutDir.cmake index a1f13e7..2a003b8 100644 --- a/Tests/OutDir/OutDir.cmake +++ b/Tests/OutDir/OutDir.cmake @@ -3,17 +3,17 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a" ".so" ".sl" ".dylib" ".dll.a") find_library(TESTC1_LIB NAMES testc1 testc1_test_debug_postfix - PATHS ${top}/archive + PATHS ${top}/archive/${cfg_dir} NO_DEFAULT_PATH) find_library(TESTC2_LIB NAMES testc2 testc2_test_debug_postfix - PATHS ${top}/archive ${top}/library + PATHS ${top}/archive/${cfg_dir} ${top}/library/${cfg_dir} NO_DEFAULT_PATH) find_program(CONLY_EXE NAMES COnly - PATHS ${top}/runtime + PATHS ${top}/runtime/${cfg_dir} NO_DEFAULT_PATH) file(RELATIVE_PATH TESTC1_LIB_FILE "${top}" "${TESTC1_LIB}") diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 004dee6..6e1e778 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -125,7 +125,7 @@ endif() if(CMAKE_GENERATOR MATCHES "Make") add_RunCMake_test(Make -DMAKE_IS_GNU=${MAKE_IS_GNU}) endif() -if(CMAKE_GENERATOR STREQUAL "Ninja") +if(CMAKE_GENERATOR MATCHES "Ninja") set(Ninja_ARGS -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION} -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX} diff --git a/Tests/RunCMake/CPack/CPackTestHelpers.cmake b/Tests/RunCMake/CPack/CPackTestHelpers.cmake index f65cb9d..24f54c6 100644 --- a/Tests/RunCMake/CPack/CPackTestHelpers.cmake +++ b/Tests/RunCMake/CPack/CPackTestHelpers.cmake @@ -75,7 +75,7 @@ function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACK if(package_target) set(cpack_command_ ${CMAKE_COMMAND} --build "${RunCMake_TEST_BINARY_DIR}" --target package) else() - set(cpack_command_ ${CMAKE_CPACK_COMMAND} ${pack_params_}) + set(cpack_command_ ${CMAKE_CPACK_COMMAND} ${pack_params_} -C Debug) endif() # execute cpack diff --git a/Tests/RunCMake/CPack/tests/EXTERNAL/expected-json-1.0.txt b/Tests/RunCMake/CPack/tests/EXTERNAL/expected-json-1.0.txt index 18bf617..ca25b1e 100644 --- a/Tests/RunCMake/CPack/tests/EXTERNAL/expected-json-1.0.txt +++ b/Tests/RunCMake/CPack/tests/EXTERNAL/expected-json-1.0.txt @@ -1,5 +1,6 @@ ^\{ - "componentGroups" :[ ] + ("buildConfig" : "Debug", +)? "componentGroups" :[ ] \{ "f12" :[ ] \{ diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake index f86e8ea..e9543f1 100644 --- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake @@ -9,7 +9,7 @@ function(run_compiler_launcher lang) run_cmake(${lang}) set(RunCMake_TEST_OUTPUT_MERGE 1) - if("${RunCMake_GENERATOR}" STREQUAL "Ninja") + if("${RunCMake_GENERATOR}" MATCHES "Ninja") set(verbose_args -- -v) endif() run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build . ${verbose_args}) diff --git a/Tests/RunCMake/FileAPI/check_index.py b/Tests/RunCMake/FileAPI/check_index.py index 23b02e9..20243c0 100644 --- a/Tests/RunCMake/FileAPI/check_index.py +++ b/Tests/RunCMake/FileAPI/check_index.py @@ -113,7 +113,7 @@ def check_cmake_generator(g): assert is_string(g["platform"]) else: assert sorted(g.keys()) == ["multiConfig", "name"] - assert is_bool(g["multiConfig"], matches(name, "^(Visual Studio |Xcode$)")) + assert is_bool(g["multiConfig"], matches(name, "^(Visual Studio |Xcode$|Ninja Multi-Config$)")) def check_index_object(indexEntry, kind, major, minor, check): assert is_dict(indexEntry) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 66c559d..de6253f 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -621,12 +621,12 @@ def gen_check_directories(c, g): }, ] - if matches(g, "^Visual Studio "): + if matches(g["name"], "^Visual Studio "): for e in expected: if e["parentSource"] is not None: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^ZERO_CHECK"), e["targetIds"]) - elif g == "Xcode": + elif g["name"] == "Xcode": if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""): for e in expected: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(link_imported_object_exe)"), e["targetIds"]) @@ -5087,13 +5087,13 @@ def gen_check_targets(c, g, inSource): for s in e["sources"]: s["path"] = s["path"].replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) if e["sourceGroups"] is not None: - for g in e["sourceGroups"]: - g["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in g["sourcePaths"]] + for group in e["sourceGroups"]: + group["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in group["sourcePaths"]] if e["compileGroups"] is not None: - for g in e["compileGroups"]: - g["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in g["sourcePaths"]] + for group in e["compileGroups"]: + group["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in group["sourcePaths"]] - if matches(g, "^Visual Studio "): + if matches(g["name"], "^Visual Studio "): expected = filter_list(lambda e: e["name"] not in ("ZERO_CHECK") or e["id"] == "^ZERO_CHECK::@6890427a1f51a3e7e1df$", expected) for e in expected: if e["type"] == "UTILITY": @@ -5130,7 +5130,7 @@ def gen_check_targets(c, g, inSource): if matches(d["id"], "^\\^ZERO_CHECK::@"): d["id"] = "^ZERO_CHECK::@6890427a1f51a3e7e1df$" - elif g == "Xcode": + elif g["name"] == "Xcode": if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""): expected = filter_list(lambda e: e["name"] not in ("link_imported_object_exe"), expected) for e in expected: @@ -5286,12 +5286,12 @@ def gen_check_projects(c, g): }, ] - if matches(g, "^Visual Studio "): + if matches(g["name"], "^Visual Studio "): for e in expected: if e["parentName"] is not None: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^ZERO_CHECK"), e["targetIds"]) - elif g == "Xcode": + elif g["name"] == "Xcode": if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""): for e in expected: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(link_imported_object_exe)"), e["targetIds"]) @@ -5327,7 +5327,7 @@ def check_object_codemodel(g): inSource = os.path.dirname(o["paths"]["build"]) == o["paths"]["source"] - if matches(g, "^(Visual Studio |Xcode$)"): + if g["multiConfig"]: assert sorted([c["name"] for c in o["configurations"]]) == ["Debug", "MinSizeRel", "RelWithDebInfo", "Release"] else: assert len(o["configurations"]) == 1 @@ -5339,4 +5339,4 @@ def check_object_codemodel(g): assert is_dict(index) assert sorted(index.keys()) == ["cmake", "objects", "reply"] -check_objects(index["objects"], index["cmake"]["generator"]["name"]) +check_objects(index["objects"], index["cmake"]["generator"]) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 808a872..a00d830 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -1,5 +1,8 @@ include(RunCMake) +set(RunCMake_GENERATOR "Ninja") +set(RunCMake_GENERATOR_IS_MULTI_CONFIG 0) + # Detect ninja version so we know what tests can be supported. execute_process( COMMAND "${RunCMake_MAKE_PROGRAM}" --version diff --git a/Tests/RunCMake/RuntimePath/Relative.cmake b/Tests/RunCMake/RuntimePath/Relative.cmake index 203241f..80ed189 100644 --- a/Tests/RunCMake/RuntimePath/Relative.cmake +++ b/Tests/RunCMake/RuntimePath/Relative.cmake @@ -1,5 +1,12 @@ enable_language(C) +set(cfg_up) +set(cfg_slash /) +if(cfg_dir) + set(cfg_up /..) + set(cfg_slash) +endif() + if(NOT CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN) if(CMAKE_C_PLATFORM_ID STREQUAL "Linux") # Sanity check for platform that is definitely known to support $ORIGIN. @@ -45,25 +52,25 @@ CheckRpath(main "\$ORIGIN") add_executable(main-norel main.c) target_link_libraries(main-norel utils) set_property(TARGET main-norel PROPERTY BUILD_RPATH_USE_ORIGIN OFF) -CheckRpath(main-norel "${CMAKE_CURRENT_BINARY_DIR}") +CheckRpath(main-norel "${CMAKE_CURRENT_BINARY_DIR}${cfg_dir}") add_executable(mainsub main.c) target_link_libraries(mainsub utils) set_property(TARGET mainsub PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) -CheckRpath(mainsub "\$ORIGIN/../") +CheckRpath(mainsub "\$ORIGIN${cfg_up}/..${cfg_dir}${cfg_slash}") add_executable(main-sub main.c) target_link_libraries(main-sub utils-sub) -CheckRpath(main-sub "\$ORIGIN/libs") +CheckRpath(main-sub "\$ORIGIN${cfg_up}/libs${cfg_dir}") add_executable(mainsub-sub main.c) target_link_libraries(mainsub-sub utils-sub) set_property(TARGET mainsub-sub PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) -CheckRpath(mainsub-sub "\$ORIGIN/../libs") +CheckRpath(mainsub-sub "\$ORIGIN${cfg_up}/../libs${cfg_dir}") if(externDir) # Binaries linking to libraries outside the build tree should have an absolute RPATH. add_executable(main-extern main.c) target_link_libraries(main-extern utils-extern) - CheckRpath(main-extern "${externDir}") + CheckRpath(main-extern "${externDir}${cfg_dir}") endif() diff --git a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake index 4c9ddcd..ad446e9 100644 --- a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake +++ b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake @@ -6,7 +6,9 @@ function(run_RuntimePath name) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) set(RunCMake_TEST_NO_CLEAN 1) if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) - set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + set(RunCMake_TEST_OPTIONS -Dcfg_dir= -DCMAKE_BUILD_TYPE=Debug) + else() + set(RunCMake_TEST_OPTIONS -Dcfg_dir=/$) endif() file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") @@ -14,12 +16,16 @@ function(run_RuntimePath name) run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug) endfunction() +set(cfg_dir) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(cfg_dir /Debug) +endif() + run_RuntimePath(SymlinkImplicit) run_cmake_command(SymlinkImplicitCheck - ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) + ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -Dcfg_dir=${cfg_dir} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) run_RuntimePath(Relative) -# FIXME: Run RelativeCheck (appears to be broken currently) run_RuntimePath(Genex) run_cmake_command(GenexCheck diff --git a/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake index d34742e..4f50d4b 100644 --- a/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake +++ b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake @@ -1,2 +1,2 @@ -file(COPY ${dir}/bin/exe DESTINATION ${dir}) +file(COPY ${dir}/bin${cfg_dir}/exe DESTINATION ${dir}) file(RPATH_CHANGE FILE "${dir}/exe" OLD_RPATH "${dir}/libLink" NEW_RPATH "old-should-not-exist") diff --git a/Tests/RunCMake/add_link_options/LINKER_expansion-list.cmake b/Tests/RunCMake/add_link_options/LINKER_expansion-list.cmake index 34dcc67..c77b43c 100644 --- a/Tests/RunCMake/add_link_options/LINKER_expansion-list.cmake +++ b/Tests/RunCMake/add_link_options/LINKER_expansion-list.cmake @@ -11,7 +11,7 @@ string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAK add_library(example SHARED LinkOptionsLib.c) # use LAUNCH facility to dump linker command -set_property(TARGET example PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"") +set_property(TARGET example PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"") add_dependencies (example dump) diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stderr.txt b/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stderr.txt index 38566fb..206ab21 100644 --- a/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stderr.txt +++ b/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stderr.txt @@ -1 +1,2 @@ -Unable to find executable:.*MyThirdPartyDependency/src/thirdparty +Unable to find executable:.*MyThirdPartyDependency/src(/[^/ +]+)?/thirdparty diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 5db4b3b..8d1b981 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -69,7 +69,7 @@ if(NOT WIN32 OR CYGWIN) run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN) endif() -if(RunCMake_GENERATOR STREQUAL "Ninja") +if(RunCMake_GENERATOR MATCHES "Ninja") # Detect ninja version so we know what tests can be supported. execute_process( COMMAND "${RunCMake_MAKE_PROGRAM}" --version @@ -90,7 +90,7 @@ if(RunCMake_GENERATOR STREQUAL "Ninja") endif() endif() -if(RunCMake_GENERATOR STREQUAL "Ninja" AND "${ninja_version}" VERSION_LESS 1.8) +if(RunCMake_GENERATOR MATCHES "Ninja" AND "${ninja_version}" VERSION_LESS 1.8) run_cmake(GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version) else() run_cmake(GLOB-warn-CONFIGURE_DEPENDS-late) diff --git a/Tests/RunCMake/get_property/RunCMakeTest.cmake b/Tests/RunCMake/get_property/RunCMakeTest.cmake index 06a0c67..6e36473 100644 --- a/Tests/RunCMake/get_property/RunCMakeTest.cmake +++ b/Tests/RunCMake/get_property/RunCMakeTest.cmake @@ -27,7 +27,7 @@ run_cmake(NoCache) # don't rely on RunCMake_GENERATOR_IS_MULTI_CONFIG being set correctly # and instead explicitly check for a match against those generators we # expect to be multi-config -if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode") +if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode|Ninja Multi-Config") run_cmake(IsMultiConfig) else() run_cmake(NotMultiConfig) diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt index 1e123f6..2561263 100644 --- a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt @@ -1,4 +1,4 @@ -^CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\): +CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\): Policy CMP0095 is not set: RPATH entries are properly escaped in the intermediary CMake install script\. Run "cmake --help-policy CMP0095" for policy details\. Use the cmake_policy command to set the policy and @@ -20,4 +20,4 @@ CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(ins intermediary cmake_install\.cmake script\. Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\) -This warning is for project developers\. Use -Wno-dev to suppress it\.$ +This warning is for project developers\. Use -Wno-dev to suppress it\. diff --git a/Tests/RunCMake/target_link_options/LINKER_expansion.cmake b/Tests/RunCMake/target_link_options/LINKER_expansion.cmake index b344867..f86d19f 100644 --- a/Tests/RunCMake/target_link_options/LINKER_expansion.cmake +++ b/Tests/RunCMake/target_link_options/LINKER_expansion.cmake @@ -1,6 +1,13 @@ enable_language(C) +set(cfg_dir) +get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(_isMultiConfig) + set(cfg_dir /Debug) +endif() +set(DUMP_EXE "${CMAKE_CURRENT_BINARY_DIR}${cfg_dir}/dump${CMAKE_EXECUTABLE_SUFFIX}") + add_executable(dump dump.c) # ensure no temp file will be used @@ -13,7 +20,7 @@ add_library(linker SHARED LinkOptionsLib.c) target_link_options(linker PRIVATE "LINKER:-foo,bar") # use LAUNCH facility to dump linker command -set_property(TARGET linker PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"") +set_property(TARGET linker PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"") add_dependencies (linker dump) @@ -23,7 +30,7 @@ add_library(linker_shell SHARED LinkOptionsLib.c) target_link_options(linker_shell PRIVATE "LINKER:SHELL:-foo bar") # use LAUNCH facility to dump linker command -set_property(TARGET linker_shell PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"") +set_property(TARGET linker_shell PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"") add_dependencies (linker_shell dump) -- cgit v0.12 From e0478cc64623fbfcb7dcd748f27b94cc8473fa1a Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 27 Nov 2019 10:59:20 -0500 Subject: Tests: Add test for Multi-Configuration Ninja generator --- Tests/CMakeLists.txt | 13 +- Tests/RunCMake/CMakeLists.txt | 7 + ...dditionalCleanFiles-all-clean-ninja-check.cmake | 4 + .../AdditionalCleanFiles-check.cmake | 8 + ...ionalCleanFiles-release-clean-build-check.cmake | 6 + .../NinjaMultiConfig/AdditionalCleanFiles.cmake | 3 + .../NinjaMultiConfig/AutoMocExecutable.cmake | 10 ++ Tests/RunCMake/NinjaMultiConfig/CMakeLists.txt | 3 + .../Clean-release-build-check.cmake | 16 ++ .../Clean-release-clean-build-check.cmake | 7 + .../Clean-release-notall-ninja-check.cmake | 16 ++ Tests/RunCMake/NinjaMultiConfig/Clean.cmake | 17 ++ Tests/RunCMake/NinjaMultiConfig/Common.cmake | 57 +++++++ .../CustomCommandGenerator-debug-build-check.cmake | 38 +++++ ...mCommandGenerator-debug-clean-ninja-check.cmake | 37 +++++ ...stomCommandGenerator-debug-generated-stdout.txt | 12 ++ ...erator-debug-in-release-graph-build-check.cmake | 44 ++++++ ...-debug-in-release-graph-clean-ninja-check.cmake | 36 +++++ ...tor-debug-in-release-graph-generated-stdout.txt | 12 ++ ...ommandGenerator-release-clean-build-check.cmake | 29 ++++ ...omCommandGenerator-release-generated-stdout.txt | 12 ++ ...tor-release-in-debug-graph-generated-stdout.txt | 12 ++ ...erator-release-in-debug-graph-ninja-check.cmake | 45 ++++++ ...ustomCommandGenerator-release-ninja-check.cmake | 46 ++++++ .../NinjaMultiConfig/CustomCommandGenerator.cmake | 56 +++++++ ...mandsAndTargets-debug-command-ninja-check.cmake | 6 + ...ug-in-release-graph-postbuild-build-check.cmake | 8 + ...mmandsAndTargets-debug-target-build-check.cmake | 8 + ...Targets-debug-targetpostbuild-build-check.cmake | 12 ++ ...AndTargets-minsizerel-command-ninja-check.cmake | 5 + ...ndsAndTargets-release-command-build-check.cmake | 5 + ...sAndTargets-release-postbuild-ninja-check.cmake | 11 ++ ...andsAndTargets-release-target-ninja-check.cmake | 7 + ...rgets-release-targetpostbuild-ninja-check.cmake | 13 ++ .../CustomCommandsAndTargets.cmake | 39 +++++ .../CustomCommandsAndTargetsSubdir/CMakeLists.txt | 1 + ...ebug-in-release-graph-install-ninja-check.cmake | 31 ++++ .../Install-release-install-build-check.cmake | 23 +++ Tests/RunCMake/NinjaMultiConfig/Install.cmake | 10 ++ ...cation-debug-in-release-graph-build-check.cmake | 7 + ...tion-release-in-release-graph-build-check.cmake | 5 + .../NinjaMultiConfig/PostfixAndLocation.cmake | 18 +++ .../Qt5-debug-in-release-graph-build-check.cmake | 7 + Tests/RunCMake/NinjaMultiConfig/Qt5.cmake | 18 +++ Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake | 173 +++++++++++++++++++++ .../Simple-all-clean-again-ninja-check.cmake | 25 +++ .../Simple-all-clean-build-check.cmake | 25 +++ .../Simple-all-configs-build-check.cmake | 47 ++++++ .../Simple-all-subdir-build-check.cmake | 49 ++++++ .../Simple-all-top-ninja-check.cmake | 56 +++++++ ...le-debug-in-release-graph-top-build-check.cmake | 53 +++++++ .../Simple-debug-subdir-build-check.cmake | 31 ++++ .../Simple-debug-target-build-check.cmake | 31 ++++ .../Simple-debug-target-ninja-check.cmake | 33 ++++ .../Simple-default-build-file-ninja-check.cmake | 51 ++++++ .../Simple-minsizerel-top-ninja-check.cmake | 51 ++++++ .../Simple-reconfigure-config-ninja-stdout.txt | 4 + .../Simple-reconfigure-noconfig-ninja-stdout.txt | 4 + .../Simple-release-file-ninja-check.cmake | 39 +++++ .../Simple-release-filename-build-check.cmake | 36 +++++ ...se-in-minsizerel-graph-subdir-ninja-check.cmake | 37 +++++ Tests/RunCMake/NinjaMultiConfig/Simple.cmake | 13 ++ .../NinjaMultiConfig/SimpleSubdir/CMakeLists.txt | 4 + Tests/RunCMake/NinjaMultiConfig/WriteFile.cmake | 1 + Tests/RunCMake/NinjaMultiConfig/badmoc.c | 7 + Tests/RunCMake/NinjaMultiConfig/empty.c | 0 Tests/RunCMake/NinjaMultiConfig/generator.c | 101 ++++++++++++ Tests/RunCMake/NinjaMultiConfig/generatorlib.c | 24 +++ Tests/RunCMake/NinjaMultiConfig/generatorobj.c | 24 +++ Tests/RunCMake/NinjaMultiConfig/main.c | 4 + Tests/RunCMake/NinjaMultiConfig/qt5.cxx | 9 ++ Tests/RunCMake/NinjaMultiConfig/qt5.h | 5 + Tests/RunCMake/NinjaMultiConfig/simplelib.c | 6 + 73 files changed, 1717 insertions(+), 6 deletions(-) create mode 100644 Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-all-clean-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-release-clean-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/AutoMocExecutable.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CMakeLists.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/Clean-release-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Clean-release-clean-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Clean-release-notall-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Clean.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Common.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-generated-stdout.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-generated-stdout.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-clean-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-generated-stdout.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-generated-stdout.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-command-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-in-release-graph-postbuild-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-target-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-targetpostbuild-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-minsizerel-command-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-command-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-postbuild-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-target-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-targetpostbuild-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargetsSubdir/CMakeLists.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/Install-debug-in-release-graph-install-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Install-release-install-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Install.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-debug-in-release-graph-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-release-in-release-graph-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Qt5.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-again-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-all-configs-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-config-ninja-stdout.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-noconfig-ninja-stdout.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-release-file-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-release-filename-build-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/WriteFile.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/badmoc.c create mode 100644 Tests/RunCMake/NinjaMultiConfig/empty.c create mode 100644 Tests/RunCMake/NinjaMultiConfig/generator.c create mode 100644 Tests/RunCMake/NinjaMultiConfig/generatorlib.c create mode 100644 Tests/RunCMake/NinjaMultiConfig/generatorobj.c create mode 100644 Tests/RunCMake/NinjaMultiConfig/main.c create mode 100644 Tests/RunCMake/NinjaMultiConfig/qt5.cxx create mode 100644 Tests/RunCMake/NinjaMultiConfig/qt5.h create mode 100644 Tests/RunCMake/NinjaMultiConfig/simplelib.c diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 7dbfeca..59f5c73 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -211,6 +211,13 @@ if(BUILD_TESTING) #--------------------------------------------------------------------------- # Add tests below here. + if(NOT DEFINED CMake_TEST_Qt5) + set(CMake_TEST_Qt5 1) + endif() + if(CMake_TEST_Qt5) + find_package(Qt5Widgets QUIET NO_MODULE) + endif() + if(NOT CMake_TEST_EXTERNAL_CMAKE) add_subdirectory(CMakeLib) @@ -1332,12 +1339,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt") - if(NOT DEFINED CMake_TEST_Qt5) - set(CMake_TEST_Qt5 1) - endif() - if(CMake_TEST_Qt5) - find_package(Qt5Widgets QUIET NO_MODULE) - endif() if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND) add_subdirectory(Qt5Autogen) endif() diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 6e1e778..10e4c6f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -134,6 +134,13 @@ if(CMAKE_GENERATOR MATCHES "Ninja") list(APPEND Ninja_ARGS -DTEST_Fortran=1) endif() add_RunCMake_test(Ninja) + set(NinjaMultiConfig_ARGS + -DCYGWIN=${CYGWIN} + ) + if(CMake_TEST_Qt5 AND Qt5Core_FOUND) + list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_Qt5=1) + endif() + add_RunCMake_test(NinjaMultiConfig) endif() add_RunCMake_test(CTest) diff --git a/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-all-clean-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-all-clean-ninja-check.cmake new file mode 100644 index 0000000..012dc2f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-all-clean-ninja-check.cmake @@ -0,0 +1,4 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + # Intentionally empty + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-check.cmake b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-check.cmake new file mode 100644 index 0000000..77412f1 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-check.cmake @@ -0,0 +1,8 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${RunCMake_TEST_BINARY_DIR}/global.txt + ${RunCMake_TEST_BINARY_DIR}/Debug.txt + ${RunCMake_TEST_BINARY_DIR}/Release.txt + ${RunCMake_TEST_BINARY_DIR}/MinSizeRel.txt + ${RunCMake_TEST_BINARY_DIR}/RelWithDebInfo.txt + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-release-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-release-clean-build-check.cmake new file mode 100644 index 0000000..f211223 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-release-clean-build-check.cmake @@ -0,0 +1,6 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${RunCMake_TEST_BINARY_DIR}/Debug.txt + ${RunCMake_TEST_BINARY_DIR}/MinSizeRel.txt + ${RunCMake_TEST_BINARY_DIR}/RelWithDebInfo.txt + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles.cmake b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles.cmake new file mode 100644 index 0000000..983a494 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles.cmake @@ -0,0 +1,3 @@ +file(GENERATE OUTPUT $.txt CONTENT "$\n") +file(TOUCH ${CMAKE_BINARY_DIR}/global.txt) +set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "$.txt;global.txt") diff --git a/Tests/RunCMake/NinjaMultiConfig/AutoMocExecutable.cmake b/Tests/RunCMake/NinjaMultiConfig/AutoMocExecutable.cmake new file mode 100644 index 0000000..950e18e --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AutoMocExecutable.cmake @@ -0,0 +1,10 @@ +enable_language(C) + +add_executable(badmoc badmoc.c) +target_compile_definitions(badmoc PRIVATE "CONFIG=\"$\"") + +add_executable(exe main.c) +set_target_properties(exe PROPERTIES + AUTOMOC ON + AUTOMOC_EXECUTABLE $ + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CMakeLists.txt b/Tests/RunCMake/NinjaMultiConfig/CMakeLists.txt new file mode 100644 index 0000000..2632ffa --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/NinjaMultiConfig/Clean-release-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Clean-release-build-check.cmake new file mode 100644 index 0000000..cfe6984 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Clean-release-build-check.cmake @@ -0,0 +1,16 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_SONAME_FILE_mylib_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + + ${TARGET_OBJECT_FILES_myobj_Release} + + ${TARGET_FILE_exeall_Release} + ${TARGET_EXE_FILE_exeall_Release} + ${TARGET_OBJECT_FILES_exeall_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_exenotall_Release} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Clean-release-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Clean-release-clean-build-check.cmake new file mode 100644 index 0000000..06b3fb6 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Clean-release-clean-build-check.cmake @@ -0,0 +1,7 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + EXCLUDE + ${TARGET_OBJECT_FILES_exeall_Release} + ${TARGET_OBJECT_FILES_exenotall_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + ${TARGET_OBJECT_FILES_myobj_Release} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Clean-release-notall-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Clean-release-notall-ninja-check.cmake new file mode 100644 index 0000000..42d6a78 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Clean-release-notall-ninja-check.cmake @@ -0,0 +1,16 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_SONAME_FILE_mylib_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + + ${TARGET_OBJECT_FILES_myobj_Release} + + ${TARGET_FILE_exeall_Release} + ${TARGET_EXE_FILE_exeall_Release} + ${TARGET_OBJECT_FILES_exeall_Release} + + ${TARGET_FILE_exenotall_Release} + ${TARGET_OBJECT_FILES_exenotall_Release} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Clean.cmake b/Tests/RunCMake/NinjaMultiConfig/Clean.cmake new file mode 100644 index 0000000..2258d2b --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Clean.cmake @@ -0,0 +1,17 @@ +enable_language(C) + +add_executable(exeall main.c) +set_target_properties(exeall PROPERTIES VERSION 1.0.0) +add_executable(exenotall main.c) +set_target_properties(exenotall PROPERTIES EXCLUDE_FROM_ALL TRUE) + +add_library(mylib SHARED simplelib.c) +set_target_properties(mylib PROPERTIES + VERSION 1.0.0 + SOVERSION 1 + ) + +add_library(myobj OBJECT simplelib.c) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(exeall exenotall mylib myobj) diff --git a/Tests/RunCMake/NinjaMultiConfig/Common.cmake b/Tests/RunCMake/NinjaMultiConfig/Common.cmake new file mode 100644 index 0000000..e13bd53 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Common.cmake @@ -0,0 +1,57 @@ +function(generate_output_files) + set(content) + foreach(tgt IN LISTS ARGN) + get_property(type TARGET ${tgt} PROPERTY TYPE) + + if(NOT type STREQUAL "OBJECT_LIBRARY") + set(file " [==[$]==]") + set(filename " [==[$]==]") + else() + set(file) + set(filename) + endif() + string(APPEND content "set(TARGET_FILE_${tgt}_$${file})\n") + string(APPEND content "set(TARGET_FILE_NAME_${tgt}_$${filename})\n") + + if(type MATCHES "^(STATIC|MODULE|SHARED)_LIBRARY$") + set(linker_file " [==[$]==]") + set(linker_filename " [==[$]==]") + else() + set(linker_file) + set(linker_filename) + endif() + string(APPEND content "set(TARGET_LINKER_FILE_${tgt}_$${linker_file})\n") + string(APPEND content "set(TARGET_LINKER_FILE_NAME_${tgt}_$${linker_filename})\n") + + if(NOT WIN32 AND NOT CYGWIN AND type MATCHES "^(SHARED_LIBRARY)$") + set(soname_file " [==[$]==]") + set(soname_filename " [==[$]==]") + else() + set(soname_file) + set(soname_filename) + endif() + string(APPEND content "set(TARGET_SONAME_FILE_${tgt}_$${soname_file})\n") + string(APPEND content "set(TARGET_SONAME_FILE_NAME_${tgt}_$${soname_filename})\n") + + if(type MATCHES "^(EXECUTABLE)$") + set(exe_file " [==[$/$$$]==]") + set(exe_filename " [==[$$$]==]") + else() + set(exe_file) + set(exe_filename) + endif() + string(APPEND content "set(TARGET_EXE_FILE_${tgt}_$${exe_file})\n") + string(APPEND content "set(TARGET_EXE_FILE_NAME_${tgt}_$${exe_filename})\n") + + string(APPEND content "set(TARGET_OBJECT_FILES_${tgt}_$ [==[$]==])\n") + endforeach() + + file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/target_files_$.cmake" CONTENT "${content}") + + set(content) + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) + string(APPEND content "include(\${CMAKE_CURRENT_LIST_DIR}/target_files_${config}.cmake)\n") + endforeach() + + file(WRITE "${CMAKE_BINARY_DIR}/target_files.cmake" "${content}") +endfunction() diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-build-check.cmake new file mode 100644 index 0000000..2abdb43 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-build-check.cmake @@ -0,0 +1,38 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + ${GENERATED_FILES} + + ${TARGET_FILE_generator_Debug} + ${TARGET_OBJECT_FILES_generator_Debug} + + ${TARGET_FILE_generated_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + + ${TARGET_FILE_generatorlib_Debug} + ${TARGET_LINKER_FILE_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + + ${TARGET_OBJECT_FILES_generatorobj_Debug} + + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Release} + ${TARGET_OBJECT_FILES_generated_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorobj_Release} + ${TARGET_OBJECT_FILES_emptyobj_Release} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-ninja-check.cmake new file mode 100644 index 0000000..aff42c3 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-ninja-check.cmake @@ -0,0 +1,37 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generated_Release} + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorobj_Debug} + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-generated-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-generated-stdout.txt new file mode 100644 index 0000000..765d486 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-generated-stdout.txt @@ -0,0 +1,12 @@ +^Generator genex config definition: Debug +Generator genex config include dir: Debug +Generator library genex config definition: Debug +Generator library genex config include dir: Debug +Generator object genex config definition: Debug +Generator object genex config include dir: Debug +Generated genex config definition: Debug +Generated genex config include dir: Debug +Generated library genex config definition: Debug +Generated library genex config include dir: Debug +Generated object genex config definition: Debug +Generated object genex config include dir: Debug$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-build-check.cmake new file mode 100644 index 0000000..f534319 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-build-check.cmake @@ -0,0 +1,44 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + ${GENERATED_FILES} + + ${TARGET_FILE_generated_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + + ${TARGET_FILE_generatorlib_Debug} + ${TARGET_LINKER_FILE_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + + ${TARGET_OBJECT_FILES_generatorobj_Debug} + + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Debug} + + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake new file mode 100644 index 0000000..5e30bfe --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake @@ -0,0 +1,36 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorobj_Debug} + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-generated-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-generated-stdout.txt new file mode 100644 index 0000000..1c9abef --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-generated-stdout.txt @@ -0,0 +1,12 @@ +^Generator genex config definition: Release +Generator genex config include dir: Release +Generator library genex config definition: Release +Generator library genex config include dir: Release +Generator object genex config definition: Release +Generator object genex config include dir: Release +Generated genex config definition: Debug +Generated genex config include dir: Debug +Generated library genex config definition: Debug +Generated library genex config include dir: Debug +Generated object genex config definition: Debug +Generated object genex config include dir: Debug$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-clean-build-check.cmake new file mode 100644 index 0000000..8ba6d68 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-clean-build-check.cmake @@ -0,0 +1,29 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorobj_Debug} + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_OBJECT_FILES_generator_Release} + ${TARGET_OBJECT_FILES_generated_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorobj_Release} + ${TARGET_OBJECT_FILES_emptyobj_Release} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-generated-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-generated-stdout.txt new file mode 100644 index 0000000..576ec51 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-generated-stdout.txt @@ -0,0 +1,12 @@ +^Generator genex config definition: Release +Generator genex config include dir: Release +Generator library genex config definition: Release +Generator library genex config include dir: Release +Generator object genex config definition: Release +Generator object genex config include dir: Release +Generated genex config definition: Release +Generated genex config include dir: Release +Generated library genex config definition: Release +Generated library genex config include dir: Release +Generated object genex config definition: Release +Generated object genex config include dir: Release$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-generated-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-generated-stdout.txt new file mode 100644 index 0000000..25392af --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-generated-stdout.txt @@ -0,0 +1,12 @@ +^Generator genex config definition: Debug +Generator genex config include dir: Debug +Generator library genex config definition: Debug +Generator library genex config include dir: Debug +Generator object genex config definition: Debug +Generator object genex config include dir: Debug +Generated genex config definition: Release +Generated genex config include dir: Release +Generated library genex config definition: Release +Generated library genex config include dir: Release +Generated object genex config definition: Release +Generated object genex config include dir: Release$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-ninja-check.cmake new file mode 100644 index 0000000..9500cda --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-ninja-check.cmake @@ -0,0 +1,45 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + ${GENERATED_FILES} + + ${TARGET_FILE_generator_Debug} + ${TARGET_OBJECT_FILES_generator_Debug} + + ${TARGET_FILE_generatorlib_Debug} + ${TARGET_LINKER_FILE_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + + ${TARGET_OBJECT_FILES_generatorobj_Debug} + + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generated_Release} + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generated_Debug} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-ninja-check.cmake new file mode 100644 index 0000000..b51a6a7 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-ninja-check.cmake @@ -0,0 +1,46 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + ${GENERATED_FILES} + + ${TARGET_FILE_generator_Debug} + ${TARGET_OBJECT_FILES_generator_Debug} + + ${TARGET_FILE_generated_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + + ${TARGET_FILE_generatorlib_Debug} + ${TARGET_LINKER_FILE_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + + ${TARGET_OBJECT_FILES_generatorobj_Debug} + + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generated_Release} + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator.cmake new file mode 100644 index 0000000..f4aca5e --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator.cmake @@ -0,0 +1,56 @@ +enable_language(C) + +add_library(generatorlib STATIC generatorlib.c) +add_library(generatorobj OBJECT generatorobj.c) +add_library(emptyobj OBJECT empty.c) +add_library(emptyobj2 OBJECT empty.c) + +add_executable(generator generator.c $) +target_link_libraries(generator PRIVATE generatorlib) + +add_custom_command(OUTPUT generated.c COMMAND generator generated.c) +add_executable(generated ${CMAKE_BINARY_DIR}/generated.c $ $) +target_link_libraries(generated PRIVATE generatorlib) + +file(GENERATE OUTPUT include/genex/$/genex_config.h CONTENT +"#ifndef GENEX_CONFIG_H +#define GENEX_CONFIG_H + +#define GENEX_CONFIG_INCLUDE_DIR \"$\" + +#endif /* GENEX_CONFIG_H */ +") +file(GENERATE OUTPUT include/intdir/$/intdir_config.h CONTENT +"#ifndef INTDIR_CONFIG_H +#define INTDIR_CONFIG_H + +#define INTDIR_CONFIG_INCLUDE_DIR \"$\" + +#endif /* INTDIR_CONFIG_H */ +") + +foreach(g generatorlib generatorobj generator generated) + target_compile_definitions(${g} PRIVATE + "GENEX_CONFIG_DEFINITION=\"$\"" + # FIXME Get this working + # "INTDIR_CONFIG_DEFINITION=\"${CMAKE_CFG_INTDIR}\"" + ) + target_include_directories(${g} PRIVATE + "${CMAKE_BINARY_DIR}/include/genex/$" + # FIXME Get this working + # "${CMAKE_BINARY_DIR}/include/intdir/${CMAKE_CFG_INTDIR}" + ) +endforeach() + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(generatorlib generatorobj emptyobj generator generated) + +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(GENERATED_FILES [==[${CMAKE_BINARY_DIR}/generated.c]==])\n") +set(genfiles) +foreach(cfg Debug Release MinSizeRel RelWithDebInfo) + list(APPEND genfiles + ${CMAKE_BINARY_DIR}/include/genex/${cfg}/genex_config.h + ${CMAKE_BINARY_DIR}/include/intdir/${cfg}/intdir_config.h + ) +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(CONFIG_FILES [==[${genfiles}]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-command-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-command-ninja-check.cmake new file mode 100644 index 0000000..f5c4020 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-command-ninja-check.cmake @@ -0,0 +1,6 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ) +check_file_contents("${TARGET_DEPENDS_TopCommand}" "^Genex config: Debug\nINTDIR config: Debug\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-in-release-graph-postbuild-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-in-release-graph-postbuild-build-check.cmake new file mode 100644 index 0000000..05861b2 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-in-release-graph-postbuild-build-check.cmake @@ -0,0 +1,8 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ${TARGET_FILE_SubdirPostBuild_Debug} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-target-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-target-build-check.cmake new file mode 100644 index 0000000..52895b2 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-target-build-check.cmake @@ -0,0 +1,8 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ) +check_file_contents("${TARGET_BYPRODUCTS_TopTarget}" "^Genex config: Debug\nINTDIR config: Debug\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-targetpostbuild-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-targetpostbuild-build-check.cmake new file mode 100644 index 0000000..80439ea --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-targetpostbuild-build-check.cmake @@ -0,0 +1,12 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ${TARGET_FILE_SubdirPostBuild_Debug} + ${TARGET_FILE_SubdirPostBuild_Release} + ${TARGET_BYPRODUCTS_SubdirPostBuild} + ${TARGET_BYPRODUCTS_TopTargetPostBuild} + ) +check_file_contents("${TARGET_BYPRODUCTS_TopTargetPostBuild}" "^Genex config: Debug\nINTDIR config: Debug\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-minsizerel-command-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-minsizerel-command-ninja-check.cmake new file mode 100644 index 0000000..2813f02 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-minsizerel-command-ninja-check.cmake @@ -0,0 +1,5 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ) +check_file_contents("${TARGET_DEPENDS_SubdirCommand}" "^Genex config: MinSizeRel\nINTDIR config: MinSizeRel\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-command-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-command-build-check.cmake new file mode 100644 index 0000000..2da9735 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-command-build-check.cmake @@ -0,0 +1,5 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ) +check_file_contents("${TARGET_DEPENDS_SubdirCommand}" "^Genex config: Release\nINTDIR config: Release\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-postbuild-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-postbuild-ninja-check.cmake new file mode 100644 index 0000000..0916b90 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-postbuild-ninja-check.cmake @@ -0,0 +1,11 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ${TARGET_FILE_SubdirPostBuild_Debug} + ${TARGET_FILE_SubdirPostBuild_Release} + ${TARGET_BYPRODUCTS_SubdirPostBuild} + ) +check_file_contents("${TARGET_BYPRODUCTS_SubdirPostBuild}" "^Genex config: Release\nINTDIR config: Release\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-target-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-target-ninja-check.cmake new file mode 100644 index 0000000..87e78b4 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-target-ninja-check.cmake @@ -0,0 +1,7 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ) +check_file_contents("${TARGET_BYPRODUCTS_SubdirTarget}" "^Genex config: Release\nINTDIR config: Release\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-targetpostbuild-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-targetpostbuild-ninja-check.cmake new file mode 100644 index 0000000..f67d5be --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-targetpostbuild-ninja-check.cmake @@ -0,0 +1,13 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ${TARGET_FILE_SubdirPostBuild_Debug} + ${TARGET_FILE_SubdirPostBuild_Release} + ${TARGET_BYPRODUCTS_SubdirPostBuild} + ${TARGET_BYPRODUCTS_TopTargetPostBuild} + ${TARGET_BYPRODUCTS_SubdirTargetPostBuild} + ) +check_file_contents("${TARGET_BYPRODUCTS_SubdirTargetPostBuild}" "^Genex config: Release\nINTDIR config: Release\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets.cmake new file mode 100644 index 0000000..b2b24e8 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets.cmake @@ -0,0 +1,39 @@ +enable_language(C) + +file(REMOVE "${CMAKE_BINARY_DIR}/target_files_custom.cmake") + +function(get_write_file_command var filename) + set(${var} ${CMAKE_COMMAND} -DOUTPUT_FILE=${filename} -DGENEX_CONFIG=$ -DINTDIR_CONFIG=${CMAKE_CFG_INTDIR} -P ${CMAKE_SOURCE_DIR}/WriteFile.cmake PARENT_SCOPE) +endfunction() + +function(create_targets prefix) + get_write_file_command(cmd ${prefix}Command.txt) + add_custom_command(OUTPUT ${prefix}Command.txt COMMAND ${cmd}) + add_custom_target(${prefix}Command DEPENDS ${prefix}Command.txt) + + get_write_file_command(cmd ${prefix}Target.txt) + add_custom_target(${prefix}Target COMMAND ${cmd} BYPRODUCTS ${prefix}Target.txt) + + get_write_file_command(cmd ${prefix}PostBuild.txt) + add_executable(${prefix}PostBuild ${CMAKE_SOURCE_DIR}/main.c) + add_custom_command(TARGET ${prefix}PostBuild COMMAND ${cmd} BYPRODUCTS ${prefix}PostBuild.txt) + + get_write_file_command(cmd ${prefix}TargetPostBuild.txt) + add_custom_target(${prefix}TargetPostBuild) + add_custom_command(TARGET ${prefix}TargetPostBuild COMMAND ${cmd} BYPRODUCTS ${prefix}TargetPostBuild.txt) + + file(APPEND "${CMAKE_BINARY_DIR}/target_files_custom.cmake" +"set(TARGET_DEPENDS_${prefix}Command [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}Command.txt]==]) +set(TARGET_BYPRODUCTS_${prefix}Target [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}Target.txt]==]) +set(TARGET_BYPRODUCTS_${prefix}PostBuild [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}PostBuild.txt]==]) +set(TARGET_BYPRODUCTS_${prefix}TargetPostBuild [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}TargetPostBuild.txt]==]) +") +endfunction() + +add_subdirectory(CustomCommandsAndTargetsSubdir) + +create_targets(Top) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(TopPostBuild SubdirPostBuild) +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "include(\${CMAKE_CURRENT_LIST_DIR}/target_files_custom.cmake)\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargetsSubdir/CMakeLists.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargetsSubdir/CMakeLists.txt new file mode 100644 index 0000000..894e3ed --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargetsSubdir/CMakeLists.txt @@ -0,0 +1 @@ +create_targets(Subdir) diff --git a/Tests/RunCMake/NinjaMultiConfig/Install-debug-in-release-graph-install-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Install-debug-in-release-graph-install-ninja-check.cmake new file mode 100644 index 0000000..bc15a25 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Install-debug-in-release-graph-install-ninja-check.cmake @@ -0,0 +1,31 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_exe_Debug} + ${TARGET_OBJECT_FILES_exe_Debug} + + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Debug} + ${TARGET_OBJECT_FILES_mylib_Debug} + + ${RunCMake_TEST_BINARY_DIR}/install/bin/Debug/${TARGET_FILE_NAME_exe_Debug} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Debug/${TARGET_FILE_NAME_mylib_Debug} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Debug/${TARGET_LINKER_FILE_NAME_mylib_Debug} + + ${TARGET_FILE_exe_Release} + ${TARGET_OBJECT_FILES_exe_Release} + + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + + ${RunCMake_TEST_BINARY_DIR}/install/bin/Release/${TARGET_FILE_NAME_exe_Release} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_FILE_NAME_mylib_Release} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_LINKER_FILE_NAME_mylib_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_exe_MinSizeRel} + ${TARGET_OBJECT_FILES_mylib_MinSizeRel} + + ${TARGET_OBJECT_FILES_exe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_mylib_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Install-release-install-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Install-release-install-build-check.cmake new file mode 100644 index 0000000..3280c89 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Install-release-install-build-check.cmake @@ -0,0 +1,23 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_exe_Release} + ${TARGET_OBJECT_FILES_exe_Release} + + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + + ${RunCMake_TEST_BINARY_DIR}/install/bin/Release/${TARGET_FILE_NAME_exe_Release} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_FILE_NAME_mylib_Release} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_LINKER_FILE_NAME_mylib_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_exe_Debug} + ${TARGET_OBJECT_FILES_mylib_Debug} + + ${TARGET_OBJECT_FILES_exe_MinSizeRel} + ${TARGET_OBJECT_FILES_mylib_MinSizeRel} + + ${TARGET_OBJECT_FILES_exe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_mylib_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Install.cmake b/Tests/RunCMake/NinjaMultiConfig/Install.cmake new file mode 100644 index 0000000..e26e3e0 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Install.cmake @@ -0,0 +1,10 @@ +enable_language(C) + +add_executable(exe main.c) +add_library(mylib STATIC simplelib.c) + +install(TARGETS exe DESTINATION bin/$) +install(TARGETS mylib DESTINATION lib/$) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(exe mylib) diff --git a/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-debug-in-release-graph-build-check.cmake new file mode 100644 index 0000000..3657b5b --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-debug-in-release-graph-build-check.cmake @@ -0,0 +1,7 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_FILE_mylib_Debug} + ${TARGET_LINKER_FILE_mylib_Debug} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-release-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-release-in-release-graph-build-check.cmake new file mode 100644 index 0000000..3345ee8 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-release-in-release-graph-build-check.cmake @@ -0,0 +1,5 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation.cmake b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation.cmake new file mode 100644 index 0000000..abef3c8 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +set(CMAKE_DEBUG_POSTFIX "_debug") + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/bin) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/lib) + +add_library(mylib SHARED simplelib.c) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(mylib) diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake new file mode 100644 index 0000000..2d8df13 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake @@ -0,0 +1,7 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${AUTOGEN_FILES} + + ${TARGET_FILE_exe_Debug} + ${TARGET_OBJECT_FILES_exe_Debug} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake b/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake new file mode 100644 index 0000000..6a80b1d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake @@ -0,0 +1,18 @@ +enable_language(CXX) + +find_package(Qt5Core REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOMOC_COMPILER_PREDEFINES OFF) + +add_executable(exe qt5.cxx) +target_link_libraries(exe PRIVATE Qt5::Core) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(exe) + +set(autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/mocs_compilation.cpp") +foreach(c IN LISTS CMAKE_CONFIGURATION_TYPES) + list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(AUTOGEN_FILES [==[${autogen_files}]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake new file mode 100644 index 0000000..4b51ddb --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -0,0 +1,173 @@ +cmake_minimum_required(VERSION 3.16) + +include(RunCMake) + +set(RunCMake_GENERATOR "Ninja Multi-Config") +set(RunCMake_GENERATOR_IS_MULTI_CONFIG 1) + +function(check_files dir) + cmake_parse_arguments(_check_files "" "" "INCLUDE;EXCLUDE" ${ARGN}) + + set(expected ${_check_files_INCLUDE}) + list(FILTER expected EXCLUDE REGEX "^$") + list(REMOVE_DUPLICATES expected) + list(SORT expected) + + file(GLOB_RECURSE actual "${dir}/*") + list(FILTER actual EXCLUDE REGEX "/CMakeFiles/|\\.ninja$|/CMakeCache\\.txt$|/target_files[^/]*\\.cmake$|/\\.ninja_[^/]*$|/cmake_install\\.cmake$|\\.ilk$|\\.manifest$|\\.pdb$|\\.exp$|/install_manifest\\.txt$") + foreach(f IN LISTS _check_files_INCLUDE _check_files_EXCLUDE) + if(EXISTS ${f}) + list(APPEND actual ${f}) + endif() + endforeach() + list(REMOVE_DUPLICATES actual) + list(SORT actual) + + if(NOT "${expected}" STREQUAL "${actual}") + string(REPLACE ";" "\n " expected_formatted "${expected}") + string(REPLACE ";" "\n " actual_formatted "${actual}") + string(APPEND RunCMake_TEST_FAILED "Actual files did not match expected\nExpected:\n ${expected_formatted}\nActual:\n ${actual_formatted}\n") + endif() + + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) +endfunction() + +function(check_file_contents filename expected) + if(NOT EXISTS "${filename}") + string(APPEND RunCMake_TEST_FAILED "File ${filename} does not exist\n") + else() + file(READ "${filename}" actual) + if(NOT actual MATCHES "${expected}") + string(REPLACE "\n" "\n " expected_formatted "${expected}") + string(REPLACE "\n" "\n " actual_formatted "${actual}") + string(APPEND RunCMake_TEST_FAILED "Contents of ${filename} do not match expected\nExpected:\n ${expected_formatted}\nActual:\n ${actual_formatted}\n") + endif() + endif() + + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) +endfunction() + +function(run_cmake_configure case) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(${case}) +endfunction() + +function(run_cmake_build case suffix config) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + set(RunCMake_TEST_NO_CLEAN 1) + set(tgts) + foreach(tgt IN LISTS ARGN) + list(APPEND tgts --target ${tgt}) + endforeach() + run_cmake_command(${case}-${suffix}-build "${CMAKE_COMMAND}" --build . --config ${config} ${tgts}) +endfunction() + +function(run_ninja case suffix file) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${case}-${suffix}-ninja "${RunCMake_MAKE_PROGRAM}" -f "${file}" ${ARGN}) +endfunction() + +############################################################################### + +set(RunCMake_TEST_NO_CLEAN 1) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Simple-build) +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE=RelWithDebInfo") +run_cmake_configure(Simple) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(Simple debug-target Debug simpleexe) +run_ninja(Simple debug-target build-Debug.ninja simplestatic) +get_filename_component(simpleshared_Release "${TARGET_FILE_simpleshared_Release}" NAME) +run_cmake_build(Simple release-filename Release ${simpleshared_Release}) +file(RELATIVE_PATH simpleexe_Release "${RunCMake_TEST_BINARY_DIR}" "${TARGET_FILE_simpleexe_Release}") +run_ninja(Simple release-file build-Release.ninja ${simpleexe_Release}) +run_cmake_build(Simple all-configs Release simplestatic:all) +run_ninja(Simple default-build-file build.ninja simpleexe) +run_cmake_build(Simple all-clean Release clean:all) +run_cmake_build(Simple debug-subdir Debug SimpleSubdir/all) +run_ninja(Simple release-in-minsizerel-graph-subdir build-MinSizeRel.ninja SimpleSubdir/all:Release) +run_cmake_build(Simple all-subdir Release SimpleSubdir/all:all) +run_ninja(Simple minsizerel-top build-MinSizeRel.ninja all) +run_cmake_build(Simple debug-in-release-graph-top Release all:Debug) +run_ninja(Simple all-clean-again build-Debug.ninja clean:all) +run_ninja(Simple all-top build-RelWithDebInfo.ninja all:all) +# Leave enough time for the timestamp to change on second-resolution systems +execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1) +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/empty.cmake") +run_ninja(Simple reconfigure-config build-Release.ninja simpleexe) +execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1) +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/empty.cmake") +run_ninja(Simple reconfigure-noconfig build.ninja simpleexe) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandGenerator-build) +run_cmake_configure(CustomCommandGenerator) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(CustomCommandGenerator debug Debug generated) +run_cmake_command(CustomCommandGenerator-debug-generated "${TARGET_FILE_generated_Debug}") +run_ninja(CustomCommandGenerator release build-Release.ninja generated) +run_cmake_command(CustomCommandGenerator-release-generated "${TARGET_FILE_generated_Release}") +run_ninja(CustomCommandGenerator debug-clean build-Debug.ninja clean) +run_cmake_build(CustomCommandGenerator release-clean Release clean) +run_cmake_build(CustomCommandGenerator debug-in-release-graph Release generated:Debug) +run_cmake_command(CustomCommandGenerator-debug-in-release-graph-generated "${TARGET_FILE_generated_Debug}") +run_ninja(CustomCommandGenerator debug-in-release-graph-clean build-Debug.ninja clean:Debug) +run_ninja(CustomCommandGenerator release-in-debug-graph build-Debug.ninja generated:Release) +run_cmake_command(CustomCommandGenerator-release-in-debug-graph-generated "${TARGET_FILE_generated_Release}") + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandsAndTargets-build) +run_cmake_configure(CustomCommandsAndTargets) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(CustomCommandsAndTargets release-command Release SubdirCommand) +#FIXME Get this working +#run_ninja(CustomCommandsAndTargets minsizerel-command build-MinSizeRel.ninja CustomCommandsAndTargetsSubdir/SubdirCommand) +run_ninja(CustomCommandsAndTargets debug-command build-Debug.ninja TopCommand) +run_ninja(CustomCommandsAndTargets release-target build-Release.ninja SubdirTarget) +run_cmake_build(CustomCommandsAndTargets debug-target Debug TopTarget) +run_cmake_build(CustomCommandsAndTargets debug-in-release-graph-postbuild Release SubdirPostBuild:Debug) +run_ninja(CustomCommandsAndTargets release-postbuild build-Release.ninja SubdirPostBuild) +run_cmake_build(CustomCommandsAndTargets debug-targetpostbuild Debug TopTargetPostBuild) +run_ninja(CustomCommandsAndTargets release-targetpostbuild build-Release.ninja SubdirTargetPostBuild) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PostfixAndLocation-build) +set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release") +run_cmake_configure(PostfixAndLocation) +set(RunCMake_TEST_OPTIONS) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(PostfixAndLocation release-in-release-graph Release mylib:Release) +run_cmake_build(PostfixAndLocation debug-in-release-graph Release mylib:Debug) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Clean-build) +run_cmake_configure(Clean) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(Clean release Release) +run_ninja(Clean release-notall build-Release.ninja exenotall) +run_cmake_build(Clean release-clean Release clean) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AdditionalCleanFiles-build) +run_cmake_configure(AdditionalCleanFiles) +run_cmake_build(AdditionalCleanFiles release-clean Release clean) +run_ninja(AdditionalCleanFiles all-clean build-Debug.ninja clean:all) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Install-build) +set(RunCMake_TEST_OPTIONS -DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install) +run_cmake_configure(Install) +set(RunCMake_TEST_OPTIONS) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(Install release-install Release install) +run_ninja(Install debug-in-release-graph-install build-Release.ninja install:Debug) + +# FIXME Get this working +#set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AutoMocExecutable-build) +#run_cmake_configure(AutoMocExecutable) +#run_cmake_build(AutoMocExecutable debug-in-release-graph Release exe) + +if(CMake_TEST_Qt5) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5-build) + run_cmake_configure(Qt5) + include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) + run_cmake_build(Qt5 debug-in-release-graph Release exe:Debug) +endif() diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-again-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-again-ninja-check.cmake new file mode 100644 index 0000000..0f919df --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-again-ninja-check.cmake @@ -0,0 +1,25 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-build-check.cmake new file mode 100644 index 0000000..0f919df --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-build-check.cmake @@ -0,0 +1,25 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-configs-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-configs-build-check.cmake new file mode 100644 index 0000000..170a0e8 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-configs-build-check.cmake @@ -0,0 +1,47 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_FILE_simplestatic_Release} + ${TARGET_LINKER_FILE_simplestatic_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_FILE_simplestatic_RelWithDebInfo} + ${TARGET_LINKER_FILE_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake new file mode 100644 index 0000000..de4505c --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake @@ -0,0 +1,49 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + + ${TARGET_FILE_simpleshared_MinSizeRel} + ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake new file mode 100644 index 0000000..c171e3d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake @@ -0,0 +1,56 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_FILE_simplestatic_Release} + ${TARGET_LINKER_FILE_simplestatic_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + + ${TARGET_FILE_simpleshared_MinSizeRel} + ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_FILE_simplestatic_RelWithDebInfo} + ${TARGET_LINKER_FILE_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake new file mode 100644 index 0000000..fe980fe --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake @@ -0,0 +1,53 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + + ${TARGET_FILE_simpleshared_MinSizeRel} + ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake new file mode 100644 index 0000000..6bb7773 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake @@ -0,0 +1,31 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-build-check.cmake new file mode 100644 index 0000000..6bb7773 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-build-check.cmake @@ -0,0 +1,31 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-ninja-check.cmake new file mode 100644 index 0000000..f9c1e92 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-ninja-check.cmake @@ -0,0 +1,33 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-ninja-check.cmake new file mode 100644 index 0000000..dae1f4d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-ninja-check.cmake @@ -0,0 +1,51 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_FILE_simplestatic_Release} + ${TARGET_LINKER_FILE_simplestatic_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_FILE_simplestatic_RelWithDebInfo} + ${TARGET_LINKER_FILE_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake new file mode 100644 index 0000000..bf4be49 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake @@ -0,0 +1,51 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + + ${TARGET_FILE_simpleshared_MinSizeRel} + ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-config-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-config-ninja-stdout.txt new file mode 100644 index 0000000..8877451 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-config-ninja-stdout.txt @@ -0,0 +1,4 @@ +-- Configuring done +-- Generating done +-- Build files have been written to: [^ +]*/Tests/RunCMake/NinjaMultiConfig/Simple-build diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-noconfig-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-noconfig-ninja-stdout.txt new file mode 100644 index 0000000..8877451 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-noconfig-ninja-stdout.txt @@ -0,0 +1,4 @@ +-- Configuring done +-- Generating done +-- Build files have been written to: [^ +]*/Tests/RunCMake/NinjaMultiConfig/Simple-build diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-release-file-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-release-file-ninja-check.cmake new file mode 100644 index 0000000..6e63aae --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-release-file-ninja-check.cmake @@ -0,0 +1,39 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-release-filename-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-release-filename-build-check.cmake new file mode 100644 index 0000000..a9bf42c --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-release-filename-build-check.cmake @@ -0,0 +1,36 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake new file mode 100644 index 0000000..b6c77ab --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake @@ -0,0 +1,37 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple.cmake new file mode 100644 index 0000000..a32f551 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple.cmake @@ -0,0 +1,13 @@ +enable_language(C) + +file(TOUCH ${CMAKE_BINARY_DIR}/empty.cmake) +include(${CMAKE_BINARY_DIR}/empty.cmake) + +add_subdirectory(SimpleSubdir) + +add_library(simplestatic STATIC simplelib.c) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(simpleexe simpleshared simplestatic simpleobj) + +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(GENERATED_FILES [==[${CMAKE_BINARY_DIR}/empty.cmake]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt new file mode 100644 index 0000000..7e754a3 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(simpleobj OBJECT ../empty.c) +add_executable(simpleexe ../main.c $) +add_library(simpleshared SHARED ../simplelib.c) +target_link_libraries(simpleexe PRIVATE simpleshared) diff --git a/Tests/RunCMake/NinjaMultiConfig/WriteFile.cmake b/Tests/RunCMake/NinjaMultiConfig/WriteFile.cmake new file mode 100644 index 0000000..82681a2 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/WriteFile.cmake @@ -0,0 +1 @@ +file(WRITE "${OUTPUT_FILE}" "Genex config: ${GENEX_CONFIG}\nINTDIR config: ${INTDIR_CONFIG}\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/badmoc.c b/Tests/RunCMake/NinjaMultiConfig/badmoc.c new file mode 100644 index 0000000..aec8dc3 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/badmoc.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("BadMoc Configuration: " CONFIG "\n"); + return 1; +} diff --git a/Tests/RunCMake/NinjaMultiConfig/empty.c b/Tests/RunCMake/NinjaMultiConfig/empty.c new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/NinjaMultiConfig/generator.c b/Tests/RunCMake/NinjaMultiConfig/generator.c new file mode 100644 index 0000000..465ee2f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/generator.c @@ -0,0 +1,101 @@ +#include +#include +/* FIXME Get this working */ +/*#include */ + +const char* generatorlib_genex_config_definition(void); +const char* generatorlib_genex_config_include_dir(void); +const char* generatorobj_genex_config_definition(void); +const char* generatorobj_genex_config_include_dir(void); + +static const char contents[] = + /* clang-format off */ +"#include \n" +"\n" +"#include \n" +/* FIXME Get this working */ +/*"#include \n"*/ +"\n" +"const char* generatorlib_genex_config_definition(void);\n" +"const char* generatorlib_genex_config_include_dir(void);\n" +"const char* generatorobj_genex_config_definition(void);\n" +"const char* generatorobj_genex_config_include_dir(void);\n" +"\n" +"int main(void)\n" +"{\n" +" printf(\n" +" \"Generator genex config definition: " + GENEX_CONFIG_DEFINITION "\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator INTDIR config definition: " + INTDIR_CONFIG_DEFINITION "\\n\"\n"*/ +" \"Generator genex config include dir: " + GENEX_CONFIG_INCLUDE_DIR "\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator INTDIR config include dir: " + INTDIR_CONFIG_INCLUDE_DIR "\\n\"\n"*/ +" \"Generator library genex config definition: %s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator library INTDIR config definition: %s\\n\"\n"*/ +" \"Generator library genex config include dir: %s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator library INTDIR config include dir: %s\\n\"\n"*/ +" \"Generator object genex config definition: %s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator object INTDIR config definition: %s\\n\"\n"*/ +" \"Generator object genex config include dir: %s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator object INTDIR config include dir: %s\\n\"\n"*/ +" \"Generated genex config definition: \"" + " GENEX_CONFIG_DEFINITION \"\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated INTDIR config definition: \"" + " INTDIR_CONFIG_DEFINITION \"\\n\"\n"*/ +" \"Generated genex config include dir: \"" + " GENEX_CONFIG_INCLUDE_DIR \"\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated INTDIR config include dir: \"" + " INTDIR_CONFIG_INCLUDE_DIR \"\\n\"\n"*/ +" \"Generated library genex config definition: %%s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated library INTDIR config definition: %%s\\n\"\n"*/ +" \"Generated library genex config include dir: %%s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated library INTDIR config include dir: %%s\\n\"\n"*/ +" \"Generated object genex config definition: %%s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated object INTDIR config definition: %%s\\n\"\n"*/ +" \"Generated object genex config include dir: %%s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated object INTDIR config include dir: %%s\\n\"\n"*/ +" , generatorlib_genex_config_definition()\n" +" , generatorlib_genex_config_include_dir()\n" +" , generatorobj_genex_config_definition()\n" +" , generatorobj_genex_config_include_dir());\n" +" return 0;\n" +"}\n"; +/* clang-format on */ + +int main(int argc, char** argv) +{ + const char* filename; + FILE* fout; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + filename = argv[1]; + if (!(fout = fopen(filename, "w"))) { + fprintf(stderr, "Could not open %s for writing\n", filename); + return 1; + } + fprintf(fout, contents, generatorlib_genex_config_definition(), + generatorlib_genex_config_include_dir(), + generatorobj_genex_config_definition(), + generatorobj_genex_config_include_dir()); + fclose(fout); + + return 0; +} diff --git a/Tests/RunCMake/NinjaMultiConfig/generatorlib.c b/Tests/RunCMake/NinjaMultiConfig/generatorlib.c new file mode 100644 index 0000000..de5c8f3 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/generatorlib.c @@ -0,0 +1,24 @@ +#include +/* FIXME Get this working */ +/*#include */ + +const char* generatorlib_genex_config_definition(void) +{ + return GENEX_CONFIG_DEFINITION; +} + +const char* generatorlib_genex_config_include_dir(void) +{ + return GENEX_CONFIG_INCLUDE_DIR; +} + +/* FIXME Get this working */ +/*const char* generatorlib_intdir_config_definition(void) +{ + return INTDIR_CONFIG_DEFINITION; +} + +const char* generatorlib_intdir_config_include_dir(void) +{ + return INTDIR_CONFIG_INCLUDE_DIR; +}*/ diff --git a/Tests/RunCMake/NinjaMultiConfig/generatorobj.c b/Tests/RunCMake/NinjaMultiConfig/generatorobj.c new file mode 100644 index 0000000..7bb5aa6 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/generatorobj.c @@ -0,0 +1,24 @@ +#include +/* FIXME Get this working */ +/*#include */ + +const char* generatorobj_genex_config_definition(void) +{ + return GENEX_CONFIG_DEFINITION; +} + +const char* generatorobj_genex_config_include_dir(void) +{ + return GENEX_CONFIG_INCLUDE_DIR; +} + +/* FIXME Get this working */ +/*const char* generatorobj_intdir_config_definition(void) +{ + return INTDIR_CONFIG_DEFINITION; +} + +const char* generatorobj_intdir_config_include_dir(void) +{ + return INTDIR_CONFIG_INCLUDE_DIR; +}*/ diff --git a/Tests/RunCMake/NinjaMultiConfig/main.c b/Tests/RunCMake/NinjaMultiConfig/main.c new file mode 100644 index 0000000..8488f4e --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/NinjaMultiConfig/qt5.cxx b/Tests/RunCMake/NinjaMultiConfig/qt5.cxx new file mode 100644 index 0000000..972227f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/qt5.cxx @@ -0,0 +1,9 @@ +#include + +int main(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + return app.exec(); +} + +#include "moc_qt5.cpp" diff --git a/Tests/RunCMake/NinjaMultiConfig/qt5.h b/Tests/RunCMake/NinjaMultiConfig/qt5.h new file mode 100644 index 0000000..b365b92 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/qt5.h @@ -0,0 +1,5 @@ +#include +class QBuffer : public QObject +{ + Q_OBJECT +}; diff --git a/Tests/RunCMake/NinjaMultiConfig/simplelib.c b/Tests/RunCMake/NinjaMultiConfig/simplelib.c new file mode 100644 index 0000000..76ff921 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/simplelib.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + void simplelib(void) +{ +} -- cgit v0.12 From 8c062f9d9986560588bbc5b7cffbbf3de940cc02 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 27 Nov 2019 11:58:02 -0500 Subject: Help: Add documentation and release notes for multi-config Ninja --- Help/generator/Ninja Multi-Config.rst | 74 ++++++++++++++++++++++ Help/generator/Ninja.rst | 8 ++- Help/manual/cmake-generators.7.rst | 5 +- Help/manual/cmake-variables.7.rst | 1 + Help/release/dev/multi-configuration-ninja.rst | 6 ++ .../CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.rst | 7 ++ 6 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 Help/generator/Ninja Multi-Config.rst create mode 100644 Help/release/dev/multi-configuration-ninja.rst create mode 100644 Help/variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.rst diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst new file mode 100644 index 0000000..71cc392 --- /dev/null +++ b/Help/generator/Ninja Multi-Config.rst @@ -0,0 +1,74 @@ +Ninja Multi-Config +------------------ + +Generates multiple ``build-.ninja`` files. + +This generator is very much like the :generator:`Ninja` generator, but with +some key differences. Only these differences will be discussed in this +document. + +Unlike the :generator:`Ninja` generator, ``Ninja Multi-Config`` generates +multiple configurations at once with :variable:`CMAKE_CONFIGURATION_TYPES` +instead of only one configuration with :variable:`CMAKE_BUILD_TYPE`. One +``build-.ninja`` file will be generated for each of these +configurations (with ```` being the configuration name.) No +``build.ninja`` file is generated, unless +:variable:`CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE` is specified. You must specify +the desired ``build-.ninja`` file with ``ninja -f``. Running +``cmake --build . --config --target `` will run Ninja with +``build-.ninja`` as the ``-f`` file and ```` as the build +target. + +Executables and libraries of any configuration can be built regardless of which +``build-.ninja`` file is used, simply by specifying +``:`` as the Ninja target. You can also specify +``:all`` to build a target in all configurations. Each +``build-.ninja`` file will additionally have ```` targets which +are aliases for ``:``. However, custom commands and custom +targets will always use the configuration specified in +``build-.ninja``. This is due to the fact that it is impossible in +Ninja for the same file to be output with different commands in the same build +graph. + +Consider the following example: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.16) + project(MultiConfigNinja C) + + add_executable(generator generator.c) + add_custom_command(OUTPUT generated.c COMMAND generator generated.c) + add_library(generated ${CMAKE_BINARY_DIR}/generated.c) + +Now assume you configure the project with ``Ninja Multi-Config`` and run one of +the following commands: + +.. code-block:: shell + + ninja -f build-Debug.ninja generated + # OR + cmake --build . --config Debug --target generated + +This would build the ``Debug`` configuration of ``generator``, which would be +used to generate ``generated.c``, which would be used to build the ``Debug`` +configuration of ``generated``. + +But if you run the following instead: + +.. code-block:: shell + + ninja -f build-Release.ninja generated:Debug + # OR + cmake --build . --config Release --target generated:Debug + +This would build the ``Release`` configuration of ``generator``, which would be +used to generate ``generated.c``, which would be used to build the ``Debug`` +configuration of ``generated``. This is useful for running a release-optimized +version of a generator utility while still building the debug version of the +targets built with the generated code. + +As a convenience, ``Ninja Multi-Config`` offers a +:variable:`CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE` setting. If this variable is +specified, a ``build.ninja`` file will be generated which points to the +specified ``build-.ninja`` file. diff --git a/Help/generator/Ninja.rst b/Help/generator/Ninja.rst index c75d2c4..275055d 100644 --- a/Help/generator/Ninja.rst +++ b/Help/generator/Ninja.rst @@ -1,7 +1,7 @@ Ninja ----- -Generates build.ninja files. +Generates ``build.ninja`` files. A ``build.ninja`` file is generated into the build tree. Use the ninja program to build the project through the ``all`` target and install the @@ -38,3 +38,9 @@ features have not been integrated into upstream Ninja. Kitware maintains a branch of Ninja with the required features on `github.com/Kitware/ninja`_. .. _`github.com/Kitware/ninja`: https://github.com/Kitware/ninja/tree/features-for-fortran#readme + +See Also +^^^^^^^^ + +The :generator:`Ninja Multi-Config` generator is similar to the ``Ninja`` +generator, but generates multiple configurations at once. diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index 41f7652..6f88c0a 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -52,13 +52,14 @@ Makefile Generators /generator/Unix Makefiles /generator/Watcom WMake -Ninja Generator -^^^^^^^^^^^^^^^ +Ninja Generators +^^^^^^^^^^^^^^^^ .. toctree:: :maxdepth: 1 /generator/Ninja + /generator/Ninja Multi-Config .. _`IDE Build Tool Generators`: diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 7a5e83e..5143124 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -214,6 +214,7 @@ Variables that Change Behavior /variable/CMAKE_MESSAGE_INDENT /variable/CMAKE_MESSAGE_LOG_LEVEL /variable/CMAKE_MODULE_PATH + /variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE /variable/CMAKE_POLICY_DEFAULT_CMPNNNN /variable/CMAKE_POLICY_WARNING_CMPNNNN /variable/CMAKE_PREFIX_PATH diff --git a/Help/release/dev/multi-configuration-ninja.rst b/Help/release/dev/multi-configuration-ninja.rst new file mode 100644 index 0000000..d9f72cb --- /dev/null +++ b/Help/release/dev/multi-configuration-ninja.rst @@ -0,0 +1,6 @@ +multi-configuration-ninja +------------------------- + +* :manual:`cmake(1)` gained a :generator:`Ninja Multi-Config` generator, + which is similar to the :generator:`Ninja` generator but can be used to build + multiple configurations at once. diff --git a/Help/variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.rst b/Help/variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.rst new file mode 100644 index 0000000..2b950e1 --- /dev/null +++ b/Help/variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.rst @@ -0,0 +1,7 @@ +CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE +------------------------------------ + +Specifies a configuration type to use as the default in ``build.ninja`` for the +:generator:`Ninja Multi-Config` generator. + +If this variable is not specified, no ``build.ninja`` file is generated. -- cgit v0.12