From 3906a1b5bc5e7f57925981b4dd009fc6b13de7c1 Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Thu, 1 Dec 2022 17:21:06 +0100 Subject: [PATCH] guix: reproducible builds of the GUI The GUI is using an insane MSRV so i had to patch my way through in order to be able to build some dependencies. --- contrib/guix/build.sh | 37 +- contrib/guix/guix-build.sh | 94 +++- contrib/guix/manifest.scm | 10 +- .../guix/patches/gui/iced_default_enum.patch | 459 ++++++++++++++++++ 4 files changed, 561 insertions(+), 39 deletions(-) create mode 100644 contrib/guix/patches/gui/iced_default_enum.patch diff --git a/contrib/guix/build.sh b/contrib/guix/build.sh index a3d8f396..2377693a 100755 --- a/contrib/guix/build.sh +++ b/contrib/guix/build.sh @@ -1,21 +1,34 @@ set -ex -# Guix comes with Cargo 1.52 but --config was stabilized in 1.63, so we need -# to specify unstable-options. -# We use the --config to redirect cargo toward our vendored source directory -# for our dependencies. -# TODO: build in release mode -cargo -Z unstable-options -vvv \ +# Instruct cargo to use our vendored sources +mkdir -p ~/.cargo +cat <~/.cargo/config.toml +[source.vendored_sources] +directory = "$VENDOR_DIR" + +[source.crates-io] +replace-with = "vendored_sources" + +[source."https://github.com/darosior/rust-miniscript"] +git = "https://github.com/darosior/rust-miniscript" +branch = "multipath_descriptors_on_8.0" +replace-with = "vendored_sources" + +[source."https://github.com/revault/liana"] +git = "https://github.com/revault/liana" +branch = "master" +replace-with = "vendored_sources" +EOF + +# We need to set RUSTC_BOOTSTRAP=1 as a workaround to be able to use unstable +# features in the GUI dependencies +# FIXME: GUIX_LD_WRAPPER_DISABLE_RPATH=yes +RUSTC_BOOTSTRAP=1 cargo -vvv \ --color always \ --frozen \ --offline \ rustc \ --release \ - --target-dir "$TARGET_DIR" \ - --config source.vendored_sources.directory=\""$VENDOR_DIR"\" \ - --config source.crates-io.replace-with=\"vendored_sources\" \ - --config source.\"https://github.com/darosior/rust-miniscript\".replace-with=\"vendored_sources\" \ - --config source.\"https://github.com/darosior/rust-miniscript\".git=\"https://github.com/darosior/rust-miniscript\" \ - --config source.\"https://github.com/darosior/rust-miniscript\".branch=\"multipath_descriptors_on_8.0\" + --target-dir "$TARGET_DIR" set +ex diff --git a/contrib/guix/guix-build.sh b/contrib/guix/guix-build.sh index d7325245..368a0ad8 100755 --- a/contrib/guix/guix-build.sh +++ b/contrib/guix/guix-build.sh @@ -21,15 +21,16 @@ VENDOR_DIR="$BUILD_ROOT/vendor" OUT_DIR="${OUT_DIR:-"$BUILD_ROOT/out"}" BIN_DIR="${BIN_DIR:-"$BUILD_ROOT/bin"}" -# Create the various folders if the root build directory is fresh. -for d in "$OUT_DIR" "$BIN_DIR"; do - if ! [ -d "$d" ]; then - mkdir -p "$d" +# Create the directory if it doesn't exist already +maybe_create_dir() { + if ! [ -d "$@" ]; then + mkdir -p "$@" fi -done +} +maybe_create_dir "$BIN_DIR" # That's what Guix comes with. -RUST_VERSION="1.52.0" +RUST_VERSION="1.60.0" CARGO_BIN="$BIN_DIR/cargo" # First off get the cargo binary to run on the host to vendor dependencies. @@ -37,17 +38,12 @@ CARGO_BIN="$BIN_DIR/cargo" if ! [ -f "$CARGO_BIN" ]; then ARCHIVE_PATH="$BIN_DIR/rust-for-cargo.tar.gz" curl -o "$ARCHIVE_PATH" "https://static.rust-lang.org/dist/rust-$RUST_VERSION-x86_64-unknown-linux-gnu.tar.gz" - echo "c082b5eea81206ff207407b41a10348282362dd972e93c86b054952b66ca0e2b $ARCHIVE_PATH" | $SHASUM_BIN -c + echo "b8a4c3959367d053825e31f90a5eb86418eb0d80cacda52bfa80b078e18150d5 $ARCHIVE_PATH" | $SHASUM_BIN -c # Path of the cargo binary within the archive CARGO_BIN_PATH="rust-$RUST_VERSION-x86_64-unknown-linux-gnu/cargo/bin/cargo" ( cd $BIN_DIR && tar -xzf $ARCHIVE_PATH $CARGO_BIN_PATH && mv $CARGO_BIN_PATH $CARGO_BIN ) fi -# Pull the sources of our dependencies before building them in the container. -if ! [ -d "$VENDOR_DIR" ]; then - $CARGO_BIN vendor $VENDOR_DIR -fi - # Execute "$@" in a pinned, possibly older version of Guix, for reproducibility # across time. time_machine() { @@ -59,19 +55,67 @@ time_machine() { -- "$@" } -# Bootstrap a reproducible environment as specified by the manifest in an isolated -# container, and build the project. -time_machine shell --no-cwd \ - --expose="$PWD/src=/liana/src" \ - --expose="$PWD/Cargo.toml=/liana/Cargo.toml" \ - --expose="$PWD/Cargo.lock=/liana/Cargo.lock" \ - --expose="$PWD/contrib/guix/build.sh=/liana/build.sh" \ - --expose="$VENDOR_DIR=$VENDOR_DIR" \ - --share="$OUT_DIR=$OUT_DIR" \ - --container \ - -m $PWD/contrib/guix/manifest.scm \ - -- env CC=clang VENDOR_DIR="$VENDOR_DIR" TARGET_DIR="$OUT_DIR" \ - /bin/sh -c "cd /liana && ./build.sh" +# Build both the daemon (at the root of the repository) and the GUI (in gui/) +for project_folder in "" "gui"; do + PROJECT_ROOT="$PWD/$project_folder" + PROJECT_VENDOR_DIR="$VENDOR_DIR/$project_folder" + PROJECT_OUT_DIR="$OUT_DIR/$project_folder" + PROJECT_PATCHES_ROOT="$PWD/contrib/guix/patches/$project_folder" + + project_needs_patches() { + test $(ls -A1q "$PROJECT_PATCHES_ROOT" |grep patch) + } + + maybe_create_dir "$PROJECT_OUT_DIR" + + # Pull the sources of our dependencies before building them in the container. + if ! [ -d "$PROJECT_VENDOR_DIR" ]; then + # Download the dependencies + ( cd "$project_folder" && $CARGO_BIN vendor "$PROJECT_VENDOR_DIR" ) + + # Patch some dependencies sources if needed for this project + if project_needs_patches; then + ( + cd "$PROJECT_VENDOR_DIR" + for patch_file in $(ls "$PROJECT_PATCHES_ROOT"); do + patch -p1 < "$PROJECT_PATCHES_ROOT/$patch_file" + done + ) + + # Some of the checksums will be incorrect. Instead of cherry-picking remove them + # altogether, since they aren't useful anyways (see comment below). + for dep in $(ls "$PROJECT_VENDOR_DIR"); do + echo "{\"files\":{}}" > "$PROJECT_VENDOR_DIR/$dep/.cargo-checksum.json" + done + fi + fi + + cp "$PROJECT_ROOT/Cargo.lock" "$BUILD_ROOT/Cargo.lock" + if project_needs_patches; then + # Remove the checksums from the Cargo.lock. In the container `cargo rustc` would compare + # them against the .cargo-checksum.json to make sure they weren't tampered with since they + # where vendored. But we just removed the checksums from the .cargo-checksum.json. + # There is little point in checking integrity between the above vendor step and now anyways. + # What matters is checking integrity after downloading the crates from the internet and + # `cargo vendor` does that already. + sed -i '/checksum/d' "$BUILD_ROOT/Cargo.lock" + fi + + # Bootstrap a reproducible environment as specified by the manifest in an isolated + # container, and build the project. + time_machine shell --no-cwd \ + --expose="$PROJECT_ROOT/src=/liana/src" \ + --expose="$PWD/gui/static=/liana/static" \ + --expose="$PROJECT_ROOT/Cargo.toml=/liana/Cargo.toml" \ + --expose="$BUILD_ROOT/Cargo.lock=/liana/Cargo.lock" \ + --expose="$PWD/contrib/guix/build.sh=/liana/build.sh" \ + --expose="$PROJECT_VENDOR_DIR=$PROJECT_VENDOR_DIR" \ + --share="$PROJECT_OUT_DIR=$PROJECT_OUT_DIR" \ + --container \ + -m $PWD/contrib/guix/manifest.scm \ + -- env CC=gcc VENDOR_DIR="$PROJECT_VENDOR_DIR" TARGET_DIR="$PROJECT_OUT_DIR" \ + /bin/sh -c "cd /liana && ./build.sh" +done set +ex diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index 564884a3..f3ec6b0a 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -1,5 +1,11 @@ +;; FIXME: Only pull the GUI dependencies when building it, not the daemon (specifications->manifest (list "rust" - "rust-cargo" + "rust:cargo" "coreutils" - "clang-toolchain")) + "pkg-config" ;; For the GUI + "eudev" ;; For the GUI + "cmake" ;; For the GUI + "make" ;; For the GUI + "fontconfig" ;; For the GUI + "gcc-toolchain@10.3.0")) diff --git a/contrib/guix/patches/gui/iced_default_enum.patch b/contrib/guix/patches/gui/iced_default_enum.patch new file mode 100644 index 00000000..e040e9aa --- /dev/null +++ b/contrib/guix/patches/gui/iced_default_enum.patch @@ -0,0 +1,459 @@ +commit f71bc71bf6724a1c5e2a3246dd8bd0a90fcf0e15 +Author: Antoine Poinsot +Date: Thu Dec 1 15:38:32 2022 +0100 + + Do not use, or special-case them, unstable features as of 1.60.0 + + This is in order to make the GUI MSRV effectively 1.60.0. + + Default derivation on enums is removed. + + Usage of bool_to_option is removed. + + Generic associated types is unfortunately special cased as enabled. This + forces use to set RUSTC_BOOTSTRAP=1 in the Guix container... + +diff --git a/iced_glow/src/lib.rs b/iced_glow/src/lib.rs +index e3690a69..b5b9cc38 100644 +--- a/iced_glow/src/lib.rs ++++ b/iced_glow/src/lib.rs +@@ -20,6 +20,7 @@ + #![forbid(rust_2018_idioms)] + #![allow(clippy::inherent_to_string, clippy::type_complexity)] + #![cfg_attr(docsrs, feature(doc_cfg))] ++#![feature(generic_associated_types)] + + pub use glow; + +diff --git a/iced_graphics/src/lib.rs b/iced_graphics/src/lib.rs +index d39dd90c..876b478f 100644 +--- a/iced_graphics/src/lib.rs ++++ b/iced_graphics/src/lib.rs +@@ -21,6 +21,7 @@ + #![forbid(rust_2018_idioms)] + #![allow(clippy::inherent_to_string, clippy::type_complexity)] + #![cfg_attr(docsrs, feature(doc_cfg))] ++#![feature(generic_associated_types)] + mod antialiasing; + mod error; + mod primitive; +diff --git a/iced_native/src/program/state.rs b/iced_native/src/program/state.rs +index 8ae1cacb..25a3028b 100644 +--- a/iced_native/src/program/state.rs ++++ b/iced_native/src/program/state.rs +@@ -120,7 +120,11 @@ where + .iter() + .zip(event_statuses) + .filter_map(|(event, status)| { +- matches!(status, event::Status::Ignored).then_some(event) ++ if matches!(status, event::Status::Ignored) { ++ Some(event) ++ } else { ++ None ++ } + }) + .cloned() + .collect(); +diff --git a/iced_style/src/theme.rs b/iced_style/src/theme.rs +index d7ebb827..224a04fc 100644 +--- a/iced_style/src/theme.rs ++++ b/iced_style/src/theme.rs +@@ -25,10 +25,9 @@ use iced_core::{Background, Color, Vector}; + use std::rc::Rc; + + /// A built-in theme. +-#[derive(Debug, Clone, PartialEq, Default)] ++#[derive(Debug, Clone, PartialEq)] + pub enum Theme { + /// The built-in light variant. +- #[default] + Light, + /// The built-in dark variant. + Dark, +@@ -61,6 +60,12 @@ impl Theme { + } + } + ++impl Default for Theme { ++ fn default() -> Self { ++ Self::Light ++ } ++} ++ + /// A [`Theme`] with a customized [`Palette`]. + #[derive(Debug, Clone, Copy, PartialEq)] + pub struct Custom { +@@ -79,15 +84,19 @@ impl Custom { + } + + /// The style of an application. +-#[derive(Default)] + pub enum Application { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Box>), + } + ++impl Default for Application { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl application::StyleSheet for Theme { + type Style = Application; + +@@ -119,10 +128,11 @@ impl From application::Appearance> for Application { + } + + /// The style of a button. +-#[derive(Default)] ++/* ++ * Button ++ */ + pub enum Button { + /// The primary style. +- #[default] + Primary, + /// The secondary style. + Secondary, +@@ -138,6 +148,12 @@ pub enum Button { + Custom(Box>), + } + ++impl Default for Button { ++ fn default() -> Self { ++ Self::Primary ++ } ++} ++ + impl button::StyleSheet for Theme { + type Style = Button; + +@@ -227,10 +243,11 @@ impl button::StyleSheet for Theme { + } + + /// The style of a checkbox. +-#[derive(Default)] ++/* ++ * Checkbox ++ */ + pub enum Checkbox { + /// The primary style. +- #[default] + Primary, + /// The secondary style. + Secondary, +@@ -242,6 +259,12 @@ pub enum Checkbox { + Custom(Box>), + } + ++impl Default for Checkbox { ++ fn default() -> Self { ++ Self::Primary ++ } ++} ++ + impl checkbox::StyleSheet for Theme { + type Style = Checkbox; + +@@ -339,10 +362,11 @@ fn checkbox_appearance( + } + + /// The style of a container. +-#[derive(Default)] ++/* ++ * Container ++ */ + pub enum Container { + /// No style. +- #[default] + Transparent, + /// A simple box. + Box, +@@ -350,6 +374,12 @@ pub enum Container { + Custom(Box>), + } + ++impl Default for Container { ++ fn default() -> Self { ++ Self::Transparent ++ } ++} ++ + impl From container::Appearance> for Container { + fn from(f: fn(&Theme) -> container::Appearance) -> Self { + Self::Custom(Box::new(f)) +@@ -387,15 +417,19 @@ impl container::StyleSheet for fn(&Theme) -> container::Appearance { + } + + /// The style of a slider. +-#[derive(Default)] + pub enum Slider { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Box>), + } + ++impl Default for Slider { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl slider::StyleSheet for Theme { + type Style = Slider; + +@@ -468,15 +502,20 @@ impl slider::StyleSheet for Theme { + } + + /// The style of a menu. +-#[derive(Clone, Default)] ++#[derive(Clone)] + pub enum Menu { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Rc>), + } + ++impl Default for Menu { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl menu::StyleSheet for Theme { + type Style = Menu; + +@@ -510,10 +549,9 @@ impl From for Menu { + } + + /// The style of a pick list. +-#[derive(Clone, Default)] ++#[derive(Clone)] + pub enum PickList { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom( +@@ -522,6 +560,12 @@ pub enum PickList { + ), + } + ++impl Default for PickList { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl pick_list::StyleSheet for Theme { + type Style = PickList; + +@@ -565,15 +609,19 @@ impl pick_list::StyleSheet for Theme { + } + + /// The style of a radio button. +-#[derive(Default)] + pub enum Radio { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Box>), + } + ++impl Default for Radio { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl radio::StyleSheet for Theme { + type Style = Radio; + +@@ -620,15 +668,19 @@ impl radio::StyleSheet for Theme { + } + + /// The style of a toggler. +-#[derive(Default)] + pub enum Toggler { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Box>), + } + ++impl Default for Toggler { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl toggler::StyleSheet for Theme { + type Style = Toggler; + +@@ -687,15 +739,19 @@ impl toggler::StyleSheet for Theme { + } + + /// The style of a pane grid. +-#[derive(Default)] + pub enum PaneGrid { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Box>), + } + ++impl Default for PaneGrid { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl pane_grid::StyleSheet for Theme { + type Style = PaneGrid; + +@@ -729,10 +785,11 @@ impl pane_grid::StyleSheet for Theme { + } + + /// The style of a progress bar. +-#[derive(Default)] ++/* ++ * Progress Bar ++ */ + pub enum ProgressBar { + /// The primary style. +- #[default] + Primary, + /// The success style. + Success, +@@ -742,6 +799,12 @@ pub enum ProgressBar { + Custom(Box>), + } + ++impl Default for ProgressBar { ++ fn default() -> Self { ++ Self::Primary ++ } ++} ++ + impl From progress_bar::Appearance> for ProgressBar { + fn from(f: fn(&Theme) -> progress_bar::Appearance) -> Self { + Self::Custom(Box::new(f)) +@@ -782,15 +845,22 @@ impl progress_bar::StyleSheet for fn(&Theme) -> progress_bar::Appearance { + } + + /// The style of a rule. +-#[derive(Default)] ++/* ++ * Rule ++ */ + pub enum Rule { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Box>), + } + ++impl Default for Rule { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl From rule::Appearance> for Rule { + fn from(f: fn(&Theme) -> rule::Appearance) -> Self { + Self::Custom(Box::new(f)) +@@ -824,15 +894,19 @@ impl rule::StyleSheet for fn(&Theme) -> rule::Appearance { + } + + /// The style of a scrollable. +-#[derive(Default)] + pub enum Scrollable { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Box>), + } + ++impl Default for Scrollable { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl scrollable::StyleSheet for Theme { + type Style = Scrollable; + +@@ -889,15 +963,23 @@ impl scrollable::StyleSheet for Theme { + } + + /// The style of text. +-#[derive(Clone, Copy, Default)] ++/* ++ * Text ++ */ ++#[derive(Clone, Copy)] + pub enum Text { + /// The default style. +- #[default] + Default, + /// Colored text. + Color(Color), + } + ++impl Default for Text { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl From for Text { + fn from(color: Color) -> Self { + Text::Color(color) +@@ -916,15 +998,19 @@ impl text::StyleSheet for Theme { + } + + /// The style of a text input. +-#[derive(Default)] + pub enum TextInput { + /// The default style. +- #[default] + Default, + /// A custom style. + Custom(Box>), + } + ++impl Default for TextInput { ++ fn default() -> Self { ++ Self::Default ++ } ++} ++ + impl text_input::StyleSheet for Theme { + type Style = TextInput; + +diff --git a/iced_wgpu/src/lib.rs b/iced_wgpu/src/lib.rs +index dcb699e8..5b3cda57 100644 +--- a/iced_wgpu/src/lib.rs ++++ b/iced_wgpu/src/lib.rs +@@ -37,6 +37,7 @@ + #![forbid(rust_2018_idioms)] + #![allow(clippy::inherent_to_string, clippy::type_complexity)] + #![cfg_attr(docsrs, feature(doc_cfg))] ++#![feature(generic_associated_types)] + + pub mod settings; + pub mod triangle; +