diff --git a/Modules/Compiler/SunPro-CXX.cmake b/Modules/Compiler/SunPro-CXX.cmake index f4345b8ec9..b4183db51e 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/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a0f677b8ec..3f50e32ff2 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 13b6b73e80..134b7c7b11 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 50ad1a881d..f3eb249401 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 33e32d17eb..8ce158b778 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(); @@ -985,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); @@ -1300,6 +1317,22 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } } +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); +} + cmGeneratorTarget* cmLocalGenerator::FindGeneratorTargetToUse( const std::string& name) const { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 1a238a83a7..e88809423e 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 @@ -100,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 fb39f016d8..359b9fdbbf 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 5ee9f45374..2b37b4dcaa 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 54ae19652d..03318284fa 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)) {