Pārlūkot izejas kodu

install: support using `DESTINATION` as-is for object installation

CMake historically has forced an `objects[-<CONFIG>]/<TARGET_NAME>`
subdirectory under an `OBJECT` library installation's `OBJECTS
DESTINATION` which may be unwanted. Support skipping this component
with a target property.
Ben Boeckel 1 mēnesi atpakaļ
vecāks
revīzija
c1de3c72a3
28 mainītis faili ar 159 papildinājumiem un 3 dzēšanām
  1. 1 0
      Help/manual/cmake-properties.7.rst
  2. 1 0
      Help/manual/cmake-variables.7.rst
  3. 18 0
      Help/prop_tgt/INSTALL_OBJECT_ONLY_USE_DESTINATION.rst
  4. 5 0
      Help/release/dev/install-object-only-destination.rst
  5. 11 0
      Help/variable/CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION.rst
  6. 10 3
      Source/cmInstallTargetGenerator.cxx
  7. 1 0
      Source/cmTarget.cxx
  8. 1 0
      Tests/RunCMake/CMakeLists.txt
  9. 3 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/CMakeLists.txt
  10. 5 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Common.cmake
  11. 1 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume-Default.cmake
  12. 1 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume-GeneratorExpression.cmake
  13. 1 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume-Off.cmake
  14. 1 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume-On.cmake
  15. 7 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume.cmake
  16. 2 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Default-install-check.cmake
  17. 1 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Default.cmake
  18. 5 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/GeneratorExpression-install-check.cmake
  19. 6 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/GeneratorExpression.cmake
  20. 10 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Inspect.cmake
  21. 5 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Off-install-check.cmake
  22. 2 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Off.cmake
  23. 5 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/On-install-check.cmake
  24. 2 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/On.cmake
  25. 43 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/RunCMakeTest.cmake
  26. 4 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/lib.c
  27. 6 0
      Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/main.c
  28. 1 0
      Tests/RunCMake/property_init/CompileSources.cmake

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -283,6 +283,7 @@ Properties on Targets
    /prop_tgt/INCLUDE_DIRECTORIES
    /prop_tgt/INSTALL_NAME_DIR
    /prop_tgt/INSTALL_OBJECT_NAME_STRATEGY
+   /prop_tgt/INSTALL_OBJECT_ONLY_USE_DESTINATION
    /prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH
    /prop_tgt/INSTALL_RPATH
    /prop_tgt/INSTALL_RPATH_USE_LINK_PATH

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -497,6 +497,7 @@ Variables that Control the Build
    /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE
    /variable/CMAKE_INSTALL_NAME_DIR
    /variable/CMAKE_INSTALL_OBJECT_NAME_STRATEGY
+   /variable/CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION
    /variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH
    /variable/CMAKE_INSTALL_RPATH
    /variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH

+ 18 - 0
Help/prop_tgt/INSTALL_OBJECT_ONLY_USE_DESTINATION.rst

@@ -0,0 +1,18 @@
+INSTALL_OBJECT_ONLY_USE_DESTINATION
+-----------------------------------
+
+.. versionadded:: 4.2
+
+Controls whether the ``install(DESTINATION)`` for object libraries is used
+as-is or supplemented with conflict-avoiding subdirectories.
+
+When installing object files, CMake automatically adds
+``objects[-<CONFIG>]/<TARGET_NAME>`` components to the destination to avoid
+conflicts. Use this property to suppress these components. Note that when
+using a single install prefix for multiple configurations (whether via
+multi-config generators or separate build trees), the destination must use
+``$<CONFIG>`` to avoid conflicts.
+
+This property is initialized by the value of
+:variable:`CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION` when the target is
+created.

+ 5 - 0
Help/release/dev/install-object-only-destination.rst

@@ -0,0 +1,5 @@
+install-object-only-destination
+-------------------------------
+
+* The :prop_tgt:`INSTALL_OBJECT_ONLY_USE_DESTINATION` target property has been
+  added to more precisely control the installation path for object files.

+ 11 - 0
Help/variable/CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION.rst

@@ -0,0 +1,11 @@
+CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION
+-----------------------------------------
+
+.. versionadded:: 4.2
+
+Controls whether the ``install(DESTINATION)`` for object libraries is used
+as-is or supplemented with conflict-avoiding subdirectories.
+
+``CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION`` is used to initialize the
+:prop_tgt:`INSTALL_OBJECT_ONLY_USE_DESTINATION` property on all targets.  See
+that target property for more information.

+ 10 - 3
Source/cmInstallTargetGenerator.cxx

@@ -260,7 +260,10 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
       files.NoTweak = true;
       files.Rename = true;
       files.FromDir = this->Target->GetObjectDirectory(config);
-      files.ToDir = computeInstallObjectDir(this->Target, config);
+      if (!this->Target->GetPropertyAsBool(
+            "INSTALL_OBJECT_ONLY_USE_DESTINATION")) {
+        files.ToDir = computeInstallObjectDir(this->Target, config);
+      }
       for (auto const& obj : objects) {
         files.From.emplace_back(obj.first.GetPath());
         files.To.emplace_back(obj.second.GetPath());
@@ -460,9 +463,13 @@ void cmInstallTargetGenerator::GetInstallObjectNames(
     };
   this->Target->GetTargetObjectLocations(config, storeObjectLocations);
   objects.reserve(installedObjects.size());
-  auto const rootDir = computeInstallObjectDir(this->Target, config);
+  std::string rootDir;
+  if (!this->Target->GetPropertyAsBool(
+        "INSTALL_OBJECT_ONLY_USE_DESTINATION")) {
+    rootDir = cmStrCat(computeInstallObjectDir(this->Target, config), '/');
+  }
   for (cmObjectLocation const& o : installedObjects) {
-    objects.emplace_back(cmStrCat(rootDir, '/', o.GetPath()));
+    objects.emplace_back(cmStrCat(rootDir, o.GetPath()));
   }
 }
 

+ 1 - 0
Source/cmTarget.cxx

@@ -420,6 +420,7 @@ TargetProperty const StaticTargetProperties[] = {
   // ---- Install
   { "INSTALL_NAME_DIR"_s, IC::CanCompileSources },
   { "INSTALL_OBJECT_NAME_STRATEGY"_s, IC::CanCompileSources },
+  { "INSTALL_OBJECT_ONLY_USE_DESTINATION"_s, IC::CanCompileSources },
   { "INSTALL_REMOVE_ENVIRONMENT_RPATH"_s, IC::CanCompileSources },
   { "INSTALL_RPATH"_s, ""_s, IC::CanCompileSources },
   { "INSTALL_RPATH_USE_LINK_PATH"_s, "OFF"_s, IC::CanCompileSources },

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -729,6 +729,7 @@ if(DEFINED CMake_TEST_NO_WRITE_ONLY_DIR)
   list(APPEND if_ARGS -DCMake_TEST_NO_WRITE_ONLY_DIR=${CMake_TEST_NO_WRITE_ONLY_DIR})
 endif()
 add_RunCMake_test(INSTALL_OBJECT_NAME_STRATEGY)
+add_RunCMake_test(INSTALL_OBJECT_ONLY_USE_DESTINATION)
 add_RunCMake_test(if -DMSYS=${MSYS})
 add_RunCMake_test(include)
 add_RunCMake_test(include_directories)

+ 3 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.16)
+project(${RunCMake_TEST} C)
+include(${RunCMake_TEST}.cmake)

+ 5 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Common.cmake

@@ -0,0 +1,5 @@
+add_library(objlib OBJECT lib.c)
+install(TARGETS objlib
+  EXPORT exp
+  DESTINATION lib/objlib)
+install(EXPORT exp DESTINATION lib/cmake/IOOUD FILE iooud-config.cmake NAMESPACE IOOUD::)

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume-Default.cmake

@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume-GeneratorExpression.cmake

@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume-Off.cmake

@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume-On.cmake

@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake")

+ 7 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Consume.cmake

@@ -0,0 +1,7 @@
+find_package(IOOUD CONFIG REQUIRED)
+
+add_executable(main main.c)
+target_link_libraries(main PRIVATE IOOUD::objlib)
+
+enable_testing()
+add_test(NAME run COMMAND main)

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Default-install-check.cmake

@@ -0,0 +1,2 @@
+# The default behavior is `Off`.
+include("${CMAKE_CURRENT_LIST_DIR}/Off-install-check.cmake")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Default.cmake

@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/Common.cmake")

+ 5 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/GeneratorExpression-install-check.cmake

@@ -0,0 +1,5 @@
+set(ext_suffix ".c")
+if (RunCMake_GENERATOR MATCHES "(Visual Studio|Xcode)")
+  set(ext_suffix "")
+endif ()
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/Debug/lib${ext_suffix}${CMAKE_C_OUTPUT_EXTENSION}")

+ 6 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/GeneratorExpression.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION 1)
+add_library(objlib OBJECT lib.c)
+install(TARGETS objlib
+  EXPORT exp
+  DESTINATION "lib/$<TARGET_NAME:objlib>/$<CONFIG>")
+install(EXPORT exp DESTINATION lib/cmake/IOOUD FILE iooud-config.cmake NAMESPACE IOOUD::)

+ 10 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Inspect.cmake

@@ -0,0 +1,10 @@
+enable_language(C)
+
+set(info "")
+
+# Forward information about the C++ compile features.
+string(APPEND info "\
+set(CMAKE_C_OUTPUT_EXTENSION \"${CMAKE_C_OUTPUT_EXTENSION}\")
+")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}")

+ 5 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Off-install-check.cmake

@@ -0,0 +1,5 @@
+set(ext_suffix ".c")
+if (RunCMake_GENERATOR MATCHES "(Visual Studio|Xcode)")
+  set(ext_suffix "")
+endif ()
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/lib${ext_suffix}${CMAKE_C_OUTPUT_EXTENSION}")

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/Off.cmake

@@ -0,0 +1,2 @@
+set(CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION 0)
+include("${CMAKE_CURRENT_LIST_DIR}/Common.cmake")

+ 5 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/On-install-check.cmake

@@ -0,0 +1,5 @@
+set(ext_suffix ".c")
+if (RunCMake_GENERATOR MATCHES "(Visual Studio|Xcode)")
+  set(ext_suffix "")
+endif ()
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/lib${ext_suffix}${CMAKE_C_OUTPUT_EXTENSION}")

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/On.cmake

@@ -0,0 +1,2 @@
+set(CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION 1)
+include("${CMAKE_CURRENT_LIST_DIR}/Common.cmake")

+ 43 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/RunCMakeTest.cmake

@@ -0,0 +1,43 @@
+cmake_minimum_required(VERSION 3.16)
+
+include(RunCMake)
+
+# This test does installation of `OBJECT` libraries which does not work with
+# multi-arch compilation under Xcode.
+if (RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
+  return ()
+endif ()
+
+function(run_install_test case)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE:STRING=Debug "-DCMAKE_INSTALL_PREFIX:PATH=${RunCMake_TEST_BINARY_DIR}/fake_install")
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  run_cmake(${case})
+  run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug)
+  set(prefix "${RunCMake_TEST_BINARY_DIR}/real_install")
+  run_cmake_command(${case}-install ${CMAKE_COMMAND} --install . --config Debug --prefix "${prefix}")
+
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Consume-${case}-build)
+  set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE:STRING=Debug "-DCMAKE_PREFIX_PATH:PATH=${prefix}")
+  run_cmake(Consume-${case} "-DCMAKE_PREFIX_PATH=${prefix}")
+  run_cmake_command(Consume-${case}-build ${CMAKE_COMMAND} --build . --config Debug)
+  run_cmake_command(Consume-${case}-test ${CMAKE_CTEST_COMMAND} -C Debug)
+endfunction()
+
+function (check_installed_object path)
+  if (NOT EXISTS "${path}")
+    list(APPEND RunCMake_TEST_FAILED
+      "Could not find installed object at '${path}'")
+  endif ()
+  set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction ()
+
+run_cmake(Inspect)
+include("${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
+
+run_install_test(Default)
+run_install_test(Off)
+run_install_test(On)
+run_install_test(GeneratorExpression)

+ 4 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/lib.c

@@ -0,0 +1,4 @@
+int f(int a)
+{
+  return a;
+}

+ 6 - 0
Tests/RunCMake/INSTALL_OBJECT_ONLY_USE_DESTINATION/main.c

@@ -0,0 +1,6 @@
+int f(int a);
+
+int main(void)
+{
+  return f(0);
+}

+ 1 - 0
Tests/RunCMake/property_init/CompileSources.cmake

@@ -79,6 +79,7 @@ set(properties
   ### Install
   "INSTALL_NAME_DIR"                        "@rpath/"           "<SAME>"
   "INSTALL_OBJECT_NAME_STRATEGY"            "SHORT"             "<SAME>"
+  "INSTALL_OBJECT_ONLY_USE_DESTINATION"     "ON"                "<SAME>"
   "INSTALL_REMOVE_ENVIRONMENT_RPATH"        "ON"                "<SAME>"
   "INSTALL_RPATH"                           "@rpath/"           "<SAME>"
   "INSTALL_RPATH_USE_LINK_PATH"             "ON"                "<SAME>"