From c651b0e002259bcca0cfd6065677c4e49cb178d1 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 19 May 2025 12:16:06 +0200 Subject: [PATCH] objects: implement installation naming strategies --- Source/cmGeneratorTarget.cxx | 54 +++++++++++++-- Source/cmGeneratorTarget.h | 12 +++- Source/cmGlobalVisualStudioGenerator.cxx | 9 ++- Source/cmInstallTargetGenerator.cxx | 67 ++++++++++++++----- Source/cmInstallTargetGenerator.h | 1 + Source/cmLocalCommonGenerator.cxx | 13 +++- Source/cmLocalCommonGenerator.h | 3 +- Source/cmLocalGenerator.cxx | 11 ++- Source/cmLocalGenerator.h | 6 +- Source/cmLocalGhsMultiGenerator.cxx | 23 ++++--- Source/cmLocalGhsMultiGenerator.h | 3 +- Source/cmLocalVisualStudioGenerator.cxx | 26 +++---- Source/cmLocalVisualStudioGenerator.h | 3 +- Source/cmLocalXCodeGenerator.cxx | 14 ++-- Source/cmLocalXCodeGenerator.h | 3 +- Tests/RunCMake/CMakeLists.txt | 1 + .../CMakeLists.txt | 3 + .../INSTALL_OBJECT_NAME_STRATEGY/Common.cmake | 3 + .../Consume-Default.cmake | 1 + .../Consume-FULL.cmake | 1 + .../Consume-SHORT.cmake | 1 + .../Consume.cmake | 7 ++ .../Default-install-check.cmake | 2 + .../Default.cmake | 1 + .../FULL-install-check.cmake | 8 +++ .../INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake | 3 + .../INVALID-result.txt | 1 + .../INVALID-stderr.txt | 6 ++ .../INVALID.cmake | 3 + .../Inspect.cmake | 10 +++ .../RunCMakeTest.cmake | 45 +++++++++++++ .../SHORT-install-check.cmake | 2 + .../INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake | 3 + .../INSTALL_OBJECT_NAME_STRATEGY/main.c | 7 ++ .../subdir/inner_test.c | 4 ++ .../INSTALL_OBJECT_NAME_STRATEGY/test.c | 4 ++ 36 files changed, 301 insertions(+), 63 deletions(-) create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/CMakeLists.txt create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Common.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-Default.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default-install-check.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL-install-check.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-stderr.txt create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Inspect.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT-install-check.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/main.c create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c create mode 100644 Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index dc29ca0d14..14cbee8792 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/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& 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 cb) + const { std::vector objectSources; this->GetObjectSources(objectSources, config); - std::map mapping; + std::map 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 { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 9f2349e4dc..517bfcc2c3 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include +#include #include #include #include @@ -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& objects) const; + /** Get the build and install locations of objects for a given context. */ + void GetTargetObjectLocations( + std::string const& config, + std::function 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; SourceEntriesType SourceDepends; mutable std::set VisitedConfigsForObjects; - mutable std::map Objects; + mutable std::map Objects; std::set ExplicitObjectName; using TargetPtrToBoolMap = std::unordered_map; diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index c905a4e8e1..4296c22396 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -873,7 +873,7 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( std::vector empty; std::vector objectSources; gt->GetObjectSources(objectSources, configName); - std::map mapping; + std::map 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 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); diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index b2a5f5115c..1bc347eb9e 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -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 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 objects; - this->Target->GetTargetObjectNames(config, objects); + std::vector> 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& objects) const { - this->Target->GetTargetObjectNames(config, objects); - for (std::string& o : objects) { - o = cmStrCat(computeInstallObjectDir(this->Target, config), '/', o); + std::vector 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())); } } diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index da51a819e7..6ddfca615a 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/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(); diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 3a8453ef0d..b79b24bdb3 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -6,9 +6,12 @@ #include #include +#include + #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& mapping, + std::map& 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)); } } diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index 7c63c19383..1c104a7a85 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/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& mapping, + std::map& mapping, cmGeneratorTarget const* gt = nullptr) override; protected: diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index d1c03a2433..52821d55e3 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -4143,7 +4143,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName( } void cmLocalGenerator::ComputeObjectFilenames( - std::map& /*unused*/, + std::map& /*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; } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 4fa48fb008..81b516b542 100644 --- a/Source/cmLocalGenerator.h +++ b/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& mapping, + std::map& mapping, cmGeneratorTarget const* gt = nullptr); bool IsWindowsShell() const; diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index 2e38dc7583..812f025282 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -5,9 +5,12 @@ #include #include +#include + #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& mapping, + std::map& 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(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); } } diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h index 698ef39a4d..ae80b2b591 100644 --- a/Source/cmLocalGhsMultiGenerator.h +++ b/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& mapping, + std::map& mapping, cmGeneratorTarget const* gt = nullptr) override; }; diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 4ea3f1ba6d..9d7a507544 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -39,7 +39,7 @@ cmLocalVisualStudioGenerator::GetVersion() const } void cmLocalVisualStudioGenerator::ComputeObjectFilenames( - std::map& mapping, + std::map& 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(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); } } diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index fdc15be87c..8c472c5e96 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/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& mapping, + std::map& mapping, cmGeneratorTarget const* = nullptr) override; std::string GetObjectOutputRoot( diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 5bf096683e..5d6a32fa6b 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -119,7 +119,7 @@ void cmLocalXCodeGenerator::AddGeneratorSpecificInstallSetup(std::ostream& os) } void cmLocalXCodeGenerator::ComputeObjectFilenames( - std::map& mapping, + std::map& mapping, cmGeneratorTarget const*) { // Count the number of object files with each name. Warn about duplicate @@ -129,15 +129,17 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames( std::map 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); } } diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h index 49a5e93e53..7b501fb6e5 100644 --- a/Source/cmLocalXCodeGenerator.h +++ b/Source/cmLocalXCodeGenerator.h @@ -9,6 +9,7 @@ #include #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& mapping, + std::map& mapping, cmGeneratorTarget const* gt = nullptr) override; void AddXCConfigSources(cmGeneratorTarget* target) override; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 7aeb1926f4..357c8c6f1b 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/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) diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/CMakeLists.txt b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/CMakeLists.txt new file mode 100644 index 0000000000..c89e9088dc --- /dev/null +++ b/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) diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Common.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Common.cmake new file mode 100644 index 0000000000..0a538ba93b --- /dev/null +++ b/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::) diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-Default.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-Default.cmake new file mode 100644 index 0000000000..57f13bb621 --- /dev/null +++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-Default.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake new file mode 100644 index 0000000000..57f13bb621 --- /dev/null +++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-FULL.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake new file mode 100644 index 0000000000..57f13bb621 --- /dev/null +++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume-SHORT.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/Consume.cmake") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Consume.cmake new file mode 100644 index 0000000000..82192e07da --- /dev/null +++ b/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) diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default-install-check.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default-install-check.cmake new file mode 100644 index 0000000000..418557e47c --- /dev/null +++ b/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") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default.cmake new file mode 100644 index 0000000000..f635ae2087 --- /dev/null +++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Default.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/Common.cmake") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL-install-check.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL-install-check.cmake new file mode 100644 index 0000000000..4fcc007480 --- /dev/null +++ b/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}") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/FULL.cmake new file mode 100644 index 0000000000..d074526af7 --- /dev/null +++ b/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") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-stderr.txt b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID-stderr.txt new file mode 100644 index 0000000000..0ad494d9bc --- /dev/null +++ b/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. diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/INVALID.cmake new file mode 100644 index 0000000000..d7ae7242f6 --- /dev/null +++ b/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") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Inspect.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/Inspect.cmake new file mode 100644 index 0000000000..ec74ed8e36 --- /dev/null +++ b/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}") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/RunCMakeTest.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/RunCMakeTest.cmake new file mode 100644 index 0000000000..67e030b39d --- /dev/null +++ b/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) diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT-install-check.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT-install-check.cmake new file mode 100644 index 0000000000..15b77d2c62 --- /dev/null +++ b/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}") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/SHORT.cmake new file mode 100644 index 0000000000..b21fb4817d --- /dev/null +++ b/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") diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/main.c b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/main.c new file mode 100644 index 0000000000..7955cce161 --- /dev/null +++ b/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); +} diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c new file mode 100644 index 0000000000..32c726da5b --- /dev/null +++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/subdir/inner_test.c @@ -0,0 +1,4 @@ +int inner(int a) +{ + return a; +} diff --git a/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c new file mode 100644 index 0000000000..6fa39df723 --- /dev/null +++ b/Tests/RunCMake/INSTALL_OBJECT_NAME_STRATEGY/test.c @@ -0,0 +1,4 @@ +int test(int a) +{ + return a; +}