try_compile: Pass linker flags into test project (#14066)

Copy CMAKE_EXE_LINKER_FLAGS into the test project generated by
try_compile, just like we already copy CMAKE_<LANG>_FLAGS.

Add CMake Policy CMP0056 to activate this behavior in a compatible way,
but do not warn by default when the policy is not set since it will
affect all try_compile calls.

Extend the RunCMake.try_compile test with a case covering this behavior
for each policy setting.
This commit is contained in:
Brad King 2014-12-03 11:02:31 -05:00
parent a4f9b6f0ca
commit 88eb5824da
11 changed files with 167 additions and 0 deletions

View File

@ -113,3 +113,4 @@ All Policies
/policy/CMP0053 /policy/CMP0053
/policy/CMP0054 /policy/CMP0054
/policy/CMP0055 /policy/CMP0055
/policy/CMP0056

32
Help/policy/CMP0056.rst Normal file
View File

@ -0,0 +1,32 @@
CMP0056
-------
Honor link flags in :command:`try_compile` source-file signature.
The :command:`try_compile` command source-file signature generates a
``CMakeLists.txt`` file to build the source file into an executable.
In order to compile the source the same way as it might be compiled
by the calling project, the generated project sets the value of the
:variable:`CMAKE_<LANG>_FLAGS` variable to that in the calling project.
The value of the :variable:`CMAKE_EXE_LINKER_FLAGS` variable may be
needed in some cases too, but CMake 3.1 and lower did not set it in
the generated project. CMake 3.2 and above prefer to set it so that
linker flags are honored as well as compiler flags. This policy
provides compatibility with the pre-3.2 behavior.
The OLD behavior for this policy is to not set the value of the
:variable:`CMAKE_EXE_LINKER_FLAGS` variable in the generated test
project. The NEW behavior for this policy is to set the value of
the :variable:`CMAKE_EXE_LINKER_FLAGS` variable in the test project
to the same as it is in the calling project.
If the project code does not set the policy explicitly, users may
set it on the command line by defining the
:variable:`CMAKE_POLICY_DEFAULT_CMP0056 <CMAKE_POLICY_DEFAULT_CMP<NNNN>>`
variable in the cache.
This policy was introduced in CMake version 3.2. Unlike most policies,
CMake version |release| does *not* warn by default when this policy
is not set and simply uses OLD behavior. See documentation of the
:variable:`CMAKE_POLICY_WARNING_CMP0056 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
variable to control the warning.

View File

@ -0,0 +1,6 @@
try_compile-link-flags
----------------------
* The :command:`try_compile` command source file signature now honors
link flags (e.g. :variable:`CMAKE_EXE_LINKER_FLAGS`) in the generated
test project. See policy :policy:`CMP0056`.

View File

@ -9,6 +9,8 @@ warn by default:
policy :policy:`CMP0025`. policy :policy:`CMP0025`.
* ``CMAKE_POLICY_WARNING_CMP0047`` controls the warning for * ``CMAKE_POLICY_WARNING_CMP0047`` controls the warning for
policy :policy:`CMP0047`. policy :policy:`CMP0047`.
* ``CMAKE_POLICY_WARNING_CMP0056`` controls the warning for
policy :policy:`CMP0056`.
This variable should not be set by a project in CMake code. Project This variable should not be set by a project in CMake code. Project
developers running CMake may set this variable in their cache to developers running CMake may set this variable in their cache to

View File

@ -331,6 +331,40 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}" fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
" ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str()); " ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str());
} }
switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0056))
{
case cmPolicies::WARN:
if(this->Makefile->PolicyOptionalWarningEnabled(
"CMAKE_POLICY_WARNING_CMP0056"))
{
cmOStringStream w;
w << (this->Makefile->GetCMakeInstance()->GetPolicies()
->GetPolicyWarning(cmPolicies::CMP0056)) << "\n"
"For compatibility with older versions of CMake, try_compile "
"is not honoring caller link flags (e.g. CMAKE_EXE_LINKER_FLAGS) "
"in the test project."
;
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
}
case cmPolicies::OLD:
// OLD behavior is to do nothing.
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
this->Makefile->GetCMakeInstance()->GetPolicies()
->GetRequiredPolicyError(cmPolicies::CMP0056)
);
case cmPolicies::NEW:
// NEW behavior is to pass linker flags.
{
const char* exeLinkFlags =
this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n",
lg->EscapeForCMake(exeLinkFlags?exeLinkFlags:"").c_str());
} break;
}
fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}" fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}"
" ${EXE_LINKER_FLAGS}\")\n"); " ${EXE_LINKER_FLAGS}\")\n");
fprintf(fout, "include_directories(${INCLUDE_DIRECTORIES})\n"); fprintf(fout, "include_directories(${INCLUDE_DIRECTORIES})\n");

View File

@ -369,6 +369,11 @@ cmPolicies::cmPolicies()
CMP0055, "CMP0055", CMP0055, "CMP0055",
"Strict checking for break() command.", "Strict checking for break() command.",
3,2,0, cmPolicies::WARN); 3,2,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0056, "CMP0056",
"Honor link flags in try_compile() source-file signature.",
3,2,0, cmPolicies::WARN);
} }
cmPolicies::~cmPolicies() cmPolicies::~cmPolicies()

View File

@ -112,6 +112,7 @@ public:
CMP0054, ///< Only interpret if() arguments as variables CMP0054, ///< Only interpret if() arguments as variables
/// or keywords when unquoted. /// or keywords when unquoted.
CMP0055, ///< Strict checking for break() command. CMP0055, ///< Strict checking for break() command.
CMP0056, ///< Honor link flags in try_compile() source-file signature.
/** \brief Always the last entry. /** \brief Always the last entry.
* *

View File

@ -0,0 +1,13 @@
before try_compile with CMP0056 WARN-default
after try_compile with CMP0056 WARN-default
*
CMake Warning \(dev\) at CMP0056.cmake:[0-9]+ \(try_compile\):
Policy CMP0056 is not set: Honor link flags in try_compile\(\) source-file
signature. Run "cmake --help-policy CMP0056" for policy details. Use the
cmake_policy command to set the policy and suppress this warning.
For compatibility with older versions of CMake, try_compile is not honoring
caller link flags \(e.g. CMAKE_EXE_LINKER_FLAGS\) in the test project.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.$

View File

@ -0,0 +1,4 @@
-- try_compile with CMP0056 WARN-default worked as expected
-- try_compile with CMP0056 WARN-enabled worked as expected
-- try_compile with CMP0056 OLD worked as expected
-- try_compile with CMP0056 NEW worked as expected

View File

@ -0,0 +1,67 @@
enable_language(C)
set(obj "${CMAKE_C_OUTPUT_EXTENSION}")
if(BORLAND)
set(pre -)
endif()
set(CMAKE_EXE_LINKER_FLAGS ${pre}BADFLAG${obj})
#-----------------------------------------------------------------------------
message("before try_compile with CMP0056 WARN-default")
try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src.c
OUTPUT_VARIABLE out
)
string(REPLACE "\n" "\n " out " ${out}")
if(NOT RESULT)
message(FATAL_ERROR "try_compile failed but should have passed:\n${out}")
elseif("x${out}" MATCHES "BADFLAG")
message(FATAL_ERROR "try_compile output mentions BADFLAG:\n${out}")
else()
message(STATUS "try_compile with CMP0056 WARN-default worked as expected")
endif()
message("after try_compile with CMP0056 WARN-default")
#-----------------------------------------------------------------------------
set(CMAKE_POLICY_WARNING_CMP0056 ON)
try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src.c
OUTPUT_VARIABLE out
)
string(REPLACE "\n" "\n " out " ${out}")
if(NOT RESULT)
message(FATAL_ERROR "try_compile failed but should have passed:\n${out}")
elseif("x${out}" MATCHES "BADFLAG")
message(FATAL_ERROR "try_compile output mentions BADFLAG:\n${out}")
else()
message(STATUS "try_compile with CMP0056 WARN-enabled worked as expected")
endif()
#-----------------------------------------------------------------------------
cmake_policy(SET CMP0056 OLD)
try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src.c
OUTPUT_VARIABLE out
)
string(REPLACE "\n" "\n " out " ${out}")
if(NOT RESULT)
message(FATAL_ERROR "try_compile failed but should have passed:\n${out}")
elseif("x${out}" MATCHES "BADFLAG")
message(FATAL_ERROR "try_compile output mentions BADFLAG:\n${out}")
else()
message(STATUS "try_compile with CMP0056 OLD worked as expected")
endif()
#-----------------------------------------------------------------------------
cmake_policy(SET CMP0056 NEW)
try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src.c
OUTPUT_VARIABLE out
)
string(REPLACE "\n" "\n " out " ${out}")
if(RESULT)
message(FATAL_ERROR "try_compile passed but should have failed:\n${out}")
elseif(NOT "x${out}" MATCHES "BADFLAG")
message(FATAL_ERROR "try_compile did not fail with BADFLAG:\n${out}")
else()
message(STATUS "try_compile with CMP0056 NEW worked as expected")
endif()

View File

@ -15,3 +15,5 @@ run_cmake(BadSources1)
run_cmake(BadSources2) run_cmake(BadSources2)
run_cmake(NonSourceCopyFile) run_cmake(NonSourceCopyFile)
run_cmake(NonSourceCompileDefinitions) run_cmake(NonSourceCompileDefinitions)
run_cmake(CMP0056)