Browse Source

Merge topic 'build-local-interface-genex'

38cbf5e15b Genex: Add $<BUILD_LOCAL_INTERFACE:...> genex
37b5c78688 cmGeneratorExpression: Refactor stripExportInterface() to use enum class

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !7919
Brad King 3 years ago
parent
commit
e558beeef6

+ 7 - 0
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
   when the target is used by another target in the same buildsystem. Expands to
   the empty string otherwise.
   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>
 .. genex:: $<INSTALL_PREFIX>
 
 
   Content of the install prefix when the target is exported via
   Content of the install prefix when the target is exported via

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

+ 36 - 16
Source/cmGeneratorExpression.cxx

@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorExpression.h"
 
 
+#include <algorithm>
 #include <cassert>
 #include <cassert>
 #include <memory>
 #include <memory>
 #include <utility>
 #include <utility>
@@ -226,23 +227,33 @@ static std::string stripExportInterface(
   while (true) {
   while (true) {
     std::string::size_type bPos = input.find("$<BUILD_INTERFACE:", lastPos);
     std::string::size_type bPos = input.find("$<BUILD_INTERFACE:", lastPos);
     std::string::size_type iPos = input.find("$<INSTALL_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;
       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 {
     } 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;
     nestingLevel = 1;
     const char* c = input.c_str() + pos;
     const char* c = input.c_str() + pos;
     const char* const cStart = c;
     const char* const cStart = c;
@@ -258,10 +269,10 @@ static std::string stripExportInterface(
           continue;
           continue;
         }
         }
         if (context == cmGeneratorExpression::BuildInterface &&
         if (context == cmGeneratorExpression::BuildInterface &&
-            !gotInstallInterface) {
+            foundGenex == FoundGenex::BuildInterface) {
           result += input.substr(pos, c - cStart);
           result += input.substr(pos, c - cStart);
         } else if (context == cmGeneratorExpression::InstallInterface &&
         } else if (context == cmGeneratorExpression::InstallInterface &&
-                   gotInstallInterface) {
+                   foundGenex == FoundGenex::InstallInterface) {
           const std::string content = input.substr(pos, c - cStart);
           const std::string content = input.substr(pos, c - cStart);
           if (resolveRelative) {
           if (resolveRelative) {
             prefixItems(content, result, "${_IMPORT_PREFIX}/");
             prefixItems(content, result, "${_IMPORT_PREFIX}/");
@@ -274,9 +285,18 @@ static std::string stripExportInterface(
     }
     }
     const std::string::size_type traversed = (c - cStart) + 1;
     const std::string::size_type traversed = (c - cStart) + 1;
     if (!*c) {
     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;
     pos += traversed;
     lastPos = pos;
     lastPos = pos;

+ 3 - 0
Source/cmGeneratorExpressionNode.cxx

@@ -114,6 +114,8 @@ static const struct OneNode buildInterfaceNode;
 
 
 static const struct ZeroNode installInterfaceNode;
 static const struct ZeroNode installInterfaceNode;
 
 
+static const struct OneNode buildLocalInterfaceNode;
+
 struct BooleanOpNode : public cmGeneratorExpressionNode
 struct BooleanOpNode : public cmGeneratorExpressionNode
 {
 {
   BooleanOpNode(const char* op_, const char* successVal_,
   BooleanOpNode(const char* op_, const char* successVal_,
@@ -3323,6 +3325,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
     { "GENEX_EVAL", &genexEvalNode },
     { "GENEX_EVAL", &genexEvalNode },
     { "BUILD_INTERFACE", &buildInterfaceNode },
     { "BUILD_INTERFACE", &buildInterfaceNode },
     { "INSTALL_INTERFACE", &installInterfaceNode },
     { "INSTALL_INTERFACE", &installInterfaceNode },
+    { "BUILD_LOCAL_INTERFACE", &buildLocalInterfaceNode },
     { "INSTALL_PREFIX", &installPrefixNode },
     { "INSTALL_PREFIX", &installPrefixNode },
     { "JOIN", &joinNode },
     { "JOIN", &joinNode },
     { "LINK_ONLY", &linkOnlyNode },
     { "LINK_ONLY", &linkOnlyNode },

+ 14 - 0
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::)

+ 9 - 0
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)

+ 25 - 0
Tests/RunCMake/ExportImport/RunCMakeTest.cmake

@@ -22,3 +22,28 @@ function(run_ExportImport_test case)
 endfunction()
 endfunction()
 
 
 run_ExportImport_test(SharedDep)
 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)

+ 8 - 0
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)
+{
+}

+ 8 - 0
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)
+{
+}

+ 8 - 0
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)
+{
+}