Skip to content

Commit 92d9e61

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

File tree

9 files changed

+139
-25
lines changed

9 files changed

+139
-25
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ SWIFTSCAN_PUBLIC swiftscan_string_ref_t
180180
swiftscan_swift_binary_detail_get_module_source_info_path(
181181
swiftscan_module_details_t details);
182182

183+
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
184+
swiftscan_swift_binary_detail_get_header_dependencies(
185+
swiftscan_module_details_t details);
186+
183187
SWIFTSCAN_PUBLIC bool
184188
swiftscan_swift_binary_detail_get_is_framework(
185189
swiftscan_module_details_t details);

include/swift/DependencyScan/DependencyScanImpl.h

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

124+
/// (Clang) header dependencies of this binary module.
125+
/// Typically pre-compiled bridging header.
126+
swiftscan_string_set_t *header_dependencies;
127+
124128
/// A flag to indicate whether or not this module is a framework.
125129
bool is_framework;
126130

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,14 @@ struct ExplicitSwiftModuleInputInfo {
241241
ExplicitSwiftModuleInputInfo(std::string modulePath,
242242
llvm::Optional<std::string> moduleDocPath,
243243
llvm::Optional<std::string> moduleSourceInfoPath,
244+
llvm::Optional<std::vector<std::string>> headerDependencyPaths,
244245
bool isFramework = false,
245246
bool isSystem = false,
246247
llvm::Optional<std::string> moduleCacheKey = None)
247248
: modulePath(modulePath),
248249
moduleDocPath(moduleDocPath),
249250
moduleSourceInfoPath(moduleSourceInfoPath),
251+
headerDependencyPaths(headerDependencyPaths),
250252
isFramework(isFramework),
251253
isSystem(isSystem),
252254
moduleCacheKey(moduleCacheKey) {}
@@ -256,6 +258,8 @@ struct ExplicitSwiftModuleInputInfo {
256258
llvm::Optional<std::string> moduleDocPath;
257259
// Path of the .swiftsourceinfo file.
258260
llvm::Optional<std::string> moduleSourceInfoPath;
261+
// Paths of the precompiled header dependencies of this module.
262+
llvm::Optional<std::vector<std::string>> headerDependencyPaths;
259263
// A flag that indicates whether this module is a framework
260264
bool isFramework = false;
261265
// A flag that indicates whether this module is a system module
@@ -369,34 +373,39 @@ class ExplicitModuleMapParser {
369373
llvm::Optional<std::string> swiftModulePath, swiftModuleDocPath,
370374
swiftModuleSourceInfoPath, swiftModuleCacheKey,
371375
clangModuleCacheKey;
376+
llvm::Optional<std::vector<std::string>> headerDependencyPaths;
372377
std::string clangModuleMapPath = "", clangModulePath = "";
373378
bool isFramework = false, isSystem = false;
374379
for (auto &entry : *mapNode) {
375380
auto key = getScalaNodeText(entry.getKey());
376-
auto val = getScalaNodeText(entry.getValue());
377-
if (key == "moduleName") {
378-
moduleName = val;
379-
} else if (key == "modulePath") {
380-
swiftModulePath = val.str();
381-
} else if (key == "docPath") {
382-
swiftModuleDocPath = val.str();
383-
} else if (key == "sourceInfoPath") {
384-
swiftModuleSourceInfoPath = val.str();
385-
} else if (key == "isFramework") {
386-
isFramework = parseBoolValue(val);
387-
} else if (key == "isSystem") {
388-
isSystem = parseBoolValue(val);
389-
} else if (key == "clangModuleMapPath") {
390-
clangModuleMapPath = val.str();
391-
} else if (key == "clangModulePath") {
392-
clangModulePath = val.str();
393-
} else if (key == "moduleCacheKey") {
394-
swiftModuleCacheKey = val.str();
395-
} else if (key == "clangModuleCacheKey") {
396-
clangModuleCacheKey = val.str();
397-
} else {
398-
// Being forgiving for future fields.
381+
if (key == "prebuiltHeaderDependencyPaths") {
399382
continue;
383+
} else {
384+
auto val = getScalaNodeText(entry.getValue());
385+
if (key == "moduleName") {
386+
moduleName = val;
387+
} else if (key == "modulePath") {
388+
swiftModulePath = val.str();
389+
} else if (key == "docPath") {
390+
swiftModuleDocPath = val.str();
391+
} else if (key == "sourceInfoPath") {
392+
swiftModuleSourceInfoPath = val.str();
393+
} else if (key == "isFramework") {
394+
isFramework = parseBoolValue(val);
395+
} else if (key == "isSystem") {
396+
isSystem = parseBoolValue(val);
397+
} else if (key == "clangModuleMapPath") {
398+
clangModuleMapPath = val.str();
399+
} else if (key == "clangModulePath") {
400+
clangModulePath = val.str();
401+
} else if (key == "moduleCacheKey") {
402+
swiftModuleCacheKey = val.str();
403+
} else if (key == "clangModuleCacheKey") {
404+
clangModuleCacheKey = val.str();
405+
} else {
406+
// Being forgiving for future fields.
407+
continue;
408+
}
400409
}
401410
}
402411
if (moduleName.empty())
@@ -409,6 +418,7 @@ class ExplicitModuleMapParser {
409418
ExplicitSwiftModuleInputInfo entry(swiftModulePath.value(),
410419
swiftModuleDocPath,
411420
swiftModuleSourceInfoPath,
421+
headerDependencyPaths,
412422
isFramework,
413423
isSystem,
414424
swiftModuleCacheKey);

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,12 @@ static llvm::Error resolveExplicitModuleInputs(
334334
: binaryDepDetails->moduleCacheKey;
335335
commandLine.push_back("-swift-module-file=" + depModuleID.first + "=" +
336336
path);
337+
for (const auto &headerDep : binaryDepDetails->preCompiledBridgingHeaderPaths) {
338+
commandLine.push_back("-Xcc");
339+
commandLine.push_back("-include-pch");
340+
commandLine.push_back("-Xcc");
341+
commandLine.push_back(headerDep);
342+
}
337343
} break;
338344
case swift::ModuleDependencyKind::SwiftPlaceholder: {
339345
auto placeholderDetails = depInfo->getAsPlaceholderDependencyModule();
@@ -1167,6 +1173,13 @@ static void writeJSON(llvm::raw_ostream &out,
11671173
swiftBinaryDeps->module_cache_key, 5,
11681174
/*trailingComma=*/true);
11691175
}
1176+
1177+
// Module Header Dependencies
1178+
if (swiftBinaryDeps->header_dependencies->count != 0)
1179+
writeJSONSingleField(out, "headerDependencies",
1180+
swiftBinaryDeps->header_dependencies, 5,
1181+
/*trailingComma=*/true);
1182+
11701183
writeJSONSingleField(out, "isFramework", swiftBinaryDeps->is_framework,
11711184
5, /*trailingComma=*/false);
11721185
} else {
@@ -1403,6 +1416,7 @@ generateFullDependencyGraph(CompilerInstance &instance,
14031416
create_clone(swiftBinaryDeps->compiledModulePath.c_str()),
14041417
create_clone(swiftBinaryDeps->moduleDocPath.c_str()),
14051418
create_clone(swiftBinaryDeps->sourceInfoPath.c_str()),
1419+
create_set(swiftBinaryDeps->preCompiledBridgingHeaderPaths),
14061420
swiftBinaryDeps->isFramework,
14071421
create_clone(swiftBinaryDeps->moduleCacheKey.c_str())};
14081422
} else {

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2004,7 +2004,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
20042004
const std::vector<std::pair<std::string, std::string>>
20052005
&commandLineExplicitInputs) {
20062006
for (const auto &moduleInput : commandLineExplicitInputs) {
2007-
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {});
2007+
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {}, {});
20082008
ExplicitModuleMap.try_emplace(moduleInput.first, std::move(entry));
20092009
}
20102010
}
@@ -2270,7 +2270,7 @@ struct ExplicitCASModuleLoader::Implementation {
22702270
const std::vector<std::pair<std::string, std::string>>
22712271
&commandLineExplicitInputs) {
22722272
for (const auto &moduleInput : commandLineExplicitInputs) {
2273-
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {});
2273+
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {}, {});
22742274
ExplicitModuleMap.try_emplace(moduleInput.first, std::move(entry));
22752275
}
22762276
}
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
@@ -344,6 +344,12 @@ swiftscan_swift_binary_detail_get_module_source_info_path(
344344
return details->swift_binary_details.module_source_info_path;
345345
}
346346

347+
swiftscan_string_set_t *
348+
swiftscan_swift_binary_detail_get_header_dependencies(
349+
swiftscan_module_details_t details) {
350+
return details->swift_binary_details.header_dependencies;
351+
}
352+
347353
bool swiftscan_swift_binary_detail_get_is_framework(
348354
swiftscan_module_details_t details) {
349355
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
@@ -22,6 +22,7 @@ swiftscan_swift_textual_detail_get_module_cache_key
2222
swiftscan_swift_binary_detail_get_compiled_module_path
2323
swiftscan_swift_binary_detail_get_module_doc_path
2424
swiftscan_swift_binary_detail_get_module_source_info_path
25+
swiftscan_swift_binary_detail_get_header_dependencies
2526
swiftscan_swift_binary_detail_get_is_framework
2627
swiftscan_swift_binary_detail_get_module_cache_key
2728
swiftscan_swift_placeholder_detail_get_compiled_module_path

0 commit comments

Comments
 (0)