@@ -75,6 +75,7 @@ extension Driver {
75
75
break
76
76
}
77
77
78
+ let jobNeedPathRemap : Bool
78
79
// If in ExplicitModuleBuild mode and the dependency graph has been computed, add module
79
80
// dependencies.
80
81
// May also be used for generation of the dependency graph itself in ExplicitModuleBuild mode.
@@ -83,17 +84,21 @@ extension Driver {
83
84
switch kind {
84
85
case . generatePCH:
85
86
try addExplicitPCHBuildArguments ( inputs: & inputs, commandLine: & commandLine)
87
+ jobNeedPathRemap = true
86
88
case . compile, . emitModule, . interpret, . verifyModuleInterface:
87
89
try addExplicitModuleBuildArguments ( inputs: & inputs, commandLine: & commandLine)
90
+ jobNeedPathRemap = true
88
91
case . backend, . mergeModule, . compileModuleFromInterface,
89
92
. generatePCM, . dumpPCM, . repl, . printTargetInfo,
90
93
. versionRequest, . autolinkExtract, . generateDSYM,
91
94
. help, . link, . verifyDebugInfo, . scanDependencies,
92
95
. emitSupportedFeatures, . moduleWrap,
93
96
. generateAPIBaseline, . generateABIBaseline, . compareAPIBaseline,
94
97
. compareABIBaseline:
95
- break // Do not support creating from dependency scanner output.
98
+ jobNeedPathRemap = false
96
99
}
100
+ } else {
101
+ jobNeedPathRemap = false
97
102
}
98
103
99
104
if let variant = parsedOptions. getLastArgument ( . targetVariant) ? . asSingle {
@@ -145,24 +150,22 @@ extension Driver {
145
150
try commandLine. appendLast ( . targetCpu, from: & parsedOptions)
146
151
147
152
if let sdkPath = frontendTargetInfo. sdkPath? . path {
148
- commandLine. appendFlag ( . sdk)
149
- commandLine. append ( . path( VirtualPath . lookup ( sdkPath) ) )
153
+ try addPathOption ( option: . sdk, path: VirtualPath . lookup ( sdkPath) , to: & commandLine, remap: jobNeedPathRemap)
150
154
}
151
155
152
156
for args : ( Option , Option ) in [
153
157
( . visualcToolsRoot, . visualcToolsVersion) ,
154
158
( . windowsSdkRoot, . windowsSdkVersion)
155
159
] {
156
- let ( rootArg, versionArg) = args
157
- if let value = parsedOptions. getLastArgument ( rootArg) ? . asSingle,
158
- isFrontendArgSupported ( rootArg) {
159
- commandLine. appendFlag ( rootArg. spelling)
160
- commandLine. appendPath ( try . init( validating: value) )
160
+ let ( rootOpt, versionOpt) = args
161
+ if let rootArg = parsedOptions. last ( for: rootOpt) ,
162
+ isFrontendArgSupported ( rootOpt) {
163
+ try addPathOption ( rootArg, to: & commandLine, remap: jobNeedPathRemap)
161
164
}
162
165
163
- if let value = parsedOptions. getLastArgument ( versionArg ) ? . asSingle,
164
- isFrontendArgSupported ( versionArg ) {
165
- commandLine. appendFlags ( versionArg . spelling, value)
166
+ if let value = parsedOptions. getLastArgument ( versionOpt ) ? . asSingle,
167
+ isFrontendArgSupported ( versionOpt ) {
168
+ commandLine. appendFlags ( versionOpt . spelling, value)
166
169
}
167
170
}
168
171
@@ -321,12 +324,14 @@ extension Driver {
321
324
commandLine. appendFlag ( . Xcc)
322
325
commandLine. appendFlag ( . workingDirectory)
323
326
commandLine. appendFlag ( . Xcc)
324
- commandLine . appendPath ( . absolute( workingDirectory) )
327
+ try addPathArgument ( . absolute( workingDirectory) , to : & commandLine , remap : jobNeedPathRemap )
325
328
}
326
329
327
330
// Resource directory.
328
- commandLine. appendFlag ( . resourceDir)
329
- commandLine. appendPath ( VirtualPath . lookup ( frontendTargetInfo. runtimeResourcePath. path) )
331
+ try addPathOption ( option: . resourceDir,
332
+ path: VirtualPath . lookup ( frontendTargetInfo. runtimeResourcePath. path) ,
333
+ to: & commandLine,
334
+ remap: jobNeedPathRemap)
330
335
331
336
if self . useStaticResourceDir {
332
337
commandLine. appendFlag ( " -use-static-resource-dir " )
@@ -366,6 +371,7 @@ extension Driver {
366
371
try commandLine. appendAll ( . casPluginOption, from: & parsedOptions)
367
372
try commandLine. appendLast ( . cacheRemarks, from: & parsedOptions)
368
373
}
374
+ addCacheReplayMapping ( to: & commandLine)
369
375
if useClangIncludeTree {
370
376
commandLine. appendFlag ( . clangIncludeTree)
371
377
}
@@ -388,16 +394,16 @@ extension Driver {
388
394
// of a lookup failure.
389
395
if parsedOptions. contains ( . pchOutputDir) &&
390
396
!parsedOptions. contains ( . driverExplicitModuleBuild) {
391
- commandLine . appendPath ( VirtualPath . lookup ( importedObjCHeader) )
397
+ try addPathArgument ( VirtualPath . lookup ( importedObjCHeader) , to : & commandLine , remap : jobNeedPathRemap )
392
398
try commandLine. appendLast ( . pchOutputDir, from: & parsedOptions)
393
399
if !compilerMode. isSingleCompilation {
394
400
commandLine. appendFlag ( . pchDisableValidation)
395
401
}
396
402
} else {
397
- commandLine . appendPath ( VirtualPath . lookup ( pch) )
403
+ try addPathArgument ( VirtualPath . lookup ( pch) , to : & commandLine , remap : jobNeedPathRemap )
398
404
}
399
405
} else {
400
- commandLine . appendPath ( VirtualPath . lookup ( importedObjCHeader) )
406
+ try addPathArgument ( VirtualPath . lookup ( importedObjCHeader) , to : & commandLine , remap : jobNeedPathRemap )
401
407
}
402
408
}
403
409
@@ -437,16 +443,17 @@ extension Driver {
437
443
}
438
444
}
439
445
440
- func addBridgingHeaderPCHCacheKeyArguments( commandLine: inout [ Job . ArgTemplate ] ,
441
- pchCompileJob: Job ? ) throws {
446
+ mutating func addBridgingHeaderPCHCacheKeyArguments( commandLine: inout [ Job . ArgTemplate ] ,
447
+ pchCompileJob: Job ? ) throws {
442
448
guard let pchJob = pchCompileJob, enableCaching else { return }
443
449
444
450
// The pch input file (the bridging header) is added as last inputs to the job.
445
451
guard let inputFile = pchJob. inputs. last else { assertionFailure ( " no input files from pch job " ) ; return }
446
452
assert ( inputFile. type == . objcHeader, " Expect objc header input type " )
453
+ let mappedInput = remapPath ( inputFile. file) . intern ( )
447
454
let bridgingHeaderCacheKey = try interModuleDependencyOracle. computeCacheKeyForOutput ( kind: . pch,
448
455
commandLine: pchJob. commandLine,
449
- input: inputFile . fileHandle )
456
+ input: mappedInput )
450
457
commandLine. appendFlag ( " -bridging-header-pch-key " )
451
458
commandLine. appendFlag ( bridgingHeaderCacheKey)
452
459
}
@@ -634,7 +641,7 @@ extension Driver {
634
641
var entries = [ VirtualPath . Handle: [ FileType: VirtualPath . Handle] ] ( )
635
642
for input in primaryInputs {
636
643
if let output = inputOutputMap [ input] ? . first {
637
- addEntry ( & entries, input: input, output: output)
644
+ try addEntry ( & entries, input: input, output: output)
638
645
} else {
639
646
// Primary inputs are expected to appear in the output file map even
640
647
// if they have no corresponding outputs.
@@ -653,7 +660,7 @@ extension Driver {
653
660
}
654
661
655
662
for flaggedPair in flaggedInputOutputPairs {
656
- addEntry ( & entries, input: flaggedPair. input, output: flaggedPair. output)
663
+ try addEntry ( & entries, input: flaggedPair. input, output: flaggedPair. output)
657
664
}
658
665
// To match the legacy driver behavior, make sure we add an entry for the
659
666
// file under indexing and the primary output file path.
@@ -687,14 +694,15 @@ extension Driver {
687
694
try commandLine. appendLast ( . symbolGraphMinimumAccessLevel, from: & parsedOptions)
688
695
}
689
696
690
- func addEntry( _ entries: inout [ VirtualPath . Handle : [ FileType : VirtualPath . Handle ] ] , input: TypedVirtualPath ? , output: TypedVirtualPath ) {
697
+ mutating func addEntry( _ entries: inout [ VirtualPath . Handle : [ FileType : VirtualPath . Handle ] ] , input: TypedVirtualPath ? , output: TypedVirtualPath ) throws {
691
698
let entryInput : VirtualPath . Handle
692
699
if let input = input? . fileHandle, input != OutputFileMap . singleInputKey {
693
700
entryInput = input
694
701
} else {
695
702
entryInput = inputFiles [ 0 ] . fileHandle
696
703
}
697
- entries [ entryInput, default: [ : ] ] [ output. type] = output. fileHandle
704
+ let inputEntry = enableCaching ? remapPath ( VirtualPath . lookup ( entryInput) ) . intern ( ) : entryInput
705
+ entries [ inputEntry, default: [ : ] ] [ output. type] = output. fileHandle
698
706
}
699
707
700
708
/// Adds all dependencies required for an explicit module build
@@ -731,3 +739,85 @@ extension Driver {
731
739
return job. moduleName == moduleOutputInfo. name
732
740
}
733
741
}
742
+
743
+ extension Driver {
744
+ private func getAbsolutePathFromVirtualPath( _ path: VirtualPath ) -> AbsolutePath ? {
745
+ guard let cwd = workingDirectory ?? fileSystem. currentWorkingDirectory else {
746
+ return nil
747
+ }
748
+ return path. resolvedRelativePath ( base: cwd) . absolutePath
749
+ }
750
+
751
+ private mutating func remapPath( absolute path: AbsolutePath ) -> AbsolutePath {
752
+ guard !prefixMapping. isEmpty else {
753
+ return path
754
+ }
755
+ for (prefix, value) in prefixMapping {
756
+ if path. isDescendantOfOrEqual ( to: prefix) {
757
+ return value. appending ( path. relative ( to: prefix) )
758
+ }
759
+ }
760
+ return path
761
+ }
762
+
763
+ public mutating func remapPath( _ path: VirtualPath ) -> VirtualPath {
764
+ guard !prefixMapping. isEmpty,
765
+ let absPath = getAbsolutePathFromVirtualPath ( path) else {
766
+ return path
767
+ }
768
+ let mappedPath = remapPath ( absolute: absPath)
769
+ return try ! VirtualPath ( path: mappedPath. pathString)
770
+ }
771
+
772
+ /// Helper function to add path to commandLine. Function will validate the path, and remap the path if needed.
773
+ public mutating func addPathArgument( _ path: VirtualPath , to commandLine: inout [ Job . ArgTemplate ] , remap: Bool = true ) throws {
774
+ guard remap && enableCaching else {
775
+ commandLine. appendPath ( path)
776
+ return
777
+ }
778
+ let mappedPath = remapPath ( path)
779
+ commandLine. appendPath ( mappedPath)
780
+ }
781
+
782
+ public mutating func addPathOption( _ option: ParsedOption , to commandLine: inout [ Job . ArgTemplate ] , remap: Bool = true ) throws {
783
+ let path = try VirtualPath ( path: option. argument. asSingle)
784
+ try addPathOption ( option: option. option, path: path, to: & commandLine, remap: remap)
785
+ }
786
+
787
+ public mutating func addPathOption( option: Option , path: VirtualPath , to commandLine: inout [ Job . ArgTemplate ] , remap: Bool = true ) throws {
788
+ commandLine. appendFlag ( option)
789
+ let needRemap = remap && option. attributes. contains ( . argumentIsPath) &&
790
+ !option. attributes. contains ( . cacheInvariant)
791
+ try addPathArgument ( path, to: & commandLine, remap: needRemap)
792
+ }
793
+
794
+ /// Helper function to add last argument with path to command-line.
795
+ public mutating func addLastArgumentWithPath( _ options: Option ... ,
796
+ from parsedOptions: inout ParsedOptions ,
797
+ to commandLine: inout [ Job . ArgTemplate ] ,
798
+ remap: Bool = true ) throws {
799
+ guard let parsedOption = parsedOptions. last ( for: options) else {
800
+ return
801
+ }
802
+ try addPathOption ( parsedOption, to: & commandLine, remap: remap)
803
+ }
804
+
805
+ /// Helper function to add all arguments with path to command-line.
806
+ public mutating func addAllArgumentsWithPath( _ options: Option ... ,
807
+ from parsedOptions: inout ParsedOptions ,
808
+ to commandLine: inout [ Job . ArgTemplate ] ,
809
+ remap: Bool ) throws {
810
+ for matching in parsedOptions. arguments ( for: options) {
811
+ try addPathOption ( matching, to: & commandLine, remap: remap)
812
+ }
813
+ }
814
+
815
+ public mutating func addCacheReplayMapping( to commandLine: inout [ Job . ArgTemplate ] ) {
816
+ if enableCaching && isFrontendArgSupported ( . scannerPrefixMap) {
817
+ for (key, value) in prefixMapping {
818
+ commandLine. appendFlag ( " -cache-replay-prefix-map " )
819
+ commandLine. appendFlag ( value. pathString + " = " + key. pathString)
820
+ }
821
+ }
822
+ }
823
+ }
0 commit comments