Skip to content

Commit f6ea53e

Browse files
authored
Merge pull request #1039 from nkcsgexi/additional-framework-search-path
PrebuiltModuleGen: add additional framework search paths
2 parents 2ed97d4 + f3d4d83 commit f6ea53e

File tree

8 files changed

+138
-12
lines changed

8 files changed

+138
-12
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,13 +349,20 @@ public struct Driver {
349349
return VirtualPath.lookup(rawSdkPath)
350350
} ()
351351

352-
lazy var iosMacFrameworksSearchPath: VirtualPath = {
352+
lazy var iosMacFrameworksBase: VirtualPath = {
353353
sdkPath!
354354
.appending(component: "System")
355355
.appending(component: "iOSSupport")
356356
.appending(component: "System")
357357
.appending(component: "Library")
358-
.appending(component: "Frameworks")
358+
} ()
359+
360+
lazy var iosMacFrameworksSearchPath: VirtualPath = {
361+
iosMacFrameworksBase.appending(component: "Frameworks")
362+
} ()
363+
364+
lazy var iosMacPrivateFrameworksSearchPath: VirtualPath = {
365+
iosMacFrameworksBase.appending(component: "PrivateFrameworks")
359366
} ()
360367

361368
lazy var abiDescriptorPath: TypedVirtualPath? = {

Sources/SwiftDriver/Jobs/PrebuiltModulesJob.swift

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212
import TSCBasic
1313
import SwiftOptions
14+
import Foundation
1415

1516
@_spi(Testing) public func isIosMacInterface(_ path: VirtualPath) throws -> Bool {
1617
let data = try localFileSystem.readFileContents(path).cString
@@ -241,14 +242,54 @@ public struct PrebuiltModuleInput {
241242
}
242243
}
243244

245+
public class SwiftAdopter: Codable {
246+
public let name: String
247+
public let moduleDir: String
248+
public let hasInterface: Bool
249+
public let hasModule: Bool
250+
public let isFramework: Bool
251+
public let isPrivate: Bool
252+
init(_ name: String, _ moduleDir: AbsolutePath, _ hasInterface: AbsolutePath?, _ hasModule: AbsolutePath?) {
253+
self.name = name
254+
self.moduleDir = SwiftAdopter.relativeToSDK(moduleDir)
255+
self.hasInterface = hasInterface != nil
256+
self.hasModule = hasModule != nil
257+
self.isFramework = self.moduleDir.contains("\(name).framework")
258+
self.isPrivate = self.moduleDir.contains("PrivateFrameworks")
259+
}
260+
static func relativeToSDK(_ fullPath: AbsolutePath) -> String {
261+
var SDKDir: AbsolutePath = fullPath
262+
while(SDKDir.extension != "sdk") {
263+
SDKDir = SDKDir.parentDirectory
264+
}
265+
assert(SDKDir.extension == "sdk")
266+
SDKDir = SDKDir.parentDirectory
267+
return fullPath.relative(to: SDKDir).pathString
268+
}
269+
270+
static public func emitSummary(_ adopters: [SwiftAdopter], to logDir: AbsolutePath?) throws {
271+
guard let logDir = logDir else { return }
272+
if !localFileSystem.exists(logDir) {
273+
try localFileSystem.createDirectory(logDir, recursive: true)
274+
}
275+
let data = try JSONEncoder().encode(adopters)
276+
if let json = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers),
277+
let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) {
278+
try localFileSystem.writeFileContents(logDir.appending(component: "adopters.json"), bytes: ByteString(jsonData))
279+
}
280+
}
281+
}
282+
244283
typealias PrebuiltModuleOutput = PrebuiltModuleInput
245284

246285
public struct SDKPrebuiltModuleInputsCollector {
247286
let sdkPath: AbsolutePath
248287
let nonFrameworkDirs = [RelativePath("usr/lib/swift"),
249288
RelativePath("System/iOSSupport/usr/lib/swift")]
250289
let frameworkDirs = [RelativePath("System/Library/Frameworks"),
251-
RelativePath("System/iOSSupport/System/Library/Frameworks")]
290+
RelativePath("System/Library/PrivateFrameworks"),
291+
RelativePath("System/iOSSupport/System/Library/Frameworks"),
292+
RelativePath("System/iOSSupport/System/Library/PrivateFrameworks")]
252293
let sdkInfo: DarwinToolchain.DarwinSDKInfo
253294
let diagEngine: DiagnosticsEngine
254295
public init(_ sdkPath: AbsolutePath, _ diagEngine: DiagnosticsEngine) {
@@ -296,7 +337,8 @@ public struct SDKPrebuiltModuleInputsCollector {
296337
}
297338
}
298339

299-
public func collectSwiftInterfaceMap() throws -> [String: [PrebuiltModuleInput]] {
340+
public func collectSwiftInterfaceMap() throws -> (inputMap: [String: [PrebuiltModuleInput]], adopters: [SwiftAdopter]) {
341+
var allSwiftAdopters: [SwiftAdopter] = []
300342
var results: [String: [PrebuiltModuleInput]] = [:]
301343

302344
func updateResults(_ dir: AbsolutePath) throws {
@@ -307,7 +349,8 @@ public struct SDKPrebuiltModuleInputsCollector {
307349
if results[moduleName] == nil {
308350
results[moduleName] = []
309351
}
310-
352+
var hasInterface: AbsolutePath?
353+
var hasModule: AbsolutePath?
311354
// Search inside a .swiftmodule directory for any .swiftinterface file, and
312355
// add the files into the dictionary.
313356
// Duplicate entries are discarded, otherwise llbuild will complain.
@@ -320,11 +363,14 @@ public struct SDKPrebuiltModuleInputsCollector {
320363
if !results[moduleName]!.contains(where: { $0.path.file.basenameWithoutExt == currentBaseName }) {
321364
results[moduleName]!.append(PrebuiltModuleInput(interfacePath))
322365
}
366+
hasInterface = currentFile
323367
}
324368
if currentFile.extension == "swiftmodule" {
325369
diagEngine.emit(warning: "found \(currentFile)")
370+
hasModule = currentFile
326371
}
327372
}
373+
allSwiftAdopters.append(SwiftAdopter(moduleName, dir, hasInterface, hasModule))
328374
}
329375
// Search inside framework dirs in an SDK to find .swiftmodule directories.
330376
for dir in frameworkDirs {
@@ -356,7 +402,7 @@ public struct SDKPrebuiltModuleInputsCollector {
356402
}
357403
}
358404
}
359-
return sanitizeInterfaceMap(results)
405+
return (inputMap: sanitizeInterfaceMap(results), adopters: allSwiftAdopters)
360406
}
361407
}
362408

@@ -448,10 +494,12 @@ extension Driver {
448494
_ dependencies: [TypedVirtualPath], _ currentABIDir: AbsolutePath?,
449495
_ baselineABIDir: AbsolutePath?) throws -> [Job] {
450496
assert(inputPath.path.file.basenameWithoutExt == outputPath.path.file.basenameWithoutExt)
497+
let sdkPath = sdkPath!
498+
let isInternal = sdkPath.basename.hasSuffix(".Internal.sdk")
451499
var commandLine: [Job.ArgTemplate] = []
452500
commandLine.appendFlag(.compileModuleFromInterface)
453501
commandLine.appendFlag(.sdk)
454-
commandLine.append(.path(sdkPath!))
502+
commandLine.append(.path(sdkPath))
455503
commandLine.appendFlag(.prebuiltModuleCachePath)
456504
commandLine.appendPath(prebuiltModuleDir)
457505
commandLine.appendFlag(.moduleName)
@@ -467,6 +515,16 @@ extension Driver {
467515
if try isIosMacInterface(inputPath.path.file) {
468516
commandLine.appendFlag(.Fsystem)
469517
commandLine.append(.path(iosMacFrameworksSearchPath))
518+
if isInternal {
519+
commandLine.appendFlag(.Fsystem)
520+
commandLine.append(.path(iosMacPrivateFrameworksSearchPath))
521+
}
522+
}
523+
if isInternal {
524+
commandLine.appendFlag(.Fsystem)
525+
commandLine.append(.path(sdkPath.appending(component: "System")
526+
.appending(component: "Library")
527+
.appending(component: "PrivateFrameworks")))
470528
}
471529
// Use the specified module cache dir
472530
if let mcp = parsedOptions.getLastArgument(.moduleCachePath)?.asSingle {

Sources/swift-build-sdk-interfaces/main.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ do {
6767
diagnosticsEngine.emit(error: "cannot find sdk: \(sdkPath.pathString)")
6868
exit(1)
6969
}
70+
let logDir = try getArgumentAsPath("-log-path")
7071
let collector = SDKPrebuiltModuleInputsCollector(sdkPath, diagnosticsEngine)
7172
var outputDir = try VirtualPath(path: rawOutputDir).absolutePath!
7273
// if the given output dir ends with 'prebuilt-modules', we should
@@ -108,7 +109,11 @@ do {
108109
.appending(component: "SystemVersion.plist"),
109110
to: sysVersionFile)
110111
let processSet = ProcessSet()
111-
let inputMap = try collector.collectSwiftInterfaceMap()
112+
let inputTuple = try collector.collectSwiftInterfaceMap()
113+
let allAdopters = inputTuple.adopters
114+
let currentABIDir = try getArgumentAsPath("-current-abi-dir")
115+
try SwiftAdopter.emitSummary(allAdopters, to: currentABIDir)
116+
let inputMap = inputTuple.inputMap
112117
let allModules = coreMode ? ["Foundation"] : Array(inputMap.keys)
113118
try withTemporaryFile(suffix: ".swift") {
114119
let tempPath = $0.path
@@ -131,8 +136,6 @@ do {
131136
args.append(mcpFlag)
132137
args.append(mcp)
133138
}
134-
let logDir = try getArgumentAsPath("-log-path")
135-
let currentABIDir = try getArgumentAsPath("-current-abi-dir")
136139
let baselineABIDir = try getArgumentAsPath("-baseline-abi-dir")
137140
var driver = try Driver(args: args,
138141
diagnosticsEngine: diagnosticsEngine,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Version": "10.15",
3+
"VersionMap": {
4+
"macOS_iOSMac": {},
5+
"iOSMac_macOS": {}
6+
},
7+
"CanonicalName": "macosx10.15"
8+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name A
3+
import Swift
4+
public func FuncA() { }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name A
3+
import Swift
4+
public func FuncA() { }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name A
3+
import Swift
4+
public func FuncA() { }

Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
13101310
testInputsPath.appending(component: "mock-sdk.sdk").pathString
13111311
let diagnosticEnging = DiagnosticsEngine()
13121312
let collector = try SDKPrebuiltModuleInputsCollector(VirtualPath(path: mockSDKPath).absolutePath!, diagnosticEnging)
1313-
let interfaceMap = try collector.collectSwiftInterfaceMap()
1313+
let interfaceMap = try collector.collectSwiftInterfaceMap().inputMap
13141314

13151315
// Check interface map always contain everything
13161316
XCTAssertTrue(interfaceMap["Swift"]!.count == 3)
@@ -1486,7 +1486,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
14861486
let baselineABIPath: String =
14871487
testInputsPath.appending(component: "ABIBaselines").pathString
14881488
let collector = try SDKPrebuiltModuleInputsCollector(VirtualPath(path: mockSDKPath).absolutePath!, DiagnosticsEngine())
1489-
let interfaceMap = try collector.collectSwiftInterfaceMap()
1489+
let interfaceMap = try collector.collectSwiftInterfaceMap().inputMap
14901490
try withTemporaryDirectory { path in
14911491
let main = path.appending(component: "testPrebuiltModuleGenerationJobs.swift")
14921492
try localFileSystem.writeFileContents(main) {
@@ -1510,5 +1510,43 @@ final class ExplicitModuleBuildTests: XCTestCase {
15101510
try abiCheckJobs.forEach { try checkABICheckingJob($0) }
15111511
}
15121512
}
1513+
func testPrebuiltModuleInternalSDK() throws {
1514+
let mockSDKPath = testInputsPath.appending(component: "mock-sdk.Internal.sdk")
1515+
let mockSDKPathStr: String = mockSDKPath.pathString
1516+
let collector = try SDKPrebuiltModuleInputsCollector(VirtualPath(path: mockSDKPathStr).absolutePath!, DiagnosticsEngine())
1517+
let interfaceMap = try collector.collectSwiftInterfaceMap().inputMap
1518+
try withTemporaryDirectory { path in
1519+
let main = path.appending(component: "testPrebuiltModuleGenerationJobs.swift")
1520+
try localFileSystem.writeFileContents(main) {
1521+
$0 <<< "import A\n"
1522+
}
1523+
let moduleCachePath = "/tmp/module-cache"
1524+
var driver = try Driver(args: ["swiftc", main.pathString,
1525+
"-sdk", mockSDKPathStr,
1526+
"-module-cache-path", moduleCachePath
1527+
])
1528+
let (jobs, _) = try driver.generatePrebuitModuleGenerationJobs(with: interfaceMap,
1529+
into: path,
1530+
exhaustive: true)
1531+
let compileJobs = jobs.filter {$0.kind == .compile}
1532+
XCTAssertTrue(!compileJobs.isEmpty)
1533+
XCTAssertTrue(compileJobs.allSatisfy { $0.commandLine.contains(.flag("-suppress-warnings")) })
1534+
let PFPath = mockSDKPath.appending(component: "System").appending(component: "Library")
1535+
.appending(component: "PrivateFrameworks")
1536+
XCTAssertTrue(compileJobs.allSatisfy { $0.commandLine.contains(.path(VirtualPath.absolute(PFPath))) })
1537+
}
1538+
}
1539+
func testCollectSwiftAdopters() throws {
1540+
let mockSDKPath = testInputsPath.appending(component: "mock-sdk.Internal.sdk")
1541+
let mockSDKPathStr: String = mockSDKPath.pathString
1542+
let collector = try SDKPrebuiltModuleInputsCollector(VirtualPath(path: mockSDKPathStr).absolutePath!, DiagnosticsEngine())
1543+
let adopters = try collector.collectSwiftInterfaceMap().adopters
1544+
XCTAssertTrue(!adopters.isEmpty)
1545+
let A = adopters.first {$0.name == "A"}!
1546+
XCTAssertFalse(A.isFramework)
1547+
XCTAssertFalse(A.isPrivate)
1548+
XCTAssertFalse(A.hasModule)
1549+
XCTAssertTrue(A.hasInterface)
1550+
}
15131551
#endif
15141552
}

0 commit comments

Comments
 (0)