Browse Source

Merge topic 'swift-implicit-module-include-dir'

2026915f8f Swift: Propagate Swift_MODULE_DIRECTORY as include directory

Acked-by: Kitware Robot <[email protected]>
Merge-request: !4320
Brad King 5 years ago
parent
commit
200bc3b785

+ 84 - 0
Source/cmGeneratorTarget.cxx

@@ -1282,6 +1282,86 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
 }
 
 namespace {
+std::string AddSwiftInterfaceIncludeDirectories(
+  const cmGeneratorTarget* root, const cmGeneratorTarget* target,
+  const std::string& config, cmGeneratorExpressionDAGChecker* context)
+{
+  cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target,
+                                       "Swift_MODULE_DIRECTORY", nullptr,
+                                       context };
+  switch (dag.Check()) {
+    case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+      dag.ReportError(nullptr,
+                      "$<TARGET_PROPERTY:" + target->GetName() +
+                        ",Swift_MODULE_DIRECTORY>");
+      return "";
+    case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+      // No error. We just skip cyclic references.
+      return "";
+    case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+      // No error. We have already seen this transitive property.
+      return "";
+    case cmGeneratorExpressionDAGChecker::DAG:
+      break;
+  }
+
+  std::string directories;
+  if (const auto* interface =
+        target->GetLinkInterfaceLibraries(config, root, true)) {
+    for (const cmLinkItem& library : interface->Libraries) {
+      if (const cmGeneratorTarget* dependency = library.Target) {
+        if (cmContains(dependency->GetAllConfigCompileLanguages(), "Swift")) {
+          std::string value =
+            dependency->GetSafeProperty("Swift_MODULE_DIRECTORY");
+          if (value.empty()) {
+            value =
+              dependency->GetLocalGenerator()->GetCurrentBinaryDirectory();
+          }
+
+          if (!directories.empty()) {
+            directories += ";";
+          }
+          directories += value;
+        }
+      }
+    }
+  }
+  return directories;
+}
+
+void AddSwiftImplicitIncludeDirectories(
+  const cmGeneratorTarget* target, const std::string& config,
+  std::vector<EvaluatedTargetPropertyEntry>& entries)
+{
+  if (const auto* libraries = target->GetLinkImplementationLibraries(config)) {
+    cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target,
+                                         "Swift_MODULE_DIRECTORY", nullptr,
+                                         nullptr };
+
+    for (const cmLinkImplItem& library : libraries->Libraries) {
+      if (const cmGeneratorTarget* dependency = library.Target) {
+        if (cmContains(dependency->GetAllConfigCompileLanguages(), "Swift")) {
+          EvaluatedTargetPropertyEntry entry{ library, library.Backtrace };
+
+          if (const char* val =
+                dependency->GetProperty("Swift_MODULE_DIRECTORY")) {
+            entry.Values.emplace_back(val);
+          } else {
+            entry.Values.emplace_back(
+              dependency->GetLocalGenerator()->GetCurrentBinaryDirectory());
+          }
+
+          cmExpandList(AddSwiftInterfaceIncludeDirectories(target, dependency,
+                                                           config, &dag),
+                       entry.Values);
+
+          entries.emplace_back(std::move(entry));
+        }
+      }
+    }
+  }
+}
+
 void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
                          std::string const& config, std::string const& prop,
                          std::string const& lang,
@@ -3177,6 +3257,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
     EvaluateTargetPropertyEntries(this, config, lang, &dagChecker,
                                   this->IncludeDirectoriesEntries);
 
+  if (lang == "Swift") {
+    AddSwiftImplicitIncludeDirectories(this, config, entries);
+  }
+
   AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang,
                       &dagChecker, entries);
 

+ 24 - 0
Tests/SwiftOnly/CMakeLists.txt

@@ -1,4 +1,16 @@
 cmake_minimum_required(VERSION 3.3)
+
+# NOTE: Force the Release mode configuration as there are some issues with the
+# debug information handling on macOS on certain Xcode builds.
+if(NOT CMAKE_CONFIGURATION_TYPES)
+  set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build" FORCE)
+endif()
+
+# NOTE: enable shared libraries by default.  Older Xcode releases do not play
+# well with static libraries, and Windows does not currently support static
+# libraries in Swift.
+set(BUILD_SHARED_LIBS YES)
+
 project(SwiftOnly Swift)
 
 if(NOT XCODE_VERSION VERSION_LESS 10.2)
@@ -7,7 +19,19 @@ elseif(NOT XCODE_VERSION VERSION_LESS 8.0)
   set(CMAKE_Swift_LANGUAGE_VERSION 3.0)
 endif()
 
+set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift)
+
 add_executable(SwiftOnly main.swift)
 
+add_library(L L.swift)
+
+add_library(M M.swift)
+target_link_libraries(M PUBLIC
+  L)
+
+add_library(N N.swift)
+target_link_libraries(N PUBLIC
+  M)
+
 # Dummy to make sure generation works with such targets.
 add_library(SwiftIface INTERFACE)

+ 1 - 0
Tests/SwiftOnly/L.swift

@@ -0,0 +1 @@
+public let ThirtyTwo: Int = 32

+ 2 - 0
Tests/SwiftOnly/M.swift

@@ -0,0 +1,2 @@
+import L
+public let SixtyFour: Int = ThirtyTwo * 2

+ 2 - 0
Tests/SwiftOnly/N.swift

@@ -0,0 +1,2 @@
+import M
+public let OneTwentyEight = SixtyFour * 2