diff options
author | Brad King <brad.king@kitware.com> | 2017-03-31 14:37:56 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2017-03-31 14:38:08 (GMT) |
commit | 8772fc81c4ab745eb5abbae58c6a69706f610429 (patch) | |
tree | cf974aec17ed5a474680b488d1effbf137a7db5e | |
parent | 60dde287e71efbad71b107902991098a6c77556d (diff) | |
parent | dfa8263f4be4f1413b73c81649fdc4567a71e56a (diff) | |
download | CMake-8772fc81c4ab745eb5abbae58c6a69706f610429.zip CMake-8772fc81c4ab745eb5abbae58c6a69706f610429.tar.gz CMake-8772fc81c4ab745eb5abbae58c6a69706f610429.tar.bz2 |
Merge topic 'ipo-policy-CMP0069'
dfa8263f Implement interprocedural optimization for GNU compilers
1588a577 Add policy CMP0069 to enforce INTERPROCEDURAL_OPTIMIZATION
a7575700 Refactoring: s,GetFeatureAsBool,IsIPOEnabled,
e05835c3 CheckIPOSupported: Visual Studio and Xcode generators do not support IPO
Acked-by: Kitware Robot <kwrobot@kitware.com>
Reviewed-by: Brad King <brad.king@kitware.com>
Reviewed-by: Nils Gladitz <nilsgladitz@gmail.com>
Merge-request: !568
51 files changed, 416 insertions, 33 deletions
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 0c9ee2d..7b85817 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.9 .. toctree:: :maxdepth: 1 + CMP0069: INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. </policy/CMP0069> CMP0068: RPATH settings on macOS do not affect install_name. </policy/CMP0068> Policies Introduced by CMake 3.8 diff --git a/Help/policy/CMP0069.rst b/Help/policy/CMP0069.rst new file mode 100644 index 0000000..b8f5d80 --- /dev/null +++ b/Help/policy/CMP0069.rst @@ -0,0 +1,92 @@ +CMP0069 +------- + +:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` is enforced when enabled. + +CMake 3.9 and newer prefer to add IPO flags whenever the +:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property is enabled and +produce an error if flags are not known to CMake for the current compiler. +Since a given compiler may not support IPO flags in all environments in which +it is used, it is now the project's responsibility to use the +:module:`CheckIPOSupported` module to check for support before enabling the +:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property. This approach +allows a project to conditionally activate IPO when supported. It also +allows an end user to set the :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` +variable in an environment known to support IPO even if the project does +not enable the property. + +Since CMake 3.8 and lower only honored :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` +for the Intel compiler on Linux, some projects may unconditionally enable the +target property. Policy ``CMP0069`` provides compatibility with such projects. + +This policy takes effect whenever the IPO property is enabled. The ``OLD`` +behavior for this policy is to add IPO flags only for Intel compiler on Linux. +The ``NEW`` behavior for this policy is to add IPO flags for the current +compiler or produce an error if CMake does not know the flags. + +This policy was introduced in CMake version 3.9. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt + +Examples +^^^^^^^^ + +Behave like CMake 3.8 and do not apply any IPO flags except for Intel compiler +on Linux: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.8) + project(foo) + + # ... + + set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + +Use the :module:`CheckIPOSupported` module to detect whether IPO is +supported by the current compiler, environment, and CMake version. +Produce a fatal error if support is not available: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.9) # CMP0069 NEW + project(foo) + + include(CheckIPOSupport) + check_ipo_support() + + # ... + + set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + +Apply IPO flags only if compiler supports it: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.9) # CMP0069 NEW + project(foo) + + include(CheckIPOSupport) + + # ... + + check_ipo_support(RESULT result) + if(result) + set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + endif() + +Apply IPO flags without any checks. This may lead to build errors if IPO +is not supported by the compiler in the current environment. Produce an +error if CMake does not know IPO flags for the current compiler: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.9) # CMP0069 NEW + project(foo) + + # ... + + set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Help/release/dev/gcc-ipo.rst b/Help/release/dev/gcc-ipo.rst new file mode 100644 index 0000000..ebc5c0d --- /dev/null +++ b/Help/release/dev/gcc-ipo.rst @@ -0,0 +1,7 @@ +GCC IPO +------- + +* Interprocedural optimization (IPO) is now supported for GNU + compilers using link time optimization (LTO) flags. See the + :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property and + :module:`CheckIPOSupported` module. diff --git a/Help/release/dev/interprocedural_optimization_policy.rst b/Help/release/dev/interprocedural_optimization_policy.rst new file mode 100644 index 0000000..93a9d68 --- /dev/null +++ b/Help/release/dev/interprocedural_optimization_policy.rst @@ -0,0 +1,8 @@ +interprocedural_optimization_policy +----------------------------------- + +* The :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property is now enforced + when enabled. CMake will add IPO flags unconditionally or produce an error + if it does not know the flags for the current compiler. The project is now + responsible to use the :module:`CheckIPOSupported` module to check for IPO + support before enabling the target property. See policy :policy:`CMP0069`. diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake index 6f7bc82..31c1bd3 100644 --- a/Modules/CheckIPOSupported.cmake +++ b/Modules/CheckIPOSupported.cmake @@ -28,6 +28,9 @@ property. Specify languages whose compilers to check. Languages ``C`` and ``CXX`` are supported. +It makes no sense to use this module when :policy:`CMP0069` is set to ``OLD`` so +module will return error in this case. See policy :policy:`CMP0069` for details. + Examples ^^^^^^^^ @@ -125,7 +128,17 @@ macro(_ipo_run_language_check language) endmacro() function(check_ipo_supported) - # TODO: IPO policy + cmake_policy(GET CMP0069 x) + + string(COMPARE EQUAL "${x}" "" not_set) + if(not_set) + message(FATAL_ERROR "Policy CMP0069 is not set") + endif() + + string(COMPARE EQUAL "${x}" "OLD" is_old) + if(is_old) + message(FATAL_ERROR "Policy CMP0069 set to OLD") + endif() set(optional) set(one RESULT OUTPUT) @@ -203,7 +216,12 @@ function(check_ipo_supported) endif() if(NOT _CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER) - _ipo_not_supported("compiler doesn't support IPO") + _ipo_not_supported("Compiler doesn't support IPO") + return() + endif() + + if(CMAKE_GENERATOR MATCHES "^(Visual Studio |Xcode$)") + _ipo_not_supported("CMake doesn't support IPO for current generator") return() endif() diff --git a/Modules/CheckIPOSupported/CMakeLists-C.txt.in b/Modules/CheckIPOSupported/CMakeLists-C.txt.in index d20f31f..5a3b8ee 100644 --- a/Modules/CheckIPOSupported/CMakeLists-C.txt.in +++ b/Modules/CheckIPOSupported/CMakeLists-C.txt.in @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION "@CMAKE_VERSION@") project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES C) -# TODO: IPO policy +cmake_policy(SET CMP0069 NEW) add_library(foo foo.c) add_executable(boo main.c) diff --git a/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in b/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in index 4b55c70..30993fa 100644 --- a/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in +++ b/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION "@CMAKE_VERSION@") project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES CXX) -# TODO: IPO policy +cmake_policy(SET CMP0069 NEW) add_library(foo foo.cpp) add_executable(boo main.cpp) diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index 96263fc..6b99a08 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -27,5 +27,13 @@ else() set(CMAKE_${lang}_COMPILE_OPTIONS_TARGET "--target=") set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "--gcc-toolchain=") endif() + + set(_CMAKE_IPO_SUPPORTED_BY_CMAKE NO) + set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + + unset(CMAKE_${lang}_COMPILE_OPTIONS_IPO) + unset(CMAKE_${lang}_ARCHIVE_CREATE_IPO) + unset(CMAKE_${lang}_ARCHIVE_APPEND_IPO) + unset(CMAKE_${lang}_ARCHIVE_FINISH_IPO) endmacro() endif() diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index b67002c..4b1c598 100644 --- a/Modules/Compiler/GNU.cmake +++ b/Modules/Compiler/GNU.cmake @@ -45,4 +45,43 @@ macro(__compiler_gnu lang) if(NOT APPLE OR NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4) # work around #4462 set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") endif() + + set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + + # '-flto' introduced since GCC 4.5: + # * https://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Option-Summary.html (no) + # * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Option-Summary.html (yes) + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.5) + set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + set(__lto_flags -flto) + + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.7) + # '-ffat-lto-objects' introduced since GCC 4.7: + # * https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Option-Summary.html (no) + # * https://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/Option-Summary.html (yes) + list(APPEND __lto_flags -fno-fat-lto-objects) + endif() + + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO ${__lto_flags}) + + # Need to use version of 'ar'/'ranlib' with plugin support. + # Quote from [documentation][1]: + # + # To create static libraries suitable for LTO, + # use gcc-ar and gcc-ranlib instead of ar and ranlib + # + # [1]: https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Optimize-Options.html + set(CMAKE_${lang}_ARCHIVE_CREATE_IPO + "${CMAKE_GCC_AR} cr <TARGET> <LINK_FLAGS> <OBJECTS>" + ) + + set(CMAKE_${lang}_ARCHIVE_APPEND_IPO + "${CMAKE_GCC_AR} r <TARGET> <LINK_FLAGS> <OBJECTS>" + ) + + set(CMAKE_${lang}_ARCHIVE_FINISH_IPO + "${CMAKE_GCC_RANLIB} <TARGET>" + ) + endif() endmacro() diff --git a/Modules/Compiler/QCC.cmake b/Modules/Compiler/QCC.cmake index 2d7e881..695a138 100644 --- a/Modules/Compiler/QCC.cmake +++ b/Modules/Compiler/QCC.cmake @@ -12,4 +12,12 @@ macro(__compiler_qcc lang) set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-Wp,-isystem,") set(CMAKE_DEPFILE_FLAGS_${lang} "-Wc,-MD,<DEPFILE>,-MT,<OBJECT>,-MF,<DEPFILE>") + + set(_CMAKE_IPO_SUPPORTED_BY_CMAKE NO) + set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + + unset(CMAKE_${lang}_COMPILE_OPTIONS_IPO) + unset(CMAKE_${lang}_ARCHIVE_CREATE_IPO) + unset(CMAKE_${lang}_ARCHIVE_APPEND_IPO) + unset(CMAKE_${lang}_ARCHIVE_FINISH_IPO) endmacro() diff --git a/Modules/Platform/Linux-Intel.cmake b/Modules/Platform/Linux-Intel.cmake index 45dc36f..6e2978a 100644 --- a/Modules/Platform/Linux-Intel.cmake +++ b/Modules/Platform/Linux-Intel.cmake @@ -39,6 +39,7 @@ macro(__linux_compiler_intel lang) "${XIAR} cr <TARGET> <LINK_FLAGS> <OBJECTS> " "${XIAR} -s <TARGET> ") set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + set(_CMAKE_IPO_LEGACY_BEHAVIOR YES) else() set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) endif() diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index fd1ad36..fe2c0fe 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -43,18 +43,13 @@ const char* cmCommonTargetGenerator::GetFeature(const std::string& feature) return this->GeneratorTarget->GetFeature(feature, this->ConfigName); } -bool cmCommonTargetGenerator::GetFeatureAsBool(const std::string& feature) -{ - return this->GeneratorTarget->GetFeatureAsBool(feature, this->ConfigName); -} - void cmCommonTargetGenerator::AddFeatureFlags(std::string& flags, const std::string& lang) { // Add language-specific flags. this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName); - if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION")) { + if (this->GeneratorTarget->IsIPOEnabled(this->ConfigName)) { this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO"); } } diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 8d68123..425ff91 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -32,7 +32,6 @@ protected: // Feature query methods. const char* GetFeature(const std::string& feature); - bool GetFeatureAsBool(const std::string& feature); // Helper to add flag for windows .def file. void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f78a933..73d2009 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -286,6 +286,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) , FortranModuleDirectoryCreated(false) , SourceFileFlagsConstructed(false) , PolicyWarnedCMP0022(false) + , PolicyReportedCMP0069(false) , DebugIncludesDone(false) , DebugCompileOptionsDone(false) , DebugCompileFeaturesDone(false) @@ -656,10 +657,65 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature, return this->LocalGenerator->GetFeature(feature, config); } -bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature, - const std::string& config) const +bool cmGeneratorTarget::IsIPOEnabled(const std::string& config) const { - return cmSystemTools::IsOn(this->GetFeature(feature, config)); + const char* feature = "INTERPROCEDURAL_OPTIMIZATION"; + const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config)); + + if (!result) { + // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies + return false; + } + + cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069(); + + if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) { + if (this->Makefile->IsOn("_CMAKE_IPO_LEGACY_BEHAVIOR")) { + return true; + } + if (this->PolicyReportedCMP0069) { + // problem is already reported, no need to issue a message + return false; + } + if (cmp0069 == cmPolicies::WARN) { + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0069) << "\n"; + w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target " + << "'" << this->GetName() << "'."; + this->LocalGenerator->GetCMakeInstance()->IssueMessage( + cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace()); + + this->PolicyReportedCMP0069 = true; + } + return false; + } + + // Note: check consistency with messages from CheckIPOSupported + const char* message = CM_NULLPTR; + if (!this->Makefile->IsOn("_CMAKE_IPO_SUPPORTED_BY_CMAKE")) { + message = "CMake doesn't support IPO for current compiler"; + } else if (!this->Makefile->IsOn( + "_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) { + message = "Compiler doesn't support IPO"; + } else if (!this->GlobalGenerator->IsIPOSupported()) { + message = "CMake doesn't support IPO for current generator"; + } + + if (!message) { + // No error/warning messages + return true; + } + + if (this->PolicyReportedCMP0069) { + // problem is already reported, no need to issue a message + return false; + } + + this->PolicyReportedCMP0069 = true; + + this->LocalGenerator->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, message, this->GetBacktrace()); + return false; } const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) @@ -2410,19 +2466,28 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config, } } +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetFeatureSpecificLinkRuleVariable( + std::string const& var, std::string const& config) const +{ + if (this->IsIPOEnabled(config)) { + std::string varIPO = var + "_IPO"; + if (this->Makefile->IsDefinitionSet(varIPO)) { + return varIPO; + } + } + + return var; +} + +//---------------------------------------------------------------------------- std::string cmGeneratorTarget::GetCreateRuleVariable( std::string const& lang, std::string const& config) const { switch (this->GetType()) { case cmStateEnums::STATIC_LIBRARY: { std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY"; - if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION", config)) { - std::string varIPO = var + "_IPO"; - if (this->Makefile->GetDefinition(varIPO)) { - return varIPO; - } - } - return var; + return this->GetFeatureSpecificLinkRuleVariable(var, config); } case cmStateEnums::SHARED_LIBRARY: return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY"; diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index d60ad24..fcab4aa 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -112,8 +112,8 @@ public: const char* GetFeature(const std::string& feature, const std::string& config) const; - bool GetFeatureAsBool(const std::string& feature, - const std::string& config) const; + + bool IsIPOEnabled(const std::string& config) const; bool IsLinkInterfaceDependentBoolProperty(const std::string& p, const std::string& config) const; @@ -309,6 +309,9 @@ public: void GetAppleArchs(const std::string& config, std::vector<std::string>& archVec) const; + std::string GetFeatureSpecificLinkRuleVariable( + std::string const& var, std::string const& config) const; + /** Return the rule variable used to create this type of target. */ std::string GetCreateRuleVariable(std::string const& lang, std::string const& config) const; @@ -745,6 +748,7 @@ private: mutable std::set<cmLinkItem> UtilityItems; cmPolicies::PolicyMap PolicyMap; mutable bool PolicyWarnedCMP0022; + mutable bool PolicyReportedCMP0069; mutable bool DebugIncludesDone; mutable bool DebugCompileOptionsDone; mutable bool DebugCompileFeaturesDone; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 2558fee..b228d41 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -333,6 +333,8 @@ public: virtual bool UseFolderProperty() const; + virtual bool IsIPOSupported() const { return false; } + /** Return whether the generator should use EFFECTIVE_PLATFORM_NAME. This is relevant for mixed macOS and iOS builds. */ virtual bool UseEffectivePlatformName(cmMakefile*) const { return false; } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index a51e919..956af51 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -99,6 +99,8 @@ public: */ static bool SupportsPlatform() { return false; } + bool IsIPOSupported() const CM_OVERRIDE { return true; } + /** * Write a build statement to @a os with the @a comment using * the @a rule the list of @a outputs files and inputs. diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 67d7bc9..bbf9f0f 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -149,6 +149,8 @@ public: /** Does the make tool tolerate .DELETE_ON_ERROR? */ virtual bool AllowDeleteOnError() const { return true; } + bool IsIPOSupported() const CM_OVERRIDE { return true; } + void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE; std::string IncludeDirective; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 42dd997..416af14 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1707,6 +1707,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, return; } + // Check IPO related warning/error. + gtgt->IsIPOEnabled(configName); + // Add define flags this->CurrentLocalGenerator->AppendFlags( defFlags, this->CurrentMakefile->GetDefineFlags()); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 82bf0b9..9333ed7 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1052,7 +1052,7 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target, // Add language-specific flags. this->AddLanguageFlags(flags, lang, config); - if (target->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION", config)) { + if (target->IsIPOEnabled(config)) { this->AppendFeatureOptions(flags, lang, "IPO"); } diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 3117ef3..260a84b 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -670,6 +670,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( // Add the target-specific flags. this->AddCompileOptions(flags, target, linkLanguage, configName); + + // Check IPO related warning/error. + target->IsIPOEnabled(configName); } if (this->FortranProject) { diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index e5fae13..cc8a6b3 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -129,14 +129,9 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - std::string linkRuleVar = "CMAKE_"; - linkRuleVar += linkLanguage; - linkRuleVar += "_CREATE_STATIC_LIBRARY"; - if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION") && - this->Makefile->GetDefinition(linkRuleVar + "_IPO")) { - linkRuleVar += "_IPO"; - } + std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( + linkLanguage, this->ConfigName); std::string extraFlags; this->LocalGenerator->GetStaticLibraryFlags( @@ -676,18 +671,30 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string arCreateVar = "CMAKE_"; arCreateVar += linkLanguage; arCreateVar += "_ARCHIVE_CREATE"; + + arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + arCreateVar, this->ConfigName); + if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) { cmSystemTools::ExpandListArgument(rule, archiveCreateCommands); } std::string arAppendVar = "CMAKE_"; arAppendVar += linkLanguage; arAppendVar += "_ARCHIVE_APPEND"; + + arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + arAppendVar, this->ConfigName); + if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) { cmSystemTools::ExpandListArgument(rule, archiveAppendCommands); } std::string arFinishVar = "CMAKE_"; arFinishVar += linkLanguage; arFinishVar += "_ARCHIVE_FINISH"; + + arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + arFinishVar, this->ConfigName); + if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) { cmSystemTools::ExpandListArgument(rule, archiveFinishCommands); } diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 560eb4f..aaeb659 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -516,6 +516,10 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() std::string linkCmdVar = "CMAKE_"; linkCmdVar += this->TargetLinkLanguage; linkCmdVar += "_ARCHIVE_CREATE"; + + linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + linkCmdVar, this->GetConfigName()); + const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmSystemTools::ExpandListArgument(linkCmd, linkCmds); } @@ -523,6 +527,10 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() std::string linkCmdVar = "CMAKE_"; linkCmdVar += this->TargetLinkLanguage; linkCmdVar += "_ARCHIVE_FINISH"; + + linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + linkCmdVar, this->GetConfigName()); + const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmSystemTools::ExpandListArgument(linkCmd, linkCmds); } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index ecf06b3..72dcc4f 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -203,6 +203,9 @@ class cmMakefile; 3, 8, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0068, \ "RPATH settings on macOS do not affect install_name.", 3, 9, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0069, \ + "INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.", 3, 9, 0, \ cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) @@ -225,7 +228,8 @@ class cmMakefile; F(CMP0060) \ F(CMP0063) \ F(CMP0065) \ - F(CMP0068) + F(CMP0068) \ + F(CMP0069) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 9c9296e..a9ccc68 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2239,6 +2239,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( linkLanguage, configName.c_str()); } + // Check IPO related warning/error. + this->GeneratorTarget->IsIPOEnabled(configName); + // Get preprocessor definitions for this directory. std::string defineFlags = this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags(); diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt new file mode 100644 index 0000000..ddb3cae --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at CMP0069-NEW-cmake\.cmake:[0-9]+ \(add_executable\): + CMake doesn't support IPO for current compiler +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake new file mode 100644 index 0000000..23fae13 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake @@ -0,0 +1,6 @@ +cmake_policy(SET CMP0069 NEW) + +set(_CMAKE_IPO_SUPPORTED_BY_CMAKE NO) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt new file mode 100644 index 0000000..8decfab --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at CMP0069-NEW-compiler\.cmake:[0-9]+ \(add_executable\): + Compiler doesn't support IPO +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake new file mode 100644 index 0000000..24b409a --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake @@ -0,0 +1,7 @@ +cmake_policy(SET CMP0069 NEW) + +set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES) +set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt new file mode 100644 index 0000000..0e05ee7 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at CMP0069-NEW-generator\.cmake:[0-9]+ \(add_executable\): + CMake doesn't support IPO for current generator +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake new file mode 100644 index 0000000..df2a888 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake @@ -0,0 +1,7 @@ +cmake_policy(SET CMP0069 NEW) + +set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES) +set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake b/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake new file mode 100644 index 0000000..cfe1e9d --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake @@ -0,0 +1,4 @@ +cmake_policy(SET CMP0069 OLD) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt new file mode 100644 index 0000000..314e180 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt @@ -0,0 +1,9 @@ +^CMake Warning \(dev\) at CMP0069-WARN\.cmake:[0-9]+ \(add_executable\): + Policy CMP0069 is not set: INTERPROCEDURAL_OPTIMIZATION is enforced when + enabled. Run "cmake --help-policy CMP0069" for policy details\. Use the + cmake_policy command to set the policy and suppress this warning\. + + INTERPROCEDURAL_OPTIMIZATION property will be ignored for target 'foo'\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake b/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake new file mode 100644 index 0000000..0e3e670 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake @@ -0,0 +1,4 @@ +set(_CMAKE_IPO_LEGACY_BEHAVIOR NO) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/CMP0069/CMakeLists.txt b/Tests/RunCMake/CMP0069/CMakeLists.txt new file mode 100644 index 0000000..375cbdb --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.8) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0069/RunCMakeTest.cmake b/Tests/RunCMake/CMP0069/RunCMakeTest.cmake new file mode 100644 index 0000000..61ba458 --- /dev/null +++ b/Tests/RunCMake/CMP0069/RunCMakeTest.cmake @@ -0,0 +1,11 @@ +include(RunCMake) + +run_cmake(CMP0069-OLD) +run_cmake(CMP0069-NEW-cmake) +run_cmake(CMP0069-NEW-compiler) +run_cmake(CMP0069-WARN) + +string(COMPARE EQUAL "${RunCMake_GENERATOR}" "Xcode" is_xcode) +if(is_xcode OR RunCMake_GENERATOR MATCHES "^Visual Studio ") + run_cmake(CMP0069-NEW-generator) +endif() diff --git a/Tests/RunCMake/CMP0069/main.cpp b/Tests/RunCMake/CMP0069/main.cpp new file mode 100644 index 0000000..5047a34 --- /dev/null +++ b/Tests/RunCMake/CMP0069/main.cpp @@ -0,0 +1,3 @@ +int main() +{ +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index e2dc128..73a4965 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -107,6 +107,7 @@ add_RunCMake_test(CMP0064) if(CMAKE_SYSTEM_NAME MATCHES Darwin AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG) add_RunCMake_test(CMP0068) endif() +add_RunCMake_test(CMP0069) # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode diff --git a/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt b/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt index a0effc9..4a13d29 100644 --- a/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt +++ b/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.0) project(${RunCMake_TEST} NONE) + +cmake_policy(SET CMP0069 NEW) + include(CheckIPOSupported) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake index e304c61..812f79b 100644 --- a/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake @@ -7,3 +7,8 @@ run_cmake(default-lang-none) run_cmake(not-supported-by-cmake) run_cmake(not-supported-by-compiler) run_cmake(save-to-result) +run_cmake(cmp0069-is-old) + +if(RunCMake_GENERATOR MATCHES "^(Visual Studio |Xcode$)") + run_cmake(not-supported-by-generator) +endif() diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-result.txt b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt new file mode 100644 index 0000000..f183594 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + Policy CMP0069 set to OLD +Call Stack \(most recent call first\): + cmp0069-is-old\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake new file mode 100644 index 0000000..14fed04 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake @@ -0,0 +1,6 @@ +project(${RunCMake_TEST} LANGUAGES C CXX) + +cmake_policy(SET CMP0069 OLD) + +include(CheckIPOSupported) +check_ipo_supported() diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt index 73e2f26..5f5f410 100644 --- a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt @@ -1,5 +1,5 @@ ^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): - IPO is not supported \(compiler doesn't support IPO\)\. + IPO is not supported \(Compiler doesn't support IPO\)\. Call Stack \(most recent call first\): .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\) not-supported-by-compiler\.cmake:[0-9]+ \(check_ipo_supported\) diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt new file mode 100644 index 0000000..a2aa58c --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + IPO is not supported \(CMake doesn't support IPO for current generator\)\. +Call Stack \(most recent call first\): + .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\) + not-supported-by-generator\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake new file mode 100644 index 0000000..dc0fa09 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake @@ -0,0 +1,6 @@ +project(${RunCMake_TEST} LANGUAGES C) + +set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES) +set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + +check_ipo_supported() diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 78657ef..5f6be87 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -21,6 +21,7 @@ \* CMP0063 \* CMP0065 \* CMP0068 + \* CMP0069 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) |