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:
parent
a4f9b6f0ca
commit
88eb5824da
|
@ -113,3 +113,4 @@ All Policies
|
|||
/policy/CMP0053
|
||||
/policy/CMP0054
|
||||
/policy/CMP0055
|
||||
/policy/CMP0056
|
||||
|
|
|
@ -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.
|
|
@ -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`.
|
|
@ -9,6 +9,8 @@ warn by default:
|
|||
policy :policy:`CMP0025`.
|
||||
* ``CMAKE_POLICY_WARNING_CMP0047`` controls the warning for
|
||||
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
|
||||
developers running CMake may set this variable in their cache to
|
||||
|
|
|
@ -331,6 +331,40 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
|
|||
fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
|
||||
" ${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}"
|
||||
" ${EXE_LINKER_FLAGS}\")\n");
|
||||
fprintf(fout, "include_directories(${INCLUDE_DIRECTORIES})\n");
|
||||
|
|
|
@ -369,6 +369,11 @@ cmPolicies::cmPolicies()
|
|||
CMP0055, "CMP0055",
|
||||
"Strict checking for break() command.",
|
||||
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()
|
||||
|
|
|
@ -112,6 +112,7 @@ public:
|
|||
CMP0054, ///< Only interpret if() arguments as variables
|
||||
/// or keywords when unquoted.
|
||||
CMP0055, ///< Strict checking for break() command.
|
||||
CMP0056, ///< Honor link flags in try_compile() source-file signature.
|
||||
|
||||
/** \brief Always the last entry.
|
||||
*
|
||||
|
|
|
@ -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.$
|
|
@ -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
|
|
@ -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()
|
|
@ -15,3 +15,5 @@ run_cmake(BadSources1)
|
|||
run_cmake(BadSources2)
|
||||
run_cmake(NonSourceCopyFile)
|
||||
run_cmake(NonSourceCompileDefinitions)
|
||||
|
||||
run_cmake(CMP0056)
|
||||
|
|
Loading…
Reference in New Issue