Просмотр исходного кода

xcode: add support for xcconfig files

Fixes: #18420
Gregor Jasny 3 лет назад
Родитель
Сommit
53ca6edd8a

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

@@ -457,6 +457,7 @@ Properties on Targets
    /prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
    /prop_tgt/XCODE_SCHEME_WORKING_DIRECTORY
    /prop_tgt/XCODE_SCHEME_ZOMBIE_OBJECTS
+   /prop_tgt/XCODE_XCCONFIG
    /prop_tgt/XCTEST
 
 .. _`Test Properties`:

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -285,6 +285,7 @@ Variables that Change Behavior
    /variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
    /variable/CMAKE_XCODE_SCHEME_WORKING_DIRECTORY
    /variable/CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS
+   /variable/CMAKE_XCODE_XCCONFIG
    /variable/PackageName_ROOT
 
 Variables that Describe the System

+ 14 - 0
Help/prop_tgt/XCODE_XCCONFIG.rst

@@ -0,0 +1,14 @@
+XCODE_XCCONFIG
+--------------
+
+.. versionadded:: 3.24
+
+If set, the :generator:`Xcode` generator will register the specified
+file as a target-level XCConfig file. For global XCConfig files see
+the :variable:`CMAKE_XCODE_XCCONFIG` variable.
+
+This feature is intended to ease migration from native Xcode projects
+to CMake projects.
+
+Contents of ``XCODE_XCCONFIG`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.

+ 6 - 0
Help/release/dev/xcode-xcconfig.rst

@@ -0,0 +1,6 @@
+xcode-xcconfig
+--------------
+
+* The Xcode generator learned to handle global and target specific
+  ``xcconfig`` files with the :variable:`CMAKE_XCODE_XCCONFIG`
+  variable and :prop_tgt:`XCODE_XCCONFIG` target property.

+ 14 - 0
Help/variable/CMAKE_XCODE_XCCONFIG.rst

@@ -0,0 +1,14 @@
+CMAKE_XCODE_XCCONFIG
+--------------------
+
+.. versionadded:: 3.24
+
+If set, the :generator:`Xcode` generator will register the specified
+file as a global XCConfig file. For target-level XCConfig files see
+the :prop_tgt:`XCODE_XCCONFIG` target property.
+
+This feature is intended to ease migration from native Xcode projects
+to CMake projects.
+
+Contents of ``CMAKE_XCODE_XCCONFIG`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.

+ 1 - 0
Source/cmGlobalGenerator.cxx

@@ -1764,6 +1764,7 @@ bool cmGlobalGenerator::AddAutomaticSources()
       if (!gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
         lg->AddPchDependencies(gt.get());
       }
+      lg->AddXCConfigSources(gt.get());
     }
   }
   for (const auto& lg : this->LocalGenerators) {

+ 78 - 0
Source/cmGlobalXCodeGenerator.cxx

@@ -616,6 +616,16 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
   cmTarget* allbuild =
     root->AddUtilityCommand("ALL_BUILD", true, std::move(cc));
 
+  // Add xcconfig files to ALL_BUILD sources
+  for (auto& config : this->CurrentConfigurationTypes) {
+    auto xcconfig = cmGeneratorExpression::Evaluate(
+      this->CurrentMakefile->GetSafeDefinition("CMAKE_XCODE_XCCONFIG"),
+      this->CurrentLocalGenerator, config);
+    if (!xcconfig.empty()) {
+      allbuild->AddSource(xcconfig);
+    }
+  }
+
   root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(allbuild, root));
 
   // Add XCODE depend helper
@@ -1142,6 +1152,9 @@ std::string GetSourcecodeValueFromFileExtension(
   } else if (ext == "xcassets") {
     keepLastKnownFileType = true;
     sourcecode = "folder.assetcatalog";
+  } else if (ext == "xcconfig") {
+    keepLastKnownFileType = true;
+    sourcecode = "text.xcconfig";
   }
   // else
   //  {
@@ -3045,6 +3058,8 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
     config->AddAttribute("name", this->CreateString(i));
     config->SetComment(i);
     config->AddAttribute("buildSettings", buildSettings);
+
+    this->CreateTargetXCConfigSettings(gtgt, config, i);
   }
   if (!configVector.empty()) {
     configlist->AddAttribute("defaultConfigurationName",
@@ -3056,6 +3071,67 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
   return "";
 }
 
+void cmGlobalXCodeGenerator::CreateGlobalXCConfigSettings(
+  cmLocalGenerator* root, cmXCodeObject* config, const std::string& configName)
+{
+  auto xcconfig = cmGeneratorExpression::Evaluate(
+    this->CurrentMakefile->GetSafeDefinition("CMAKE_XCODE_XCCONFIG"),
+    this->CurrentLocalGenerator, configName);
+  if (xcconfig.empty()) {
+    return;
+  }
+
+  auto sf = this->CurrentMakefile->GetSource(xcconfig);
+  if (!sf) {
+    cmSystemTools::Error(
+      cmStrCat("sources for ALL_BUILD do not contain xcconfig file: '",
+               xcconfig, "' (configuration: ", configName, ")"));
+    return;
+  }
+
+  cmXCodeObject* fileRef = this->CreateXCodeFileReferenceFromPath(
+    sf->ResolveFullPath(), root->FindGeneratorTargetToUse("ALL_BUILD"), "",
+    sf);
+
+  if (!fileRef) {
+    // error is already reported by CreateXCodeFileReferenceFromPath
+    return;
+  }
+
+  config->AddAttribute("baseConfigurationReference",
+                       this->CreateObjectReference(fileRef));
+}
+
+void cmGlobalXCodeGenerator::CreateTargetXCConfigSettings(
+  cmGeneratorTarget* target, cmXCodeObject* config,
+  const std::string& configName)
+{
+  auto xcconfig =
+    cmGeneratorExpression::Evaluate(target->GetSafeProperty("XCODE_XCCONFIG"),
+                                    this->CurrentLocalGenerator, configName);
+  if (xcconfig.empty()) {
+    return;
+  }
+
+  auto sf = target->Makefile->GetSource(xcconfig);
+  if (!sf) {
+    cmSystemTools::Error(cmStrCat("target sources for target ",
+                                  target->Target->GetName(),
+                                  " do not contain xcconfig file: '", xcconfig,
+                                  "' (configuration: ", configName, ")"));
+    return;
+  }
+
+  cmXCodeObject* fileRef = this->CreateXCodeFileReferenceFromPath(
+    sf->ResolveFullPath(), target, "", sf);
+  if (!fileRef) {
+    // error is already reported by CreateXCodeFileReferenceFromPath
+    return;
+  }
+  config->AddAttribute("baseConfigurationReference",
+                       this->CreateObjectReference(fileRef));
+}
+
 const char* cmGlobalXCodeGenerator::GetTargetLinkFlagsVar(
   cmGeneratorTarget const* target) const
 {
@@ -4245,6 +4321,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
   }
 
   for (auto& config : configs) {
+    CreateGlobalXCConfigSettings(root, config.second, config.first);
+
     cmXCodeObject* buildSettingsForCfg = this->CreateFlatClone(buildSettings);
 
     // Put this last so it can override existing settings

+ 6 - 0
Source/cmGlobalXCodeGenerator.h

@@ -224,6 +224,12 @@ private:
   void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
                                            cmXCodeObject* buildSettings,
                                            const std::string& configName);
+  void CreateGlobalXCConfigSettings(cmLocalGenerator* root,
+                                    cmXCodeObject* config,
+                                    const std::string& configName);
+  void CreateTargetXCConfigSettings(cmGeneratorTarget* target,
+                                    cmXCodeObject* config,
+                                    const std::string& configName);
   void CreateBuildSettings(cmGeneratorTarget* gtgt,
                            cmXCodeObject* buildSettings,
                            const std::string& buildType);

+ 1 - 0
Source/cmLocalGenerator.h

@@ -170,6 +170,7 @@ public:
   void AddISPCDependencies(cmGeneratorTarget* target);
   void AddPchDependencies(cmGeneratorTarget* target);
   void AddUnityBuild(cmGeneratorTarget* target);
+  virtual void AddXCConfigSources(cmGeneratorTarget* /* target */) {}
   void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
                             const std::string& config,
                             const std::string& lang);

+ 20 - 0
Source/cmLocalXCodeGenerator.cxx

@@ -6,6 +6,7 @@
 #include <ostream>
 #include <utility>
 
+#include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalXCodeGenerator.h"
 #include "cmMakefile.h"
@@ -134,3 +135,22 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames(
     si.second = objectName;
   }
 }
+
+void cmLocalXCodeGenerator::AddXCConfigSources(cmGeneratorTarget* target)
+{
+  auto xcconfig = target->GetProperty("XCODE_XCCONFIG");
+  if (!xcconfig) {
+    return;
+  }
+  auto configs = target->Makefile->GetGeneratorConfigs(
+                          cmMakefile::IncludeEmptyConfig);
+
+  for (auto& config : configs) {
+    auto file = cmGeneratorExpression::Evaluate(
+      xcconfig,
+      this, config);
+    if (!file.empty()) {
+      target->AddSource(file);
+    }
+  }
+}

+ 2 - 0
Source/cmLocalXCodeGenerator.h

@@ -38,5 +38,7 @@ public:
     std::map<cmSourceFile const*, std::string>& mapping,
     cmGeneratorTarget const* gt = nullptr) override;
 
+  void AddXCConfigSources(cmGeneratorTarget* target) override;
+
 private:
 };

+ 10 - 0
Tests/RunCMake/XcodeProject/RunCMakeTest.cmake

@@ -141,6 +141,16 @@ endfunction()
 
 XcodeRemoveExcessiveISystem()
 
+function(XcodeXCConfig)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeXCConfig-build)
+  run_cmake(XcodeXCConfig)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(XcodeXCConfig-build ${CMAKE_COMMAND} --build . --config Debug)
+  run_cmake_command(XcodeXCConfig-build ${CMAKE_COMMAND} --build . --config Release)
+endfunction()
+
+XcodeXCConfig()
+
 # Isolate device tests from host architecture selection.
 unset(ENV{CMAKE_OSX_ARCHITECTURES})
 

+ 20 - 0
Tests/RunCMake/XcodeProject/XcodeXCConfig.c

@@ -0,0 +1,20 @@
+#ifndef BUILD_DEBUG
+#  error BUILD_DEBUG is undefined
+#endif
+#ifndef GLOBAL_DEBUG
+#  error GLOBAL_DEBUG is undefined
+#endif
+#ifndef TARGET_DEBUG
+#  error TARGET_DEBUG is undefined
+#endif
+
+#if GLOBAL_DEBUG != BUILD_DEBUG
+#  error GLOBAL_DEBUG does not match BUILD_DEBUG
+#endif
+#if TARGET_DEBUG != BUILD_DEBUG
+#  error TARGET_DEBUG does not match BUILD_DEBUG
+#endif
+
+void some_symbol()
+{
+}

+ 11 - 0
Tests/RunCMake/XcodeProject/XcodeXCConfig.cmake

@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.23)
+
+project(XcodeXCConfig C)
+
+set(CMAKE_XCODE_XCCONFIG "$<IF:$<CONFIG:Debug>,XcodeXCConfig.global.debug.xcconfig,XcodeXCConfig.global.release.xcconfig>")
+
+add_library(somelib XcodeXCConfig.c)
+target_compile_definitions(somelib PUBLIC "BUILD_DEBUG=$<IF:$<CONFIG:Debug>,1,0>")
+set_target_properties(somelib PROPERTIES
+  XCODE_XCCONFIG "$<IF:$<CONFIG:Debug>,XcodeXCConfig.target.debug.xcconfig,XcodeXCConfig.target.release.xcconfig>"
+)

+ 1 - 0
Tests/RunCMake/XcodeProject/XcodeXCConfig.global.debug.xcconfig

@@ -0,0 +1 @@
+OTHER_CFLAGS = $(inherited) -DGLOBAL_DEBUG=1

+ 1 - 0
Tests/RunCMake/XcodeProject/XcodeXCConfig.global.release.xcconfig

@@ -0,0 +1 @@
+OTHER_CFLAGS = $(inherited) -DGLOBAL_DEBUG=0

+ 1 - 0
Tests/RunCMake/XcodeProject/XcodeXCConfig.target.debug.xcconfig

@@ -0,0 +1 @@
+OTHER_CFLAGS = $(inherited) -DTARGET_DEBUG=1

+ 1 - 0
Tests/RunCMake/XcodeProject/XcodeXCConfig.target.release.xcconfig

@@ -0,0 +1 @@
+OTHER_CFLAGS = $(inherited) -DTARGET_DEBUG=0