Skip to content

Commit e8c40d9

Browse files
committed
[Dependency Scanning] Emit header dependencies of binary Swift module dependencies in output and provide libSwiftScan API to query it
1 parent c1ff14b commit e8c40d9

File tree

10 files changed

+137
-23
lines changed

10 files changed

+137
-23
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ SWIFTSCAN_PUBLIC swiftscan_string_ref_t
168168
swiftscan_swift_binary_detail_get_module_source_info_path(
169169
swiftscan_module_details_t details);
170170

171+
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
172+
swiftscan_swift_binary_detail_get_header_dependencies(
173+
swiftscan_module_details_t details);
174+
171175
SWIFTSCAN_PUBLIC bool
172176
swiftscan_swift_binary_detail_get_is_framework(
173177
swiftscan_module_details_t details);

include/swift/DependencyScan/DependencyScanImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ typedef struct {
109109
/// The path to the .swiftSourceInfo file.
110110
swiftscan_string_ref_t module_source_info_path;
111111

112+
/// (Clang) header dependencies of this binary module.
113+
/// Typically pre-compiled bridging header.
114+
swiftscan_string_set_t *header_dependencies;
115+
112116
/// A flag to indicate whether or not this module is a framework.
113117
bool is_framework;
114118
} swiftscan_swift_binary_details_t;

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,13 @@ struct ExplicitSwiftModuleInputInfo {
184184
ExplicitSwiftModuleInputInfo(std::string modulePath,
185185
llvm::Optional<std::string> moduleDocPath,
186186
llvm::Optional<std::string> moduleSourceInfoPath,
187+
llvm::Optional<std::vector<std::string>> headerDependencyPaths,
187188
bool isFramework = false,
188189
bool isSystem = false)
189190
: modulePath(modulePath),
190191
moduleDocPath(moduleDocPath),
191192
moduleSourceInfoPath(moduleSourceInfoPath),
193+
headerDependencyPaths(headerDependencyPaths),
192194
isFramework(isFramework),
193195
isSystem(isSystem) {}
194196
// Path of the .swiftmodule file.
@@ -197,6 +199,8 @@ struct ExplicitSwiftModuleInputInfo {
197199
llvm::Optional<std::string> moduleDocPath;
198200
// Path of the .swiftsourceinfo file.
199201
llvm::Optional<std::string> moduleSourceInfoPath;
202+
// Paths of the precompiled header dependencies of this module.
203+
llvm::Optional<std::vector<std::string>> headerDependencyPaths;
200204
// A flag that indicates whether this module is a framework
201205
bool isFramework = false;
202206
// A flag that indicates whether this module is a system module
@@ -306,30 +310,35 @@ class ExplicitModuleMapParser {
306310
StringRef moduleName;
307311
llvm::Optional<std::string> swiftModulePath, swiftModuleDocPath,
308312
swiftModuleSourceInfoPath;
313+
llvm::Optional<std::vector<std::string>> headerDependencyPaths;
309314
std::string clangModuleMapPath = "", clangModulePath = "";
310315
bool isFramework = false, isSystem = false;
311316
for (auto &entry : *mapNode) {
312317
auto key = getScalaNodeText(entry.getKey());
313-
auto val = getScalaNodeText(entry.getValue());
314-
if (key == "moduleName") {
315-
moduleName = val;
316-
} else if (key == "modulePath") {
317-
swiftModulePath = val.str();
318-
} else if (key == "docPath") {
319-
swiftModuleDocPath = val.str();
320-
} else if (key == "sourceInfoPath") {
321-
swiftModuleSourceInfoPath = val.str();
322-
} else if (key == "isFramework") {
323-
isFramework = parseBoolValue(val);
324-
} else if (key == "isSystem") {
325-
isSystem = parseBoolValue(val);
326-
} else if (key == "clangModuleMapPath") {
327-
clangModuleMapPath = val.str();
328-
} else if (key == "clangModulePath") {
329-
clangModulePath = val.str();
330-
} else {
331-
// Being forgiving for future fields.
318+
if (key == "prebuiltHeaderDependencyPaths") {
332319
continue;
320+
} else {
321+
auto val = getScalaNodeText(entry.getValue());
322+
if (key == "moduleName") {
323+
moduleName = val;
324+
} else if (key == "modulePath") {
325+
swiftModulePath = val.str();
326+
} else if (key == "docPath") {
327+
swiftModuleDocPath = val.str();
328+
} else if (key == "sourceInfoPath") {
329+
swiftModuleSourceInfoPath = val.str();
330+
} else if (key == "isFramework") {
331+
isFramework = parseBoolValue(val);
332+
} else if (key == "isSystem") {
333+
isSystem = parseBoolValue(val);
334+
} else if (key == "clangModuleMapPath") {
335+
clangModuleMapPath = val.str();
336+
} else if (key == "clangModulePath") {
337+
clangModulePath = val.str();
338+
} else {
339+
// Being forgiving for future fields.
340+
continue;
341+
}
333342
}
334343
}
335344
if (moduleName.empty())
@@ -342,6 +351,7 @@ class ExplicitModuleMapParser {
342351
ExplicitSwiftModuleInputInfo entry(swiftModulePath.value(),
343352
swiftModuleDocPath,
344353
swiftModuleSourceInfoPath,
354+
headerDependencyPaths,
345355
isFramework,
346356
isSystem);
347357
swiftModuleMap.try_emplace(moduleName, std::move(entry));

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,15 @@ resolveExplicitModuleInputs(ModuleDependencyID moduleID,
276276
case swift::ModuleDependencyKind::SwiftBinary: {
277277
auto binaryDepDetails = depInfo->getAsSwiftBinaryModule();
278278
assert(binaryDepDetails && "Expected Swift Binary Module dependency.");
279+
auto &path = binaryDepDetails->compiledModulePath;
279280
commandLine.push_back("-swift-module-file=" + depModuleID.first + "=" +
280-
binaryDepDetails->compiledModulePath);
281+
path);
282+
for (const auto &headerDep : binaryDepDetails->preCompiledBridgingHeaderPaths) {
283+
commandLine.push_back("-Xcc");
284+
commandLine.push_back("-include-pch");
285+
commandLine.push_back("-Xcc");
286+
commandLine.push_back(headerDep);
287+
}
281288
} break;
282289
case swift::ModuleDependencyKind::SwiftPlaceholder: {
283290
auto placeholderDetails = depInfo->getAsPlaceholderDependencyModule();
@@ -943,6 +950,13 @@ static void writeJSON(llvm::raw_ostream &out,
943950
swiftBinaryDeps->module_source_info_path,
944951
/*indentLevel=*/5,
945952
/*trailingComma=*/true);
953+
954+
// Module Header Dependencies
955+
if (swiftBinaryDeps->header_dependencies->count != 0)
956+
writeJSONSingleField(out, "headerDependencies",
957+
swiftBinaryDeps->header_dependencies, 5,
958+
/*trailingComma=*/true);
959+
946960
writeJSONSingleField(out, "isFramework", swiftBinaryDeps->is_framework,
947961
5, /*trailingComma=*/false);
948962
} else {
@@ -1129,6 +1143,7 @@ generateFullDependencyGraph(CompilerInstance &instance,
11291143
create_clone(swiftBinaryDeps->compiledModulePath.c_str()),
11301144
create_clone(swiftBinaryDeps->moduleDocPath.c_str()),
11311145
create_clone(swiftBinaryDeps->sourceInfoPath.c_str()),
1146+
create_set(swiftBinaryDeps->preCompiledBridgingHeaderPaths),
11321147
swiftBinaryDeps->isFramework};
11331148
} else {
11341149
// Clang module details

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1995,7 +1995,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
19951995
const std::vector<std::pair<std::string, std::string>>
19961996
&commandLineExplicitInputs) {
19971997
for (const auto &moduleInput : commandLineExplicitInputs) {
1998-
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {});
1998+
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {}, {});
19991999
ExplicitModuleMap.try_emplace(moduleInput.first, std::move(entry));
20002000
}
20012001
}

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,8 +478,7 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework) {
478478
// Map the set of dependencies over to the "module dependencies".
479479
auto dependencies = ModuleDependencyInfo::forSwiftBinaryModule(
480480
modulePath.str(), moduleDocPath, sourceInfoPath,
481-
importedModuleNames, importedHeaders, isFramework,
482-
/*module-cache-key*/ "");
481+
importedModuleNames, importedHeaders, isFramework);
483482

484483
return std::move(dependencies);
485484
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name FooClient
3+
import Swift
4+
import Foo
5+
public func overlayFuncA() { }
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// REQUIRES: objc_interop, OS=macosx
2+
// RUN: %empty-directory(%t)
3+
// RUN: %empty-directory(%t/clang-module-cache)
4+
// RUN: %empty-directory(%t/PCH)
5+
// RUN: %empty-directory(%t/SwiftModules)
6+
7+
// - Set up Foo Swift dependency
8+
// RUN: echo "extension Profiler {" >> %t/foo.swift
9+
// RUN: echo " public static let count: Int = 42" >> %t/foo.swift
10+
// RUN: echo "}" >> %t/foo.swift
11+
12+
// - Set up Foo bridging header
13+
// RUN: echo "struct Profiler { void* ptr; };" >> %t/foo.h
14+
15+
// - Compile bridging header
16+
// RUN: %target-swift-frontend -enable-objc-interop -emit-pch %t/foo.h -o %t/PCH/foo.pch -disable-implicit-swift-modules
17+
18+
// - Set up explicit dependencies for Foo
19+
// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift-lib-dir/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm
20+
// RUN: %target-swift-emit-pcm -module-name _SwiftConcurrencyShims %swift-lib-dir/swift/shims/module.modulemap -o %t/inputs/_SwiftConcurrencyShims.pcm
21+
// RUN: echo "[{" > %t/foo_inputs_map.json
22+
// RUN: echo "\"moduleName\": \"Swift\"," >> %t/foo_inputs_map.json
23+
// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %t/foo_inputs_map.json
24+
// RUN: echo "\"isFramework\": false" >> %t/foo_inputs_map.json
25+
// RUN: echo "}," >> %t/foo_inputs_map.json
26+
// RUN: echo "{" >> %t/foo_inputs_map.json
27+
// RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %t/foo_inputs_map.json
28+
// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %t/foo_inputs_map.json
29+
// RUN: echo "\"isFramework\": false" >> %t/foo_inputs_map.json
30+
// RUN: echo "}," >> %t/foo_inputs_map.json
31+
// RUN: echo "{" >> %t/foo_inputs_map.json
32+
// RUN: echo "\"moduleName\": \"_StringProcessing\"," >> %t/foo_inputs_map.json
33+
// RUN: echo "\"modulePath\": \"%/string_processing_module\"," >> %t/foo_inputs_map.json
34+
// RUN: echo "\"isFramework\": false" >> %t/foo_inputs_map.json
35+
// RUN: echo "}," >> %t/foo_inputs_map.json
36+
// RUN: echo "{" >> %t/foo_inputs_map.json
37+
// RUN: echo "\"moduleName\": \"SwiftShims\"," >> %t/foo_inputs_map.json
38+
// RUN: echo "\"isFramework\": false," >> %t/foo_inputs_map.json
39+
// RUN: echo "\"clangModuleMapPath\": \"%swift-lib-dir/swift/shims/module.modulemap\"," >> %t/foo_inputs_map.json
40+
// RUN: echo "\"clangModulePath\": \"%t/inputs/SwiftShims.pcm\"" >> %t/foo_inputs_map.json
41+
// RUN: echo "}," >> %t/foo_inputs_map.json
42+
// RUN: echo "{" >> %t/foo_inputs_map.json
43+
// RUN: echo "\"moduleName\": \"_SwiftConcurrencyShims\"," >> %t/foo_inputs_map.json
44+
// RUN: echo "\"isFramework\": false," >> %t/foo_inputs_map.json
45+
// RUN: echo "\"clangModuleMapPath\": \"%swift-lib-dir/swift/shims/module.modulemap\"," >> %t/foo_inputs_map.json
46+
// RUN: echo "\"clangModulePath\": \"%t/inputs/_SwiftConcurrencyShims.pcm\"" >> %t/foo_inputs_map.json
47+
// RUN: echo "}]" >> %t/foo_inputs_map.json
48+
49+
// - Build Foo module dependency, explicitly
50+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/SwiftModules/Foo.swiftmodule %t/foo.swift -module-name Foo -import-objc-header %t/PCH/foo.pch -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -disable-implicit-swift-modules -explicit-swift-module-map-file %t/foo_inputs_map.json
51+
52+
// - Scan main module
53+
// RUN: %target-swift-frontend -scan-dependencies %s -I %t/SwiftModules -I %S/Inputs/Swift -o %t/deps.json
54+
// RUN: %FileCheck %s --input-file %t/deps.json
55+
56+
// CHECK: "swift": "FooClient"
57+
// CHECK: "swift": "FooClient"
58+
// CHECK: "swiftPrebuiltExternal": "Foo"
59+
// CHECK: "commandLine": [
60+
// CHECK: "-include-pch",
61+
// CHECK-NEXT: "-Xcc",
62+
// CHECK-NEXT: "{{.*}}{{/|\\}}PCH{{/|\\}}foo.pch"
63+
64+
65+
// CHECK: "swiftPrebuiltExternal": "Foo"
66+
// CHECK: "headerDependencies": [
67+
// CHECK: "{{.*}}{{/|\\}}PCH{{/|\\}}foo.pch"
68+
// CHECK: ],
69+
70+
import FooClient

tools/libSwiftScan/libSwiftScan.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,12 @@ swiftscan_swift_binary_detail_get_module_source_info_path(
314314
return details->swift_binary_details.module_source_info_path;
315315
}
316316

317+
swiftscan_string_set_t *
318+
swiftscan_swift_binary_detail_get_header_dependencies(
319+
swiftscan_module_details_t details) {
320+
return details->swift_binary_details.header_dependencies;
321+
}
322+
317323
bool swiftscan_swift_binary_detail_get_is_framework(
318324
swiftscan_module_details_t details) {
319325
return details->swift_binary_details.is_framework;

tools/libSwiftScan/libSwiftScan.exports

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ swiftscan_swift_textual_detail_get_swift_overlay_dependencies
1919
swiftscan_swift_binary_detail_get_compiled_module_path
2020
swiftscan_swift_binary_detail_get_module_doc_path
2121
swiftscan_swift_binary_detail_get_module_source_info_path
22+
swiftscan_swift_binary_detail_get_header_dependencies
2223
swiftscan_swift_binary_detail_get_is_framework
2324
swiftscan_swift_placeholder_detail_get_compiled_module_path
2425
swiftscan_swift_placeholder_detail_get_module_doc_path

0 commit comments

Comments
 (0)