summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst18
-rw-r--r--Help/prop_tgt/IMPORTED_CONFIGURATIONS.rst25
-rw-r--r--Help/prop_tgt/IMPORTED_IMPLIB.rst9
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmGeneratorExpressionNode.cxx56
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake15
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared-check.cmake15
-rw-r--r--Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake13
8 files changed, 117 insertions, 36 deletions
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 66ae6ae..a640c13 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -1922,7 +1922,9 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
List of DLLs that the target depends on at runtime. This is determined by
the locations of all the ``SHARED`` targets in the target's transitive
- dependencies. Using this generator expression on targets other than
+ dependencies. If only the directories of the DLLs are needed, see the
+ :genex:`TARGET_RUNTIME_DLL_DIRS` generator expression.
+ Using this generator expression on targets other than
executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error.
**On non-DLL platforms, this expression always evaluates to an empty string**.
@@ -1954,6 +1956,20 @@ On platforms that support runtime paths (``RPATH``), refer to the
:prop_tgt:`INSTALL_RPATH` target property.
On Apple platforms, refer to the :prop_tgt:`INSTALL_NAME_DIR` target property.
+.. genex:: $<TARGET_RUNTIME_DLL_DIRS:tgt>
+
+ .. versionadded:: 3.27
+
+ List of the directories which contain the DLLs that the target depends on at
+ runtime (see :genex:`TARGET_RUNTIME_DLLS`). This is determined by
+ the locations of all the ``SHARED`` targets in the target's transitive
+ dependencies. Using this generator expression on targets other than
+ executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error.
+ **On non-DLL platforms, this expression always evaluates to an empty string**.
+
+ This generator expression can e.g. be used to create a batch file using
+ :command:`file(GENERATE)` which sets the PATH environment variable accordingly.
+
Export And Install Expressions
------------------------------
diff --git a/Help/prop_tgt/IMPORTED_CONFIGURATIONS.rst b/Help/prop_tgt/IMPORTED_CONFIGURATIONS.rst
index 6de1baa..8605548 100644
--- a/Help/prop_tgt/IMPORTED_CONFIGURATIONS.rst
+++ b/Help/prop_tgt/IMPORTED_CONFIGURATIONS.rst
@@ -1,11 +1,20 @@
IMPORTED_CONFIGURATIONS
-----------------------
-Configurations provided for an IMPORTED target.
-
-Set this to the list of configuration names available for an IMPORTED
-target. The names correspond to configurations defined in the project
-from which the target is imported. If the importing project uses a
-different set of configurations the names may be mapped using the
-MAP_IMPORTED_CONFIG_<CONFIG> property. Ignored for non-imported
-targets.
+Configurations provided for an :ref:`imported target <Imported targets>`.
+
+Set this to the list of configuration names available for an imported
+target. For each configuration named, the imported target's artifacts
+must be specified in other target properties:
+
+* :prop_tgt:`IMPORTED_LOCATION_<CONFIG>`, or
+* :prop_tgt:`IMPORTED_IMPLIB_<CONFIG>` (on DLL platforms), or
+* :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` (for :ref:`Object Libraries`), or
+* :prop_tgt:`IMPORTED_LIBNAME_<CONFIG>` (for :ref:`Interface Libraries`).
+
+The configuration names correspond to those defined in the project from
+which the target is imported. If the importing project uses a different
+set of configurations, the names may be mapped using the
+:prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` target property.
+
+The ``IMPORTED_CONFIGURATIONS`` property is ignored for non-imported targets.
diff --git a/Help/prop_tgt/IMPORTED_IMPLIB.rst b/Help/prop_tgt/IMPORTED_IMPLIB.rst
index 77549f3..e67acba 100644
--- a/Help/prop_tgt/IMPORTED_IMPLIB.rst
+++ b/Help/prop_tgt/IMPORTED_IMPLIB.rst
@@ -12,4 +12,13 @@ This property may be set:
the :prop_tgt:`ENABLE_EXPORTS` target property). For frameworks this is the
location of the ``.tbd`` file symlink just inside the framework folder.
+The ``IMPORTED_IMPLIB`` target property may be overridden for a
+given configuration ``<CONFIG>`` by the configuration-specific
+:prop_tgt:`IMPORTED_IMPLIB_<CONFIG>` target property. Furthermore,
+the :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` target property may be
+used to map between a project's configurations and those of an imported
+target. If none of these is set then the name of any other configuration
+listed in the :prop_tgt:`IMPORTED_CONFIGURATIONS` target property may be
+selected and its :prop_tgt:`IMPORTED_IMPLIB_<CONFIG>` value used.
+
This property is ignored for non-imported targets.
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 827273c..b86fe1d 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 26)
-set(CMake_VERSION_PATCH 20230302)
+set(CMake_VERSION_PATCH 20230303)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 2a01c9e..6e78f55 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -2402,15 +2402,12 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
}
} targetObjectsNode;
-static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode
+struct TargetRuntimeDllsBaseNode : public cmGeneratorExpressionNode
{
- TargetRuntimeDllsNode() {} // NOLINT(modernize-use-equals-default)
-
- std::string Evaluate(
+ std::vector<std::string> CollectDlls(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ const GeneratorExpressionContent* content) const
{
std::string const& tgtName = parameters.front();
cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
@@ -2419,7 +2416,7 @@ static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode
e << "Objects of target \"" << tgtName
<< "\" referenced but no such target exists.";
reportError(context, content->GetOriginalExpression(), e.str());
- return std::string();
+ return std::vector<std::string>();
}
cmStateEnums::TargetType type = gt->GetType();
if (type != cmStateEnums::EXECUTABLE &&
@@ -2430,7 +2427,7 @@ static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode
<< "\" referenced but is not one of the allowed target types "
<< "(EXECUTABLE, SHARED, MODULE).";
reportError(context, content->GetOriginalExpression(), e.str());
- return std::string();
+ return std::vector<std::string>();
}
if (auto* cli = gt->GetLinkInformation(context->Config)) {
@@ -2443,13 +2440,51 @@ static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode
}
}
- return cmJoin(dllPaths, ";");
+ return dllPaths;
}
- return "";
+ return std::vector<std::string>();
+ }
+};
+
+static const struct TargetRuntimeDllsNode : public TargetRuntimeDllsBaseNode
+{
+ TargetRuntimeDllsNode() {} // NOLINT(modernize-use-equals-default)
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ std::vector<std::string> dlls = CollectDlls(parameters, context, content);
+ return cmJoin(dlls, ";");
}
} targetRuntimeDllsNode;
+static const struct TargetRuntimeDllDirsNode : public TargetRuntimeDllsBaseNode
+{
+ TargetRuntimeDllDirsNode() {} // NOLINT(modernize-use-equals-default)
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ std::vector<std::string> dlls = CollectDlls(parameters, context, content);
+ std::vector<std::string> dllDirs;
+ for (const std::string& dll : dlls) {
+ std::string directory = cmSystemTools::GetFilenamePath(dll);
+ if (std::find(dllDirs.begin(), dllDirs.end(), directory) ==
+ dllDirs.end()) {
+ dllDirs.push_back(directory);
+ }
+ }
+ return cmJoin(dllDirs, ";");
+ }
+} targetRuntimeDllDirsNode;
+
static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
{
CompileFeaturesNode() {} // NOLINT(modernize-use-equals-default)
@@ -3774,6 +3809,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "TARGET_NAME_IF_EXISTS", &targetNameIfExistsNode },
{ "TARGET_GENEX_EVAL", &targetGenexEvalNode },
{ "TARGET_RUNTIME_DLLS", &targetRuntimeDllsNode },
+ { "TARGET_RUNTIME_DLL_DIRS", &targetRuntimeDllDirsNode },
{ "GENEX_EVAL", &genexEvalNode },
{ "BUILD_INTERFACE", &buildInterfaceNode },
{ "INSTALL_INTERFACE", &installInterfaceNode },
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake
deleted file mode 100644
index e19598e..0000000
--- a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake
+++ /dev/null
@@ -1,15 +0,0 @@
-function(check_genex expected actual)
- if(NOT expected STREQUAL actual)
- string(APPEND RunCMake_TEST_FAILED "Expected DLLs:\n")
- foreach(dll IN LISTS expected)
- string(APPEND RunCMake_TEST_FAILED " ${dll}\n")
- endforeach()
- string(APPEND RunCMake_TEST_FAILED "Actual DLLs:\n")
- foreach(dll IN LISTS actual)
- string(APPEND RunCMake_TEST_FAILED " ${dll}\n")
- endforeach()
- endif()
- set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
-endfunction()
-
-include("${RunCMake_TEST_BINARY_DIR}/dlls.cmake")
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared-check.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared-check.cmake
new file mode 100644
index 0000000..6b05b4e
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared-check.cmake
@@ -0,0 +1,15 @@
+function(check_genex expected actual)
+ if(NOT expected STREQUAL actual)
+ string(APPEND RunCMake_TEST_FAILED "Expected items:\n")
+ foreach(item IN LISTS expected)
+ string(APPEND RunCMake_TEST_FAILED " ${item}\n")
+ endforeach()
+ string(APPEND RunCMake_TEST_FAILED "Actual items:\n")
+ foreach(item IN LISTS actual)
+ string(APPEND RunCMake_TEST_FAILED " ${item}\n")
+ endforeach()
+ endif()
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction()
+
+include("${RunCMake_TEST_BINARY_DIR}/dlls.cmake")
diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake
index 806f0b6..c38fa39 100644
--- a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake
+++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake
@@ -4,6 +4,10 @@ add_executable(exe main.c)
add_library(lib1 SHARED lib1.c)
add_library(lib2 SHARED lib2.c)
add_library(lib3 SHARED lib3.c)
+if(WIN32 OR CYGWIN)
+ set_property(TARGET lib3 PROPERTY RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/SomeSubDir/")
+endif()
+
add_library(static STATIC static.c)
add_library(imported SHARED IMPORTED)
set_property(TARGET imported PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/imported.dll")
@@ -26,9 +30,16 @@ if(WIN32 OR CYGWIN)
"$<TARGET_FILE:lib3>"
"$<TARGET_FILE:lib2>"
)
+ set(expected_dll_dirs
+ "$<PATH:GET_PARENT_PATH,$<TARGET_FILE:lib2>>"
+ "$<PATH:GET_PARENT_PATH,$<TARGET_FILE:imported>>"
+ "$<PATH:GET_PARENT_PATH,$<TARGET_FILE:lib3>>"
+ )
endif()
-set(content "check_genex(\"${expected_dlls}\" \"$<TARGET_RUNTIME_DLLS:exe>\")\n")
+set(content "check_genex(\"${expected_dlls}\" \"$<TARGET_RUNTIME_DLLS:exe>\")
+check_genex(\"${expected_dll_dirs}\" \"$<TARGET_RUNTIME_DLL_DIRS:exe>\")\n")
+
set(condition)
get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(multi_config)