浏览代码

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
Brad King 6 年之前
父节点
当前提交
8a7f93d000
共有 2 个文件被更改,包括 12 次插入3 次删除
  1. 7 0
      Source/cmGeneratorTarget.cxx
  2. 5 3
      Source/cmGlobalXCodeGenerator.cxx

+ 7 - 0
Source/cmGeneratorTarget.cxx

@@ -3859,6 +3859,13 @@ std::string cmGeneratorTarget::GetObjectDirectory(
   // find and replace $(PROJECT_NAME) xcode placeholder
   // find and replace $(PROJECT_NAME) xcode placeholder
   const std::string projectName = this->LocalGenerator->GetProjectName();
   const std::string projectName = this->LocalGenerator->GetProjectName();
   cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName);
   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
 #endif
   return obj_dir;
   return obj_dir;
 }
 }

+ 5 - 3
Source/cmGlobalXCodeGenerator.cxx

@@ -510,6 +510,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
   makeHelper.push_back(dir);
   makeHelper.push_back(dir);
   makeHelper.push_back("-f");
   makeHelper.push_back("-f");
   makeHelper.push_back(this->CurrentXCodeHackMakefile);
   makeHelper.push_back(this->CurrentXCodeHackMakefile);
+  makeHelper.push_back("OBJDIR=$(OBJDIR)");
   makeHelper.push_back(""); // placeholder, see below
   makeHelper.push_back(""); // placeholder, see below
 
 
   // Add ZERO_CHECK
   // Add ZERO_CHECK
@@ -1662,6 +1663,7 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
   makecmd += cdir;
   makecmd += cdir;
   makecmd += " -f ";
   makecmd += " -f ";
   makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION"));
   makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION"));
+  makecmd += " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\")";
   makecmd += " all";
   makecmd += " all";
   buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
   buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
   buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
   buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
@@ -3359,7 +3361,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
         // then remove those executables as well
         // then remove those executables as well
         if (this->Architectures.size() > 1) {
         if (this->Architectures.size() > 1) {
           std::string universal = this->GetObjectsDirectory(
           std::string universal = this->GetObjectsDirectory(
-            this->CurrentProject, configName, gt, "Objects-normal/");
+            this->CurrentProject, configName, gt, "$(OBJDIR)/");
           for (const auto& architecture : this->Architectures) {
           for (const auto& architecture : this->Architectures) {
             std::string universalFile = universal;
             std::string universalFile = universal;
             universalFile += architecture;
             universalFile += architecture;
@@ -3763,8 +3765,8 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
   cmGeneratorTarget* gt) const
 {
 {
   std::string configName = this->GetCMakeCFGIntDir();
   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 += this->ObjectDirArch;
   dir += "/";
   dir += "/";
   gt->ObjectDirectory = dir;
   gt->ObjectDirectory = dir;