From eff9c69740d5d4a26025a89f517a612e446077c0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 30 Jan 2019 09:33:35 -0500 Subject: Xcode: Place object library artifacts outside Objects-normal directory The `CONFIGURATION_BUILD_DIR` value in the Xcode project file specifies where to place the library artifact. For object libraries we've used the `Objects-normal` directory to hide away the `.a` that we otherwise cannot stop Xcode from producing. The parent of this directory is also specific to the target and does not vary with Xcode's sanitizer features, so move the artifact there. Issue: #16289 --- Source/cmGlobalXCodeGenerator.cxx | 26 ++++++++++++++------------ Source/cmGlobalXCodeGenerator.h | 7 ++++--- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 6d15b8c..cc5ddb8 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -485,6 +485,7 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget( } #define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK" +#define OBJECT_LIBRARY_ARTIFACT_DIR std::string() void cmGlobalXCodeGenerator::AddExtraTargets( cmLocalGenerator* root, std::vector& gens) @@ -1968,8 +1969,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, pnbase = gtgt->GetName(); pnsuffix = ".a"; - std::string pncdir = - this->GetObjectsNormalDirectory(this->CurrentProject, configName, gtgt); + std::string pncdir = this->GetObjectsDirectory( + this->CurrentProject, configName, gtgt, OBJECT_LIBRARY_ARTIFACT_DIR); buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", this->CreateString(pncdir)); } @@ -3199,9 +3200,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( return true; } -std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory( +std::string cmGlobalXCodeGenerator::GetObjectsDirectory( const std::string& projName, const std::string& configName, - const cmGeneratorTarget* t) const + const cmGeneratorTarget* t, const std::string& variant) const { std::string dir = t->GetLocalGenerator()->GetCurrentBinaryDirectory(); dir += "/"; @@ -3210,8 +3211,8 @@ std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory( dir += configName; dir += "/"; dir += t->GetName(); - dir += ".build/Objects-normal/"; - + dir += ".build/"; + dir += variant; return dir; } @@ -3338,8 +3339,9 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( for (auto objLib : objlibs) { const std::string objLibName = objLib->GetName(); - std::string d = this->GetObjectsNormalDirectory(this->CurrentProject, - configName, objLib); + std::string d = + this->GetObjectsDirectory(this->CurrentProject, configName, objLib, + OBJECT_LIBRARY_ARTIFACT_DIR); d += "lib"; d += objLibName; d += ".a"; @@ -3356,8 +3358,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( // if building for more than one architecture // then remove those executables as well if (this->Architectures.size() > 1) { - std::string universal = this->GetObjectsNormalDirectory( - this->CurrentProject, configName, gt); + std::string universal = this->GetObjectsDirectory( + this->CurrentProject, configName, gt, "Objects-normal/"); for (const auto& architecture : this->Architectures) { std::string universalFile = universal; universalFile += architecture; @@ -3761,8 +3763,8 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { std::string configName = this->GetCMakeCFGIntDir(); - std::string dir = - this->GetObjectsNormalDirectory("$(PROJECT_NAME)", configName, gt); + std::string dir = this->GetObjectsDirectory("$(PROJECT_NAME)", configName, + gt, "Objects-normal/"); dir += this->ObjectDirArch; dir += "/"; gt->ObjectDirectory = dir; diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 92ff258..e1e412d 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -264,9 +264,10 @@ private: { } - std::string GetObjectsNormalDirectory(const std::string& projName, - const std::string& configName, - const cmGeneratorTarget* t) const; + std::string GetObjectsDirectory(const std::string& projName, + const std::string& configName, + const cmGeneratorTarget* t, + const std::string& variant) const; static std::string GetDeploymentPlatform(const cmMakefile* mf); -- cgit v0.12 From 8a7f93d000f1676d6051027b0608ca7658c8f00e Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 30 Jan 2019 09:42:02 -0500 Subject: Xcode: Fix object library builds with sanitizers enabled Using `xcodebuild -enableAddressSanitizer YES ...` causes object files to be placed in a different directory name. Xcode provides a placeholder for this that we can use in `OTHER_LDFLAGS` to reference object files for linking the dependents of object libraries. However, CMake's features for installing and exporting object libraries depend on knowing the real path with no placeholders. For these cases, use the default object directory. Users will then have to choose between sanitizers and the installation and export features, but both will work individually. Fixes: #16289 --- Source/cmGeneratorTarget.cxx | 7 +++++++ Source/cmGlobalXCodeGenerator.cxx | 8 +++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 86f10dc..78040c3 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -3859,6 +3859,13 @@ std::string cmGeneratorTarget::GetObjectDirectory( // find and replace $(PROJECT_NAME) xcode placeholder const std::string projectName = this->LocalGenerator->GetProjectName(); cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName); + // Replace Xcode's placeholder for the object file directory since + // installation and export scripts need to know the real directory. + // Xcode has build-time settings (e.g. for sanitizers) that affect this, + // but we use the default here. Users that want to enable sanitizers + // will do so at the cost of object library installation and export. + cmSystemTools::ReplaceString(obj_dir, "$(OBJECT_FILE_DIR_normal:base)", + "Objects-normal"); #endif return obj_dir; } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index cc5ddb8..0bd0580 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -510,6 +510,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( makeHelper.push_back(dir); makeHelper.push_back("-f"); makeHelper.push_back(this->CurrentXCodeHackMakefile); + makeHelper.push_back("OBJDIR=$(OBJDIR)"); makeHelper.push_back(""); // placeholder, see below // Add ZERO_CHECK @@ -1662,6 +1663,7 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase( makecmd += cdir; makecmd += " -f "; makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION")); + makecmd += " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\")"; makecmd += " all"; buildphase->AddAttribute("shellScript", this->CreateString(makecmd)); buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0")); @@ -3359,7 +3361,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( // then remove those executables as well if (this->Architectures.size() > 1) { std::string universal = this->GetObjectsDirectory( - this->CurrentProject, configName, gt, "Objects-normal/"); + this->CurrentProject, configName, gt, "$(OBJDIR)/"); for (const auto& architecture : this->Architectures) { std::string universalFile = universal; universalFile += architecture; @@ -3763,8 +3765,8 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { std::string configName = this->GetCMakeCFGIntDir(); - std::string dir = this->GetObjectsDirectory("$(PROJECT_NAME)", configName, - gt, "Objects-normal/"); + std::string dir = this->GetObjectsDirectory( + "$(PROJECT_NAME)", configName, gt, "$(OBJECT_FILE_DIR_normal:base)/"); dir += this->ObjectDirArch; dir += "/"; gt->ObjectDirectory = dir; -- cgit v0.12