소스 검색

objects: implement installation naming strategies

Ben Boeckel 7 달 전
부모
커밋
c651b0e002
36개의 변경된 파일301개의 추가작업 그리고 63개의 파일을 삭제
  1. 49 5
      Source/cmGeneratorTarget.cxx
  2. 10 2
      Source/cmGeneratorTarget.h
  3. 7 2
      Source/cmGlobalVisualStudioGenerator.cxx
  4. 52 15
      Source/cmInstallTargetGenerator.cxx
  5. 1 0
      Source/cmInstallTargetGenerator.h
  6. 10 3
      Source/cmLocalCommonGenerator.cxx
  7. 2 1
      Source/cmLocalCommonGenerator.h
  8. 8 3
      Source/cmLocalGenerator.cxx
  9. 4 2
      Source/cmLocalGenerator.h
  10. 15 8
      Source/cmLocalGhsMultiGenerator.cxx
  11. 2 1
      Source/cmLocalGhsMultiGenerator.h
  12. 13 13
      Source/cmLocalVisualStudioGenerator.cxx
  13. 2 1
      Source/cmLocalVisualStudioGenerator.h
  14. 8 6
      Source/cmLocalXCodeGenerator.cxx
  15. 2 1
      Source/cmLocalXCodeGenerator.h
  16. 1 0
      Tests/RunCMake/CMakeLists.txt
  17. 3 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/CMakeLists.txt
  18. 3 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Common.cmake
  19. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-Default.cmake
  20. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake
  21. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake
  22. 7 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume.cmake
  23. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default-install-check.cmake
  24. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default.cmake
  25. 8 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL-install-check.cmake
  26. 3 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake
  27. 1 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt
  28. 6 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-stderr.txt
  29. 3 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID.cmake
  30. 10 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Inspect.cmake
  31. 45 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/RunCMakeTest.cmake
  32. 2 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT-install-check.cmake
  33. 3 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake
  34. 7 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/main.c
  35. 4 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c
  36. 4 0
      Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c

+ 49 - 5
Source/cmGeneratorTarget.cxx

@@ -856,7 +856,10 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
 std::string const& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
 {
   this->ComputeObjectMapping();
-  return this->Objects[file];
+  auto const useShortPaths = this->GetUseShortObjectNames()
+    ? cmObjectLocations::UseShortPath::Yes
+    : cmObjectLocations::UseShortPath::No;
+  return this->Objects[file].GetPath(useShortPaths);
 }
 
 char const* cmGeneratorTarget::GetCustomObjectExtension() const
@@ -3994,10 +3997,22 @@ std::string cmGeneratorTarget::GetObjectDirectory(
 
 void cmGeneratorTarget::GetTargetObjectNames(
   std::string const& config, std::vector<std::string>& objects) const
+{
+  this->GetTargetObjectLocations(
+    config,
+    [&objects](cmObjectLocation const& buildLoc, cmObjectLocation const&) {
+      objects.push_back(buildLoc.GetPath());
+    });
+}
+
+void cmGeneratorTarget::GetTargetObjectLocations(
+  std::string const& config,
+  std::function<void(cmObjectLocation const&, cmObjectLocation const&)> cb)
+  const
 {
   std::vector<cmSourceFile const*> objectSources;
   this->GetObjectSources(objectSources, config);
-  std::map<cmSourceFile const*, std::string> mapping;
+  std::map<cmSourceFile const*, cmObjectLocations> mapping;
 
   for (cmSourceFile const* sf : objectSources) {
     mapping[sf];
@@ -4005,12 +4020,20 @@ void cmGeneratorTarget::GetTargetObjectNames(
 
   this->LocalGenerator->ComputeObjectFilenames(mapping, this);
 
+  auto const buildUseShortPaths = this->GetUseShortObjectNames()
+    ? cmObjectLocations::UseShortPath::Yes
+    : cmObjectLocations::UseShortPath::No;
+  auto const installUseShortPaths = this->GetUseShortObjectNamesForInstall();
+
   for (cmSourceFile const* src : objectSources) {
     // 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);
     // It must exist because we populated the mapping just above.
-    assert(!map_it->second.empty());
-    objects.push_back(map_it->second);
+    assert(!buildLoc.GetPath().empty());
+    assert(!installLoc.GetPath().empty());
+    cb(buildLoc, installLoc);
   }
 
   // We need to compute the relative path from the root of
@@ -4020,7 +4043,9 @@ void cmGeneratorTarget::GetTargetObjectNames(
   auto ispcObjects = this->GetGeneratedISPCObjects(config);
   for (std::string const& output : ispcObjects) {
     auto relativePathFromObjectDir = output.substr(rootObjectDir.size());
-    objects.push_back(relativePathFromObjectDir);
+    cmObjectLocation ispcLoc(relativePathFromObjectDir);
+    // FIXME: apply short path to this object if needed.
+    cb(ispcLoc, ispcLoc);
   }
 }
 
@@ -5370,6 +5395,25 @@ bool cmGeneratorTarget::GetUseShortObjectNames(
   return this->LocalGenerator->UseShortObjectNames(kind);
 }
 
+cmObjectLocations::UseShortPath
+cmGeneratorTarget::GetUseShortObjectNamesForInstall() const
+{
+  auto prop = this->Target->GetProperty("INSTALL_OBJECT_NAME_STRATEGY");
+  if (prop == "SHORT"_s) {
+    return cmObjectLocations::UseShortPath::Yes;
+  }
+  if (prop == "FULL"_s) {
+    return cmObjectLocations::UseShortPath::No;
+  }
+  if (prop.IsSet()) {
+    this->Makefile->IssueMessage(
+      MessageType::FATAL_ERROR,
+      cmStrCat("Property INSTALL_OBJECT_NAME_STRATEGY of target \"",
+               this->GetName(), "\" set to the unsupported strategy ", prop));
+  }
+  return cmObjectLocations::UseShortPath::No;
+}
+
 std::string cmGeneratorTarget::GetSupportDirectory(
   cmStateEnums::IntermediateDirKind kind) const
 {

+ 10 - 2
Source/cmGeneratorTarget.h

@@ -5,6 +5,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <cstddef>
+#include <functional>
 #include <map>
 #include <memory>
 #include <set>
@@ -20,6 +21,7 @@
 #include "cmAlgorithms.h"
 #include "cmLinkItem.h"
 #include "cmListFileCache.h"
+#include "cmObjectLocation.h"
 #include "cmPolicies.h"
 #include "cmStandardLevel.h"
 #include "cmStateTypes.h"
@@ -298,9 +300,14 @@ public:
                                   cmStateEnums::RuntimeBinaryArtifact) const;
 
   /** Get the names of an object library's object files underneath
-      its object file directory.  */
+      its object file directory for the build.  */
   void GetTargetObjectNames(std::string const& config,
                             std::vector<std::string>& objects) const;
+  /** Get the build and install locations of objects for a given context. */
+  void GetTargetObjectLocations(
+    std::string const& config,
+    std::function<void(cmObjectLocation const&, cmObjectLocation const&)> cb)
+    const;
 
   /** What hierarchy level should the reported directory contain */
   enum BundleDirectoryLevel
@@ -940,6 +947,7 @@ public:
   bool GetUseShortObjectNames(
     cmStateEnums::IntermediateDirKind kind =
       cmStateEnums::IntermediateDirKind::ObjectFiles) const;
+  cmObjectLocations::UseShortPath GetUseShortObjectNamesForInstall() const;
 
   /** Get a build-tree directory in which to place target support files.  */
   std::string GetSupportDirectory(
@@ -1142,7 +1150,7 @@ private:
   using SourceEntriesType = std::map<cmSourceFile const*, SourceEntry>;
   SourceEntriesType SourceDepends;
   mutable std::set<std::string> VisitedConfigsForObjects;
-  mutable std::map<cmSourceFile const*, std::string> Objects;
+  mutable std::map<cmSourceFile const*, cmObjectLocations> Objects;
   std::set<cmSourceFile const*> ExplicitObjectName;
 
   using TargetPtrToBoolMap = std::unordered_map<cmTarget*, bool>;

+ 7 - 2
Source/cmGlobalVisualStudioGenerator.cxx

@@ -873,7 +873,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
   std::vector<std::string> empty;
   std::vector<cmSourceFile const*> objectSources;
   gt->GetObjectSources(objectSources, configName);
-  std::map<cmSourceFile const*, std::string> mapping;
+  std::map<cmSourceFile const*, cmObjectLocations> mapping;
   for (cmSourceFile const* it : objectSources) {
     mapping[it];
   }
@@ -891,12 +891,17 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
     return;
   }
 
+  auto const useShortPaths = this->UseShortObjectNames()
+    ? cmObjectLocations::UseShortPath::Yes
+    : cmObjectLocations::UseShortPath::No;
+
   if (mdi->WindowsExportAllSymbols) {
     std::vector<std::string> objs;
     for (cmSourceFile const* it : objectSources) {
       // Find the object file name corresponding to this source file.
       // It must exist because we populated the mapping just above.
-      auto const& v = mapping[it];
+      auto const& locs = mapping[it];
+      std::string const& v = locs.GetPath(useShortPaths);
       assert(!v.empty());
       std::string objFile = cmStrCat(obj_dir, v);
       objs.push_back(objFile);

+ 52 - 15
Source/cmInstallTargetGenerator.cxx

@@ -4,6 +4,7 @@
 
 #include <algorithm>
 #include <cassert>
+#include <cstddef>
 #include <functional>
 #include <map>
 #include <set>
@@ -21,6 +22,7 @@
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmObjectLocation.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
 #include "cmScriptGenerator.h"
@@ -174,18 +176,40 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
 
   // Write code to install the target file.
   char const* no_dir_permissions = nullptr;
-  char const* no_rename = nullptr;
   bool optional = this->Optional || this->ImportLibrary;
   std::string literal_args;
-  if (!files.FromDir.empty()) {
-    literal_args += " FILES_FROM_DIR \"" + files.FromDir + "\"";
-  }
   if (files.UseSourcePermissions) {
     literal_args += " USE_SOURCE_PERMISSIONS";
   }
-  this->AddInstallRule(os, dest, files.Type, files.From, optional,
-                       this->FilePermissions.c_str(), no_dir_permissions,
-                       no_rename, literal_args.c_str(), indent);
+  if (files.Rename) {
+    if (files.From.size() != files.To.size()) {
+      this->Target->GetLocalGenerator()->IssueMessage(
+        MessageType::INTERNAL_ERROR,
+        "cmInstallTargetGenerator generated a rename request with mismatched "
+        "names.");
+      return;
+    }
+    std::vector<std::string> FileNames;
+    FileNames.resize(1);
+    for (size_t i = 0; i < files.From.size(); ++i) {
+      if (files.FromDir.empty()) {
+        FileNames[0] = files.From[i];
+      } else {
+        FileNames[0] = cmStrCat(files.FromDir, '/', files.From[i]);
+      }
+      this->AddInstallRule(os, dest, files.Type, FileNames, optional,
+                           this->FilePermissions.c_str(), no_dir_permissions,
+                           files.To[i].c_str(), literal_args.c_str(), indent);
+    }
+  } else {
+    char const* no_rename = nullptr;
+    if (!files.FromDir.empty()) {
+      literal_args += " FILES_FROM_DIR \"" + files.FromDir + "\"";
+    }
+    this->AddInstallRule(os, dest, files.Type, files.From, optional,
+                         this->FilePermissions.c_str(), no_dir_permissions,
+                         no_rename, literal_args.c_str(), indent);
+  }
 
   // Add post-installation tweaks.
   if (!files.NoTweak) {
@@ -225,16 +249,21 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
 
     case cmStateEnums::OBJECT_LIBRARY: {
       // Compute all the object files inside this target
-      std::vector<std::string> objects;
-      this->Target->GetTargetObjectNames(config, objects);
+      std::vector<std::pair<cmObjectLocation, cmObjectLocation>> objects;
+      auto storeObjectLocations = [&objects](cmObjectLocation const& build,
+                                             cmObjectLocation const& install) {
+        objects.emplace_back(build, install);
+      };
+      this->Target->GetTargetObjectLocations(config, storeObjectLocations);
 
       files.Type = cmInstallType_FILES;
       files.NoTweak = true;
+      files.Rename = true;
       files.FromDir = this->Target->GetObjectDirectory(config);
       files.ToDir = computeInstallObjectDir(this->Target, config);
-      for (std::string& obj : objects) {
-        files.From.emplace_back(obj);
-        files.To.emplace_back(std::move(obj));
+      for (auto const& obj : objects) {
+        files.From.emplace_back(obj.first.GetPath());
+        files.To.emplace_back(obj.second.GetPath());
       }
       return files;
     }
@@ -423,9 +452,17 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
 void cmInstallTargetGenerator::GetInstallObjectNames(
   std::string const& config, std::vector<std::string>& objects) const
 {
-  this->Target->GetTargetObjectNames(config, objects);
-  for (std::string& o : objects) {
-    o = cmStrCat(computeInstallObjectDir(this->Target, config), '/', o);
+  std::vector<cmObjectLocation> installedObjects;
+  auto storeObjectLocations =
+    [&installedObjects](cmObjectLocation const&,
+                        cmObjectLocation const& install) {
+      installedObjects.emplace_back(install);
+    };
+  this->Target->GetTargetObjectLocations(config, storeObjectLocations);
+  objects.reserve(installedObjects.size());
+  auto const rootDir = computeInstallObjectDir(this->Target, config);
+  for (cmObjectLocation const& o : installedObjects) {
+    objects.emplace_back(cmStrCat(rootDir, '/', o.GetPath()));
   }
 }
 

+ 1 - 0
Source/cmInstallTargetGenerator.h

@@ -86,6 +86,7 @@ public:
     std::string ToDir;
 
     NamelinkModeType NamelinkMode = NamelinkModeNone;
+    bool Rename = false;
     bool NoTweak = false;
     bool UseSourcePermissions = false;
     cmInstallType Type = cmInstallType();

+ 10 - 3
Source/cmLocalCommonGenerator.cxx

@@ -6,9 +6,12 @@
 #include <utility>
 #include <vector>
 
+#include <cm/optional>
+
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
+#include "cmObjectLocation.h"
 #include "cmOutputConverter.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
@@ -111,7 +114,7 @@ std::string cmLocalCommonGenerator::GetTargetDirectory(
 }
 
 void cmLocalCommonGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& mapping,
+  std::map<cmSourceFile const*, cmObjectLocations>& mapping,
   cmGeneratorTarget const* gt)
 {
   // Determine if these object files should use a custom extension
@@ -119,7 +122,11 @@ void cmLocalCommonGenerator::ComputeObjectFilenames(
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
     bool keptSourceExtension;
-    si.second = this->GetObjectFileNameWithoutTarget(
-      *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext);
+    bool force = true;
+    si.second.ShortLoc.emplace(this->GetObjectFileNameWithoutTarget(
+      *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext, &force));
+    force = false;
+    si.second.LongLoc.Update(this->GetObjectFileNameWithoutTarget(
+      *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext, &force));
   }
 }

+ 2 - 1
Source/cmLocalCommonGenerator.h

@@ -13,6 +13,7 @@
 class cmGeneratorTarget;
 class cmGlobalGenerator;
 class cmMakefile;
+struct cmObjectLocations;
 class cmSourceFile;
 
 /** \class cmLocalCommonGenerator
@@ -39,7 +40,7 @@ public:
     cmGeneratorTarget const* target) const override;
 
   void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* gt = nullptr) override;
 
 protected:

+ 8 - 3
Source/cmLocalGenerator.cxx

@@ -4143,7 +4143,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(
 }
 
 void cmLocalGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& /*unused*/,
+  std::map<cmSourceFile const*, cmObjectLocations>& /*unused*/,
   cmGeneratorTarget const* /*unused*/)
 {
 }
@@ -4227,8 +4227,13 @@ std::string cmLocalGenerator::GetRelativeSourceFileName(
 
 std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
   cmSourceFile const& source, std::string const& dir_max,
-  bool* hasSourceExtension, char const* customOutputExtension)
+  bool* hasSourceExtension, char const* customOutputExtension,
+  bool const* forceShortObjectName)
 {
+  bool useShortObjectNames = this->UseShortObjectNames();
+  if (forceShortObjectName) {
+    useShortObjectNames = *forceShortObjectName;
+  }
 
   // This can return an absolute path in the case where source is
   // not relative to the current source or binary directoreis
@@ -4246,7 +4251,7 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
   // Short object path policy selected, use as little info as necessary to
   // select an object name
   bool keptSourceExtension = true;
-  if (this->UseShortObjectNames()) {
+  if (useShortObjectNames) {
     objectName = this->GetShortObjectFileName(source);
     keptSourceExtension = false;
   }

+ 4 - 2
Source/cmLocalGenerator.h

@@ -37,6 +37,7 @@ class cmImplicitDependsList;
 class cmLinkLineComputer;
 class cmLinkLineDeviceComputer;
 class cmMakefile;
+struct cmObjectLocations;
 class cmRulePlaceholderExpander;
 class cmSourceFile;
 class cmState;
@@ -473,7 +474,8 @@ public:
   std::string GetObjectFileNameWithoutTarget(
     cmSourceFile const& source, std::string const& dir_max,
     bool* hasSourceExtension = nullptr,
-    char const* customOutputExtension = nullptr);
+    char const* customOutputExtension = nullptr,
+    bool const* forceShortObjectName = nullptr);
 
   /** Fill out the static linker flags for the given target.  */
   void GetStaticLibraryFlags(std::string& flags, std::string const& config,
@@ -524,7 +526,7 @@ public:
                                             std::string const& config);
 
   virtual void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* gt = nullptr);
 
   bool IsWindowsShell() const;

+ 15 - 8
Source/cmLocalGhsMultiGenerator.cxx

@@ -5,9 +5,12 @@
 #include <utility>
 #include <vector>
 
+#include <cm/optional>
+
 #include "cmGeneratorTarget.h"
 #include "cmGhsMultiTargetGenerator.h"
 #include "cmGlobalGenerator.h"
+#include "cmObjectLocation.h"
 #include "cmSourceFile.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
@@ -41,7 +44,7 @@ void cmLocalGhsMultiGenerator::Generate()
 }
 
 void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& mapping,
+  std::map<cmSourceFile const*, cmObjectLocations>& mapping,
   cmGeneratorTarget const* gt)
 {
   std::string dir_max = cmStrCat(gt->GetSupportDirectory(), '/');
@@ -63,17 +66,21 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
   // object name computation.
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectName = cmStrCat(
+    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));
 
-    if (counts[cmSystemTools::LowerCase(objectName)] > 1) {
+    if (counts[cmSystemTools::LowerCase(longObjectName)] > 1) {
       const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
-      bool keptSourceExtension;
-      objectName = this->GetObjectFileNameWithoutTarget(*sf, dir_max,
-                                                        &keptSourceExtension);
-      cmsys::SystemTools::ReplaceString(objectName, "/", "_");
+      forceShortObjectName = false;
+      longObjectName = this->GetObjectFileNameWithoutTarget(
+        *sf, dir_max, nullptr, nullptr, &forceShortObjectName);
+      cmsys::SystemTools::ReplaceString(longObjectName, "/", "_");
     }
-    si.second = objectName;
+    si.second.ShortLoc.emplace(shortObjectName);
+    si.second.LongLoc.Update(longObjectName);
   }
 }

+ 2 - 1
Source/cmLocalGhsMultiGenerator.h

@@ -10,6 +10,7 @@
 class cmGeneratorTarget;
 class cmGlobalGenerator;
 class cmMakefile;
+struct cmObjectLocations;
 class cmSourceFile;
 
 /** \class cmLocalGhsMultiGenerator
@@ -34,6 +35,6 @@ public:
     cmGeneratorTarget const* target) const override;
 
   void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* gt = nullptr) override;
 };

+ 13 - 13
Source/cmLocalVisualStudioGenerator.cxx

@@ -39,7 +39,7 @@ cmLocalVisualStudioGenerator::GetVersion() const
 }
 
 void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& mapping,
+  std::map<cmSourceFile const*, cmObjectLocations>& mapping,
   cmGeneratorTarget const* gt)
 {
   char const* custom_ext = gt->GetCustomObjectExtension();
@@ -73,25 +73,25 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
 
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectName;
-    if (gt->GetUseShortObjectNames()) {
-      objectName = this->GetShortObjectFileName(*sf);
-    } else {
-      objectName =
-        cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
-    }
+    std::string shortObjectName = this->GetShortObjectFileName(*sf);
+    std::string longObjectName =
+      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
     if (custom_ext) {
-      objectName += custom_ext;
+      shortObjectName += custom_ext;
+      longObjectName += custom_ext;
     } else {
-      objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+      shortObjectName +=
+        this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+      longObjectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
     }
-    if (counts[cmSystemTools::LowerCase(objectName)] > 1) {
+    if (counts[cmSystemTools::LowerCase(longObjectName)] > 1) {
       const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
       bool keptSourceExtension;
-      objectName = this->GetObjectFileNameWithoutTarget(
+      longObjectName = this->GetObjectFileNameWithoutTarget(
         *sf, dir_max, &keptSourceExtension, custom_ext);
     }
-    si.second = objectName;
+    si.second.ShortLoc.emplace(shortObjectName);
+    si.second.LongLoc.Update(longObjectName);
   }
 }
 

+ 2 - 1
Source/cmLocalVisualStudioGenerator.h

@@ -10,6 +10,7 @@
 
 #include "cmGlobalVisualStudioGenerator.h"
 #include "cmLocalGenerator.h"
+#include "cmObjectLocation.h"
 #include "cmStateTypes.h"
 #include "cmVsProjectType.h"
 
@@ -49,7 +50,7 @@ public:
     cmGeneratorTarget const*) const = 0;
 
   void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* = nullptr) override;
 
   std::string GetObjectOutputRoot(

+ 8 - 6
Source/cmLocalXCodeGenerator.cxx

@@ -119,7 +119,7 @@ void cmLocalXCodeGenerator::AddGeneratorSpecificInstallSetup(std::ostream& os)
 }
 
 void cmLocalXCodeGenerator::ComputeObjectFilenames(
-  std::map<cmSourceFile const*, std::string>& mapping,
+  std::map<cmSourceFile const*, cmObjectLocations>& mapping,
   cmGeneratorTarget const*)
 {
   // Count the number of object files with each name. Warn about duplicate
@@ -129,15 +129,17 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames(
   std::map<std::string, int> counts;
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectName = cmStrCat(
+    std::string shortObjectName = this->GetShortObjectFileName(*sf);
+    std::string longObjectName = cmStrCat(
       cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()), ".o");
 
-    std::string objectNameLower = cmSystemTools::LowerCase(objectName);
-    counts[objectNameLower] += 1;
-    if (2 == counts[objectNameLower]) {
+    std::string longObjectNameLower = cmSystemTools::LowerCase(longObjectName);
+    counts[longObjectNameLower] += 1;
+    if (2 == counts[longObjectNameLower]) {
       // TODO: emit warning about duplicate name?
     }
-    si.second = objectName;
+    si.second.ShortLoc.emplace(shortObjectName);
+    si.second.LongLoc.Update(longObjectName);
   }
 }
 

+ 2 - 1
Source/cmLocalXCodeGenerator.h

@@ -9,6 +9,7 @@
 #include <string>
 
 #include "cmLocalGenerator.h"
+#include "cmObjectLocation.h"
 
 class cmGeneratorTarget;
 class cmGlobalGenerator;
@@ -35,7 +36,7 @@ public:
   void Generate() override;
   void AddGeneratorSpecificInstallSetup(std::ostream& os) override;
   void ComputeObjectFilenames(
-    std::map<cmSourceFile const*, std::string>& mapping,
+    std::map<cmSourceFile const*, cmObjectLocations>& mapping,
     cmGeneratorTarget const* gt = nullptr) override;
 
   void AddXCConfigSources(cmGeneratorTarget* target) override;

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

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

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

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

+ 3 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Common.cmake

@@ -0,0 +1,3 @@
+add_library(objlib OBJECT test.c subdir/inner_test.c)
+install(TARGETS objlib EXPORT exp OBJECTS DESTINATION "lib/objlib")
+install(EXPORT exp DESTINATION lib/cmake/IONS FILE ions-config.cmake NAMESPACE IONS::)

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

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

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake

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

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake

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

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

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

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

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

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

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

+ 8 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL-install-check.cmake

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

+ 3 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake

@@ -0,0 +1,3 @@
+set(CMAKE_INSTALL_OBJECT_NAME_STRATEGY FULL)
+
+include("${CMAKE_CURRENT_SOURCE_DIR}/Common.cmake")

+ 1 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt

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

+ 6 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-stderr.txt

@@ -0,0 +1,6 @@
+CMake Error in CMakeLists.txt:
+  Property INSTALL_OBJECT_NAME_STRATEGY of target "objlib" set to the
+  unsupported strategy INVALID
+
+
+CMake Generate step failed.  Build files cannot be regenerated correctly.

+ 3 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID.cmake

@@ -0,0 +1,3 @@
+set(CMAKE_INSTALL_OBJECT_NAME_STRATEGY INVALID)
+
+include("${CMAKE_CURRENT_SOURCE_DIR}/Common.cmake")

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

+ 45 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/RunCMakeTest.cmake

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

+ 2 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT-install-check.cmake

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

+ 3 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake

@@ -0,0 +1,3 @@
+set(CMAKE_INSTALL_OBJECT_NAME_STRATEGY SHORT)
+
+include("${CMAKE_CURRENT_SOURCE_DIR}/Common.cmake")

+ 7 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/main.c

@@ -0,0 +1,7 @@
+int test(int a);
+int inner(int a);
+
+int main(void)
+{
+  return test(0) + inner(0);
+}

+ 4 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c

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

+ 4 - 0
Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c

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