Commit 29f9db5c authored by Marc Chevrier's avatar Marc Chevrier

try_compile/try_run: Add support for LINK_OPTIONS option.

parent 78c2edb1
......@@ -33,6 +33,7 @@ Try Compiling Source Files
try_compile(RESULT_VAR <bindir> <srcfile|SOURCES srcfile...>
[CMAKE_FLAGS <flags>...]
[COMPILE_DEFINITIONS <defs>...]
[LINK_OPTIONS <options>...]
[LINK_LIBRARIES <libs>...]
[OUTPUT_VARIABLE <var>]
[COPY_FILE <fileName> [COPY_FILE_ERROR <var>]]
......@@ -55,6 +56,7 @@ the source(s) as an executable that looks something like this:
include_directories(${INCLUDE_DIRECTORIES})
link_directories(${LINK_DIRECTORIES})
add_executable(cmTryCompileExec <srcfile>...)
target_link_options(cmTryCompileExec PRIVATE <LINK_OPTIONS from caller>)
target_link_libraries(cmTryCompileExec ${LINK_LIBRARIES})
The options are:
......@@ -67,7 +69,7 @@ The options are:
are used.
``COMPILE_DEFINITIONS <defs>...``
Specify ``-Ddefinition`` arguments to pass to ``add_definitions``
Specify ``-Ddefinition`` arguments to pass to :command:`add_definitions`
in the generated test project.
``COPY_FILE <fileName>``
......@@ -85,6 +87,11 @@ The options are:
If this option is specified, any ``-DLINK_LIBRARIES=...`` value
given to the ``CMAKE_FLAGS`` option will be ignored.
``LINK_OPTIONS <options>...``
Specify link step options to pass to :command:`target_link_options` or
to :prop_tgt:`STATIC_LIBRARY_OPTIONS` target property in the generated
project, depending of the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable.
``OUTPUT_VARIABLE <var>``
Store the output from the build process the given variable.
......
......@@ -15,6 +15,7 @@ Try Compiling and Running Source Files
try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR
bindir srcfile [CMAKE_FLAGS <flags>...]
[COMPILE_DEFINITIONS <defs>...]
[LINK_OPTIONS <options>...]
[LINK_LIBRARIES <libs>...]
[COMPILE_OUTPUT_VARIABLE <var>]
[RUN_OUTPUT_VARIABLE <var>]
......@@ -38,7 +39,7 @@ The options are:
are used.
``COMPILE_DEFINITIONS <defs>...``
Specify ``-Ddefinition`` arguments to pass to ``add_definitions``
Specify ``-Ddefinition`` arguments to pass to :command:`add_definitions`
in the generated test project.
``COMPILE_OUTPUT_VARIABLE <var>``
......@@ -52,6 +53,10 @@ The options are:
If this option is specified, any ``-DLINK_LIBRARIES=...`` value
given to the ``CMAKE_FLAGS`` option will be ignored.
``LINK_OPTIONS <options>...``
Specify link step options to pass to :command:`target_link_options` in the
generated project.
``OUTPUT_VARIABLE <var>``
Report the compile build output and the output from running the executable
in the given variable. This option exists for legacy reasons. Prefer
......
try_compile-LINK_OPTIONS
------------------------
* The commands :command:`try_compile` and :command:`try_run` gain new
option ``LINK_OPTIONS``.
......@@ -121,6 +121,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::string cxxExtensions;
std::string cudaExtensions;
std::vector<std::string> targets;
std::vector<std::string> linkOptions;
std::string libsToLink = " ";
bool useOldLinkLibs = true;
char targetNameBuf[64];
......@@ -144,6 +145,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
DoingNone,
DoingCMakeFlags,
DoingCompileDefinitions,
DoingLinkOptions,
DoingLinkLibraries,
DoingOutputVariable,
DoingCopyFile,
......@@ -165,6 +167,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
doing = DoingCMakeFlags;
} else if (argv[i] == "COMPILE_DEFINITIONS") {
doing = DoingCompileDefinitions;
} else if (argv[i] == "LINK_OPTIONS") {
doing = DoingLinkOptions;
} else if (argv[i] == "LINK_LIBRARIES") {
doing = DoingLinkLibraries;
useOldLinkLibs = false;
......@@ -208,6 +212,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cmakeFlags.push_back(argv[i]);
} else if (doing == DoingCompileDefinitions) {
compileDefs.push_back(argv[i]);
} else if (doing == DoingLinkOptions) {
linkOptions.push_back(argv[i]);
} else if (doing == DoingLinkLibraries) {
libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) {
......@@ -814,6 +820,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
if (!linkOptions.empty()) {
std::vector<std::string> options;
options.reserve(linkOptions.size());
for (const auto& option : linkOptions) {
options.emplace_back(cmOutputConverter::EscapeForCMake(option));
}
if (targetType == cmStateEnums::STATIC_LIBRARY) {
fprintf(fout,
"set_property(TARGET %s PROPERTY STATIC_LIBRARY_OPTIONS %s)\n",
targetName.c_str(), cmJoin(options, " ").c_str());
} else {
fprintf(fout, "target_link_options(%s PRIVATE %s)\n",
targetName.c_str(), cmJoin(options, " ").c_str());
}
}
if (useOldLinkLibs) {
fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
targetName.c_str());
......
......@@ -45,7 +45,8 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
if (argv[i] == "ARGS") {
++i;
while (i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" &&
argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_LIBRARIES") {
argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_OPTIONS" &&
argv[i] != "LINK_LIBRARIES") {
runArgs += " ";
runArgs += argv[i];
++i;
......
......@@ -275,6 +275,7 @@ function(add_RunCMake_test_try_compile)
endif()
endif()
foreach(var
CMAKE_SYSTEM_NAME
CMAKE_C_COMPILER_ID
CMAKE_C_COMPILER_VERSION
CMAKE_C_STANDARD_DEFAULT
......@@ -291,7 +292,8 @@ function(add_RunCMake_test_try_compile)
endfunction()
add_RunCMake_test_try_compile()
add_RunCMake_test(try_run)
add_RunCMake_test(try_run -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
add_RunCMake_test(set)
add_RunCMake_test(variable_watch)
add_RunCMake_test(while)
......
enable_language(C)
cmake_policy(SET CMP0054 NEW)
set (lib_name "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}lib${CMAKE_STATIC_LIBRARY_SUFFIX}")
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if (RunCMake_C_COMPILER_ID STREQUAL "MSVC")
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set (undef_flag /INCLUDE:_func)
else()
set (undef_flag /INCLUDE:func)
endif()
else()
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set (undef_flag -u _func)
else()
set (undef_flag -u func)
endif()
endif()
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set (undef_flag -u _func)
else()
set (undef_flag -u func)
endif()
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
try_compile(result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lib.c
COPY_FILE "${lib_name}")
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
try_compile(result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/main.c
OUTPUT_VARIABLE out
LINK_OPTIONS ${undef_flag} "${lib_name}")
if(NOT result)
message(FATAL_ERROR "try_compile(... LINK_OPTIONS ...) failed:\n${out}")
endif()
......@@ -25,6 +25,13 @@ run_cmake(TargetTypeExe)
run_cmake(TargetTypeInvalid)
run_cmake(TargetTypeStatic)
if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
CMAKE_C_COMPILER_ID MATCHES "^(MSVC|GNU|Clang|AppleClang)$")
set (RunCMake_TEST_OPTIONS -DRunCMake_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
run_cmake(LinkOptions)
unset (RunCMake_TEST_OPTIONS)
endif()
if(CMAKE_C_STANDARD_DEFAULT)
run_cmake(CStandard)
elseif(DEFINED CMAKE_C_STANDARD_DEFAULT)
......
extern void func();
int main(void)
{
func();
return 0;
}
enable_language(C)
cmake_policy(SET CMP0054 NEW)
set (lib_name "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}lib${CMAKE_STATIC_LIBRARY_SUFFIX}")
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if (RunCMake_C_COMPILER_ID STREQUAL "MSVC")
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set (undef_flag /INCLUDE:_func)
else()
set (undef_flag /INCLUDE:func)
endif()
else()
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set (undef_flag -u _func)
else()
set (undef_flag -u func)
endif()
endif()
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set (undef_flag -u _func)
else()
set (undef_flag -u func)
endif()
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
try_compile(result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lib.c
COPY_FILE "${lib_name}")
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
try_run(run_result compile_result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/main.c
COMPILE_OUTPUT_VARIABLE compile_out
RUN_OUTPUT_VARIABLE run_out
LINK_OPTIONS ${undef_flag} "${lib_name}")
if(NOT compile_result)
message(FATAL_ERROR "try_run(... LINK_OPTIONS ...) compilation failed:\n${compile_out}")
endif()
if(run_result STREQUAL "FAILED_TO_RUN")
message(FATAL_ERROR "try_run(... LINK_OPTIONS ...) execution failed:\n${run_out}")
endif()
include(RunCMake)
run_cmake(BadLinkLibraries)
if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
CMAKE_C_COMPILER_ID MATCHES "^(MSVC|GNU|Clang|AppleClang)$")
set (RunCMake_TEST_OPTIONS -DRunCMake_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
run_cmake(LinkOptions)
unset (RunCMake_TEST_OPTIONS)
endif()
extern void func();
int main(void)
{
func();
return 0;
}
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