Skip to content

Commit 1fbf112

Browse files
Adding bridging header as module handling
1 parent 893f014 commit 1fbf112

File tree

8 files changed

+407
-9
lines changed

8 files changed

+407
-9
lines changed

Sources/SwiftDriver/Driver/Driver.swift

+32-1
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ public struct Driver {
299299
/// The path to the pch for the imported Objective-C header.
300300
let bridgingPrecompiledHeader: VirtualPath.Handle?
301301

302+
/// The path to the module map for imported Objective-C header.
303+
let bridgingModuleMap: VirtualPath.Handle?
304+
302305
/// Path to the dependencies file.
303306
let dependenciesFilePath: VirtualPath.Handle?
304307

@@ -758,6 +761,9 @@ public struct Driver {
758761
compilerMode: compilerMode,
759762
importedObjCHeader: importedObjCHeader,
760763
outputFileMap: outputFileMap)
764+
self.bridgingModuleMap = try Self.generateModuleMapForObjCHeader(&parsedOptions,
765+
fileSystem: fileSystem,
766+
importedObjCHeader: importedObjCHeader)
761767

762768
self.supportedFrontendFlags =
763769
try Self.computeSupportedCompilerArgs(of: self.toolchain,
@@ -2739,7 +2745,8 @@ extension Driver {
27392745
outputFileMap: OutputFileMap?) throws -> VirtualPath.Handle? {
27402746
guard compilerMode.supportsBridgingPCH,
27412747
let input = importedObjCHeader,
2742-
parsedOptions.hasFlag(positive: .enableBridgingPch, negative: .disableBridgingPch, default: true) else {
2748+
parsedOptions.hasFlag(positive: .enableBridgingPch, negative: .disableBridgingPch, default: true),
2749+
!parsedOptions.hasArgument(.experimentalBridgingHeaderAsModule) else {
27432750
return nil
27442751
}
27452752

@@ -2755,6 +2762,30 @@ extension Driver {
27552762
return VirtualPath.createUniqueTemporaryFile(RelativePath(pchFileName)).intern()
27562763
}
27572764
}
2765+
2766+
/// Write the module map for bridging header.
2767+
static func generateModuleMapForObjCHeader(_ parsedOptions: inout ParsedOptions,
2768+
fileSystem: FileSystem,
2769+
importedObjCHeader: VirtualPath.Handle?) throws -> VirtualPath.Handle? {
2770+
guard let header = importedObjCHeader,
2771+
parsedOptions.hasArgument(.experimentalBridgingHeaderAsModule) else {
2772+
return nil
2773+
}
2774+
guard let moduleMapContent = """
2775+
module __ObjC {
2776+
umbrella header \"\(VirtualPath.lookup(header))\"
2777+
export *
2778+
}
2779+
""".data(using: .utf8) else { return nil }
2780+
// Write the modulemap inside -pch-output-dir if specified, otherwise in temporary directory.
2781+
if let outputDir = parsedOptions.getLastArgument(.pchOutputDir)?.asSingle {
2782+
let moduleMap = try VirtualPath(path: outputDir).appending(components: "module.modulemap")
2783+
try fileSystem.writeFileContents(moduleMap, bytes: ByteString(moduleMapContent), atomically: true)
2784+
return moduleMap.intern()
2785+
}
2786+
return VirtualPath.createUniqueTemporaryFileWithKnownContents(.init("module.modulemap"),
2787+
moduleMapContent).intern()
2788+
}
27582789
}
27592790

27602791
extension Diagnostic.Message {

Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,10 @@ public extension Driver {
106106
var commandLine: [Job.ArgTemplate] = swiftCompilerPrefixArgs.map { Job.ArgTemplate.flag($0) }
107107
commandLine.appendFlag("-frontend")
108108
commandLine.appendFlag("-scan-dependencies")
109+
110+
let bridgingHandling: BridgingHeaderHandling = parsedOptions.hasArgument(.experimentalBridgingHeaderAsModule) ? .module : .parsed
109111
try addCommonFrontendOptions(commandLine: &commandLine, inputs: &inputs, kind: .scanDependencies,
110-
bridgingHeaderHandling: .parsed,
112+
bridgingHeaderHandling: bridgingHandling,
111113
moduleDependencyGraphUse: .dependencyScan)
112114
// FIXME: MSVC runtime flags
113115

Sources/SwiftDriver/Jobs/CompileJob.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ extension Driver {
284284
commandLine.appendFlag(.disableObjcAttrRequiresFoundationModule)
285285
}
286286

287-
try addCommonFrontendOptions(commandLine: &commandLine, inputs: &inputs, kind: .compile)
287+
let bridgingHandling: BridgingHeaderHandling = parsedOptions.hasArgument(.experimentalBridgingHeaderAsModule) ? .module : .precompiled
288+
try addCommonFrontendOptions(commandLine: &commandLine, inputs: &inputs, kind: .compile, bridgingHeaderHandling: bridgingHandling)
288289

289290
// FIXME: MSVC runtime flags
290291

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

+20-6
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ extension Driver {
4141

4242
/// Use the precompiled bridging header.
4343
case precompiled
44+
45+
/// Use module for bridging header.
46+
case module
4447
}
4548
/// Whether the driver has already constructed a module dependency graph or is in the process
4649
/// of doing so
@@ -364,15 +367,17 @@ extension Driver {
364367
try commandLine.appendAll(.Xcc, from: &parsedOptions)
365368
}
366369

367-
if let importedObjCHeader = importedObjCHeader,
368-
bridgingHeaderHandling != .ignored {
369-
commandLine.appendFlag(.importObjcHeader)
370-
if bridgingHeaderHandling == .precompiled,
371-
let pch = bridgingPrecompiledHeader {
370+
if let importedObjCHeader = importedObjCHeader {
371+
switch bridgingHeaderHandling {
372+
case .ignored:
373+
break
374+
case .precompiled:
375+
guard let pch = bridgingPrecompiledHeader else { break }
372376
// For explicit module build, we directly pass the compiled pch as
373377
// `-import-objc-header`, rather than rely on swift-frontend to locate
374378
// the pch in the pchOutputDir and can start an implicit build in case
375379
// of a lookup failure.
380+
commandLine.appendFlag(.importObjcHeader)
376381
if parsedOptions.contains(.pchOutputDir) &&
377382
!parsedOptions.contains(.driverExplicitModuleBuild) {
378383
commandLine.appendPath(VirtualPath.lookup(importedObjCHeader))
@@ -383,8 +388,17 @@ extension Driver {
383388
} else {
384389
commandLine.appendPath(VirtualPath.lookup(pch))
385390
}
386-
} else {
391+
case .parsed:
392+
commandLine.appendFlag(.importObjcHeader)
387393
commandLine.appendPath(VirtualPath.lookup(importedObjCHeader))
394+
case .module:
395+
commandLine.appendFlag(.experimentalBridgingHeaderAsModule)
396+
// Tell clang importer where to look for the module map during dependency scanning.
397+
guard let moduleMapFile = bridgingModuleMap, kind == .scanDependencies else { break }
398+
commandLine.appendFlag(.clangModuleMap)
399+
commandLine.appendPath(VirtualPath.lookup(moduleMapFile))
400+
inputs.append(TypedVirtualPath(file: moduleMapFile,
401+
type: .clangModuleMap))
388402
}
389403
}
390404

Sources/SwiftOptions/Options.swift

+6
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ extension Option {
6060
public static let bsdk: Option = Option("-bsdk", .joinedOrSeparate, attributes: [.noDriver, .argumentIsPath], helpText: "path to the baseline SDK to import frameworks")
6161
public static let buildModuleFromParseableInterface: Option = Option("-build-module-from-parseable-interface", .flag, alias: Option.compileModuleFromInterface, attributes: [.helpHidden, .frontend, .noDriver], group: .modes)
6262
public static let bypassBatchModeChecks: Option = Option("-bypass-batch-mode-checks", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Bypass checks for batch-mode errors.")
63+
public static let bypassResilience: Option = Option("-bypass-resilience-checks", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Ignore all checks for module resilience.")
6364
public static let cacheCompileJob: Option = Option("-cache-compile-job", .flag, attributes: [.frontend], helpText: "Enable compiler caching")
6465
public static let cacheDisableReplay: Option = Option("-cache-disable-replay", .flag, attributes: [.frontend], helpText: "Skip loading the compilation result from cache")
6566
public static let candidateModuleFile: Option = Option("-candidate-module-file", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "<path>", helpText: "Specify Swift module may be ready to use for an interface")
@@ -74,6 +75,7 @@ extension Option {
7475
public static let clangHeaderExposeModule: Option = Option("-clang-header-expose-module", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "<imported-module-name>=<generated-header-name>", helpText: "Allow the compiler to assume that APIs from the specified module are exposed to C/C++/Objective-C in another generated header, so that APIs in the current module that depend on declarations from the specified module can be exposed in the generated header.")
7576
public static let clangIncludeTreeRoot: Option = Option("-clang-include-tree-root", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "<cas-id>", helpText: "Clang Include Tree CASID")
7677
public static let clangIncludeTree: Option = Option("-clang-include-tree", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use clang include tree")
78+
public static let clangModuleMap: Option = Option("-clang-module-map", .separate, attributes: [.frontend, .argumentIsPath], metaVar: "<path>", helpText: "clang module map path")
7779
public static let clangTarget: Option = Option("-clang-target", .separate, attributes: [.frontend], helpText: "Separately set the target we should use for internal Clang instance")
7880
public static let codeCompleteCallPatternHeuristics: Option = Option("-code-complete-call-pattern-heuristics", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use heuristics to guess whether we want call pattern completions")
7981
public static let codeCompleteInitsInPostfixExpr: Option = Option("-code-complete-inits-in-postfix-expr", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Include initializers when completing a postfix expression")
@@ -431,6 +433,7 @@ extension Option {
431433
public static let enforceExclusivityEQ: Option = Option("-enforce-exclusivity=", .joined, attributes: [.frontend, .moduleInterface], metaVar: "<enforcement>", helpText: "Enforce law of exclusivity")
432434
public static let entryPointFunctionName: Option = Option("-entry-point-function-name", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "<string>", helpText: "Name of the entry point function")
433435
public static let experimentalAllowModuleWithCompilerErrors: Option = Option("-experimental-allow-module-with-compiler-errors", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Attempt to output .swiftmodule, regardless of compilation errors")
436+
public static let experimentalBridgingHeaderAsModule: Option = Option("-experimental-bridging-header-as-module", .flag, attributes: [.frontend], helpText: "Import bridging header as module")
434437
public static let experimentalCForeignReferenceTypes: Option = Option("-experimental-c-foreign-reference-types", .flag, attributes: [.helpHidden, .frontend, .moduleInterface], helpText: "Enable experimental C foreign references types (with reference coutning).")
435438
public static let experimentalCxxStdlib: Option = Option("-experimental-cxx-stdlib", .separate, attributes: [.helpHidden], helpText: "C++ standard library to use; forwarded to Clang's -stdlib flag")
436439
public static let emitModuleSeparately: Option = Option("-experimental-emit-module-separately", .flag, attributes: [.helpHidden], helpText: "Emit module files as a distinct job")
@@ -853,6 +856,7 @@ extension Option {
853856
Option.bsdk,
854857
Option.buildModuleFromParseableInterface,
855858
Option.bypassBatchModeChecks,
859+
Option.bypassResilience,
856860
Option.cacheCompileJob,
857861
Option.cacheDisableReplay,
858862
Option.candidateModuleFile,
@@ -867,6 +871,7 @@ extension Option {
867871
Option.clangHeaderExposeModule,
868872
Option.clangIncludeTreeRoot,
869873
Option.clangIncludeTree,
874+
Option.clangModuleMap,
870875
Option.clangTarget,
871876
Option.codeCompleteCallPatternHeuristics,
872877
Option.codeCompleteInitsInPostfixExpr,
@@ -1224,6 +1229,7 @@ extension Option {
12241229
Option.enforceExclusivityEQ,
12251230
Option.entryPointFunctionName,
12261231
Option.experimentalAllowModuleWithCompilerErrors,
1232+
Option.experimentalBridgingHeaderAsModule,
12271233
Option.experimentalCForeignReferenceTypes,
12281234
Option.experimentalCxxStdlib,
12291235
Option.emitModuleSeparately,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "A.h"
2+
3+
@interface A
4+
@end
5+
6+
void bridgingA(A *a);

0 commit comments

Comments
 (0)