Ninja: Add multi-config variant

Co-Authored-by: vector-of-bool <vectorofbool@gmail.com>
This commit is contained in:
Kyle Edwards
2019-12-13 10:51:46 -05:00
co-authored by vector-of-bool
parent 3bc63e99e4
commit 5a8a9f7229
54 changed files with 1264 additions and 416 deletions
+15 -10
View File
@@ -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<std::string> 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();
+10 -4
View File
@@ -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, std::string>;
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<std::string> GetLinkedTargetDirectories(
const std::string& config) const;
std::string ComputeTargetCompilePDB(const std::string& config) const;
private:
using ByLanguageMap = std::map<std::string, std::string>;
struct ByConfig
{
ByLanguageMap FlagsByLanguage;
ByLanguageMap DefinesByLanguage;
ByLanguageMap IncludesByLanguage;
};
std::map<std::string, ByConfig> Configs;
};
#endif
+6 -2
View File
@@ -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());
}
}
}
+2 -1
View File
@@ -70,7 +70,8 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE,
cmTarget::VisibilityNormal, tgt->Target->GetMakefile());
cmTarget::VisibilityNormal, tgt->Target->GetMakefile(),
true);
cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());
+6 -4
View File
@@ -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<std::string> configSet(configs.begin(), configs.end());
if (configSet == this->VisitedConfigsForObjects) {
return;
}
std::vector<std::string> const& configs =
this->Makefile->GetGeneratorConfigs();
for (std::string const& c : configs) {
std::vector<cmSourceFile const*> sourceFiles;
this->GetObjectSources(sourceFiles, c);
+1
View File
@@ -767,6 +767,7 @@ private:
};
using SourceEntriesType = std::map<cmSourceFile const*, SourceEntry>;
SourceEntriesType SourceDepends;
mutable std::set<std::string> VisitedConfigsForObjects;
mutable std::map<cmSourceFile const*, std::string> Objects;
std::set<cmSourceFile const*> ExplicitObjectName;
mutable std::map<std::string, std::vector<std::string>> SystemIncludesCache;
+3 -1
View File
@@ -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<std::string> no_outputs;
+6
View File
@@ -479,6 +479,11 @@ public:
int RecursionDepth;
virtual void GetQtAutoGenConfigs(std::vector<std::string>& configs) const
{
configs.emplace_back("$<CONFIG>");
}
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<std::string> Depends;
std::string WorkingDir;
bool UsesTerminal = false;
bool PerConfig = true;
};
void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);
+476 -127
View File
@@ -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<std::string> const& langs, cmMakefile* mf, bool optional)
{
if (this->IsMultiConfig()) {
if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
mf->AddCacheDefinition(
"CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
"Semicolon separated list of supported configuration types, only "
"supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything "
"else will be ignored",
cmStateEnums::STRING);
}
}
this->cmGlobalGenerator::EnableLanguage(langs, mf, optional);
for (std::string const& l : langs) {
if (l == "NONE") {
@@ -653,7 +683,7 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalNinjaGenerator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& /*projectName*/,
const std::string& /*projectDir*/,
std::vector<std::string> const& targetNames, const std::string& /*config*/,
std::vector<std::string> const& targetNames, const std::string& config,
bool /*fast*/, int jobs, bool verbose,
std::vector<std::string> const& makeOptions)
{
@@ -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,35 +743,21 @@ 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);
// Get a stream where to generate things.
if (!this->BuildFileStream) {
this->BuildFileStream = cm::make_unique<cmGeneratedFileStream>(
buildFilePath, false, this->GetMakefileEncoding());
if (!(*this->BuildFileStream)) {
// An error message is generated by the constructor if it cannot
// open the file.
return false;
}
if (!this->OpenFileStream(this->BuildFileStream,
cmGlobalNinjaGenerator::NINJA_BUILD_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"
@@ -747,7 +766,30 @@ bool cmGlobalNinjaGenerator::OpenBuildFileStream()
return true;
}
void cmGlobalNinjaGenerator::CloseBuildFileStream()
bool cmGlobalNinjaGenerator::OpenFileStream(
std::unique_ptr<cmGeneratedFileStream>& stream, const std::string& name)
{
// Get a stream where to generate things.
if (!stream) {
// Compute Ninja's build file path.
std::string path =
cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', name);
stream = cm::make_unique<cmGeneratedFileStream>(
path, false, this->GetMakefileEncoding());
if (!(*stream)) {
// An error message is generated by the constructor if it cannot
// open the file.
return false;
}
// Write the do not edit header.
this->WriteDisclaimer(*stream);
}
return true;
}
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<cmGeneratedFileStream>(
rulesFilePath, false, this->GetMakefileEncoding());
if (!(*this->RulesFileStream)) {
// An error message is generated by the constructor if it cannot
// open the file.
return false;
}
if (!this->OpenFileStream(this->RulesFileStream,
cmGlobalNinjaGenerator::NINJA_RULES_FILE)) {
return false;
}
// Write the do not edit header.
this->WriteDisclaimer(*this->RulesFileStream);
// Write comment about this file.
/* clang-format off */
*this->RulesFileStream
@@ -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<TargetAliasMap::iterator, bool> newAlias =
TargetAliases.insert(std::make_pair(buildAlias, target));
if (newAlias.second && newAlias.first->second != target) {
newAlias.first->second = nullptr;
TargetAlias ta;
ta.GeneratorTarget = target;
ta.Config = config;
std::pair<TargetAliasMap::iterator, bool> newAliasGlobal =
this->TargetAliases.insert(std::make_pair(buildAlias, ta));
if (newAliasGlobal.second &&
newAliasGlobal.first->second.GeneratorTarget != target) {
newAliasGlobal.first->second.GeneratorTarget = nullptr;
}
if (config != "all") {
std::pair<TargetAliasMap::iterator, bool> newAliasConfig =
this->Configs[config].TargetAliases.insert(
std::make_pair(outputPath, ta));
if (newAliasConfig.second &&
newAliasConfig.first->second.GeneratorTarget != target) {
newAliasConfig.first->second.GeneratorTarget = nullptr;
}
}
}
@@ -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<std::string> 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<std::string> configs;
dt.LG->GetMakefile()->GetConfigurations(configs, true);
if (configs.empty()) {
configs.emplace_back();
}
// Setup target
cmNinjaDeps configDeps;
build.Comment = "Folder: " + currentBinaryDir;
build.Outputs.emplace_back(
this->ConvertToNinjaPath(currentBinaryDir + "/all"));
for (DirectoryTarget::Target const& t : dt.Targets) {
if (!t.ExcludeFromAll) {
std::vector<std::string> 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<std::string> configs;
this->Makefiles[0]->GetConfigurations(configs, true);
if (configs.empty()) {
configs.emplace_back();
}
// Check if there are additional files to clean
if (this->AdditionalCleanFiles.empty()) {
bool empty = true;
for (auto const& config : configs) {
auto const it = this->Configs.find(config);
if (it != this->Configs.end() &&
!it->second.AdditionalCleanFiles.empty()) {
empty = false;
break;
}
}
if (empty) {
// Remove cmake clean script file if it exists
cmSystemTools::RemoveFile(cleanScriptAbs);
return false;
@@ -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<std::string>::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-<Config>.ninja files.";
}
std::string cmGlobalNinjaMultiGenerator::ExpandCFGIntDir(
const std::string& str, const std::string& config) const
{
std::string result = str;
cmSystemTools::ReplaceString(result, this->GetCMakeCFGIntDir(), config);
return result;
}
bool cmGlobalNinjaMultiGenerator::OpenBuildFileStreams()
{
if (!this->OpenFileStream(this->CommonFileStream,
cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE)) {
return false;
}
// Write a comment about this file.
*this->CommonFileStream
<< "# This file contains build statements common to all "
"configurations.\n\n";
for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
if (!this->OpenFileStream(this->ConfigFileStreams[config],
GetNinjaFilename(config))) {
return false;
}
// Write a comment about this file.
*this->ConfigFileStreams[config]
<< "# This file contains build statements specific to the \"" << config
<< "\"\n# configuration.\n\n";
}
return true;
}
void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams()
{
if (this->CommonFileStream) {
this->CommonFileStream.reset();
} else {
cmSystemTools::Error("Common file stream was not open.");
}
for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
if (this->ConfigFileStreams[config]) {
this->ConfigFileStreams[config].reset();
} else {
cmSystemTools::Error(
cmStrCat("Config file stream for \"", config, "\" was not open."));
}
}
}
void cmGlobalNinjaMultiGenerator::AppendNinjaFileArgument(
GeneratedMakeCommand& command, const std::string& config) const
{
command.Add("-f");
command.Add(GetNinjaFilename(config));
}
std::string cmGlobalNinjaMultiGenerator::GetNinjaFilename(
const std::string& config)
{
return cmStrCat("build-", config,
cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION);
}
void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs(
cmNinjaDeps& outputs) const
{
for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) {
outputs.push_back(this->NinjaOutputPath(GetNinjaFilename(config)));
}
if (this->Makefiles.front()->GetDefinition(
"CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE")) {
outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
}
}
void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs(
std::vector<std::string>& configs) const
{
auto const oldSize = configs.size();
this->Makefiles.front()->GetConfigurations(configs);
if (configs.size() == oldSize) {
configs.emplace_back();
}
}
bool cmGlobalNinjaMultiGenerator::WriteDefaultBuildFile()
{
auto const* defaultConfig = this->Makefiles.front()->GetDefinition(
"CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE");
if (defaultConfig) {
std::unique_ptr<cmGeneratedFileStream> defaultStream;
if (!this->OpenFileStream(defaultStream, NINJA_BUILD_FILE)) {
return false;
}
*defaultStream << "# This file is a convenience file generated by\n"
<< "# CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.\n\n"
<< "include " << this->GetNinjaFilename(defaultConfig)
<< "\n";
}
return true;
}
+168 -18
View File
@@ -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<std::string> const& linked_target_dirs,
std::string const& arg_lang);
virtual std::string BuildAlias(const std::string& alias,
const std::string& /*config*/) const
{
return alias;
}
virtual std::string ConfigDirectory(const std::string& /*config*/) const
{
return "";
}
cmNinjaDeps& GetByproductsForCleanTarget()
{
return this->ByproductsForCleanTarget;
}
cmNinjaDeps& GetByproductsForCleanTarget(const std::string& config)
{
return this->Configs[config].ByproductsForCleanTarget;
}
protected:
void Generate() override;
bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
virtual bool OpenBuildFileStreams();
virtual void CloseBuildFileStreams();
virtual bool WriteDefaultBuildFile() { return true; }
bool OpenFileStream(std::unique_ptr<cmGeneratedFileStream>& stream,
const std::string& name);
private:
std::string GetEditCacheCommand() const override;
bool FindMakeProgram(cmMakefile* mf) override;
@@ -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<cmCustomCommand const*> CustomCommands;
/// The set of custom command outputs we have seen.
std::set<std::string> CustomCommandOutputs;
@@ -417,11 +470,14 @@ private:
/// The mapping from source file to assumed dependencies.
std::map<std::string, std::set<std::string>> AssumedSourceDependencies;
using TargetAliasMap = std::map<std::string, cmGeneratorTarget*>;
struct TargetAlias
{
cmGeneratorTarget* GeneratorTarget;
std::string Config;
};
using TargetAliasMap = std::map<std::string, TargetAlias>;
TargetAliasMap TargetAliases;
std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures;
/// the local cache for calls to ConvertToNinjaPath
mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache;
@@ -439,7 +495,101 @@ private:
std::string OutputPathPrefix;
std::string TargetAll;
std::string CMakeCacheFile;
std::set<std::string> AdditionalCleanFiles;
struct ByConfig
{
std::set<std::string> AdditionalCleanFiles;
/// The set of custom commands we have seen.
std::set<cmCustomCommand const*> CustomCommands;
std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures;
TargetAliasMap TargetAliases;
cmNinjaDeps ByproductsForCleanTarget;
};
std::map<std::string, ByConfig> Configs;
cmNinjaDeps ByproductsForCleanTarget;
};
class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator
{
public:
/// The default name of Ninja's common file. Typically: common.ninja.
static const char* NINJA_COMMON_FILE;
/// The default file extension to use for per-config Ninja files.
static const char* NINJA_FILE_EXTENSION;
cmGlobalNinjaMultiGenerator(cmake* cm);
bool IsMultiConfig() const override { return true; }
static cmGlobalGeneratorFactory* NewFactory()
{
return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>();
}
static void GetDocumentation(cmDocumentationEntry& entry);
std::string GetName() const override
{
return cmGlobalNinjaMultiGenerator::GetActualName();
}
static std::string GetActualName() { return "Ninja Multi-Config"; }
std::string BuildAlias(const std::string& alias,
const std::string& config) const override
{
if (config.empty()) {
return alias;
}
return cmStrCat(alias, ":", config);
}
std::string ConfigDirectory(const std::string& config) const override
{
if (!config.empty()) {
return cmStrCat('/', config);
}
return "";
}
const char* GetCMakeCFGIntDir() const override { return "${CONFIGURATION}"; }
std::string ExpandCFGIntDir(const std::string& str,
const std::string& config) const override;
cmGeneratedFileStream* GetConfigFileStream(
const std::string& config) const override
{
return this->ConfigFileStreams.at(config).get();
}
cmGeneratedFileStream* GetCommonFileStream() const override
{
return this->CommonFileStream.get();
}
void AppendNinjaFileArgument(GeneratedMakeCommand& command,
const std::string& config) const override;
static std::string GetNinjaFilename(const std::string& config);
void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override;
void GetQtAutoGenConfigs(std::vector<std::string>& configs) const override;
bool WriteDefaultBuildFile() override;
protected:
bool OpenBuildFileStreams() override;
void CloseBuildFileStreams() override;
private:
std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
ConfigFileStreams;
std::unique_ptr<cmGeneratedFileStream> CommonFileStream;
};
#endif // ! cmGlobalNinjaGenerator_h
+22 -8
View File
@@ -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);
}
+2
View File
@@ -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;
};
+8 -1
View File
@@ -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)
+1
View File
@@ -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;
+73 -18
View File
@@ -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()->GetBuildFileStream();
return *this->GetGlobalNinjaGenerator()->GetConfigFileStream(config);
}
cmGeneratedFileStream& cmLocalNinjaGenerator::GetCommonFileStream() const
{
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<std::string>& 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);
}
}
}
+7 -2
View File
@@ -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);
+3 -2
View File
@@ -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();
+109 -45
View File
@@ -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<std::string> preLinkCmdLines;
std::vector<std::string> postBuildCmdLines;
std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
&preLinkCmdLines,
&postBuildCmdLines };
for (unsigned i = 0; i != 3; ++i) {
for (cmCustomCommand const& cc : *cmdLists[i]) {
cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator());
localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
std::transform(ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(byproducts), MapToNinjaPath());
if (config == fileConfig) {
std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
&preLinkCmdLines,
&postBuildCmdLines };
for (unsigned i = 0; i != 3; ++i) {
for (cmCustomCommand const& cc : *cmdLists[i]) {
cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator());
localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
std::transform(ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(byproducts), MapToNinjaPath());
std::transform(
ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(globalGen->GetByproductsForCleanTarget()),
MapToNinjaPath());
}
}
}
@@ -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.
+2 -1
View File
@@ -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);
+123 -79
View File
@@ -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
@@ -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<cmSourceFile const*> 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<std::string>& ccoutputs = ccg.GetOutputs();
const std::vector<std::string>& 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<cmSourceFile const*> 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(
+44 -23
View File
@@ -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<std::string, cmNinjaDeps> DDIFiles;
// Swift Support
Json::Value SwiftOutputMap;
std::vector<cmCustomCommand const*> CustomCommands;
cmNinjaDeps ExtraFiles;
struct ByConfig
{
/// List of object files for this target.
cmNinjaDeps Objects;
// Fortran Support
std::map<std::string, cmNinjaDeps> DDIFiles;
// Swift Support
Json::Value SwiftOutputMap;
std::vector<cmCustomCommand const*> CustomCommands;
cmNinjaDeps ExtraFiles;
};
std::map<std::string, ByConfig> Configs;
};
#endif // ! cmNinjaTargetGenerator_h
+30 -6
View File
@@ -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);
}
}
+18 -5
View File
@@ -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;
}
+6 -3
View File
@@ -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);
+10 -3
View File
@@ -1042,9 +1042,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
}
// Compose command lines
cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen",
this->AutogenTarget.InfoFile, "$<CONFIGURATION>" });
// TODO: Refactor autogen to output a per-config mocs_compilation.cpp instead
// of fiddling with the include directories
std::vector<std::string> configs;
this->GlobalGen->GetQtAutoGenConfigs(configs);
cmCustomCommandLines commandLines;
for (auto const& config : configs) {
commandLines.push_back(cmMakeCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen",
this->AutogenTarget.InfoFile, config }));
}
// Use PRE_BUILD on demand
bool usePRE_BUILD = false;
+10
View File
@@ -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();
+3
View File
@@ -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;
};
+8 -1
View File
@@ -176,6 +176,7 @@ public:
bool IsImportedTarget;
bool ImportedGloballyVisible;
bool BuildInterfaceIncludesAppended;
bool PerConfig;
std::set<BT<std::string>> Utilities;
std::vector<cmCustomCommand> PreBuildCommands;
std::vector<cmCustomCommand> PreLinkCommands;
@@ -213,7 +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<cmTargetInternals>())
{
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
{
+2 -1
View File
@@ -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;
+1
View File
@@ -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());
+4 -3
View File
@@ -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 $<CONFIG>
--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=$<CONFIG>"
-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"
@@ -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
@@ -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)
+1 -1
View File
@@ -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()
+7 -1
View File
@@ -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 /$<CONFIG>)
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
+10 -4
View File
@@ -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 /$<CONFIG>)
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)
+2 -2
View File
@@ -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}/$<CONFIG>")
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=$<CONFIG> -P ${OutDir_SOURCE_DIR}/OutDir.cmake
DEPENDS COnly ${OutDir_SOURCE_DIR}/OutDir.cmake
)
include_directories(${top})
+3 -3
View File
@@ -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}")
+1 -1
View File
@@ -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}
+1 -1
View File
@@ -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
@@ -1,5 +1,6 @@
^\{
"componentGroups" :[ ]
("buildConfig" : "Debug",
)? "componentGroups" :[ ]
\{
"f12" :[ ]
\{
@@ -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})
+1 -1
View File
@@ -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)
+12 -12
View File
@@ -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"])
+3
View File
@@ -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
+12 -5
View File
@@ -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()
@@ -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=/$<CONFIG>)
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
@@ -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")
@@ -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)
@@ -1 +1,2 @@
Unable to find executable:.*MyThirdPartyDependency/src/thirdparty
Unable to find executable:.*MyThirdPartyDependency/src(/[^/
]+)?/thirdparty
+2 -2
View File
@@ -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)
@@ -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)
@@ -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\.
@@ -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)