Browse Source

prop_sf/INSTALL_OBJECT_NAME: support custom install object names

These can support configuration-dependent queries much more easily, so
separate it out.
Ben Boeckel 1 month ago
parent
commit
b53837a1bd
52 changed files with 351 additions and 1 deletions
  1. 1 0
      Help/manual/cmake-properties.7.rst
  2. 25 0
      Help/prop_sf/INSTALL_OBJECT_NAME.rst
  3. 3 0
      Help/prop_sf/OBJECT_NAME.rst
  4. 3 1
      Help/prop_tgt/INSTALL_OBJECT_ONLY_USE_DESTINATION.rst
  5. 3 0
      Help/release/dev/object-name-properties.rst
  6. 2 0
      Source/cmLocalCommonGenerator.cxx
  7. 2 0
      Source/cmLocalFastbuildGenerator.cxx
  8. 100 0
      Source/cmLocalGenerator.cxx
  9. 8 0
      Source/cmLocalGenerator.h
  10. 2 0
      Source/cmLocalGhsMultiGenerator.cxx
  11. 2 0
      Source/cmLocalVisualStudioGenerator.cxx
  12. 1 0
      Source/cmLocalXCodeGenerator.cxx
  13. 1 0
      Tests/RunCMake/CMakeLists.txt
  14. 3 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/CMakeLists.txt
  15. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-DisableOnEmpty.cmake
  16. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-GeneratorExpression.cmake
  17. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-GeneratorExpressionContextSensitive.cmake
  18. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ObjectLibrary.cmake
  19. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ShortInstallStrategy.cmake
  20. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ShortStrategy.cmake
  21. 7 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume.cmake
  22. 5 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/DisableOnEmpty-install-check.cmake
  23. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/DisableOnEmpty.cmake
  24. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpression-install-check.cmake
  25. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpression.cmake
  26. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpressionContextSensitive-install-check.cmake
  27. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpressionContextSensitive.cmake
  28. 10 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Inspect.cmake
  29. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression-result.txt
  30. 9 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression-stderr.txt
  31. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression.cmake
  32. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute-result.txt
  33. 11 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute-stderr.txt
  34. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute.cmake
  35. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot-result.txt
  36. 9 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot-stderr.txt
  37. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot.cmake
  38. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ObjectLibrary-install-check.cmake
  39. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ObjectLibrary.cmake
  40. 50 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/RunCMakeTest.cmake
  41. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ShortInstallStrategy-install-check.cmake
  42. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ShortInstallStrategy.cmake
  43. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ShortStrategy-install-check.cmake
  44. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ShortStrategy.cmake
  45. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget-result.txt
  46. 12 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget-stderr.txt
  47. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget.cmake
  48. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage-result.txt
  49. 10 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage-stderr.txt
  50. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage.cmake
  51. 4 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/lib.c
  52. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/main.c

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

@@ -578,6 +578,7 @@ Properties on Source Files
    /prop_sf/GENERATED
    /prop_sf/HEADER_FILE_ONLY
    /prop_sf/INCLUDE_DIRECTORIES
+   /prop_sf/INSTALL_OBJECT_NAME
    /prop_sf/KEEP_EXTENSION
    /prop_sf/LABELS
    /prop_sf/LANGUAGE

+ 25 - 0
Help/prop_sf/INSTALL_OBJECT_NAME.rst

@@ -0,0 +1,25 @@
+INSTALL_OBJECT_NAME
+-------------------
+
+.. versionadded:: 4.2
+
+Set the installed object name (without the object extension) of the source
+file. An empty string value disables custom object naming. The value must be a
+relative path, and may not include special directory components (e.g.,
+``..``).
+
+Note that the object name may not be used as-is in
+:prop_tgt:`INSTALL_OBJECT_NAME_STRATEGY` strategies, but instead changed as
+the strategy requires to fulfill its goals.
+
+This property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+.. note::
+   No collision resistance within a target is performed by CMake. When using
+   this property, collisions must be avoided in the project code. CMake has a
+   number of source files it generates that also create object files that may
+   collide with a given custom name. These include:
+   * Generated PCH source files (``cmake_pch``)
+   * Generated Unity compilation files (``unity_``)
+   * Qt autogen sources (``moc_compilations.cpp``)

+ 3 - 0
Help/prop_sf/OBJECT_NAME.rst

@@ -12,6 +12,9 @@ Note that the object name may not be used as-is in
 :prop_tgt:`INSTALL_OBJECT_NAME_STRATEGY` strategies, but instead changed as
 the strategy requires to fulfill its goals.
 
+When installing objects, the :prop_sf:`INSTALL_OBJECT_NAME` property takes
+precedence.
+
 This property supports
 :manual:`generator expressions <cmake-generator-expressions(7)>`, but does not
 allow for context-sensitive (i.e., configuration-dependent) expressions.

+ 3 - 1
Help/prop_tgt/INSTALL_OBJECT_ONLY_USE_DESTINATION.rst

@@ -11,7 +11,9 @@ When installing object files, CMake automatically adds
 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.
+``$<CONFIG>`` to avoid conflicts. Alternatively, the
+:prop_sf:`INSTALL_OBJECT_NAME` may be used to avoid configuration-based
+conflicts.
 
 This property is initialized by the value of
 :variable:`CMAKE_INSTALL_OBJECT_ONLY_USE_DESTINATION` when the target is

+ 3 - 0
Help/release/dev/object-name-properties.rst

@@ -3,3 +3,6 @@ object-name-properties
 
 * The :prop_sf:`OBJECT_NAME` source file property may be used to control
   object names of source files.
+
+* The :prop_sf:`INSTALL_OBJECT_NAME` source file property may be used to
+  control names of installed object files.

+ 2 - 0
Source/cmLocalCommonGenerator.cxx

@@ -129,5 +129,7 @@ void cmLocalCommonGenerator::ComputeObjectFilenames(
     force = false;
     si.second.LongLoc.Update(this->GetObjectFileNameWithoutTarget(
       *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext, &force));
+    this->FillCustomInstallObjectLocations(*sf, config, custom_ext,
+                                           si.second.InstallLongLoc);
   }
 }

+ 2 - 0
Source/cmLocalFastbuildGenerator.cxx

@@ -66,6 +66,8 @@ void cmLocalFastbuildGenerator::ComputeObjectFilenames(
     cmSourceFile const* sf = si.first;
     si.second.LongLoc =
       this->GetObjectFileNameWithoutTarget(*sf, gt->ObjectDirectory);
+    this->FillCustomInstallObjectLocations(*sf, config, nullptr,
+                                           si.second.InstallLongLoc);
   }
 }
 

+ 100 - 0
Source/cmLocalGenerator.cxx

@@ -45,6 +45,7 @@
 #include "cmList.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmObjectLocation.h"
 #include "cmRange.h"
 #include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
@@ -4326,6 +4327,105 @@ std::string cmLocalGenerator::GetCustomObjectFileName(
   return std::string{};
 }
 
+std::string cmLocalGenerator::GetCustomInstallObjectFileName(
+  cmSourceFile const& source, std::string const& config,
+  char const* custom_ext) const
+{
+  if (auto objName = source.GetProperty("INSTALL_OBJECT_NAME")) {
+    cmGeneratorExpression ge(*this->GetCMakeInstance());
+    auto cge = ge.Parse(objName);
+    static std::string const INVALID_GENEX =
+      "_cmake_invalid_object_name_genex";
+    static std::string const INVALID_VALUE =
+      "_cmake_invalid_object_name_value";
+
+    if (!cge) {
+      this->Makefile->IssueMessage(
+        MessageType::FATAL_ERROR,
+        cmStrCat("The  \"INSTALL_OBJECT_NAME\" property for\n  ",
+                 source.GetFullPath(),
+                 "\nis not a valid generator expression (", objName, ")."));
+      return INVALID_GENEX;
+    }
+    if (cge->GetHadHeadSensitiveCondition()) {
+      // Not reachable; all target-sensitive  genexes actually fail to parse.
+      this->Makefile->IssueMessage(
+        MessageType::FATAL_ERROR,
+        cmStrCat("The  \"INSTALL_OBJECT_NAME\" property for\n  ",
+                 source.GetFullPath(),
+                 "\ncontains a condition that queries the consuming target "
+                 "which is not supported (",
+                 objName, ")."));
+      return INVALID_GENEX;
+    }
+    if (cge->GetHadLinkLanguageSensitiveCondition()) {
+      // Not reachable; all target-sensitive  genexes actually fail to parse.
+      this->Makefile->IssueMessage(
+        MessageType::FATAL_ERROR,
+        cmStrCat("The  \"INSTALL_OBJECT_NAME\" property for\n  ",
+                 source.GetFullPath(),
+                 "\ncontains a condition that queries the link language "
+                 "which is not supported (",
+                 objName, ")."));
+      return INVALID_GENEX;
+    }
+
+    auto objNameValue = cge->Evaluate(this, config);
+
+    // Skip if it evaluates to empty.
+    if (!objNameValue.empty()) {
+      cmCMakePath objNamePath = objNameValue;
+      // Verify that it is a relative path.
+      if (objNamePath.IsAbsolute()) {
+        this->Makefile->IssueMessage(
+          MessageType::FATAL_ERROR,
+          cmStrCat(
+            "The  \"INSTALL_OBJECT_NAME\" property for\n  ",
+            source.GetFullPath(),
+            "\nresolves to an absolute path which is not supported:\n  ",
+            objNameValue));
+        return INVALID_VALUE;
+      }
+      auto isInvalidComponent = [](cmCMakePath const& component) -> bool {
+        return component == ".."_s;
+      };
+      // Verify that it contains no `..` components.
+      if (std::any_of(objNamePath.begin(), objNamePath.end(),
+                      isInvalidComponent)) {
+        this->Makefile->IssueMessage(
+          MessageType::FATAL_ERROR,
+          cmStrCat("The  \"INSTALL_OBJECT_NAME\" property for\n  ",
+                   source.GetFullPath(), "\ncontains an invalid component (",
+                   objNameValue, ")."));
+        return INVALID_VALUE;
+      }
+
+      if (custom_ext) {
+        objNameValue += custom_ext;
+      } else {
+        objNameValue +=
+          this->GetGlobalGenerator()->GetLanguageOutputExtension(source);
+      }
+
+      return objNameValue;
+    }
+  }
+
+  return std::string{};
+}
+
+void cmLocalGenerator::FillCustomInstallObjectLocations(
+  cmSourceFile const& source, std::string const& config,
+  char const* custom_ext,
+  std::map<std::string, cmObjectLocation>& mapping) const
+{
+  auto installLoc =
+    this->GetCustomInstallObjectFileName(source, config, custom_ext);
+  if (!installLoc.empty()) {
+    mapping[config] = installLoc;
+  }
+}
+
 std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
   cmSourceFile const& source, std::string const& dir_max,
   bool* hasSourceExtension, char const* customOutputExtension,

+ 8 - 0
Source/cmLocalGenerator.h

@@ -37,6 +37,7 @@ class cmImplicitDependsList;
 class cmLinkLineComputer;
 class cmLinkLineDeviceComputer;
 class cmMakefile;
+struct cmObjectLocation;
 struct cmObjectLocations;
 class cmRulePlaceholderExpander;
 class cmSourceFile;
@@ -453,6 +454,13 @@ public:
   virtual std::string ComputeShortTargetDirectory(
     cmGeneratorTarget const* gt) const;
   std::string GetCustomObjectFileName(cmSourceFile const& source) const;
+  std::string GetCustomInstallObjectFileName(cmSourceFile const& source,
+                                             std::string const& config,
+                                             char const* custom_ext) const;
+  void FillCustomInstallObjectLocations(
+    cmSourceFile const& source, std::string const& config,
+    char const* custom_ext,
+    std::map<std::string, cmObjectLocation>& mapping) const;
 
   /**
    * Generate a macOS application bundle Info.plist file.

+ 2 - 0
Source/cmLocalGhsMultiGenerator.cxx

@@ -100,5 +100,7 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
     }
     si.second.ShortLoc.emplace(shortObjectName);
     si.second.LongLoc.Update(longObjectName);
+    this->FillCustomInstallObjectLocations(*sf, config, nullptr,
+                                           si.second.InstallLongLoc);
   }
 }

+ 2 - 0
Source/cmLocalVisualStudioGenerator.cxx

@@ -104,6 +104,8 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
     }
     si.second.ShortLoc.emplace(shortObjectName);
     si.second.LongLoc.Update(longObjectName);
+    this->FillCustomInstallObjectLocations(*sf, config, custom_ext,
+                                           si.second.InstallLongLoc);
   }
 }
 

+ 1 - 0
Source/cmLocalXCodeGenerator.cxx

@@ -142,6 +142,7 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames(
     }
     si.second.ShortLoc.emplace(shortObjectName);
     si.second.LongLoc.Update(longObjectName);
+    this->FillCustomInstallObjectLocations(*sf, config, ".o", si.second.InstallLongLoc);
   }
 }
 

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -570,6 +570,7 @@ if(XCODE_VERSION)
   set(ObjectLibrary_ARGS -DXCODE_VERSION=${XCODE_VERSION})
 endif()
 add_RunCMake_test(ObjectLibrary)
+add_RunCMake_test(INSTALL_OBJECT_NAME)
 add_RunCMake_test(OBJECT_NAME)
 add_RunCMake_test(ParseImplicitIncludeInfo)
 add_RunCMake_test(ParseImplicitLinkInfo)

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

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

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-DisableOnEmpty.cmake

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

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

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

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-GeneratorExpressionContextSensitive.cmake

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

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ObjectLibrary.cmake

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

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ShortInstallStrategy.cmake

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

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ShortStrategy.cmake

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

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

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

+ 5 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/DisableOnEmpty-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}")

+ 6 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/DisableOnEmpty.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
+
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "$<$<BOOL:0>:objlib_lib.c>")
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/ION FILE ion-config.cmake NAMESPACE ION::)

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpression-install-check.cmake

@@ -0,0 +1 @@
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/1/objlib_lib.c${CMAKE_C_OUTPUT_EXTENSION}")

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

@@ -0,0 +1,6 @@
+set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
+
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "$<BOOL:ON>/objlib_lib.c")
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/ION FILE ion-config.cmake NAMESPACE ION::)

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpressionContextSensitive-install-check.cmake

@@ -0,0 +1 @@
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/objlib_lib_debug.c${CMAKE_C_OUTPUT_EXTENSION}")

+ 6 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpressionContextSensitive.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
+
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "objlib_lib_$<LOWER_CASE:$<CONFIG>>.c")
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/ION FILE ion-config.cmake NAMESPACE ION::)

+ 10 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/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}")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression-result.txt

@@ -0,0 +1 @@
+1

+ 9 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression-stderr.txt

@@ -0,0 +1,9 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<invalid>
+
+  Expression did not evaluate to a known generator expression
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression.cmake

@@ -0,0 +1,2 @@
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "$<invalid>")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute-result.txt

@@ -0,0 +1 @@
+1

+ 11 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute-stderr.txt

@@ -0,0 +1,11 @@
+CMake Error in CMakeLists.txt:
+  The "INSTALL_OBJECT_NAME" property for
+
+    .*/Tests/RunCMake/INSTALL_OBJECT_NAME/lib.c
+
+  resolves to an absolute path which is not supported:
+
+    .*/Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute-build/lib.c
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute.cmake

@@ -0,0 +1,2 @@
+add_library(static STATIC lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "${CMAKE_BINARY_DIR}/lib.c")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot-result.txt

@@ -0,0 +1 @@
+1

+ 9 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot-stderr.txt

@@ -0,0 +1,9 @@
+CMake Error in CMakeLists.txt:
+  The "INSTALL_OBJECT_NAME" property for
+
+    .*/Tests/RunCMake/INSTALL_OBJECT_NAME/lib.c
+
+  contains an invalid component \(subdir/\.\./sibling/lib.c\).
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot.cmake

@@ -0,0 +1,2 @@
+add_library(static STATIC lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "subdir/../sibling/lib.c")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/ObjectLibrary-install-check.cmake

@@ -0,0 +1 @@
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/objlib_lib.c${CMAKE_C_OUTPUT_EXTENSION}")

+ 6 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/ObjectLibrary.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
+
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "objlib_lib.c")
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/ION FILE ion-config.cmake NAMESPACE ION::)

+ 50 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/RunCMakeTest.cmake

@@ -0,0 +1,50 @@
+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_OPTIONS -DCMAKE_BUILD_TYPE:STRING=Debug "-DCMAKE_INSTALL_PREFIX:PATH=${RunCMake_TEST_BINARY_DIR}/fake_install")
+  run_cmake(${case})
+  set(RunCMake_TEST_NO_CLEAN 1)
+  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_cmake(NoAbsolute)
+run_cmake(NoDotDot)
+run_cmake(InvalidGeneratorExpression)
+run_cmake(UnsupportedGeneratorExpressionHeadTarget)
+run_cmake(UnsupportedGeneratorExpressionLinkLanguage)
+
+run_install_test(ObjectLibrary)
+run_install_test(DisableOnEmpty)
+if (RunCMake_GENERATOR MATCHES "(Ninja|Makefiles|Visual Studio)")
+  run_install_test(ShortInstallStrategy)
+endif ()
+run_install_test(GeneratorExpression)
+run_install_test(GeneratorExpressionContextSensitive)

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/ShortInstallStrategy-install-check.cmake

@@ -0,0 +1 @@
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/d33a1361${CMAKE_C_OUTPUT_EXTENSION}")

+ 6 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/ShortInstallStrategy.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_INSTALL_OBJECT_NAME_STRATEGY SHORT)
+
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "objlib_lib.c")
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/ION FILE ion-config.cmake NAMESPACE ION::)

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/ShortStrategy-install-check.cmake

@@ -0,0 +1 @@
+check_installed_object("${RunCMake_TEST_BINARY_DIR}/real_install/lib/objlib/objects-Debug/objlib/objlib_lib.c${CMAKE_C_OUTPUT_EXTENSION}")

+ 6 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/ShortStrategy.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_INTERMEDIATE_DIR_STRATEGY SHORT CACHE STRING "" FORCE)
+
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "objlib_lib.c")
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/ION FILE ion-config.cmake NAMESPACE ION::)

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget-result.txt

@@ -0,0 +1 @@
+1

+ 12 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget-stderr.txt

@@ -0,0 +1,12 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:foo>
+
+  \$<TARGET_PROPERTY:prop> may only be used with binary targets.  It may not
+  be used with add_custom_command or add_custom_target.  Specify the target
+  to read a property from using the \$<TARGET_PROPERTY:tgt,prop> signature
+  instead.
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget.cmake

@@ -0,0 +1,2 @@
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "$<TARGET_PROPERTY:foo>/objlib_lib.c")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<LINK_LANGUAGE>
+
+  \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
+  libraries, link directories, link options and link depends.
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage.cmake

@@ -0,0 +1,2 @@
+add_library(objlib OBJECT lib.c)
+set_property(SOURCE lib.c PROPERTY INSTALL_OBJECT_NAME "$<LINK_LANGUAGE>/objlib_lib.c")

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

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

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

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