Skip to content

Commit

Permalink
Make dependency files deterministic
Browse files Browse the repository at this point in the history
The dependency file generated by Clang can sometimes contain absolute
paths to system headers, system modules and files generated by Bazel
during the build.  These paths can defer between machines and between
Bazel instances, for example:

```
bazel-out/apl-darwin_x86_64-fastbuild/bin/_objs/B/arc/B.o: B.m \
  /private/var/tmp/_bazel_user/b4422045cf7215be2d3fa4e439c7376a/sandbox/darwin-sandbox/214/execroot/__main__/bazel-out/apl-darwin_x86_64-fastbuild/bin/A.modulemap \
  /Applications/Xcode-11.6.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Foundation.framework/Modules/module.modulemap
```

This patch adds a post-process to wrapped_clang to normalize those paths
by:

* converting absolute paths to relative paths for paths to files under
the execution root
* standardizing the paths to system headers, system modules to always
use the standard location of Xcode (`/Applications/Xcode.app`).  The
user doesn't need to have Xcode installed to this location as Bazel are
already mapping them to the correct location locally.

This makes the produced `.d` files deterministic and can reliably be
shared with the remote cache.

Fixes bazelbuild#11817.
  • Loading branch information
thii committed Jul 22, 2020
1 parent 39ac64a commit fef1f83
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
6 changes: 5 additions & 1 deletion tools/osx/crosstool/cc_toolchain_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5572,7 +5572,11 @@ def _impl(ctx):
],
flag_groups = [
flag_group(
flags = ["-MD", "-MF", "%{dependency_file}"],
flags = [
"-MD",
"-MF",
"DEPENDENCY_FILE=%{dependency_file}",
],
expand_if_available = "dependency_file",
),
],
Expand Down
43 changes: 38 additions & 5 deletions tools/osx/crosstool/wrapped_clang.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@
// link action generating the dsym file.
// "DSYM_HINT_DSYM_PATH": Workspace-relative path to dSYM dwarf file.
//
// Additionally, this post-processes the output dependency file (`.d` file) to
// always use the relative paths to the execution root, and to standardize the
// system header paths to always start with
// `/Applications/Xcode.app/Contents/Developer`). This makes dependency files
// deterministic and cacheable, as the user may have Xcode installed to a
// non-standard location (e.g. `/Applications/Xcode-11.6.0.app`).
//
// Likewise, this wrapper also contains a workaround for a bug in ld that causes
// flaky builds when using Bitcode symbol maps. ld allows the
// -bitcode_symbol_map to be either a directory (into which the file will be
Expand Down Expand Up @@ -59,6 +66,7 @@ extern char **environ;
namespace {

constexpr char kAddASTPathPrefix[] = "-Wl,-add_ast_path,";
constexpr char kStandardDeveloperDir[] = "/Applications/Xcode.app/Contents/Developer";

// Returns the base name of the given filepath. For example, given
// /foo/bar/baz.txt, returns 'baz.txt'.
Expand Down Expand Up @@ -169,6 +177,25 @@ bool StripPrefixStringIfPresent(std::string *str, const std::string &prefix) {
return false;
}

// Post-processes the dependency file to convert the absolute paths to relative paths
// and normalize the system header paths to always start with the standard developer
// directory.
void PostProcessDepFile(const std::string cwd_str, const std::string developer_dir,
const std::string preprocessed_depfile,
const std::string depfile) {
if (preprocessed_depfile.empty()) {
return;
}
std::ifstream in(preprocessed_depfile);
std::ofstream out(depfile);
std::string line;
while (getline(in, line)) {
FindAndReplace(developer_dir, kStandardDeveloperDir, &line);
FindAndReplace(cwd_str, "", &line);
out << line << '\n';
}
}

} // namespace

int main(int argc, char *argv[]) {
Expand All @@ -193,6 +220,7 @@ int main(int argc, char *argv[]) {

std::string linked_binary, dsym_path, bitcode_symbol_map;
std::string dest_dir;
std::string depfile, preprocessed_depfile;

std::unique_ptr<char, decltype(std::free) *> cwd{getcwd(nullptr, 0),
std::free};
Expand All @@ -219,6 +247,10 @@ int main(int argc, char *argv[]) {
if (SetArgIfFlagPresent(arg, "DEBUG_PREFIX_MAP_PWD", &dest_dir)) {
arg = "-fdebug-prefix-map=" + std::string(cwd.get()) + "=" + dest_dir;
}
if (SetArgIfFlagPresent(arg, "DEPENDENCY_FILE", &depfile)) {
preprocessed_depfile = depfile + "_preprocessed";
arg = preprocessed_depfile;
}
if (arg.compare("OSO_PREFIX_MAP_PWD") == 0) {
arg = "-Wl,-oso_prefix," + std::string(cwd.get()) + "/";
}
Expand Down Expand Up @@ -268,14 +300,15 @@ int main(int argc, char *argv[]) {
}
}

RunSubProcess(processed_args);

std::string cwd_str = std::string(cwd.get()) + "/";
PostProcessDepFile(cwd_str, developer_dir, preprocessed_depfile, depfile);

if (!postprocess) {
ExecProcess(processed_args);
std::cerr << "ExecProcess should not return. Please fix!\n";
abort();
return 0;
}

RunSubProcess(processed_args);

std::vector<std::string> dsymutil_args = {"/usr/bin/xcrun", "dsymutil",
linked_binary, "-o", dsym_path,
"--flat"};
Expand Down

0 comments on commit fef1f83

Please sign in to comment.