Browse Source

Merge topic 'object-name-properties'

b53837a1bd prop_sf/INSTALL_OBJECT_NAME: support custom install object names
08f1a0fbc6 cmLocalGenerator: get the configuration when building object paths
168e55be41 cmObjectLocation: support install-specific object locations
84372ce0b5 prop_sf/OBJECT_NAME: no-op for the FASTBuild and Xcode generators
9ef99353cb prop_sf/OBJECT_NAME: support custom object names
7aff0d37b5 cmSourceFile: add accessors for PCH source files
bbdc2fd908 cmSourceFile: internally track CMake-managed source files
388923818d cmGeneratorTarget: return the source file added
...

Acked-by: Kitware Robot <[email protected]>
Merge-request: !11144
Brad King 4 months ago
parent
commit
042b88e3f4
100 changed files with 738 additions and 53 deletions
  1. 1 1
      .gitlab-ci.yml
  2. 1 0
      .gitlab/os-linux.yml
  3. 2 0
      Help/manual/cmake-properties.7.rst
  4. 25 0
      Help/prop_sf/INSTALL_OBJECT_NAME.rst
  5. 33 0
      Help/prop_sf/OBJECT_NAME.rst
  6. 2 1
      Help/prop_tgt/INSTALL_OBJECT_NAME_STRATEGY.rst
  7. 3 1
      Help/prop_tgt/INSTALL_OBJECT_ONLY_USE_DESTINATION.rst
  8. 8 0
      Help/release/dev/object-name-properties.rst
  9. 2 1
      Help/variable/CMAKE_INTERMEDIATE_DIR_STRATEGY.rst
  10. 11 10
      Source/cmCMakePath.h
  11. 1 1
      Source/cmFastbuildNormalTargetGenerator.cxx
  12. 12 5
      Source/cmGeneratorTarget.cxx
  13. 1 1
      Source/cmGeneratorTarget.h
  14. 2 0
      Source/cmGlobalFastbuildGenerator.h
  15. 2 0
      Source/cmGlobalGenerator.h
  16. 1 1
      Source/cmGlobalVisualStudioGenerator.cxx
  17. 11 1
      Source/cmGlobalXCodeGenerator.cxx
  18. 2 0
      Source/cmGlobalXCodeGenerator.h
  19. 3 1
      Source/cmLocalCommonGenerator.cxx
  20. 1 1
      Source/cmLocalCommonGenerator.h
  21. 3 1
      Source/cmLocalFastbuildGenerator.cxx
  22. 1 1
      Source/cmLocalFastbuildGenerator.h
  23. 212 3
      Source/cmLocalGenerator.cxx
  24. 10 1
      Source/cmLocalGenerator.h
  25. 23 8
      Source/cmLocalGhsMultiGenerator.cxx
  26. 1 1
      Source/cmLocalGhsMultiGenerator.h
  27. 19 5
      Source/cmLocalVisualStudioGenerator.cxx
  28. 1 1
      Source/cmLocalVisualStudioGenerator.h
  29. 4 1
      Source/cmLocalXCodeGenerator.cxx
  30. 1 1
      Source/cmLocalXCodeGenerator.h
  31. 1 0
      Source/cmMakefile.cxx
  32. 19 0
      Source/cmObjectLocation.cxx
  33. 7 0
      Source/cmObjectLocation.h
  34. 2 0
      Source/cmQTWrapCPPCommand.cxx
  35. 2 0
      Source/cmQtAutoGenInitializer.cxx
  36. 15 0
      Source/cmSourceFile.cxx
  37. 31 0
      Source/cmSourceFile.h
  38. 10 5
      Source/cmVisualStudio10TargetGenerator.cxx
  39. 2 0
      Tests/RunCMake/CMakeLists.txt
  40. 3 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/CMakeLists.txt
  41. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-DisableOnEmpty.cmake
  42. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-GeneratorExpression.cmake
  43. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-GeneratorExpressionContextSensitive.cmake
  44. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ObjectLibrary.cmake
  45. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ShortInstallStrategy.cmake
  46. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume-ShortStrategy.cmake
  47. 7 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Consume.cmake
  48. 5 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/DisableOnEmpty-install-check.cmake
  49. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/DisableOnEmpty.cmake
  50. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpression-install-check.cmake
  51. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpression.cmake
  52. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpressionContextSensitive-install-check.cmake
  53. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/GeneratorExpressionContextSensitive.cmake
  54. 10 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/Inspect.cmake
  55. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression-result.txt
  56. 9 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression-stderr.txt
  57. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/InvalidGeneratorExpression.cmake
  58. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute-result.txt
  59. 11 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute-stderr.txt
  60. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoAbsolute.cmake
  61. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot-result.txt
  62. 9 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot-stderr.txt
  63. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/NoDotDot.cmake
  64. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ObjectLibrary-install-check.cmake
  65. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ObjectLibrary.cmake
  66. 50 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/RunCMakeTest.cmake
  67. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ShortInstallStrategy-install-check.cmake
  68. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ShortInstallStrategy.cmake
  69. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ShortStrategy-install-check.cmake
  70. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/ShortStrategy.cmake
  71. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget-result.txt
  72. 12 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget-stderr.txt
  73. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionHeadTarget.cmake
  74. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage-result.txt
  75. 10 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage-stderr.txt
  76. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/UnsupportedGeneratorExpressionLinkLanguage.cmake
  77. 4 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/lib.c
  78. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME/main.c
  79. 3 0
      Tests/RunCMake/OBJECT_NAME/CMakeLists.txt
  80. 1 0
      Tests/RunCMake/OBJECT_NAME/Collision-result.txt
  81. 1 0
      Tests/RunCMake/OBJECT_NAME/Collision-stderr.txt
  82. 1 0
      Tests/RunCMake/OBJECT_NAME/Collision.cmake
  83. 1 0
      Tests/RunCMake/OBJECT_NAME/CollisionBuild-build-result.txt
  84. 1 0
      Tests/RunCMake/OBJECT_NAME/CollisionBuild-build-stderr.txt
  85. 1 0
      Tests/RunCMake/OBJECT_NAME/CollisionBuild-build-stdout.txt
  86. 1 0
      Tests/RunCMake/OBJECT_NAME/CollisionBuild-stderr.txt
  87. 7 0
      Tests/RunCMake/OBJECT_NAME/CollisionBuild.cmake
  88. 1 0
      Tests/RunCMake/OBJECT_NAME/Consume-DisableOnEmpty.cmake
  89. 1 0
      Tests/RunCMake/OBJECT_NAME/Consume-GeneratorExpression.cmake
  90. 1 0
      Tests/RunCMake/OBJECT_NAME/Consume-ObjectLibrary.cmake
  91. 1 0
      Tests/RunCMake/OBJECT_NAME/Consume-ShortInstallStrategy.cmake
  92. 1 0
      Tests/RunCMake/OBJECT_NAME/Consume-ShortStrategy.cmake
  93. 7 0
      Tests/RunCMake/OBJECT_NAME/Consume.cmake
  94. 5 0
      Tests/RunCMake/OBJECT_NAME/DisableOnEmpty-build-check.cmake
  95. 5 0
      Tests/RunCMake/OBJECT_NAME/DisableOnEmpty-install-check.cmake
  96. 6 0
      Tests/RunCMake/OBJECT_NAME/DisableOnEmpty.cmake
  97. 1 0
      Tests/RunCMake/OBJECT_NAME/Executable-build-check.cmake
  98. 4 0
      Tests/RunCMake/OBJECT_NAME/Executable.cmake
  99. 1 0
      Tests/RunCMake/OBJECT_NAME/GeneratorExpression-build-check.cmake
  100. 1 0
      Tests/RunCMake/OBJECT_NAME/GeneratorExpression-install-check.cmake

+ 1 - 1
.gitlab-ci.yml

@@ -1097,7 +1097,7 @@ t:macos-x86_64-ninja-ub:
     needs:
         - t:macos-x86_64-ninja
     variables:
-        CMAKE_CI_JOB_NIGHTLY: "true"
+        CMAKE_CI_NO_MR: "true"
 
 t:macos-arm64-xcode-ub:
     extends:

+ 1 - 0
.gitlab/os-linux.yml

@@ -789,6 +789,7 @@
         - .needs_centos7_x86_64
     variables:
         CMAKE_CI_JOB_NIGHTLY: "true"
+        CMAKE_CI_NO_MR: "true"
 
 .cmake_test_linux_inteloneapi_makefiles:
     extends:

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

@@ -579,12 +579,14 @@ 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
    /prop_sf/LOCATION
    /prop_sf/MACOSX_PACKAGE_LOCATION
    /prop_sf/OBJECT_DEPENDS
+   /prop_sf/OBJECT_NAME
    /prop_sf/OBJECT_OUTPUTS
    /prop_sf/JOB_POOL_COMPILE
    /prop_sf/SKIP_AUTOGEN

+ 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``)

+ 33 - 0
Help/prop_sf/OBJECT_NAME.rst

@@ -0,0 +1,33 @@
+OBJECT_NAME
+-----------
+
+.. versionadded:: 4.2
+
+Set the 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
+:variable:`CMAKE_INTERMEDIATE_DIR_STRATEGY` and
+: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.
+
+.. 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``)
+
+.. note::
+   The :generator:`FASTBuild` and :generator:`Xcode` generators do not support
+   this property and it is ignored.

+ 2 - 1
Help/prop_tgt/INSTALL_OBJECT_NAME_STRATEGY.rst

@@ -7,7 +7,8 @@ INSTALL_OBJECT_NAME_STRATEGY
 specifying the strategy to use when naming installed object files. The
 supported values are:
 
-- ``FULL``: Object files are named after the associated source file.
+- ``FULL``: Object files are named after the associated source file or
+  its :prop_sf:`OBJECT_NAME` property.
 - ``SHORT``: Object files are named based on the hash of the source file name
   to reduce path lengths.
 

+ 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

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

@@ -0,0 +1,8 @@
+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 - 1
Help/variable/CMAKE_INTERMEDIATE_DIR_STRATEGY.rst

@@ -10,7 +10,8 @@ supported values are:
 - ``FULL``: Intermediate directories are named based on a
   ``<TARGET_NAME>.dir`` pattern (with some slight deviations and sanitizations
   applied in various places). Object file names are based on the filename of
-  the source file being compiled.
+  the source file being compiled or, if set, its :prop_sf:`OBJECT_NAME`
+  property.
 - ``SHORT``: Intermediate directories are named from the hash of the target
   name and the build directory location. Object file names are based on hashes
   of the source file name to reduce path lengths. This may help with projects

+ 11 - 10
Source/cmCMakePath.h

@@ -664,12 +664,7 @@ public:
 
   iterator() = default;
 
-  iterator(iterator const& other)
-    : Iterator(other.Iterator)
-    , Path(other.Path)
-    , PathElement(*this->Iterator)
-  {
-  }
+  iterator(iterator const& other) = default;
 
   ~iterator() = default;
 
@@ -678,7 +673,7 @@ public:
     if (this != &other) {
       this->Iterator = other.Iterator;
       this->Path = other.Path;
-      this->PathElement = *this->Iterator;
+      this->PathElement = other.PathElement;
     }
 
     return *this;
@@ -691,7 +686,9 @@ public:
   iterator& operator++()
   {
     ++this->Iterator;
-    this->PathElement = *this->Iterator;
+    if (this->Path && this->Iterator != this->Path->Path.end()) {
+      this->PathElement = *this->Iterator;
+    }
 
     return *this;
   }
@@ -706,7 +703,9 @@ public:
   iterator& operator--()
   {
     --this->Iterator;
-    this->PathElement = *this->Iterator;
+    if (this->Path && this->Iterator != this->Path->Path.end()) {
+      this->PathElement = *this->Iterator;
+    }
 
     return *this;
   }
@@ -725,8 +724,10 @@ private:
   iterator(cmCMakePath const* path, cm::filesystem::path::iterator const& it)
     : Iterator(it)
     , Path(path)
-    , PathElement(*this->Iterator)
   {
+    if (this->Path && this->Iterator != this->Path->Path.end()) {
+      this->PathElement = *this->Iterator;
+    }
   }
 
   cm::filesystem::path::iterator Iterator;

+ 1 - 1
Source/cmFastbuildNormalTargetGenerator.cxx

@@ -570,7 +570,7 @@ void cmFastbuildNormalTargetGenerator::GenerateModuleDefinitionInfo(
       for (cmSourceFile const* it : objectSources) {
         mapping[it];
       }
-      GeneratorTarget->LocalGenerator->ComputeObjectFilenames(mapping,
+      GeneratorTarget->LocalGenerator->ComputeObjectFilenames(mapping, Config,
                                                               GeneratorTarget);
 
       std::vector<std::string> objs;

+ 12 - 5
Source/cmGeneratorTarget.cxx

@@ -566,10 +566,11 @@ void cmGeneratorTarget::AddSourceCommon(std::string const& src, bool before)
   this->ClearSourcesCache();
 }
 
-void cmGeneratorTarget::AddSource(std::string const& src, bool before)
+cmSourceFile* cmGeneratorTarget::AddSource(std::string const& src, bool before)
 {
-  this->Target->AddSource(src, before);
+  auto* sf = this->Target->AddSource(src, before);
   this->AddSourceCommon(src, before);
+  return sf;
 }
 
 void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
@@ -697,7 +698,7 @@ void cmGeneratorTarget::GetObjectSources(
     this->Objects[it];
   }
 
-  this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
+  this->LocalGenerator->ComputeObjectFilenames(this->Objects, config, this);
   this->VisitedConfigsForObjects.insert(config);
 }
 
@@ -3140,6 +3141,7 @@ std::string cmGeneratorTarget::GetPchFileObject(std::string const& config,
 
     auto* pchSf = this->Makefile->GetOrCreateSource(
       pchSource, false, cmSourceFileLocationKind::Known);
+    pchSf->SetSpecialSourceType(cmSourceFile::SpecialSourceType::PchSource);
     pchSf->ResolveFullPath();
     filename = cmStrCat(this->GetObjectDirectory(config), '/',
                         this->GetObjectName(pchSf));
@@ -3187,6 +3189,8 @@ std::string cmGeneratorTarget::GetPchFile(std::string const& config,
         auto pchSource = this->GetPchSource(config, language, arch);
         auto* pchSf = this->Makefile->GetOrCreateSource(
           pchSource, false, cmSourceFileLocationKind::Known);
+        pchSf->SetSpecialSourceType(
+          cmSourceFile::SpecialSourceType::PchSource);
         pchSf->ResolveFullPath();
         std::string cfgSubdir;
         if (this->GetGlobalGenerator()->IsMultiConfig()) {
@@ -4039,7 +4043,7 @@ void cmGeneratorTarget::GetTargetObjectLocations(
     mapping[sf];
   }
 
-  this->LocalGenerator->ComputeObjectFilenames(mapping, this);
+  this->LocalGenerator->ComputeObjectFilenames(mapping, config, this);
 
   auto const buildUseShortPaths = this->GetUseShortObjectNames()
     ? cmObjectLocations::UseShortPath::Yes
@@ -4050,7 +4054,8 @@ void cmGeneratorTarget::GetTargetObjectLocations(
     // Find the object file name corresponding to this source file.
     auto map_it = mapping.find(src);
     auto const& buildLoc = map_it->second.GetLocation(buildUseShortPaths);
-    auto const& installLoc = map_it->second.GetLocation(installUseShortPaths);
+    auto const& installLoc =
+      map_it->second.GetInstallLocation(installUseShortPaths, config);
     // It must exist because we populated the mapping just above.
     assert(!buildLoc.GetPath().empty());
     assert(!installLoc.GetPath().empty());
@@ -5797,6 +5802,8 @@ std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile(
     this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->GetName(),
     "_verify_interface_header_sets/", headerFilename, extension);
   auto* verificationSource = this->Makefile->GetOrCreateSource(filename);
+  source.SetSpecialSourceType(
+    cmSourceFile::SpecialSourceType::HeaderSetVerificationSource);
   verificationSource->SetProperty("LANGUAGE", language);
 
   cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(filename));

+ 1 - 1
Source/cmGeneratorTarget.h

@@ -845,7 +845,7 @@ public:
    */
   void ClearLinkInterfaceCache();
 
-  void AddSource(std::string const& src, bool before = false);
+  cmSourceFile* AddSource(std::string const& src, bool before = false);
   void AddTracedSources(std::vector<std::string> const& srcs);
 
   /**

+ 2 - 0
Source/cmGlobalFastbuildGenerator.h

@@ -356,6 +356,8 @@ public:
 
   bool IsMultiConfig() const override { return false; }
 
+  bool SupportsCustomObjectNames() const override { return false; }
+
   void ComputeTargetObjectDirectory(cmGeneratorTarget*) const override;
   void AppendDirectoryForConfig(std::string const& prefix,
                                 std::string const& config,

+ 2 - 0
Source/cmGlobalGenerator.h

@@ -174,6 +174,8 @@ public:
     return false;
   }
 
+  virtual bool SupportsCustomObjectNames() const { return true; }
+
   virtual bool SupportsBuildDatabase() const { return false; }
   bool AddBuildDatabaseTargets();
   void AddBuildDatabaseFile(std::string const& lang, std::string const& config,

+ 1 - 1
Source/cmGlobalVisualStudioGenerator.cxx

@@ -723,7 +723,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
   for (cmSourceFile const* it : objectSources) {
     mapping[it];
   }
-  gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
+  gt->LocalGenerator->ComputeObjectFilenames(mapping, configName, gt);
   std::string obj_dir = gt->ObjectDirectory;
   std::string cmakeCommand = cmSystemTools::GetCMakeCommand();
   std::string obj_dir_expanded = obj_dir;

+ 11 - 1
Source/cmGlobalXCodeGenerator.cxx

@@ -740,7 +740,9 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
       this->CurrentMakefile->GetSafeDefinition("CMAKE_XCODE_XCCONFIG"),
       this->CurrentLocalGenerator, config);
     if (!xcconfig.empty()) {
-      allbuild->AddSource(xcconfig);
+      auto* xcconfig_sf = allbuild->AddSource(xcconfig);
+      xcconfig_sf->SetSpecialSourceType(
+        cmSourceFile::SpecialSourceType::XcodeXCConfigFile);
     }
   }
 
@@ -1161,6 +1163,8 @@ void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
     target->GetLocalGenerator()->GetCurrentSourceDirectory());
   cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(
     listfile, false, cmSourceFileLocationKind::Known);
+  srcCMakeLists->SetSpecialSourceType(
+    cmSourceFile::SpecialSourceType::CMakeLists);
   if (!cm::contains(sources, srcCMakeLists)) {
     sources.push_back(srcCMakeLists);
   }
@@ -1538,6 +1542,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
     std::string plist = this->ComputeInfoPListLocation(gtgt);
     cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
       plist, true, cmSourceFileLocationKind::Known);
+    sf->SetSpecialSourceType(cmSourceFile::SpecialSourceType::BundleInfoPlist);
     commonSourceFiles.push_back(sf);
   }
 
@@ -1811,6 +1816,8 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
     fout << '\n';
   }
   if (cmSourceFile* sf = mf->GetOrCreateSource(fname)) {
+    sf->SetSpecialSourceType(
+      cmSourceFile::SpecialSourceType::XcodeForceLinkerSource);
     sf->SetProperty("LANGUAGE", llang);
     sf->SetProperty("CXX_SCAN_FOR_MODULES", "0");
     gtgt->AddSource(fname);
@@ -4519,6 +4526,7 @@ bool cmGlobalXCodeGenerator::CreateGroups(
           gtgt->GetLocalGenerator()->GetCurrentSourceDirectory());
         cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
           listfile, false, cmSourceFileLocationKind::Known);
+        sf->SetSpecialSourceType(cmSourceFile::SpecialSourceType::CMakeLists);
         addSourceToGroup(sf->ResolveFullPath());
       }
 
@@ -4527,6 +4535,8 @@ bool cmGlobalXCodeGenerator::CreateGroups(
         std::string plist = this->ComputeInfoPListLocation(gtgt.get());
         cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
           plist, true, cmSourceFileLocationKind::Known);
+        sf->SetSpecialSourceType(
+          cmSourceFile::SpecialSourceType::BundleInfoPlist);
         addSourceToGroup(sf->ResolveFullPath());
       }
     }

+ 2 - 0
Source/cmGlobalXCodeGenerator.h

@@ -116,6 +116,8 @@ public:
 
   bool ShouldStripResourcePath(cmMakefile*) const override;
 
+  bool SupportsCustomObjectNames() const override { return false; }
+
   /**
    * Used to determine if this generator supports DEPFILE option.
    */

+ 3 - 1
Source/cmLocalCommonGenerator.cxx

@@ -116,7 +116,7 @@ std::string cmLocalCommonGenerator::GetTargetDirectory(
 
 void cmLocalCommonGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-  cmGeneratorTarget const* gt)
+  std::string const& config, cmGeneratorTarget const* gt)
 {
   // Determine if these object files should use a custom extension
   char const* custom_ext = gt->GetCustomObjectExtension();
@@ -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);
   }
 }

+ 1 - 1
Source/cmLocalCommonGenerator.h

@@ -45,7 +45,7 @@ public:
 
   void ComputeObjectFilenames(
     std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-    cmGeneratorTarget const* gt = nullptr) override;
+    std::string const& config, cmGeneratorTarget const* gt = nullptr) override;
 
 protected:
   std::vector<std::string> ConfigNames;

+ 3 - 1
Source/cmLocalFastbuildGenerator.cxx

@@ -60,12 +60,14 @@ cmLocalFastbuildGenerator::GetGlobalFastbuildGenerator()
 
 void cmLocalFastbuildGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-  cmGeneratorTarget const* gt)
+  std::string const& config, cmGeneratorTarget const* gt)
 {
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
     si.second.LongLoc =
       this->GetObjectFileNameWithoutTarget(*sf, gt->ObjectDirectory);
+    this->FillCustomInstallObjectLocations(*sf, config, nullptr,
+                                           si.second.InstallLongLoc);
   }
 }
 

+ 1 - 1
Source/cmLocalFastbuildGenerator.h

@@ -26,7 +26,7 @@ public:
 
   void ComputeObjectFilenames(
     std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-    cmGeneratorTarget const* gt = nullptr) override;
+    std::string const& config, cmGeneratorTarget const* gt = nullptr) override;
 
   cmGlobalFastbuildGenerator const* GetGlobalFastbuildGenerator() const;
   cmGlobalFastbuildGenerator* GetGlobalFastbuildGenerator();

+ 212 - 3
Source/cmLocalGenerator.cxx

@@ -25,6 +25,7 @@
 #include "cmsys/RegularExpression.hxx"
 
 #include "cmAlgorithms.h"
+#include "cmCMakePath.h"
 #include "cmComputeLinkInformation.h"
 #include "cmCryptoHash.h"
 #include "cmCustomCommand.h"
@@ -44,6 +45,7 @@
 #include "cmList.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmObjectLocation.h"
 #include "cmRange.h"
 #include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
@@ -2786,6 +2788,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
 
         auto* pch_sf = this->Makefile->GetOrCreateSource(
           pchSource, false, cmSourceFileLocationKind::Known);
+        pch_sf->SetSpecialSourceType(
+          cmSourceFile::SpecialSourceType::PchSource);
         // PCH sources should never be scanned as they cannot contain C++
         // module references.
         pch_sf->SetProperty("CXX_SCAN_FOR_MODULES", "0");
@@ -2881,6 +2885,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
           // be grouped as "Precompile Header File"
           auto* pchHeader_sf = this->Makefile->GetOrCreateSource(
             pchHeader, false, cmSourceFileLocationKind::Known);
+          pchHeader_sf->SetSpecialSourceType(
+            cmSourceFile::SpecialSourceType::PchHeader);
           std::string err;
           pchHeader_sf->ResolveFullPath(&err);
           if (!err.empty()) {
@@ -2989,7 +2995,9 @@ void cmLocalGenerator::CopyPchCompilePdb(
     cmSourceFile* copy_rule = this->AddCustomCommandToOutput(std::move(cc));
     if (copy_rule) {
       copy_rule->SetProperty("CXX_SCAN_FOR_MODULES", "0");
-      target->AddSource(copy_rule->ResolveFullPath());
+      auto* pch_pdb_sf = target->AddSource(copy_rule->ResolveFullPath());
+      pch_pdb_sf->SetSpecialSourceType(
+        cmSourceFile::SpecialSourceType::PchPdbReuseSource);
     }
   }
 }
@@ -3338,6 +3346,8 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
 
     for (UnitySource const& file : unity_files) {
       auto* unity = this->GetMakefile()->GetOrCreateSource(file.Path);
+      unity->SetSpecialSourceType(
+        cmSourceFile::SpecialSourceType::UnitySource);
       target->AddSource(file.Path, true);
       unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON");
       unity->SetProperty("UNITY_SOURCE_FILE", file.Path);
@@ -4148,7 +4158,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(
 
 void cmLocalGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, cmObjectLocations>& /*unused*/,
-  cmGeneratorTarget const* /*unused*/)
+  std::string const& /*unused*/, cmGeneratorTarget const* /*unused*/)
 {
 }
 
@@ -4229,6 +4239,193 @@ std::string cmLocalGenerator::GetRelativeSourceFileName(
   return objectName;
 }
 
+std::string cmLocalGenerator::GetCustomObjectFileName(
+  cmSourceFile const& source) const
+{
+  if (!this->GetGlobalGenerator()->SupportsCustomObjectNames()) {
+    return std::string{};
+  }
+
+  if (auto objName = source.GetProperty("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  \"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  \"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  \"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, "");
+    if (cge->GetHadContextSensitiveCondition()) {
+      this->Makefile->IssueMessage(
+        MessageType::FATAL_ERROR,
+        cmStrCat("The  \"OBJECT_NAME\" property for\n  ", source.GetFullPath(),
+                 "\ncontains a context-sensitive condition which is not "
+                 "supported (",
+                 objName, ")."));
+      return INVALID_GENEX;
+    }
+
+    // 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  \"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  \"OBJECT_NAME\" property for\n  ",
+                   source.GetFullPath(), "\ncontains an invalid component (",
+                   objNameValue, ")."));
+        return INVALID_VALUE;
+      }
+
+      return objNameValue;
+    }
+  }
+
+  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,
@@ -4239,6 +4436,18 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
     useShortObjectNames = *forceShortObjectName;
   }
 
+  if (!useShortObjectNames &&
+      this->GetGlobalGenerator()->SupportsCustomObjectNames()) {
+    auto customName = this->GetCustomObjectFileName(source);
+    if (!customName.empty()) {
+      auto ext = this->GlobalGenerator->GetLanguageOutputExtension(source);
+      if (customOutputExtension) {
+        ext = *customOutputExtension;
+      }
+      return cmStrCat(customName, ext);
+    }
+  }
+
   // This can return an absolute path in the case where source is
   // not relative to the current source or binary directories
   std::string objectName = this->GetRelativeSourceFileName(source);
@@ -4250,7 +4459,7 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
       objectName = cmSystemTools::GetFilenameName(source.GetFullPath());
     }
   }
-  bool const isPchObject = objectName.find("cmake_pch") != std::string::npos;
+  bool const isPchObject = source.IsPchHeader() || source.IsPchSource();
 
   // Short object path policy selected, use as little info as necessary to
   // select an object name

+ 10 - 1
Source/cmLocalGenerator.h

@@ -37,6 +37,7 @@ class cmImplicitDependsList;
 class cmLinkLineComputer;
 class cmLinkLineDeviceComputer;
 class cmMakefile;
+struct cmObjectLocation;
 struct cmObjectLocations;
 class cmRulePlaceholderExpander;
 class cmSourceFile;
@@ -452,6 +453,14 @@ public:
   virtual std::string GetShortObjectFileName(cmSourceFile const& source) const;
   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.
@@ -528,7 +537,7 @@ public:
 
   virtual void ComputeObjectFilenames(
     std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-    cmGeneratorTarget const* gt = nullptr);
+    std::string const& config, cmGeneratorTarget const* gt = nullptr);
 
   bool IsWindowsShell() const;
   bool IsWatcomWMake() const;

+ 23 - 8
Source/cmLocalGhsMultiGenerator.cxx

@@ -50,7 +50,7 @@ void cmLocalGhsMultiGenerator::Generate()
 
 void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-  cmGeneratorTarget const* gt)
+  std::string const& config, cmGeneratorTarget const* gt)
 {
   std::string dir_max = cmStrCat(gt->GetSupportDirectory(), '/');
 
@@ -60,10 +60,16 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
 
   for (auto const& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectNameLower = cmStrCat(
-      cmSystemTools::LowerCase(
-        cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())),
-      this->GlobalGenerator->GetLanguageOutputExtension(*sf));
+    std::string objectName;
+    auto customObjectName = this->GetCustomObjectFileName(*sf);
+    if (customObjectName.empty()) {
+      objectName =
+        cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+    } else {
+      objectName = std::move(customObjectName);
+    }
+    objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+    std::string objectNameLower = cmSystemTools::LowerCase(objectName);
     counts[objectNameLower] += 1;
   }
 
@@ -74,9 +80,16 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
     bool forceShortObjectName = true;
     std::string shortObjectName = this->GetObjectFileNameWithoutTarget(
       *sf, dir_max, nullptr, nullptr, &forceShortObjectName);
-    std::string longObjectName = cmStrCat(
-      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()),
-      this->GlobalGenerator->GetLanguageOutputExtension(*sf));
+    std::string longObjectName;
+    auto customObjectName = this->GetCustomObjectFileName(*sf);
+    if (customObjectName.empty()) {
+      longObjectName =
+        cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+    } else {
+      longObjectName = std::move(customObjectName);
+      const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
+    }
+    longObjectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
 
     if (counts[cmSystemTools::LowerCase(longObjectName)] > 1) {
       const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
@@ -87,5 +100,7 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
     }
     si.second.ShortLoc.emplace(shortObjectName);
     si.second.LongLoc.Update(longObjectName);
+    this->FillCustomInstallObjectLocations(*sf, config, nullptr,
+                                           si.second.InstallLongLoc);
   }
 }

+ 1 - 1
Source/cmLocalGhsMultiGenerator.h

@@ -40,5 +40,5 @@ public:
 
   void ComputeObjectFilenames(
     std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-    cmGeneratorTarget const* gt = nullptr) override;
+    std::string const& config, cmGeneratorTarget const* gt = nullptr) override;
 };

+ 19 - 5
Source/cmLocalVisualStudioGenerator.cxx

@@ -40,7 +40,7 @@ cmLocalVisualStudioGenerator::GetVersion() const
 
 void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-  cmGeneratorTarget const* gt)
+  std::string const& config, cmGeneratorTarget const* gt)
 {
   char const* custom_ext = gt->GetCustomObjectExtension();
   std::string dir_max = this->ComputeLongestObjectDirectory(gt);
@@ -55,8 +55,13 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
     if (gt->GetUseShortObjectNames()) {
       baseObjectName = this->GetShortObjectFileName(*sf);
     } else {
-      baseObjectName =
-        cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+      auto customObjectName = this->GetCustomObjectFileName(*sf);
+      if (customObjectName.empty()) {
+        baseObjectName =
+          cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+      } else {
+        baseObjectName = std::move(customObjectName);
+      }
     }
     std::string objectNameLower = cmSystemTools::LowerCase(baseObjectName);
     if (custom_ext) {
@@ -74,8 +79,15 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
     std::string shortObjectName = this->GetShortObjectFileName(*sf);
-    std::string longObjectName =
-      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+    std::string longObjectName;
+    auto customObjectName = this->GetCustomObjectFileName(*sf);
+    if (customObjectName.empty()) {
+      longObjectName =
+        cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+    } else {
+      longObjectName = std::move(customObjectName);
+      const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
+    }
     if (custom_ext) {
       shortObjectName += custom_ext;
       longObjectName += custom_ext;
@@ -92,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 - 1
Source/cmLocalVisualStudioGenerator.h

@@ -51,7 +51,7 @@ public:
 
   void ComputeObjectFilenames(
     std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-    cmGeneratorTarget const* = nullptr) override;
+    std::string const& config, cmGeneratorTarget const* = nullptr) override;
 
   std::string GetObjectOutputRoot(
     cmStateEnums::IntermediateDirKind kind =

+ 4 - 1
Source/cmLocalXCodeGenerator.cxx

@@ -121,6 +121,7 @@ void cmLocalXCodeGenerator::AddGeneratorSpecificInstallSetup(std::ostream& os)
 
 void cmLocalXCodeGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, cmObjectLocations>& mapping,
+  std::string const& config,
   cmGeneratorTarget const*)
 {
   // Count the number of object files with each name. Warn about duplicate
@@ -141,6 +142,7 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames(
     }
     si.second.ShortLoc.emplace(shortObjectName);
     si.second.LongLoc.Update(longObjectName);
+    this->FillCustomInstallObjectLocations(*sf, config, ".o", si.second.InstallLongLoc);
   }
 }
 
@@ -158,7 +160,8 @@ void cmLocalXCodeGenerator::AddXCConfigSources(cmGeneratorTarget* target)
       *xcconfig,
       this, config);
     if (!file.empty()) {
-      target->AddSource(file);
+      auto* xcconfig_sf = target->AddSource(file);
+      xcconfig_sf->SetSpecialSourceType(cmSourceFile::SpecialSourceType::XcodeXCConfigFile);
     }
   }
 }

+ 1 - 1
Source/cmLocalXCodeGenerator.h

@@ -38,7 +38,7 @@ public:
   void AddGeneratorSpecificInstallSetup(std::ostream& os) override;
   void ComputeObjectFilenames(
     std::map<cmSourceFile const*, cmObjectLocations>& mapping,
-    cmGeneratorTarget const* gt = nullptr) override;
+    std::string const& config, cmGeneratorTarget const* gt = nullptr) override;
 
   void AddXCConfigSources(cmGeneratorTarget* target) override;
 

+ 1 - 0
Source/cmMakefile.cxx

@@ -3147,6 +3147,7 @@ void cmMakefile::AddTargetObject(std::string const& tgtName,
 {
   cmSourceFile* sf =
     this->GetOrCreateSource(objFile, true, cmSourceFileLocationKind::Known);
+  sf->SetSpecialSourceType(cmSourceFile::SpecialSourceType::Object);
   sf->SetObjectLibrary(tgtName);
   sf->SetProperty("EXTERNAL_OBJECT", "1");
   // TODO: Compute a language for this object based on the associated source

+ 19 - 0
Source/cmObjectLocation.cxx

@@ -45,3 +45,22 @@ std::string const& cmObjectLocations::GetPath(UseShortPath use) const
 {
   return this->GetLocation(use).GetPath();
 }
+
+cmObjectLocation const& cmObjectLocations::GetInstallLocation(
+  UseShortPath use, std::string const& config) const
+{
+  if (use == UseShortPath::Yes && this->ShortLoc) {
+    return *this->ShortLoc;
+  }
+  auto it = this->InstallLongLoc.find(config);
+  if (it != this->InstallLongLoc.end()) {
+    return it->second;
+  }
+  return this->LongLoc;
+}
+
+std::string const& cmObjectLocations::GetInstallPath(
+  UseShortPath use, std::string const& config) const
+{
+  return this->GetInstallLocation(use, config).GetPath();
+}

+ 7 - 0
Source/cmObjectLocation.h

@@ -4,6 +4,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <map>
 #include <string>
 #include <utility>
 
@@ -39,6 +40,7 @@ struct cmObjectLocations
 
   cm::optional<cmObjectLocation> ShortLoc;
   cmObjectLocation LongLoc;
+  std::map<std::string, cmObjectLocation> InstallLongLoc;
 
   enum class UseShortPath
   {
@@ -47,4 +49,9 @@ struct cmObjectLocations
   };
   cmObjectLocation const& GetLocation(UseShortPath use) const;
   std::string const& GetPath(UseShortPath use) const;
+
+  cmObjectLocation const& GetInstallLocation(UseShortPath use,
+                                             std::string const& config) const;
+  std::string const& GetInstallPath(UseShortPath use,
+                                    std::string const& config) const;
 };

+ 2 - 0
Source/cmQTWrapCPPCommand.cxx

@@ -43,6 +43,8 @@ bool cmQTWrapCPPCommand(std::vector<std::string> const& args,
       std::string newName =
         cmStrCat(mf.GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx");
       cmSourceFile* sf = mf.GetOrCreateSource(newName, true);
+      sf->SetSpecialSourceType(
+        cmSourceFile::SpecialSourceType::QtWrapCppSource);
       if (curr) {
         sf->SetProperty("ABSTRACT", curr->GetProperty("ABSTRACT"));
       }

+ 2 - 0
Source/cmQtAutoGenInitializer.cxx

@@ -2105,6 +2105,8 @@ cmSourceFile* cmQtAutoGenInitializer::RegisterGeneratedSource(
   std::string const& filename)
 {
   cmSourceFile* gFile = this->Makefile->GetOrCreateSource(filename, true);
+  gFile->SetSpecialSourceType(
+    cmSourceFile::SpecialSourceType::QtAutogenSource);
   gFile->MarkAsGenerated();
   gFile->SetProperty("SKIP_AUTOGEN", "1");
   gFile->SetProperty("SKIP_LINTING", "ON");

+ 15 - 0
Source/cmSourceFile.cxx

@@ -29,6 +29,21 @@ cmSourceFile::cmSourceFile(cmMakefile* mf, std::string const& name,
   }
 }
 
+void cmSourceFile::SetSpecialSourceType(cmSourceFile::SpecialSourceType type)
+{
+  this->SpecialSource = type;
+}
+
+bool cmSourceFile::IsPchHeader() const
+{
+  return this->SpecialSource == SpecialSourceType::PchHeader;
+}
+
+bool cmSourceFile::IsPchSource() const
+{
+  return this->SpecialSource == SpecialSourceType::PchSource;
+}
+
 std::string const& cmSourceFile::GetExtension() const
 {
   return this->Extension;

+ 31 - 0
Source/cmSourceFile.h

@@ -40,6 +40,36 @@ public:
   cmCustomCommand* GetCustomCommand() const;
   void SetCustomCommand(std::unique_ptr<cmCustomCommand> cc);
 
+  enum class SpecialSourceType
+  {
+    // Sources for user-provided sources.
+    User,
+    // Source files for object files.
+    Object,
+    // Sources representing `CMakeLists.txt` files.
+    CMakeLists,
+    // Xcode `Info.plist` files for bundle targets.
+    BundleInfoPlist,
+    // Xcode source to force a link to occur with an appropriate language.
+    XcodeForceLinkerSource,
+    // Xcode `
+    XcodeXCConfigFile,
+    // Header set verification files.
+    HeaderSetVerificationSource,
+    // PCH files.
+    PchHeader,
+    PchSource,
+    PchPdbReuseSource,
+    // Unity sources.
+    UnitySource,
+    // Qt support sources.
+    QtWrapCppSource,
+    QtAutogenSource,
+  };
+  void SetSpecialSourceType(SpecialSourceType type);
+  bool IsPchHeader() const;
+  bool IsPchSource() const;
+
   //! Set/Get a property of this source file
   void SetProperty(std::string const& prop, cmValue value);
   void RemoveProperty(std::string const& prop)
@@ -166,6 +196,7 @@ private:
   std::vector<BT<std::string>> IncludeDirectories;
   bool FindFullPathFailed = false;
   bool IsGenerated = false;
+  SpecialSourceType SpecialSource = SpecialSourceType::User;
 
   bool FindFullPath(std::string* error, std::string* cmp0115Warning);
   void CheckExtension();

+ 10 - 5
Source/cmVisualStudio10TargetGenerator.cxx

@@ -2721,16 +2721,21 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
         this->WriteExcludeFromBuild(e2, exclude_configs);
       }
 
+      std::string customObjectName;
       if (this->GlobalGenerator->UseShortObjectNames()) {
+        customObjectName =
+          this->LocalGenerator->GetShortObjectFileName(*si.Source);
+      } else {
+        customObjectName =
+          this->LocalGenerator->GetCustomObjectFileName(*si.Source);
+      }
+      if (!customObjectName.empty()) {
         std::string outputName = "ObjectFileName";
         if (si.Source->GetLanguage() == "CUDA"_s) {
           outputName = "CompileOut";
         }
-        e2.Element(
-          outputName,
-          cmStrCat("$(IntDir)",
-                   this->LocalGenerator->GetShortObjectFileName(*si.Source),
-                   ".obj"));
+        e2.Element(outputName,
+                   cmStrCat("$(IntDir)", customObjectName, ".obj"));
       }
 
       this->FinishWritingSource(e2, toolSettings);

+ 2 - 0
Tests/RunCMake/CMakeLists.txt

@@ -570,6 +570,8 @@ 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)
 if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG)

+ 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);
+}

+ 3 - 0
Tests/RunCMake/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/OBJECT_NAME/Collision-result.txt

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

+ 1 - 0
Tests/RunCMake/OBJECT_NAME/Collision-stderr.txt

@@ -0,0 +1 @@
+((Ninja)?multiple rules generate CMakeFiles/objlib.dir/objlib_lib.c.o)

+ 1 - 0
Tests/RunCMake/OBJECT_NAME/Collision.cmake

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

+ 1 - 0
Tests/RunCMake/OBJECT_NAME/CollisionBuild-build-result.txt

@@ -0,0 +1 @@
+(1|(Makefiles)?2)

+ 1 - 0
Tests/RunCMake/OBJECT_NAME/CollisionBuild-build-stderr.txt

@@ -0,0 +1 @@
+((Ninja Multi-Config)?multiple rules generate CMakeFiles/objlib.dir/Debug/objlib_lib.c.o|(Makefiles)?((Linux)?undefined reference to `[fg]'|(macOS)?"?_[fg]"?, referenced from:|(Solaris)?[fg][ \t]*CMakeFiles/usefuncs.dir/test.c.o|(AIX)?Undefined symbol: \.[fg]|(FreeBSD)?undefined symbol: [fg])|(NMake Makefiles)?NMAKE : |(NMake Makefiles JOM)?jom: |(Watcom WMake)?Last command making \(usefuncs.exe\) returned a bad status|^$)

+ 1 - 0
Tests/RunCMake/OBJECT_NAME/CollisionBuild-build-stdout.txt

@@ -0,0 +1 @@
+((NMake Makefiles)?unresolved external symbol [fg] referenced in function main|(Watcom WMake)?undefined symbol [fg]_|)

+ 1 - 0
Tests/RunCMake/OBJECT_NAME/CollisionBuild-stderr.txt

@@ -0,0 +1 @@
+((Makefiles)?Warning: Source file "[^"]*/Tests/RunCMake/OBJECT_NAME/lib2?.c" is listed multiple times for target "objlib".|^$)

+ 7 - 0
Tests/RunCMake/OBJECT_NAME/CollisionBuild.cmake

@@ -0,0 +1,7 @@
+set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
+
+add_library(objlib OBJECT lib.c lib2.c)
+set_property(SOURCE lib.c lib2.c PROPERTY OBJECT_NAME "objlib_lib.c")
+
+add_executable(usefuncs test.c)
+target_link_libraries(usefuncs PRIVATE objlib)

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

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

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

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

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

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

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

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

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

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

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

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

+ 5 - 0
Tests/RunCMake/OBJECT_NAME/DisableOnEmpty-build-check.cmake

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

+ 5 - 0
Tests/RunCMake/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/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 OBJECT_NAME "$<$<BOOL:0>:objlib_lib.c>")
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/ON FILE on-config.cmake NAMESPACE ON::)

+ 1 - 0
Tests/RunCMake/OBJECT_NAME/Executable-build-check.cmake

@@ -0,0 +1 @@
+check_build_object(exe exe_main.c)

+ 4 - 0
Tests/RunCMake/OBJECT_NAME/Executable.cmake

@@ -0,0 +1,4 @@
+set(CMAKE_INTERMEDIATE_DIR_STRATEGY FULL CACHE STRING "" FORCE)
+
+add_executable(exe main.c lib.c)
+set_property(SOURCE main.c PROPERTY OBJECT_NAME "exe_main.c")

+ 1 - 0
Tests/RunCMake/OBJECT_NAME/GeneratorExpression-build-check.cmake

@@ -0,0 +1 @@
+check_build_object(objlib 1/objlib_lib.c)

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

Some files were not shown because too many files changed in this diff