Swift: Propagate Swift_MODULE_DIRECTORY as include directory
Teach include directory computation for Swift to implicitly propagate the `Swift_MODULE_DIRECTORY` of all linked targets as include directories. This is required to ensure that the swiftmodule of a linked target is accessible to the compiler of the current target. Fixes: #19272
This commit is contained in:
parent
cb8227ecbf
commit
2026915f8f
@ -1282,6 +1282,86 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
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,
|
void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
|
||||||
std::string const& config, std::string const& prop,
|
std::string const& config, std::string const& prop,
|
||||||
std::string const& lang,
|
std::string const& lang,
|
||||||
@ -3177,6 +3257,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
|
|||||||
EvaluateTargetPropertyEntries(this, config, lang, &dagChecker,
|
EvaluateTargetPropertyEntries(this, config, lang, &dagChecker,
|
||||||
this->IncludeDirectoriesEntries);
|
this->IncludeDirectoriesEntries);
|
||||||
|
|
||||||
|
if (lang == "Swift") {
|
||||||
|
AddSwiftImplicitIncludeDirectories(this, config, entries);
|
||||||
|
}
|
||||||
|
|
||||||
AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang,
|
AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang,
|
||||||
&dagChecker, entries);
|
&dagChecker, entries);
|
||||||
|
|
||||||
|
@ -1,4 +1,16 @@
|
|||||||
cmake_minimum_required(VERSION 3.3)
|
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)
|
project(SwiftOnly Swift)
|
||||||
|
|
||||||
if(NOT XCODE_VERSION VERSION_LESS 10.2)
|
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)
|
set(CMAKE_Swift_LANGUAGE_VERSION 3.0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift)
|
||||||
|
|
||||||
add_executable(SwiftOnly main.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.
|
# Dummy to make sure generation works with such targets.
|
||||||
add_library(SwiftIface INTERFACE)
|
add_library(SwiftIface INTERFACE)
|
||||||
|
1
Tests/SwiftOnly/L.swift
Normal file
1
Tests/SwiftOnly/L.swift
Normal file
@ -0,0 +1 @@
|
|||||||
|
public let ThirtyTwo: Int = 32
|
2
Tests/SwiftOnly/M.swift
Normal file
2
Tests/SwiftOnly/M.swift
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import L
|
||||||
|
public let SixtyFour: Int = ThirtyTwo * 2
|
2
Tests/SwiftOnly/N.swift
Normal file
2
Tests/SwiftOnly/N.swift
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import M
|
||||||
|
public let OneTwentyEight = SixtyFour * 2
|
Loading…
Reference in New Issue
Block a user