summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/DEVICE_LINK_OPTIONS.txt7
-rw-r--r--Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt6
-rw-r--r--Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt6
-rw-r--r--Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt6
-rw-r--r--Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt6
-rw-r--r--Help/guide/tutorial/index.rst8
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst5
-rw-r--r--Help/manual/cmake-properties.7.rst2
-rw-r--r--Help/prop_sf/VS_SETTINGS.rst2
-rw-r--r--Help/prop_tgt/FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG.rst23
-rw-r--r--Help/prop_tgt/PCH_WARN_INVALID.rst6
-rw-r--r--Help/prop_tgt/VS_SOLUTION_DEPLOY.rst16
-rw-r--r--Help/prop_tgt/VS_SOURCE_SETTINGS_tool.rst2
-rw-r--r--Help/release/3.18.rst23
-rw-r--r--Modules/CMakeDetermineCUDACompiler.cmake257
-rw-r--r--Modules/Compiler/ARMClang.cmake2
-rw-r--r--Modules/FindBLAS.cmake2
-rw-r--r--Modules/FindCUDAToolkit.cmake6
-rw-r--r--Modules/FindLAPACK.cmake2
-rw-r--r--Modules/GoogleTest.cmake8
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmCoreTryCompile.cxx486
-rw-r--r--Source/cmCoreTryCompile.h4
-rw-r--r--Source/cmGeneratorExpressionNode.cxx6
-rw-r--r--Source/cmGeneratorTarget.cxx97
-rw-r--r--Source/cmGeneratorTarget.h17
-rw-r--r--Source/cmGlobalGenerator.cxx10
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx215
-rw-r--r--Source/cmGlobalXCodeGenerator.h3
-rw-r--r--Source/cmLocalGenerator.cxx52
-rw-r--r--Source/cmLocalGenerator.h3
-rw-r--r--Source/cmMakefile.cxx209
-rw-r--r--Source/cmMakefile.h59
-rw-r--r--Tests/Cuda/Toolkit/CMakeLists.txt22
-rw-r--r--Tests/CudaOnly/Toolkit/CMakeLists.txt17
-rw-r--r--Tests/RunCMake/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/target_link_libraries-ALIAS/AliasTargets.cmake (renamed from Tests/RunCMake/target_link_libraries/AliasTargets.cmake)0
-rw-r--r--Tests/RunCMake/target_link_libraries-ALIAS/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/target_link_libraries-ALIAS/RunCMakeTest.cmake23
-rw-r--r--Tests/RunCMake/target_link_libraries-ALIAS/func.c (renamed from Tests/RunCMake/target_link_libraries/func.c)0
-rw-r--r--Tests/RunCMake/target_link_libraries-ALIAS/lib.c10
-rw-r--r--Tests/RunCMake/target_link_libraries-ALIAS/main.c (renamed from Tests/RunCMake/target_link_libraries/main.c)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake41
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang-result.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang-result.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang-stderr.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang-stderr.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang.cmake (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang.cmake)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage-result.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage-result.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage-stderr.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage-stderr.txt)2
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage.cmake (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage.cmake)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/empty.c0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.c7
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.cxx (renamed from Tests/RunCMake/target_link_libraries/func.cxx)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/genex.cmake (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE.cmake)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/lib.c10
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c12
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.cxx (renamed from Tests/RunCMake/target_link_libraries/main.cxx)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/RunCMakeTest.cmake38
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang-result.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang-result.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang-stderr.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang-stderr.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang.cmake (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang.cmake)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/basic-result.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-interface-result.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/empty.c0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/exe_c-result.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-exe_cxx-result.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/exe_cxx-result.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-exe_c-result.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/func.c7
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/func.cxx7
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/genex.cmake (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID.cmake)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/interface-result.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-basic-result.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/lib.c10
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/main.c12
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/main.cxx12
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/no_language-result.txt (renamed from Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-no_language-result.txt)0
-rw-r--r--Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake68
75 files changed, 1179 insertions, 689 deletions
diff --git a/Help/command/DEVICE_LINK_OPTIONS.txt b/Help/command/DEVICE_LINK_OPTIONS.txt
index 012e9b1..3f0226f 100644
--- a/Help/command/DEVICE_LINK_OPTIONS.txt
+++ b/Help/command/DEVICE_LINK_OPTIONS.txt
@@ -1,9 +1,10 @@
When a device link step is involved, which is controlled by
:prop_tgt:`CUDA_SEPARABLE_COMPILATION` and
-:prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties, the raw options will be
-delivered to the host and device link steps (wrapped in ``-Xcompiler`` or
-equivalent for device link). Options wrapped with ``$<DEVICE_LINK:...>``
+:prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties and policy :policy:`CMP0105`,
+the raw options will be delivered to the host and device link steps (wrapped in
+``-Xcompiler`` or equivalent for device link). Options wrapped with
+``$<DEVICE_LINK:...>``
:manual:`generator expression <cmake-generator-expressions(7)>` will be used
only for the device link step. Options wrapped with ``$<HOST_LINK:...>``
:manual:`generator expression <cmake-generator-expressions(7)>` will be used
diff --git a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
index c911625..a47d5e0 100644
--- a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
@@ -57,7 +57,11 @@ set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
# install rules
-install(TARGETS MathFunctions tutorial_compiler_flags
+set(installable_libs MathFunctions tutorial_compiler_flags)
+if(TARGET SqrtLibrary)
+ list(APPEND installable_libs SqrtLibrary)
+endif()
+install(TARGETS ${installable_libs}
DESTINATION lib
EXPORT MathFunctionsTargets)
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
index e0c0621..0bfe20c 100644
--- a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt
@@ -47,5 +47,9 @@ endif()
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
# install rules
-install(TARGETS MathFunctions DESTINATION lib)
+set(installable_libs MathFunctions)
+if(TARGET SqrtLibrary)
+ list(APPEND installable_libs SqrtLibrary)
+endif()
+install(TARGETS ${installable_libs} DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
index 32f5e08..0d287ca 100644
--- a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
@@ -51,5 +51,9 @@ target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
# install rules
-install(TARGETS MathFunctions DESTINATION lib)
+set(installable_libs MathFunctions tutorial_compiler_flags)
+if(TARGET SqrtLibrary)
+ list(APPEND installable_libs SqrtLibrary)
+endif()
+install(TARGETS ${installable_libs} DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt
index 720ee64..ea3861c 100644
--- a/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt
@@ -53,7 +53,11 @@ target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
# install rules
-install(TARGETS MathFunctions tutorial_compiler_flags
+set(installable_libs MathFunctions tutorial_compiler_flags)
+if(TARGET SqrtLibrary)
+ list(APPEND installable_libs SqrtLibrary)
+endif()
+install(TARGETS ${installable_libs}
DESTINATION lib
EXPORT MathFunctionsTargets)
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst
index 6e26de9..e7ea290 100644
--- a/Help/guide/tutorial/index.rst
+++ b/Help/guide/tutorial/index.rst
@@ -675,9 +675,9 @@ The first step is to update the starting section of the top-level
Now that we have made MathFunctions always be used, we will need to update
the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to
-create a SqrtLibrary that will conditionally be built when ``USE_MYMATH`` is
-enabled. Now, since this is a tutorial, we are going to explicitly require
-that SqrtLibrary is built statically.
+create a SqrtLibrary that will conditionally be built and installed when
+``USE_MYMATH`` is enabled. Now, since this is a tutorial, we are going to
+explicitly require that SqrtLibrary is built statically.
The end result is that ``MathFunctions/CMakeLists.txt`` should look like:
@@ -703,7 +703,7 @@ Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines:
.. literalinclude:: Step10/MathFunctions/MathFunctions.h
:language: c++
-At this point, if you build everything, you will notice that linking fails
+At this point, if you build everything, you may notice that linking fails
as we are combining a static library without position independent code with a
library that has position independent code. The solution to this is to
explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 9e411a4..124da44 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -365,8 +365,9 @@ Variable Queries
``$<DEVICE_LINK:list>``
Returns the list if it is the device link step, an empty list otherwise.
The device link step is controlled by :prop_tgt:`CUDA_SEPARABLE_COMPILATION`
- and :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties. This expression can
- only be used to specify link options.
+ and :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties and
+ policy :policy:`CMP0105`. This expression can only be used to specify link
+ options.
``$<HOST_LINK:list>``
Returns the list if it is the normal link step, an empty list otherwise.
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 7f7ed50..30b2a05 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -128,7 +128,6 @@ Properties on Targets
/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY
/prop_tgt/ARCHIVE_OUTPUT_NAME_CONFIG
/prop_tgt/ARCHIVE_OUTPUT_NAME
- /prop_tgt/PCH_WARN_INVALID
/prop_tgt/AUTOGEN_BUILD_DIR
/prop_tgt/AUTOGEN_ORIGIN_DEPENDS
/prop_tgt/AUTOGEN_PARALLEL
@@ -312,6 +311,7 @@ Properties on Targets
/prop_tgt/OSX_ARCHITECTURES
/prop_tgt/OUTPUT_NAME_CONFIG
/prop_tgt/OUTPUT_NAME
+ /prop_tgt/PCH_WARN_INVALID
/prop_tgt/PDB_NAME_CONFIG
/prop_tgt/PDB_NAME
/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG
diff --git a/Help/prop_sf/VS_SETTINGS.rst b/Help/prop_sf/VS_SETTINGS.rst
index 0719406..50034fb 100644
--- a/Help/prop_sf/VS_SETTINGS.rst
+++ b/Help/prop_sf/VS_SETTINGS.rst
@@ -15,4 +15,4 @@ For example:
will set ``Key`` to ``Value`` and ``Key2`` to ``Value2`` on the
``file.hlsl`` item as metadata.
-Generator expressions are supported.
+:manual:`Generator expressions <cmake-generator-expressions(7)>` are supported.
diff --git a/Help/prop_tgt/FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG.rst b/Help/prop_tgt/FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG.rst
index 2b20bf9..5d0fc3d 100644
--- a/Help/prop_tgt/FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG.rst
+++ b/Help/prop_tgt/FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG.rst
@@ -1,24 +1,25 @@
FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>
---------------------------------------
-Postfix to append to the framework file name for configuration <CONFIG>,
+Postfix to append to the framework file name for configuration ``<CONFIG>``,
when using a multi-config generator (like Xcode and Ninja Multi-Config).
-When building with configuration <CONFIG> the value of this property
+When building with configuration ``<CONFIG>`` the value of this property
is appended to the framework file name built on disk.
-For example given a framework called ``my_fw``, a value of ``_debug``
-for the :prop_tgt:`FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>` property, and
-``Debug;Release`` in `CMAKE_CONFIGURATION_TYPES`, the following relevant
-files would be created for the ``Debug`` and ``Release`` configurations:
+For example, given a framework called ``my_fw``, a value of ``_debug``
+for the ``FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>`` property, and
+``Debug;Release`` in :variable:`CMAKE_CONFIGURATION_TYPES`, the following
+relevant files would be created for the ``Debug`` and ``Release``
+configurations:
-- Release/my_fw.framework/my_fw
-- Release/my_fw.framework/Versions/A/my_fw
-- Debug/my_fw.framework/my_fw_debug
-- Debug/my_fw.framework/Versions/A/my_fw_debug
+- ``Release/my_fw.framework/my_fw``
+- ``Release/my_fw.framework/Versions/A/my_fw``
+- ``Debug/my_fw.framework/my_fw_debug``
+- ``Debug/my_fw.framework/Versions/A/my_fw_debug``
For framework targets, this property is initialized by the value of the
-variable :variable:`CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>` if it
+:variable:`CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>` variable if it
is set when a target is created.
This property is ignored for non-framework targets, and when using single
diff --git a/Help/prop_tgt/PCH_WARN_INVALID.rst b/Help/prop_tgt/PCH_WARN_INVALID.rst
index 36ec348..96e1abd 100644
--- a/Help/prop_tgt/PCH_WARN_INVALID.rst
+++ b/Help/prop_tgt/PCH_WARN_INVALID.rst
@@ -2,7 +2,9 @@ PCH_WARN_INVALID
----------------
When this property is set to true, the precompile header compiler options
-will contain a compiler flag wich should warn about invalid precompiled
+will contain a compiler flag which should warn about invalid precompiled
headers e.g. ``-Winvalid-pch`` for GNU compiler.
-The defalut value is ``ON``.
+This property is initialized by the value of the
+:variable:`CMAKE_PCH_WARN_INVALID` variable if it is set when a target is
+created. If that variable is not set, the property defaults to ``ON``.
diff --git a/Help/prop_tgt/VS_SOLUTION_DEPLOY.rst b/Help/prop_tgt/VS_SOLUTION_DEPLOY.rst
index 7906d75..eef848f 100644
--- a/Help/prop_tgt/VS_SOLUTION_DEPLOY.rst
+++ b/Help/prop_tgt/VS_SOLUTION_DEPLOY.rst
@@ -4,24 +4,22 @@ VS_SOLUTION_DEPLOY
Specify that the target should be marked for deployment when not targeting
Windows CE, Windows Phone or a Windows Store application.
-If the target platform doesn't support deployment, this property won't have any effect.
+If the target platform doesn't support deployment, this property won't have
+any effect.
-Generator expressions are supported.
+:manual:`Generator expressions <cmake-generator-expressions(7)>` are supported.
-Example 1
-^^^^^^^^^
+Examples
+^^^^^^^^
-This shows setting the variable for the target foo.
+Always deploy target ``foo``:
.. code-block:: cmake
add_executable(foo SHARED foo.cpp)
set_property(TARGET foo PROPERTY VS_SOLUTION_DEPLOY ON)
-Example 2
-^^^^^^^^^
-
-This shows setting the variable for the Release configuration only.
+Deploy target ``foo`` for all configurations except ``Release``:
.. code-block:: cmake
diff --git a/Help/prop_tgt/VS_SOURCE_SETTINGS_tool.rst b/Help/prop_tgt/VS_SOURCE_SETTINGS_tool.rst
index f706888..738a912 100644
--- a/Help/prop_tgt/VS_SOURCE_SETTINGS_tool.rst
+++ b/Help/prop_tgt/VS_SOURCE_SETTINGS_tool.rst
@@ -16,4 +16,4 @@ For example:
will set ``Key`` to ``Value`` and ``Key2`` to ``Value2`` for all
non-built files that use ``FXCompile``.
-Generator expressions are supported.
+:manual:`Generator expressions <cmake-generator-expressions(7)>` are supported.
diff --git a/Help/release/3.18.rst b/Help/release/3.18.rst
index 072f9aa..c98b12a 100644
--- a/Help/release/3.18.rst
+++ b/Help/release/3.18.rst
@@ -117,6 +117,9 @@ Properties
* The :prop_sf:`OBJECT_OUTPUTS` source file property now supports
:manual:`generator expressions <cmake-generator-expressions(7)>`.
+* The :prop_tgt:`PCH_WARN_INVALID` target property was added to allow the
+ removal of the precompiled header invalid warning.
+
* The :prop_tgt:`UNITY_BUILD_MODE` target property was added to tell
generators which algorithm to use for grouping included source
files.
@@ -157,6 +160,14 @@ Modules
* The :module:`FindBLAS` module now provides an imported target.
+* The :module:`FindCUDAToolkit` module:
+
+ * gained the variable
+ ``CUDAToolkit_LIBRARY_ROOT``, which is the directory containing the
+ ``nvvm`` directory and ``version.txt``.
+
+ * uses toolkit and library root found during ``CUDA`` compiler detection.
+
* The :module:`FindLAPACK` module now provides an imported target.
* The :module:`FindPython3`, :module:`FindPython2` and :module:`FindPython`
@@ -195,14 +206,6 @@ Modules
.. _`SWIG-Fortran`: https://github.com/swig-fortran/swig
-* The :module:`FindCUDAToolkit` module:
-
- * gained the variable
- ``CUDAToolkit_LIBRARY_ROOT``, which is the directory containing the
- ``nvvm`` directory and ``version.txt``.
-
- * uses toolkit and library root found during ``CUDA`` compiler detection.
-
Generator Expressions
---------------------
@@ -243,9 +246,9 @@ CPack
installer is DPI-aware.
* The :cpack_gen:`CPack RPM Generator` gained
- :variable:`CPACK_RPM_PRE_TRANS_SCRIPT_FILE`
+ :variable:`CPACK_RPM_PRE_TRANS_SCRIPT_FILE` and
:variable:`CPACK_RPM_POST_TRANS_SCRIPT_FILE`
- variables to specify pre- and post-trans scripts.
+ variables to specify pre- and post-transaction scripts.
Other
-----
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index e12da45..692ce20 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -51,146 +51,139 @@ endif()
if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
set(CMAKE_CUDA_COMPILER_ID_RUN 1)
- # Try to identify the compiler.
- set(CMAKE_CUDA_COMPILER_ID)
- set(CMAKE_CUDA_PLATFORM_ID)
- file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
- CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT)
-
- list(APPEND CMAKE_CUDA_COMPILER_ID_VENDORS NVIDIA Clang)
- set(CMAKE_CUDA_COMPILER_ID_VENDOR_REGEX_NVIDIA "nvcc: NVIDIA \\(R\\) Cuda compiler driver")
- set(CMAKE_CUDA_COMPILER_ID_VENDOR_REGEX_Clang "(clang version)")
-
- set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdCUDA/(\\./)?(CompilerIdCUDA.xctest/)?CompilerIdCUDA[ \t\n\\\"]")
- set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX 2)
- set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-v")
-
- # We determine the vendor to help with find the toolkit and use the right flags for detection right away.
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
- CMAKE_DETERMINE_COMPILER_ID_VENDOR(CUDA "--version")
-
- # Find the CUDA toolkit. We store the CMAKE_CUDA_COMPILER_TOOLKIT_ROOT and CMAKE_CUDA_COMPILER_LIBRARY_ROOT
- # in CMakeCUDACompiler.cmake, so FindCUDAToolkit can avoid searching on future runs and the toolkit stays the same.
- # This is very similar to FindCUDAToolkit, but somewhat simplified since we can issue fatal errors
- # if we fail to find things we need and we don't need to account for searching the libraries.
- # For NVCC we can easily deduce the SDK binary directory from the compiler path.
- if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
- get_filename_component(_CUDA_BIN_DIR "${CMAKE_CUDA_COMPILER}" DIRECTORY)
- find_program(CUDAToolkit_NVCC_EXECUTABLE
- NAMES nvcc nvcc.exe
- PATHS ${_CUDA_BIN_DIR}
- NO_DEFAULT_PATH
- )
- unset(_CUDA_BIN_DIR)
- endif()
+ if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
+ # We will not know CMAKE_CUDA_COMPILER until the main compiler id step
+ # below extracts it, but we do know that the compiler id will be NVIDIA.
+ set(CMAKE_CUDA_COMPILER_ID "NVIDIA")
+ else()
+ # We determine the vendor to help with find the toolkit and use the right flags for detection right away.
+ # The main compiler identification is still needed below to extract other information.
+ list(APPEND CMAKE_CUDA_COMPILER_ID_VENDORS NVIDIA Clang)
+ set(CMAKE_CUDA_COMPILER_ID_VENDOR_REGEX_NVIDIA "nvcc: NVIDIA \\(R\\) Cuda compiler driver")
+ set(CMAKE_CUDA_COMPILER_ID_VENDOR_REGEX_Clang "(clang version)")
+ CMAKE_DETERMINE_COMPILER_ID_VENDOR(CUDA "--version")
+
+ # Find the CUDA toolkit. We store the CMAKE_CUDA_COMPILER_TOOLKIT_ROOT and CMAKE_CUDA_COMPILER_LIBRARY_ROOT
+ # in CMakeCUDACompiler.cmake, so FindCUDAToolkit can avoid searching on future runs and the toolkit stays the same.
+ # This is very similar to FindCUDAToolkit, but somewhat simplified since we can issue fatal errors
+ # if we fail to find things we need and we don't need to account for searching the libraries.
+
+ # For NVCC we can easily deduce the SDK binary directory from the compiler path.
+ if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
+ set(_CUDA_NVCC_EXECUTABLE "${CMAKE_CUDA_COMPILER}")
+ else()
+ # Search using CUDAToolkit_ROOT and then CUDA_PATH for equivalence with FindCUDAToolkit.
+ # In FindCUDAToolkit CUDAToolkit_ROOT is searched automatically due to being in a find_package().
+ # First we search candidate non-default paths to give them priority.
+ find_program(_CUDA_NVCC_EXECUTABLE
+ NAMES nvcc nvcc.exe
+ PATHS ${CUDAToolkit_ROOT}
+ ENV CUDAToolkit_ROOT
+ ENV CUDA_PATH
+ PATH_SUFFIXES bin
+ NO_DEFAULT_PATH
+ )
+
+ # If we didn't find NVCC, then try the default paths.
+ find_program(_CUDA_NVCC_EXECUTABLE
+ NAMES nvcc nvcc.exe
+ PATH_SUFFIXES bin
+ )
+
+ # If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error.
+ if(NOT _CUDA_NVCC_EXECUTABLE AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT}))
+ set(fail_base "Could not find nvcc executable in path specified by")
+
+ if(DEFINED CUDAToolkit_ROOT)
+ message(FATAL_ERROR "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}")
+ elseif(DEFINED ENV{CUDAToolkit_ROOT})
+ message(FATAL_ERROR "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}")
+ endif()
+ endif()
- # Search using CUDAToolkit_ROOT and then CUDA_PATH for equivalence with FindCUDAToolkit.
- # In FindCUDAToolkit CUDAToolkit_ROOT is searched automatically due to being in a find_package().
- # First we search candidate non-default paths to give them priority.
- find_program(_CUDA_NVCC_EXECUTABLE
- NAMES nvcc nvcc.exe
- PATHS ${CUDAToolkit_ROOT}
- ENV CUDAToolkit_ROOT
- ENV CUDA_PATH
- PATH_SUFFIXES bin
- NO_DEFAULT_PATH
- )
+ # CUDAToolkit_ROOT cmake/env variable not specified, try platform defaults.
+ #
+ # - Linux: /usr/local/cuda-X.Y
+ # - macOS: /Developer/NVIDIA/CUDA-X.Y
+ # - Windows: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y
+ #
+ # We will also search the default symlink location /usr/local/cuda first since
+ # if CUDAToolkit_ROOT is not specified, it is assumed that the symlinked
+ # directory is the desired location.
+ if(NOT _CUDA_NVCC_EXECUTABLE)
+ if(UNIX)
+ if(NOT APPLE)
+ set(platform_base "/usr/local/cuda-")
+ else()
+ set(platform_base "/Developer/NVIDIA/CUDA-")
+ endif()
+ else()
+ set(platform_base "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v")
+ endif()
- # If we didn't find NVCC, then try the default paths.
- find_program(_CUDA_NVCC_EXECUTABLE
- NAMES nvcc nvcc.exe
- PATH_SUFFIXES bin
- )
+ # Build out a descending list of possible cuda installations, e.g.
+ file(GLOB possible_paths "${platform_base}*")
+ # Iterate the glob results and create a descending list.
+ set(versions)
+ foreach(p ${possible_paths})
+ # Extract version number from end of string
+ string(REGEX MATCH "[0-9][0-9]?\\.[0-9]$" p_version ${p})
+ if(IS_DIRECTORY ${p} AND p_version)
+ list(APPEND versions ${p_version})
+ endif()
+ endforeach()
- # If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error.
- if(NOT _CUDA_NVCC_EXECUTABLE AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT}))
- set(fail_base "Could not find nvcc executable in path specified by")
+ # Sort numerically in descending order, so we try the newest versions first.
+ list(SORT versions COMPARE NATURAL ORDER DESCENDING)
- if(DEFINED CUDAToolkit_ROOT)
- message(FATAL_ERROR "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}")
- elseif(DEFINED ENV{CUDAToolkit_ROOT})
- message(FATAL_ERROR "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}")
- endif()
- endif()
+ # With a descending list of versions, populate possible paths to search.
+ set(search_paths)
+ foreach(v ${versions})
+ list(APPEND search_paths "${platform_base}${v}")
+ endforeach()
- # CUDAToolkit_ROOT cmake/env variable not specified, try platform defaults.
- #
- # - Linux: /usr/local/cuda-X.Y
- # - macOS: /Developer/NVIDIA/CUDA-X.Y
- # - Windows: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y
- #
- # We will also search the default symlink location /usr/local/cuda first since
- # if CUDAToolkit_ROOT is not specified, it is assumed that the symlinked
- # directory is the desired location.
- if(NOT _CUDA_NVCC_EXECUTABLE)
- if(UNIX)
- if(NOT APPLE)
- set(platform_base "/usr/local/cuda-")
- else()
- set(platform_base "/Developer/NVIDIA/CUDA-")
- endif()
- else()
- set(platform_base "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v")
- endif()
+ # Force the global default /usr/local/cuda to the front on Unix.
+ if(UNIX)
+ list(INSERT search_paths 0 "/usr/local/cuda")
+ endif()
- # Build out a descending list of possible cuda installations, e.g.
- file(GLOB possible_paths "${platform_base}*")
- # Iterate the glob results and create a descending list.
- set(versions)
- foreach(p ${possible_paths})
- # Extract version number from end of string
- string(REGEX MATCH "[0-9][0-9]?\\.[0-9]$" p_version ${p})
- if(IS_DIRECTORY ${p} AND p_version)
- list(APPEND versions ${p_version})
+ # Now search for nvcc again using the platform default search paths.
+ find_program(_CUDA_NVCC_EXECUTABLE
+ NAMES nvcc nvcc.exe
+ PATHS ${search_paths}
+ PATH_SUFFIXES bin
+ )
+
+ # We are done with these variables now, cleanup.
+ unset(platform_base)
+ unset(possible_paths)
+ unset(versions)
+ unset(search_paths)
+
+ if(NOT _CUDA_NVCC_EXECUTABLE)
+ message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.")
+ endif()
endif()
- endforeach()
-
- # Sort numerically in descending order, so we try the newest versions first.
- list(SORT versions COMPARE NATURAL ORDER DESCENDING)
-
- # With a descending list of versions, populate possible paths to search.
- set(search_paths)
- foreach(v ${versions})
- list(APPEND search_paths "${platform_base}${v}")
- endforeach()
-
- # Force the global default /usr/local/cuda to the front on Unix.
- if(UNIX)
- list(INSERT search_paths 0 "/usr/local/cuda")
endif()
- # Now search for nvcc again using the platform default search paths.
- find_program(_CUDA_NVCC_EXECUTABLE
- NAMES nvcc nvcc.exe
- PATHS ${search_paths}
- PATH_SUFFIXES bin
- )
-
- # We are done with these variables now, cleanup.
- unset(platform_base)
- unset(possible_paths)
- unset(versions)
- unset(search_paths)
-
- if(NOT _CUDA_NVCC_EXECUTABLE)
- message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.")
+ get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY)
+ get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY)
+
+ # CMAKE_CUDA_COMPILER_LIBRARY_ROOT contains the device library and version file.
+ # In a non-scattered installation this is equivalent to CMAKE_CUDA_COMPILER_TOOLKIT_ROOT.
+ # We first check for a non-scattered installation to prefer it over a scattered installation.
+ if(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/version.txt")
+ set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}")
+ elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/version.txt")
+ set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/cuda")
+ elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/version.txt")
+ set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT}/usr/lib/cuda")
endif()
endif()
- get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY)
- get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY ABSOLUTE)
-
- # CMAKE_CUDA_COMPILER_LIBRARY_ROOT contains the device library and version file.
- # In a non-scattered installation this is equivalent to CMAKE_CUDA_COMPILER_TOOLKIT_ROOT.
- # We first check for a non-scattered installation to prefer it over a scattered installation.
- if(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/version.txt")
- set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}")
- elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/version.txt")
- set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/cuda")
- elseif(EXISTS "${CMAKE_SYSROOT}/usr/lib/cuda/version.txt")
- set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT}/usr/lib/cuda")
- endif()
+ set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-v")
if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
set(nvcc_test_flags "--keep --keep-dir tmp")
@@ -242,10 +235,20 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
# We also use it to verify that CMAKE_CUDA_ARCHITECTURES and additionaly on Clang that CUDA toolkit path works.
# The latter could be done during compiler testing in the future to avoid doing this for Clang.
# We need to unset the compiler ID otherwise CMAKE_DETERMINE_COMPILER_ID() doesn't work.
- unset(CMAKE_CUDA_COMPILER_ID)
+ set(CMAKE_CUDA_COMPILER_ID)
+ set(CMAKE_CUDA_PLATFORM_ID)
+ file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
+ CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT)
CMAKE_DETERMINE_COMPILER_ID(CUDA CUDAFLAGS CMakeCUDACompilerId.cu)
+ if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
+ # Now that we have the path to nvcc, we can compute the toolkit root.
+ get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER}" DIRECTORY)
+ get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY)
+ set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}")
+ endif()
+
_cmake_find_compiler_sysroot(CUDA)
endif()
diff --git a/Modules/Compiler/ARMClang.cmake b/Modules/Compiler/ARMClang.cmake
index d412399..01ce91d 100644
--- a/Modules/Compiler/ARMClang.cmake
+++ b/Modules/Compiler/ARMClang.cmake
@@ -61,7 +61,7 @@ function(__armlink_set_cpu_list lang out_var)
if(__CMAKE_ARMClang_USING_armlink)
set(__linker_wrapper_flags "")
else()
- set(__linker_wrapper_flags --target=${CMAKE_${lang}_COMPILER_TARGET} -XLinker)
+ set(__linker_wrapper_flags --target=${CMAKE_${lang}_COMPILER_TARGET} -Xlinker)
endif()
execute_process(COMMAND "${CMAKE_LINKER}" ${__linker_wrapper_flags} --cpu=list
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 4c569b3..c5d791e 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -483,7 +483,9 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
endif()
set(BLAS_mkl_LIB_PATH_SUFFIXES
"compiler/lib" "compiler/lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}"
+ "compiler/lib/${BLAS_mkl_ARCH_NAME}"
"mkl/lib" "mkl/lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}"
+ "mkl/lib/${BLAS_mkl_ARCH_NAME}"
"lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}")
foreach(IT ${BLAS_SEARCH_LIBS})
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index 00d1a50..47bc546 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -154,6 +154,8 @@ Targets Created:
- ``CUDA::cublas``
- ``CUDA::cublas_static``
+- ``CUDA::cublasLt`` starting in CUDA 10.1
+- ``CUDA::cublasLt_static`` starting in CUDA 10.1
.. _`cuda_toolkit_cuFFT`:
@@ -240,6 +242,7 @@ Targets Created:
- ``CUDA::nppicc_static``
- `nppicom`: JPEG compression and decompression functions in `nppi_compression_functions.h`
+ Removed starting in CUDA 11.0, use :ref:`nvJPEG<cuda_toolkit_nvJPEG>` instead.
- ``CUDA::nppicom``
- ``CUDA::nppicom_static``
@@ -302,6 +305,7 @@ nvGRAPH
"""""""
The `nvGRAPH <https://docs.nvidia.com/cuda/nvgraph/index.html>`_ library.
+Removed starting in CUDA 11.0
Targets Created:
@@ -821,7 +825,7 @@ if(CUDAToolkit_FOUND)
endif()
_CUDAToolkit_find_and_add_import_lib(culibos) # it's a static library
- foreach (cuda_lib cublas cufft curand cusparse nppc nvjpeg)
+ foreach (cuda_lib cublasLt cublas cufft curand cusparse nppc nvjpeg)
_CUDAToolkit_find_and_add_import_lib(${cuda_lib})
_CUDAToolkit_find_and_add_import_lib(${cuda_lib}_static DEPS culibos)
endforeach()
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index e275946..a18cec4 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -289,7 +289,9 @@ if(BLAS_FOUND)
endif()
set(LAPACK_mkl_LIB_PATH_SUFFIXES
"compiler/lib" "compiler/lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}"
+ "compiler/lib/${LAPACK_mkl_ARCH_NAME}"
"mkl/lib" "mkl/lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}"
+ "mkl/lib/${LAPACK_mkl_ARCH_NAME}"
"lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}")
# First try empty lapack libs
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
index 975ce6c..f75d6ad 100644
--- a/Modules/GoogleTest.cmake
+++ b/Modules/GoogleTest.cmake
@@ -155,7 +155,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
[DISCOVERY_MODE <POST_BUILD|PRE_TEST>]
)
- ``gtest_discover_tests`` sets up a post-build command on the test executable
+ ``gtest_discover_tests()`` sets up a post-build command on the test executable
that generates the list of tests by parsing the output from running the test
with the ``--gtest_list_tests`` argument. Compared to the source parsing
approach of :command:`gtest_add_tests`, this ensures that the full list of
@@ -212,7 +212,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
``PROPERTIES name1 value1...``
Specifies additional properties to be set on all tests discovered by this
- invocation of ``gtest_discover_tests``.
+ invocation of ``gtest_discover_tests()``.
``TEST_LIST var``
Make the list of tests available in the variable ``var``, rather than the
@@ -246,7 +246,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
XML result output when using parallel test execution.
``DISCOVERY_MODE``
- Provides greater control over when ``gtest_discover_tests``performs test
+ Provides greater control over when ``gtest_discover_tests()`` performs test
discovery. By default, ``POST_BUILD`` sets up a post-build command
to perform test discovery at build time. In certain scenarios, like
cross-compiling, this ``POST_BUILD`` behavior is not desirable.
@@ -257,7 +257,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
``DISCOVERY_MODE`` defaults to the value of the
``CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE`` variable if it is not
- passed when calling ``gtest_discover_tests``. This provides a mechanism
+ passed when calling ``gtest_discover_tests()``. This provides a mechanism
for globally selecting a preferred test discovery behavior without having
to modify each call site.
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 40bf305..1d3dcce 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 18)
-set(CMake_VERSION_PATCH 20200617)
+set(CMake_VERSION_PATCH 20200619)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index a7acadc..677bc0f 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -25,6 +25,148 @@
#include "cmVersion.h"
#include "cmake.h"
+namespace {
+class LanguageStandardState
+{
+public:
+ LanguageStandardState(std::string&& lang)
+ : IsEnabled(false)
+ , DidStandard(false)
+ , DidStandardRequired(false)
+ , DidExtensions(false)
+ , StandardFlag(lang + "_STANDARD")
+ , RequiredFlag(lang + "_STANDARD_REQUIRED")
+ , ExtensionFlag(lang + "_EXTENSIONS")
+ {
+ }
+
+ void Enabled(bool isEnabled) { this->IsEnabled = isEnabled; }
+
+ bool UpdateIfMatches(std::vector<std::string> const& argv, size_t& index)
+ {
+ bool updated = false;
+ if (argv[index] == this->StandardFlag) {
+ this->DidStandard = true;
+ this->StandardValue = argv[++index];
+ updated = true;
+ } else if (argv[index] == this->RequiredFlag) {
+ this->DidStandardRequired = true;
+ this->RequiredValue = argv[++index];
+ updated = true;
+ } else if (argv[index] == this->ExtensionFlag) {
+ this->DidExtensions = true;
+ this->ExtensionValue = argv[++index];
+ updated = true;
+ }
+ return updated;
+ }
+
+ bool Validate(cmMakefile* const makefile) const
+ {
+ if (this->DidStandard) {
+ makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(this->StandardFlag,
+ " allowed only in source file signature."));
+ return false;
+ }
+ if (this->DidStandardRequired) {
+ makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(this->RequiredFlag,
+ " allowed only in source file signature."));
+ return false;
+ }
+ if (this->DidExtensions) {
+ makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(this->ExtensionFlag,
+ " allowed only in source file signature."));
+ return false;
+ }
+
+ return true;
+ }
+
+ bool DidNone() const
+ {
+ return !this->DidStandard && !this->DidStandardRequired &&
+ !this->DidExtensions;
+ }
+
+ void LoadUnsetPropertyValues(cmMakefile* const makefile, bool honorStandard,
+ bool warnCMP0067,
+ std::vector<std::string>& warnCMP0067Variables)
+ {
+ if (!this->IsEnabled) {
+ return;
+ }
+
+ auto lookupStdVar = [&](std::string const& var) -> std::string {
+ std::string value = makefile->GetSafeDefinition(var);
+ if (warnCMP0067 && !value.empty()) {
+ value.clear();
+ warnCMP0067Variables.push_back(var);
+ }
+ return value;
+ };
+
+ if (honorStandard || warnCMP0067) {
+ if (!this->DidStandard) {
+ this->StandardValue =
+ lookupStdVar(cmStrCat("CMAKE_", this->StandardFlag));
+ }
+ if (!this->DidStandardRequired) {
+ this->RequiredValue =
+ lookupStdVar(cmStrCat("CMAKE_", this->RequiredFlag));
+ }
+ if (!this->DidExtensions) {
+ this->ExtensionValue =
+ lookupStdVar(cmStrCat("CMAKE_", this->ExtensionFlag));
+ }
+ }
+ }
+
+ void WriteProperties(FILE* fout, std::string const& targetName) const
+ {
+ if (!this->IsEnabled) {
+ return;
+ }
+
+ auto writeProp = [&](std::string const& prop, std::string const& value) {
+ fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n",
+ targetName.c_str(),
+ cmOutputConverter::EscapeForCMake(prop).c_str(),
+ cmOutputConverter::EscapeForCMake(value).c_str());
+ };
+
+ if (!this->StandardValue.empty()) {
+ writeProp(this->StandardFlag, this->StandardValue);
+ }
+ if (!this->RequiredValue.empty()) {
+ writeProp(this->RequiredFlag, this->RequiredValue);
+ }
+ if (!this->ExtensionValue.empty()) {
+ writeProp(this->ExtensionFlag, this->ExtensionValue);
+ }
+ }
+
+private:
+ bool IsEnabled;
+ bool DidStandard;
+ bool DidStandardRequired;
+ bool DidExtensions;
+
+ std::string StandardFlag;
+ std::string RequiredFlag;
+ std::string ExtensionFlag;
+
+ std::string StandardValue;
+ std::string RequiredValue;
+ std::string ExtensionValue;
+};
+}
+
static std::string const kCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN =
"CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN";
static std::string const kCMAKE_C_COMPILER_TARGET = "CMAKE_C_COMPILER_TARGET";
@@ -79,25 +221,6 @@ static std::set<std::string> ghs_platform_vars{
"GHS_OS_DIR_OPTION"
};
-static void writeProperty(FILE* fout, std::string const& targetName,
- std::string const& prop, std::string const& value)
-{
- fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n", targetName.c_str(),
- cmOutputConverter::EscapeForCMake(prop).c_str(),
- cmOutputConverter::EscapeForCMake(value).c_str());
-}
-
-std::string cmCoreTryCompile::LookupStdVar(std::string const& var,
- bool warnCMP0067)
-{
- std::string value = this->Makefile->GetSafeDefinition(var);
- if (warnCMP0067 && !value.empty()) {
- value.clear();
- this->WarnCMP0067.push_back(var);
- }
- return value;
-}
-
int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
bool isTryRun)
{
@@ -137,21 +260,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::string outputVariable;
std::string copyFile;
std::string copyFileError;
- std::string cStandard;
- std::string objcStandard;
- std::string cxxStandard;
- std::string objcxxStandard;
- std::string cudaStandard;
- std::string cStandardRequired;
- std::string cxxStandardRequired;
- std::string objcStandardRequired;
- std::string objcxxStandardRequired;
- std::string cudaStandardRequired;
- std::string cExtensions;
- std::string cxxExtensions;
- std::string objcExtensions;
- std::string objcxxExtensions;
- std::string cudaExtensions;
+ LanguageStandardState cState("C");
+ LanguageStandardState cudaState("CUDA");
+ LanguageStandardState cxxState("CXX");
+ LanguageStandardState objcState("OBJC");
+ LanguageStandardState objcxxState("OBJCXX");
std::vector<std::string> targets;
std::vector<std::string> linkOptions;
std::string libsToLink = " ";
@@ -160,21 +273,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
bool didOutputVariable = false;
bool didCopyFile = false;
bool didCopyFileError = false;
- bool didCStandard = false;
- bool didCxxStandard = false;
- bool didObjCStandard = false;
- bool didObjCxxStandard = false;
- bool didCudaStandard = false;
- bool didCStandardRequired = false;
- bool didCxxStandardRequired = false;
- bool didObjCStandardRequired = false;
- bool didObjCxxStandardRequired = false;
- bool didCudaStandardRequired = false;
- bool didCExtensions = false;
- bool didCxxExtensions = false;
- bool didObjCExtensions = false;
- bool didObjCxxExtensions = false;
- bool didCudaExtensions = false;
bool useSources = argv[2] == "SOURCES";
std::vector<std::string> sources;
@@ -188,21 +286,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
DoingOutputVariable,
DoingCopyFile,
DoingCopyFileError,
- DoingCStandard,
- DoingCxxStandard,
- DoingObjCStandard,
- DoingObjCxxStandard,
- DoingCudaStandard,
- DoingCStandardRequired,
- DoingCxxStandardRequired,
- DoingObjCStandardRequired,
- DoingObjCxxStandardRequired,
- DoingCudaStandardRequired,
- DoingCExtensions,
- DoingCxxExtensions,
- DoingObjCExtensions,
- DoingObjCxxExtensions,
- DoingCudaExtensions,
DoingSources,
DoingCMakeInternal
};
@@ -226,51 +309,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (argv[i] == "COPY_FILE_ERROR") {
doing = DoingCopyFileError;
didCopyFileError = true;
- } else if (argv[i] == "C_STANDARD") {
- doing = DoingCStandard;
- didCStandard = true;
- } else if (argv[i] == "CXX_STANDARD") {
- doing = DoingCxxStandard;
- didCxxStandard = true;
- } else if (argv[i] == "OBJC_STANDARD") {
- doing = DoingObjCStandard;
- didObjCStandard = true;
- } else if (argv[i] == "OBJCXX_STANDARD") {
- doing = DoingObjCxxStandard;
- didObjCxxStandard = true;
- } else if (argv[i] == "CUDA_STANDARD") {
- doing = DoingCudaStandard;
- didCudaStandard = true;
- } else if (argv[i] == "C_STANDARD_REQUIRED") {
- doing = DoingCStandardRequired;
- didCStandardRequired = true;
- } else if (argv[i] == "CXX_STANDARD_REQUIRED") {
- doing = DoingCxxStandardRequired;
- didCxxStandardRequired = true;
- } else if (argv[i] == "OBJC_STANDARD_REQUIRED") {
- doing = DoingObjCStandardRequired;
- didObjCStandardRequired = true;
- } else if (argv[i] == "OBJCXX_STANDARD_REQUIRED") {
- doing = DoingObjCxxStandardRequired;
- didObjCxxStandardRequired = true;
- } else if (argv[i] == "CUDA_STANDARD_REQUIRED") {
- doing = DoingCudaStandardRequired;
- didCudaStandardRequired = true;
- } else if (argv[i] == "C_EXTENSIONS") {
- doing = DoingCExtensions;
- didCExtensions = true;
- } else if (argv[i] == "CXX_EXTENSIONS") {
- doing = DoingCxxExtensions;
- didCxxExtensions = true;
- } else if (argv[i] == "OBJC_EXTENSIONS") {
- doing = DoingObjCExtensions;
- didObjCExtensions = true;
- } else if (argv[i] == "OBJCXX_EXTENSIONS") {
- doing = DoingObjCxxExtensions;
- didObjCxxExtensions = true;
- } else if (argv[i] == "CUDA_EXTENSIONS") {
- doing = DoingCudaExtensions;
- didCudaExtensions = true;
+ } else if (cState.UpdateIfMatches(argv, i) ||
+ cxxState.UpdateIfMatches(argv, i) ||
+ cudaState.UpdateIfMatches(argv, i) ||
+ objcState.UpdateIfMatches(argv, i) ||
+ objcxxState.UpdateIfMatches(argv, i)) {
+ continue;
} else if (argv[i] == "__CMAKE_INTERNAL") {
doing = DoingCMakeInternal;
} else if (doing == DoingCMakeFlags) {
@@ -315,51 +359,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (doing == DoingCopyFileError) {
copyFileError = argv[i];
doing = DoingNone;
- } else if (doing == DoingCStandard) {
- cStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCxxStandard) {
- cxxStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCStandard) {
- objcStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCxxStandard) {
- objcxxStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCudaStandard) {
- cudaStandard = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCStandardRequired) {
- cStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCxxStandardRequired) {
- cxxStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCStandardRequired) {
- objcStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCxxStandardRequired) {
- objcxxStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCudaStandardRequired) {
- cudaStandardRequired = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCExtensions) {
- cExtensions = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCxxExtensions) {
- cxxExtensions = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCExtensions) {
- objcExtensions = argv[i];
- doing = DoingNone;
- } else if (doing == DoingObjCxxExtensions) {
- objcxxExtensions = argv[i];
- doing = DoingNone;
- } else if (doing == DoingCudaExtensions) {
- cudaExtensions = argv[i];
- doing = DoingNone;
} else if (doing == DoingSources) {
sources.push_back(argv[i]);
} else if (doing == DoingCMakeInternal) {
@@ -411,59 +410,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
return -1;
}
- if (didCStandard && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "C_STANDARD allowed only in source file signature.");
- return -1;
- }
- if (didCxxStandard && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CXX_STANDARD allowed only in source file signature.");
- return -1;
- }
- if (didCudaStandard && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CUDA_STANDARD allowed only in source file signature.");
- return -1;
- }
- if (didCStandardRequired && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "C_STANDARD_REQUIRED allowed only in source file signature.");
- return -1;
- }
- if (didCxxStandardRequired && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CXX_STANDARD_REQUIRED allowed only in source file signature.");
- return -1;
- }
- if (didCudaStandardRequired && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CUDA_STANDARD_REQUIRED allowed only in source file signature.");
- return -1;
- }
- if (didCExtensions && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "C_EXTENSIONS allowed only in source file signature.");
- return -1;
- }
- if (didCxxExtensions && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CXX_EXTENSIONS allowed only in source file signature.");
- return -1;
- }
- if (didCudaExtensions && !this->SrcFileSignature) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- "CUDA_EXTENSIONS allowed only in source file signature.");
- return -1;
+ if (!this->SrcFileSignature) {
+ if (!cState.Validate(this->Makefile)) {
+ return -1;
+ }
+ if (!cudaState.Validate(this->Makefile)) {
+ return -1;
+ }
+ if (!cxxState.Validate(this->Makefile)) {
+ return -1;
+ }
+ if (!objcState.Validate(this->Makefile)) {
+ return -1;
+ }
+ if (!objcxxState.Validate(this->Makefile)) {
+ return -1;
+ }
}
// compute the binary dir when TRY_COMPILE is called with a src file
@@ -819,21 +781,17 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
fprintf(fout, ")\n");
- bool const testC = testLangs.find("C") != testLangs.end();
- bool const testObjC = testLangs.find("OBJC") != testLangs.end();
- bool const testCxx = testLangs.find("CXX") != testLangs.end();
- bool const testObjCxx = testLangs.find("OBJCXX") != testLangs.end();
- bool const testCuda = testLangs.find("CUDA") != testLangs.end();
+ cState.Enabled(testLangs.find("C") != testLangs.end());
+ cxxState.Enabled(testLangs.find("CXX") != testLangs.end());
+ cudaState.Enabled(testLangs.find("CUDA") != testLangs.end());
+ objcState.Enabled(testLangs.find("OBJC") != testLangs.end());
+ objcxxState.Enabled(testLangs.find("OBJCXX") != testLangs.end());
bool warnCMP0067 = false;
bool honorStandard = true;
- if (!didCStandard && !didCxxStandard && !didObjCStandard &&
- !didObjCxxStandard && !didCudaStandard && !didCStandardRequired &&
- !didCxxStandardRequired && !didObjCStandardRequired &&
- !didObjCxxStandardRequired && !didCudaStandardRequired &&
- !didCExtensions && !didCxxExtensions && !didObjCExtensions &&
- !didObjCxxExtensions && !didCudaExtensions) {
+ if (cState.DidNone() && cxxState.DidNone() && objcState.DidNone() &&
+ objcxxState.DidNone() && cudaState.DidNone()) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
case cmPolicies::WARN:
warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
@@ -855,46 +813,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
- if (honorStandard || warnCMP0067) {
+ std::vector<std::string> warnCMP0067Variables;
- auto testLanguage =
- [&](bool testLang, bool didLangStandard, bool didLangStandardRequired,
- bool didLangExtensions, std::string& langStandard,
- std::string& langStandardRequired, std::string& langExtensions,
- const std::string& lang) {
- if (testLang) {
- if (!didLangStandard) {
- langStandard = this->LookupStdVar(
- cmStrCat("CMAKE_", lang, "_STANDARD"), warnCMP0067);
- }
- if (!didLangStandardRequired) {
- langStandardRequired = this->LookupStdVar(
- cmStrCat("CMAKE_", lang, "_STANDARD_REQUIRED"), warnCMP0067);
- }
- if (!didLangExtensions) {
- langExtensions = this->LookupStdVar(
- cmStrCat("CMAKE_", lang, "_EXTENSIONS"), warnCMP0067);
- }
- }
- };
-
- testLanguage(testC, didCStandard, didCStandardRequired, didCExtensions,
- cStandard, cStandardRequired, cExtensions, "C");
- testLanguage(testObjC, didObjCStandard, didObjCStandardRequired,
- didObjCExtensions, objcStandard, objcStandardRequired,
- objcExtensions, "OBJC");
- testLanguage(testCxx, didCxxStandard, didCxxStandardRequired,
- didCxxExtensions, cxxStandard, cxxStandardRequired,
- cxxExtensions, "CXX");
- testLanguage(testObjCxx, didObjCxxStandard, didObjCxxStandardRequired,
- didObjCxxExtensions, objcxxStandard, objcxxStandardRequired,
- objcxxExtensions, "OBJCXX");
- testLanguage(testCuda, didCudaStandard, didCudaStandardRequired,
- didCudaExtensions, cudaStandard, cudaStandardRequired,
- cudaExtensions, "CUDA");
- }
+ cState.LoadUnsetPropertyValues(this->Makefile, honorStandard, warnCMP0067,
+ warnCMP0067Variables);
+ cxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
+ warnCMP0067, warnCMP0067Variables);
+ cudaState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
+ warnCMP0067, warnCMP0067Variables);
+ objcState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
+ warnCMP0067, warnCMP0067Variables);
+ objcxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard,
+ warnCMP0067, warnCMP0067Variables);
- if (!this->WarnCMP0067.empty()) {
+ if (!warnCMP0067Variables.empty()) {
std::ostringstream w;
/* clang-format off */
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0067) << "\n"
@@ -902,43 +834,17 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
"is not honoring language standard variables in the test project:\n"
;
/* clang-format on */
- for (std::string const& vi : this->WarnCMP0067) {
+ for (std::string const& vi : warnCMP0067Variables) {
w << " " << vi << "\n";
}
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
- auto writeLanguageProperties = [&](bool testLang,
- const std::string& langStandard,
- const std::string& langStandardRequired,
- const std::string& langExtensions,
- const std::string& lang) {
- if (testLang) {
- if (!langStandard.empty()) {
- writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD"),
- langStandard);
- }
- if (!langStandardRequired.empty()) {
- writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD_REQUIRED"),
- langStandardRequired);
- }
- if (!langExtensions.empty()) {
- writeProperty(fout, targetName, cmStrCat(lang, "_EXTENSIONS"),
- langExtensions);
- }
- }
- };
-
- writeLanguageProperties(testC, cStandard, cStandardRequired, cExtensions,
- "C");
- writeLanguageProperties(testObjC, objcStandard, objcStandardRequired,
- objcExtensions, "OBJC");
- writeLanguageProperties(testCxx, cxxStandard, cxxStandardRequired,
- cxxExtensions, "CXX");
- writeLanguageProperties(testObjCxx, objcxxStandard, objcxxStandardRequired,
- objcxxExtensions, "OBJCXX");
- writeLanguageProperties(testCuda, cudaStandard, cudaStandardRequired,
- cudaExtensions, "CUDA");
+ cState.WriteProperties(fout, targetName);
+ cxxState.WriteProperties(fout, targetName);
+ cudaState.WriteProperties(fout, targetName);
+ objcState.WriteProperties(fout, targetName);
+ objcxxState.WriteProperties(fout, targetName);
if (!linkOptions.empty()) {
std::vector<std::string> options;
@@ -1050,7 +956,9 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir)
std::set<std::string> deletedFiles;
for (unsigned long i = 0; i < dir.GetNumberOfFiles(); ++i) {
const char* fileName = dir.GetFile(i);
- if (strcmp(fileName, ".") != 0 && strcmp(fileName, "..") != 0) {
+ if (strcmp(fileName, ".") != 0 && strcmp(fileName, "..") != 0 &&
+ // Do not delete NFS temporary files.
+ !cmHasPrefix(fileName, ".nfs")) {
if (deletedFiles.insert(fileName).second) {
std::string const fullPath =
std::string(binDir).append("/").append(fileName);
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index ae714a6..916572a 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -47,10 +47,6 @@ protected:
std::string OutputFile;
std::string FindErrorMessage;
bool SrcFileSignature = false;
-
-private:
- std::vector<std::string> WarnCMP0067;
- std::string LookupStdVar(std::string const& var, bool warnCMP0067);
};
#endif
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index e4fb67e..3e0c21c 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1708,7 +1708,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
std::string error;
std::string lang;
if (!context->LG->GetMakefile()->CompileFeatureKnown(
- context->HeadTarget->Target, p, lang, &error)) {
+ context->HeadTarget->Target->GetName(), p, lang, &error)) {
reportError(context, content->GetOriginalExpression(), error);
return std::string();
}
@@ -1742,9 +1742,9 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
continue;
}
if (!context->LG->GetMakefile()->HaveStandardAvailable(
- target->Target, lit.first, it)) {
+ target, lit.first, context->Config, it)) {
if (evalLL) {
- cmProp l = target->GetProperty(lit.first + "_STANDARD");
+ cmProp l = target->GetLanguageStandard(lit.first, context->Config);
if (!l) {
l = standardDefault;
}
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index f2011ee..1f66a9f 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -947,6 +947,45 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
return it != this->ExplicitObjectName.end();
}
+cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang,
+ std::string const& config) const
+{
+ std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
+ auto langStandardIter = this->LanguageStandardMap.find(key);
+ if (langStandardIter != this->LanguageStandardMap.end()) {
+ return &langStandardIter->second;
+ }
+
+ return this->Target->GetProperty(cmStrCat(lang, "_STANDARD"));
+}
+
+cmProp cmGeneratorTarget::GetLanguageStandardProperty(std::string const& lang,
+ const char* suffix) const
+{
+ cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix));
+ if (propertyValue == nullptr) {
+ // Check if we should use the value set by another language.
+ if (lang == "OBJC") {
+ propertyValue = this->GetLanguageStandardProperty("C", suffix);
+ } else if (lang == "OBJCXX" || lang == "CUDA") {
+ propertyValue = this->GetLanguageStandardProperty("CXX", suffix);
+ }
+ }
+ return propertyValue;
+}
+
+cmProp cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const
+{
+ return this->GetLanguageStandardProperty(lang, "_EXTENSIONS");
+}
+
+bool cmGeneratorTarget::GetLanguageStandardRequired(
+ std::string const& lang) const
+{
+ cmProp p = this->GetLanguageStandardProperty(lang, "_STANDARD_REQUIRED");
+ return p && cmIsOn(*p);
+}
+
void cmGeneratorTarget::GetModuleDefinitionSources(
std::vector<cmSourceFile const*>& data, const std::string& config) const
{
@@ -4408,12 +4447,68 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
{
+ // Compute the language standard based on the compile features.
std::vector<BT<std::string>> features = this->GetCompileFeatures(config);
for (BT<std::string> const& f : features) {
- if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) {
+ std::string lang;
+ if (!this->Makefile->CompileFeatureKnown(this->Target->GetName(), f.Value,
+ lang, nullptr)) {
return false;
}
+
+ std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
+ cmProp currentLanguageStandard = this->GetLanguageStandard(lang, config);
+
+ std::string newRequiredStandard;
+ if (!this->Makefile->GetNewRequiredStandard(
+ this->Target->GetName(), f.Value, currentLanguageStandard,
+ newRequiredStandard)) {
+ return false;
+ }
+
+ if (!newRequiredStandard.empty()) {
+ this->LanguageStandardMap[key] = newRequiredStandard;
+ }
}
+
+ return true;
+}
+
+bool cmGeneratorTarget::ComputeCompileFeatures(
+ std::string const& config, std::set<LanguagePair> const& languagePairs) const
+{
+ for (const auto& language : languagePairs) {
+ cmProp generatorTargetLanguageStandard =
+ this->GetLanguageStandard(language.first, config);
+ if (!generatorTargetLanguageStandard) {
+ // If the standard isn't explicitly set we copy it over from the
+ // specified paired language.
+ std::string key =
+ cmStrCat(cmSystemTools::UpperCase(config), '-', language.first);
+ cmProp standardToCopy =
+ this->GetLanguageStandard(language.second, config);
+ if (standardToCopy != nullptr) {
+ this->LanguageStandardMap[key] = *standardToCopy;
+ generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
+ } else {
+ cmProp defaultStandard = this->Makefile->GetDef(
+ cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT"));
+ if (defaultStandard != nullptr) {
+ this->LanguageStandardMap[key] = *defaultStandard;
+ generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
+ }
+ }
+
+ // Custom updates for the CUDA standard.
+ if (generatorTargetLanguageStandard != nullptr &&
+ language.first == "CUDA") {
+ if (*generatorTargetLanguageStandard == "98") {
+ this->LanguageStandardMap[key] = "03";
+ }
+ }
+ }
+ }
+
return true;
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 3aedbf5..a71e64c 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -148,6 +148,13 @@ public:
bool HasExplicitObjectName(cmSourceFile const* file) const;
void AddExplicitObjectName(cmSourceFile const* sf);
+ cmProp GetLanguageStandard(std::string const& lang,
+ std::string const& config) const;
+
+ cmProp GetLanguageExtensions(std::string const& lang) const;
+
+ bool GetLanguageStandardRequired(std::string const& lang) const;
+
void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetExternalObjects(std::vector<cmSourceFile const*>&,
@@ -515,6 +522,11 @@ public:
bool ComputeCompileFeatures(std::string const& config) const;
+ using LanguagePair = std::pair<std::string, std::string>;
+ bool ComputeCompileFeatures(
+ std::string const& config,
+ std::set<LanguagePair> const& languagePairs) const;
+
/**
* Trace through the source files in this target and add al source files
* that they depend on, used by all generators
@@ -1038,6 +1050,11 @@ private:
bool GetRPATH(const std::string& config, const std::string& prop,
std::string& rpath) const;
+ mutable std::map<std::string, std::string> LanguageStandardMap;
+
+ cmProp GetLanguageStandardProperty(std::string const& lang,
+ const char* suffix) const;
+
public:
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
const std::string& config) const;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 1ed5e8b..4b4ffda 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1442,12 +1442,10 @@ bool cmGlobalGenerator::Compute()
localGen->AddHelperCommands();
}
- // Finalize the set of compile features for each target.
- // FIXME: This turns into calls to cmMakefile::AddRequiredTargetFeature
- // which actually modifies the <lang>_STANDARD target property
- // on the original cmTarget instance. It accumulates features
- // across all configurations. Some refactoring is needed to
- // compute a per-config resulta purely during generation.
+ // Perform up-front computation in order to handle errors (such as unknown
+ // features) at this point. While processing the compile features we also
+ // calculate and cache the language standard required by the compile
+ // features.
for (const auto& localGen : this->LocalGenerators) {
if (!localGen->ComputeTargetCompileFeatures()) {
return false;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 4d589ed..bb422eb 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1152,23 +1152,24 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
}
// organize the sources
- std::vector<cmSourceFile*> classes;
- if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ std::vector<cmSourceFile*> commonSourceFiles;
+ if (!gtgt->GetConfigCommonSourceFiles(commonSourceFiles)) {
return false;
}
// Add CMakeLists.txt file for user convenience.
- this->AddXCodeProjBuildRule(gtgt, classes);
+ this->AddXCodeProjBuildRule(gtgt, commonSourceFiles);
// Add the Info.plist we are about to generate for an App Bundle.
if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
std::string plist = this->ComputeInfoPListLocation(gtgt);
cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
plist, true, cmSourceFileLocationKind::Known);
- classes.push_back(sf);
+ commonSourceFiles.push_back(sf);
}
- std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
+ std::sort(commonSourceFiles.begin(), commonSourceFiles.end(),
+ cmSourceFilePathCompare());
gtgt->ComputeObjectMapping();
@@ -1176,7 +1177,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
std::vector<cmXCodeObject*> headerFiles;
std::vector<cmXCodeObject*> resourceFiles;
std::vector<cmXCodeObject*> sourceFiles;
- for (auto sourceFile : classes) {
+ for (auto sourceFile : commonSourceFiles) {
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
this->CurrentLocalGenerator, sourceFile, gtgt);
cmXCodeObject* fr = xsf->GetObject("fileRef");
@@ -1275,7 +1276,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
using mapOfVectorOfSourceFiles =
std::map<std::string, std::vector<cmSourceFile*>>;
mapOfVectorOfSourceFiles bundleFiles;
- for (auto sourceFile : classes) {
+ for (auto sourceFile : commonSourceFiles) {
cmGeneratorTarget::SourceFileFlags tsFlags =
gtgt->GetTargetSourceFileFlags(sourceFile);
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
@@ -1323,7 +1324,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
using mapOfVectorOfSourceFiles =
std::map<std::string, std::vector<cmSourceFile*>>;
mapOfVectorOfSourceFiles bundleFiles;
- for (auto sourceFile : classes) {
+ for (auto sourceFile : commonSourceFiles) {
cmGeneratorTarget::SourceFileFlags tsFlags =
gtgt->GetTargetSourceFileFlags(sourceFile);
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
@@ -1353,22 +1354,20 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
}
}
- // create framework build phase
+ // always create framework build phase
cmXCodeObject* frameworkBuildPhase = nullptr;
- if (!externalObjFiles.empty()) {
- frameworkBuildPhase =
- this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
- frameworkBuildPhase->SetComment("Frameworks");
- frameworkBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- frameworkBuildPhase->AddAttribute("files", buildFiles);
- for (auto& externalObjFile : externalObjFiles) {
- buildFiles->AddObject(externalObjFile);
- }
- frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- }
+ frameworkBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
+ frameworkBuildPhase->SetComment("Frameworks");
+ frameworkBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ frameworkBuildPhase->AddAttribute("files", buildFiles);
+ for (auto& externalObjFile : externalObjFiles) {
+ buildFiles->AddObject(externalObjFile);
+ }
+ frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
// create list of build phases and create the Xcode target
cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -2768,6 +2767,156 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
}
+ // Separate libraries into ones that can be linked using "Link Binary With
+ // Libraries" build phase and the ones that can't. Only targets that build
+ // Apple bundles (.app, .framework, .bundle) can use this feature and only
+ // targets that represent actual libraries (static or dynamic, local or
+ // imported) not objects and not executables will be used. These are
+ // limitations imposed by CMake use-cases - otherwise a lot of things break.
+ // The rest will be linked using linker flags (OTHER_LDFLAGS setting in Xcode
+ // project).
+ std::map<std::string, std::vector<cmComputeLinkInformation::Item const*>>
+ configItemMap;
+ auto addToLinkerArguments =
+ [&configItemMap](const std::string& configName,
+ cmComputeLinkInformation::Item const* libItemPtr) {
+ auto& linkVector = configItemMap[configName];
+ if (std::find_if(linkVector.begin(), linkVector.end(),
+ [libItemPtr](cmComputeLinkInformation::Item const* p) {
+ return p == libItemPtr;
+ }) == linkVector.end()) {
+ linkVector.push_back(libItemPtr);
+ }
+ };
+ std::vector<cmComputeLinkInformation::Item const*> linkPhaseTargetVector;
+ std::map<std::string, std::vector<std::string>> targetConfigMap;
+ using ConfigItemPair =
+ std::pair<std::string, cmComputeLinkInformation::Item const*>;
+ std::map<std::string, std::vector<ConfigItemPair>> targetItemMap;
+ std::map<std::string, std::vector<std::string>> targetProductNameMap;
+ for (auto const& configName : this->CurrentConfigurationTypes) {
+ cmComputeLinkInformation* cli = gt->GetLinkInformation(configName);
+ if (!cli) {
+ continue;
+ }
+ for (auto const& libItem : cli->GetItems()) {
+ // TODO: Drop this check once we have option to add outside libraries to
+ // Xcode project
+ auto* libTarget = FindXCodeTarget(libItem.Target);
+ if (gt->IsBundleOnApple() &&
+ (gt->GetType() == cmStateEnums::EXECUTABLE ||
+ gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ gt->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ gt->GetType() == cmStateEnums::UNKNOWN_LIBRARY) &&
+ (libTarget && libItem.Target &&
+ (libItem.Target->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ libItem.Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ libItem.Target->GetType() == cmStateEnums::MODULE_LIBRARY))) {
+ // Add unique configuration name to target-config map for later
+ // checks
+ std::string libName = libItem.Target->GetName();
+ auto& configVector = targetConfigMap[libName];
+ if (std::find(configVector.begin(), configVector.end(), configName) ==
+ configVector.end()) {
+ configVector.push_back(configName);
+ }
+ // Add a pair of config and item to target-item map
+ auto& itemVector = targetItemMap[libName];
+ itemVector.emplace_back(ConfigItemPair(configName, &libItem));
+ // Add product file-name to a lib-product map
+ auto productName = cmSystemTools::GetFilenameName(libItem.Value.Value);
+ auto& productVector = targetProductNameMap[libName];
+ if (std::find(productVector.begin(), productVector.end(),
+ productName) == productVector.end()) {
+ productVector.push_back(productName);
+ }
+ } else {
+ // Add this library item to a regular linker flag list
+ addToLinkerArguments(configName, &libItem);
+ }
+ }
+ }
+
+ // Go through target library map and separate libraries that are linked
+ // in all configurations and produce only single product, from the rest.
+ // Only these will be linked through "Link Binary With Libraries" build
+ // phase.
+ for (auto const& targetLibConfigs : targetConfigMap) {
+ // Add this library to "Link Binary With Libraries" build phase if it's
+ // linked in all configurations and it has only one product name
+ auto& itemVector = targetItemMap[targetLibConfigs.first];
+ auto& productVector = targetProductNameMap[targetLibConfigs.first];
+ if (targetLibConfigs.second == this->CurrentConfigurationTypes &&
+ productVector.size() == 1) {
+ // Add this library to "Link Binary With Libraries" list
+ linkPhaseTargetVector.push_back(itemVector[0].second);
+ } else {
+ for (auto const& libItem : targetItemMap[targetLibConfigs.first]) {
+ // Add this library item to a regular linker flag list
+ addToLinkerArguments(libItem.first, libItem.second);
+ }
+ }
+ }
+
+ // Add libraries to "Link Binary With Libraries" build phase and collect
+ // their search paths. Xcode does not support per-configuration linking
+ // in this build phase so we don't have to do this for each configuration
+ // separately.
+ std::vector<std::string> linkSearchPaths;
+ for (auto const& libItem : linkPhaseTargetVector) {
+ // Add target output directory as a library search path
+ std::string linkDir = cmSystemTools::GetParentDirectory(
+ libItem->Target->GetLocationForBuild());
+ if (std::find(linkSearchPaths.begin(), linkSearchPaths.end(), linkDir) ==
+ linkSearchPaths.end()) {
+ linkSearchPaths.push_back(linkDir);
+ }
+ // Add target dependency
+ auto const& libName = *libItem;
+ if (!libName.Target->IsImported()) {
+ for (auto const& configName : this->CurrentConfigurationTypes) {
+ target->AddDependTarget(configName, libName.Target->GetName());
+ }
+ }
+ // Get the library target
+ auto* libTarget = FindXCodeTarget(libItem->Target);
+ if (!libTarget) {
+ continue;
+ }
+ // Add the target output file as a build reference for other targets
+ // to link against
+ auto* fileRefObject = libTarget->GetObject("productReference");
+ if (!fileRefObject) {
+ continue;
+ }
+ cmXCodeObject* buildFile;
+ auto it = FileRefToBuildFileMap.find(fileRefObject);
+ if (it == FileRefToBuildFileMap.end()) {
+ buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
+ buildFile->AddAttribute("fileRef", fileRefObject);
+ FileRefToBuildFileMap[fileRefObject] = buildFile;
+ } else {
+ buildFile = it->second;
+ }
+ // Add this reference to current target
+ auto* buildPhases = target->GetObject("buildPhases");
+ if (!buildPhases) {
+ continue;
+ }
+ auto* frameworkBuildPhase =
+ buildPhases->GetObject(cmXCodeObject::PBXFrameworksBuildPhase);
+ if (!frameworkBuildPhase) {
+ continue;
+ }
+ auto* buildFiles = frameworkBuildPhase->GetObject("files");
+ if (!buildFiles) {
+ continue;
+ }
+ if (!buildFiles->HasObject(buildFile)) {
+ buildFiles->AddObject(buildFile);
+ }
+ }
+
// Loop over configuration types and set per-configuration info.
for (auto const& configName : this->CurrentConfigurationTypes) {
{
@@ -2795,21 +2944,20 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
// Compute the link library and directory information.
- cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
- if (!pcli) {
+ cmComputeLinkInformation* cli = gt->GetLinkInformation(configName);
+ if (!cli) {
continue;
}
- cmComputeLinkInformation& cli = *pcli;
// Add dependencies directly on library files.
- for (auto const& libDep : cli.GetDepends()) {
+ for (auto const& libDep : cli->GetDepends()) {
target->AddDependLibrary(configName, libDep);
}
// add the library search paths
{
std::string linkDirs;
- for (auto const& libDir : cli.GetDirectories()) {
+ for (auto const& libDir : cli->GetDirectories()) {
if (!libDir.empty() && libDir != "/usr/lib") {
// Now add the same one but append
// $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
@@ -2820,15 +2968,22 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
linkDirs += this->XCodeEscapePath(libDir);
}
}
+ // Add previously collected paths where to look for libraries
+ // that were added to "Link Binary With Libraries"
+ for (auto& linkDir : linkSearchPaths) {
+ linkDirs += " ";
+ linkDirs += this->XCodeEscapePath(linkDir);
+ }
this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
linkDirs.c_str(), configName);
}
- // now add the link libraries
+ // now add the left-over link libraries
{
std::string linkLibs;
const char* sep = "";
- for (auto const& libName : cli.GetItems()) {
+ for (auto const& libItem : configItemMap[configName]) {
+ auto const& libName = *libItem;
linkLibs += sep;
sep = " ";
if (libName.IsPath) {
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index e380f1c..0fc6558 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -28,7 +28,7 @@ struct cmDocumentationEntry;
/** \class cmGlobalXCodeGenerator
* \brief Write a Unix makefiles.
*
- * cmGlobalXCodeGenerator manages UNIX build process for a tree
+ * cmGlobalXCodeGenerator manages Xcode build process for a tree
*/
class cmGlobalXCodeGenerator : public cmGlobalGenerator
{
@@ -295,6 +295,7 @@ private:
std::map<std::string, cmXCodeObject*> TargetGroup;
std::map<std::string, cmXCodeObject*> FileRefs;
std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap;
+ std::map<cmXCodeObject*, cmXCodeObject*> FileRefToBuildFileMap;
std::vector<std::string> Architectures;
std::string ObjectDirArchDefault;
std::string ObjectDirArch;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3b3f110..95caa30 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -803,39 +803,8 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures()
// Now that C/C++ _STANDARD values have been computed
// set the values to ObjC/ObjCXX _STANDARD variables
if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- auto copyStandardToObjLang = [&](LanguagePair const& lang) -> bool {
- if (!target->GetProperty(cmStrCat(lang.first, "_STANDARD"))) {
- cmProp standard =
- target->GetProperty(cmStrCat(lang.second, "_STANDARD"));
- if (!standard) {
- standard = this->Makefile->GetDef(
- cmStrCat("CMAKE_", lang.second, "_STANDARD_DEFAULT"));
- }
- target->Target->SetProperty(cmStrCat(lang.first, "_STANDARD"),
- standard ? standard->c_str() : nullptr);
- return true;
- }
- return false;
- };
- auto copyPropertyToObjLang = [&](LanguagePair const& lang,
- const char* property) {
- if (!target->GetProperty(cmStrCat(lang.first, property)) &&
- target->GetProperty(cmStrCat(lang.second, property))) {
- cmProp p = target->GetProperty(cmStrCat(lang.second, property));
- target->Target->SetProperty(cmStrCat(lang.first, property),
- p ? p->c_str() : nullptr);
- }
- };
- for (auto const& lang : pairedLanguages) {
- if (copyStandardToObjLang(lang)) {
- copyPropertyToObjLang(lang, "_STANDARD_REQUIRED");
- copyPropertyToObjLang(lang, "_EXTENSIONS");
- }
- }
- if (cmProp standard = target->GetProperty("CUDA_STANDARD")) {
- if (*standard == "98") {
- target->Target->SetProperty("CUDA_STANDARD", "03");
- }
+ for (std::string const& c : configNames) {
+ target->ComputeCompileFeatures(c, inferredEnabledLanguages);
}
}
}
@@ -1026,7 +995,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
}
for (auto const& it : target->GetMaxLanguageStandards()) {
- cmProp standard = target->GetProperty(it.first + "_STANDARD");
+ cmProp standard = target->GetLanguageStandard(it.first, config);
if (!standard) {
continue;
}
@@ -1050,7 +1019,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
}
std::string compReqFlag;
- this->AddCompilerRequirementFlag(compReqFlag, target, lang);
+ this->AddCompilerRequirementFlag(compReqFlag, target, lang, config);
if (!compReqFlag.empty()) {
flags.emplace_back(std::move(compReqFlag));
}
@@ -2046,7 +2015,7 @@ void cmLocalGenerator::AddLanguageFlagsForLinking(
// when linking in order to use the matching standard library.
// FIXME: If CMake gains an abstraction for standard library
// selection, this will have to be reconciled with it.
- this->AddCompilerRequirementFlag(flags, target, lang);
+ this->AddCompilerRequirementFlag(flags, target, lang, config);
}
this->AddLanguageFlags(flags, target, lang, config);
@@ -2189,7 +2158,8 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
}
void cmLocalGenerator::AddCompilerRequirementFlag(
- std::string& flags, cmGeneratorTarget const* target, const std::string& lang)
+ std::string& flags, cmGeneratorTarget const* target, const std::string& lang,
+ const std::string& config)
{
if (lang.empty()) {
return;
@@ -2200,15 +2170,13 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
// This compiler has no notion of language standard levels.
return;
}
- std::string extProp = lang + "_EXTENSIONS";
bool ext = true;
- if (cmProp extPropValue = target->GetProperty(extProp)) {
+ if (cmProp extPropValue = target->GetLanguageExtensions(lang)) {
if (cmIsOff(*extPropValue)) {
ext = false;
}
}
- std::string stdProp = lang + "_STANDARD";
- cmProp standardProp = target->GetProperty(stdProp);
+ cmProp standardProp = target->GetLanguageStandard(lang, config);
if (!standardProp) {
if (ext) {
// No language standard is specified and extensions are not disabled.
@@ -2228,7 +2196,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
std::string const type = ext ? "EXTENSION" : "STANDARD";
- if (target->GetPropertyAsBool(lang + "_STANDARD_REQUIRED")) {
+ if (target->GetLanguageStandardRequired(lang)) {
std::string option_flag =
"CMAKE_" + lang + *standardProp + "_" + type + "_COMPILE_OPTION";
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index f2d9145..f4781d6 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -123,7 +123,8 @@ public:
const std::string& config);
void AddCompilerRequirementFlag(std::string& flags,
cmGeneratorTarget const* target,
- const std::string& lang);
+ const std::string& lang,
+ const std::string& config);
//! Append flags to a string.
virtual void AppendFlags(std::string& flags,
const std::string& newFlags) const;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 5c3063b..1f1c06a 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -39,6 +39,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionEvaluationFile.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallGenerator.h" // IWYU pragma: keep
#include "cmInstallSubdirectoryGenerator.h"
@@ -4027,6 +4028,8 @@ int cmMakefile::ConfigureFile(const std::string& infile,
if (copyonly) {
if (!cmSystemTools::CopyFileIfDifferent(sinfile, soutfile)) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ cmSystemTools::GetLastSystemError());
return 0;
}
} else {
@@ -4077,9 +4080,15 @@ int cmMakefile::ConfigureFile(const std::string& infile,
fin.close();
fout.close();
if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile, soutfile)) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ cmSystemTools::GetLastSystemError());
res = 0;
} else {
- cmSystemTools::SetPermissions(soutfile, perm);
+ if (!cmSystemTools::SetPermissions(soutfile, perm)) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ cmSystemTools::GetLastSystemError());
+ res = 0;
+ }
}
cmSystemTools::RemoveFile(tempOutputFile);
}
@@ -4673,7 +4682,33 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
}
std::string lang;
- if (!this->CompileFeatureKnown(target, feature, lang, error)) {
+ if (!this->CheckCompileFeaturesAvailable(target->GetName(), feature, lang,
+ error)) {
+ return false;
+ }
+
+ target->AppendProperty("COMPILE_FEATURES", feature);
+
+ // FIXME: Add a policy to avoid updating the <LANG>_STANDARD target
+ // property due to COMPILE_FEATURES. The language standard selection
+ // should be done purely at generate time based on whatever the project
+ // code put in these properties explicitly. That is mostly true now,
+ // but for compatibility we need to continue updating the property here.
+ if (lang == "C" || lang == "OBJC") {
+ return this->AddRequiredTargetCFeature(target, feature, lang, error);
+ }
+ if (lang == "CUDA") {
+ return this->AddRequiredTargetCudaFeature(target, feature, lang, error);
+ }
+ return this->AddRequiredTargetCxxFeature(target, feature, lang, error);
+}
+
+bool cmMakefile::CheckCompileFeaturesAvailable(const std::string& targetName,
+ const std::string& feature,
+ std::string& lang,
+ std::string* error) const
+{
+ if (!this->CompileFeatureKnown(targetName, feature, lang, error)) {
return false;
}
@@ -4699,18 +4734,10 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
return false;
}
- target->AppendProperty("COMPILE_FEATURES", feature);
-
- if (lang == "C" || lang == "OBJC") {
- return this->AddRequiredTargetCFeature(target, feature, lang, error);
- }
- if (lang == "CUDA") {
- return this->AddRequiredTargetCudaFeature(target, feature, lang, error);
- }
- return this->AddRequiredTargetCxxFeature(target, feature, lang, error);
+ return true;
}
-bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
+bool cmMakefile::CompileFeatureKnown(const std::string& targetName,
const std::string& feature,
std::string& lang,
std::string* error) const
@@ -4747,7 +4774,7 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
e << " unknown feature \"" << feature
<< "\" for "
"target \""
- << target->GetName() << "\".";
+ << targetName << "\".";
if (error) {
*error = e.str();
} else {
@@ -4802,22 +4829,50 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang,
return featuresKnown;
}
-bool cmMakefile::HaveStandardAvailable(cmTarget const* target,
+bool cmMakefile::GetNewRequiredStandard(const std::string& targetName,
+ const std::string& feature,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error) const
+{
+ std::string lang;
+ if (!this->CheckCompileFeaturesAvailable(targetName, feature, lang, error)) {
+ return false;
+ }
+
+ if (lang == "C" || lang == "OBJC") {
+ return this->GetNewRequiredCStandard(targetName, feature, lang,
+ currentLangStandardValue,
+ newRequiredStandard, error);
+ }
+ if (lang == "CUDA") {
+ return this->GetNewRequiredCudaStandard(targetName, feature, lang,
+ currentLangStandardValue,
+ newRequiredStandard, error);
+ }
+ return this->GetNewRequiredCxxStandard(targetName, feature, lang,
+ currentLangStandardValue,
+ newRequiredStandard, error);
+}
+
+bool cmMakefile::HaveStandardAvailable(cmGeneratorTarget const* target,
std::string const& lang,
+ std::string const& config,
const std::string& feature) const
{
if (lang == "C" || lang == "OBJC") {
- return this->HaveCStandardAvailable(target, feature, lang);
+ return this->HaveCStandardAvailable(target, lang, config, feature);
}
if (lang == "CUDA") {
- return this->HaveCudaStandardAvailable(target, feature, lang);
+ return this->HaveCudaStandardAvailable(target, lang, config, feature);
}
- return this->HaveCxxStandardAvailable(target, feature, lang);
+ return this->HaveCxxStandardAvailable(target, lang, config, feature);
}
-bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const
+bool cmMakefile::HaveCStandardAvailable(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config,
+ const std::string& feature) const
{
cmProp defaultCStandard =
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
@@ -4846,7 +4901,7 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
- cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD"));
+ cmProp existingCStandard = target->GetLanguageStandard(lang, config);
if (!existingCStandard) {
existingCStandard = defaultCStandard;
}
@@ -4909,9 +4964,10 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
cm::cend(CXX_STANDARDS);
}
-bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const
+bool cmMakefile::HaveCxxStandardAvailable(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config,
+ const std::string& feature) const
{
cmProp defaultCxxStandard =
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
@@ -4941,8 +4997,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
needCxx17, needCxx20);
- cmProp existingCxxStandard =
- target->GetProperty(cmStrCat(lang, "_STANDARD"));
+ cmProp existingCxxStandard = target->GetLanguageStandard(lang, config);
if (!existingCxxStandard) {
existingCxxStandard = defaultCxxStandard;
}
@@ -5009,6 +5064,29 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
std::string const& lang,
std::string* error) const
{
+ std::string newRequiredStandard;
+ if (this->GetNewRequiredCxxStandard(
+ target->GetName(), feature, lang,
+ target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard,
+ error)) {
+ if (!newRequiredStandard.empty()) {
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool cmMakefile::GetNewRequiredCxxStandard(const std::string& targetName,
+ const std::string& feature,
+ std::string const& lang,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error) const
+{
+ newRequiredStandard.clear();
+
bool needCxx98 = false;
bool needCxx11 = false;
bool needCxx14 = false;
@@ -5018,8 +5096,7 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
needCxx17, needCxx20);
- cmProp existingCxxStandard =
- target->GetProperty(cmStrCat(lang, "_STANDARD"));
+ cmProp existingCxxStandard = currentLangStandardValue;
if (existingCxxStandard == nullptr) {
cmProp defaultCxxStandard =
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
@@ -5034,7 +5111,7 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
cmStrCmp(*existingCxxStandard));
if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "The ", lang, "_STANDARD property on target \"", targetName,
"\" contained an invalid value: \"", *existingCxxStandard, "\".");
if (error) {
*error = e;
@@ -5060,16 +5137,17 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
// Ensure the C++ language level is high enough to support
// the needed C++ features.
if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
- target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel);
+ newRequiredStandard = *needCxxLevel;
}
}
return true;
}
-bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const
+bool cmMakefile::HaveCudaStandardAvailable(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config,
+ const std::string& feature) const
{
cmProp defaultCudaStandard =
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
@@ -5100,8 +5178,7 @@ bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target,
this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
needCuda14, needCuda17, needCuda20);
- cmProp existingCudaStandard =
- target->GetProperty(cmStrCat(lang, "_STANDARD"));
+ cmProp existingCudaStandard = target->GetLanguageStandard(lang, config);
if (!existingCudaStandard) {
existingCudaStandard = defaultCudaStandard;
}
@@ -5168,6 +5245,28 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
std::string const& lang,
std::string* error) const
{
+ std::string newRequiredStandard;
+ if (this->GetNewRequiredCudaStandard(
+ target->GetName(), feature, lang,
+ target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard,
+ error)) {
+ if (!newRequiredStandard.empty()) {
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool cmMakefile::GetNewRequiredCudaStandard(const std::string& targetName,
+ const std::string& feature,
+ std::string const& lang,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error) const
+{
+ newRequiredStandard.clear();
+
bool needCuda03 = false;
bool needCuda11 = false;
bool needCuda14 = false;
@@ -5177,8 +5276,7 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
needCuda14, needCuda17, needCuda20);
- cmProp existingCudaStandard =
- target->GetProperty(cmStrCat(lang, "_STANDARD"));
+ cmProp existingCudaStandard = currentLangStandardValue;
if (existingCudaStandard == nullptr) {
cmProp defaultCudaStandard =
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
@@ -5193,7 +5291,7 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
cmStrCmp(*existingCudaStandard));
if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) {
const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "The ", lang, "_STANDARD property on target \"", targetName,
"\" contained an invalid value: \"", *existingCudaStandard, "\".");
if (error) {
*error = e;
@@ -5219,7 +5317,7 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
// Ensure the CUDA language level is high enough to support
// the needed CUDA features.
if (!existingCudaLevel || existingCudaLevel < needCudaLevel) {
- target->SetProperty("CUDA_STANDARD", *needCudaLevel);
+ newRequiredStandard = *needCudaLevel;
}
}
@@ -5252,13 +5350,36 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
std::string const& lang,
std::string* error) const
{
+ std::string newRequiredStandard;
+ if (this->GetNewRequiredCStandard(
+ target->GetName(), feature, lang,
+ target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard,
+ error)) {
+ if (!newRequiredStandard.empty()) {
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool cmMakefile::GetNewRequiredCStandard(const std::string& targetName,
+ const std::string& feature,
+ std::string const& lang,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error) const
+{
+ newRequiredStandard.clear();
+
bool needC90 = false;
bool needC99 = false;
bool needC11 = false;
this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
- cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD"));
+ cmProp existingCStandard = currentLangStandardValue;
if (existingCStandard == nullptr) {
cmProp defaultCStandard =
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
@@ -5270,7 +5391,7 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) {
const std::string e = cmStrCat(
- "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "The ", lang, "_STANDARD property on target \"", targetName,
"\" contained an invalid value: \"", *existingCStandard, "\".");
if (error) {
*error = e;
@@ -5307,11 +5428,11 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
}
if (setC11) {
- target->SetProperty(cmStrCat(lang, "_STANDARD"), "11");
+ newRequiredStandard = "11";
} else if (setC99) {
- target->SetProperty(cmStrCat(lang, "_STANDARD"), "99");
+ newRequiredStandard = "99";
} else if (setC90) {
- target->SetProperty(cmStrCat(lang, "_STANDARD"), "90");
+ newRequiredStandard = "90";
}
return true;
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 45d7109..332554e 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -47,6 +47,7 @@ class cmExpandedCommandArgument;
class cmExportBuildFileGenerator;
class cmFunctionBlocker;
class cmGeneratorExpressionEvaluationFile;
+class cmGeneratorTarget;
class cmGlobalGenerator;
class cmImplicitDependsList;
class cmInstallGenerator;
@@ -928,13 +929,22 @@ public:
bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature,
std::string* error = nullptr) const;
- bool CompileFeatureKnown(cmTarget const* target, const std::string& feature,
- std::string& lang, std::string* error) const;
+ bool CompileFeatureKnown(const std::string& targetName,
+ const std::string& feature, std::string& lang,
+ std::string* error) const;
const char* CompileFeaturesAvailable(const std::string& lang,
std::string* error) const;
- bool HaveStandardAvailable(cmTarget const* target, std::string const& lang,
+ bool GetNewRequiredStandard(const std::string& targetName,
+ const std::string& feature,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error = nullptr) const;
+
+ bool HaveStandardAvailable(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config,
const std::string& feature) const;
bool IsLaterStandard(std::string const& lang, std::string const& lhs,
@@ -1174,6 +1184,11 @@ private:
std::string const& lang,
std::string* error = nullptr) const;
+ bool CheckCompileFeaturesAvailable(const std::string& targetName,
+ const std::string& feature,
+ std::string& lang,
+ std::string* error) const;
+
void CheckNeededCLanguage(const std::string& feature,
std::string const& lang, bool& needC90,
bool& needC99, bool& needC11) const;
@@ -1186,15 +1201,37 @@ private:
bool& needCuda11, bool& needCuda14,
bool& needCuda17, bool& needCuda20) const;
- bool HaveCStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const;
- bool HaveCxxStandardAvailable(cmTarget const* target,
- const std::string& feature,
- std::string const& lang) const;
- bool HaveCudaStandardAvailable(cmTarget const* target,
+ bool GetNewRequiredCStandard(const std::string& targetName,
+ const std::string& feature,
+ std::string const& lang,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error = nullptr) const;
+ bool GetNewRequiredCxxStandard(const std::string& targetName,
const std::string& feature,
- std::string const& lang) const;
+ std::string const& lang,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error = nullptr) const;
+ bool GetNewRequiredCudaStandard(const std::string& targetName,
+ const std::string& feature,
+ std::string const& lang,
+ cmProp currentLangStandardValue,
+ std::string& newRequiredStandard,
+ std::string* error = nullptr) const;
+
+ bool HaveCStandardAvailable(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config,
+ const std::string& feature) const;
+ bool HaveCxxStandardAvailable(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config,
+ const std::string& feature) const;
+ bool HaveCudaStandardAvailable(cmGeneratorTarget const* target,
+ std::string const& lang,
+ std::string const& config,
+ const std::string& feature) const;
void CheckForUnusedVariables() const;
diff --git a/Tests/Cuda/Toolkit/CMakeLists.txt b/Tests/Cuda/Toolkit/CMakeLists.txt
index 86b4652..00125e3 100644
--- a/Tests/Cuda/Toolkit/CMakeLists.txt
+++ b/Tests/Cuda/Toolkit/CMakeLists.txt
@@ -14,15 +14,29 @@ message(STATUS "CUDAToolkit_INCLUDE_DIRS: ${CUDAToolkit_INCLUDE_DIRS}")
message(STATUS "CUDAToolkit_LIBRARY_DIR: ${CUDAToolkit_LIBRARY_DIR}")
message(STATUS "CUDAToolkit_NVCC_EXECUTABLE ${CUDAToolkit_NVCC_EXECUTABLE}")
-# Verify that all the CUDA:: targets exist even when the CUDA language isn't enabled
+set(cuda_libs cudart cuda_driver cublas cufft cufftw curand cusolver cusparse)
+if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.1)
+ list(APPEND cuda_libs cublasLt)
+endif()
+if(CUDAToolkit_VERSION_MAJOR VERSION_LESS 11)
+ list(APPEND cuda_libs nvgraph)
+endif()
-foreach (cuda_lib cudart cuda_driver cublas cufft cufftw curand cusolver cusparse nvgraph)
+# Verify that all the CUDA:: targets exist even when the CUDA language isn't enabled
+foreach (cuda_lib IN LISTS cuda_libs)
+ if(NOT CUDA_${cuda_lib}_LIBRARY)
+ message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found")
+ endif()
if(NOT TARGET CUDA::${cuda_lib})
- message(FATAL_ERROR "The CUDA::${cuda_lib} target was expected but couldn't be found")
+ message(FATAL_ERROR "expected CUDAToolkit target CUDA::${cuda_lib} not found")
endif()
endforeach()
-foreach (cuda_lib nppc nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppicom nppisu)
+set(npp_libs nppc nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppisu)
+if(CUDAToolkit_VERSION_MAJOR VERSION_LESS 11)
+ list(APPEND npp_libs nppicom)
+endif()
+foreach (cuda_lib IN LISTS npp_libs)
if(NOT TARGET CUDA::${cuda_lib})
message(FATAL_ERROR "The CUDA::${cuda_lib} target was expected but couldn't be found")
endif()
diff --git a/Tests/CudaOnly/Toolkit/CMakeLists.txt b/Tests/CudaOnly/Toolkit/CMakeLists.txt
index 0d5d574..bb06ba8 100644
--- a/Tests/CudaOnly/Toolkit/CMakeLists.txt
+++ b/Tests/CudaOnly/Toolkit/CMakeLists.txt
@@ -11,8 +11,17 @@ message(STATUS "CUDAToolkit_INCLUDE_DIRS: ${CUDAToolkit_INCLUDE_DIRS}")
message(STATUS "CUDAToolkit_LIBRARY_DIR: ${CUDAToolkit_LIBRARY_DIR}")
message(STATUS "CUDAToolkit_NVCC_EXECUTABLE ${CUDAToolkit_NVCC_EXECUTABLE}")
+
+set(cuda_libs cudart cuda_driver cublas cufft cufftw curand cusolver cusparse)
+if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.1)
+ list(APPEND cuda_libs cublasLt)
+endif()
+if(CUDAToolkit_VERSION_MAJOR VERSION_LESS 11)
+ list(APPEND cuda_libs nvgraph)
+endif()
+
# Verify that all the CUDA:: targets and variables exist
-foreach (cuda_lib cudart cuda_driver cublas cufft cufftw curand cusolver cusparse nvgraph)
+foreach (cuda_lib IN LISTS cuda_libs)
if(NOT CUDA_${cuda_lib}_LIBRARY)
message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found")
endif()
@@ -21,7 +30,11 @@ foreach (cuda_lib cudart cuda_driver cublas cufft cufftw curand cusolver cuspars
endif()
endforeach()
-foreach (cuda_lib nppc nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppicom nppisu)
+set(npp_libs nppc nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppisu)
+if(CUDAToolkit_VERSION_MAJOR VERSION_LESS 11)
+ list(APPEND npp_libs nppicom)
+endif()
+foreach (cuda_lib )
if(NOT CUDA_${cuda_lib}_LIBRARY)
message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found")
endif()
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 866e7c0..6c634b5 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -494,6 +494,9 @@ add_RunCMake_test(File_Generate)
add_RunCMake_test(ExportWithoutLanguage)
add_RunCMake_test(target_link_directories)
add_RunCMake_test(target_link_libraries)
+add_RunCMake_test(target_link_libraries-ALIAS)
+add_RunCMake_test(target_link_libraries-LINK_LANGUAGE)
+add_RunCMake_test(target_link_libraries-LINK_LANG_AND_ID)
add_RunCMake_test(add_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
add_RunCMake_test(target_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
-DCMake_TEST_CUDA=${CMake_TEST_CUDA})
diff --git a/Tests/RunCMake/target_link_libraries/AliasTargets.cmake b/Tests/RunCMake/target_link_libraries-ALIAS/AliasTargets.cmake
index 73f8a7d..73f8a7d 100644
--- a/Tests/RunCMake/target_link_libraries/AliasTargets.cmake
+++ b/Tests/RunCMake/target_link_libraries-ALIAS/AliasTargets.cmake
diff --git a/Tests/RunCMake/target_link_libraries-ALIAS/CMakeLists.txt b/Tests/RunCMake/target_link_libraries-ALIAS/CMakeLists.txt
new file mode 100644
index 0000000..9cf020f
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-ALIAS/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.1)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
diff --git a/Tests/RunCMake/target_link_libraries-ALIAS/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-ALIAS/RunCMakeTest.cmake
new file mode 100644
index 0000000..4d24a6e
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-ALIAS/RunCMakeTest.cmake
@@ -0,0 +1,23 @@
+include(RunCMake)
+
+macro(run_cmake_target test subtest target)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+endif()
+run_cmake(AliasTargets)
+run_cmake_target(AliasTargets func func --config Release)
+run_cmake_target(AliasTargets lib-local lib-local --config Release)
+run_cmake_target(AliasTargets main-local main-local --config Release)
+run_cmake_target(AliasTargets lib-global lib-global --config Release)
+run_cmake_target(AliasTargets main-global main-global --config Release)
+unset(RunCMake_TEST_OPTIONS)
+unset(RunCMake_TEST_OUTPUT_MERGE)
diff --git a/Tests/RunCMake/target_link_libraries/func.c b/Tests/RunCMake/target_link_libraries-ALIAS/func.c
index 415a9bf..415a9bf 100644
--- a/Tests/RunCMake/target_link_libraries/func.c
+++ b/Tests/RunCMake/target_link_libraries-ALIAS/func.c
diff --git a/Tests/RunCMake/target_link_libraries-ALIAS/lib.c b/Tests/RunCMake/target_link_libraries-ALIAS/lib.c
new file mode 100644
index 0000000..b2d1b66
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-ALIAS/lib.c
@@ -0,0 +1,10 @@
+
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+ void func_c();
+
+void lib()
+{
+ func_c();
+}
diff --git a/Tests/RunCMake/target_link_libraries/main.c b/Tests/RunCMake/target_link_libraries-ALIAS/main.c
index a908dea..a908dea 100644
--- a/Tests/RunCMake/target_link_libraries/main.c
+++ b/Tests/RunCMake/target_link_libraries-ALIAS/main.c
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/CMakeLists.txt b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/CMakeLists.txt
new file mode 100644
index 0000000..9cf020f
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.1)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake
new file mode 100644
index 0000000..0f0e5d8
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake
@@ -0,0 +1,41 @@
+include(RunCMake)
+
+macro(run_cmake_target test subtest target)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+run_cmake(bad-usage)
+
+if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Visual Studio|Xcode|Watcom WMake")
+
+ run_cmake(bad-mix-lang)
+
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+ endif()
+
+ run_cmake(genex)
+
+ run_cmake_target(genex lib LinkLibraries_lib --config Release)
+ run_cmake_target(genex lib2 LinkLibraries_lib2 --config Release)
+ run_cmake_target(genex lib3 LinkLibraries_lib3 --config Release)
+ run_cmake_target(genex exe LinkLibraries_exe --config Release)
+ run_cmake_target(genex C_import LinkLibraries_C_import --config Release)
+ run_cmake_target(genex CXX_import LinkLibraries_CXX_import --config Release)
+ run_cmake_target(genex C_interface LinkLibraries_C_interface --config Release)
+ run_cmake_target(genex CXX_interface LinkLibraries_CXX_interface --config Release)
+ run_cmake_target(genex C_interface2 LinkLibraries_C_interface2 --config Release)
+ run_cmake_target(genex CXX_interface2 LinkLibraries_CXX_interface2 --config Release)
+ run_cmake_target(genex C_static LinkLibraries_C_static --config Release)
+ run_cmake_target(genex CXX_static LinkLibraries_CXX_static --config Release)
+
+ unset(RunCMake_TEST_OPTIONS)
+ unset(RunCMake_TEST_OUTPUT_MERGE)
+
+endif()
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang-result.txt b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang-result.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang-result.txt
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang-stderr.txt b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang-stderr.txt
index 2ecdc0c..2ecdc0c 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang-stderr.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang-stderr.txt
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang.cmake
index e8efa75..e8efa75 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-mix-lang.cmake
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage-result.txt b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage-result.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage-result.txt
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage-stderr.txt b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage-stderr.txt
index 469f1fe..d61f789 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage-stderr.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at genex_LINK_LANGUAGE-bad-usage.cmake:4 \(target_link_libraries\):
+CMake Error at bad-usage.cmake:4 \(target_link_libraries\):
Error evaluating generator expression:
\$<LINK_LANGUAGE>
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage.cmake
index 81cfb0c..81cfb0c 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-usage.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/bad-usage.cmake
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/empty.c b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/empty.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/empty.c
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.c b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.c
new file mode 100644
index 0000000..415a9bf
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.c
@@ -0,0 +1,7 @@
+
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ void func_c()
+{
+}
diff --git a/Tests/RunCMake/target_link_libraries/func.cxx b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.cxx
index a12caca..a12caca 100644
--- a/Tests/RunCMake/target_link_libraries/func.cxx
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.cxx
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/genex.cmake
index f3fe955..f3fe955 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/genex.cmake
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/lib.c b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/lib.c
new file mode 100644
index 0000000..b2d1b66
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/lib.c
@@ -0,0 +1,10 @@
+
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+ void func_c();
+
+void lib()
+{
+ func_c();
+}
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c
new file mode 100644
index 0000000..a908dea
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c
@@ -0,0 +1,12 @@
+
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+ void func_c();
+
+int main()
+{
+ func_c();
+
+ return 0;
+}
diff --git a/Tests/RunCMake/target_link_libraries/main.cxx b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.cxx
index ffaa3b4..ffaa3b4 100644
--- a/Tests/RunCMake/target_link_libraries/main.cxx
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.cxx
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/CMakeLists.txt b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/CMakeLists.txt
new file mode 100644
index 0000000..9cf020f
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.1)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/RunCMakeTest.cmake
new file mode 100644
index 0000000..3b16f9e
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/RunCMakeTest.cmake
@@ -0,0 +1,38 @@
+include(RunCMake)
+
+macro(run_cmake_target test subtest target)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Visual Studio|Xcode|Watcom WMake")
+
+ run_cmake(bad-mix-lang)
+
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+ endif()
+
+ run_cmake(genex)
+
+ run_cmake_target(genex lib LinkLibraries_lib --config Release)
+ run_cmake_target(genex lib2 LinkLibraries_lib2 --config Release)
+ run_cmake_target(genex lib3 LinkLibraries_lib3 --config Release)
+ run_cmake_target(genex exe LinkLibraries_exe --config Release)
+ run_cmake_target(genex C_import LinkLibraries_C_import --config Release)
+ run_cmake_target(genex CXX_import LinkLibraries_CXX_import --config Release)
+ run_cmake_target(genex C_interface LinkLibraries_C_interface --config Release)
+ run_cmake_target(genex CXX_interface LinkLibraries_CXX_interface --config Release)
+ run_cmake_target(genex C_interface2 LinkLibraries_C_interface2 --config Release)
+ run_cmake_target(genex CXX_interface2 LinkLibraries_CXX_interface2 --config Release)
+ run_cmake_target(genex CXX_static LinkLibraries_CXX_static --config Release)
+
+ unset(RunCMake_TEST_OPTIONS)
+ unset(RunCMake_TEST_OUTPUT_MERGE)
+
+endif()
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang-result.txt b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang-result.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang-result.txt
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang-stderr.txt b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang-stderr.txt
index 2ecdc0c..2ecdc0c 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANGUAGE-bad-mix-lang-stderr.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang-stderr.txt
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang.cmake
index f80010a..f80010a 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-bad-mix-lang.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/bad-mix-lang.cmake
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-interface-result.txt b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/basic-result.txt
index 8d98f9d..8d98f9d 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-interface-result.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/basic-result.txt
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/empty.c b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/empty.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/empty.c
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-exe_cxx-result.txt b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/exe_c-result.txt
index 8d98f9d..8d98f9d 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-exe_cxx-result.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/exe_c-result.txt
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-exe_c-result.txt b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/exe_cxx-result.txt
index 8d98f9d..8d98f9d 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-exe_c-result.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/exe_cxx-result.txt
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/func.c b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/func.c
new file mode 100644
index 0000000..415a9bf
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/func.c
@@ -0,0 +1,7 @@
+
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ void func_c()
+{
+}
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/func.cxx b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/func.cxx
new file mode 100644
index 0000000..a12caca
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/func.cxx
@@ -0,0 +1,7 @@
+
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ void func_cxx()
+{
+}
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/genex.cmake
index 9feccd0..9feccd0 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/genex.cmake
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-basic-result.txt b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/interface-result.txt
index 8d98f9d..8d98f9d 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-basic-result.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/interface-result.txt
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/lib.c b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/lib.c
new file mode 100644
index 0000000..b2d1b66
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/lib.c
@@ -0,0 +1,10 @@
+
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+ void func_c();
+
+void lib()
+{
+ func_c();
+}
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/main.c b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/main.c
new file mode 100644
index 0000000..a908dea
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/main.c
@@ -0,0 +1,12 @@
+
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+ void func_c();
+
+int main()
+{
+ func_c();
+
+ return 0;
+}
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/main.cxx b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/main.cxx
new file mode 100644
index 0000000..ffaa3b4
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/main.cxx
@@ -0,0 +1,12 @@
+
+#if defined(_WIN32)
+__declspec(dllimport)
+#endif
+ void func_cxx();
+
+int main()
+{
+ func_cxx();
+
+ return 0;
+}
diff --git a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-no_language-result.txt b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/no_language-result.txt
index 573541a..573541a 100644
--- a/Tests/RunCMake/target_link_libraries/genex_LINK_LANG_AND_ID-no_language-result.txt
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANG_AND_ID/no_language-result.txt
diff --git a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
index 1f4077c..189592d 100644
--- a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
@@ -30,71 +30,3 @@ run_cmake(StaticPrivateDepNotExported)
run_cmake(StaticPrivateDepNotTarget)
run_cmake(UNKNOWN-IMPORTED-GLOBAL)
run_cmake(empty_keyword_args)
-
-macro(run_cmake_target test subtest target)
- set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
- set(RunCMake_TEST_NO_CLEAN 1)
- run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
-
- unset(RunCMake_TEST_BINARY_DIR)
- unset(RunCMake_TEST_NO_CLEAN)
-endmacro()
-
-set(RunCMake_TEST_OUTPUT_MERGE TRUE)
-if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
- set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
-endif()
-run_cmake(AliasTargets)
-run_cmake_target(AliasTargets func func --config Release)
-run_cmake_target(AliasTargets lib-local lib-local --config Release)
-run_cmake_target(AliasTargets main-local main-local --config Release)
-run_cmake_target(AliasTargets lib-global lib-global --config Release)
-run_cmake_target(AliasTargets main-global main-global --config Release)
-unset(RunCMake_TEST_OPTIONS)
-unset(RunCMake_TEST_OUTPUT_MERGE)
-
-run_cmake(genex_LINK_LANGUAGE-bad-usage)
-
-if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Visual Studio|Xcode|Watcom WMake")
-
- run_cmake(genex_LINK_LANGUAGE-bad-mix-lang)
- run_cmake(genex_LINK_LANG_AND_ID-bad-mix-lang)
-
- set(RunCMake_TEST_OUTPUT_MERGE TRUE)
- if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
- set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
- endif()
-
- run_cmake(genex_LINK_LANGUAGE)
-
- run_cmake_target(genex_LINK_LANGUAGE lib LinkLibraries_lib --config Release)
- run_cmake_target(genex_LINK_LANGUAGE lib2 LinkLibraries_lib2 --config Release)
- run_cmake_target(genex_LINK_LANGUAGE lib3 LinkLibraries_lib3 --config Release)
- run_cmake_target(genex_LINK_LANGUAGE exe LinkLibraries_exe --config Release)
- run_cmake_target(genex_LINK_LANGUAGE C_import LinkLibraries_C_import --config Release)
- run_cmake_target(genex_LINK_LANGUAGE CXX_import LinkLibraries_CXX_import --config Release)
- run_cmake_target(genex_LINK_LANGUAGE C_interface LinkLibraries_C_interface --config Release)
- run_cmake_target(genex_LINK_LANGUAGE CXX_interface LinkLibraries_CXX_interface --config Release)
- run_cmake_target(genex_LINK_LANGUAGE C_interface2 LinkLibraries_C_interface2 --config Release)
- run_cmake_target(genex_LINK_LANGUAGE CXX_interface2 LinkLibraries_CXX_interface2 --config Release)
- run_cmake_target(genex_LINK_LANGUAGE C_static LinkLibraries_C_static --config Release)
- run_cmake_target(genex_LINK_LANGUAGE CXX_static LinkLibraries_CXX_static --config Release)
-
- run_cmake(genex_LINK_LANG_AND_ID)
-
- run_cmake_target(genex_LINK_LANG_AND_ID lib LinkLibraries_lib --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID lib2 LinkLibraries_lib2 --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID lib3 LinkLibraries_lib3 --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID exe LinkLibraries_exe --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID C_import LinkLibraries_C_import --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID CXX_import LinkLibraries_CXX_import --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID C_interface LinkLibraries_C_interface --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID CXX_interface LinkLibraries_CXX_interface --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID C_interface2 LinkLibraries_C_interface2 --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID CXX_interface2 LinkLibraries_CXX_interface2 --config Release)
- run_cmake_target(genex_LINK_LANG_AND_ID CXX_static LinkLibraries_CXX_static --config Release)
-
- unset(RunCMake_TEST_OPTIONS)
- unset(RunCMake_TEST_OUTPUT_MERGE)
-
-endif()