summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst7
-rw-r--r--Help/release/dev/build-local-interface-genex.rst5
-rw-r--r--Source/cmGeneratorExpression.cxx52
-rw-r--r--Source/cmGeneratorExpressionNode.cxx3
-rw-r--r--Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-export.cmake14
-rw-r--r--Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake9
-rw-r--r--Tests/RunCMake/ExportImport/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/ExportImport/buildlib.c8
-rw-r--r--Tests/RunCMake/ExportImport/installlib.c8
-rw-r--r--Tests/RunCMake/ExportImport/locallib.c8
10 files changed, 123 insertions, 16 deletions
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index eb57b1e..a72eac1 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -1711,6 +1711,13 @@ Export And Install Expressions
when the target is used by another target in the same buildsystem. Expands to
the empty string otherwise.
+.. genex:: $<BUILD_LOCAL_INTERFACE:...>
+
+ .. versionadded:: 3.26
+
+ Content of ``...`` when the target is used by another target in the same
+ buildsystem. Expands to the empty string otherwise.
+
.. genex:: $<INSTALL_PREFIX>
Content of the install prefix when the target is exported via
diff --git a/Help/release/dev/build-local-interface-genex.rst b/Help/release/dev/build-local-interface-genex.rst
new file mode 100644
index 0000000..7fe702e
--- /dev/null
+++ b/Help/release/dev/build-local-interface-genex.rst
@@ -0,0 +1,5 @@
+build-local-interface-genex
+---------------------------
+
+* The :genex:`BUILD_LOCAL_INTERFACE` generator expression was added to
+ prevent usage requirements from being exported to dependent projects.
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 21ace89..b605350 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpression.h"
+#include <algorithm>
#include <cassert>
#include <memory>
#include <utility>
@@ -226,23 +227,33 @@ static std::string stripExportInterface(
while (true) {
std::string::size_type bPos = input.find("$<BUILD_INTERFACE:", lastPos);
std::string::size_type iPos = input.find("$<INSTALL_INTERFACE:", lastPos);
+ std::string::size_type lPos =
+ input.find("$<BUILD_LOCAL_INTERFACE:", lastPos);
- if (bPos == std::string::npos && iPos == std::string::npos) {
+ pos = std::min({ bPos, iPos, lPos });
+ if (pos == std::string::npos) {
break;
}
- if (bPos == std::string::npos) {
- pos = iPos;
- } else if (iPos == std::string::npos) {
- pos = bPos;
+ result += input.substr(lastPos, pos - lastPos);
+ enum class FoundGenex
+ {
+ BuildInterface,
+ InstallInterface,
+ BuildLocalInterface,
+ } foundGenex = FoundGenex::BuildInterface;
+ if (pos == bPos) {
+ foundGenex = FoundGenex::BuildInterface;
+ pos += cmStrLen("$<BUILD_INTERFACE:");
+ } else if (pos == iPos) {
+ foundGenex = FoundGenex::InstallInterface;
+ pos += cmStrLen("$<INSTALL_INTERFACE:");
+ } else if (pos == lPos) {
+ foundGenex = FoundGenex::BuildLocalInterface;
+ pos += cmStrLen("$<BUILD_LOCAL_INTERFACE:");
} else {
- pos = (bPos < iPos) ? bPos : iPos;
+ assert(false && "Invalid position found");
}
-
- result += input.substr(lastPos, pos - lastPos);
- const bool gotInstallInterface = input[pos + 2] == 'I';
- pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1
- : sizeof("$<BUILD_INTERFACE:") - 1;
nestingLevel = 1;
const char* c = input.c_str() + pos;
const char* const cStart = c;
@@ -258,10 +269,10 @@ static std::string stripExportInterface(
continue;
}
if (context == cmGeneratorExpression::BuildInterface &&
- !gotInstallInterface) {
+ foundGenex == FoundGenex::BuildInterface) {
result += input.substr(pos, c - cStart);
} else if (context == cmGeneratorExpression::InstallInterface &&
- gotInstallInterface) {
+ foundGenex == FoundGenex::InstallInterface) {
const std::string content = input.substr(pos, c - cStart);
if (resolveRelative) {
prefixItems(content, result, "${_IMPORT_PREFIX}/");
@@ -274,9 +285,18 @@ static std::string stripExportInterface(
}
const std::string::size_type traversed = (c - cStart) + 1;
if (!*c) {
- result += std::string(gotInstallInterface ? "$<INSTALL_INTERFACE:"
- : "$<BUILD_INTERFACE:") +
- input.substr(pos, traversed);
+ auto remaining = input.substr(pos, traversed);
+ switch (foundGenex) {
+ case FoundGenex::BuildInterface:
+ result = cmStrCat(result, "$<BUILD_INTERFACE:", remaining);
+ break;
+ case FoundGenex::InstallInterface:
+ result = cmStrCat(result, "$<INSTALL_INTERFACE:", remaining);
+ break;
+ case FoundGenex::BuildLocalInterface:
+ result = cmStrCat(result, "$<BUILD_LOCAL_INTERFACE:", remaining);
+ break;
+ }
}
pos += traversed;
lastPos = pos;
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 81629c6..c14012e 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -114,6 +114,8 @@ static const struct OneNode buildInterfaceNode;
static const struct ZeroNode installInterfaceNode;
+static const struct OneNode buildLocalInterfaceNode;
+
struct BooleanOpNode : public cmGeneratorExpressionNode
{
BooleanOpNode(const char* op_, const char* successVal_,
@@ -3323,6 +3325,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "GENEX_EVAL", &genexEvalNode },
{ "BUILD_INTERFACE", &buildInterfaceNode },
{ "INSTALL_INTERFACE", &installInterfaceNode },
+ { "BUILD_LOCAL_INTERFACE", &buildLocalInterfaceNode },
{ "INSTALL_PREFIX", &installPrefixNode },
{ "JOIN", &joinNode },
{ "LINK_ONLY", &linkOnlyNode },
diff --git a/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-export.cmake b/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-export.cmake
new file mode 100644
index 0000000..94076bb
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-export.cmake
@@ -0,0 +1,14 @@
+enable_language(C)
+
+add_library(mainlib STATIC foo.c)
+target_compile_definitions(mainlib INTERFACE
+ $<BUILD_LOCAL_INTERFACE:BUILD_LOCAL_INTERFACE>
+ $<BUILD_INTERFACE:BUILD_INTERFACE>
+ $<INSTALL_INTERFACE:INSTALL_INTERFACE>
+ )
+add_library(locallib STATIC locallib.c)
+target_link_libraries(locallib PRIVATE mainlib)
+
+install(TARGETS mainlib EXPORT export)
+install(EXPORT export DESTINATION lib/cmake/install FILE install-config.cmake NAMESPACE install::)
+export(EXPORT export FILE build-config.cmake NAMESPACE build::)
diff --git a/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake b/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake
new file mode 100644
index 0000000..3fe5fae
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+find_package(build REQUIRED)
+find_package(install REQUIRED)
+
+add_library(buildlib STATIC buildlib.c)
+target_link_libraries(buildlib PRIVATE build::mainlib)
+add_library(installlib STATIC installlib.c)
+target_link_libraries(installlib PRIVATE install::mainlib)
diff --git a/Tests/RunCMake/ExportImport/RunCMakeTest.cmake b/Tests/RunCMake/ExportImport/RunCMakeTest.cmake
index d07fca2..b730047 100644
--- a/Tests/RunCMake/ExportImport/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExportImport/RunCMakeTest.cmake
@@ -22,3 +22,28 @@ function(run_ExportImport_test case)
endfunction()
run_ExportImport_test(SharedDep)
+
+function(run_ExportImportBuildInstall_test case)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-export-build)
+ set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+ endif()
+ run_cmake(${case}-export)
+ unset(RunCMake_TEST_OPTIONS)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${case}-export-build ${CMAKE_COMMAND} --build . --config Debug)
+ run_cmake_command(${case}-export-install ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -P cmake_install.cmake)
+ unset(RunCMake_TEST_NO_CLEAN)
+
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-import-build)
+ run_cmake_with_options(${case}-import
+ -Dbuild_DIR=${RunCMake_BINARY_DIR}/${case}-export-build
+ -Dinstall_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/install
+ )
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${case}-import-build ${CMAKE_COMMAND} --build . --config Debug)
+ unset(RunCMake_TEST_NO_CLEAN)
+endfunction()
+
+run_ExportImportBuildInstall_test(BuildInstallInterfaceGenex)
diff --git a/Tests/RunCMake/ExportImport/buildlib.c b/Tests/RunCMake/ExportImport/buildlib.c
new file mode 100644
index 0000000..ac19310
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/buildlib.c
@@ -0,0 +1,8 @@
+#if !(!defined(BUILD_LOCAL_INTERFACE) && defined(BUILD_INTERFACE) && \
+ !defined(INSTALL_INTERFACE))
+# error "Incorrect compile definitions"
+#endif
+
+void buildlib(void)
+{
+}
diff --git a/Tests/RunCMake/ExportImport/installlib.c b/Tests/RunCMake/ExportImport/installlib.c
new file mode 100644
index 0000000..00d503c
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/installlib.c
@@ -0,0 +1,8 @@
+#if !(!defined(BUILD_LOCAL_INTERFACE) && !defined(BUILD_INTERFACE) && \
+ defined(INSTALL_INTERFACE))
+# error "Incorrect compile definitions"
+#endif
+
+void installlib(void)
+{
+}
diff --git a/Tests/RunCMake/ExportImport/locallib.c b/Tests/RunCMake/ExportImport/locallib.c
new file mode 100644
index 0000000..f9e3d8d
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/locallib.c
@@ -0,0 +1,8 @@
+#if !(defined(BUILD_LOCAL_INTERFACE) && defined(BUILD_INTERFACE) && \
+ !defined(INSTALL_INTERFACE))
+# error "Incorrect compile definitions"
+#endif
+
+void locallib(void)
+{
+}