@@ -332,17 +332,38 @@ public struct Driver {
332
332
}
333
333
}
334
334
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
+
335
341
/// 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
+ } ( )
337
357
338
358
/// The path to the pch for the imported Objective-C header.
339
359
lazy var bridgingPrecompiledHeader : VirtualPath . Handle ? = {
340
360
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)
346
367
} ( )
347
368
348
369
/// Path to the dependencies file.
@@ -1049,8 +1070,6 @@ public struct Driver {
1049
1070
parsedOptions: parsedOptions,
1050
1071
recordedInputModificationDates: recordedInputModificationDates)
1051
1072
1052
- self . importedObjCHeader = try Self . computeImportedObjCHeader ( & parsedOptions, compilerMode: compilerMode, diagnosticEngine: diagnosticEngine)
1053
-
1054
1073
self . supportedFrontendFlags =
1055
1074
try Self . computeSupportedCompilerArgs ( of: self . toolchain,
1056
1075
libSwiftScan: self . swiftScanLibInstance,
@@ -1075,16 +1094,38 @@ public struct Driver {
1075
1094
diagnosticsEngine. emit ( . warning( " -cache-compile-job cannot be used without explicit module build, turn off caching " ) ,
1076
1095
location: nil )
1077
1096
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
1082
1097
} else {
1083
1098
self . enableCaching = true
1084
1099
}
1085
1100
} else {
1086
1101
self . enableCaching = false
1087
1102
}
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
+
1088
1129
self . useClangIncludeTree = !parsedOptions. hasArgument ( . noClangIncludeTree) && !env. keys. contains ( " SWIFT_CACHING_USE_CLANG_CAS_FS " )
1089
1130
self . scannerPrefixMap = try Self . computeScanningPrefixMapper ( & parsedOptions)
1090
1131
if let sdkMapping = parsedOptions. getLastArgument ( . scannerPrefixMapSdk) ? . asSingle {
@@ -3052,36 +3093,47 @@ extension Driver {
3052
3093
// Imported Objective-C header.
3053
3094
extension Driver {
3054
3095
/// Compute the path of the imported Objective-C header.
3055
- static func computeImportedObjCHeader(
3096
+ func computeImportedObjCHeader(
3056
3097
_ parsedOptions: inout ParsedOptions ,
3057
3098
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 ( )
3062
3111
}
3112
+ return originalObjCHeaderFile
3113
+ }
3063
3114
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
3067
3122
}
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)
3071
3125
}
3072
-
3073
- return try VirtualPath . intern ( path: objcHeaderPathArg. asSingle)
3126
+ return nil
3074
3127
}
3075
3128
3076
3129
/// 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 {
3085
3137
return nil
3086
3138
}
3087
3139
@@ -3096,8 +3148,8 @@ extension Driver {
3096
3148
} else {
3097
3149
pchFile = baseName. appendingFileTypeExtension ( . pch)
3098
3150
}
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 ( )
3101
3153
} else {
3102
3154
return try ? VirtualPath . temporary ( RelativePath ( validating: pchFile) ) . intern ( )
3103
3155
}
0 commit comments