aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo van der Wijst <hvanderwijst@tesla.com>2019-01-15 22:42:50 -0800
committerJorge Aparicio <jorge@japaric.io>2019-02-16 00:22:22 +0100
commit2f89688ca974944781878a74873801597c0b1f11 (patch)
treee837ee30f5ccdfaa62c83791fd4544f6f861b2f3
parentfdba26525c4a190d0275dd3b5f3a154fa189a799 (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.yml5
-rw-r--r--ci/script.sh45
-rw-r--r--macros/src/analyze.rs4
-rw-r--r--macros/src/codegen.rs14
-rw-r--r--macros/src/syntax.rs36
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>,
}