From 224cfc8c74133a6b4fe6c9e96a90925ebaf066aa Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Sun, 26 Aug 2018 06:17:02 +0200 Subject: [PATCH] build: fix rust temp file conflicts during parallel build --- .appveyor.yml | 6 ------ build_extra/rust/get_version_hash.py | 14 ++++++++++++++ build_extra/rust/rust.gni | 23 ++++++++++++++++++++++- 3 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 build_extra/rust/get_version_hash.py diff --git a/.appveyor.yml b/.appveyor.yml index 9e37f3640e..da96eb2b3f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -306,12 +306,6 @@ before_build: Set-FilesNeeded -Auto -Path $outputs -Reason "Build dependency graph" build_script: - # Attempt to work around multiple rustc instances messing with the same file - # when building in parallel. - # TODO: fix this properly. - - ps: ninja -C $env:DENO_BUILD_PATH -j 1 - build_extra/rust:winapi build_extra/rust:winapi-0.2 - - python tools\build.py - ps: Set-FilesNeeded -Auto -Reason "Build finished" diff --git a/build_extra/rust/get_version_hash.py b/build_extra/rust/get_version_hash.py new file mode 100644 index 0000000000..7d37cbf9b3 --- /dev/null +++ b/build_extra/rust/get_version_hash.py @@ -0,0 +1,14 @@ +# Copyright 2018 the Deno authors. All rights reserved. MIT license. + +# This script computes the sha256sum of the first command line argument, and +# writes a few hex digits of it to stdout. It is used by rust.gni to derive a +# unique string (without dots/special characters) from a crate version number. + +from hashlib import sha256 +import sys + +if len(sys.argv) != 2: + raise Exception('Expected exactly one argument.') + +hash = sha256(sys.argv[1]).hexdigest() +sys.stdout.write(hash[0:8]) diff --git a/build_extra/rust/rust.gni b/build_extra/rust/rust.gni index ece21d6c01..5869539176 100644 --- a/build_extra/rust/rust.gni +++ b/build_extra/rust/rust.gni @@ -118,9 +118,30 @@ template("run_rustc") { ] if (defined(crate_version)) { + # Compute the sha256sum of the version number. See comments below. + # Note that we do this only if there are multiple versions of this crate. + hash = + exec_script("get_version_hash.py", [ crate_version ], "trim string") + args += [ + # In our build setup, all crates are built in the same directory. The + # actual build outputs have unique names (e.g. 'foo-1.2.3.rlib'), but + # rustc also creates many temp files (e.g. 'foo.crate.metadata.rcgu.bc', + # 'foo.foo0.rcgu.o'), and with those files, name collisions do occur. + # This causes random failures during parallel builds and on CI. + # + # These name conflicts can be avoided by setting `-C extra-filename=` to + # some unique value. Unfortunately the version number as such can't be + # used: everything after the first dot (.) is thrown away, so winapi-0.2 + # vs. winapi-0.3 would still have conflicts -- so we use a hash instead. "-C", - "metadata=$crate_version", + "extra-filename=$hash", + + # Rustc blows up if a target (directly or indirectly) depends on two+ + # crates that have the same name *and* the same metadata. So we use the + # hash to give 'metadata' a unique value too (any unique value will do). + "-C", + "metadata=$hash", ] }