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/CMP0053
|
||||||
/policy/CMP0054
|
/policy/CMP0054
|
||||||
/policy/CMP0055
|
/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`.
|
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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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(BadSources2)
|
||||||
run_cmake(NonSourceCopyFile)
|
run_cmake(NonSourceCopyFile)
|
||||||
run_cmake(NonSourceCompileDefinitions)
|
run_cmake(NonSourceCompileDefinitions)
|
||||||
|
|
||||||
|
run_cmake(CMP0056)
|
||||||
|
|
Loading…
Reference in New Issue