From 29f9db5c63dbfa53acdb449fad78d716a4113a88 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 19 Nov 2018 17:23:45 +0100 Subject: try_compile/try_run: Add support for LINK_OPTIONS option. --- Help/command/try_compile.rst | 9 +++++- Help/command/try_run.rst | 7 ++++- Help/release/dev/try_compile-LINK_OPTIONS.rst | 5 ++++ Source/cmCoreTryCompile.cxx | 23 +++++++++++++++ Source/cmTryRunCommand.cxx | 3 +- Tests/RunCMake/CMakeLists.txt | 4 ++- Tests/RunCMake/try_compile/LinkOptions.cmake | 38 ++++++++++++++++++++++++ Tests/RunCMake/try_compile/RunCMakeTest.cmake | 7 +++++ Tests/RunCMake/try_compile/lib.c | 4 +++ Tests/RunCMake/try_compile/main.c | 8 +++++ Tests/RunCMake/try_run/LinkOptions.cmake | 42 +++++++++++++++++++++++++++ Tests/RunCMake/try_run/RunCMakeTest.cmake | 7 +++++ Tests/RunCMake/try_run/lib.c | 4 +++ Tests/RunCMake/try_run/main.c | 8 +++++ 14 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 Help/release/dev/try_compile-LINK_OPTIONS.rst create mode 100644 Tests/RunCMake/try_compile/LinkOptions.cmake create mode 100644 Tests/RunCMake/try_compile/lib.c create mode 100644 Tests/RunCMake/try_compile/main.c create mode 100644 Tests/RunCMake/try_run/LinkOptions.cmake create mode 100644 Tests/RunCMake/try_run/lib.c create mode 100644 Tests/RunCMake/try_run/main.c diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst index 310ad11..f50fcb6 100644 --- a/Help/command/try_compile.rst +++ b/Help/command/try_compile.rst @@ -33,6 +33,7 @@ Try Compiling Source Files try_compile(RESULT_VAR [CMAKE_FLAGS ...] [COMPILE_DEFINITIONS ...] + [LINK_OPTIONS ...] [LINK_LIBRARIES ...] [OUTPUT_VARIABLE ] [COPY_FILE [COPY_FILE_ERROR ]] @@ -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 ...) + target_link_options(cmTryCompileExec PRIVATE ) target_link_libraries(cmTryCompileExec ${LINK_LIBRARIES}) The options are: @@ -67,7 +69,7 @@ The options are: are used. ``COMPILE_DEFINITIONS ...`` - Specify ``-Ddefinition`` arguments to pass to ``add_definitions`` + Specify ``-Ddefinition`` arguments to pass to :command:`add_definitions` in the generated test project. ``COPY_FILE `` @@ -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 ...`` + 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 `` Store the output from the build process the given variable. diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst index dfa0bf9..137402f 100644 --- a/Help/command/try_run.rst +++ b/Help/command/try_run.rst @@ -15,6 +15,7 @@ Try Compiling and Running Source Files try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR bindir srcfile [CMAKE_FLAGS ...] [COMPILE_DEFINITIONS ...] + [LINK_OPTIONS ...] [LINK_LIBRARIES ...] [COMPILE_OUTPUT_VARIABLE ] [RUN_OUTPUT_VARIABLE ] @@ -38,7 +39,7 @@ The options are: are used. ``COMPILE_DEFINITIONS ...`` - 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 `` @@ -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 ...`` + Specify link step options to pass to :command:`target_link_options` in the + generated project. + ``OUTPUT_VARIABLE `` Report the compile build output and the output from running the executable in the given variable. This option exists for legacy reasons. Prefer diff --git a/Help/release/dev/try_compile-LINK_OPTIONS.rst b/Help/release/dev/try_compile-LINK_OPTIONS.rst new file mode 100644 index 0000000..1db485b --- /dev/null +++ b/Help/release/dev/try_compile-LINK_OPTIONS.rst @@ -0,0 +1,5 @@ +try_compile-LINK_OPTIONS +------------------------ + +* The commands :command:`try_compile` and :command:`try_run` gain new + option ``LINK_OPTIONS``. diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index f6ec606..541ae76 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -121,6 +121,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, std::string cxxExtensions; std::string cudaExtensions; std::vector targets; + std::vector linkOptions; std::string libsToLink = " "; bool useOldLinkLibs = true; char targetNameBuf[64]; @@ -144,6 +145,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, DoingNone, DoingCMakeFlags, DoingCompileDefinitions, + DoingLinkOptions, DoingLinkLibraries, DoingOutputVariable, DoingCopyFile, @@ -165,6 +167,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector 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 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 const& argv, } } + if (!linkOptions.empty()) { + std::vector 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()); diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 9396138..fafbd24 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -45,7 +45,8 @@ bool cmTryRunCommand::InitialPass(std::vector 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; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index a4d829b..b044757 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -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) diff --git a/Tests/RunCMake/try_compile/LinkOptions.cmake b/Tests/RunCMake/try_compile/LinkOptions.cmake new file mode 100644 index 0000000..9b246c4 --- /dev/null +++ b/Tests/RunCMake/try_compile/LinkOptions.cmake @@ -0,0 +1,38 @@ + +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() diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake index 6a1bc64..77fb7a0 100644 --- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -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) diff --git a/Tests/RunCMake/try_compile/lib.c b/Tests/RunCMake/try_compile/lib.c new file mode 100644 index 0000000..b00c576 --- /dev/null +++ b/Tests/RunCMake/try_compile/lib.c @@ -0,0 +1,4 @@ + +void func() +{ +} diff --git a/Tests/RunCMake/try_compile/main.c b/Tests/RunCMake/try_compile/main.c new file mode 100644 index 0000000..2128ead --- /dev/null +++ b/Tests/RunCMake/try_compile/main.c @@ -0,0 +1,8 @@ +extern void func(); + +int main(void) +{ + func(); + + return 0; +} diff --git a/Tests/RunCMake/try_run/LinkOptions.cmake b/Tests/RunCMake/try_run/LinkOptions.cmake new file mode 100644 index 0000000..17af2f7 --- /dev/null +++ b/Tests/RunCMake/try_run/LinkOptions.cmake @@ -0,0 +1,42 @@ + +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() diff --git a/Tests/RunCMake/try_run/RunCMakeTest.cmake b/Tests/RunCMake/try_run/RunCMakeTest.cmake index 1ec9a55..3689562 100644 --- a/Tests/RunCMake/try_run/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_run/RunCMakeTest.cmake @@ -1,3 +1,10 @@ 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() diff --git a/Tests/RunCMake/try_run/lib.c b/Tests/RunCMake/try_run/lib.c new file mode 100644 index 0000000..b00c576 --- /dev/null +++ b/Tests/RunCMake/try_run/lib.c @@ -0,0 +1,4 @@ + +void func() +{ +} diff --git a/Tests/RunCMake/try_run/main.c b/Tests/RunCMake/try_run/main.c new file mode 100644 index 0000000..2128ead --- /dev/null +++ b/Tests/RunCMake/try_run/main.c @@ -0,0 +1,8 @@ +extern void func(); + +int main(void) +{ + func(); + + return 0; +} -- cgit v0.12