Browse Source

Apple Frameworks: honor SYSTEM target property

Fixes: #24109
Marc Chevrier 2 years ago
parent
commit
ad9020a899

+ 4 - 0
Help/release/dev/System-Framework.rst

@@ -0,0 +1,4 @@
+System-Framework
+----------------
+
+* The :prop_tgt:`SYSTEM` target property is now honored for Apple Frameworks.

+ 28 - 13
Source/cmGeneratorTarget.cxx

@@ -794,6 +794,15 @@ void handleSystemIncludesDep(cmLocalGenerator* lg,
     result.append(cmGeneratorExpression::Evaluate(
       *dirs, lg, config, headTarget, dagChecker, depTgt, language));
   }
+
+  if (depTgt->Target->IsFrameworkOnApple()) {
+    if (auto fwDescriptor = depTgt->GetGlobalGenerator()->SplitFrameworkPath(
+          depTgt->GetLocation(config),
+          cmGlobalGenerator::FrameworkFormat::Strict)) {
+      result.push_back(fwDescriptor->Directory);
+      result.push_back(fwDescriptor->GetFrameworkPath());
+    }
+  }
 }
 }
 
@@ -3819,32 +3828,38 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
   AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang,
                       &dagChecker, entries, IncludeRuntimeInterface::Yes);
 
+  processIncludeDirectories(this, entries, includes, uniqueIncludes,
+                            debugIncludes);
+
   if (this->IsApple()) {
     if (cmLinkImplementationLibraries const* impl =
           this->GetLinkImplementationLibraries(config,
                                                LinkInterfaceFor::Usage)) {
       for (cmLinkImplItem const& lib : impl->Libraries) {
-        std::string libDir = cmSystemTools::CollapseFullPath(
-          lib.AsStr(), this->Makefile->GetHomeOutputDirectory());
-
-        static cmsys::RegularExpression frameworkCheck(
-          "(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
-        if (!frameworkCheck.find(libDir)) {
+        std::string libDir;
+        if (lib.Target == nullptr) {
+          libDir = cmSystemTools::CollapseFullPath(
+            lib.AsStr(), this->Makefile->GetHomeOutputDirectory());
+        } else if (lib.Target->Target->IsFrameworkOnApple()) {
+          libDir = lib.Target->GetLocation(config);
+        } else {
           continue;
         }
 
-        libDir = frameworkCheck.match(1);
+        auto fwDescriptor =
+          this->GetGlobalGenerator()->SplitFrameworkPath(libDir);
+        if (!fwDescriptor) {
+          continue;
+        }
 
-        EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace());
-        ee.Values.emplace_back(std::move(libDir));
-        entries.Entries.emplace_back(std::move(ee));
+        auto fwInclude = fwDescriptor->GetFrameworkPath();
+        if (uniqueIncludes.insert(fwInclude).second) {
+          includes.emplace_back(fwInclude, cmListFileBacktrace());
+        }
       }
     }
   }
 
-  processIncludeDirectories(this, entries, includes, uniqueIncludes,
-                            debugIncludes);
-
   this->IncludeDirectoriesCache.emplace(cacheKey, includes);
   return includes;
 }

+ 1 - 3
Source/cmGlobalXCodeGenerator.cxx

@@ -2765,7 +2765,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
       if (emitted.insert(frameworkDir).second) {
         std::string incpath = this->XCodeEscapePath(frameworkDir);
         if (emitSystemIncludes &&
-            gtgt->IsSystemIncludeDirectory(include, configName,
+            gtgt->IsSystemIncludeDirectory(frameworkDir, configName,
                                            langForIncludes)) {
           sysfdirs.Add(incpath);
         } else {
@@ -3910,8 +3910,6 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
       // otherwise we end up hard-coding a path to the wrong SDK for
       // SDK-provided frameworks that are added by their full path.
       std::set<std::string> emitted(cli->GetFrameworkPathsEmitted());
-      const auto& fwPaths = cli->GetFrameworkPaths();
-      emitted.insert(fwPaths.begin(), fwPaths.end());
       BuildObjectListOrString libPaths(this, true);
       BuildObjectListOrString fwSearchPaths(this, true);
       for (auto const& libItem : configItemMap[configName]) {

+ 14 - 6
Source/cmLinkLineComputer.cxx

@@ -191,16 +191,24 @@ std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
 }
 
 std::string cmLinkLineComputer::ComputeFrameworkPath(
-  cmComputeLinkInformation& cli, std::string const& fwSearchFlag)
+  cmComputeLinkInformation& cli, cmValue fwSearchFlag, cmValue sysFwSearchFlag)
 {
+  if (!fwSearchFlag && !sysFwSearchFlag) {
+    return std::string{};
+  }
+
   std::string frameworkPath;
-  if (!fwSearchFlag.empty()) {
-    std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
-    for (std::string const& fd : fwDirs) {
+  auto const& fwDirs = cli.GetFrameworkPaths();
+  for (auto const& fd : fwDirs) {
+    if (sysFwSearchFlag &&
+        cli.GetTarget()->IsSystemIncludeDirectory(fd, cli.GetConfig(),
+                                                  cli.GetLinkLanguage())) {
+      frameworkPath += sysFwSearchFlag;
+    } else {
       frameworkPath += fwSearchFlag;
-      frameworkPath += this->ConvertToOutputFormat(fd);
-      frameworkPath += " ";
     }
+    frameworkPath += this->ConvertToOutputFormat(fd);
+    frameworkPath += " ";
   }
   return frameworkPath;
 }

+ 3 - 1
Source/cmLinkLineComputer.h

@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "cmStateDirectory.h"
+#include "cmValue.h"
 
 class cmComputeLinkInformation;
 class cmGeneratorTarget;
@@ -43,7 +44,8 @@ public:
                        std::vector<BT<std::string>>& linkPath);
 
   std::string ComputeFrameworkPath(cmComputeLinkInformation& cli,
-                                   std::string const& fwSearchFlag);
+                                   cmValue fwSearchFlag,
+                                   cmValue sysFwSearchFlag);
 
   std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
                                    std::string const& stdLibString);

+ 22 - 18
Source/cmLocalGenerator.cxx

@@ -914,7 +914,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
         cmSystemTools::CollapseFullPath(cmStrCat(i, "/../"));
       if (emitted.insert(frameworkDir).second) {
         if (sysFwSearchFlag && target &&
-            target->IsSystemIncludeDirectory(i, config, lang)) {
+            target->IsSystemIncludeDirectory(frameworkDir, config, lang)) {
           includeFlags << *sysFwSearchFlag;
         } else {
           includeFlags << *fwSearchFlag;
@@ -1645,9 +1645,9 @@ std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags(
   return flags;
 }
 
-static std::string GetFrameworkFlags(const std::string& lang,
-                                     const std::string& config,
-                                     cmGeneratorTarget* target)
+std::string cmLocalGenerator::GetFrameworkFlags(std::string const& lang,
+                                                std::string const& config,
+                                                cmGeneratorTarget* target)
 {
   cmLocalGenerator* lg = target->GetLocalGenerator();
   cmMakefile* mf = lg->GetMakefile();
@@ -1656,10 +1656,13 @@ static std::string GetFrameworkFlags(const std::string& lang,
     return std::string();
   }
 
-  std::string fwSearchFlagVar = "CMAKE_" + lang + "_FRAMEWORK_SEARCH_FLAG";
-  cmValue fwSearchFlag = mf->GetDefinition(fwSearchFlagVar);
-  if (!cmNonempty(fwSearchFlag)) {
-    return std::string();
+  cmValue fwSearchFlag =
+    mf->GetDefinition(cmStrCat("CMAKE_", lang, "_FRAMEWORK_SEARCH_FLAG"));
+  cmValue sysFwSearchFlag = mf->GetDefinition(
+    cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG"));
+
+  if (!fwSearchFlag && !sysFwSearchFlag) {
+    return std::string{};
   }
 
   std::set<std::string> emitted;
@@ -1684,7 +1687,12 @@ static std::string GetFrameworkFlags(const std::string& lang,
     std::vector<std::string> const& frameworks = cli->GetFrameworkPaths();
     for (std::string const& framework : frameworks) {
       if (emitted.insert(framework).second) {
-        flags += *fwSearchFlag;
+        if (sysFwSearchFlag &&
+            target->IsSystemIncludeDirectory(framework, config, lang)) {
+          flags += *sysFwSearchFlag;
+        } else {
+          flags += *fwSearchFlag;
+        }
         flags +=
           lg->ConvertToOutputFormat(framework, cmOutputConverter::SHELL);
         flags += " ";
@@ -1694,13 +1702,6 @@ static std::string GetFrameworkFlags(const std::string& lang,
   return flags;
 }
 
-std::string cmLocalGenerator::GetFrameworkFlags(std::string const& l,
-                                                std::string const& config,
-                                                cmGeneratorTarget* target)
-{
-  return ::GetFrameworkFlags(l, config, target);
-}
-
 void cmLocalGenerator::GetTargetDefines(cmGeneratorTarget const* target,
                                         std::string const& config,
                                         std::string const& lang,
@@ -1788,10 +1789,13 @@ void cmLocalGenerator::OutputLinkLibraries(
     cmStrCat("CMAKE_", cli.GetLinkLanguage(), "_STANDARD_LIBRARIES"));
 
   // Append the framework search path flags.
-  std::string fwSearchFlag = this->Makefile->GetSafeDefinition(
+  cmValue fwSearchFlag = this->Makefile->GetDefinition(
     cmStrCat("CMAKE_", linkLanguage, "_FRAMEWORK_SEARCH_FLAG"));
+  cmValue sysFwSearchFlag = this->Makefile->GetDefinition(
+    cmStrCat("CMAKE_", linkLanguage, "_SYSTEM_FRAMEWORK_SEARCH_FLAG"));
 
-  frameworkPath = linkLineComputer->ComputeFrameworkPath(cli, fwSearchFlag);
+  frameworkPath =
+    linkLineComputer->ComputeFrameworkPath(cli, fwSearchFlag, sysFwSearchFlag);
   linkLineComputer->ComputeLinkPath(cli, libPathFlag, libPathTerminator,
                                     linkPath);
   linkLineComputer->ComputeLinkLibraries(cli, stdLibString, linkLibraries);

+ 12 - 0
Tests/RunCMake/Framework/FrameworkSystemIncludeTest.cmake

@@ -10,3 +10,15 @@ set_target_properties(Example::Example PROPERTIES
 add_library(testcase FrameworkSystemIncludeTest.c)
 target_compile_options(testcase PRIVATE "-Werror=#pragma-messages")
 target_link_libraries(testcase PRIVATE Example::Example)
+
+
+
+add_library(Example::Example2 SHARED IMPORTED)
+set_target_properties(Example::Example2 PROPERTIES
+  FRAMEWORK 1
+  IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/subdir/Example.framework/Example.tbd"
+)
+
+add_library(testcase2 FrameworkSystemIncludeTest.c)
+target_compile_options(testcase2 PRIVATE "-Werror=#pragma-messages")
+target_link_libraries(testcase2 PRIVATE Example::Example2)