From b115bc49ff26da9db3e9238a98030fd94847d0d0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 Apr 2017 14:17:13 -0400 Subject: Features: Refactor _STANDARD update In order to support generator expressions in target COMPILE_FEATURES we apply them at generate time. Move this step to the beginning of generation instead of doing it on demand while collecting flags. This avoids repeating the process unnecessarily, and will then allow `cmLocalGenerator::AddCompilerRequirementFlag` to be used any time during generation. --- Source/cmGeneratorTarget.cxx | 13 +++++++++++++ Source/cmGeneratorTarget.h | 2 ++ Source/cmGlobalGenerator.cxx | 12 ++++++++++++ Source/cmLocalGenerator.cxx | 33 +++++++++++++++++++++++++-------- Source/cmLocalGenerator.h | 2 ++ 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a0f677b..3f50e32 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2919,6 +2919,19 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const } } +bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const +{ + std::vector features; + this->GetCompileFeatures(features, config); + for (std::vector::const_iterator it = features.begin(); + it != features.end(); ++it) { + if (!this->Makefile->AddRequiredTargetFeature(this->Target, *it)) { + return false; + } + } + return true; +} + std::string cmGeneratorTarget::GetImportedLibName( std::string const& config) const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 13b6b73..134b7c7 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -412,6 +412,8 @@ public: /** Add the target output files to the global generator manifest. */ void ComputeTargetManifest(const std::string& config) const; + bool ComputeCompileFeatures(std::string const& config) const; + /** * Trace through the source files in this target and add al source files * that they depend on, used by all generators diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 50ad1a8..f3eb249 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1272,6 +1272,18 @@ bool cmGlobalGenerator::Compute() this->LocalGenerators[i]->AddHelperCommands(); } + // Finalize the set of compile features for each target. + // FIXME: This turns into calls to cmMakefile::AddRequiredTargetFeature + // which actually modifies the _STANDARD target property + // on the original cmTarget instance. It accumulates features + // across all configurations. Some refactoring is needed to + // compute a per-config resulta purely during generation. + for (i = 0; i < this->LocalGenerators.size(); ++i) { + if (!this->LocalGenerators[i]->ComputeTargetCompileFeatures()) { + return false; + } + } + #ifdef CMAKE_BUILD_WITH_CMAKE for (std::vector::iterator it = autogenTargets.begin(); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 33e32d1..6c8f132 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -558,6 +558,31 @@ void cmLocalGenerator::ComputeTargetManifest() } } +bool cmLocalGenerator::ComputeTargetCompileFeatures() +{ + // Collect the set of configuration types. + std::vector configNames; + this->Makefile->GetConfigurations(configNames); + if (configNames.empty()) { + configNames.push_back(""); + } + + // Process compile features of all targets. + std::vector targets = this->GetGeneratorTargets(); + for (std::vector::iterator t = targets.begin(); + t != targets.end(); ++t) { + cmGeneratorTarget* target = *t; + for (std::vector::iterator ci = configNames.begin(); + ci != configNames.end(); ++ci) { + if (!target->ComputeCompileFeatures(*ci)) { + return false; + } + } + } + + return true; +} + bool cmLocalGenerator::IsRootMakefile() const { return !this->StateSnapshot.GetBuildsystemDirectoryParent().IsValid(); @@ -742,14 +767,6 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, this->AppendFlagEscape(flags, *i); } } - std::vector features; - target->GetCompileFeatures(features, config); - for (std::vector::const_iterator it = features.begin(); - it != features.end(); ++it) { - if (!this->Makefile->AddRequiredTargetFeature(target->Target, *it)) { - return; - } - } for (std::map::const_iterator it = target->GetMaxLanguageStandards().begin(); diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 1a238a8..7d591ac 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -70,6 +70,8 @@ public: */ void ComputeTargetManifest(); + bool ComputeTargetCompileFeatures(); + bool IsRootMakefile() const; ///! Get the makefile for this generator -- cgit v0.12 From d037be122e15fb3860869e07a0b6ccd8e7d4d94a Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 Apr 2017 14:30:00 -0400 Subject: cmLocalGenerator: Add a hook for compiler flags used at link time When using a compiler to drive linking we add compiler flags from `CMAKE__FLAGS` in case they affect the way the compiler invokes the linker, but we don't add flags from other places that are meant only for compiling sources. Rather than calling the `AddLanguageFlags` method (which is used to add flags for compiling sources) directly, add an intermediate method that is used when adding the flags for linking. This will give us a way to add language-specific compiler flags needed when driving the linker in the same place on the command line as other compiler flags go. --- Source/cmLocalGenerator.cxx | 9 ++++++++- Source/cmLocalGenerator.h | 4 ++++ Source/cmMakefileExecutableTargetGenerator.cxx | 8 ++++---- Source/cmMakefileLibraryTargetGenerator.cxx | 8 ++++---- Source/cmNinjaNormalTargetGenerator.cxx | 6 ++++-- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 6c8f132..dd1b86f 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1002,7 +1002,7 @@ void cmLocalGenerator::GetTargetFlags( target->GetName().c_str()); return; } - this->AddLanguageFlags(flags, target, linkLanguage, buildType); + this->AddLanguageFlagsForLinking(flags, target, linkLanguage, buildType); if (pcli) { this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); @@ -1317,6 +1317,13 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } } +void cmLocalGenerator::AddLanguageFlagsForLinking( + std::string& flags, cmGeneratorTarget const* target, const std::string& lang, + const std::string& config) +{ + this->AddLanguageFlags(flags, target, lang, config); +} + cmGeneratorTarget* cmLocalGenerator::FindGeneratorTargetToUse( const std::string& name) const { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 7d591ac..e888094 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -102,6 +102,10 @@ public: void AddLanguageFlags(std::string& flags, cmGeneratorTarget const* target, const std::string& lang, const std::string& config); + void AddLanguageFlagsForLinking(std::string& flags, + cmGeneratorTarget const* target, + const std::string& lang, + const std::string& config); void AddCMP0018Flags(std::string& flags, cmGeneratorTarget const* target, std::string const& lang, const std::string& config); void AddVisibilityPresetFlags(std::string& flags, diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index fb39f01..359b9fd 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -150,8 +150,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( linkLanguage, *this->GeneratorTarget)); // Add language feature flags. - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddLanguageFlagsForLinking( + flags, this->GeneratorTarget, linkLanguage, this->ConfigName); this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, linkLanguage, this->ConfigName); @@ -434,8 +434,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } // Add language feature flags. - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddLanguageFlagsForLinking( + flags, this->GeneratorTarget, linkLanguage, this->ConfigName); this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, linkLanguage, this->ConfigName); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 5ee9f45..2b37b4d 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -397,8 +397,8 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // Add language-specific flags. std::string langFlags; - this->LocalGenerator->AddLanguageFlags(langFlags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddLanguageFlagsForLinking( + langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); vars.LanguageCompileFlags = langFlags.c_str(); @@ -858,8 +858,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Add language-specific flags. std::string langFlags; - this->LocalGenerator->AddLanguageFlags(langFlags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddLanguageFlagsForLinking( + langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); this->LocalGenerator->AddArchitectureFlags( langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 54ae196..0331828 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -655,7 +655,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName); vars["ARCH_FLAGS"] = t; t = ""; - localGen.AddLanguageFlags(t, &genTarget, cudaLinkLanguage, cfgName); + localGen.AddLanguageFlagsForLinking(t, &genTarget, cudaLinkLanguage, + cfgName); vars["LANGUAGE_COMPILE_FLAGS"] = t; } if (this->GetGeneratorTarget()->HasSOName(cfgName)) { @@ -874,7 +875,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["ARCH_FLAGS"] = t; t = ""; t += lwyuFlags; - localGen.AddLanguageFlags(t, &genTarget, TargetLinkLanguage, cfgName); + localGen.AddLanguageFlagsForLinking(t, &genTarget, TargetLinkLanguage, + cfgName); vars["LANGUAGE_COMPILE_FLAGS"] = t; } if (this->GetGeneratorTarget()->HasSOName(cfgName)) { -- cgit v0.12 From e17b1791843b473d0d57ccdbe98689d1be8228e2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 Apr 2017 14:45:11 -0400 Subject: Features: On SunPro link with language standard compiler flag When C++ feature requirements or `CXX_STANDARD` cause us to compile on SunPro with the `-std=c++11` option, link with the option too. This is needed to make the compiler use the matching standard library. --- Modules/Compiler/SunPro-CXX.cmake | 1 + Source/cmLocalGenerator.cxx | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/Modules/Compiler/SunPro-CXX.cmake b/Modules/Compiler/SunPro-CXX.cmake index f4345b8..b4183db 100644 --- a/Modules/Compiler/SunPro-CXX.cmake +++ b/Modules/Compiler/SunPro-CXX.cmake @@ -36,6 +36,7 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13) set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "") set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11") set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=c++11") + set(CMAKE_CXX_LINK_WITH_STANDARD_COMPILE_OPTION 1) endif() if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index dd1b86f..8ce158b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1321,6 +1321,15 @@ void cmLocalGenerator::AddLanguageFlagsForLinking( std::string& flags, cmGeneratorTarget const* target, const std::string& lang, const std::string& config) { + if (this->Makefile->IsOn("CMAKE_" + lang + + "_LINK_WITH_STANDARD_COMPILE_OPTION")) { + // This toolchain requires use of the language standard flag + // when linking in order to use the matching standard library. + // FIXME: If CMake gains an abstraction for standard library + // selection, this will have to be reconciled with it. + this->AddCompilerRequirementFlag(flags, target, lang); + } + this->AddLanguageFlags(flags, target, lang, config); } -- cgit v0.12