Merge topic 'ninja-multi'

8c062f9d99 Help: Add documentation and release notes for multi-config Ninja
e0478cc646 Tests: Add test for Multi-Configuration Ninja generator
5a8a9f7229 Ninja: Add multi-config variant
3bc63e99e4 Refactor: Prepare Ninja generator for multi-config

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4086
This commit is contained in:
Brad King
2019-12-16 15:06:26 +00:00
committed by Kitware Robot
143 changed files with 3676 additions and 908 deletions
+74
View File
@@ -0,0 +1,74 @@
Ninja Multi-Config
------------------
Generates multiple ``build-<Config>.ninja`` files.
This generator is very much like the :generator:`Ninja` generator, but with
some key differences. Only these differences will be discussed in this
document.
Unlike the :generator:`Ninja` generator, ``Ninja Multi-Config`` generates
multiple configurations at once with :variable:`CMAKE_CONFIGURATION_TYPES`
instead of only one configuration with :variable:`CMAKE_BUILD_TYPE`. One
``build-<Config>.ninja`` file will be generated for each of these
configurations (with ``<Config>`` being the configuration name.) No
``build.ninja`` file is generated, unless
:variable:`CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE` is specified. You must specify
the desired ``build-<Config>.ninja`` file with ``ninja -f``. Running
``cmake --build . --config <Config> --target <target>`` will run Ninja with
``build-<Config>.ninja`` as the ``-f`` file and ``<target>`` as the build
target.
Executables and libraries of any configuration can be built regardless of which
``build-<Config>.ninja`` file is used, simply by specifying
``<target>:<Config>`` as the Ninja target. You can also specify
``<target>:all`` to build a target in all configurations. Each
``build-<Config>.ninja`` file will additionally have ``<target>`` targets which
are aliases for ``<target>:<Config>``. However, custom commands and custom
targets will always use the configuration specified in
``build-<Config>.ninja``. This is due to the fact that it is impossible in
Ninja for the same file to be output with different commands in the same build
graph.
Consider the following example:
.. code-block:: cmake
cmake_minimum_required(VERSION 3.16)
project(MultiConfigNinja C)
add_executable(generator generator.c)
add_custom_command(OUTPUT generated.c COMMAND generator generated.c)
add_library(generated ${CMAKE_BINARY_DIR}/generated.c)
Now assume you configure the project with ``Ninja Multi-Config`` and run one of
the following commands:
.. code-block:: shell
ninja -f build-Debug.ninja generated
# OR
cmake --build . --config Debug --target generated
This would build the ``Debug`` configuration of ``generator``, which would be
used to generate ``generated.c``, which would be used to build the ``Debug``
configuration of ``generated``.
But if you run the following instead:
.. code-block:: shell
ninja -f build-Release.ninja generated:Debug
# OR
cmake --build . --config Release --target generated:Debug
This would build the ``Release`` configuration of ``generator``, which would be
used to generate ``generated.c``, which would be used to build the ``Debug``
configuration of ``generated``. This is useful for running a release-optimized
version of a generator utility while still building the debug version of the
targets built with the generated code.
As a convenience, ``Ninja Multi-Config`` offers a
:variable:`CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE` setting. If this variable is
specified, a ``build.ninja`` file will be generated which points to the
specified ``build-<Config>.ninja`` file.
+7 -1
View File
@@ -1,7 +1,7 @@
Ninja
-----
Generates build.ninja files.
Generates ``build.ninja`` files.
A ``build.ninja`` file is generated into the build tree. Use the ninja
program to build the project through the ``all`` target and install the
@@ -38,3 +38,9 @@ features have not been integrated into upstream Ninja. Kitware maintains
a branch of Ninja with the required features on `github.com/Kitware/ninja`_.
.. _`github.com/Kitware/ninja`: https://github.com/Kitware/ninja/tree/features-for-fortran#readme
See Also
^^^^^^^^
The :generator:`Ninja Multi-Config` generator is similar to the ``Ninja``
generator, but generates multiple configurations at once.
+3 -2
View File
@@ -52,13 +52,14 @@ Makefile Generators
/generator/Unix Makefiles
/generator/Watcom WMake
Ninja Generator
^^^^^^^^^^^^^^^
Ninja Generators
^^^^^^^^^^^^^^^^
.. toctree::
:maxdepth: 1
/generator/Ninja
/generator/Ninja Multi-Config
.. _`IDE Build Tool Generators`:
+1
View File
@@ -214,6 +214,7 @@ Variables that Change Behavior
/variable/CMAKE_MESSAGE_INDENT
/variable/CMAKE_MESSAGE_LOG_LEVEL
/variable/CMAKE_MODULE_PATH
/variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE
/variable/CMAKE_POLICY_DEFAULT_CMPNNNN
/variable/CMAKE_POLICY_WARNING_CMPNNNN
/variable/CMAKE_PREFIX_PATH
@@ -0,0 +1,6 @@
multi-configuration-ninja
-------------------------
* :manual:`cmake(1)` gained a :generator:`Ninja Multi-Config` generator,
which is similar to the :generator:`Ninja` generator but can be used to build
multiple configurations at once.
@@ -0,0 +1,7 @@
CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE
------------------------------------
Specifies a configuration type to use as the default in ``build.ninja`` for the
:generator:`Ninja Multi-Config` generator.
If this variable is not specified, no ``build.ninja`` file is generated.
+43 -33
View File
@@ -25,27 +25,29 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
, GlobalCommonGenerator(static_cast<cmGlobalCommonGenerator*>(
gt->LocalGenerator->GetGlobalGenerator()))
, ConfigName(LocalCommonGenerator->GetConfigName())
, ConfigNames(LocalCommonGenerator->GetConfigNames())
{
}
cmCommonTargetGenerator::~cmCommonTargetGenerator() = default;
std::string const& cmCommonTargetGenerator::GetConfigName() const
std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const
{
return this->ConfigName;
return this->ConfigNames;
}
const char* cmCommonTargetGenerator::GetFeature(const std::string& feature)
const char* cmCommonTargetGenerator::GetFeature(const std::string& feature,
const std::string& config)
{
return this->GeneratorTarget->GetFeature(feature, this->ConfigName);
return this->GeneratorTarget->GetFeature(feature, config);
}
void cmCommonTargetGenerator::AddModuleDefinitionFlag(
cmLinkLineComputer* linkLineComputer, std::string& flags)
cmLinkLineComputer* linkLineComputer, std::string& flags,
const std::string& config)
{
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
this->GeneratorTarget->GetModuleDefinitionInfo(config);
if (!mdi || mdi->DefFile.empty()) {
return;
}
@@ -94,57 +96,60 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags(
}
}
std::string cmCommonTargetGenerator::GetFlags(const std::string& l)
std::string cmCommonTargetGenerator::GetFlags(const std::string& l,
const std::string& config)
{
auto i = this->FlagsByLanguage.find(l);
if (i == this->FlagsByLanguage.end()) {
auto i = this->Configs[config].FlagsByLanguage.find(l);
if (i == this->Configs[config].FlagsByLanguage.end()) {
std::string flags;
this->LocalCommonGenerator->GetTargetCompileFlags(
this->GeneratorTarget, this->ConfigName, l, flags);
this->LocalCommonGenerator->GetTargetCompileFlags(this->GeneratorTarget,
config, l, flags);
ByLanguageMap::value_type entry(l, flags);
i = this->FlagsByLanguage.insert(entry).first;
i = this->Configs[config].FlagsByLanguage.insert(entry).first;
}
return i->second;
}
std::string cmCommonTargetGenerator::GetDefines(const std::string& l)
std::string cmCommonTargetGenerator::GetDefines(const std::string& l,
const std::string& config)
{
auto i = this->DefinesByLanguage.find(l);
if (i == this->DefinesByLanguage.end()) {
auto i = this->Configs[config].DefinesByLanguage.find(l);
if (i == this->Configs[config].DefinesByLanguage.end()) {
std::set<std::string> defines;
this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget,
this->ConfigName, l, defines);
this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, config,
l, defines);
std::string definesString;
this->LocalCommonGenerator->JoinDefines(defines, definesString, l);
ByLanguageMap::value_type entry(l, definesString);
i = this->DefinesByLanguage.insert(entry).first;
i = this->Configs[config].DefinesByLanguage.insert(entry).first;
}
return i->second;
}
std::string cmCommonTargetGenerator::GetIncludes(std::string const& l)
std::string cmCommonTargetGenerator::GetIncludes(std::string const& l,
const std::string& config)
{
auto i = this->IncludesByLanguage.find(l);
if (i == this->IncludesByLanguage.end()) {
auto i = this->Configs[config].IncludesByLanguage.find(l);
if (i == this->Configs[config].IncludesByLanguage.end()) {
std::string includes;
this->AddIncludeFlags(includes, l);
this->AddIncludeFlags(includes, l, config);
ByLanguageMap::value_type entry(l, includes);
i = this->IncludesByLanguage.insert(entry).first;
i = this->Configs[config].IncludesByLanguage.insert(entry).first;
}
return i->second;
}
std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories()
const
std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories(
const std::string& config) const
{
std::vector<std::string> dirs;
std::set<cmGeneratorTarget const*> emitted;
if (cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(this->ConfigName)) {
this->GeneratorTarget->GetLinkInformation(config)) {
cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
for (auto const& item : items) {
cmGeneratorTarget const* linkee = item.Target;
@@ -165,19 +170,24 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories()
return dirs;
}
std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const
std::string cmCommonTargetGenerator::ComputeTargetCompilePDB(
const std::string& config) const
{
std::string compilePdbPath;
if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
return compilePdbPath;
}
compilePdbPath =
this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName());
compilePdbPath = this->GeneratorTarget->GetCompilePDBPath(config);
if (compilePdbPath.empty()) {
// Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`.
// A trailing slash tells the toolchain to add its default file name.
compilePdbPath = this->GeneratorTarget->GetSupportDirectory() + "/";
compilePdbPath = this->GeneratorTarget->GetSupportDirectory();
if (this->GlobalCommonGenerator->IsMultiConfig()) {
compilePdbPath += "/";
compilePdbPath += config;
}
compilePdbPath += "/";
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
// Match VS default for static libs: `$(IntDir)$(ProjectName).pdb`.
compilePdbPath += this->GeneratorTarget->GetName();
@@ -188,10 +198,10 @@ std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const
return compilePdbPath;
}
std::string cmCommonTargetGenerator::GetManifests()
std::string cmCommonTargetGenerator::GetManifests(const std::string& config)
{
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
this->GeneratorTarget->GetManifests(manifest_srcs, config);
std::vector<std::string> manifests;
manifests.reserve(manifest_srcs.size());
+24 -16
View File
@@ -25,42 +25,50 @@ public:
cmCommonTargetGenerator(cmGeneratorTarget* gt);
virtual ~cmCommonTargetGenerator();
std::string const& GetConfigName() const;
std::vector<std::string> const& GetConfigNames() const;
protected:
// Feature query methods.
const char* GetFeature(const std::string& feature);
const char* GetFeature(const std::string& feature,
const std::string& config);
// Helper to add flag for windows .def file.
void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer,
std::string& flags);
std::string& flags, const std::string& config);
cmGeneratorTarget* GeneratorTarget;
cmMakefile* Makefile;
cmLocalCommonGenerator* LocalCommonGenerator;
cmGlobalCommonGenerator* GlobalCommonGenerator;
std::string ConfigName;
std::vector<std::string> ConfigNames;
void AppendFortranFormatFlags(std::string& flags,
cmSourceFile const& source);
virtual void AddIncludeFlags(std::string& flags,
std::string const& lang) = 0;
virtual void AddIncludeFlags(std::string& flags, std::string const& lang,
const std::string& config) = 0;
void AppendOSXVerFlag(std::string& flags, const std::string& lang,
const char* name, bool so);
using ByLanguageMap = std::map<std::string, std::string>;
std::string GetFlags(const std::string& l);
ByLanguageMap FlagsByLanguage;
std::string GetDefines(const std::string& l);
ByLanguageMap DefinesByLanguage;
std::string GetIncludes(std::string const& l);
ByLanguageMap IncludesByLanguage;
std::string GetManifests();
std::string GetFlags(const std::string& l, const std::string& config);
std::string GetDefines(const std::string& l, const std::string& config);
std::string GetIncludes(std::string const& l, const std::string& config);
std::string GetManifests(const std::string& config);
std::vector<std::string> GetLinkedTargetDirectories() const;
std::string ComputeTargetCompilePDB() const;
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);
+489 -125
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,23 +933,22 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
"Assume dependencies for generated source file.",
/*depfile*/ "", /*job_pool*/ "",
/*uses_terminal*/ false,
/*restat*/ true, cmNinjaDeps(1, asd.first),
/*restat*/ true, cmNinjaDeps(1, asd.first), "",
cmNinjaDeps(), orderOnlyDeps);
}
}
std::string OrderDependsTargetForTarget(cmGeneratorTarget const* target)
std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget(
cmGeneratorTarget const* target, const std::string& config)
{
return "cmake_object_order_depends_target_" + target->GetName();
return "cmake_object_order_depends_target_" + target->GetName() + "_" +
config;
}
void cmGlobalNinjaGenerator::AppendTargetOutputs(
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
cmNinjaTargetDepends depends)
const std::string& config, cmNinjaTargetDepends depends)
{
std::string configName =
target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
// for frameworks, we want the real name, not smple name
// frameworks always appear versioned, and the build.ninja
// will always attempt to manage symbolic links instead
@@ -932,19 +960,19 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::MODULE_LIBRARY: {
if (depends == DependOnTargetOrdering) {
outputs.push_back(OrderDependsTargetForTarget(target));
outputs.push_back(OrderDependsTargetForTarget(target, config));
break;
}
}
// FALLTHROUGH
case cmStateEnums::EXECUTABLE: {
outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath(
configName, cmStateEnums::RuntimeBinaryArtifact, realname)));
config, cmStateEnums::RuntimeBinaryArtifact, realname)));
break;
}
case cmStateEnums::OBJECT_LIBRARY: {
if (depends == DependOnTargetOrdering) {
outputs.push_back(OrderDependsTargetForTarget(target));
outputs.push_back(OrderDependsTargetForTarget(target, config));
break;
}
}
@@ -954,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;
}
@@ -965,6 +997,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
void cmGlobalNinjaGenerator::AppendTargetDepends(
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
const std::string& config, const std::string& fileConfig,
cmNinjaTargetDepends depends)
{
if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
@@ -973,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;
@@ -982,7 +1015,14 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
this->AppendTargetOutputs(targetDep, outs, depends);
// For some reason, object libraries show up as "utility" dependencies
// even though they're used for linking. Treat them as link dependencies.
if (targetDep.IsUtil() &&
targetDep->GetType() != cmStateEnums::OBJECT_LIBRARY) {
this->AppendTargetOutputs(targetDep, outs, fileConfig, depends);
} else {
this->AppendTargetOutputs(targetDep, outs, config, depends);
}
}
std::sort(outs.begin(), outs.end());
cmAppend(outputs, outs);
@@ -990,21 +1030,24 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
}
void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmGeneratorTarget const* target, cmNinjaDeps& outputs)
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
const std::string& config)
{
cmNinjaOuts outs;
this->AppendTargetDependsClosure(target, outs, true);
this->AppendTargetDependsClosure(target, outs, config, true);
cmAppend(outputs, outs);
}
void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmGeneratorTarget const* target, cmNinjaOuts& outputs, bool omit_self)
cmGeneratorTarget const* target, cmNinjaOuts& outputs,
const std::string& config, bool omit_self)
{
// try to locate the target in the cache
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
@@ -1019,10 +1062,10 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
}
// Collect the dependent targets for _this_ target
this->AppendTargetDependsClosure(dep_target, this_outs, false);
this->AppendTargetDependsClosure(dep_target, this_outs, config, false);
}
find = this->TargetDependsClosures.emplace_hint(find, target,
std::move(this_outs));
find = this->Configs[config].TargetDependsClosures.emplace_hint(
find, target, std::move(this_outs));
}
// now fill the outputs of the final result from the newly generated cache
@@ -1032,29 +1075,48 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
// finally generate the outputs of the target itself, if applicable
cmNinjaDeps outs;
if (!omit_self) {
this->AppendTargetOutputs(target, outs);
this->AppendTargetOutputs(target, outs, config);
}
outputs.insert(outs.begin(), outs.end());
}
void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
cmGeneratorTarget* target)
cmGeneratorTarget* target,
const std::string& config)
{
std::string buildAlias = this->NinjaOutputPath(alias);
std::string outputPath = this->NinjaOutputPath(alias);
std::string buildAlias = this->BuildAlias(outputPath, config);
cmNinjaDeps outputs;
this->AppendTargetOutputs(target, outputs);
// Mark the target's outputs as ambiguous to ensure that no other target uses
// the output as an alias.
this->AppendTargetOutputs(target, outputs, config);
// Mark the target's outputs as ambiguous to ensure that no other target
// uses the output as an alias.
for (std::string const& output : outputs) {
TargetAliases[output] = nullptr;
this->TargetAliases[output].GeneratorTarget = nullptr;
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,14 +1139,43 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
continue;
}
// Outputs
build.Outputs[0] = ta.first;
// Explicit depdendencies
build.Outputs.front() = ta.first;
build.ExplicitDeps.clear();
this->AppendTargetOutputs(ta.second, build.ExplicitDeps);
// Write
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);
}
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);
}
}
}
}
void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
@@ -1100,24 +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) {
this->AppendTargetOutputs(t.GT, build.ExplicitDeps);
build.Outputs.emplace_back();
for (auto const& config : configs) {
build.ExplicitDeps.clear();
build.Outputs.front() = this->BuildAlias(
this->ConvertToNinjaPath(currentBinaryDir + "/all"), config);
configDeps.emplace_back(build.Outputs.front());
for (DirectoryTarget::Target const& t : dt.Targets) {
if (!t.ExcludeFromAll) {
this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config);
}
}
for (DirectoryTarget::Dir const& d : dt.Children) {
if (!d.ExcludeFromAll) {
build.ExplicitDeps.emplace_back(this->BuildAlias(
this->ConvertToNinjaPath(d.Path + "/all"), config));
}
}
// Write target
this->WriteBuild(os, build);
}
// 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);
}
}
for (DirectoryTarget::Dir const& d : dt.Children) {
if (!d.ExcludeFromAll) {
build.ExplicitDeps.emplace_back(
this->ConvertToNinjaPath(d.Path + "/all"));
// 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);
}
// Write target
this->WriteBuild(os, build);
}
}
@@ -1250,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)
@@ -1290,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()) {
@@ -1420,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;
@@ -1434,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);
@@ -1450,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...";
@@ -1462,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;
@@ -1479,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);
}
}
}
@@ -2001,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;
}
+175 -20
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,20 +298,43 @@ public:
ASD.insert(deps.begin(), deps.end());
}
static std::string OrderDependsTargetForTarget(
cmGeneratorTarget const* target, const std::string& config);
void AppendTargetOutputs(
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
const std::string& config,
cmNinjaTargetDepends depends = DependOnTargetArtifact);
void AppendTargetDepends(
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
const std::string& config, const std::string& fileConfig,
cmNinjaTargetDepends depends = DependOnTargetArtifact);
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
cmNinjaDeps& outputs);
cmNinjaDeps& outputs,
const std::string& config);
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
cmNinjaOuts& outputs, bool omit_self);
cmNinjaOuts& outputs,
const std::string& config, bool omit_self);
void AppendDirectoryForConfig(const std::string& prefix,
const std::string& config,
const std::string& suffix,
std::string& dir) override;
virtual void AppendNinjaFileArgument(GeneratedMakeCommand& /*command*/,
const std::string& /*config*/) const
{
}
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);
void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target,
const std::string& config);
void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
@@ -331,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;
@@ -344,9 +408,6 @@ private:
cmMakefile* mf) const override;
bool CheckFortran(cmMakefile* mf) const;
bool OpenBuildFileStream();
void CloseBuildFileStream();
void CloseCompileCommandsStream();
bool OpenRulesFileStream();
@@ -391,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;
@@ -412,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;
@@ -434,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;
};
+3 -7
View File
@@ -17,13 +17,9 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
: cmLocalGenerator(gg, mf)
, WorkingDirectory(std::move(wd))
{
// Store the configuration name that will be generated.
if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
// Use the build type given by the user.
this->ConfigName = config;
} else {
// No configuration type given.
this->ConfigName.clear();
this->Makefile->GetConfigurations(this->ConfigNames);
if (this->ConfigNames.empty()) {
this->ConfigNames.emplace_back();
}
}
+6 -2
View File
@@ -7,6 +7,7 @@
#include <map>
#include <string>
#include <vector>
#include "cmLocalGenerator.h"
@@ -25,7 +26,10 @@ public:
std::string wd);
~cmLocalCommonGenerator() override;
std::string const& GetConfigName() const { return this->ConfigName; }
std::vector<std::string> const& GetConfigNames() const
{
return this->ConfigNames;
}
std::string GetWorkingDirectory() const { return this->WorkingDirectory; }
@@ -39,7 +43,7 @@ public:
protected:
std::string WorkingDirectory;
std::string ConfigName;
std::vector<std::string> ConfigNames;
friend class cmCommonTargetGenerator;
};
+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;
+102 -37
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,12 +94,20 @@ void cmLocalNinjaGenerator::Generate()
}
auto tg = cmNinjaTargetGenerator::New(target.get());
if (tg) {
tg->Generate();
if (target->Target->IsPerConfig()) {
for (auto const& config : this->GetConfigNames()) {
tg->Generate(config);
}
} else {
tg->Generate("");
}
}
}
this->WriteCustomCommandBuildStatements();
this->AdditionalCleanFiles();
for (auto const& config : this->GetConfigNames()) {
this->WriteCustomCommandBuildStatements(config);
this->AdditionalCleanFiles(config);
}
}
// TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it.
@@ -140,9 +154,15 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
// Private methods.
cmGeneratedFileStream& cmLocalNinjaGenerator::GetBuildFileStream() const
cmGeneratedFileStream& cmLocalNinjaGenerator::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
@@ -162,10 +182,22 @@ cmake* cmLocalNinjaGenerator::GetCMakeInstance()
void cmLocalNinjaGenerator::WriteBuildFileTop()
{
// For the build file.
this->WriteProjectHeader(this->GetBuildFileStream());
this->WriteNinjaRequiredVersion(this->GetBuildFileStream());
this->WriteNinjaFilesInclusion(this->GetBuildFileStream());
this->WriteProjectHeader(this->GetCommonFileStream());
if (this->GetGlobalGenerator()->IsMultiConfig()) {
for (auto const& config : this->GetConfigNames()) {
auto& stream = this->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());
@@ -175,7 +207,8 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Project: " << this->GetProjectName() << std::endl
<< "# Configuration: " << this->ConfigName << std::endl;
<< "# Configurations: " << cmJoin(this->GetConfigNames(), ", ")
<< std::endl;
cmGlobalNinjaGenerator::WriteDivider(os);
}
@@ -206,6 +239,14 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os)
<< std::endl;
}
void cmLocalNinjaGenerator::WriteNinjaConfigurationVariable(
std::ostream& os, const std::string& config)
{
cmGlobalNinjaGenerator::WriteVariable(
os, "CONFIGURATION", config,
"Set configuration variable for custom commands.");
}
void cmLocalNinjaGenerator::WritePools(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
@@ -235,7 +276,21 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os)
}
}
void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os)
void cmLocalNinjaGenerator::WriteNinjaFilesInclusionConfig(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Include auxiliary files.\n"
<< "\n";
cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
std::string const ninjaCommonFile =
ng->NinjaOutputPath(cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE);
std::string const commonFilePath = ng->EncodePath(ninjaCommonFile);
cmGlobalNinjaGenerator::WriteInclude(os, commonFilePath,
"Include common file.");
os << "\n";
}
void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Include auxiliary files.\n"
@@ -263,25 +318,30 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
}
void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target,
cmNinjaDeps& outputs)
cmNinjaDeps& outputs,
const std::string& config)
{
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs);
this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs,
config);
}
void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target,
cmNinjaDeps& outputs,
const std::string& config,
const std::string& fileConfig,
cmNinjaTargetDepends depends)
{
this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs,
depends);
this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, config,
fileConfig, depends);
}
void cmLocalNinjaGenerator::AppendCustomCommandDeps(
cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps)
cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps,
const std::string& config)
{
for (std::string const& i : ccg.GetDepends()) {
std::string dep;
if (this->GetRealDependency(i, this->GetConfigName(), dep)) {
if (this->GetRealDependency(i, config, dep)) {
ninjaDeps.push_back(
this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep));
}
@@ -416,6 +476,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
void cmLocalNinjaGenerator::AppendCustomCommandLines(
cmCustomCommandGenerator const& ccg, std::vector<std::string>& cmdLines)
{
auto* gg = this->GetGlobalNinjaGenerator();
if (ccg.GetNumberOfCommands() > 0) {
std::string wd = ccg.GetWorkingDirectory();
if (wd.empty()) {
@@ -437,8 +499,10 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(
for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
cmdLines.push_back(launcher +
this->ConvertToOutputFormat(ccg.GetCommand(i),
cmOutputConverter::SHELL));
this->ConvertToOutputFormat(
ccg.GetCommand(i),
gg->IsMultiConfig() ? cmOutputConverter::NINJAMULTI
: cmOutputConverter::SHELL));
std::string& cmd = cmdLines.back();
ccg.AppendArguments(i, cmd);
@@ -446,14 +510,15 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(
}
void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps)
cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps,
const std::string& config)
{
cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator();
if (gg->SeenCustomCommand(cc)) {
if (gg->SeenCustomCommand(cc, config)) {
return;
}
cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this);
cmCustomCommandGenerator ccg(*cc, config, this);
const std::vector<std::string>& outputs = ccg.GetOutputs();
const std::vector<std::string>& byproducts = ccg.GetByproducts();
@@ -484,7 +549,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
}
cmNinjaDeps ninjaDeps;
this->AppendCustomCommandDeps(ccg, ninjaDeps);
this->AppendCustomCommandDeps(ccg, ninjaDeps, config);
std::vector<std::string> cmdLines;
this->AppendCustomCommandLines(ccg, cmdLines);
@@ -495,7 +560,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
build.Outputs = std::move(ninjaOutputs);
build.ExplicitDeps = std::move(ninjaDeps);
build.OrderOnlyDeps = orderOnlyDeps;
gg->WriteBuild(this->GetBuildFileStream(), build);
gg->WriteBuild(this->GetConfigFileStream(config), build);
} else {
std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
// Hash full path to make unique.
@@ -507,8 +572,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
this->BuildCommandLine(cmdLines, customStep),
this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
orderOnlyDeps);
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config,
ninjaDeps, orderOnlyDeps);
}
}
@@ -524,7 +589,8 @@ void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
ins.first->second.insert(target);
}
void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements(
const std::string& config)
{
for (cmCustomCommand const* customCommand : this->CustomCommands) {
auto i = this->CustomCommandTargets.find(customCommand);
@@ -542,15 +608,16 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
auto j = i->second.begin();
assert(j != i->second.end());
std::vector<std::string> ccTargetDeps;
this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j,
ccTargetDeps);
this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(
*j, ccTargetDeps, config);
std::sort(ccTargetDeps.begin(), ccTargetDeps.end());
++j;
for (; j != i->second.end(); ++j) {
std::vector<std::string> jDeps;
std::vector<std::string> depsIntersection;
this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps);
this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps,
config);
std::sort(jDeps.begin(), jDeps.end());
std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(),
jDeps.begin(), jDeps.end(),
@@ -558,7 +625,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
ccTargetDeps = depsIntersection;
}
this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps);
this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps, config);
}
}
@@ -599,15 +666,13 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
return launcher;
}
void cmLocalNinjaGenerator::AdditionalCleanFiles()
void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config)
{
if (const char* prop_value =
this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
std::vector<std::string> cleanFiles;
{
cmExpandList(cmGeneratorExpression::Evaluate(
prop_value, this,
this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")),
cmExpandList(cmGeneratorExpression::Evaluate(prop_value, this, config),
cleanFiles);
}
std::string const& binaryDir = this->GetCurrentBinaryDirectory();
@@ -615,7 +680,7 @@ void cmLocalNinjaGenerator::AdditionalCleanFiles()
for (std::string const& cleanFile : cleanFiles) {
// Support relative paths
gg->AddAdditionalCleanFile(
cmSystemTools::CollapseFullPath(cleanFile, binaryDir));
cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config);
}
}
}
+16 -8
View File
@@ -64,9 +64,11 @@ public:
std::string const& customStep = std::string(),
cmGeneratorTarget const* target = nullptr) const;
void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs,
const std::string& config);
void AppendTargetDepends(
cmGeneratorTarget* target, cmNinjaDeps& outputs,
cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config,
const std::string& fileConfig,
cmNinjaTargetDepends depends = DependOnTargetArtifact);
void AddCustomCommandTarget(cmCustomCommand const* cc,
@@ -74,7 +76,8 @@ public:
void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg,
std::vector<std::string>& cmdLines);
void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg,
cmNinjaDeps& ninjaDeps);
cmNinjaDeps& ninjaDeps,
const std::string& config);
protected:
std::string ConvertToIncludeReference(
@@ -83,20 +86,25 @@ protected:
bool forceFullPaths = false) override;
private:
cmGeneratedFileStream& GetBuildFileStream() const;
cmGeneratedFileStream& 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);
void WriteCustomCommandBuildStatement(cmCustomCommand const* cc,
const cmNinjaDeps& orderOnlyDeps);
const cmNinjaDeps& orderOnlyDeps,
const std::string& config);
void WriteCustomCommandBuildStatements();
void WriteCustomCommandBuildStatements(const std::string& config);
std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
@@ -104,7 +112,7 @@ private:
std::string const& customStep,
cmGeneratorTarget const* target) const;
void AdditionalCleanFiles();
void AdditionalCleanFiles(const std::string& config);
std::string HomeRelativeOutputPath;
+15 -7
View File
@@ -3,6 +3,7 @@
#include "cmLocalUnixMakefileGenerator3.h"
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <sstream>
#include <utility>
@@ -106,6 +107,13 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() = default;
std::string cmLocalUnixMakefileGenerator3::GetConfigName() const
{
auto const& configNames = this->GetConfigNames();
assert(configNames.size() == 1);
return configNames.front();
}
void cmLocalUnixMakefileGenerator3::Generate()
{
// Record whether some options are enabled to avoid checking many
@@ -162,7 +170,7 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles(
continue;
}
std::vector<cmSourceFile const*> objectSources;
gt->GetObjectSources(objectSources, this->ConfigName);
gt->GetObjectSources(objectSources, this->GetConfigName());
// Compute full path to object file directory for this target.
std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(),
'/', this->GetTargetDirectory(gt.get()), '/');
@@ -401,7 +409,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
// Add a local name for the rule to relink the target before
// installation.
if (target->NeedRelinkBeforeInstall(this->ConfigName)) {
if (target->NeedRelinkBeforeInstall(this->GetConfigName())) {
makeTargetName = cmStrCat(
this->GetRelativeTargetDirectory(target.get()), "/preinstall");
localName = cmStrCat(target->GetName(), "/preinstall");
@@ -858,7 +866,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepends(
std::vector<std::string>& depends, const std::vector<cmCustomCommand>& ccs)
{
for (cmCustomCommand const& cc : ccs) {
cmCustomCommandGenerator ccg(cc, this->ConfigName, this);
cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this);
this->AppendCustomDepend(depends, ccg);
}
}
@@ -869,7 +877,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepend(
for (std::string const& d : ccg.GetDepends()) {
// Lookup the real name of the dependency in case it is a CMake target.
std::string dep;
if (this->GetRealDependency(d, this->ConfigName, dep)) {
if (this->GetRealDependency(d, this->GetConfigName(), dep)) {
depends.push_back(std::move(dep));
}
}
@@ -880,7 +888,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommands(
cmGeneratorTarget* target, std::string const& relative)
{
for (cmCustomCommand const& cc : ccs) {
cmCustomCommandGenerator ccg(cc, this->ConfigName, this);
cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this);
this->AppendCustomCommand(commands, ccg, target, relative, true);
}
}
@@ -1839,7 +1847,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
// Build a list of preprocessor definitions for the target.
std::set<std::string> defines;
this->GetTargetDefines(target, this->ConfigName, implicitLang.first,
this->GetTargetDefines(target, this->GetConfigName(), implicitLang.first,
defines);
if (!defines.empty()) {
/* clang-format off */
@@ -1863,7 +1871,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
std::vector<std::string> includes;
this->GetIncludeDirectories(includes, target, implicitLang.first,
this->ConfigName);
this->GetConfigName());
std::string binaryDir = this->GetState()->GetBinaryDirectory();
if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
std::string const& sourceDir = this->GetState()->GetSourceDirectory();
+2
View File
@@ -33,6 +33,8 @@ public:
cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf);
~cmLocalUnixMakefileGenerator3() override;
std::string GetConfigName() const;
void ComputeHomeRelativeOutputPath() override;
/**
+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();
+29 -26
View File
@@ -35,10 +35,9 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator(
{
this->CustomCommandDriver = OnDepends;
this->TargetNames =
this->GeneratorTarget->GetExecutableNames(this->ConfigName);
this->GeneratorTarget->GetExecutableNames(this->GetConfigName());
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
@@ -64,7 +63,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
// write the link rules
this->WriteExecutableRule(false);
if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) {
if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->GetConfigName())) {
// Write rules to link an installable version of the target.
this->WriteExecutableRule(true);
}
@@ -85,7 +84,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
{
#ifndef CMAKE_BOOTSTRAP
const bool requiresDeviceLinking = requireDeviceLinking(
*this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
*this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName());
if (!requiresDeviceLinking) {
return;
}
@@ -141,10 +140,10 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
// Add language feature flags.
this->LocalGenerator->AddLanguageFlagsForLinking(
flags, this->GeneratorTarget, linkLanguage, this->ConfigName);
flags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget,
linkLanguage, this->ConfigName);
this->LocalGenerator->AddArchitectureFlags(
flags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
// Add target-specific linker flags.
this->GetTargetLinkFlags(linkFlags, linkLanguage);
@@ -213,7 +212,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal),
output);
std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB();
std::string targetFullPathCompilePDB =
this->ComputeTargetCompilePDB(this->GetConfigName());
std::string targetOutPathCompilePDB =
this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB,
cmOutputConverter::SHELL);
@@ -287,12 +287,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Get the name of the executable to generate.
cmGeneratorTarget::Names targetNames =
this->GeneratorTarget->GetExecutableNames(this->ConfigName);
this->GeneratorTarget->GetExecutableNames(this->GetConfigName());
// Construct the full path version of the names.
std::string outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
std::string outpath =
this->GeneratorTarget->GetDirectory(this->GetConfigName());
if (this->GeneratorTarget->IsAppBundleOnApple()) {
this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath);
this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath,
this->GetConfigName());
}
outpath += '/';
std::string outpathImp;
@@ -308,18 +310,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
cmSystemTools::MakeDirectory(outpath);
if (!targetNames.ImportLibrary.empty()) {
outpathImp = this->GeneratorTarget->GetDirectory(
this->ConfigName, cmStateEnums::ImportLibraryArtifact);
this->GetConfigName(), cmStateEnums::ImportLibraryArtifact);
cmSystemTools::MakeDirectory(outpathImp);
outpathImp += '/';
}
}
std::string compilePdbOutputPath =
this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName);
this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName());
cmSystemTools::MakeDirectory(compilePdbOutputPath);
std::string pdbOutputPath =
this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
this->GeneratorTarget->GetPDBDirectory(this->GetConfigName());
cmSystemTools::MakeDirectory(pdbOutputPath);
pdbOutputPath += '/';
@@ -347,7 +349,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Get the language to use for linking this executable.
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
// Make sure we have a link language.
if (linkLanguage.empty()) {
@@ -380,7 +382,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Add flags to create an executable.
this->LocalGenerator->AddConfigVariableFlags(
linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->ConfigName);
linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GetConfigName());
if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) {
this->LocalGenerator->AppendFlags(
@@ -409,10 +411,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Add language feature flags.
this->LocalGenerator->AddLanguageFlagsForLinking(
flags, this->GeneratorTarget, linkLanguage, this->ConfigName);
flags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget,
linkLanguage, this->ConfigName);
this->LocalGenerator->AddArchitectureFlags(
flags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
// Add target-specific linker flags.
this->GetTargetLinkFlags(linkFlags, linkLanguage);
@@ -423,11 +425,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags);
this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags,
this->GetConfigName());
}
this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget,
this->ConfigName, linkLanguage);
this->LocalGenerator->AppendIPOLinkerFlags(
linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
// Construct a list of files associated with this executable that
// may need to be cleaned.
@@ -451,7 +454,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
targetFullPathImport));
std::string implib;
if (this->GeneratorTarget->GetImplibGNUtoMS(
this->ConfigName, targetFullPathImport, implib)) {
this->GetConfigName(), targetFullPathImport, implib)) {
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
}
@@ -479,7 +482,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Construct the main link rule.
std::vector<std::string> real_link_commands;
std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable(
linkLanguage, this->ConfigName);
linkLanguage, this->GetConfigName());
std::string linkRule = this->GetLinkRule(linkRuleVar);
std::vector<std::string> commands1;
cmExpandList(linkRule, real_link_commands);
@@ -536,7 +539,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// maybe create .def file from list of objects
this->GenDefFile(real_link_commands);
std::string manifests = this->GetManifests();
std::string manifests = this->GetManifests(this->GetConfigName());
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
+48 -44
View File
@@ -36,11 +36,10 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator(
this->CustomCommandDriver = OnDepends;
if (this->GeneratorTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
this->TargetNames =
this->GeneratorTarget->GetLibraryNames(this->ConfigName);
this->GeneratorTarget->GetLibraryNames(this->GetConfigName());
}
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
@@ -69,14 +68,16 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
break;
case cmStateEnums::SHARED_LIBRARY:
this->WriteSharedLibraryRules(false);
if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) {
if (this->GeneratorTarget->NeedRelinkBeforeInstall(
this->GetConfigName())) {
// Write rules to link an installable version of the target.
this->WriteSharedLibraryRules(true);
}
break;
case cmStateEnums::MODULE_LIBRARY:
this->WriteModuleLibraryRules(false);
if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) {
if (this->GeneratorTarget->NeedRelinkBeforeInstall(
this->GetConfigName())) {
// Write rules to link an installable version of the target.
this->WriteModuleLibraryRules(true);
}
@@ -126,21 +127,21 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
{
const bool requiresDeviceLinking = requireDeviceLinking(
*this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
*this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName());
if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
this->WriteDeviceLibraryRules(linkRuleVar, false);
}
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable(
linkLanguage, this->ConfigName);
linkLanguage, this->GetConfigName());
std::string extraFlags;
this->LocalGenerator->GetStaticLibraryFlags(
extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage,
extraFlags, cmSystemTools::UpperCase(this->GetConfigName()), linkLanguage,
this->GeneratorTarget);
this->WriteLibraryRules(linkRuleVar, extraFlags, false);
}
@@ -154,7 +155,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
if (!relink) {
const bool requiresDeviceLinking = requireDeviceLinking(
*this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
*this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName());
if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
this->WriteDeviceLibraryRules(linkRuleVar, relink);
@@ -162,21 +163,22 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
}
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
std::string linkRuleVar =
cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY");
std::string extraFlags;
this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->GetConfigName());
std::unique_ptr<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags);
this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags,
this->GetConfigName());
if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed");
@@ -188,7 +190,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
{
if (!relink) {
const bool requiresDeviceLinking = requireDeviceLinking(
*this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
*this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName());
if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
this->WriteDeviceLibraryRules(linkRuleVar, relink);
@@ -196,21 +198,22 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
}
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
std::string linkRuleVar =
cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_MODULE");
std::string extraFlags;
this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->GetConfigName());
std::unique_ptr<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags);
this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags,
this->GetConfigName());
this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}
@@ -218,14 +221,14 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
{
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
std::string linkRuleVar =
cmStrCat("CMAKE_", linkLanguage, "_CREATE_MACOSX_FRAMEWORK");
std::string extraFlags;
this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->GetConfigName());
this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}
@@ -331,7 +334,8 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal),
output);
std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB();
std::string targetFullPathCompilePDB =
this->ComputeTargetCompilePDB(this->GetConfigName());
std::string targetOutPathCompilePDB =
this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB,
cmOutputConverter::SHELL);
@@ -347,7 +351,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
// Add language-specific flags.
std::string langFlags;
this->LocalGenerator->AddLanguageFlagsForLinking(
langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
vars.LanguageCompileFlags = langFlags.c_str();
@@ -420,7 +424,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Get the language to use for linking this library.
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
// Make sure we have a link language.
if (linkLanguage.empty()) {
@@ -439,8 +443,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Create set of linking flags.
std::string linkFlags;
this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget,
this->ConfigName, linkLanguage);
this->LocalGenerator->AppendIPOLinkerFlags(
linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
// Add OSX version flags, if any.
if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
@@ -450,20 +454,20 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
}
// Construct the name of the library.
this->GeneratorTarget->GetLibraryNames(this->ConfigName);
this->GeneratorTarget->GetLibraryNames(this->GetConfigName());
// Construct the full path version of the names.
std::string outpath;
std::string outpathImp;
if (this->GeneratorTarget->IsFrameworkOnApple()) {
outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName());
this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output,
outpath);
outpath, this->GetConfigName());
outpath += '/';
} else if (this->GeneratorTarget->IsCFBundleOnApple()) {
outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output,
outpath);
outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName());
this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, outpath,
this->GetConfigName());
outpath += '/';
} else if (relink) {
outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(),
@@ -474,23 +478,23 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
outpathImp = outpath;
}
} else {
outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName());
cmSystemTools::MakeDirectory(outpath);
outpath += '/';
if (!this->TargetNames.ImportLibrary.empty()) {
outpathImp = this->GeneratorTarget->GetDirectory(
this->ConfigName, cmStateEnums::ImportLibraryArtifact);
this->GetConfigName(), cmStateEnums::ImportLibraryArtifact);
cmSystemTools::MakeDirectory(outpathImp);
outpathImp += '/';
}
}
std::string compilePdbOutputPath =
this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName);
this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName());
cmSystemTools::MakeDirectory(compilePdbOutputPath);
std::string pdbOutputPath =
this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
this->GeneratorTarget->GetPDBDirectory(this->GetConfigName());
cmSystemTools::MakeDirectory(pdbOutputPath);
pdbOutputPath += "/";
@@ -586,7 +590,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
targetFullPathImport));
std::string implib;
if (this->GeneratorTarget->GetImplibGNUtoMS(
this->ConfigName, targetFullPathImport, implib)) {
this->GetConfigName(), targetFullPathImport, implib)) {
libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
}
@@ -638,7 +642,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_CREATE");
arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
arCreateVar, linkLanguage, this->ConfigName);
arCreateVar, linkLanguage, this->GetConfigName());
if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) {
cmExpandList(rule, archiveCreateCommands);
@@ -647,7 +651,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_APPEND");
arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
arAppendVar, linkLanguage, this->ConfigName);
arAppendVar, linkLanguage, this->GetConfigName());
if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) {
cmExpandList(rule, archiveAppendCommands);
@@ -656,7 +660,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_FINISH");
arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
arFinishVar, linkLanguage, this->ConfigName);
arFinishVar, linkLanguage, this->GetConfigName());
if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) {
cmExpandList(rule, archiveFinishCommands);
@@ -726,7 +730,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// maybe create .def file from list of objects
this->GenDefFile(real_link_commands);
std::string manifests = this->GetManifests();
std::string manifests = this->GetManifests(this->GetConfigName());
cmRulePlaceholderExpander::RuleVariables vars;
vars.TargetPDB = targetOutPathPDB.c_str();
@@ -771,7 +775,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars.Target = target.c_str();
vars.LinkLibraries = linkLibs.c_str();
vars.ObjectsQuoted = buildObjs.c_str();
if (this->GeneratorTarget->HasSOName(this->ConfigName)) {
if (this->GeneratorTarget->HasSOName(this->GetConfigName())) {
vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
vars.TargetSOName = this->TargetNames.SharedObject.c_str();
}
@@ -783,8 +787,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
std::string install_name_dir;
if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY) {
// Get the install_name directory for the build tree.
install_name_dir =
this->GeneratorTarget->GetInstallNameDirForBuildTree(this->ConfigName);
install_name_dir = this->GeneratorTarget->GetInstallNameDirForBuildTree(
this->GetConfigName());
// Set the rule variable replacement value.
if (install_name_dir.empty()) {
@@ -800,10 +804,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Add language-specific flags.
std::string langFlags;
this->LocalGenerator->AddLanguageFlagsForLinking(
langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
this->LocalGenerator->AddArchitectureFlags(
langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName());
vars.LanguageCompileFlags = langFlags.c_str();
+73 -50
View File
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileTargetGenerator.h"
#include <cassert>
#include <cstdio>
#include <memory>
#include <sstream>
@@ -85,6 +86,13 @@ cmMakefileTargetGenerator* cmMakefileTargetGenerator::New(
return result;
}
std::string cmMakefileTargetGenerator::GetConfigName()
{
auto const& configNames = this->LocalGenerator->GetConfigNames();
assert(configNames.size() == 1);
return configNames.front();
}
void cmMakefileTargetGenerator::GetTargetLinkFlags(
std::string& flags, const std::string& linkLanguage)
{
@@ -92,17 +100,18 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags(
flags, this->GeneratorTarget->GetSafeProperty("LINK_FLAGS"));
std::string linkFlagsConfig =
cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->ConfigName));
cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->GetConfigName()));
this->LocalGenerator->AppendFlags(
flags, this->GeneratorTarget->GetSafeProperty(linkFlagsConfig));
std::vector<std::string> opts;
this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage);
this->GeneratorTarget->GetLinkOptions(opts, this->GetConfigName(),
linkLanguage);
// LINK_OPTIONS are escaped.
this->LocalGenerator->AppendCompileOptions(flags, opts);
this->LocalGenerator->AppendPositionIndependentLinkerFlags(
flags, this->GeneratorTarget, this->ConfigName, linkLanguage);
flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
}
void cmMakefileTargetGenerator::CreateRuleFile()
@@ -154,10 +163,10 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
auto evaluatedFiles =
[this](const char* prop_value) -> std::vector<std::string> {
std::vector<std::string> files;
cmExpandList(
cmGeneratorExpression::Evaluate(prop_value, this->LocalGenerator,
this->ConfigName, this->GeneratorTarget),
files);
cmExpandList(cmGeneratorExpression::Evaluate(
prop_value, this->LocalGenerator, this->GetConfigName(),
this->GeneratorTarget),
files);
return files;
};
@@ -187,12 +196,13 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
// First generate the object rule files. Save a list of all object
// files for this target.
std::vector<cmSourceFile const*> customCommands;
this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
this->GeneratorTarget->GetCustomCommands(customCommands,
this->GetConfigName());
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
for (cmSourceFile const* sf : customCommands) {
cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), this->ConfigName,
this->LocalGenerator);
cmCustomCommandGenerator ccg(*sf->GetCustomCommand(),
this->GetConfigName(), this->LocalGenerator);
this->GenerateCustomRuleFile(ccg);
if (clean) {
const std::vector<std::string>& outputs = ccg.GetOutputs();
@@ -220,7 +230,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
this->GeneratorTarget->GetPostBuildCommands());
for (const auto& be : buildEventCommands) {
cmCustomCommandGenerator beg(be, this->ConfigName, this->LocalGenerator);
cmCustomCommandGenerator beg(be, this->GetConfigName(),
this->LocalGenerator);
const std::vector<std::string>& byproducts = beg.GetByproducts();
for (std::string const& byproduct : byproducts) {
this->CleanFiles.insert(
@@ -230,17 +241,19 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
}
}
std::vector<cmSourceFile const*> headerSources;
this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName);
this->GeneratorTarget->GetHeaderSources(headerSources,
this->GetConfigName());
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
headerSources, this->MacOSXContentGenerator);
headerSources, this->MacOSXContentGenerator, this->GetConfigName());
std::vector<cmSourceFile const*> extraSources;
this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName);
this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName());
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
extraSources, this->MacOSXContentGenerator);
extraSources, this->MacOSXContentGenerator, this->GetConfigName());
const char* pchExtension =
this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
std::vector<cmSourceFile const*> externalObjects;
this->GeneratorTarget->GetExternalObjects(externalObjects, this->ConfigName);
this->GeneratorTarget->GetExternalObjects(externalObjects,
this->GetConfigName());
for (cmSourceFile const* sf : externalObjects) {
auto const& objectFileName = sf->GetFullPath();
if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
@@ -248,7 +261,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
}
}
std::vector<cmSourceFile const*> objectSources;
this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName);
this->GeneratorTarget->GetObjectSources(objectSources,
this->GetConfigName());
for (cmSourceFile const* sf : objectSources) {
// Generate this object file's rule file.
this->WriteObjectRuleFiles(*sf);
@@ -334,9 +348,9 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
}
for (std::string const& language : languages) {
std::string flags = this->GetFlags(language);
std::string defines = this->GetDefines(language);
std::string includes = this->GetIncludes(language);
std::string flags = this->GetFlags(language, this->GetConfigName());
std::string defines = this->GetDefines(language, this->GetConfigName());
std::string includes = this->GetIncludes(language, this->GetConfigName());
// Escape comment characters so they do not terminate assignment.
cmSystemTools::ReplaceString(flags, "#", "\\#");
cmSystemTools::ReplaceString(defines, "#", "\\#");
@@ -348,7 +362,7 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
}
void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
cmSourceFile const& source, const char* pkgloc)
cmSourceFile const& source, const char* pkgloc, const std::string& config)
{
// Skip OS X content when not building a Framework or Bundle.
if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) {
@@ -356,7 +370,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
}
std::string macdir =
this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc,
config);
// Get the input file location.
std::string const& input = source.GetFullPath();
@@ -451,7 +466,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// generate the depend scanning rule
this->WriteObjectDependRules(source, depends);
std::string config = this->LocalGenerator->GetConfigName();
std::string config = this->GetConfigName();
std::string configUpper = cmSystemTools::UpperCase(config);
// Add precompile headers dependencies
@@ -593,16 +608,17 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
{
std::string targetFullPathReal;
std::string targetFullPathPDB;
std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB();
std::string targetFullPathCompilePDB =
this->ComputeTargetCompilePDB(this->GetConfigName());
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
targetFullPathReal = this->GeneratorTarget->GetFullPath(
this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true);
targetFullPathPDB =
cmStrCat(this->GeneratorTarget->GetPDBDirectory(this->ConfigName), '/',
this->GeneratorTarget->GetPDBName(this->ConfigName));
this->GetConfigName(), cmStateEnums::RuntimeBinaryArtifact, true);
targetFullPathPDB = cmStrCat(
this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/',
this->GeneratorTarget->GetPDBName(this->GetConfigName()));
}
targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
@@ -708,13 +724,15 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::string workingDirectory = cmSystemTools::CollapseFullPath(
this->LocalGenerator->GetCurrentBinaryDirectory());
compileCommand.replace(compileCommand.find(langFlags), langFlags.size(),
this->GetFlags(lang));
this->GetFlags(lang, this->GetConfigName()));
std::string langDefines = std::string("$(") + lang + "_DEFINES)";
compileCommand.replace(compileCommand.find(langDefines),
langDefines.size(), this->GetDefines(lang));
langDefines.size(),
this->GetDefines(lang, this->GetConfigName()));
std::string langIncludes = std::string("$(") + lang + "_INCLUDES)";
compileCommand.replace(compileCommand.find(langIncludes),
langIncludes.size(), this->GetIncludes(lang));
langIncludes.size(),
this->GetIncludes(lang, this->GetConfigName()));
const char* eliminate[] = {
this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"),
@@ -1068,7 +1086,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "# Targets to which this target links.\n"
<< "set(CMAKE_TARGET_LINKED_INFO_FILES\n";
/* clang-format on */
std::vector<std::string> dirs = this->GetLinkedTargetDirectories();
std::vector<std::string> dirs =
this->GetLinkedTargetDirectories(this->GetConfigName());
for (std::string const& d : dirs) {
*this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n";
}
@@ -1171,7 +1190,7 @@ void cmMakefileTargetGenerator::DriveCustomCommands(
sources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
for (cmSourceFile* source : sources) {
if (cmCustomCommand* cc = source->GetCustomCommand()) {
cmCustomCommandGenerator ccg(*cc, this->ConfigName,
cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
this->LocalGenerator);
cmAppend(depends, ccg.GetOutputs());
}
@@ -1429,7 +1448,7 @@ void cmMakefileTargetGenerator::AppendTargetDepends(
}
// Loop over all library dependencies.
const std::string& cfg = this->LocalGenerator->GetConfigName();
const std::string& cfg = this->GetConfigName();
if (cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(cfg)) {
cmAppend(depends, cli->GetDepends());
@@ -1474,13 +1493,13 @@ void cmMakefileTargetGenerator::AppendLinkDepends(
// Add a dependency on user-specified manifest files, if any.
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
this->GeneratorTarget->GetManifests(manifest_srcs, this->GetConfigName());
for (cmSourceFile const* manifest_src : manifest_srcs) {
depends.push_back(manifest_src->GetFullPath());
}
// Add user-specified dependencies.
this->GeneratorTarget->GetLinkDepends(depends, this->ConfigName,
this->GeneratorTarget->GetLinkDepends(depends, this->GetConfigName(),
linkLanguage);
}
@@ -1488,10 +1507,11 @@ std::string cmMakefileTargetGenerator::GetLinkRule(
const std::string& linkRuleVar)
{
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) {
std::string ruleVar = cmStrCat(
"CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
"_GNUtoMS_RULE");
if (this->GeneratorTarget->HasImplibGNUtoMS(this->GetConfigName())) {
std::string ruleVar =
cmStrCat("CMAKE_",
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
"_GNUtoMS_RULE");
if (const char* rule = this->Makefile->GetDefinition(ruleVar)) {
linkRule += rule;
}
@@ -1630,7 +1650,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
std::string frameworkPath;
std::string linkPath;
cmComputeLinkInformation* pcli =
this->GeneratorTarget->GetLinkInformation(this->ConfigName);
this->GeneratorTarget->GetLinkInformation(this->GetConfigName());
this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
frameworkPath, linkPath);
linkLibs = frameworkPath + linkPath + linkLibs;
@@ -1638,9 +1658,10 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
if (useResponseFile &&
linkLibs.find_first_not_of(' ') != std::string::npos) {
// Lookup the response file reference flag.
std::string responseFlagVar = cmStrCat(
"CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
"_RESPONSE_FILE_LINK_FLAG");
std::string responseFlagVar =
cmStrCat("CMAKE_",
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
"_RESPONSE_FILE_LINK_FLAG");
const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar);
if (!responseFlag) {
responseFlag = "@";
@@ -1675,9 +1696,10 @@ void cmMakefileTargetGenerator::CreateObjectLists(
this->WriteObjectsStrings(object_strings, responseFileLimit);
// Lookup the response file reference flag.
std::string responseFlagVar = cmStrCat(
"CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
"_RESPONSE_FILE_LINK_FLAG");
std::string responseFlagVar =
cmStrCat("CMAKE_",
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
"_RESPONSE_FILE_LINK_FLAG");
const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar);
if (!responseFlag) {
responseFlag = "@";
@@ -1716,7 +1738,8 @@ void cmMakefileTargetGenerator::CreateObjectLists(
}
void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
const std::string& lang)
const std::string& lang,
const std::string& /*config*/)
{
std::string responseVar =
cmStrCat("CMAKE_", lang, "_USE_RESPONSE_FILE_FOR_INCLUDES");
@@ -1724,11 +1747,11 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
std::vector<std::string> includes;
this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
lang, this->ConfigName);
lang, this->GetConfigName());
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
includes, this->GeneratorTarget, lang, false, useResponseFile,
this->ConfigName);
this->GetConfigName());
if (includeFlags.empty()) {
return;
}
+6 -2
View File
@@ -52,6 +52,8 @@ public:
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
std::string GetConfigName();
protected:
void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage);
@@ -81,7 +83,8 @@ protected:
{
}
void operator()(cmSourceFile const& source, const char* pkgloc) override;
void operator()(cmSourceFile const& source, const char* pkgloc,
const std::string& config) override;
private:
cmMakefileTargetGenerator* Generator;
@@ -163,7 +166,8 @@ protected:
/** Add commands for generate def files */
void GenDefFile(std::vector<std::string>& real_link_commands);
void AddIncludeFlags(std::string& flags, const std::string& lang) override;
void AddIncludeFlags(std::string& flags, const std::string& lang,
const std::string& config) override;
virtual void CloseFileStreams();
cmLocalUnixMakefileGenerator3* LocalGenerator;
+1 -2
View File
@@ -22,8 +22,7 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
: cmMakefileTargetGenerator(target)
{
this->CustomCommandDriver = OnUtility;
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
+278 -185
View File
@@ -41,33 +41,25 @@
cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
cmGeneratorTarget* target)
: cmNinjaTargetGenerator(target)
, TargetLinkLanguage("")
{
this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
if (target->GetType() == cmStateEnums::EXECUTABLE) {
this->TargetNames = this->GetGeneratorTarget()->GetExecutableNames(
GetLocalGenerator()->GetConfigName());
} else {
this->TargetNames = this->GetGeneratorTarget()->GetLibraryNames(
GetLocalGenerator()->GetConfigName());
}
if (target->GetType() != cmStateEnums::OBJECT_LIBRARY) {
// on Windows the output dir is already needed at compile time
// ensure the directory exists (OutDir test)
EnsureDirectoryExists(target->GetDirectory(this->GetConfigName()));
for (auto const& config : this->GetConfigNames()) {
EnsureDirectoryExists(target->GetDirectory(config));
}
}
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->GetConfigName());
this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default;
void cmNinjaNormalTargetGenerator::Generate()
void cmNinjaNormalTargetGenerator::Generate(const std::string& config)
{
if (this->TargetLinkLanguage.empty()) {
std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
if (this->TargetLinkLanguage(config).empty()) {
cmSystemTools::Error("CMake can not determine linker language for "
"target: " +
this->GetGeneratorTarget()->GetName());
@@ -75,25 +67,36 @@ void cmNinjaNormalTargetGenerator::Generate()
}
// Write the rules for each language.
this->WriteLanguagesRules();
this->WriteLanguagesRules(config);
// Write the build statements
this->WriteObjectBuildStatements();
bool firstForConfig = true;
for (auto const& fileConfig : this->GetConfigNames()) {
this->WriteObjectBuildStatements(config, fileConfig, firstForConfig);
firstForConfig = false;
}
if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
this->WriteObjectLibStatement();
this->WriteObjectLibStatement(config);
} else {
// If this target has cuda language link inputs, and we need to do
// device linking
this->WriteDeviceLinkStatement();
this->WriteLinkStatement();
this->WriteDeviceLinkStatement(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();
this->AdditionalCleanFiles(config);
}
void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
void cmNinjaNormalTargetGenerator::WriteLanguagesRules(
const std::string& config)
{
#ifdef NINJA_GEN_VERBOSE_FILES
cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream());
@@ -106,8 +109,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
// Write rules for languages compiled in this target.
std::set<std::string> languages;
std::vector<cmSourceFile const*> sourceFiles;
this->GetGeneratorTarget()->GetObjectSources(
sourceFiles, this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"));
this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config);
for (cmSourceFile const* sf : sourceFiles) {
std::string const lang = sf->GetLanguage();
if (!lang.empty()) {
@@ -115,7 +117,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
}
}
for (std::string const& language : languages) {
this->WriteLanguageRules(language);
this->WriteLanguageRules(language, config);
}
}
@@ -139,22 +141,26 @@ const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const
}
}
std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule() const
std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule(
const std::string& config) const
{
return this->TargetLinkLanguage + "_" +
return this->TargetLinkLanguage(config) + "_" +
cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
"_LINKER__" +
cmGlobalNinjaGenerator::EncodeRuleName(
this->GetGeneratorTarget()->GetName());
this->GetGeneratorTarget()->GetName()) +
"_" + config;
}
std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule() const
std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule(
const std::string& config) const
{
return this->TargetLinkLanguage + "_" +
return this->TargetLinkLanguage(config) + "_" +
cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
"_DEVICE_LINKER__" +
cmGlobalNinjaGenerator::EncodeRuleName(
this->GetGeneratorTarget()->GetName());
this->GetGeneratorTarget()->GetName()) +
"_" + config;
}
struct cmNinjaRemoveNoOpCommands
@@ -165,9 +171,10 @@ struct cmNinjaRemoveNoOpCommands
}
};
void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(
bool useResponseFile, const std::string& config)
{
cmNinjaRule rule(this->LanguageLinkerDeviceRule());
cmNinjaRule rule(this->LanguageLinkerDeviceRule(config));
if (!this->GetGlobalGenerator()->HasRule(rule.Name)) {
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
@@ -241,30 +248,34 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds);
// Write the linker rule with response file if needed.
rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ',
this->GetVisibleTypeName(), '.');
rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ',
this->GetVisibleTypeName(), " $TARGET_FILE");
rule.Comment =
cmStrCat("Rule for linking ", this->TargetLinkLanguage(config), ' ',
this->GetVisibleTypeName(), '.');
rule.Description =
cmStrCat("Linking ", this->TargetLinkLanguage(config), ' ',
this->GetVisibleTypeName(), " $TARGET_FILE");
rule.Restat = "$RESTAT";
this->GetGlobalGenerator()->AddRule(rule);
}
}
void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
const std::string& config)
{
cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType();
std::string linkRuleName = this->LanguageLinkerRule();
std::string linkRuleName = this->LanguageLinkerRule(config);
if (!this->GetGlobalGenerator()->HasRule(linkRuleName)) {
cmNinjaRule rule(std::move(linkRuleName));
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
vars.CMTargetType = cmState::GetTargetTypeName(targetType);
vars.Language = this->TargetLinkLanguage.c_str();
std::string lang = this->TargetLinkLanguage(config);
vars.Language = config.c_str();
if (this->TargetLinkLanguage == "Swift") {
if (this->TargetLinkLanguage(config) == "Swift") {
vars.SwiftLibraryName = "$SWIFT_LIBRARY_NAME";
vars.SwiftModule = "$SWIFT_MODULE";
vars.SwiftModuleName = "$SWIFT_MODULE_NAME";
@@ -278,7 +289,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
std::string responseFlag;
std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage);
std::string cmakeVarLang =
cmStrCat("CMAKE_", this->TargetLinkLanguage(config));
// build response file name
std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
@@ -286,7 +298,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
if (flag) {
responseFlag = flag;
} else if (this->TargetLinkLanguage != "CUDA") {
} else if (this->TargetLinkLanguage(config) != "CUDA") {
responseFlag = "@";
}
@@ -304,7 +316,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
rule.RspContent = "$in_newline";
}
rule.RspContent += " $LINK_PATH $LINK_LIBRARIES";
if (this->TargetLinkLanguage == "Swift") {
if (this->TargetLinkLanguage(config) == "Swift") {
vars.SwiftSources = responseFlag.c_str();
} else {
vars.Objects = responseFlag.c_str();
@@ -359,7 +371,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
// Rule for linking library/executable.
std::vector<std::string> linkCmds = this->ComputeLinkCmd();
std::vector<std::string> linkCmds = this->ComputeLinkCmd(config);
for (std::string& linkCmd : linkCmds) {
linkCmd = cmStrCat(launcher, linkCmd);
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
@@ -374,15 +386,18 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds);
// Write the linker rule with response file if needed.
rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ',
this->GetVisibleTypeName(), '.');
rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ',
this->GetVisibleTypeName(), " $TARGET_FILE");
rule.Comment =
cmStrCat("Rule for linking ", this->TargetLinkLanguage(config), ' ',
this->GetVisibleTypeName(), '.');
rule.Description =
cmStrCat("Linking ", this->TargetLinkLanguage(config), ' ',
this->GetVisibleTypeName(), " $TARGET_FILE");
rule.Restat = "$RESTAT";
this->GetGlobalGenerator()->AddRule(rule);
}
if (this->TargetNames.Output != this->TargetNames.Real &&
auto const tgtNames = this->TargetNames(config);
if (tgtNames.Output != tgtNames.Real &&
!this->GetGeneratorTarget()->IsFrameworkOnApple()) {
std::string cmakeCommand =
this->GetLocalGenerator()->ConvertToOutputFormat(
@@ -441,7 +456,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd()
return linkCmds;
}
std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd(
const std::string& config)
{
std::vector<std::string> linkCmds;
cmMakefile* mf = this->GetMakefile();
@@ -450,14 +466,14 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
// this occurs when things like IPO is enabled, and we need to use the
// CMAKE_<lang>_CREATE_STATIC_LIBRARY_IPO define instead.
std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable(
this->TargetLinkLanguage, this->GetConfigName());
this->TargetLinkLanguage(config), config);
const char* linkCmd = mf->GetDefinition(linkCmdVar);
if (linkCmd) {
std::string linkCmdStr = linkCmd;
if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) {
std::string ruleVar = cmStrCat(
"CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
"_GNUtoMS_RULE");
if (this->GetGeneratorTarget()->HasImplibGNUtoMS(config)) {
std::string ruleVar =
cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(config),
"_GNUtoMS_RULE");
if (const char* rule = this->Makefile->GetDefinition(ruleVar)) {
linkCmdStr += rule;
}
@@ -469,9 +485,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
" -E __run_co_compile --lwyu=");
cmGeneratorTarget& gt = *this->GetGeneratorTarget();
const std::string cfgName = this->GetConfigName();
std::string targetOutputReal = this->ConvertToNinjaPath(
gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
gt.GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact,
/*realname=*/true));
cmakeCommand += targetOutputReal;
linkCmds.push_back(std::move(cmakeCommand));
@@ -490,21 +505,21 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
}
// TODO: Use ARCHIVE_APPEND for archives over a certain size.
{
std::string linkCmdVar =
cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_CREATE");
std::string linkCmdVar = cmStrCat(
"CMAKE_", this->TargetLinkLanguage(config), "_ARCHIVE_CREATE");
linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
linkCmdVar, this->TargetLinkLanguage(config), config);
std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar);
cmExpandList(linkCmd, linkCmds);
}
{
std::string linkCmdVar =
cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_FINISH");
std::string linkCmdVar = cmStrCat(
"CMAKE_", this->TargetLinkLanguage(config), "_ARCHIVE_FINISH");
linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
linkCmdVar, this->TargetLinkLanguage(config), config);
std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar);
cmExpandList(linkCmd, linkCmds);
@@ -535,7 +550,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
return std::vector<std::string>();
}
void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement(
const std::string& config)
{
cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator();
if (!globalGen->GetLanguageEnabled("CUDA")) {
@@ -545,7 +561,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
cmGeneratorTarget* genTarget = this->GetGeneratorTarget();
bool requiresDeviceLinking = requireDeviceLinking(
*this->GeneratorTarget, *this->GetLocalGenerator(), this->ConfigName);
*this->GeneratorTarget, *this->GetLocalGenerator(), config);
if (!requiresDeviceLinking) {
return;
}
@@ -558,24 +574,23 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
std::string const& objExt =
this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
std::string const cfgName = this->GetConfigName();
std::string const targetOutputReal = ConvertToNinjaPath(
genTarget->ObjectDirectory + "cmake_device_link" + objExt);
std::string const targetOutputImplib = ConvertToNinjaPath(
genTarget->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
genTarget->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
this->DeviceLinkObject = targetOutputReal;
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
cmGlobalNinjaGenerator::WriteDivider(this->GetCommonFileStream());
const cmStateEnums::TargetType targetType = genTarget->GetType();
this->GetBuildFileStream() << "# Device Link build statements for "
<< cmState::GetTargetTypeName(targetType)
<< " target " << this->GetTargetName() << "\n\n";
this->GetCommonFileStream() << "# Device Link build statements for "
<< cmState::GetTargetTypeName(targetType)
<< " target " << this->GetTargetName() << "\n\n";
// Compute the comment.
cmNinjaBuild build(this->LanguageLinkerDeviceRule());
cmNinjaBuild build(this->LanguageLinkerDeviceRule(config));
build.Comment =
cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal);
@@ -584,14 +599,15 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
// Compute outputs.
build.Outputs.push_back(targetOutputReal);
// Compute specific libraries to link with.
build.ExplicitDeps = this->GetObjects();
build.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage);
build.ExplicitDeps = this->GetObjects(config);
build.ImplicitDeps =
this->ComputeLinkDeps(this->TargetLinkLanguage(config), config);
std::string frameworkPath;
std::string linkPath;
std::string createRule = genTarget->GetCreateRuleVariable(
this->TargetLinkLanguage, this->GetConfigName());
std::string createRule =
genTarget->GetCreateRuleVariable(this->TargetLinkLanguage(config), config);
const bool useWatcomQuote =
this->GetMakefile()->IsOn(createRule + "_USE_WATCOM_QUOTE");
cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();
@@ -605,17 +621,17 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(),
globalGen));
linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig());
localGen.GetTargetFlags(
linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget);
linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"],
vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget);
this->addPoolNinjaVariable("JOB_POOL_LINK", genTarget, vars);
vars["LINK_FLAGS"] =
cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]);
vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]);
vars["MANIFESTS"] = this->GetManifests();
vars["MANIFESTS"] = this->GetManifests(config);
vars["LINK_PATH"] = frameworkPath + linkPath;
@@ -624,24 +640,25 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
// code between the Makefile executable and library generators.
if (targetType == cmStateEnums::EXECUTABLE) {
std::string t = vars["FLAGS"];
localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName);
localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, config);
vars["FLAGS"] = t;
} else {
std::string t = vars["ARCH_FLAGS"];
localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName);
localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, config);
vars["ARCH_FLAGS"] = t;
t.clear();
localGen.AddLanguageFlagsForLinking(t, genTarget, cudaLinkLanguage,
cfgName);
config);
vars["LANGUAGE_COMPILE_FLAGS"] = t;
}
if (genTarget->HasSOName(cfgName)) {
auto const tgtNames = this->TargetNames(config);
if (genTarget->HasSOName(config)) {
vars["SONAME_FLAG"] =
this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage);
vars["SONAME"] = this->TargetNames.SharedObject;
this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage(config));
vars["SONAME"] = tgtNames.SharedObject;
if (targetType == cmStateEnums::SHARED_LIBRARY) {
std::string install_dir =
this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(config);
if (!install_dir.empty()) {
vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat(
install_dir, cmOutputConverter::SHELL);
@@ -649,25 +666,28 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
}
}
if (!this->TargetNames.ImportLibrary.empty()) {
if (!tgtNames.ImportLibrary.empty()) {
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
EnsureParentDirectoryExists(impLibPath);
}
const std::string objPath = GetGeneratorTarget()->GetSupportDirectory();
const std::string objPath =
cmStrCat(GetGeneratorTarget()->GetSupportDirectory(),
globalGen->ConfigDirectory(config));
vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL);
EnsureDirectoryExists(objPath);
this->SetMsvcTargetPdbVariable(vars);
this->SetMsvcTargetPdbVariable(vars, config);
std::string& linkLibraries = vars["LINK_LIBRARIES"];
std::string& link_path = vars["LINK_PATH"];
if (globalGen->IsGCCOnWindows()) {
// ar.exe can't handle backslashes in rsp files (implicitly used by gcc)
std::string& linkLibraries = vars["LINK_LIBRARIES"];
std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/');
std::string& link_path = vars["LINK_PATH"];
std::replace(link_path.begin(), link_path.end(), '\\', '/');
}
@@ -675,65 +695,88 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
// do not check if the user has explicitly forced a response file.
int const commandLineLengthLimit =
static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule());
globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule(config));
build.RspFile = this->ConvertToNinjaPath(std::string("CMakeFiles/") +
genTarget->GetName() + ".rsp");
// Gather order-only dependencies.
this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
build.OrderOnlyDeps);
this->GetLocalGenerator()->AppendTargetDepends(
this->GetGeneratorTarget(), build.OrderOnlyDeps, config, config);
// Write the build statement for this target.
bool usedResponseFile = false;
globalGen->WriteBuild(this->GetBuildFileStream(), build,
globalGen->WriteBuild(this->GetCommonFileStream(), build,
commandLineLengthLimit, &usedResponseFile);
this->WriteDeviceLinkRule(usedResponseFile);
this->WriteDeviceLinkRule(usedResponseFile, config);
}
void cmNinjaNormalTargetGenerator::WriteLinkStatement()
void cmNinjaNormalTargetGenerator::WriteLinkStatement(
const std::string& config, const std::string& fileConfig,
bool firstForConfig)
{
cmMakefile* mf = this->GetMakefile();
cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator();
cmGeneratorTarget* gt = this->GetGeneratorTarget();
const std::string cfgName = this->GetConfigName();
std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(cfgName));
std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(config));
std::string targetOutputReal = ConvertToNinjaPath(
gt->GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact,
/*realname=*/true));
std::string targetOutputImplib = ConvertToNinjaPath(
gt->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
gt->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
if (config != fileConfig) {
if (targetOutput == ConvertToNinjaPath(gt->GetFullPath(fileConfig))) {
return;
}
if (targetOutputReal ==
ConvertToNinjaPath(gt->GetFullPath(fileConfig,
cmStateEnums::RuntimeBinaryArtifact,
/*realname=*/true))) {
return;
}
if (!gt->GetFullName(config, cmStateEnums::ImportLibraryArtifact)
.empty() &&
!gt->GetFullName(fileConfig, cmStateEnums::ImportLibraryArtifact)
.empty() &&
targetOutputImplib ==
ConvertToNinjaPath(gt->GetFullPath(
fileConfig, cmStateEnums::ImportLibraryArtifact))) {
return;
}
}
auto const tgtNames = this->TargetNames(config);
if (gt->IsAppBundleOnApple()) {
// Create the app bundle
std::string outpath = gt->GetDirectory(cfgName);
this->OSXBundleGenerator->CreateAppBundle(this->TargetNames.Output,
outpath);
std::string outpath = gt->GetDirectory(config);
this->OSXBundleGenerator->CreateAppBundle(tgtNames.Output, outpath,
config);
// Calculate the output path
targetOutput = cmStrCat(outpath, '/', this->TargetNames.Output);
targetOutput = cmStrCat(outpath, '/', tgtNames.Output);
targetOutput = this->ConvertToNinjaPath(targetOutput);
targetOutputReal = cmStrCat(outpath, '/', this->TargetNames.Real);
targetOutputReal = cmStrCat(outpath, '/', tgtNames.Real);
targetOutputReal = this->ConvertToNinjaPath(targetOutputReal);
} else if (gt->IsFrameworkOnApple()) {
// Create the library framework.
this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output,
gt->GetDirectory(cfgName));
this->OSXBundleGenerator->CreateFramework(
tgtNames.Output, gt->GetDirectory(config), config);
} else if (gt->IsCFBundleOnApple()) {
// Create the core foundation bundle.
this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output,
gt->GetDirectory(cfgName));
this->OSXBundleGenerator->CreateCFBundle(tgtNames.Output,
gt->GetDirectory(config), config);
}
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
cmGlobalNinjaGenerator::WriteDivider(this->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";
cmNinjaBuild linkBuild(this->LanguageLinkerRule());
cmNinjaBuild linkBuild(this->LanguageLinkerRule(config));
cmNinjaVars& vars = linkBuild.Variables;
// Compute the comment.
@@ -742,11 +785,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
// Compute outputs.
linkBuild.Outputs.push_back(targetOutputReal);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(targetOutputReal);
}
if (this->TargetLinkLanguage == "Swift") {
vars["SWIFT_LIBRARY_NAME"] = [this]() -> std::string {
if (this->TargetLinkLanguage(config) == "Swift") {
vars["SWIFT_LIBRARY_NAME"] = [this, config]() -> std::string {
cmGeneratorTarget::Names targetNames =
this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName());
this->GetGeneratorTarget()->GetLibraryNames(config);
return targetNames.Base;
}();
@@ -782,12 +828,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
"/output-file-map.json"),
cmOutputConverter::SHELL);
vars["SWIFT_SOURCES"] = [this]() -> std::string {
vars["SWIFT_SOURCES"] = [this, config]() -> std::string {
std::vector<cmSourceFile const*> sources;
std::stringstream oss;
this->GetGeneratorTarget()->GetObjectSources(sources,
this->GetConfigName());
this->GetGeneratorTarget()->GetObjectSources(sources, config);
cmLocalGenerator const* LocalGen = this->GetLocalGenerator();
for (const auto& source : sources) {
oss << " "
@@ -801,27 +846,28 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
// Since we do not perform object builds, compute the
// defines/flags/includes here so that they can be passed along
// appropriately.
vars["DEFINES"] = this->GetDefines("Swift");
vars["FLAGS"] = this->GetFlags("Swift");
vars["INCLUDES"] = this->GetIncludes("Swift");
vars["DEFINES"] = this->GetDefines("Swift", config);
vars["FLAGS"] = this->GetFlags("Swift", config);
vars["INCLUDES"] = this->GetIncludes("Swift", config);
}
// Compute specific libraries to link with.
if (this->TargetLinkLanguage == "Swift") {
if (this->TargetLinkLanguage(config) == "Swift") {
std::vector<cmSourceFile const*> sources;
gt->GetObjectSources(sources, this->GetConfigName());
gt->GetObjectSources(sources, config);
for (const auto& source : sources) {
linkBuild.Outputs.push_back(
this->ConvertToNinjaPath(this->GetObjectFilePath(source)));
this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)));
linkBuild.ExplicitDeps.push_back(
this->ConvertToNinjaPath(this->GetSourceFilePath(source)));
}
linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]);
} else {
linkBuild.ExplicitDeps = this->GetObjects();
linkBuild.ExplicitDeps = this->GetObjects(config);
}
linkBuild.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage);
linkBuild.ImplicitDeps =
this->ComputeLinkDeps(this->TargetLinkLanguage(config), config);
if (!this->DeviceLinkObject.empty()) {
linkBuild.ExplicitDeps.push_back(this->DeviceLinkObject);
@@ -831,7 +877,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
std::string linkPath;
std::string createRule =
gt->GetCreateRuleVariable(this->TargetLinkLanguage, this->GetConfigName());
gt->GetCreateRuleVariable(this->TargetLinkLanguage(config), config);
bool useWatcomQuote = mf->IsOn(createRule + "_USE_WATCOM_QUOTE");
cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();
@@ -843,27 +889,29 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
this->GetLocalGenerator(),
this->GetLocalGenerator()->GetStateSnapshot().GetDirectory()));
linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig());
localGen.GetTargetFlags(linkLineComputer.get(), this->GetConfigName(),
localGen.GetTargetFlags(linkLineComputer.get(), config,
vars["LINK_LIBRARIES"], vars["FLAGS"],
vars["LINK_FLAGS"], frameworkPath, linkPath, gt);
// Add OS X version flags, if any.
if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage,
"COMPATIBILITY", true);
this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage,
"CURRENT", false);
this->AppendOSXVerFlag(vars["LINK_FLAGS"],
this->TargetLinkLanguage(config), "COMPATIBILITY",
true);
this->AppendOSXVerFlag(vars["LINK_FLAGS"],
this->TargetLinkLanguage(config), "CURRENT", false);
}
this->addPoolNinjaVariable("JOB_POOL_LINK", gt, vars);
this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]);
vars["LINK_FLAGS"] =
cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]);
this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"],
config);
vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]);
vars["MANIFESTS"] = this->GetManifests();
vars["MANIFESTS"] = this->GetManifests(config);
vars["LINK_PATH"] = frameworkPath + linkPath;
std::string lwyuFlags;
@@ -876,23 +924,26 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
// code between the Makefile executable and library generators.
if (targetType == cmStateEnums::EXECUTABLE) {
std::string t = vars["FLAGS"];
localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName);
localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config),
config);
t += lwyuFlags;
vars["FLAGS"] = t;
} else {
std::string t = vars["ARCH_FLAGS"];
localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName);
localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config),
config);
vars["ARCH_FLAGS"] = t;
t.clear();
t += lwyuFlags;
localGen.AddLanguageFlagsForLinking(t, gt, TargetLinkLanguage, cfgName);
localGen.AddLanguageFlagsForLinking(
t, gt, this->TargetLinkLanguage(config), config);
vars["LANGUAGE_COMPILE_FLAGS"] = t;
}
if (gt->HasSOName(cfgName)) {
vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage);
vars["SONAME"] = this->TargetNames.SharedObject;
if (gt->HasSOName(config)) {
vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage(config));
vars["SONAME"] = tgtNames.SharedObject;
if (targetType == cmStateEnums::SHARED_LIBRARY) {
std::string install_dir = gt->GetInstallNameDirForBuildTree(cfgName);
std::string install_dir = gt->GetInstallNameDirForBuildTree(config);
if (!install_dir.empty()) {
vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat(
install_dir, cmOutputConverter::SHELL);
@@ -902,17 +953,21 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
cmNinjaDeps byproducts;
if (!this->TargetNames.ImportLibrary.empty()) {
if (!tgtNames.ImportLibrary.empty()) {
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
EnsureParentDirectoryExists(impLibPath);
if (gt->HasImportLibrary(cfgName)) {
if (gt->HasImportLibrary(config)) {
byproducts.push_back(targetOutputImplib);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(
targetOutputImplib);
}
}
}
if (!this->SetMsvcTargetPdbVariable(vars)) {
if (!this->SetMsvcTargetPdbVariable(vars, config)) {
// It is common to place debug symbols at a specific place,
// so we need a plain target name in the rule available.
std::string prefix;
@@ -927,16 +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(), '\\', '/');
}
@@ -947,23 +1003,30 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
std::vector<std::string> preLinkCmdLines;
std::vector<std::string> postBuildCmdLines;
std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
&preLinkCmdLines,
&postBuildCmdLines };
for (unsigned i = 0; i != 3; ++i) {
for (cmCustomCommand const& cc : *cmdLists[i]) {
cmCustomCommandGenerator ccg(cc, cfgName, this->GetLocalGenerator());
localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
std::transform(ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(byproducts), MapToNinjaPath());
if (config == fileConfig) {
std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
&preLinkCmdLines,
&postBuildCmdLines };
for (unsigned i = 0; i != 3; ++i) {
for (cmCustomCommand const& cc : *cmdLists[i]) {
cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator());
localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
std::transform(ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(byproducts), MapToNinjaPath());
std::transform(
ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(globalGen->GetByproductsForCleanTarget()),
MapToNinjaPath());
}
}
}
// maybe create .def file from list of objects
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
gt->GetModuleDefinitionInfo(this->GetConfigName());
gt->GetModuleDefinitionInfo(config);
if (mdi && mdi->DefFileGenerated) {
std::string cmakeCommand =
this->GetLocalGenerator()->ConvertToOutputFormat(
@@ -989,7 +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";
@@ -1024,7 +1087,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
symlinkVars["POST_BUILD"] = postBuildCmdLine;
}
std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage);
std::string cmakeVarLang =
cmStrCat("CMAKE_", this->TargetLinkLanguage(config));
// build response file name
std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
@@ -1032,8 +1096,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar);
bool const lang_supports_response =
!(this->TargetLinkLanguage == "RC" ||
(this->TargetLinkLanguage == "CUDA" && !flag));
!(this->TargetLinkLanguage(config) == "RC" ||
(this->TargetLinkLanguage(config) == "CUDA" && !flag));
int commandLineLengthLimit = -1;
if (!lang_supports_response || !this->ForceResponseFile()) {
commandLineLengthLimit =
@@ -1045,18 +1109,19 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
gt->GetName() + ".rsp");
// Gather order-only dependencies.
this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps);
this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps,
config, fileConfig);
// Add order-only dependencies on versioning symlinks of shared libs we link.
if (!this->GeneratorTarget->IsDLLPlatform()) {
if (cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(this->GetConfigName())) {
this->GeneratorTarget->GetLinkInformation(config)) {
for (auto const& item : cli->GetItems()) {
if (item.Target &&
item.Target->GetType() == cmStateEnums::SHARED_LIBRARY &&
!item.Target->IsFrameworkOnApple()) {
std::string const& lib = this->ConvertToNinjaPath(
item.Target->GetFullPath(this->GetConfigName()));
std::string const& lib =
this->ConvertToNinjaPath(item.Target->GetFullPath(config));
if (std::find(linkBuild.ImplicitDeps.begin(),
linkBuild.ImplicitDeps.end(),
lib) == linkBuild.ImplicitDeps.end()) {
@@ -1077,24 +1142,27 @@ 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);
this->WriteLinkRule(usedResponseFile, config);
if (symlinkNeeded) {
if (targetType == cmStateEnums::EXECUTABLE) {
cmNinjaBuild build("CMAKE_SYMLINK_EXECUTABLE");
build.Comment = "Create executable symlink " + targetOutput;
build.Outputs.push_back(targetOutput);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(targetOutput);
}
build.ExplicitDeps.push_back(targetOutputReal);
build.Variables = std::move(symlinkVars);
globalGen->WriteBuild(this->GetBuildFileStream(), build);
globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), build);
} else {
cmNinjaBuild build("CMAKE_SYMLINK_LIBRARY");
build.Comment = "Create library symlink " + targetOutput;
std::string const soName = this->ConvertToNinjaPath(
this->GetTargetFilePath(this->TargetNames.SharedObject));
this->GetTargetFilePath(tgtNames.SharedObject, config));
// If one link has to be created.
if (targetOutputReal == soName || targetOutput == soName) {
symlinkVars["SONAME"] =
@@ -1103,33 +1171,58 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
} else {
symlinkVars["SONAME"].clear();
build.Outputs.push_back(soName);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(soName);
}
}
build.Outputs.push_back(targetOutput);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(targetOutput);
}
build.ExplicitDeps.push_back(targetOutputReal);
build.Variables = std::move(symlinkVars);
globalGen->WriteBuild(this->GetBuildFileStream(), build);
globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), build);
}
}
// Add aliases for the file name and the target name.
globalGen->AddTargetAlias(this->TargetNames.Output, gt);
globalGen->AddTargetAlias(this->GetTargetName(), gt);
globalGen->AddTargetAlias(tgtNames.Output, gt, config);
globalGen->AddTargetAlias(this->GetTargetName(), gt, config);
}
void cmNinjaNormalTargetGenerator::WriteObjectLibStatement()
void cmNinjaNormalTargetGenerator::WriteObjectLibStatement(
const std::string& config)
{
// Write a phony output that depends on all object files.
{
cmNinjaBuild build("phony");
build.Comment = "Object library " + this->GetTargetName();
this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
build.Outputs);
build.ExplicitDeps = this->GetObjects();
this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
build.Outputs, config);
this->GetLocalGenerator()->AppendTargetOutputs(
this->GetGeneratorTarget(),
this->GetGlobalGenerator()->GetByproductsForCleanTarget(config), config);
build.ExplicitDeps = this->GetObjects(config);
this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), build);
}
// Add aliases for the target name.
this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
this->GetGeneratorTarget());
this->GetGlobalGenerator()->AddTargetAlias(
this->GetTargetName(), this->GetGeneratorTarget(), config);
}
cmGeneratorTarget::Names cmNinjaNormalTargetGenerator::TargetNames(
const std::string& config) const
{
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
return this->GeneratorTarget->GetExecutableNames(config);
}
return this->GeneratorTarget->GetLibraryNames(config);
}
std::string cmNinjaNormalTargetGenerator::TargetLinkLanguage(
const std::string& config) const
{
return this->GeneratorTarget->GetLinkerLanguage(config);
}
+13 -12
View File
@@ -17,30 +17,31 @@ public:
cmNinjaNormalTargetGenerator(cmGeneratorTarget* target);
~cmNinjaNormalTargetGenerator() override;
void Generate() override;
void Generate(const std::string& config) override;
private:
std::string LanguageLinkerRule() const;
std::string LanguageLinkerDeviceRule() const;
std::string LanguageLinkerRule(const std::string& config) const;
std::string LanguageLinkerDeviceRule(const std::string& config) const;
const char* GetVisibleTypeName() const;
void WriteLanguagesRules();
void WriteLanguagesRules(const std::string& config);
void WriteLinkRule(bool useResponseFile);
void WriteDeviceLinkRule(bool useResponseFile);
void WriteLinkRule(bool useResponseFile, const std::string& config);
void WriteDeviceLinkRule(bool useResponseFile, const std::string& config);
void WriteLinkStatement();
void WriteDeviceLinkStatement();
void WriteLinkStatement(const std::string& config,
const std::string& fileConfig, bool firstForConfig);
void WriteDeviceLinkStatement(const std::string& config);
void WriteObjectLibStatement();
void WriteObjectLibStatement(const std::string& config);
std::vector<std::string> ComputeLinkCmd();
std::vector<std::string> ComputeLinkCmd(const std::string& config);
std::vector<std::string> ComputeDeviceLinkCmd();
private:
// Target name info.
cmGeneratorTarget::Names TargetNames;
std::string TargetLinkLanguage;
cmGeneratorTarget::Names TargetNames(const std::string& config) const;
std::string TargetLinkLanguage(const std::string& config) const;
std::string DeviceLinkObject;
};
+183 -141
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
@@ -138,10 +149,10 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget()
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
// Refactor it.
std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
cmSourceFile const* source, const std::string& language)
cmSourceFile const* source, const std::string& language,
const std::string& config)
{
std::string flags = this->GetFlags(language);
const std::string configName = this->LocalGenerator->GetConfigName();
std::string flags = this->GetFlags(language, config);
// Add Fortran format flags.
if (language == "Fortran") {
@@ -150,7 +161,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
// Add source file specific flags.
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, configName, this->GeneratorTarget, language);
this->LocalGenerator, config, this->GeneratorTarget, language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
@@ -166,16 +177,16 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
// Add precompile headers compile options.
const std::string pchSource =
this->GeneratorTarget->GetPchSource(configName, language);
this->GeneratorTarget->GetPchSource(config, language);
if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
if (source->GetFullPath() == pchSource) {
pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions(
configName, language);
pchOptions =
this->GeneratorTarget->GetPchCreateCompileOptions(config, language);
} else {
pchOptions =
this->GeneratorTarget->GetPchUseCompileOptions(configName, language);
this->GeneratorTarget->GetPchUseCompileOptions(config, language);
}
this->LocalGenerator->AppendCompileOptions(
@@ -186,16 +197,17 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
}
void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
std::string const& language)
std::string const& language,
const std::string& config)
{
std::vector<std::string> includes;
this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
language, this->GetConfigName());
language, config);
// Add include directory flags.
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
includes, this->GeneratorTarget, language,
language == "RC", // full include paths for RC needed by cmcldeps
false, this->GetConfigName());
false, config);
if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/');
}
@@ -232,13 +244,18 @@ bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const
// TODO: Refactor with
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
const std::string& language)
const std::string& language,
const std::string& config)
{
std::set<std::string> defines;
const std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, config, this->GeneratorTarget, language);
// Seriously??
if (this->GetGlobalGenerator()->IsMultiConfig()) {
defines.insert(cmStrCat("CMAKE_INTDIR=\"", config, '"'));
}
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
this->LocalGenerator->AppendDefines(
@@ -253,17 +270,17 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS));
}
std::string definesString = this->GetDefines(language);
std::string definesString = this->GetDefines(language, config);
this->LocalGenerator->JoinDefines(defines, definesString, language);
return definesString;
}
std::string cmNinjaTargetGenerator::ComputeIncludes(
cmSourceFile const* source, const std::string& language)
cmSourceFile const* source, const std::string& language,
const std::string& config)
{
std::vector<std::string> includes;
const std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, config, this->GeneratorTarget, language);
@@ -277,13 +294,13 @@ std::string cmNinjaTargetGenerator::ComputeIncludes(
std::string includesString = this->LocalGenerator->GetIncludeFlags(
includes, this->GeneratorTarget, language, true, false, config);
this->LocalGenerator->AppendFlags(includesString,
this->GetIncludes(language));
this->GetIncludes(language, config));
return includesString;
}
cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
const std::string& linkLanguage) const
const std::string& linkLanguage, const std::string& config) const
{
// Static libraries never depend on other targets for linking.
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
@@ -292,7 +309,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
}
cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(this->GetConfigName());
this->GeneratorTarget->GetLinkInformation(config);
if (!cli) {
return cmNinjaDeps();
}
@@ -303,8 +320,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
// Add a dependency on the link definitions file, if any.
if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(
this->GetConfigName())) {
this->GeneratorTarget->GetModuleDefinitionInfo(config)) {
for (cmSourceFile const* src : mdi->Sources) {
result.push_back(this->ConvertToNinjaPath(src->GetFullPath()));
}
@@ -312,15 +328,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
// Add a dependency on user-specified manifest files, if any.
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
this->GeneratorTarget->GetManifests(manifest_srcs, config);
for (cmSourceFile const* manifest_src : manifest_srcs) {
result.push_back(this->ConvertToNinjaPath(manifest_src->GetFullPath()));
}
// Add user-specified dependencies.
std::vector<std::string> linkDeps;
this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName,
linkLanguage);
this->GeneratorTarget->GetLinkDepends(linkDeps, config, linkLanguage);
std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result),
MapToNinjaPath());
@@ -334,7 +349,7 @@ std::string cmNinjaTargetGenerator::GetSourceFilePath(
}
std::string cmNinjaTargetGenerator::GetObjectFilePath(
cmSourceFile const* source) const
cmSourceFile const* source, const std::string& config) const
{
std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
if (!path.empty()) {
@@ -342,13 +357,14 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath(
}
std::string const& objectName = this->GeneratorTarget->GetObjectName(source);
path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
path += this->GetGlobalGenerator()->ConfigDirectory(config);
path += "/";
path += objectName;
return path;
}
std::string cmNinjaTargetGenerator::GetPreprocessedFilePath(
cmSourceFile const* source) const
cmSourceFile const* source, const std::string& config) const
{
// Choose an extension to compile already-preprocessed source.
std::string ppExt = source->GetExtension();
@@ -378,19 +394,21 @@ std::string cmNinjaTargetGenerator::GetPreprocessedFilePath(
path += "/";
}
path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
path += this->GetGlobalGenerator()->ConfigDirectory(config);
path += "/";
path += ppName;
return path;
}
std::string cmNinjaTargetGenerator::GetDyndepFilePath(
std::string const& lang) const
std::string const& lang, const std::string& config) const
{
std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
if (!path.empty()) {
path += "/";
}
path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
path += this->GetGlobalGenerator()->ConfigDirectory(config);
path += "/";
path += lang;
path += ".dd";
@@ -398,25 +416,27 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath(
}
std::string cmNinjaTargetGenerator::GetTargetDependInfoPath(
std::string const& lang) const
std::string const& lang, const std::string& config) const
{
std::string path =
cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/',
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
'/', lang, "DependInfo.json");
this->GetGlobalGenerator()->ConfigDirectory(config), '/', lang,
"DependInfo.json");
return path;
}
std::string cmNinjaTargetGenerator::GetTargetOutputDir() const
std::string cmNinjaTargetGenerator::GetTargetOutputDir(
const std::string& config) const
{
std::string dir = this->GeneratorTarget->GetDirectory(this->GetConfigName());
std::string dir = this->GeneratorTarget->GetDirectory(config);
return ConvertToNinjaPath(dir);
}
std::string cmNinjaTargetGenerator::GetTargetFilePath(
const std::string& name) const
const std::string& name, const std::string& config) const
{
std::string path = this->GetTargetOutputDir();
std::string path = this->GetTargetOutputDir(config);
if (path.empty() || path == ".") {
return name;
}
@@ -430,21 +450,21 @@ std::string cmNinjaTargetGenerator::GetTargetName() const
return this->GeneratorTarget->GetName();
}
bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(
cmNinjaVars& vars, const std::string& config) const
{
cmMakefile* mf = this->GetMakefile();
if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") ||
mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") ||
mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) {
std::string pdbPath;
std::string compilePdbPath = this->ComputeTargetCompilePDB();
std::string compilePdbPath = this->ComputeTargetCompilePDB(config);
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
pdbPath = cmStrCat(
this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/',
this->GeneratorTarget->GetPDBName(this->GetConfigName()));
pdbPath = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config), '/',
this->GeneratorTarget->GetPDBName(config));
}
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
@@ -460,15 +480,17 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
return false;
}
void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language)
void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language,
const std::string& config)
{
#ifdef NINJA_GEN_VERBOSE_FILES
this->GetRulesFileStream() << "# Rules for language " << language << "\n\n";
#endif
this->WriteCompileRule(language);
this->WriteCompileRule(language, config);
}
void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
const std::string& config)
{
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
@@ -509,7 +531,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat(
ConvertToNinjaPath(this->GetTargetDependInfoPath(lang)),
ConvertToNinjaPath(this->GetTargetDependInfoPath(lang, config)),
cmLocalGenerator::SHELL);
std::string launcher;
@@ -524,7 +546,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
if (explicitPP) {
cmNinjaRule rule(this->LanguagePreprocessRule(lang));
cmNinjaRule rule(this->LanguagePreprocessRule(lang, config));
// Explicit preprocessing always uses a depfile.
rule.DepType = ""; // no deps= for multiple outputs
rule.DepFile = "$DEP_FILE";
@@ -604,7 +626,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
if (needDyndep) {
// Write the rule for ninja dyndep file generation.
cmNinjaRule rule(this->LanguageDyndepRule(lang));
cmNinjaRule rule(this->LanguageDyndepRule(lang, config));
// Command line length is almost always limited -> use response file for
// dyndep rules
rule.RspFile = "$out.rsp";
@@ -628,7 +650,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
this->GetGlobalGenerator()->AddRule(rule);
}
cmNinjaRule rule(this->LanguageCompilerRule(lang));
cmNinjaRule rule(this->LanguageCompilerRule(lang, config));
// If using a response file, move defines, includes, and flags into it.
if (!responseFlag.empty()) {
rule.RspFile = "$RSP_FILE";
@@ -787,50 +809,52 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
this->GetGlobalGenerator()->AddRule(rule);
}
void cmNinjaTargetGenerator::WriteObjectBuildStatements()
void cmNinjaTargetGenerator::WriteObjectBuildStatements(
const std::string& config, const std::string& fileConfig,
bool firstForConfig)
{
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
this->GetBuildFileStream()
cmGlobalNinjaGenerator::WriteDivider(this->GetConfigFileStream(fileConfig));
this->GetConfigFileStream(fileConfig)
<< "# Object build statements for "
<< cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType())
<< " target " << this->GetTargetName() << "\n\n";
{
std::vector<cmSourceFile const*> customCommands;
this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
this->GeneratorTarget->GetCustomCommands(customCommands, config);
for (cmSourceFile const* sf : customCommands) {
cmCustomCommand const* cc = sf->GetCustomCommand();
this->GetLocalGenerator()->AddCustomCommandTarget(
cc, this->GetGeneratorTarget());
// Record the custom commands for this target. The container is used
// in WriteObjectBuildStatement when called in a loop below.
this->CustomCommands.push_back(cc);
this->Configs[config].CustomCommands.push_back(cc);
}
}
{
std::vector<cmSourceFile const*> headerSources;
this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName);
this->GeneratorTarget->GetHeaderSources(headerSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
headerSources, this->MacOSXContentGenerator.get());
headerSources, this->MacOSXContentGenerator.get(), config);
}
{
std::vector<cmSourceFile const*> extraSources;
this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName);
this->GeneratorTarget->GetExtraSources(extraSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
extraSources, this->MacOSXContentGenerator.get());
extraSources, this->MacOSXContentGenerator.get(), config);
}
{
if (firstForConfig) {
const char* pchExtension =
GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
std::vector<cmSourceFile const*> externalObjects;
this->GeneratorTarget->GetExternalObjects(externalObjects,
this->ConfigName);
this->GeneratorTarget->GetExternalObjects(externalObjects, config);
for (cmSourceFile const* sf : externalObjects) {
const auto objectFileName = this->GetSourceFilePath(sf);
auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir(
this->GetSourceFilePath(sf), config);
if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
this->Objects.push_back(objectFileName);
this->Configs[config].Objects.push_back(objectFileName);
}
}
}
@@ -838,19 +862,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
{
cmNinjaBuild build("phony");
build.Comment = "Order-only phony target for " + this->GetTargetName();
build.Outputs.push_back(this->OrderDependsTargetForTarget());
build.Outputs.push_back(this->OrderDependsTargetForTarget(config));
cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps;
this->GetLocalGenerator()->AppendTargetDepends(
this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering);
this->GeneratorTarget, orderOnlyDeps, config, fileConfig,
DependOnTargetOrdering);
// Add order-only dependencies on other files associated with the target.
cmAppend(orderOnlyDeps, this->ExtraFiles);
cmAppend(orderOnlyDeps, this->Configs[config].ExtraFiles);
// Add order-only dependencies on custom command outputs.
for (cmCustomCommand const* cc : this->CustomCommands) {
cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
this->GetLocalGenerator());
for (cmCustomCommand const* cc : this->Configs[config].CustomCommands) {
cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator());
const std::vector<std::string>& ccoutputs = ccg.GetOutputs();
const std::vector<std::string>& ccbyproducts = ccg.GetByproducts();
std::transform(ccoutputs.begin(), ccoutputs.end(),
@@ -876,26 +900,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir));
}
this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
this->GetGlobalGenerator()->WriteBuild(
this->GetConfigFileStream(fileConfig), build);
}
{
std::vector<cmSourceFile const*> objectSources;
this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName);
this->GeneratorTarget->GetObjectSources(objectSources, config);
for (cmSourceFile const* sf : objectSources) {
this->WriteObjectBuildStatement(sf);
this->WriteObjectBuildStatement(sf, config, fileConfig, firstForConfig);
}
}
for (auto const& langDDIFiles : this->DDIFiles) {
for (auto const& langDDIFiles : this->Configs[config].DDIFiles) {
std::string const& language = langDDIFiles.first;
cmNinjaDeps const& ddiFiles = langDDIFiles.second;
cmNinjaBuild build(this->LanguageDyndepRule(language));
build.Outputs.push_back(this->GetDyndepFilePath(language));
cmNinjaBuild build(this->LanguageDyndepRule(language, config));
build.Outputs.push_back(this->GetDyndepFilePath(language, config));
build.ExplicitDeps = ddiFiles;
this->WriteTargetDependInfo(language);
this->WriteTargetDependInfo(language, config);
// Make sure dyndep files for all our dependencies have already
// been generated so that the '<LANG>Modules.json' files they
@@ -906,46 +931,51 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
// refactoring the Ninja generator to generate targets in
// dependency order so that we can collect the needed information.
this->GetLocalGenerator()->AppendTargetDepends(
this->GeneratorTarget, build.OrderOnlyDeps, DependOnTargetArtifact);
this->GeneratorTarget, build.OrderOnlyDeps, config, fileConfig,
DependOnTargetArtifact);
this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
this->GetGlobalGenerator()->WriteBuild(
this->GetConfigFileStream(fileConfig), build);
}
this->GetBuildFileStream() << "\n";
this->GetConfigFileStream(fileConfig) << "\n";
if (!this->SwiftOutputMap.empty()) {
if (!this->Configs[config].SwiftOutputMap.empty()) {
std::string const mapFilePath =
this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json";
std::string const targetSwiftDepsPath = [this]() -> std::string {
std::string const targetSwiftDepsPath = [this, config]() -> std::string {
cmGeneratorTarget const* target = this->GeneratorTarget;
if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) {
return name;
}
return this->ConvertToNinjaPath(target->GetSupportDirectory() + "/" +
target->GetName() + ".swiftdeps");
config + "/" + target->GetName() +
".swiftdeps");
}();
// build the global target dependencies
// https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps
Json::Value deps(Json::objectValue);
deps["swift-dependencies"] = targetSwiftDepsPath;
this->SwiftOutputMap[""] = deps;
this->Configs[config].SwiftOutputMap[""] = deps;
cmGeneratedFileStream output(mapFilePath);
output << this->SwiftOutputMap;
output << this->Configs[config].SwiftOutputMap;
}
}
void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmSourceFile const* source)
cmSourceFile const* source, const std::string& config,
const std::string& fileConfig, bool firstForConfig)
{
std::string const language = source->GetLanguage();
std::string const sourceFileName =
language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source);
std::string const objectDir =
this->ConvertToNinjaPath(this->GeneratorTarget->GetSupportDirectory());
std::string const objectDir = this->ConvertToNinjaPath(
cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
this->GetGlobalGenerator()->ConfigDirectory(config)));
std::string const objectFileName =
this->ConvertToNinjaPath(this->GetObjectFilePath(source));
this->ConvertToNinjaPath(this->GetObjectFilePath(source, config));
std::string const objectFileDir =
cmSystemTools::GetFilenamePath(objectFileName);
@@ -961,11 +991,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
int const commandLineLengthLimit =
((lang_supports_response && this->ForceResponseFile())) ? -1 : 0;
cmNinjaBuild objBuild(this->LanguageCompilerRule(language));
cmNinjaBuild objBuild(this->LanguageCompilerRule(language, config));
cmNinjaVars& vars = objBuild.Variables;
vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
vars["DEFINES"] = this->ComputeDefines(source, language);
vars["INCLUDES"] = this->ComputeIncludes(source, language);
vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config);
vars["DEFINES"] = this->ComputeDefines(source, language, config);
vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
if (!this->NeedDepTypeMSVC(language)) {
bool replaceExt(false);
@@ -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);
@@ -1006,13 +1038,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::vector<std::string> depList;
const std::string pchSource =
this->GeneratorTarget->GetPchSource(this->GetConfigName(), language);
this->GeneratorTarget->GetPchSource(config, language);
if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
depList.push_back(
this->GeneratorTarget->GetPchHeader(this->GetConfigName(), language));
depList.push_back(this->GeneratorTarget->GetPchHeader(config, language));
if (source->GetFullPath() != pchSource) {
depList.push_back(
this->GeneratorTarget->GetPchFile(this->GetConfigName(), language));
depList.push_back(this->GeneratorTarget->GetPchFile(config, language));
}
}
@@ -1033,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
@@ -1053,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";
@@ -1114,7 +1144,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags(
sourceDirectory, this->GeneratorTarget, language, false, false,
this->GetConfigName());
config);
vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"];
}
@@ -1138,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;
}
@@ -1163,15 +1195,15 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
vars);
this->SetMsvcTargetPdbVariable(vars);
this->SetMsvcTargetPdbVariable(vars, config);
objBuild.RspFile = objectFileName + ".rsp";
if (language == "Swift") {
this->EmitSwiftDependencyInfo(source);
this->EmitSwiftDependencyInfo(source, config);
} else {
this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(),
objBuild, commandLineLengthLimit);
this->GetGlobalGenerator()->WriteBuild(
this->GetConfigFileStream(fileConfig), objBuild, commandLineLengthLimit);
}
if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
@@ -1181,11 +1213,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::transform(build.Outputs.begin(), build.Outputs.end(),
build.Outputs.begin(), MapToNinjaPath());
build.ExplicitDeps = objBuild.Outputs;
this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
this->GetGlobalGenerator()->WriteBuild(
this->GetConfigFileStream(fileConfig), build);
}
}
void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
const std::string& config)
{
Json::Value tdi(Json::objectValue);
tdi["language"] = lang;
@@ -1213,7 +1247,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
Json::Value& tdi_include_dirs = tdi["include-dirs"] = Json::arrayValue;
std::vector<std::string> includes;
this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
lang, this->GetConfigName());
lang, config);
for (std::string const& i : includes) {
// Convert the include directories the same way we do for -I flags.
// See upstream ninja issue 1251.
@@ -1222,22 +1256,22 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] =
Json::arrayValue;
for (std::string const& l : this->GetLinkedTargetDirectories()) {
for (std::string const& l : this->GetLinkedTargetDirectories(config)) {
tdi_linked_target_dirs.append(l);
}
std::string const tdin = this->GetTargetDependInfoPath(lang);
std::string const tdin = this->GetTargetDependInfoPath(lang, config);
cmGeneratedFileStream tdif(tdin);
tdif << tdi;
}
void cmNinjaTargetGenerator::EmitSwiftDependencyInfo(
cmSourceFile const* source)
cmSourceFile const* source, const std::string& config)
{
std::string const sourceFilePath =
this->ConvertToNinjaPath(this->GetSourceFilePath(source));
std::string const objectFilePath =
this->ConvertToNinjaPath(this->GetObjectFilePath(source));
this->ConvertToNinjaPath(this->GetObjectFilePath(source, config));
std::string const swiftDepsPath = [source, objectFilePath]() -> std::string {
if (const char* name = source->GetProperty("Swift_DEPENDENCIES_FILE")) {
return name;
@@ -1250,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);
@@ -1274,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(
@@ -1349,27 +1383,34 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName);
}
void cmNinjaTargetGenerator::AdditionalCleanFiles()
void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config)
{
if (const char* prop_value =
this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) {
cmLocalNinjaGenerator* lg = this->LocalGenerator;
std::vector<std::string> cleanFiles;
cmExpandList(cmGeneratorExpression::Evaluate(
prop_value, lg,
this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"),
this->GeneratorTarget),
cmExpandList(cmGeneratorExpression::Evaluate(prop_value, lg, config,
this->GeneratorTarget),
cleanFiles);
std::string const& binaryDir = lg->GetCurrentBinaryDirectory();
cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator();
for (std::string const& cleanFile : cleanFiles) {
// Support relative paths
gg->AddAdditionalCleanFile(
cmSystemTools::CollapseFullPath(cleanFile, binaryDir));
cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config);
}
}
}
cmNinjaDeps cmNinjaTargetGenerator::GetObjects(const std::string& config) const
{
auto const it = this->Configs.find(config);
if (it != this->Configs.end()) {
return it->second.Objects;
}
return {};
}
void cmNinjaTargetGenerator::EnsureDirectoryExists(
const std::string& path) const
{
@@ -1392,7 +1433,7 @@ void cmNinjaTargetGenerator::EnsureParentDirectoryExists(
}
void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
cmSourceFile const& source, const char* pkgloc)
cmSourceFile const& source, const char* pkgloc, const std::string& config)
{
// Skip OS X content when not building a Framework or Bundle.
if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) {
@@ -1400,7 +1441,8 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
}
std::string macdir =
this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc,
config);
// Get the input file location.
std::string input = source.GetFullPath();
@@ -1412,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(
+65 -35
View File
@@ -38,16 +38,17 @@ public:
/// Destructor.
~cmNinjaTargetGenerator() override;
virtual void Generate() = 0;
virtual void Generate(const std::string& config) = 0;
std::string GetTargetName() const;
bool NeedDepTypeMSVC(const std::string& lang) const;
protected:
bool SetMsvcTargetPdbVariable(cmNinjaVars&) const;
bool SetMsvcTargetPdbVariable(cmNinjaVars&, const std::string& config) const;
cmGeneratedFileStream& GetBuildFileStream() const;
cmGeneratedFileStream& 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();
@@ -82,15 +86,19 @@ protected:
* by LanguageFlagsVarName().
*/
std::string ComputeFlagsForObject(cmSourceFile const* source,
const std::string& language);
const std::string& language,
const std::string& config);
void AddIncludeFlags(std::string& flags, std::string const& lang) override;
void AddIncludeFlags(std::string& flags, std::string const& lang,
const std::string& config) override;
std::string ComputeDefines(cmSourceFile const* source,
const std::string& language);
const std::string& language,
const std::string& config);
std::string ComputeIncludes(cmSourceFile const* source,
const std::string& language);
const std::string& language,
const std::string& config);
std::string ConvertToNinjaPath(const std::string& path) const
{
@@ -102,36 +110,51 @@ protected:
}
/// @return the list of link dependency for the given target @a target.
cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage) const;
cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage,
const std::string& config) const;
/// @return the source file path for the given @a source.
std::string GetSourceFilePath(cmSourceFile const* source) const;
/// @return the object file path for the given @a source.
std::string GetObjectFilePath(cmSourceFile const* source) const;
std::string GetObjectFilePath(cmSourceFile const* source,
const std::string& config) const;
/// @return the preprocessed source file path for the given @a source.
std::string GetPreprocessedFilePath(cmSourceFile const* source) const;
std::string GetPreprocessedFilePath(cmSourceFile const* source,
const std::string& config) const;
/// @return the dyndep file path for this target.
std::string GetDyndepFilePath(std::string const& lang) const;
std::string GetDyndepFilePath(std::string const& lang,
const std::string& config) const;
/// @return the target dependency scanner info file path
std::string GetTargetDependInfoPath(std::string const& lang) const;
std::string GetTargetDependInfoPath(std::string const& lang,
const std::string& config) const;
/// @return the file path where the target named @a name is generated.
std::string GetTargetFilePath(const std::string& name) const;
std::string GetTargetFilePath(const std::string& name,
const std::string& config) const;
/// @return the output path for the target.
virtual std::string GetTargetOutputDir() const;
virtual std::string GetTargetOutputDir(const std::string& config) const;
void WriteLanguageRules(const std::string& language);
void WriteCompileRule(const std::string& language);
void WriteObjectBuildStatements();
void WriteObjectBuildStatement(cmSourceFile const* source);
void WriteTargetDependInfo(std::string const& lang);
void WriteLanguageRules(const std::string& language,
const std::string& config);
void WriteCompileRule(const std::string& language,
const std::string& config);
void WriteObjectBuildStatements(const std::string& config,
const std::string& fileConfig,
bool firstForConfig);
void WriteObjectBuildStatement(cmSourceFile const* source,
const std::string& config,
const std::string& fileConfig,
bool firstForConfig);
void WriteTargetDependInfo(std::string const& lang,
const std::string& config);
void EmitSwiftDependencyInfo(cmSourceFile const* source);
void EmitSwiftDependencyInfo(cmSourceFile const* source,
const std::string& config);
void ExportObjectCompileCommand(
std::string const& language, std::string const& sourceFileName,
@@ -139,9 +162,9 @@ protected:
std::string const& objectFileDir, std::string const& flags,
std::string const& defines, std::string const& includes);
void AdditionalCleanFiles();
void AdditionalCleanFiles(const std::string& config);
cmNinjaDeps GetObjects() const { return this->Objects; }
cmNinjaDeps GetObjects(const std::string& config) const;
void EnsureDirectoryExists(const std::string& dir) const;
void EnsureParentDirectoryExists(const std::string& path) const;
@@ -155,7 +178,8 @@ protected:
{
}
void operator()(cmSourceFile const& source, const char* pkgloc) override;
void operator()(cmSourceFile const& source, const char* pkgloc,
const std::string& config) override;
private:
cmNinjaTargetGenerator* Generator;
@@ -174,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
+36 -15
View File
@@ -15,13 +15,13 @@
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
#include "cmNinjaTypes.h"
#include "cmOutputConverter.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
cmGeneratorTarget* target)
@@ -31,14 +31,18 @@ cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() = default;
void cmNinjaUtilityTargetGenerator::Generate()
void cmNinjaUtilityTargetGenerator::Generate(const std::string& config)
{
cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator();
cmLocalNinjaGenerator* lg = this->GetLocalGenerator();
cmGeneratorTarget* genTarget = this->GetGeneratorTarget();
std::string configDir;
if (genTarget->Target->IsPerConfig()) {
configDir = gg->ConfigDirectory(config);
}
std::string utilCommandName =
cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/",
cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles", configDir, "/",
this->GetTargetName(), ".util");
utilCommandName = this->ConvertToNinjaPath(utilCommandName);
@@ -55,8 +59,8 @@ void cmNinjaUtilityTargetGenerator::Generate()
for (std::vector<cmCustomCommand> const* cmdList : cmdLists) {
for (cmCustomCommand const& ci : *cmdList) {
cmCustomCommandGenerator ccg(ci, this->GetConfigName(), lg);
lg->AppendCustomCommandDeps(ccg, deps);
cmCustomCommandGenerator ccg(ci, config, lg);
lg->AppendCustomCommandDeps(ccg, deps, config);
lg->AppendCustomCommandLines(ccg, commands);
std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
std::transform(ccByproducts.begin(), ccByproducts.end(),
@@ -69,13 +73,11 @@ void cmNinjaUtilityTargetGenerator::Generate()
}
{
std::string const& config =
this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
std::vector<cmSourceFile*> sources;
genTarget->GetSourceFiles(sources, config);
for (cmSourceFile const* source : sources) {
if (cmCustomCommand const* cc = source->GetCustomCommand()) {
cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), lg);
cmCustomCommandGenerator ccg(*cc, config, lg);
lg->AddCustomCommandTarget(cc, genTarget);
// Depend on all custom command outputs.
@@ -89,13 +91,21 @@ void cmNinjaUtilityTargetGenerator::Generate()
}
}
lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs);
lg->AppendTargetDepends(genTarget, deps);
std::string outputConfig;
if (genTarget->Target->IsPerConfig()) {
outputConfig = config;
}
lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs, outputConfig);
if (genTarget->Target->GetType() != cmStateEnums::GLOBAL_TARGET) {
lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(),
config);
}
lg->AppendTargetDepends(genTarget, deps, config, config);
if (commands.empty()) {
phonyBuild.Comment = "Utility command for " + this->GetTargetName();
phonyBuild.ExplicitDeps = std::move(deps);
gg->WriteBuild(this->GetBuildFileStream(), phonyBuild);
gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
} else {
std::string command =
lg->BuildCommandLine(commands, "utility", this->GeneratorTarget);
@@ -118,6 +128,7 @@ void cmNinjaUtilityTargetGenerator::Generate()
lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
cmOutputConverter::SHELL));
cmSystemTools::ReplaceString(command, "$(ARGS)", "");
command = gg->ExpandCFGIntDir(command, config);
if (command.find('$') != std::string::npos) {
return;
@@ -127,22 +138,32 @@ void cmNinjaUtilityTargetGenerator::Generate()
gg->SeenCustomCommandOutput(util_output);
}
std::string ccConfig;
if (genTarget->Target->IsPerConfig() &&
genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
ccConfig = config;
}
gg->WriteCustomCommandBuild(command, desc,
"Utility command for " + this->GetTargetName(),
/*depfile*/ "", /*job_pool*/ "", uses_terminal,
/*restat*/ true, util_outputs, deps);
/*restat*/ true, util_outputs, ccConfig, deps);
phonyBuild.ExplicitDeps.push_back(utilCommandName);
gg->WriteBuild(this->GetBuildFileStream(), phonyBuild);
gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
}
// Find ADDITIONAL_CLEAN_FILES
this->AdditionalCleanFiles();
this->AdditionalCleanFiles(config);
// Add an alias for the logical target name regardless of what directory
// contains it. Skip this for GLOBAL_TARGET because they are meant to
// be per-directory and have one at the top-level anyway.
if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
gg->AddTargetAlias(this->GetTargetName(), genTarget);
gg->AddTargetAlias(this->GetTargetName(), genTarget, config);
} else if (gg->IsMultiConfig() && genTarget->Target->IsPerConfig()) {
cmNinjaBuild phonyAlias("phony");
gg->AppendTargetOutputs(genTarget, phonyAlias.Outputs, "");
phonyAlias.ExplicitDeps = phonyBuild.Outputs;
gg->WriteBuild(this->GetConfigFileStream(config), phonyAlias);
}
}
+3 -1
View File
@@ -5,6 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include "cmNinjaTargetGenerator.h"
class cmGeneratorTarget;
@@ -15,7 +17,7 @@ public:
cmNinjaUtilityTargetGenerator(cmGeneratorTarget* target);
~cmNinjaUtilityTargetGenerator() override;
void Generate() override;
void Generate(const std::string& config) override;
};
#endif // ! cmNinjaUtilityTargetGenerator_h
+32 -39
View File
@@ -3,7 +3,6 @@
#include "cmOSXBundleGenerator.h"
#include <cassert>
#include <utility>
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
@@ -15,12 +14,10 @@
class cmSourceFile;
cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target,
std::string configName)
cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target)
: GT(target)
, Makefile(target->Target->GetMakefile())
, LocalGenerator(target->GetLocalGenerator())
, ConfigName(std::move(configName))
, MacContentFolders(nullptr)
{
if (this->MustSkip()) {
@@ -34,34 +31,34 @@ bool cmOSXBundleGenerator::MustSkip()
}
void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
std::string& outpath)
std::string& outpath,
const std::string& config)
{
if (this->MustSkip()) {
return;
}
// Compute bundle directory names.
std::string out =
cmStrCat(outpath, '/',
this->GT->GetAppBundleDirectory(this->ConfigName,
cmGeneratorTarget::FullLevel));
std::string out = cmStrCat(
outpath, '/',
this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::FullLevel));
cmSystemTools::MakeDirectory(out);
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
std::string plist =
cmStrCat(outpath, '/',
this->GT->GetAppBundleDirectory(this->ConfigName,
cmGeneratorTarget::ContentLevel),
"/Info.plist");
std::string plist = cmStrCat(
outpath, '/',
this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::ContentLevel),
"/Info.plist");
this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist);
this->Makefile->AddCMakeOutputFile(plist);
outpath = out;
}
void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
const std::string& outpath)
const std::string& outpath,
const std::string& config)
{
if (this->MustSkip()) {
return;
@@ -70,15 +67,13 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
assert(this->MacContentFolders);
// Compute the location of the top-level foo.framework directory.
std::string contentdir =
cmStrCat(outpath, '/',
this->GT->GetFrameworkDirectory(this->ConfigName,
cmGeneratorTarget::ContentLevel),
'/');
std::string contentdir = cmStrCat(
outpath, '/',
this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::ContentLevel),
'/');
std::string newoutpath = outpath + "/" +
this->GT->GetFrameworkDirectory(this->ConfigName,
cmGeneratorTarget::FullLevel);
this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel);
std::string frameworkVersion = this->GT->GetFrameworkVersion();
@@ -156,27 +151,26 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
}
void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
const std::string& root)
const std::string& root,
const std::string& config)
{
if (this->MustSkip()) {
return;
}
// Compute bundle directory names.
std::string out =
cmStrCat(root, '/',
this->GT->GetCFBundleDirectory(this->ConfigName,
cmGeneratorTarget::FullLevel));
std::string out = cmStrCat(
root, '/',
this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel));
cmSystemTools::MakeDirectory(out);
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
std::string plist =
cmStrCat(root, '/',
this->GT->GetCFBundleDirectory(this->ConfigName,
cmGeneratorTarget::ContentLevel),
"/Info.plist");
std::string plist = cmStrCat(
root, '/',
this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel),
"/Info.plist");
std::string name = cmSystemTools::GetFilenameName(targetName);
this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist);
this->Makefile->AddCMakeOutputFile(plist);
@@ -184,7 +178,7 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
std::vector<cmSourceFile const*> const& sources,
MacOSXContentGeneratorType* generator)
MacOSXContentGeneratorType* generator, const std::string& config)
{
if (this->MustSkip()) {
return;
@@ -194,20 +188,19 @@ void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
cmGeneratorTarget::SourceFileFlags tsFlags =
this->GT->GetTargetSourceFileFlags(source);
if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
(*generator)(*source, tsFlags.MacFolder);
(*generator)(*source, tsFlags.MacFolder, config);
}
}
}
std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
const char* pkgloc)
const char* pkgloc, const std::string& config)
{
// Construct the full path to the content subdirectory.
std::string macdir =
cmStrCat(this->GT->GetMacContentDirectory(
this->ConfigName, cmStateEnums::RuntimeBinaryArtifact),
'/', pkgloc);
std::string macdir = cmStrCat(this->GT->GetMacContentDirectory(
config, cmStateEnums::RuntimeBinaryArtifact),
'/', pkgloc);
cmSystemTools::MakeDirectory(macdir);
// Record use of this content location. Only the first level
+12 -9
View File
@@ -17,29 +17,33 @@ class cmSourceFile;
class cmOSXBundleGenerator
{
public:
cmOSXBundleGenerator(cmGeneratorTarget* target, std::string configName);
cmOSXBundleGenerator(cmGeneratorTarget* target);
// create an app bundle at a given root, and return
// the directory within the bundle that contains the executable
void CreateAppBundle(const std::string& targetName, std::string& root);
void CreateAppBundle(const std::string& targetName, std::string& root,
const std::string& config);
// create a framework at a given root
void CreateFramework(const std::string& targetName, const std::string& root);
void CreateFramework(const std::string& targetName, const std::string& root,
const std::string& config);
// create a cf bundle at a given root
void CreateCFBundle(const std::string& targetName, const std::string& root);
void CreateCFBundle(const std::string& targetName, const std::string& root,
const std::string& config);
struct MacOSXContentGeneratorType
{
virtual ~MacOSXContentGeneratorType() = default;
virtual void operator()(cmSourceFile const& source,
const char* pkgloc) = 0;
virtual void operator()(cmSourceFile const& source, const char* pkgloc,
const std::string& config) = 0;
};
void GenerateMacOSXContentStatements(
std::vector<cmSourceFile const*> const& sources,
MacOSXContentGeneratorType* generator);
std::string InitMacOSXContentDirectory(const char* pkgloc);
MacOSXContentGeneratorType* generator, const std::string& config);
std::string InitMacOSXContentDirectory(const char* pkgloc,
const std::string& config);
void SetMacContentFolders(std::set<std::string>* macContentFolders)
{
@@ -53,7 +57,6 @@ private:
cmGeneratorTarget* GT;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
std::string ConfigName;
std::set<std::string>* MacContentFolders;
};
+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());
+11 -9
View File
@@ -211,6 +211,13 @@ if(BUILD_TESTING)
#---------------------------------------------------------------------------
# Add tests below here.
if(NOT DEFINED CMake_TEST_Qt5)
set(CMake_TEST_Qt5 1)
endif()
if(CMake_TEST_Qt5)
find_package(Qt5Widgets QUIET NO_MODULE)
endif()
if(NOT CMake_TEST_EXTERNAL_CMAKE)
add_subdirectory(CMakeLib)
@@ -1134,8 +1141,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 +1159,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()
@@ -1331,12 +1339,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt")
if(NOT DEFINED CMake_TEST_Qt5)
set(CMake_TEST_Qt5 1)
endif()
if(CMake_TEST_Qt5)
find_package(Qt5Widgets QUIET NO_MODULE)
endif()
if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND)
add_subdirectory(Qt5Autogen)
endif()
@@ -1868,7 +1870,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}")
+8 -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}
@@ -134,6 +134,13 @@ if(CMAKE_GENERATOR STREQUAL "Ninja")
list(APPEND Ninja_ARGS -DTEST_Fortran=1)
endif()
add_RunCMake_test(Ninja)
set(NinjaMultiConfig_ARGS
-DCYGWIN=${CYGWIN}
)
if(CMake_TEST_Qt5 AND Qt5Core_FOUND)
list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_Qt5=1)
endif()
add_RunCMake_test(NinjaMultiConfig)
endif()
add_RunCMake_test(CTest)
+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
@@ -0,0 +1,4 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
# Intentionally empty
)
@@ -0,0 +1,8 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${RunCMake_TEST_BINARY_DIR}/global.txt
${RunCMake_TEST_BINARY_DIR}/Debug.txt
${RunCMake_TEST_BINARY_DIR}/Release.txt
${RunCMake_TEST_BINARY_DIR}/MinSizeRel.txt
${RunCMake_TEST_BINARY_DIR}/RelWithDebInfo.txt
)
@@ -0,0 +1,6 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${RunCMake_TEST_BINARY_DIR}/Debug.txt
${RunCMake_TEST_BINARY_DIR}/MinSizeRel.txt
${RunCMake_TEST_BINARY_DIR}/RelWithDebInfo.txt
)
@@ -0,0 +1,3 @@
file(GENERATE OUTPUT $<CONFIG>.txt CONTENT "$<CONFIG>\n")
file(TOUCH ${CMAKE_BINARY_DIR}/global.txt)
set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "$<CONFIG>.txt;global.txt")
@@ -0,0 +1,10 @@
enable_language(C)
add_executable(badmoc badmoc.c)
target_compile_definitions(badmoc PRIVATE "CONFIG=\"$<CONFIG>\"")
add_executable(exe main.c)
set_target_properties(exe PROPERTIES
AUTOMOC ON
AUTOMOC_EXECUTABLE $<TARGET_FILE:badmoc>
)
@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.16)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
@@ -0,0 +1,16 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_mylib_Release}
${TARGET_LINKER_FILE_mylib_Release}
${TARGET_SONAME_FILE_mylib_Release}
${TARGET_OBJECT_FILES_mylib_Release}
${TARGET_OBJECT_FILES_myobj_Release}
${TARGET_FILE_exeall_Release}
${TARGET_EXE_FILE_exeall_Release}
${TARGET_OBJECT_FILES_exeall_Release}
EXCLUDE
${TARGET_OBJECT_FILES_exenotall_Release}
)
@@ -0,0 +1,7 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
EXCLUDE
${TARGET_OBJECT_FILES_exeall_Release}
${TARGET_OBJECT_FILES_exenotall_Release}
${TARGET_OBJECT_FILES_mylib_Release}
${TARGET_OBJECT_FILES_myobj_Release}
)
@@ -0,0 +1,16 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_mylib_Release}
${TARGET_LINKER_FILE_mylib_Release}
${TARGET_SONAME_FILE_mylib_Release}
${TARGET_OBJECT_FILES_mylib_Release}
${TARGET_OBJECT_FILES_myobj_Release}
${TARGET_FILE_exeall_Release}
${TARGET_EXE_FILE_exeall_Release}
${TARGET_OBJECT_FILES_exeall_Release}
${TARGET_FILE_exenotall_Release}
${TARGET_OBJECT_FILES_exenotall_Release}
)
@@ -0,0 +1,17 @@
enable_language(C)
add_executable(exeall main.c)
set_target_properties(exeall PROPERTIES VERSION 1.0.0)
add_executable(exenotall main.c)
set_target_properties(exenotall PROPERTIES EXCLUDE_FROM_ALL TRUE)
add_library(mylib SHARED simplelib.c)
set_target_properties(mylib PROPERTIES
VERSION 1.0.0
SOVERSION 1
)
add_library(myobj OBJECT simplelib.c)
include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
generate_output_files(exeall exenotall mylib myobj)
@@ -0,0 +1,57 @@
function(generate_output_files)
set(content)
foreach(tgt IN LISTS ARGN)
get_property(type TARGET ${tgt} PROPERTY TYPE)
if(NOT type STREQUAL "OBJECT_LIBRARY")
set(file " [==[$<TARGET_FILE:${tgt}>]==]")
set(filename " [==[$<TARGET_FILE_NAME:${tgt}>]==]")
else()
set(file)
set(filename)
endif()
string(APPEND content "set(TARGET_FILE_${tgt}_$<CONFIG>${file})\n")
string(APPEND content "set(TARGET_FILE_NAME_${tgt}_$<CONFIG>${filename})\n")
if(type MATCHES "^(STATIC|MODULE|SHARED)_LIBRARY$")
set(linker_file " [==[$<TARGET_LINKER_FILE:${tgt}>]==]")
set(linker_filename " [==[$<TARGET_LINKER_FILE_NAME:${tgt}>]==]")
else()
set(linker_file)
set(linker_filename)
endif()
string(APPEND content "set(TARGET_LINKER_FILE_${tgt}_$<CONFIG>${linker_file})\n")
string(APPEND content "set(TARGET_LINKER_FILE_NAME_${tgt}_$<CONFIG>${linker_filename})\n")
if(NOT WIN32 AND NOT CYGWIN AND type MATCHES "^(SHARED_LIBRARY)$")
set(soname_file " [==[$<TARGET_SONAME_FILE:${tgt}>]==]")
set(soname_filename " [==[$<TARGET_SONAME_FILE_NAME:${tgt}>]==]")
else()
set(soname_file)
set(soname_filename)
endif()
string(APPEND content "set(TARGET_SONAME_FILE_${tgt}_$<CONFIG>${soname_file})\n")
string(APPEND content "set(TARGET_SONAME_FILE_NAME_${tgt}_$<CONFIG>${soname_filename})\n")
if(type MATCHES "^(EXECUTABLE)$")
set(exe_file " [==[$<TARGET_FILE_DIR:${tgt}>/$<TARGET_FILE_PREFIX:${tgt}>$<TARGET_FILE_BASE_NAME:${tgt}>$<TARGET_FILE_SUFFIX:${tgt}>]==]")
set(exe_filename " [==[$<TARGET_FILE_PREFIX:${tgt}>$<TARGET_FILE_BASE_NAME:${tgt}>$<TARGET_FILE_SUFFIX:${tgt}>]==]")
else()
set(exe_file)
set(exe_filename)
endif()
string(APPEND content "set(TARGET_EXE_FILE_${tgt}_$<CONFIG>${exe_file})\n")
string(APPEND content "set(TARGET_EXE_FILE_NAME_${tgt}_$<CONFIG>${exe_filename})\n")
string(APPEND content "set(TARGET_OBJECT_FILES_${tgt}_$<CONFIG> [==[$<TARGET_OBJECTS:${tgt}>]==])\n")
endforeach()
file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/target_files_$<CONFIG>.cmake" CONTENT "${content}")
set(content)
foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
string(APPEND content "include(\${CMAKE_CURRENT_LIST_DIR}/target_files_${config}.cmake)\n")
endforeach()
file(WRITE "${CMAKE_BINARY_DIR}/target_files.cmake" "${content}")
endfunction()
@@ -0,0 +1,38 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${CONFIG_FILES}
${GENERATED_FILES}
${TARGET_FILE_generator_Debug}
${TARGET_OBJECT_FILES_generator_Debug}
${TARGET_FILE_generated_Debug}
${TARGET_OBJECT_FILES_generated_Debug}
${TARGET_FILE_generatorlib_Debug}
${TARGET_LINKER_FILE_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorobj_Debug}
${TARGET_OBJECT_FILES_emptyobj_Debug}
EXCLUDE
${TARGET_OBJECT_FILES_generator_Release}
${TARGET_OBJECT_FILES_generated_Release}
${TARGET_OBJECT_FILES_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorobj_Release}
${TARGET_OBJECT_FILES_emptyobj_Release}
${TARGET_OBJECT_FILES_generator_MinSizeRel}
${TARGET_OBJECT_FILES_generated_MinSizeRel}
${TARGET_OBJECT_FILES_generatorlib_MinSizeRel}
${TARGET_OBJECT_FILES_generatorobj_MinSizeRel}
${TARGET_OBJECT_FILES_emptyobj_MinSizeRel}
${TARGET_OBJECT_FILES_generator_RelWithDebInfo}
${TARGET_OBJECT_FILES_generated_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo}
${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo}
)
@@ -0,0 +1,37 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${CONFIG_FILES}
${TARGET_FILE_generator_Release}
${TARGET_OBJECT_FILES_generator_Release}
${TARGET_FILE_generated_Release}
${TARGET_OBJECT_FILES_generated_Release}
${TARGET_FILE_generatorlib_Release}
${TARGET_LINKER_FILE_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorobj_Release}
${TARGET_OBJECT_FILES_emptyobj_Release}
EXCLUDE
${TARGET_OBJECT_FILES_generator_Debug}
${TARGET_OBJECT_FILES_generated_Debug}
${TARGET_OBJECT_FILES_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorobj_Debug}
${TARGET_OBJECT_FILES_emptyobj_Debug}
${TARGET_OBJECT_FILES_generator_MinSizeRel}
${TARGET_OBJECT_FILES_generated_MinSizeRel}
${TARGET_OBJECT_FILES_generatorlib_MinSizeRel}
${TARGET_OBJECT_FILES_generatorobj_MinSizeRel}
${TARGET_OBJECT_FILES_emptyobj_MinSizeRel}
${TARGET_OBJECT_FILES_generator_RelWithDebInfo}
${TARGET_OBJECT_FILES_generated_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo}
${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo}
)
@@ -0,0 +1,12 @@
^Generator genex config definition: Debug
Generator genex config include dir: Debug
Generator library genex config definition: Debug
Generator library genex config include dir: Debug
Generator object genex config definition: Debug
Generator object genex config include dir: Debug
Generated genex config definition: Debug
Generated genex config include dir: Debug
Generated library genex config definition: Debug
Generated library genex config include dir: Debug
Generated object genex config definition: Debug
Generated object genex config include dir: Debug$
@@ -0,0 +1,44 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${CONFIG_FILES}
${GENERATED_FILES}
${TARGET_FILE_generated_Debug}
${TARGET_OBJECT_FILES_generated_Debug}
${TARGET_FILE_generatorlib_Debug}
${TARGET_LINKER_FILE_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorobj_Debug}
${TARGET_OBJECT_FILES_emptyobj_Debug}
${TARGET_FILE_generator_Release}
${TARGET_OBJECT_FILES_generator_Release}
${TARGET_FILE_generatorlib_Release}
${TARGET_LINKER_FILE_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorobj_Release}
${TARGET_OBJECT_FILES_emptyobj_Release}
EXCLUDE
${TARGET_OBJECT_FILES_generator_Debug}
${TARGET_OBJECT_FILES_generated_Release}
${TARGET_OBJECT_FILES_generator_MinSizeRel}
${TARGET_OBJECT_FILES_generated_MinSizeRel}
${TARGET_OBJECT_FILES_generatorlib_MinSizeRel}
${TARGET_OBJECT_FILES_generatorobj_MinSizeRel}
${TARGET_OBJECT_FILES_emptyobj_MinSizeRel}
${TARGET_OBJECT_FILES_generator_RelWithDebInfo}
${TARGET_OBJECT_FILES_generated_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo}
${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo}
)
@@ -0,0 +1,36 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${CONFIG_FILES}
${TARGET_FILE_generator_Release}
${TARGET_OBJECT_FILES_generator_Release}
${TARGET_FILE_generatorlib_Release}
${TARGET_LINKER_FILE_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorobj_Release}
${TARGET_OBJECT_FILES_emptyobj_Release}
EXCLUDE
${TARGET_OBJECT_FILES_generator_Debug}
${TARGET_OBJECT_FILES_generated_Debug}
${TARGET_OBJECT_FILES_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorobj_Debug}
${TARGET_OBJECT_FILES_emptyobj_Debug}
${TARGET_OBJECT_FILES_generated_Release}
${TARGET_OBJECT_FILES_generator_MinSizeRel}
${TARGET_OBJECT_FILES_generated_MinSizeRel}
${TARGET_OBJECT_FILES_generatorlib_MinSizeRel}
${TARGET_OBJECT_FILES_generatorobj_MinSizeRel}
${TARGET_OBJECT_FILES_emptyobj_MinSizeRel}
${TARGET_OBJECT_FILES_generator_RelWithDebInfo}
${TARGET_OBJECT_FILES_generated_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo}
${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo}
)
@@ -0,0 +1,12 @@
^Generator genex config definition: Release
Generator genex config include dir: Release
Generator library genex config definition: Release
Generator library genex config include dir: Release
Generator object genex config definition: Release
Generator object genex config include dir: Release
Generated genex config definition: Debug
Generated genex config include dir: Debug
Generated library genex config definition: Debug
Generated library genex config include dir: Debug
Generated object genex config definition: Debug
Generated object genex config include dir: Debug$
@@ -0,0 +1,29 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${CONFIG_FILES}
EXCLUDE
${TARGET_OBJECT_FILES_generator_Debug}
${TARGET_OBJECT_FILES_generated_Debug}
${TARGET_OBJECT_FILES_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorobj_Debug}
${TARGET_OBJECT_FILES_emptyobj_Debug}
${TARGET_OBJECT_FILES_generator_Release}
${TARGET_OBJECT_FILES_generated_Release}
${TARGET_OBJECT_FILES_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorobj_Release}
${TARGET_OBJECT_FILES_emptyobj_Release}
${TARGET_OBJECT_FILES_generator_MinSizeRel}
${TARGET_OBJECT_FILES_generated_MinSizeRel}
${TARGET_OBJECT_FILES_generatorlib_MinSizeRel}
${TARGET_OBJECT_FILES_generatorobj_MinSizeRel}
${TARGET_OBJECT_FILES_emptyobj_MinSizeRel}
${TARGET_OBJECT_FILES_generator_RelWithDebInfo}
${TARGET_OBJECT_FILES_generated_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo}
${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo}
)
@@ -0,0 +1,12 @@
^Generator genex config definition: Release
Generator genex config include dir: Release
Generator library genex config definition: Release
Generator library genex config include dir: Release
Generator object genex config definition: Release
Generator object genex config include dir: Release
Generated genex config definition: Release
Generated genex config include dir: Release
Generated library genex config definition: Release
Generated library genex config include dir: Release
Generated object genex config definition: Release
Generated object genex config include dir: Release$
@@ -0,0 +1,12 @@
^Generator genex config definition: Debug
Generator genex config include dir: Debug
Generator library genex config definition: Debug
Generator library genex config include dir: Debug
Generator object genex config definition: Debug
Generator object genex config include dir: Debug
Generated genex config definition: Release
Generated genex config include dir: Release
Generated library genex config definition: Release
Generated library genex config include dir: Release
Generated object genex config definition: Release
Generated object genex config include dir: Release$
@@ -0,0 +1,45 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${CONFIG_FILES}
${GENERATED_FILES}
${TARGET_FILE_generator_Debug}
${TARGET_OBJECT_FILES_generator_Debug}
${TARGET_FILE_generatorlib_Debug}
${TARGET_LINKER_FILE_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorobj_Debug}
${TARGET_OBJECT_FILES_emptyobj_Debug}
${TARGET_FILE_generator_Release}
${TARGET_OBJECT_FILES_generator_Release}
${TARGET_FILE_generated_Release}
${TARGET_OBJECT_FILES_generated_Release}
${TARGET_FILE_generatorlib_Release}
${TARGET_LINKER_FILE_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorobj_Release}
${TARGET_OBJECT_FILES_emptyobj_Release}
EXCLUDE
${TARGET_OBJECT_FILES_generated_Debug}
${TARGET_OBJECT_FILES_generator_MinSizeRel}
${TARGET_OBJECT_FILES_generated_MinSizeRel}
${TARGET_OBJECT_FILES_generatorlib_MinSizeRel}
${TARGET_OBJECT_FILES_generatorobj_MinSizeRel}
${TARGET_OBJECT_FILES_emptyobj_MinSizeRel}
${TARGET_OBJECT_FILES_generator_RelWithDebInfo}
${TARGET_OBJECT_FILES_generated_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo}
${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo}
)
@@ -0,0 +1,46 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${CONFIG_FILES}
${GENERATED_FILES}
${TARGET_FILE_generator_Debug}
${TARGET_OBJECT_FILES_generator_Debug}
${TARGET_FILE_generated_Debug}
${TARGET_OBJECT_FILES_generated_Debug}
${TARGET_FILE_generatorlib_Debug}
${TARGET_LINKER_FILE_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorlib_Debug}
${TARGET_OBJECT_FILES_generatorobj_Debug}
${TARGET_OBJECT_FILES_emptyobj_Debug}
${TARGET_FILE_generator_Release}
${TARGET_OBJECT_FILES_generator_Release}
${TARGET_FILE_generated_Release}
${TARGET_OBJECT_FILES_generated_Release}
${TARGET_FILE_generatorlib_Release}
${TARGET_LINKER_FILE_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorlib_Release}
${TARGET_OBJECT_FILES_generatorobj_Release}
${TARGET_OBJECT_FILES_emptyobj_Release}
EXCLUDE
${TARGET_OBJECT_FILES_generator_MinSizeRel}
${TARGET_OBJECT_FILES_generated_MinSizeRel}
${TARGET_OBJECT_FILES_generatorlib_MinSizeRel}
${TARGET_OBJECT_FILES_generatorobj_MinSizeRel}
${TARGET_OBJECT_FILES_emptyobj_MinSizeRel}
${TARGET_OBJECT_FILES_generator_RelWithDebInfo}
${TARGET_OBJECT_FILES_generated_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo}
${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo}
${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo}
)
@@ -0,0 +1,56 @@
enable_language(C)
add_library(generatorlib STATIC generatorlib.c)
add_library(generatorobj OBJECT generatorobj.c)
add_library(emptyobj OBJECT empty.c)
add_library(emptyobj2 OBJECT empty.c)
add_executable(generator generator.c $<TARGET_OBJECTS:generatorobj>)
target_link_libraries(generator PRIVATE generatorlib)
add_custom_command(OUTPUT generated.c COMMAND generator generated.c)
add_executable(generated ${CMAKE_BINARY_DIR}/generated.c $<TARGET_OBJECTS:generatorobj> $<TARGET_OBJECTS:emptyobj>)
target_link_libraries(generated PRIVATE generatorlib)
file(GENERATE OUTPUT include/genex/$<CONFIG>/genex_config.h CONTENT
"#ifndef GENEX_CONFIG_H
#define GENEX_CONFIG_H
#define GENEX_CONFIG_INCLUDE_DIR \"$<CONFIG>\"
#endif /* GENEX_CONFIG_H */
")
file(GENERATE OUTPUT include/intdir/$<CONFIG>/intdir_config.h CONTENT
"#ifndef INTDIR_CONFIG_H
#define INTDIR_CONFIG_H
#define INTDIR_CONFIG_INCLUDE_DIR \"$<CONFIG>\"
#endif /* INTDIR_CONFIG_H */
")
foreach(g generatorlib generatorobj generator generated)
target_compile_definitions(${g} PRIVATE
"GENEX_CONFIG_DEFINITION=\"$<CONFIG>\""
# FIXME Get this working
# "INTDIR_CONFIG_DEFINITION=\"${CMAKE_CFG_INTDIR}\""
)
target_include_directories(${g} PRIVATE
"${CMAKE_BINARY_DIR}/include/genex/$<CONFIG>"
# FIXME Get this working
# "${CMAKE_BINARY_DIR}/include/intdir/${CMAKE_CFG_INTDIR}"
)
endforeach()
include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
generate_output_files(generatorlib generatorobj emptyobj generator generated)
file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(GENERATED_FILES [==[${CMAKE_BINARY_DIR}/generated.c]==])\n")
set(genfiles)
foreach(cfg Debug Release MinSizeRel RelWithDebInfo)
list(APPEND genfiles
${CMAKE_BINARY_DIR}/include/genex/${cfg}/genex_config.h
${CMAKE_BINARY_DIR}/include/intdir/${cfg}/intdir_config.h
)
endforeach()
file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(CONFIG_FILES [==[${genfiles}]==])\n")
@@ -0,0 +1,6 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
${TARGET_DEPENDS_TopCommand}
)
check_file_contents("${TARGET_DEPENDS_TopCommand}" "^Genex config: Debug\nINTDIR config: Debug\n$")
@@ -0,0 +1,8 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
${TARGET_DEPENDS_TopCommand}
${TARGET_BYPRODUCTS_SubdirTarget}
${TARGET_BYPRODUCTS_TopTarget}
${TARGET_FILE_SubdirPostBuild_Debug}
)
@@ -0,0 +1,8 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
${TARGET_DEPENDS_TopCommand}
${TARGET_BYPRODUCTS_SubdirTarget}
${TARGET_BYPRODUCTS_TopTarget}
)
check_file_contents("${TARGET_BYPRODUCTS_TopTarget}" "^Genex config: Debug\nINTDIR config: Debug\n$")
@@ -0,0 +1,12 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
${TARGET_DEPENDS_TopCommand}
${TARGET_BYPRODUCTS_SubdirTarget}
${TARGET_BYPRODUCTS_TopTarget}
${TARGET_FILE_SubdirPostBuild_Debug}
${TARGET_FILE_SubdirPostBuild_Release}
${TARGET_BYPRODUCTS_SubdirPostBuild}
${TARGET_BYPRODUCTS_TopTargetPostBuild}
)
check_file_contents("${TARGET_BYPRODUCTS_TopTargetPostBuild}" "^Genex config: Debug\nINTDIR config: Debug\n$")
@@ -0,0 +1,5 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
)
check_file_contents("${TARGET_DEPENDS_SubdirCommand}" "^Genex config: MinSizeRel\nINTDIR config: MinSizeRel\n$")
@@ -0,0 +1,5 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
)
check_file_contents("${TARGET_DEPENDS_SubdirCommand}" "^Genex config: Release\nINTDIR config: Release\n$")
@@ -0,0 +1,11 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
${TARGET_DEPENDS_TopCommand}
${TARGET_BYPRODUCTS_SubdirTarget}
${TARGET_BYPRODUCTS_TopTarget}
${TARGET_FILE_SubdirPostBuild_Debug}
${TARGET_FILE_SubdirPostBuild_Release}
${TARGET_BYPRODUCTS_SubdirPostBuild}
)
check_file_contents("${TARGET_BYPRODUCTS_SubdirPostBuild}" "^Genex config: Release\nINTDIR config: Release\n$")
@@ -0,0 +1,7 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
${TARGET_DEPENDS_TopCommand}
${TARGET_BYPRODUCTS_SubdirTarget}
)
check_file_contents("${TARGET_BYPRODUCTS_SubdirTarget}" "^Genex config: Release\nINTDIR config: Release\n$")
@@ -0,0 +1,13 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_DEPENDS_SubdirCommand}
${TARGET_DEPENDS_TopCommand}
${TARGET_BYPRODUCTS_SubdirTarget}
${TARGET_BYPRODUCTS_TopTarget}
${TARGET_FILE_SubdirPostBuild_Debug}
${TARGET_FILE_SubdirPostBuild_Release}
${TARGET_BYPRODUCTS_SubdirPostBuild}
${TARGET_BYPRODUCTS_TopTargetPostBuild}
${TARGET_BYPRODUCTS_SubdirTargetPostBuild}
)
check_file_contents("${TARGET_BYPRODUCTS_SubdirTargetPostBuild}" "^Genex config: Release\nINTDIR config: Release\n$")
@@ -0,0 +1,39 @@
enable_language(C)
file(REMOVE "${CMAKE_BINARY_DIR}/target_files_custom.cmake")
function(get_write_file_command var filename)
set(${var} ${CMAKE_COMMAND} -DOUTPUT_FILE=${filename} -DGENEX_CONFIG=$<CONFIG> -DINTDIR_CONFIG=${CMAKE_CFG_INTDIR} -P ${CMAKE_SOURCE_DIR}/WriteFile.cmake PARENT_SCOPE)
endfunction()
function(create_targets prefix)
get_write_file_command(cmd ${prefix}Command.txt)
add_custom_command(OUTPUT ${prefix}Command.txt COMMAND ${cmd})
add_custom_target(${prefix}Command DEPENDS ${prefix}Command.txt)
get_write_file_command(cmd ${prefix}Target.txt)
add_custom_target(${prefix}Target COMMAND ${cmd} BYPRODUCTS ${prefix}Target.txt)
get_write_file_command(cmd ${prefix}PostBuild.txt)
add_executable(${prefix}PostBuild ${CMAKE_SOURCE_DIR}/main.c)
add_custom_command(TARGET ${prefix}PostBuild COMMAND ${cmd} BYPRODUCTS ${prefix}PostBuild.txt)
get_write_file_command(cmd ${prefix}TargetPostBuild.txt)
add_custom_target(${prefix}TargetPostBuild)
add_custom_command(TARGET ${prefix}TargetPostBuild COMMAND ${cmd} BYPRODUCTS ${prefix}TargetPostBuild.txt)
file(APPEND "${CMAKE_BINARY_DIR}/target_files_custom.cmake"
"set(TARGET_DEPENDS_${prefix}Command [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}Command.txt]==])
set(TARGET_BYPRODUCTS_${prefix}Target [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}Target.txt]==])
set(TARGET_BYPRODUCTS_${prefix}PostBuild [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}PostBuild.txt]==])
set(TARGET_BYPRODUCTS_${prefix}TargetPostBuild [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}TargetPostBuild.txt]==])
")
endfunction()
add_subdirectory(CustomCommandsAndTargetsSubdir)
create_targets(Top)
include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
generate_output_files(TopPostBuild SubdirPostBuild)
file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "include(\${CMAKE_CURRENT_LIST_DIR}/target_files_custom.cmake)\n")
@@ -0,0 +1 @@
create_targets(Subdir)
@@ -0,0 +1,31 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_exe_Debug}
${TARGET_OBJECT_FILES_exe_Debug}
${TARGET_FILE_mylib_Release}
${TARGET_LINKER_FILE_mylib_Debug}
${TARGET_OBJECT_FILES_mylib_Debug}
${RunCMake_TEST_BINARY_DIR}/install/bin/Debug/${TARGET_FILE_NAME_exe_Debug}
${RunCMake_TEST_BINARY_DIR}/install/lib/Debug/${TARGET_FILE_NAME_mylib_Debug}
${RunCMake_TEST_BINARY_DIR}/install/lib/Debug/${TARGET_LINKER_FILE_NAME_mylib_Debug}
${TARGET_FILE_exe_Release}
${TARGET_OBJECT_FILES_exe_Release}
${TARGET_FILE_mylib_Release}
${TARGET_LINKER_FILE_mylib_Release}
${TARGET_OBJECT_FILES_mylib_Release}
${RunCMake_TEST_BINARY_DIR}/install/bin/Release/${TARGET_FILE_NAME_exe_Release}
${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_FILE_NAME_mylib_Release}
${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_LINKER_FILE_NAME_mylib_Release}
EXCLUDE
${TARGET_OBJECT_FILES_exe_MinSizeRel}
${TARGET_OBJECT_FILES_mylib_MinSizeRel}
${TARGET_OBJECT_FILES_exe_RelWithDebInfo}
${TARGET_OBJECT_FILES_mylib_RelWithDebInfo}
)
@@ -0,0 +1,23 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_exe_Release}
${TARGET_OBJECT_FILES_exe_Release}
${TARGET_FILE_mylib_Release}
${TARGET_LINKER_FILE_mylib_Release}
${TARGET_OBJECT_FILES_mylib_Release}
${RunCMake_TEST_BINARY_DIR}/install/bin/Release/${TARGET_FILE_NAME_exe_Release}
${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_FILE_NAME_mylib_Release}
${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_LINKER_FILE_NAME_mylib_Release}
EXCLUDE
${TARGET_OBJECT_FILES_exe_Debug}
${TARGET_OBJECT_FILES_mylib_Debug}
${TARGET_OBJECT_FILES_exe_MinSizeRel}
${TARGET_OBJECT_FILES_mylib_MinSizeRel}
${TARGET_OBJECT_FILES_exe_RelWithDebInfo}
${TARGET_OBJECT_FILES_mylib_RelWithDebInfo}
)
@@ -0,0 +1,10 @@
enable_language(C)
add_executable(exe main.c)
add_library(mylib STATIC simplelib.c)
install(TARGETS exe DESTINATION bin/$<CONFIG>)
install(TARGETS mylib DESTINATION lib/$<CONFIG>)
include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
generate_output_files(exe mylib)

Some files were not shown because too many files have changed in this diff Show More