Commit 1588a577 authored by Ruslan Baratov's avatar Ruslan Baratov Committed by Brad King

Add policy CMP0069 to enforce INTERPROCEDURAL_OPTIMIZATION

Previously the `INTERPROCEDURAL_OPTIMIZATION` target property was
honored only for the Intel compiler on Linux and otherwise ignored.  In
order to add support for more compilers incrementally without changing
behavior in the future, add a new policy whose NEW behavior enforces the
`INTERPROCEDURAL_OPTIMIZATION` property.  Add flags for supported
compilers and otherwise produce an error.
parent a7575700
......@@ -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
......
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)
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`.
......@@ -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)
......
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)
......
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)
......
......@@ -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()
......
......@@ -286,6 +286,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
, FortranModuleDirectoryCreated(false)
, SourceFileFlagsConstructed(false)
, PolicyWarnedCMP0022(false)
, PolicyReportedCMP0069(false)
, DebugIncludesDone(false)
, DebugCompileOptionsDone(false)
, DebugCompileFeaturesDone(false)
......@@ -659,7 +660,62 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
bool cmGeneratorTarget::IsIPOEnabled(const std::string& config) const
{
const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
return cmSystemTools::IsOn(this->GetFeature(feature, config));
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)
......
......@@ -743,6 +743,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;
......
......@@ -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; }
......
......@@ -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.
......
......@@ -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;
......
......@@ -1664,6 +1664,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());
......
......@@ -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) {
......
......@@ -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
......
......@@ -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();
......
^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\)$
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)
^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\)$
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)
^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\)$
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)
cmake_policy(SET CMP0069 OLD)
add_executable(foo main.cpp)
set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
^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\.$
set(_CMAKE_IPO_LEGACY_BEHAVIOR NO)
add_executable(foo main.cpp)
set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
cmake_minimum_required(VERSION 3.8)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake)
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()
......@@ -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
......
cmake_minimum_required(VERSION 3.0)
project(${RunCMake_TEST} NONE)
cmake_policy(SET CMP0069 NEW)
include(CheckIPOSupported)
include(${RunCMake_TEST}.cmake)
......@@ -7,6 +7,7 @@ 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)
......
^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\)$
project(${RunCMake_TEST} LANGUAGES C CXX)
cmake_policy(SET CMP0069 OLD)
include(CheckIPOSupported)
check_ipo_supported()
......@@ -21,6 +21,7 @@
\* CMP0063
\* CMP0065
\* CMP0068
\* CMP0069
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment