Merge #140: Bootstrappable builds
ef20b782301bae2fdfb842dfd89a749e60cb449e guix: make the builds actually reproducible (Antoine Poinsot) 72a332d2caf6c139d20855203d107fe3b185ba7d guix: fix the dependencies listing for the GUI container (Antoine Poinsot) 4a38040acf12dd457ac5f29a24f4b3800114255c guix: documentation (Antoine Poinsot) 37a28dbf7d5a22426d1844ef792d04e604e5b91b guix: use a lighter environment for building the daemon (Antoine Poinsot) ae0b24f97494a7a859578ab6191187c4405a225f guix: allow to limit the number of cores dedicated to the build (Antoine Poinsot) 940c28d072c449295f6e1225446b829bea2d3053 guix: use patchelf to strip interpreter and RPATH (Antoine Poinsot) 3906a1b5bc5e7f57925981b4dd009fc6b13de7c1 guix: reproducible builds of the GUI (Antoine Poinsot) 8dda896e4b2c4baa69b5e1b839bfaf47b9b36320 guix: Linux reproducible builds of the daemon (Antoine Poinsot) Pull request description: This introduces reproducible and bootstrappable builds of our softwares by using [Guix](https://guix.gnu.org/). This is heavily inspired by the work on Guix [that was done in the Bitcoin Core project](https://github.com/bitcoin/bitcoin/tree/master/contrib/guix). For an intro to reproducible builds with Guix see [this post](https://guix.gnu.org/blog/2020/reproducible-computations-with-guix/). For details, see the documentation introduced in this PR. Apologies for the poor commit history. ACKs for top commit: darosior: ACK ef20b782301bae2fdfb842dfd89a749e60cb449e Tree-SHA512: 58800170a8fd0822129f1fefa23c8a8cb68e8758a56b3ea9933b41cff1eff7691ed735a28f156395b76c18447044f2ba5a3f4cd519696667b6df90e27e20d3f6
This commit is contained in:
commit
f9359869f7
@ -56,6 +56,3 @@ libc = "0.2"
|
||||
|
||||
# Used for PSBTs
|
||||
base64 = "0.13"
|
||||
|
||||
[patch.crates-io]
|
||||
|
||||
|
||||
176
contrib/guix/README.md
Normal file
176
contrib/guix/README.md
Normal file
@ -0,0 +1,176 @@
|
||||
## Bootstrappable Liana builds
|
||||
|
||||
This repository contains the scripts to perform [reproducible](https://reproducible-builds.org/) and
|
||||
[bootstrappable](https://bootstrappable.org/) builds of Liana using [Guix](https://guix.gnu.org/), a
|
||||
functional package manager.
|
||||
|
||||
For a short high-level introduction to the purpose of bootstrappable builds, see [this
|
||||
talk](https://www.youtube.com/watch?v=I2iShmUTEl8) by Carl Dong in the context of the Bitcoin Core
|
||||
project.
|
||||
|
||||
For now, only `x86_64` Linux binaries are supported. We aim to extend bootstrappable builds to more
|
||||
targets in the future.
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
See the very [detailed document about GUIX installation in the Bitcoin Core
|
||||
project](https://github.com/bitcoin/bitcoin/blob/master/contrib/guix/INSTALL.md). Almost all of it
|
||||
is directly applicable to Liana as well.
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
First of all, you need to decide on the amount of trust in the building process. Of course this
|
||||
decision needs to fall within a broader threat model, but it is still interesting to consider.
|
||||
|
||||
*(Note: this section was taken from the Bitcoin Core documentation and initially written by Carl
|
||||
Dong.)*
|
||||
|
||||
#### Choosing your security model
|
||||
|
||||
No matter how you installed Guix, you need to decide on your security model for
|
||||
building packages with Guix.
|
||||
|
||||
Guix allows us to achieve better binary security by using our CPU time to build
|
||||
everything from scratch. However, it doesn't sacrifice user choice in pursuit of
|
||||
this: users can decide whether or not to use **substitutes** (pre-built
|
||||
packages).
|
||||
|
||||
##### Option 1: Building with substitutes
|
||||
|
||||
###### Step 1: Authorize the signing keys
|
||||
|
||||
Depending on the installation procedure you followed, you may have already
|
||||
authorized the Guix build farm key. In particular, the official shell installer
|
||||
script asks you if you want the key installed, and the debian distribution
|
||||
package authorized the key during installation.
|
||||
|
||||
You can check the current list of authorized keys at `/etc/guix/acl`.
|
||||
|
||||
At the time of writing, a `/etc/guix/acl` with just the Guix build farm key
|
||||
authorized looks something like:
|
||||
|
||||
```lisp
|
||||
(acl
|
||||
(entry
|
||||
(public-key
|
||||
(ecc
|
||||
(curve Ed25519)
|
||||
(q #8D156F295D24B0D9A86FA5741A840FF2D24F60F7B6C4134814AD55625971B394#)
|
||||
)
|
||||
)
|
||||
(tag
|
||||
(guix import)
|
||||
)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
If you've determined that the official Guix build farm key hasn't been
|
||||
authorized, and you would like to authorize it, run the following as root:
|
||||
|
||||
```
|
||||
guix archive --authorize < /var/guix/profiles/per-user/root/current-guix/share/guix/ci.guix.gnu.org.pub
|
||||
```
|
||||
|
||||
If
|
||||
`/var/guix/profiles/per-user/root/current-guix/share/guix/ci.guix.gnu.org.pub`
|
||||
doesn't exist, try:
|
||||
|
||||
```sh
|
||||
guix archive --authorize < <PREFIX>/share/guix/ci.guix.gnu.org.pub
|
||||
```
|
||||
|
||||
Where `<PREFIX>` is likely:
|
||||
- `/usr` if you installed from a distribution package
|
||||
- `/usr/local` if you installed Guix from source and didn't supply any
|
||||
prefix-modifying flags to Guix's `./configure`
|
||||
|
||||
For dongcarl's substitute server at https://guix.carldong.io, run as root:
|
||||
|
||||
```sh
|
||||
wget -qO- 'https://guix.carldong.io/signing-key.pub' | guix archive --authorize
|
||||
```
|
||||
|
||||
To remove previously authorized keys, simply edit `/etc/guix/acl` and remove the
|
||||
`(entry (public-key ...))` entry.
|
||||
|
||||
###### Step 2: Specify the substitute servers
|
||||
|
||||
Once its key is authorized, the official Guix build farm at
|
||||
https://ci.guix.gnu.org is automatically used unless the `--no-substitutes` flag
|
||||
is supplied. This default list of substitute servers is overridable both on a
|
||||
`guix-daemon` level and when you invoke `guix` commands. See examples below for
|
||||
the various ways of adding dongcarl's substitute server after having [authorized
|
||||
his signing key](#step-1-authorize-the-signing-keys).
|
||||
|
||||
Change the **default list** of substitute servers by starting `guix-daemon` with
|
||||
the `--substitute-urls` option (you will likely need to edit your init script):
|
||||
|
||||
```sh
|
||||
guix-daemon <cmd> --substitute-urls='https://guix.carldong.io https://ci.guix.gnu.org'
|
||||
```
|
||||
|
||||
Override the default list of substitute servers by passing the
|
||||
`--substitute-urls` option for invocations of `guix` commands:
|
||||
|
||||
```sh
|
||||
guix <cmd> --substitute-urls='https://guix.carldong.io https://ci.guix.gnu.org'
|
||||
```
|
||||
|
||||
For scripts under `./contrib/guix`, set the `SUBSTITUTE_URLS` environment
|
||||
variable:
|
||||
|
||||
```sh
|
||||
export SUBSTITUTE_URLS='https://guix.carldong.io https://ci.guix.gnu.org'
|
||||
```
|
||||
|
||||
##### Option 2: Disabling substitutes on an ad-hoc basis
|
||||
|
||||
If you prefer not to use any substitutes, make sure to supply `--no-substitutes`
|
||||
like in the following snippet. The first build will take a while, but the
|
||||
resulting packages will be cached for future builds.
|
||||
|
||||
For direct invocations of `guix`:
|
||||
```sh
|
||||
guix <cmd> --no-substitutes
|
||||
```
|
||||
|
||||
The build script doesn't yet allow you to provide this via an environment variable, you'd
|
||||
have to modify it yourself (or contribute a patch :p).
|
||||
|
||||
##### Option 3: Disabling substitutes by default
|
||||
|
||||
`guix-daemon` accepts a `--no-substitutes` flag, which will make sure that,
|
||||
unless otherwise overridden by a command line invocation, no substitutes will be
|
||||
used.
|
||||
|
||||
If you start `guix-daemon` using an init script, you can edit said script to
|
||||
supply this flag.
|
||||
|
||||
|
||||
#### Building Liana
|
||||
|
||||
For both the daemon (`lianad`) and the GUI (`liana-gui`), the [`guix-build.sh`](./guix-build.sh)
|
||||
script will vendor the dependencies of the project (as pinned in the `Cargo.lock`) and start a [GUIX
|
||||
container](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-shell.html) that will run
|
||||
the `build.sh` script that will take care of building the dependencies and the project using `cargo`.
|
||||
|
||||
To start a build, simply run the `guix-build.sh` script from the root of the repository:
|
||||
```
|
||||
$ ./contrib/guix/guix-build.sh
|
||||
```
|
||||
|
||||
The script shouldn't contain any bash-ism, so it should work with other shells as well.
|
||||
|
||||
|
||||
#### Customization
|
||||
|
||||
Environment variables are available to configure the build.
|
||||
|
||||
`BUILD_ROOT` allows you to specify the root folder that will contain the vendored dependencies'
|
||||
source, the build cache as well as the resulting binaries (in `$BUILD_ROOT/out`).
|
||||
|
||||
`JOBS` allows you to specify the number of cores to dedicate to the build both for bootstrapping the
|
||||
toolchain with GUIX and building the project using `cargo`.
|
||||
45
contrib/guix/build.sh
Executable file
45
contrib/guix/build.sh
Executable file
@ -0,0 +1,45 @@
|
||||
# ==========================================================================
|
||||
# The script ran within the GUIX container to build the Liana daemon or GUI.
|
||||
# ==========================================================================
|
||||
|
||||
set -ex
|
||||
|
||||
# Instruct cargo to use our vendored sources
|
||||
mkdir -p ~/.cargo
|
||||
cat <<EOF >~/.cargo/config.toml
|
||||
[source.vendored_sources]
|
||||
directory = "/vendor"
|
||||
|
||||
[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
|
||||
RUSTC_BOOTSTRAP=1 cargo -vvv \
|
||||
--color always \
|
||||
--frozen \
|
||||
--offline \
|
||||
rustc \
|
||||
--jobs "$JOBS" \
|
||||
--release \
|
||||
--target-dir "/out"
|
||||
|
||||
# Assume 64bits. Even bitcoind doesn't ship 32bits binaries for x86.
|
||||
# FIXME: is there a cleaner way than using patchelf for this?
|
||||
patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 "/out/release/$BINARY_NAME"
|
||||
|
||||
# FIXME: Find a way to use GUIX_LD_WRAPPER_DISABLE_RPATH=yes instead
|
||||
patchelf --remove-rpath "/out/release/$BINARY_NAME"
|
||||
|
||||
set +ex
|
||||
140
contrib/guix/guix-build.sh
Executable file
140
contrib/guix/guix-build.sh
Executable file
@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -ex
|
||||
|
||||
# How many cores to allocate to Guix building.
|
||||
JOBS="${JOBS:-$(nproc)}"
|
||||
|
||||
# The binary to check the hash of downloaded archives.
|
||||
SHASUM_BIN="${SHASUM_BIN:-sha256sum}"
|
||||
|
||||
# We do everything in a single directory. That's the root of it, configurable
|
||||
# through the environment.
|
||||
BUILD_ROOT="${BUILD_ROOT:-$(mktemp -d)}"
|
||||
|
||||
# Various folders we expose to the container. The vendor directory will contain
|
||||
# the sources of all our dependencies. Because we restrict network access from
|
||||
# within the container, this is pulled beforehand.
|
||||
# The out directory will contain the resulting binaries. It's wired to the --target-dir
|
||||
# for a cargo build.
|
||||
VENDOR_DIR="$BUILD_ROOT/vendor"
|
||||
OUT_DIR="${OUT_DIR:-"$BUILD_ROOT/out"}"
|
||||
BIN_DIR="${BIN_DIR:-"$BUILD_ROOT/bin"}"
|
||||
|
||||
# Create the directory if it doesn't exist already
|
||||
maybe_create_dir() {
|
||||
if ! [ -d "$@" ]; then
|
||||
mkdir -p "$@"
|
||||
fi
|
||||
}
|
||||
maybe_create_dir "$BIN_DIR"
|
||||
|
||||
# That's what Guix comes with.
|
||||
RUST_VERSION="1.60.0"
|
||||
CARGO_BIN="$BIN_DIR/cargo"
|
||||
|
||||
# First off get the cargo binary to run on the host to vendor dependencies.
|
||||
# We assume the host is a 64bit Linux system.
|
||||
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 "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
|
||||
|
||||
# Execute "$@" in a pinned, possibly older version of Guix, for reproducibility
|
||||
# across time.
|
||||
time_machine() {
|
||||
guix time-machine --url=https://git.savannah.gnu.org/git/guix.git \
|
||||
--commit=059d38dc3f8b087f4a42df586daeb05761ee18d7 \
|
||||
--cores="$JOBS" \
|
||||
--keep-failed \
|
||||
--fallback \
|
||||
-- "$@"
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
# FIXME: find a cleaner way to get the binary name, or get rid of patchelf entirely
|
||||
# Note: we also rely on it in manifest.scm
|
||||
if [ "$project_folder" = "" ]; then
|
||||
BINARY_NAME="lianad"
|
||||
elif [ "$project_folder" = "gui" ]; then
|
||||
BINARY_NAME="liana-gui"
|
||||
else
|
||||
echo "Can't determine binary name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Bootstrap a reproducible environment as specified by the manifest in an isolated
|
||||
# container, and build the project.
|
||||
# NOTE: it looks like "--rebuild-cache" is necessary for the BINARY_NAME variable to
|
||||
# be taken into account when building the container (otherwise the GUI container could
|
||||
# miss some dependencies).
|
||||
BINARY_NAME="$BINARY_NAME" 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=/vendor" \
|
||||
--share="$PROJECT_OUT_DIR=/out" \
|
||||
--cores="$JOBS" \
|
||||
--container \
|
||||
--pure \
|
||||
--fallback \
|
||||
--rebuild-cache \
|
||||
-m $PWD/contrib/guix/manifest.scm \
|
||||
-- env CC=gcc VENDOR_DIR="$PROJECT_VENDOR_DIR" TARGET_DIR="$PROJECT_OUT_DIR" BINARY_NAME="$BINARY_NAME" JOBS="$JOBS" \
|
||||
/bin/sh -c "cd /liana && ./build.sh"
|
||||
done
|
||||
|
||||
set +ex
|
||||
|
||||
echo "Build successful. Output available at $OUT_DIR"
|
||||
15
contrib/guix/manifest.scm
Normal file
15
contrib/guix/manifest.scm
Normal file
@ -0,0 +1,15 @@
|
||||
(specifications->manifest
|
||||
(append
|
||||
(list "rust"
|
||||
"rust:cargo"
|
||||
"coreutils"
|
||||
"patchelf"
|
||||
"gcc-toolchain@10.3.0")
|
||||
;; Additional dependencies for building the GUI
|
||||
(let ((binary_name (getenv "BINARY_NAME")))
|
||||
(if
|
||||
(string=? binary_name "liana-gui")
|
||||
(list "pkg-config"
|
||||
"eudev"
|
||||
"fontconfig")
|
||||
'()))))
|
||||
459
contrib/guix/patches/gui/iced_default_enum.patch
Normal file
459
contrib/guix/patches/gui/iced_default_enum.patch
Normal file
@ -0,0 +1,459 @@
|
||||
commit f71bc71bf6724a1c5e2a3246dd8bd0a90fcf0e15
|
||||
Author: Antoine Poinsot <darosior@protonmail.com>
|
||||
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<dyn application::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+impl Default for Application {
|
||||
+ fn default() -> Self {
|
||||
+ Self::Default
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
impl application::StyleSheet for Theme {
|
||||
type Style = Application;
|
||||
|
||||
@@ -119,10 +128,11 @@ impl From<fn(&Theme) -> 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<dyn button::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+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<dyn checkbox::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+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<dyn container::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+impl Default for Container {
|
||||
+ fn default() -> Self {
|
||||
+ Self::Transparent
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
impl From<fn(&Theme) -> 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<dyn slider::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+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<dyn menu::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+impl Default for Menu {
|
||||
+ fn default() -> Self {
|
||||
+ Self::Default
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
impl menu::StyleSheet for Theme {
|
||||
type Style = Menu;
|
||||
|
||||
@@ -510,10 +549,9 @@ impl From<PickList> 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<dyn radio::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+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<dyn toggler::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+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<dyn pane_grid::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+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<dyn progress_bar::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+impl Default for ProgressBar {
|
||||
+ fn default() -> Self {
|
||||
+ Self::Primary
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
impl From<fn(&Theme) -> 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<dyn rule::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+impl Default for Rule {
|
||||
+ fn default() -> Self {
|
||||
+ Self::Default
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
impl From<fn(&Theme) -> 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<dyn scrollable::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+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<Color> 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<dyn text_input::StyleSheet<Style = Theme>>),
|
||||
}
|
||||
|
||||
+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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user