summaryrefslogtreecommitdiffstats
path: root/tests/run-make/reproducible-build
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run-make/reproducible-build')
-rw-r--r--tests/run-make/reproducible-build/Makefile140
-rw-r--r--tests/run-make/reproducible-build/linker.rs50
-rw-r--r--tests/run-make/reproducible-build/reproducible-build-aux.rs28
-rw-r--r--tests/run-make/reproducible-build/reproducible-build.rs116
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) = &regular_fn;
+
+ TupleStruct(1, 2, 3, 4).bar();
+}