diff options
-rw-r--r-- | Help/manual/cmake-generator-expressions.7.rst | 7 | ||||
-rw-r--r-- | Help/release/dev/build-local-interface-genex.rst | 5 | ||||
-rw-r--r-- | Source/cmGeneratorExpression.cxx | 52 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 3 | ||||
-rw-r--r-- | Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-export.cmake | 14 | ||||
-rw-r--r-- | Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake | 9 | ||||
-rw-r--r-- | Tests/RunCMake/ExportImport/RunCMakeTest.cmake | 25 | ||||
-rw-r--r-- | Tests/RunCMake/ExportImport/buildlib.c | 8 | ||||
-rw-r--r-- | Tests/RunCMake/ExportImport/installlib.c | 8 | ||||
-rw-r--r-- | Tests/RunCMake/ExportImport/locallib.c | 8 |
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) +{ +} |