Standardizing support for path remappings - hermetic builds and indexing

To support hermetic/reproducible builds, the following flags have been added to the Swift compiler so far:

  • -debug-prefix-map - Added in PR#17665 to allow remapping paths in debug information (to make debug info reproducible). This mirrors -fdebug-prefix-map in Clang.
  • -coverage-prefix-map - Added in PR#32175 to do the same for coverage information. This mirrors -fcoverage-prefix-map in Clang.
  • -file-compilation-dir - Added in PR#40735 to allow setting the cwd for debug information (but doesn't allow remapping other paths, e.g. Xcode/toolchain paths). This mirrors -ffile-compilation-dir in Clang.

I'm currently looking to add something similar for the Index Store information - I've sent out a PR to apple/clang to add a flag to clang to allow path remappings for indexing information using the existing -fdebug-prefix-map flag (avoiding adding a new flag that would only exist in the Apple fork of Clang).

I'd like to do something similar for Swift, here are the options I can think of:

  • Reuse -debug-prefix-map just like I did in the Clang PR above
  • Introduce a new -file-prefix-map (like Clang's -ffile-prefix-map) which applies to all path remappings (and should be the preferred way for all remappings going forward - effectively deprecating but not removing the current -debug-prefix-map and -coverage-prefix-map flags while leaving -file-compilation-dir as is).
  • Introduce a new -file-prefix-map and make the existing -debug-prefix-map and -coverage-prefix-map aliases for -file-prefix-map

Any opinions/suggestions/concerns?


Is there any case where it would make sense to have a different debug/coverage mapping? If not, then I would prefer (3). It's a little weird, but we'd only be keeping the options for compatibility purposes. (2) is effectively the same, but we'd be keeping the options in the compiler, which is confusing (in my opinion) if they're supposed to always be the same.

If there is a good reason for them to be separate, I'd vote (1).

@Adrian_Prantl @Keith @akyrtzi

The only case I could think of is if some tool in the toolchain doesn't support relative paths (or remapping back to absolute paths), and therefore you want to allow some portion of the build to be non-hermetic until that's resolved. Specifically today I'm thinking where things integrate with Xcode, since externally we can't fix those cases. Coverage is actually this way now, but at Lyft we just ignore that and don't support viewing coverage in Xcode.

I think in general for folks who care about hermetic builds really what you want is a magical --hermetic flag that just "does the right thing", which likely translates to always remapping source paths to . and toolchain paths to some identifier that can be remapped back later. So I think simplifying the interface for folks by having a single flag that continues to have more things added to it as needed is highly practical.

From a clean design perspective, it's not great if an option that starts with -debug affects anything not debug info related. Maybe there should be a high-level -path-prefix-map option that the driver translates into (among other things) -debug-prefix map. But I don't have a very strong opinion on this.

And of course there's another option, add a -index-prefix-map, continuing to add a new prefix-map option for every place that can use it.

I think unless someone feels strongly the default should be to add -file-prefix-map / -path-prefix-map, that implies all the existing options, without changing the behavior of the existing options. And in the future when another case comes up for this add the behavior to this flag before trying to add yet another flag for it, which is similar to what's being done with clang at this point.

Sounds good to me. I was gonna go with -file-prefix-map to mirror Clang's -ffile-prefix-map but I'm OK with -path-prefix-map as well (we could intentionally diverge from Clang here).

1 Like

I personally would try to match clang as well, but don't feel strongly

+1 to following clang, because of consistency, and I agree with the direction it's going.