@@ -332,17 +332,38 @@ public struct Driver {
332332 }
333333 }
334334
335+ /// If PCH job is needed.
336+ let producePCHJob : Bool
337+
338+ /// Original ObjC Header passed from command-line
339+ let originalObjCHeaderFile : VirtualPath . Handle ?
340+
335341 /// The path to the imported Objective-C header.
336- let importedObjCHeader : VirtualPath . Handle ?
342+ lazy var importedObjCHeader : VirtualPath . Handle ? = {
343+ assert ( explicitDependencyBuildPlanner != nil ||
344+ !parsedOptions. hasArgument ( . driverExplicitModuleBuild) ||
345+ !inputFiles. contains { $0. type == . swift } ,
346+ " should not be queried before scanning " )
347+ let chainedBridgingHeader = try ? explicitDependencyBuildPlanner? . getChainedBridgingHeaderFile ( )
348+ return try ? computeImportedObjCHeader ( & parsedOptions, compilerMode: compilerMode,
349+ chainedBridgingHeader: chainedBridgingHeader) ?? originalObjCHeaderFile
350+ } ( )
351+
352+ /// The directory to emit PCH file.
353+ lazy var bridgingPrecompiledHeaderOutputDir : VirtualPath ? = {
354+ return try ? computePrecompiledBridgingHeaderDir ( & parsedOptions,
355+ compilerMode: compilerMode)
356+ } ( )
337357
338358 /// The path to the pch for the imported Objective-C header.
339359 lazy var bridgingPrecompiledHeader : VirtualPath . Handle ? = {
340360 let contextHash = try ? explicitDependencyBuildPlanner? . getMainModuleContextHash ( )
341- return Self . computeBridgingPrecompiledHeader ( & parsedOptions,
342- compilerMode: compilerMode,
343- importedObjCHeader: importedObjCHeader,
344- outputFileMap: outputFileMap,
345- contextHash: contextHash)
361+ return computeBridgingPrecompiledHeader ( & parsedOptions,
362+ compilerMode: compilerMode,
363+ importedObjCHeader: importedObjCHeader,
364+ outputFileMap: outputFileMap,
365+ outputDirectory: bridgingPrecompiledHeaderOutputDir,
366+ contextHash: contextHash)
346367 } ( )
347368
348369 /// Path to the dependencies file.
@@ -1049,8 +1070,6 @@ public struct Driver {
10491070 parsedOptions: parsedOptions,
10501071 recordedInputModificationDates: recordedInputModificationDates)
10511072
1052- self . importedObjCHeader = try Self . computeImportedObjCHeader ( & parsedOptions, compilerMode: compilerMode, diagnosticEngine: diagnosticEngine)
1053-
10541073 self . supportedFrontendFlags =
10551074 try Self . computeSupportedCompilerArgs ( of: self . toolchain,
10561075 libSwiftScan: self . swiftScanLibInstance,
@@ -1075,16 +1094,38 @@ public struct Driver {
10751094 diagnosticsEngine. emit ( . warning( " -cache-compile-job cannot be used without explicit module build, turn off caching " ) ,
10761095 location: nil )
10771096 self . enableCaching = false
1078- } else if importedObjCHeader != nil , !parsedOptions. hasFlag ( positive: . enableBridgingPch, negative: . disableBridgingPch, default: true ) {
1079- diagnosticsEngine. emit ( . warning( " -cache-compile-job cannot be used with -disable-bridging-pch, turn off caching " ) ,
1080- location: nil )
1081- self . enableCaching = false
10821097 } else {
10831098 self . enableCaching = true
10841099 }
10851100 } else {
10861101 self . enableCaching = false
10871102 }
1103+
1104+ // PCH related options.
1105+ if parsedOptions. hasArgument ( . importObjcHeader) {
1106+ // Check for conflicting options.
1107+ if parsedOptions. hasArgument ( . importUnderlyingModule) {
1108+ diagnosticEngine. emit ( . error_framework_bridging_header)
1109+ }
1110+
1111+ if parsedOptions. hasArgument ( . emitModuleInterface, . emitModuleInterfacePath) {
1112+ diagnosticEngine. emit ( . error_bridging_header_module_interface)
1113+ }
1114+ }
1115+ var maybeNeedPCH = parsedOptions. hasFlag ( positive: . enableBridgingPch, negative: . disableBridgingPch, default: true )
1116+ if enableCaching && !maybeNeedPCH {
1117+ diagnosticsEngine. emit ( . warning( " -cache-compile-job cannot be used with -disable-bridging-pch, turn on PCH generation " ) ,
1118+ location: nil )
1119+ maybeNeedPCH = true
1120+ }
1121+ self . producePCHJob = maybeNeedPCH
1122+
1123+ if let objcHeaderPathArg = parsedOptions. getLastArgument ( . importObjcHeader) {
1124+ self . originalObjCHeaderFile = try ? VirtualPath . intern ( path: objcHeaderPathArg. asSingle)
1125+ } else {
1126+ self . originalObjCHeaderFile = nil
1127+ }
1128+
10881129 self . useClangIncludeTree = !parsedOptions. hasArgument ( . noClangIncludeTree) && !env. keys. contains ( " SWIFT_CACHING_USE_CLANG_CAS_FS " )
10891130 self . scannerPrefixMap = try Self . computeScanningPrefixMapper ( & parsedOptions)
10901131 if let sdkMapping = parsedOptions. getLastArgument ( . scannerPrefixMapSdk) ? . asSingle {
@@ -3052,36 +3093,47 @@ extension Driver {
30523093// Imported Objective-C header.
30533094extension Driver {
30543095 /// Compute the path of the imported Objective-C header.
3055- static func computeImportedObjCHeader(
3096+ func computeImportedObjCHeader(
30563097 _ parsedOptions: inout ParsedOptions ,
30573098 compilerMode: CompilerMode ,
3058- diagnosticEngine: DiagnosticsEngine
3059- ) throws -> VirtualPath . Handle ? {
3060- guard let objcHeaderPathArg = parsedOptions. getLastArgument ( . importObjcHeader) else {
3061- return nil
3099+ chainedBridgingHeader: ChainedBridgingHeaderFile ? ) throws -> VirtualPath . Handle ? {
3100+ // handle chained bridging header.
3101+ if let chainedHeader = chainedBridgingHeader, !chainedHeader. path. isEmpty {
3102+ let path = try VirtualPath ( path: chainedHeader. path)
3103+ let dirExists = try fileSystem. exists ( path. parentDirectory)
3104+ if !dirExists, let dirToCreate = path. parentDirectory. absolutePath {
3105+ try fileSystem. createDirectory ( dirToCreate, recursive: true )
3106+ }
3107+ try fileSystem. writeFileContents ( path,
3108+ bytes: ByteString ( encodingAsUTF8: chainedHeader. content) ,
3109+ atomically: true )
3110+ return path. intern ( )
30623111 }
3112+ return originalObjCHeaderFile
3113+ }
30633114
3064- // Check for conflicting options.
3065- if parsedOptions. hasArgument ( . importUnderlyingModule) {
3066- diagnosticEngine. emit ( . error_framework_bridging_header)
3115+ /// Compute the path to the bridging precompiled header directory path.
3116+ func computePrecompiledBridgingHeaderDir(
3117+ _ parsedOptions: inout ParsedOptions ,
3118+ compilerMode: CompilerMode ) throws -> VirtualPath ? {
3119+ if let input = originalObjCHeaderFile,
3120+ let outputPath = try ? outputFileMap? . existingOutput ( inputFile: input, outputType: . pch) {
3121+ return VirtualPath . lookup ( outputPath) . parentDirectory
30673122 }
3068-
3069- if parsedOptions. hasArgument ( . emitModuleInterface, . emitModuleInterfacePath) {
3070- diagnosticEngine. emit ( . error_bridging_header_module_interface)
3123+ if let outputDir = parsedOptions. getLastArgument ( . pchOutputDir) ? . asSingle {
3124+ return try VirtualPath ( path: outputDir)
30713125 }
3072-
3073- return try VirtualPath . intern ( path: objcHeaderPathArg. asSingle)
3126+ return nil
30743127 }
30753128
30763129 /// Compute the path of the generated bridging PCH for the Objective-C header.
3077- static func computeBridgingPrecompiledHeader( _ parsedOptions: inout ParsedOptions ,
3078- compilerMode: CompilerMode ,
3079- importedObjCHeader: VirtualPath . Handle ? ,
3080- outputFileMap: OutputFileMap ? ,
3081- contextHash: String ? ) -> VirtualPath . Handle ? {
3082- guard compilerMode. supportsBridgingPCH,
3083- let input = importedObjCHeader,
3084- parsedOptions. hasFlag ( positive: . enableBridgingPch, negative: . disableBridgingPch, default: true ) else {
3130+ func computeBridgingPrecompiledHeader( _ parsedOptions: inout ParsedOptions ,
3131+ compilerMode: CompilerMode ,
3132+ importedObjCHeader: VirtualPath . Handle ? ,
3133+ outputFileMap: OutputFileMap ? ,
3134+ outputDirectory: VirtualPath ? ,
3135+ contextHash: String ? ) -> VirtualPath . Handle ? {
3136+ guard compilerMode. supportsBridgingPCH, producePCHJob, let input = importedObjCHeader else {
30853137 return nil
30863138 }
30873139
@@ -3096,8 +3148,8 @@ extension Driver {
30963148 } else {
30973149 pchFile = baseName. appendingFileTypeExtension ( . pch)
30983150 }
3099- if let outputDirectory = parsedOptions . getLastArgument ( . pchOutputDir ) ? . asSingle {
3100- return try ? VirtualPath ( path : outputDirectory) . appending ( component: pchFile) . intern ( )
3151+ if let outputDirectory = outputDirectory {
3152+ return outputDirectory. appending ( component: pchFile) . intern ( )
31013153 } else {
31023154 return try ? VirtualPath . temporary ( RelativePath ( validating: pchFile) ) . intern ( )
31033155 }
0 commit comments