summaryrefslogtreecommitdiffstats
path: root/Source/cmNinjaTargetGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmNinjaTargetGenerator.cxx')
-rw-r--r--Source/cmNinjaTargetGenerator.cxx326
1 files changed, 184 insertions, 142 deletions
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 0aab912..bd19b28 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -10,11 +10,11 @@
#include <utility>
#include <cm/memory>
+#include <cmext/algorithm>
#include "cm_jsoncpp_value.h"
#include "cm_jsoncpp_writer.h"
-#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
@@ -68,9 +68,15 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target)
cmNinjaTargetGenerator::~cmNinjaTargetGenerator() = default;
-cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const
+cmGeneratedFileStream& cmNinjaTargetGenerator::GetConfigFileStream(
+ const std::string& config) const
{
- return *this->GetGlobalGenerator()->GetBuildFileStream();
+ return *this->GetGlobalGenerator()->GetConfigFileStream(config);
+}
+
+cmGeneratedFileStream& cmNinjaTargetGenerator::GetCommonFileStream() const
+{
+ return *this->GetGlobalGenerator()->GetCommonFileStream();
}
cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const
@@ -84,17 +90,19 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const
}
std::string cmNinjaTargetGenerator::LanguageCompilerRule(
- const std::string& lang) const
+ const std::string& lang, const std::string& config) const
{
return lang + "_COMPILER__" +
- cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName());
+ cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) +
+ "_" + config;
}
std::string cmNinjaTargetGenerator::LanguagePreprocessRule(
- std::string const& lang) const
+ std::string const& lang, const std::string& config) const
{
return lang + "_PREPROCESS__" +
- cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName());
+ cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) +
+ "_" + config;
}
bool cmNinjaTargetGenerator::NeedExplicitPreprocessing(
@@ -117,10 +125,11 @@ bool cmNinjaTargetGenerator::CompilePreprocessedSourceWithDefines(
}
std::string cmNinjaTargetGenerator::LanguageDyndepRule(
- const std::string& lang) const
+ const std::string& lang, const std::string& config) const
{
return lang + "_DYNDEP__" +
- cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName());
+ cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) +
+ "_" + config;
}
bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const
@@ -128,9 +137,11 @@ bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const
return lang == "Fortran";
}
-std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget()
+std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget(
+ const std::string& config)
{
- return "cmake_object_order_depends_target_" + this->GetTargetName();
+ return cmGlobalNinjaGenerator::OrderDependsTargetForTarget(
+ this->GeneratorTarget, config);
}
// TODO: Most of the code is picked up from
@@ -138,10 +149,10 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget()
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
// Refactor it.
std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
- cmSourceFile const* source, const std::string& language)
+ cmSourceFile const* source, const std::string& language,
+ const std::string& config)
{
- std::string flags = this->GetFlags(language);
- const std::string configName = this->LocalGenerator->GetConfigName();
+ std::string flags = this->GetFlags(language, config);
// Add Fortran format flags.
if (language == "Fortran") {
@@ -150,7 +161,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
// Add source file specific flags.
cmGeneratorExpressionInterpreter genexInterpreter(
- this->LocalGenerator, configName, this->GeneratorTarget, language);
+ this->LocalGenerator, config, this->GeneratorTarget, language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
@@ -166,16 +177,16 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
// Add precompile headers compile options.
const std::string pchSource =
- this->GeneratorTarget->GetPchSource(configName, language);
+ this->GeneratorTarget->GetPchSource(config, language);
if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
if (source->GetFullPath() == pchSource) {
- pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions(
- configName, language);
+ pchOptions =
+ this->GeneratorTarget->GetPchCreateCompileOptions(config, language);
} else {
pchOptions =
- this->GeneratorTarget->GetPchUseCompileOptions(configName, language);
+ this->GeneratorTarget->GetPchUseCompileOptions(config, language);
}
this->LocalGenerator->AppendCompileOptions(
@@ -186,16 +197,17 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
}
void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
- std::string const& language)
+ std::string const& language,
+ const std::string& config)
{
std::vector<std::string> includes;
this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
- language, this->GetConfigName());
+ language, config);
// Add include directory flags.
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
includes, this->GeneratorTarget, language,
language == "RC", // full include paths for RC needed by cmcldeps
- false, this->GetConfigName());
+ false, config);
if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/');
}
@@ -232,13 +244,18 @@ bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const
// TODO: Refactor with
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
- const std::string& language)
+ const std::string& language,
+ const std::string& config)
{
std::set<std::string> defines;
- const std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, config, this->GeneratorTarget, language);
+ // Seriously??
+ if (this->GetGlobalGenerator()->IsMultiConfig()) {
+ defines.insert(cmStrCat("CMAKE_INTDIR=\"", config, '"'));
+ }
+
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
this->LocalGenerator->AppendDefines(
@@ -253,17 +270,17 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS));
}
- std::string definesString = this->GetDefines(language);
+ std::string definesString = this->GetDefines(language, config);
this->LocalGenerator->JoinDefines(defines, definesString, language);
return definesString;
}
std::string cmNinjaTargetGenerator::ComputeIncludes(
- cmSourceFile const* source, const std::string& language)
+ cmSourceFile const* source, const std::string& language,
+ const std::string& config)
{
std::vector<std::string> includes;
- const std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, config, this->GeneratorTarget, language);
@@ -277,13 +294,13 @@ std::string cmNinjaTargetGenerator::ComputeIncludes(
std::string includesString = this->LocalGenerator->GetIncludeFlags(
includes, this->GeneratorTarget, language, true, false, config);
this->LocalGenerator->AppendFlags(includesString,
- this->GetIncludes(language));
+ this->GetIncludes(language, config));
return includesString;
}
cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
- const std::string& linkLanguage) const
+ const std::string& linkLanguage, const std::string& config) const
{
// Static libraries never depend on other targets for linking.
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
@@ -292,7 +309,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
}
cmComputeLinkInformation* cli =
- this->GeneratorTarget->GetLinkInformation(this->GetConfigName());
+ this->GeneratorTarget->GetLinkInformation(config);
if (!cli) {
return cmNinjaDeps();
}
@@ -303,8 +320,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
// Add a dependency on the link definitions file, if any.
if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
- this->GeneratorTarget->GetModuleDefinitionInfo(
- this->GetConfigName())) {
+ this->GeneratorTarget->GetModuleDefinitionInfo(config)) {
for (cmSourceFile const* src : mdi->Sources) {
result.push_back(this->ConvertToNinjaPath(src->GetFullPath()));
}
@@ -312,15 +328,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
// Add a dependency on user-specified manifest files, if any.
std::vector<cmSourceFile const*> manifest_srcs;
- this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
+ this->GeneratorTarget->GetManifests(manifest_srcs, config);
for (cmSourceFile const* manifest_src : manifest_srcs) {
result.push_back(this->ConvertToNinjaPath(manifest_src->GetFullPath()));
}
// Add user-specified dependencies.
std::vector<std::string> linkDeps;
- this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName,
- linkLanguage);
+ this->GeneratorTarget->GetLinkDepends(linkDeps, config, linkLanguage);
std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result),
MapToNinjaPath());
@@ -334,7 +349,7 @@ std::string cmNinjaTargetGenerator::GetSourceFilePath(
}
std::string cmNinjaTargetGenerator::GetObjectFilePath(
- cmSourceFile const* source) const
+ cmSourceFile const* source, const std::string& config) const
{
std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
if (!path.empty()) {
@@ -342,13 +357,14 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath(
}
std::string const& objectName = this->GeneratorTarget->GetObjectName(source);
path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ path += this->GetGlobalGenerator()->ConfigDirectory(config);
path += "/";
path += objectName;
return path;
}
std::string cmNinjaTargetGenerator::GetPreprocessedFilePath(
- cmSourceFile const* source) const
+ cmSourceFile const* source, const std::string& config) const
{
// Choose an extension to compile already-preprocessed source.
std::string ppExt = source->GetExtension();
@@ -378,19 +394,21 @@ std::string cmNinjaTargetGenerator::GetPreprocessedFilePath(
path += "/";
}
path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ path += this->GetGlobalGenerator()->ConfigDirectory(config);
path += "/";
path += ppName;
return path;
}
std::string cmNinjaTargetGenerator::GetDyndepFilePath(
- std::string const& lang) const
+ std::string const& lang, const std::string& config) const
{
std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
if (!path.empty()) {
path += "/";
}
path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ path += this->GetGlobalGenerator()->ConfigDirectory(config);
path += "/";
path += lang;
path += ".dd";
@@ -398,25 +416,27 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath(
}
std::string cmNinjaTargetGenerator::GetTargetDependInfoPath(
- std::string const& lang) const
+ std::string const& lang, const std::string& config) const
{
std::string path =
cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/',
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
- '/', lang, "DependInfo.json");
+ this->GetGlobalGenerator()->ConfigDirectory(config), '/', lang,
+ "DependInfo.json");
return path;
}
-std::string cmNinjaTargetGenerator::GetTargetOutputDir() const
+std::string cmNinjaTargetGenerator::GetTargetOutputDir(
+ const std::string& config) const
{
- std::string dir = this->GeneratorTarget->GetDirectory(this->GetConfigName());
+ std::string dir = this->GeneratorTarget->GetDirectory(config);
return ConvertToNinjaPath(dir);
}
std::string cmNinjaTargetGenerator::GetTargetFilePath(
- const std::string& name) const
+ const std::string& name, const std::string& config) const
{
- std::string path = this->GetTargetOutputDir();
+ std::string path = this->GetTargetOutputDir(config);
if (path.empty() || path == ".") {
return name;
}
@@ -430,21 +450,21 @@ std::string cmNinjaTargetGenerator::GetTargetName() const
return this->GeneratorTarget->GetName();
}
-bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
+bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(
+ cmNinjaVars& vars, const std::string& config) const
{
cmMakefile* mf = this->GetMakefile();
if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") ||
mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") ||
mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) {
std::string pdbPath;
- std::string compilePdbPath = this->ComputeTargetCompilePDB();
+ std::string compilePdbPath = this->ComputeTargetCompilePDB(config);
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
- pdbPath = cmStrCat(
- this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/',
- this->GeneratorTarget->GetPDBName(this->GetConfigName()));
+ pdbPath = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config), '/',
+ this->GeneratorTarget->GetPDBName(config));
}
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
@@ -460,15 +480,17 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
return false;
}
-void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language)
+void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language,
+ const std::string& config)
{
#ifdef NINJA_GEN_VERBOSE_FILES
this->GetRulesFileStream() << "# Rules for language " << language << "\n\n";
#endif
- this->WriteCompileRule(language);
+ this->WriteCompileRule(language, config);
}
-void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
+void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
+ const std::string& config)
{
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
@@ -509,7 +531,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat(
- ConvertToNinjaPath(this->GetTargetDependInfoPath(lang)),
+ ConvertToNinjaPath(this->GetTargetDependInfoPath(lang, config)),
cmLocalGenerator::SHELL);
std::string launcher;
@@ -524,7 +546,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
if (explicitPP) {
- cmNinjaRule rule(this->LanguagePreprocessRule(lang));
+ cmNinjaRule rule(this->LanguagePreprocessRule(lang, config));
// Explicit preprocessing always uses a depfile.
rule.DepType = ""; // no deps= for multiple outputs
rule.DepFile = "$DEP_FILE";
@@ -604,7 +626,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
if (needDyndep) {
// Write the rule for ninja dyndep file generation.
- cmNinjaRule rule(this->LanguageDyndepRule(lang));
+ cmNinjaRule rule(this->LanguageDyndepRule(lang, config));
// Command line length is almost always limited -> use response file for
// dyndep rules
rule.RspFile = "$out.rsp";
@@ -628,7 +650,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
this->GetGlobalGenerator()->AddRule(rule);
}
- cmNinjaRule rule(this->LanguageCompilerRule(lang));
+ cmNinjaRule rule(this->LanguageCompilerRule(lang, config));
// If using a response file, move defines, includes, and flags into it.
if (!responseFlag.empty()) {
rule.RspFile = "$RSP_FILE";
@@ -788,50 +810,52 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
this->GetGlobalGenerator()->AddRule(rule);
}
-void cmNinjaTargetGenerator::WriteObjectBuildStatements()
+void cmNinjaTargetGenerator::WriteObjectBuildStatements(
+ const std::string& config, const std::string& fileConfig,
+ bool firstForConfig)
{
// Write comments.
- cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
- this->GetBuildFileStream()
+ cmGlobalNinjaGenerator::WriteDivider(this->GetConfigFileStream(fileConfig));
+ this->GetConfigFileStream(fileConfig)
<< "# Object build statements for "
<< cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType())
<< " target " << this->GetTargetName() << "\n\n";
{
std::vector<cmSourceFile const*> customCommands;
- this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
+ this->GeneratorTarget->GetCustomCommands(customCommands, config);
for (cmSourceFile const* sf : customCommands) {
cmCustomCommand const* cc = sf->GetCustomCommand();
this->GetLocalGenerator()->AddCustomCommandTarget(
cc, this->GetGeneratorTarget());
// Record the custom commands for this target. The container is used
// in WriteObjectBuildStatement when called in a loop below.
- this->CustomCommands.push_back(cc);
+ this->Configs[config].CustomCommands.push_back(cc);
}
}
{
std::vector<cmSourceFile const*> headerSources;
- this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName);
+ this->GeneratorTarget->GetHeaderSources(headerSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
- headerSources, this->MacOSXContentGenerator.get());
+ headerSources, this->MacOSXContentGenerator.get(), config);
}
{
std::vector<cmSourceFile const*> extraSources;
- this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName);
+ this->GeneratorTarget->GetExtraSources(extraSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
- extraSources, this->MacOSXContentGenerator.get());
+ extraSources, this->MacOSXContentGenerator.get(), config);
}
- {
+ if (firstForConfig) {
const char* pchExtension =
GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
std::vector<cmSourceFile const*> externalObjects;
- this->GeneratorTarget->GetExternalObjects(externalObjects,
- this->ConfigName);
+ this->GeneratorTarget->GetExternalObjects(externalObjects, config);
for (cmSourceFile const* sf : externalObjects) {
- const auto objectFileName = this->GetSourceFilePath(sf);
+ auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir(
+ this->GetSourceFilePath(sf), config);
if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
- this->Objects.push_back(objectFileName);
+ this->Configs[config].Objects.push_back(objectFileName);
}
}
}
@@ -839,19 +863,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
{
cmNinjaBuild build("phony");
build.Comment = "Order-only phony target for " + this->GetTargetName();
- build.Outputs.push_back(this->OrderDependsTargetForTarget());
+ build.Outputs.push_back(this->OrderDependsTargetForTarget(config));
cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps;
this->GetLocalGenerator()->AppendTargetDepends(
- this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering);
+ this->GeneratorTarget, orderOnlyDeps, config, fileConfig,
+ DependOnTargetOrdering);
// Add order-only dependencies on other files associated with the target.
- cmAppend(orderOnlyDeps, this->ExtraFiles);
+ cm::append(orderOnlyDeps, this->Configs[config].ExtraFiles);
// Add order-only dependencies on custom command outputs.
- for (cmCustomCommand const* cc : this->CustomCommands) {
- cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
- this->GetLocalGenerator());
+ for (cmCustomCommand const* cc : this->Configs[config].CustomCommands) {
+ cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator());
const std::vector<std::string>& ccoutputs = ccg.GetOutputs();
const std::vector<std::string>& ccbyproducts = ccg.GetByproducts();
std::transform(ccoutputs.begin(), ccoutputs.end(),
@@ -877,26 +901,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir));
}
- this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
+ this->GetGlobalGenerator()->WriteBuild(
+ this->GetConfigFileStream(fileConfig), build);
}
{
std::vector<cmSourceFile const*> objectSources;
- this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName);
+ this->GeneratorTarget->GetObjectSources(objectSources, config);
for (cmSourceFile const* sf : objectSources) {
- this->WriteObjectBuildStatement(sf);
+ this->WriteObjectBuildStatement(sf, config, fileConfig, firstForConfig);
}
}
- for (auto const& langDDIFiles : this->DDIFiles) {
+ for (auto const& langDDIFiles : this->Configs[config].DDIFiles) {
std::string const& language = langDDIFiles.first;
cmNinjaDeps const& ddiFiles = langDDIFiles.second;
- cmNinjaBuild build(this->LanguageDyndepRule(language));
- build.Outputs.push_back(this->GetDyndepFilePath(language));
+ cmNinjaBuild build(this->LanguageDyndepRule(language, config));
+ build.Outputs.push_back(this->GetDyndepFilePath(language, config));
build.ExplicitDeps = ddiFiles;
- this->WriteTargetDependInfo(language);
+ this->WriteTargetDependInfo(language, config);
// Make sure dyndep files for all our dependencies have already
// been generated so that the '<LANG>Modules.json' files they
@@ -907,46 +932,51 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
// refactoring the Ninja generator to generate targets in
// dependency order so that we can collect the needed information.
this->GetLocalGenerator()->AppendTargetDepends(
- this->GeneratorTarget, build.OrderOnlyDeps, DependOnTargetArtifact);
+ this->GeneratorTarget, build.OrderOnlyDeps, config, fileConfig,
+ DependOnTargetArtifact);
- this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
+ this->GetGlobalGenerator()->WriteBuild(
+ this->GetConfigFileStream(fileConfig), build);
}
- this->GetBuildFileStream() << "\n";
+ this->GetConfigFileStream(fileConfig) << "\n";
- if (!this->SwiftOutputMap.empty()) {
+ if (!this->Configs[config].SwiftOutputMap.empty()) {
std::string const mapFilePath =
this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json";
- std::string const targetSwiftDepsPath = [this]() -> std::string {
+ std::string const targetSwiftDepsPath = [this, config]() -> std::string {
cmGeneratorTarget const* target = this->GeneratorTarget;
if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) {
return name;
}
return this->ConvertToNinjaPath(target->GetSupportDirectory() + "/" +
- target->GetName() + ".swiftdeps");
+ config + "/" + target->GetName() +
+ ".swiftdeps");
}();
// build the global target dependencies
// https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps
Json::Value deps(Json::objectValue);
deps["swift-dependencies"] = targetSwiftDepsPath;
- this->SwiftOutputMap[""] = deps;
+ this->Configs[config].SwiftOutputMap[""] = deps;
cmGeneratedFileStream output(mapFilePath);
- output << this->SwiftOutputMap;
+ output << this->Configs[config].SwiftOutputMap;
}
}
void cmNinjaTargetGenerator::WriteObjectBuildStatement(
- cmSourceFile const* source)
+ cmSourceFile const* source, const std::string& config,
+ const std::string& fileConfig, bool firstForConfig)
{
std::string const language = source->GetLanguage();
std::string const sourceFileName =
language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source);
- std::string const objectDir =
- this->ConvertToNinjaPath(this->GeneratorTarget->GetSupportDirectory());
+ std::string const objectDir = this->ConvertToNinjaPath(
+ cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
+ this->GetGlobalGenerator()->ConfigDirectory(config)));
std::string const objectFileName =
- this->ConvertToNinjaPath(this->GetObjectFilePath(source));
+ this->ConvertToNinjaPath(this->GetObjectFilePath(source, config));
std::string const objectFileDir =
cmSystemTools::GetFilenamePath(objectFileName);
@@ -962,11 +992,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
int const commandLineLengthLimit =
((lang_supports_response && this->ForceResponseFile())) ? -1 : 0;
- cmNinjaBuild objBuild(this->LanguageCompilerRule(language));
+ cmNinjaBuild objBuild(this->LanguageCompilerRule(language, config));
cmNinjaVars& vars = objBuild.Variables;
- vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
- vars["DEFINES"] = this->ComputeDefines(source, language);
- vars["INCLUDES"] = this->ComputeIncludes(source, language);
+ vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config);
+ vars["DEFINES"] = this->ComputeDefines(source, language, config);
+ vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
if (!this->NeedDepTypeMSVC(language)) {
bool replaceExt(false);
@@ -994,11 +1024,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]);
objBuild.Outputs.push_back(objectFileName);
- const char* pchExtension =
- this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
- if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
- // Add this object to the list of object files.
- this->Objects.push_back(objectFileName);
+ if (firstForConfig) {
+ const char* pchExtension =
+ this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
+ if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
+ // Add this object to the list of object files.
+ this->Configs[config].Objects.push_back(objectFileName);
+ }
}
objBuild.ExplicitDeps.push_back(sourceFileName);
@@ -1007,13 +1039,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::vector<std::string> depList;
const std::string pchSource =
- this->GeneratorTarget->GetPchSource(this->GetConfigName(), language);
+ this->GeneratorTarget->GetPchSource(config, language);
if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
- depList.push_back(
- this->GeneratorTarget->GetPchHeader(this->GetConfigName(), language));
+ depList.push_back(this->GeneratorTarget->GetPchHeader(config, language));
if (source->GetFullPath() != pchSource) {
- depList.push_back(
- this->GeneratorTarget->GetPchFile(this->GetConfigName(), language));
+ depList.push_back(this->GeneratorTarget->GetPchFile(config, language));
}
}
@@ -1034,7 +1064,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
MapToNinjaPath());
}
- objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget());
+ objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config));
// If the source file is GENERATED and does not have a custom command
// (either attached to this source file or another one), assume that one of
@@ -1054,10 +1084,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
// For some cases we do an explicit preprocessor invocation.
bool const explicitPP = this->NeedExplicitPreprocessing(language);
if (explicitPP) {
- cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language));
+ cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language, config));
std::string const ppFileName =
- this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source));
+ this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config));
ppBuild.Outputs.push_back(ppFileName);
ppBuild.RspFile = ppFileName + ".rsp";
@@ -1115,7 +1145,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags(
sourceDirectory, this->GeneratorTarget, language, false, false,
- this->GetConfigName());
+ config);
vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"];
}
@@ -1139,17 +1169,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::string const ddiFile = objectFileName + ".ddi";
ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
ppBuild.ImplicitOuts.push_back(ddiFile);
- this->DDIFiles[language].push_back(ddiFile);
+ if (firstForConfig) {
+ this->Configs[config].DDIFiles[language].push_back(ddiFile);
+ }
}
this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
ppBuild.Variables);
- this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), ppBuild,
- commandLineLengthLimit);
+ this->GetGlobalGenerator()->WriteBuild(
+ this->GetConfigFileStream(fileConfig), ppBuild, commandLineLengthLimit);
}
if (needDyndep) {
- std::string const dyndep = this->GetDyndepFilePath(language);
+ std::string const dyndep = this->GetDyndepFilePath(language, config);
objBuild.OrderOnlyDeps.push_back(dyndep);
vars["dyndep"] = dyndep;
}
@@ -1164,15 +1196,15 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
vars);
- this->SetMsvcTargetPdbVariable(vars);
+ this->SetMsvcTargetPdbVariable(vars, config);
objBuild.RspFile = objectFileName + ".rsp";
if (language == "Swift") {
- this->EmitSwiftDependencyInfo(source);
+ this->EmitSwiftDependencyInfo(source, config);
} else {
- this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(),
- objBuild, commandLineLengthLimit);
+ this->GetGlobalGenerator()->WriteBuild(
+ this->GetConfigFileStream(fileConfig), objBuild, commandLineLengthLimit);
}
if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
@@ -1182,11 +1214,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::transform(build.Outputs.begin(), build.Outputs.end(),
build.Outputs.begin(), MapToNinjaPath());
build.ExplicitDeps = objBuild.Outputs;
- this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
+ this->GetGlobalGenerator()->WriteBuild(
+ this->GetConfigFileStream(fileConfig), build);
}
}
-void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
+void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
+ const std::string& config)
{
Json::Value tdi(Json::objectValue);
tdi["language"] = lang;
@@ -1214,7 +1248,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
Json::Value& tdi_include_dirs = tdi["include-dirs"] = Json::arrayValue;
std::vector<std::string> includes;
this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
- lang, this->GetConfigName());
+ lang, config);
for (std::string const& i : includes) {
// Convert the include directories the same way we do for -I flags.
// See upstream ninja issue 1251.
@@ -1223,22 +1257,22 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] =
Json::arrayValue;
- for (std::string const& l : this->GetLinkedTargetDirectories()) {
+ for (std::string const& l : this->GetLinkedTargetDirectories(config)) {
tdi_linked_target_dirs.append(l);
}
- std::string const tdin = this->GetTargetDependInfoPath(lang);
+ std::string const tdin = this->GetTargetDependInfoPath(lang, config);
cmGeneratedFileStream tdif(tdin);
tdif << tdi;
}
void cmNinjaTargetGenerator::EmitSwiftDependencyInfo(
- cmSourceFile const* source)
+ cmSourceFile const* source, const std::string& config)
{
std::string const sourceFilePath =
this->ConvertToNinjaPath(this->GetSourceFilePath(source));
std::string const objectFilePath =
- this->ConvertToNinjaPath(this->GetObjectFilePath(source));
+ this->ConvertToNinjaPath(this->GetObjectFilePath(source, config));
std::string const swiftDepsPath = [source, objectFilePath]() -> std::string {
if (const char* name = source->GetProperty("Swift_DEPENDENCIES_FILE")) {
return name;
@@ -1251,10 +1285,10 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo(
}
return objectFilePath + ".dia";
}();
- std::string const makeDepsPath = [this, source]() -> std::string {
+ std::string const makeDepsPath = [this, source, config]() -> std::string {
cmLocalNinjaGenerator const* local = this->GetLocalGenerator();
std::string const objectFileName =
- this->ConvertToNinjaPath(this->GetObjectFilePath(source));
+ this->ConvertToNinjaPath(this->GetObjectFilePath(source, config));
std::string const objectFileDir =
cmSystemTools::GetFilenamePath(objectFileName);
@@ -1275,7 +1309,7 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo(
entry["dependencies"] = makeDepsPath;
entry["swift-dependencies"] = swiftDepsPath;
entry["diagnostics"] = swiftDiaPath;
- SwiftOutputMap[sourceFilePath] = entry;
+ this->Configs[config].SwiftOutputMap[sourceFilePath] = entry;
}
void cmNinjaTargetGenerator::ExportObjectCompileCommand(
@@ -1350,27 +1384,34 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName);
}
-void cmNinjaTargetGenerator::AdditionalCleanFiles()
+void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config)
{
if (const char* prop_value =
this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) {
cmLocalNinjaGenerator* lg = this->LocalGenerator;
std::vector<std::string> cleanFiles;
- cmExpandList(cmGeneratorExpression::Evaluate(
- prop_value, lg,
- this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"),
- this->GeneratorTarget),
+ cmExpandList(cmGeneratorExpression::Evaluate(prop_value, lg, config,
+ this->GeneratorTarget),
cleanFiles);
std::string const& binaryDir = lg->GetCurrentBinaryDirectory();
cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator();
for (std::string const& cleanFile : cleanFiles) {
// Support relative paths
gg->AddAdditionalCleanFile(
- cmSystemTools::CollapseFullPath(cleanFile, binaryDir));
+ cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config);
}
}
}
+cmNinjaDeps cmNinjaTargetGenerator::GetObjects(const std::string& config) const
+{
+ auto const it = this->Configs.find(config);
+ if (it != this->Configs.end()) {
+ return it->second.Objects;
+ }
+ return {};
+}
+
void cmNinjaTargetGenerator::EnsureDirectoryExists(
const std::string& path) const
{
@@ -1393,7 +1434,7 @@ void cmNinjaTargetGenerator::EnsureParentDirectoryExists(
}
void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
- cmSourceFile const& source, const char* pkgloc)
+ cmSourceFile const& source, const char* pkgloc, const std::string& config)
{
// Skip OS X content when not building a Framework or Bundle.
if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) {
@@ -1401,7 +1442,8 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
}
std::string macdir =
- this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
+ this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc,
+ config);
// Get the input file location.
std::string input = source.GetFullPath();
@@ -1413,11 +1455,11 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
output = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output);
// Write a build statement to copy the content into the bundle.
- this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input,
- output);
+ this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input, output,
+ config);
// Add as a dependency to the target so that it gets called.
- this->Generator->ExtraFiles.push_back(std::move(output));
+ this->Generator->Configs[config].ExtraFiles.push_back(std::move(output));
}
void cmNinjaTargetGenerator::addPoolNinjaVariable(