diff options
Diffstat (limited to 'tests/run-make/reproducible-build')
-rw-r--r-- | tests/run-make/reproducible-build/Makefile | 140 | ||||
-rw-r--r-- | tests/run-make/reproducible-build/linker.rs | 50 | ||||
-rw-r--r-- | tests/run-make/reproducible-build/reproducible-build-aux.rs | 28 | ||||
-rw-r--r-- | tests/run-make/reproducible-build/reproducible-build.rs | 116 |
4 files changed, 334 insertions, 0 deletions
diff --git a/tests/run-make/reproducible-build/Makefile b/tests/run-make/reproducible-build/Makefile new file mode 100644 index 000000000..f5d17a234 --- /dev/null +++ b/tests/run-make/reproducible-build/Makefile @@ -0,0 +1,140 @@ +# ignore-cross-compile +include ../tools.mk + +# ignore-musl +# Objects are reproducible but their path is not. + +all: \ + smoke \ + debug \ + opt \ + link_paths \ + remap_paths \ + different_source_dirs_rlib \ + remap_cwd_rlib \ + remap_cwd_to_empty \ + extern_flags + +# TODO: Builds of `bin` crate types are not deterministic with debuginfo=2 on +# Windows. +# See: https://github.com/rust-lang/rust/pull/87320#issuecomment-920105533 +# Issue: https://github.com/rust-lang/rust/issues/88982 +# +# different_source_dirs_bin \ +# remap_cwd_bin \ + +smoke: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" + +debug: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O + $(RUSTC) reproducible-build-aux.rs -g + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -g + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -g + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" + +opt: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O + $(RUSTC) reproducible-build-aux.rs -O + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -O + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -O + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" + +link_paths: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs --crate-type rlib -L /b + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs --crate-type rlib -L /a + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 + +remap_paths: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/a=/c + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/b=/c + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 + +different_source_dirs_bin: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type bin --remap-path-prefix=$$PWD=/b + cp $(TMPDIR)/reproducible-build $(TMPDIR)/foo + (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \ + --remap-path-prefix=$(TMPDIR)/test=/b \ + --crate-type bin) + cmp "$(TMPDIR)/reproducible-build" "$(TMPDIR)/foo" || exit 1 + +different_source_dirs_rlib: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=$$PWD=/b + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \ + --remap-path-prefix=$(TMPDIR)/test=/b \ + --crate-type rlib) + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 + +remap_cwd_bin: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \ + -Z remap-cwd-prefix=. + cp $(TMPDIR)/reproducible-build $(TMPDIR)/first + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \ + -Z remap-cwd-prefix=.) + cmp "$(TMPDIR)/first" "$(TMPDIR)/reproducible-build" || exit 1 + +remap_cwd_rlib: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=. + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=.) + cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1 + +remap_cwd_to_empty: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix= + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=) + cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1 + +extern_flags: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs \ + --extern reproducible_build_aux=$(TMPDIR)/libreproducible_build_aux.rlib \ + --crate-type rlib + cp $(TMPDIR)/libreproducible_build_aux.rlib $(TMPDIR)/libbar.rlib + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs \ + --extern reproducible_build_aux=$(TMPDIR)/libbar.rlib \ + --crate-type rlib + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 diff --git a/tests/run-make/reproducible-build/linker.rs b/tests/run-make/reproducible-build/linker.rs new file mode 100644 index 000000000..3dda6f190 --- /dev/null +++ b/tests/run-make/reproducible-build/linker.rs @@ -0,0 +1,50 @@ +use std::env; +use std::path::Path; +use std::fs::File; +use std::io::{Read, Write}; + +fn main() { + let mut dst = env::current_exe().unwrap(); + dst.pop(); + dst.push("linker-arguments1"); + if dst.exists() { + dst.pop(); + dst.push("linker-arguments2"); + assert!(!dst.exists()); + } + + let mut out = String::new(); + for arg in env::args().skip(1) { + let path = Path::new(&arg); + if !path.is_file() { + out.push_str(&arg); + out.push_str("\n"); + continue + } + + let mut contents = Vec::new(); + File::open(path).unwrap().read_to_end(&mut contents).unwrap(); + + // This file is produced during linking in a temporary directory. + let arg = if arg.ends_with("/symbols.o") || arg.ends_with("\\symbols.o") { + "symbols.o" + } else { + &*arg + }; + out.push_str(&format!("{}: {}\n", arg, hash(&contents))); + } + + File::create(dst).unwrap().write_all(out.as_bytes()).unwrap(); +} + +// fnv hash for now +fn hash(contents: &[u8]) -> u64 { + let mut hash = 0xcbf29ce484222325; + + for byte in contents { + hash = hash ^ (*byte as u64); + hash = hash.wrapping_mul(0x100000001b3); + } + + hash +} diff --git a/tests/run-make/reproducible-build/reproducible-build-aux.rs b/tests/run-make/reproducible-build/reproducible-build-aux.rs new file mode 100644 index 000000000..8105b3d2b --- /dev/null +++ b/tests/run-make/reproducible-build/reproducible-build-aux.rs @@ -0,0 +1,28 @@ +#![crate_type="lib"] + +pub static STATIC: i32 = 1234; + +pub struct Struct<T1, T2> { + _t1: std::marker::PhantomData<T1>, + _t2: std::marker::PhantomData<T2>, +} + +pub fn regular_fn(_: i32) {} + +pub fn generic_fn<T1, T2>() {} + +impl<T1, T2> Drop for Struct<T1, T2> { + fn drop(&mut self) {} +} + +pub enum Enum { + Variant1, + Variant2(u32), + Variant3 { x: u32 } +} + +pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64); + +pub trait Trait<T1, T2> { + fn foo(&self); +} diff --git a/tests/run-make/reproducible-build/reproducible-build.rs b/tests/run-make/reproducible-build/reproducible-build.rs new file mode 100644 index 000000000..a6c04774c --- /dev/null +++ b/tests/run-make/reproducible-build/reproducible-build.rs @@ -0,0 +1,116 @@ +// This test case makes sure that two identical invocations of the compiler +// (i.e., same code base, same compile-flags, same compiler-versions, etc.) +// produce the same output. In the past, symbol names of monomorphized functions +// were not deterministic (which we want to avoid). +// +// The test tries to exercise as many different paths into symbol name +// generation as possible: +// +// - regular functions +// - generic functions +// - methods +// - statics +// - closures +// - enum variant constructors +// - tuple struct constructors +// - drop glue +// - FnOnce adapters +// - Trait object shims +// - Fn Pointer shims + +#![allow(dead_code, warnings)] + +extern crate reproducible_build_aux; + +static STATIC: i32 = 1234; + +pub struct Struct<T1, T2> { + x: T1, + y: T2, +} + +fn regular_fn(_: i32) {} + +fn generic_fn<T1, T2>() {} + +impl<T1, T2> Drop for Struct<T1, T2> { + fn drop(&mut self) {} +} + +pub enum Enum { + Variant1, + Variant2(u32), + Variant3 { x: u32 } +} + +struct TupleStruct(i8, i16, i32, i64); + +impl TupleStruct { + pub fn bar(&self) {} +} + +trait Trait<T1, T2> { + fn foo(&self); +} + +impl Trait<i32, u64> for u64 { + fn foo(&self) {} +} + +impl reproducible_build_aux::Trait<char, String> for TupleStruct { + fn foo(&self) {} +} + +fn main() { + regular_fn(STATIC); + generic_fn::<u32, char>(); + generic_fn::<char, Struct<u32, u64>>(); + generic_fn::<Struct<u64, u32>, reproducible_build_aux::Struct<u32, u64>>(); + + let dropped = Struct { + x: "", + y: 'a', + }; + + let _ = Enum::Variant1; + let _ = Enum::Variant2(0); + let _ = Enum::Variant3 { x: 0 }; + let _ = TupleStruct(1, 2, 3, 4); + + let closure = |x| { + x + 1i32 + }; + + fn inner<F: Fn(i32) -> i32>(f: F) -> i32 { + f(STATIC) + } + + println!("{}", inner(closure)); + + let object_shim: &Trait<i32, u64> = &0u64; + object_shim.foo(); + + fn with_fn_once_adapter<F: FnOnce(i32)>(f: F) { + f(0); + } + + with_fn_once_adapter(|_:i32| { }); + + reproducible_build_aux::regular_fn(STATIC); + reproducible_build_aux::generic_fn::<u32, char>(); + reproducible_build_aux::generic_fn::<char, Struct<u32, u64>>(); + reproducible_build_aux::generic_fn::<Struct<u64, u32>, + reproducible_build_aux::Struct<u32, u64>>(); + + let _ = reproducible_build_aux::Enum::Variant1; + let _ = reproducible_build_aux::Enum::Variant2(0); + let _ = reproducible_build_aux::Enum::Variant3 { x: 0 }; + let _ = reproducible_build_aux::TupleStruct(1, 2, 3, 4); + + let object_shim: &reproducible_build_aux::Trait<char, String> = &TupleStruct(0, 1, 2, 3); + object_shim.foo(); + + let pointer_shim: &Fn(i32) = ®ular_fn; + + TupleStruct(1, 2, 3, 4).bar(); +} |