Browse Source

try_compile/try_run: Add support for LINK_OPTIONS option.

Marc Chevrier 7 years ago
parent
commit
29f9db5c63

+ 8 - 1
Help/command/try_compile.rst

@@ -33,6 +33,7 @@ Try Compiling Source Files
   try_compile(RESULT_VAR <bindir> <srcfile|SOURCES srcfile...>
   try_compile(RESULT_VAR <bindir> <srcfile|SOURCES srcfile...>
               [CMAKE_FLAGS <flags>...]
               [CMAKE_FLAGS <flags>...]
               [COMPILE_DEFINITIONS <defs>...]
               [COMPILE_DEFINITIONS <defs>...]
+              [LINK_OPTIONS <options>...]
               [LINK_LIBRARIES <libs>...]
               [LINK_LIBRARIES <libs>...]
               [OUTPUT_VARIABLE <var>]
               [OUTPUT_VARIABLE <var>]
               [COPY_FILE <fileName> [COPY_FILE_ERROR <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})
   include_directories(${INCLUDE_DIRECTORIES})
   link_directories(${LINK_DIRECTORIES})
   link_directories(${LINK_DIRECTORIES})
   add_executable(cmTryCompileExec <srcfile>...)
   add_executable(cmTryCompileExec <srcfile>...)
+  target_link_options(cmTryCompileExec PRIVATE <LINK_OPTIONS from caller>)
   target_link_libraries(cmTryCompileExec ${LINK_LIBRARIES})
   target_link_libraries(cmTryCompileExec ${LINK_LIBRARIES})
 
 
 The options are:
 The options are:
@@ -67,7 +69,7 @@ The options are:
   are used.
   are used.
 
 
 ``COMPILE_DEFINITIONS <defs>...``
 ``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.
   in the generated test project.
 
 
 ``COPY_FILE <fileName>``
 ``COPY_FILE <fileName>``
@@ -85,6 +87,11 @@ The options are:
   If this option is specified, any ``-DLINK_LIBRARIES=...`` value
   If this option is specified, any ``-DLINK_LIBRARIES=...`` value
   given to the ``CMAKE_FLAGS`` option will be ignored.
   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>``
 ``OUTPUT_VARIABLE <var>``
   Store the output from the build process the given variable.
   Store the output from the build process the given variable.
 
 

+ 6 - 1
Help/command/try_run.rst

@@ -15,6 +15,7 @@ Try Compiling and Running Source Files
   try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR
   try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR
           bindir srcfile [CMAKE_FLAGS <flags>...]
           bindir srcfile [CMAKE_FLAGS <flags>...]
           [COMPILE_DEFINITIONS <defs>...]
           [COMPILE_DEFINITIONS <defs>...]
+          [LINK_OPTIONS <options>...]
           [LINK_LIBRARIES <libs>...]
           [LINK_LIBRARIES <libs>...]
           [COMPILE_OUTPUT_VARIABLE <var>]
           [COMPILE_OUTPUT_VARIABLE <var>]
           [RUN_OUTPUT_VARIABLE <var>]
           [RUN_OUTPUT_VARIABLE <var>]
@@ -38,7 +39,7 @@ The options are:
   are used.
   are used.
 
 
 ``COMPILE_DEFINITIONS <defs>...``
 ``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.
   in the generated test project.
 
 
 ``COMPILE_OUTPUT_VARIABLE <var>``
 ``COMPILE_OUTPUT_VARIABLE <var>``
@@ -52,6 +53,10 @@ The options are:
   If this option is specified, any ``-DLINK_LIBRARIES=...`` value
   If this option is specified, any ``-DLINK_LIBRARIES=...`` value
   given to the ``CMAKE_FLAGS`` option will be ignored.
   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>``
 ``OUTPUT_VARIABLE <var>``
   Report the compile build output and the output from running the executable
   Report the compile build output and the output from running the executable
   in the given variable.  This option exists for legacy reasons.  Prefer
   in the given variable.  This option exists for legacy reasons.  Prefer

+ 5 - 0
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``.

+ 23 - 0
Source/cmCoreTryCompile.cxx

@@ -121,6 +121,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
   std::string cxxExtensions;
   std::string cxxExtensions;
   std::string cudaExtensions;
   std::string cudaExtensions;
   std::vector<std::string> targets;
   std::vector<std::string> targets;
+  std::vector<std::string> linkOptions;
   std::string libsToLink = " ";
   std::string libsToLink = " ";
   bool useOldLinkLibs = true;
   bool useOldLinkLibs = true;
   char targetNameBuf[64];
   char targetNameBuf[64];
@@ -144,6 +145,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
     DoingNone,
     DoingNone,
     DoingCMakeFlags,
     DoingCMakeFlags,
     DoingCompileDefinitions,
     DoingCompileDefinitions,
+    DoingLinkOptions,
     DoingLinkLibraries,
     DoingLinkLibraries,
     DoingOutputVariable,
     DoingOutputVariable,
     DoingCopyFile,
     DoingCopyFile,
@@ -165,6 +167,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       doing = DoingCMakeFlags;
       doing = DoingCMakeFlags;
     } else if (argv[i] == "COMPILE_DEFINITIONS") {
     } else if (argv[i] == "COMPILE_DEFINITIONS") {
       doing = DoingCompileDefinitions;
       doing = DoingCompileDefinitions;
+    } else if (argv[i] == "LINK_OPTIONS") {
+      doing = DoingLinkOptions;
     } else if (argv[i] == "LINK_LIBRARIES") {
     } else if (argv[i] == "LINK_LIBRARIES") {
       doing = DoingLinkLibraries;
       doing = DoingLinkLibraries;
       useOldLinkLibs = false;
       useOldLinkLibs = false;
@@ -208,6 +212,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       cmakeFlags.push_back(argv[i]);
       cmakeFlags.push_back(argv[i]);
     } else if (doing == DoingCompileDefinitions) {
     } else if (doing == DoingCompileDefinitions) {
       compileDefs.push_back(argv[i]);
       compileDefs.push_back(argv[i]);
+    } else if (doing == DoingLinkOptions) {
+      linkOptions.push_back(argv[i]);
     } else if (doing == DoingLinkLibraries) {
     } else if (doing == DoingLinkLibraries) {
       libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
       libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
       if (cmTarget* tgt = this->Makefile->FindTargetToUse(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) {
     if (useOldLinkLibs) {
       fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
       fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n",
               targetName.c_str());
               targetName.c_str());

+ 2 - 1
Source/cmTryRunCommand.cxx

@@ -45,7 +45,8 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
     if (argv[i] == "ARGS") {
     if (argv[i] == "ARGS") {
       ++i;
       ++i;
       while (i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" &&
       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 += " ";
         runArgs += argv[i];
         runArgs += argv[i];
         ++i;
         ++i;

+ 3 - 1
Tests/RunCMake/CMakeLists.txt

@@ -275,6 +275,7 @@ function(add_RunCMake_test_try_compile)
     endif()
     endif()
   endif()
   endif()
   foreach(var
   foreach(var
+      CMAKE_SYSTEM_NAME
       CMAKE_C_COMPILER_ID
       CMAKE_C_COMPILER_ID
       CMAKE_C_COMPILER_VERSION
       CMAKE_C_COMPILER_VERSION
       CMAKE_C_STANDARD_DEFAULT
       CMAKE_C_STANDARD_DEFAULT
@@ -291,7 +292,8 @@ function(add_RunCMake_test_try_compile)
 endfunction()
 endfunction()
 add_RunCMake_test_try_compile()
 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(set)
 add_RunCMake_test(variable_watch)
 add_RunCMake_test(variable_watch)
 add_RunCMake_test(while)
 add_RunCMake_test(while)

+ 38 - 0
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()

+ 7 - 0
Tests/RunCMake/try_compile/RunCMakeTest.cmake

@@ -25,6 +25,13 @@ run_cmake(TargetTypeExe)
 run_cmake(TargetTypeInvalid)
 run_cmake(TargetTypeInvalid)
 run_cmake(TargetTypeStatic)
 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)
 if(CMAKE_C_STANDARD_DEFAULT)
   run_cmake(CStandard)
   run_cmake(CStandard)
 elseif(DEFINED CMAKE_C_STANDARD_DEFAULT)
 elseif(DEFINED CMAKE_C_STANDARD_DEFAULT)

+ 4 - 0
Tests/RunCMake/try_compile/lib.c

@@ -0,0 +1,4 @@
+
+void func()
+{
+}

+ 8 - 0
Tests/RunCMake/try_compile/main.c

@@ -0,0 +1,8 @@
+extern void func();
+
+int main(void)
+{
+  func();
+
+  return 0;
+}

+ 42 - 0
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()

+ 7 - 0
Tests/RunCMake/try_run/RunCMakeTest.cmake

@@ -1,3 +1,10 @@
 include(RunCMake)
 include(RunCMake)
 
 
 run_cmake(BadLinkLibraries)
 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()

+ 4 - 0
Tests/RunCMake/try_run/lib.c

@@ -0,0 +1,4 @@
+
+void func()
+{
+}

+ 8 - 0
Tests/RunCMake/try_run/main.c

@@ -0,0 +1,8 @@
+extern void func();
+
+int main(void)
+{
+  func();
+
+  return 0;
+}