diff options
| author | Hugo van der Wijst <hvanderwijst@tesla.com> | 2019-01-15 22:42:50 -0800 |
|---|---|---|
| committer | Jorge Aparicio <jorge@japaric.io> | 2019-02-16 00:22:22 +0100 |
| commit | 2f89688ca974944781878a74873801597c0b1f11 (patch) | |
| tree | e837ee30f5ccdfaa62c83791fd4544f6f861b2f3 | |
| parent | fdba26525c4a190d0275dd3b5f3a154fa189a799 (diff) | |
Make builds reproducible
This is done by using `BTreeMap`s and `BTreeSet`s to get deterministic
ordering.
Also updated the CI job to check reproducibility of all examples.
| -rw-r--r-- | .travis.yml | 5 | ||||
| -rw-r--r-- | ci/script.sh | 45 | ||||
| -rw-r--r-- | macros/src/analyze.rs | 4 | ||||
| -rw-r--r-- | macros/src/codegen.rs | 14 | ||||
| -rw-r--r-- | macros/src/syntax.rs | 36 |
5 files changed, 66 insertions, 38 deletions
diff --git a/.travis.yml b/.travis.yml index 481f8fe..31d10e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,10 @@ matrix: rust: nightly if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master) -before_install: set -e +before_install: + - set -e + - sudo apt-get update + - sudo apt-get install -y binutils-arm-none-eabi install: - bash ci/install.sh diff --git a/ci/script.sh b/ci/script.sh index 645db3a..ab7f34b 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -81,20 +81,45 @@ main() { continue fi - if [ $ex != types ]; then - cargo run --example $ex --target $T | \ - diff -u ci/expected/$ex.run - + test_arm_example() { + local EXAMPLE=$1 + local TARGET=$2 + local BUILD_MODE=$3 + local FEATURES=$4 + + if [ $BUILD_MODE = "release" ]; then + local RELEASE_FLAG="--release" + else + local RELEASE_FLAG="" + fi + + if [ -n "$FEATURES" ]; then + local FEATURES_FLAG="--features $FEATURES" + else + local FEATURES_FLAG="" + fi + local CARGO_FLAGS="--example $EXAMPLE --target $TARGET $RELEASE_FLAG $FEATURES_FLAG" + + cargo run $CARGO_FLAGS | diff -u ci/expected/$EXAMPLE.run - + arm-none-eabi-objcopy -O ihex target/$TARGET/$BUILD_MODE/examples/$EXAMPLE ${EXAMPLE}_1.hex + + # build again to ensure that the build is reproducable + cargo clean + cargo build $CARGO_FLAGS + arm-none-eabi-objcopy -O ihex target/$TARGET/$BUILD_MODE/examples/$EXAMPLE ${EXAMPLE}_2.hex + + # compare results of both builds + cmp ${EXAMPLE}_1.hex ${EXAMPLE}_2.hex + } - cargo run --example $ex --target $T --release | \ - diff -u ci/expected/$ex.run - + if [ $ex != types ]; then + test_arm_example $ex $T "debug" "" + test_arm_example $ex $T "release" "" fi if [ $TARGET != thumbv6m-none-eabi ]; then - cargo run --features timer-queue --example $ex --target $T | \ - diff -u ci/expected/$ex.run - - - cargo run --features timer-queue --example $ex --target $T --release | \ - diff -u ci/expected/$ex.run - + test_arm_example $ex $T "debug" "timer-queue" + test_arm_example $ex $T "release" "timer-queue" fi done esac diff --git a/macros/src/analyze.rs b/macros/src/analyze.rs index 19575b7..cfd8ebc 100644 --- a/macros/src/analyze.rs +++ b/macros/src/analyze.rs @@ -1,6 +1,6 @@ use std::{ cmp, - collections::{HashMap, HashSet}, + collections::{BTreeMap, HashMap, HashSet}, }; use syn::{Attribute, Ident, Type}; @@ -65,7 +65,7 @@ pub struct Dispatcher { } /// Priority -> Dispatcher -pub type Dispatchers = HashMap<u8, Dispatcher>; +pub type Dispatchers = BTreeMap<u8, Dispatcher>; pub type Capacities = HashMap<Ident, u8>; diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index af3def6..a96eaef 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -2,7 +2,7 @@ use proc_macro::TokenStream; use std::{ - collections::HashMap, + collections::{BTreeMap, HashMap}, sync::atomic::{AtomicUsize, Ordering}, time::{SystemTime, UNIX_EPOCH}, }; @@ -20,13 +20,13 @@ use crate::{ // NOTE to avoid polluting the user namespaces we map some identifiers to pseudo-hygienic names. // In some instances we also use the pseudo-hygienic names for safety, for example the user should // not modify the priority field of resources. -type Aliases = HashMap<Ident, Ident>; +type Aliases = BTreeMap<Ident, Ident>; struct Context { // Alias #[cfg(feature = "timer-queue")] baseline: Ident, - dispatchers: HashMap<u8, Dispatcher>, + dispatchers: BTreeMap<u8, Dispatcher>, // Alias (`fn`) idle: Ident, // Alias (`fn`) @@ -41,7 +41,7 @@ struct Context { schedule_enum: Ident, // Task -> Alias (`fn`) schedule_fn: Aliases, - tasks: HashMap<Ident, Task>, + tasks: BTreeMap<Ident, Task>, // Alias (`struct` / `static mut`) timer_queue: Ident, } @@ -66,7 +66,7 @@ impl Default for Context { Context { #[cfg(feature = "timer-queue")] baseline: mk_ident(None), - dispatchers: HashMap::new(), + dispatchers: BTreeMap::new(), idle: mk_ident(Some("idle")), init: mk_ident(Some("init")), priority: mk_ident(None), @@ -74,7 +74,7 @@ impl Default for Context { resources: HashMap::new(), schedule_enum: mk_ident(None), schedule_fn: Aliases::new(), - tasks: HashMap::new(), + tasks: BTreeMap::new(), timer_queue: mk_ident(None), } } @@ -2034,7 +2034,7 @@ fn mk_ident(name: Option<&str>) -> Ident { } // `once = true` means that these locals will be called from a function that will run *once* -fn mk_locals(locals: &HashMap<Ident, Static>, once: bool) -> proc_macro2::TokenStream { +fn mk_locals(locals: &BTreeMap<Ident, Static>, once: bool) -> proc_macro2::TokenStream { let lt = if once { Some(quote!('static)) } else { None }; let locals = locals diff --git a/macros/src/syntax.rs b/macros/src/syntax.rs index ad7d8bd..581eb83 100644 --- a/macros/src/syntax.rs +++ b/macros/src/syntax.rs @@ -1,5 +1,5 @@ use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeMap, BTreeSet}, iter, u8, }; @@ -120,10 +120,10 @@ impl App { pub fn parse(items: Vec<Item>, args: AppArgs) -> parse::Result<Self> { let mut idle = None; let mut init = None; - let mut exceptions = HashMap::new(); - let mut interrupts = HashMap::new(); - let mut resources = HashMap::new(); - let mut tasks = HashMap::new(); + let mut exceptions = BTreeMap::new(); + let mut interrupts = BTreeMap::new(); + let mut resources = BTreeMap::new(); + let mut tasks = BTreeMap::new(); let mut free_interrupts = None; for item in items { @@ -418,25 +418,25 @@ impl App { } } -pub type Idents = HashSet<Ident>; +pub type Idents = BTreeSet<Ident>; -pub type Exceptions = HashMap<Ident, Exception>; +pub type Exceptions = BTreeMap<Ident, Exception>; -pub type Interrupts = HashMap<Ident, Interrupt>; +pub type Interrupts = BTreeMap<Ident, Interrupt>; -pub type Resources = HashMap<Ident, Resource>; +pub type Resources = BTreeMap<Ident, Resource>; pub type Statics = Vec<ItemStatic>; -pub type Tasks = HashMap<Ident, Task>; +pub type Tasks = BTreeMap<Ident, Task>; -pub type FreeInterrupts = HashMap<Ident, FreeInterrupt>; +pub type FreeInterrupts = BTreeMap<Ident, FreeInterrupt>; pub struct Idle { pub args: IdleArgs, pub attrs: Vec<Attribute>, pub unsafety: Option<Token![unsafe]>, - pub statics: HashMap<Ident, Static>, + pub statics: BTreeMap<Ident, Static>, pub stmts: Vec<Stmt>, } @@ -607,7 +607,7 @@ pub struct Init { pub args: InitArgs, pub attrs: Vec<Attribute>, pub unsafety: Option<Token![unsafe]>, - pub statics: HashMap<Ident, Static>, + pub statics: BTreeMap<Ident, Static>, pub stmts: Vec<Stmt>, // TODO remove in v0.5.x pub assigns: Vec<Assign>, @@ -703,7 +703,7 @@ pub struct Exception { pub args: ExceptionArgs, pub attrs: Vec<Attribute>, pub unsafety: Option<Token![unsafe]>, - pub statics: HashMap<Ident, Static>, + pub statics: BTreeMap<Ident, Static>, pub stmts: Vec<Stmt>, } @@ -791,7 +791,7 @@ pub struct Interrupt { pub args: InterruptArgs, pub attrs: Vec<Attribute>, pub unsafety: Option<Token![unsafe]>, - pub statics: HashMap<Ident, Static>, + pub statics: BTreeMap<Ident, Static>, pub stmts: Vec<Stmt>, } @@ -1070,8 +1070,8 @@ pub struct Static { } impl Static { - fn parse(items: Vec<ItemStatic>) -> parse::Result<HashMap<Ident, Static>> { - let mut statics = HashMap::new(); + fn parse(items: Vec<ItemStatic>) -> parse::Result<BTreeMap<Ident, Static>> { + let mut statics = BTreeMap::new(); for item in items { if statics.contains_key(&item.ident) { @@ -1104,7 +1104,7 @@ pub struct Task { pub attrs: Vec<Attribute>, pub unsafety: Option<Token![unsafe]>, pub inputs: Vec<ArgCaptured>, - pub statics: HashMap<Ident, Static>, + pub statics: BTreeMap<Ident, Static>, pub stmts: Vec<Stmt>, } |
