diff --git a/.buildkite/linux/release-entrypoint b/.buildkite/linux/release-entrypoint index a85877d93..7e52c90a5 100755 --- a/.buildkite/linux/release-entrypoint +++ b/.buildkite/linux/release-entrypoint @@ -4,7 +4,7 @@ set -e export PATH="$PATH:/state/rust/cargo/bin" export BUILD_ROOT=/state/build -export RELEASE=1 +export RELEASE=2 ln -sf out/node_modules . if [ $(uname -m) = "aarch64" ]; then diff --git a/Cargo.toml b/Cargo.toml index 42f9e8068..68e92b477 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -152,3 +152,7 @@ debug = 0 debug = 0 [profile.dev.package.rsbridge] debug = 0 + +[profile.release-lto] +inherits = "release" +lto = true diff --git a/build/configure/src/bundle.rs b/build/configure/src/bundle.rs index ece14b10c..4c55a58af 100644 --- a/build/configure/src/bundle.rs +++ b/build/configure/src/bundle.rs @@ -8,6 +8,7 @@ use ninja_gen::archives::empty_manifest; use ninja_gen::archives::with_exe; use ninja_gen::archives::OnlineArchive; use ninja_gen::archives::Platform; +use ninja_gen::build::BuildProfile; use ninja_gen::cargo::CargoBuild; use ninja_gen::cargo::RustOutput; use ninja_gen::git::SyncSubmodule; @@ -269,7 +270,7 @@ fn build_pyoxidizer(build: &mut Build) -> Result<()> { "--manifest-path={} --target-dir={} -p pyoxidizer", "qt/bundle/PyOxidizer/Cargo.toml", "$builddir/bundle/rust" ), - release_override: Some(true), + release_override: Some(BuildProfile::Release), }, )?; Ok(()) @@ -320,7 +321,8 @@ impl BuildAction for BuildBundle { overriden_rust_target_triple() .unwrap_or_else(|| Platform::current().as_rust_triple()), ), - true, + // our pyoxidizer bin uses lto on the release profile + BuildProfile::Release, )], ); } diff --git a/build/configure/src/rust.rs b/build/configure/src/rust.rs index bbd6038f1..3765e3003 100644 --- a/build/configure/src/rust.rs +++ b/build/configure/src/rust.rs @@ -3,6 +3,7 @@ use anyhow::Result; use ninja_gen::action::BuildAction; +use ninja_gen::build::BuildProfile; use ninja_gen::build::FilesHandle; use ninja_gen::cargo::CargoBuild; use ninja_gen::cargo::CargoClippy; @@ -202,7 +203,7 @@ pub fn check_minilints(build: &mut Build) -> Result<()> { outputs: &[RustOutput::Binary("minilints")], target: None, extra_args: "-p minilints", - release_override: Some(false), + release_override: Some(BuildProfile::Debug), }, ) } diff --git a/build/ninja_gen/src/build.rs b/build/ninja_gen/src/build.rs index 30db0e29e..cba663335 100644 --- a/build/ninja_gen/src/build.rs +++ b/build/ninja_gen/src/build.rs @@ -19,7 +19,7 @@ use crate::input::BuildInput; pub struct Build { pub variables: HashMap<&'static str, String>, pub buildroot: Utf8PathBuf, - pub release: bool, + pub build_profile: BuildProfile, pub pools: Vec<(&'static str, usize)>, pub trailing_text: String, pub host_platform: Platform, @@ -40,7 +40,7 @@ impl Build { let mut build = Build { buildroot, - release: std::env::var("RELEASE").is_ok(), + build_profile: BuildProfile::from_env(), host_platform: Platform::current(), variables: Default::default(), pools: Default::default(), @@ -102,7 +102,7 @@ impl Build { }; let mut statement = - BuildStatement::from_build_action(group, action, &self.groups, self.release); + BuildStatement::from_build_action(group, action, &self.groups, self.build_profile); if first_invocation { let command = statement.prepare_command(command)?; @@ -218,7 +218,7 @@ struct BuildStatement<'a> { env_vars: Vec, working_dir: Option, create_dirs: Vec, - release: bool, + build_profile: BuildProfile, bypass_runner: bool, } @@ -227,7 +227,7 @@ impl BuildStatement<'_> { group: &str, mut action: impl BuildAction, existing_outputs: &'a HashMap>, - release: bool, + build_profile: BuildProfile, ) -> BuildStatement<'a> { let mut stmt = BuildStatement { existing_outputs, @@ -244,7 +244,7 @@ impl BuildStatement<'_> { env_vars: Default::default(), working_dir: None, create_dirs: Default::default(), - release, + build_profile, bypass_runner: action.bypass_runner(), }; action.files(&mut stmt); @@ -328,6 +328,23 @@ fn expand_inputs( vec } +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum BuildProfile { + Debug, + Release, + ReleaseWithLto, +} + +impl BuildProfile { + fn from_env() -> Self { + match std::env::var("RELEASE").unwrap_or_default().as_str() { + "1" => Self::Release, + "2" => Self::ReleaseWithLto, + _ => Self::Debug, + } + } +} + pub trait FilesHandle { /// Add inputs to the build statement. Can be called multiple times with /// different variables. This is a shortcut for calling .expand_inputs() @@ -391,7 +408,7 @@ pub trait FilesHandle { /// at the folder. fn create_dir_all(&mut self, key: &str, path: impl Into); - fn release_build(&self) -> bool; + fn build_profile(&self) -> BuildProfile; } impl FilesHandle for BuildStatement<'_> { @@ -474,8 +491,8 @@ impl FilesHandle for BuildStatement<'_> { expand_inputs(inputs, self.existing_outputs) } - fn release_build(&self) -> bool { - self.release + fn build_profile(&self) -> BuildProfile { + self.build_profile } fn add_output_stamp(&mut self, path: impl Into) { diff --git a/build/ninja_gen/src/cargo.rs b/build/ninja_gen/src/cargo.rs index c3875442c..3419c9869 100644 --- a/build/ninja_gen/src/cargo.rs +++ b/build/ninja_gen/src/cargo.rs @@ -7,6 +7,7 @@ use camino::Utf8PathBuf; use crate::action::BuildAction; use crate::archives::with_exe; +use crate::build::BuildProfile; use crate::build::FilesHandle; use crate::input::BuildInput; use crate::inputs; @@ -31,7 +32,12 @@ impl RustOutput<'_> { } } - pub fn path(&self, rust_base: &Utf8Path, target: Option<&str>, release: bool) -> String { + pub fn path( + &self, + rust_base: &Utf8Path, + target: Option<&str>, + build_profile: BuildProfile, + ) -> String { let filename = match *self { RustOutput::Binary(package) => { if cfg!(windows) { @@ -56,20 +62,26 @@ impl RustOutput<'_> { if let Some(target) = target { path = path.join(target); } - path = path - .join(if release { "release" } else { "debug" }) - .join(filename); + path = path.join(profile_output_dir(build_profile)).join(filename); path.to_string() } } +fn profile_output_dir(profile: BuildProfile) -> &'static str { + match profile { + BuildProfile::Debug => "debug", + BuildProfile::Release => "release", + BuildProfile::ReleaseWithLto => "release-lto", + } +} + #[derive(Debug, Default)] pub struct CargoBuild<'a> { pub inputs: BuildInput, pub outputs: &'a [RustOutput<'a>], pub target: Option<&'static str>, pub extra_args: &'a str, - pub release_override: Option, + pub release_override: Option, } impl BuildAction for CargoBuild<'_> { @@ -80,8 +92,8 @@ impl BuildAction for CargoBuild<'_> { fn files(&mut self, build: &mut impl FilesHandle) { let release_build = self .release_override - .unwrap_or_else(|| build.release_build()); - let release_arg = if release_build { "--release" } else { "" }; + .unwrap_or_else(|| build.build_profile()); + let release_arg = profile_arg_for_cargo(release_build).unwrap_or_default(); let target_arg = if let Some(target) = self.target { format!("--target {target}") } else { @@ -114,6 +126,14 @@ impl BuildAction for CargoBuild<'_> { } } +fn profile_arg_for_cargo(profile: BuildProfile) -> Option<&'static str> { + match profile { + BuildProfile::Debug => None, + BuildProfile::Release => Some("--release"), + BuildProfile::ReleaseWithLto => Some("--profile release-lto"), + } +} + fn setup_flags(build: &mut Build) -> Result<()> { build.once_only("cargo_flags_and_pool", |build| { build.variable("cargo_flags", "--locked"); diff --git a/build/ninja_gen/src/configure.rs b/build/ninja_gen/src/configure.rs index bb87904ec..c0fbec33a 100644 --- a/build/ninja_gen/src/configure.rs +++ b/build/ninja_gen/src/configure.rs @@ -4,6 +4,7 @@ use anyhow::Result; use crate::action::BuildAction; +use crate::build::BuildProfile; use crate::build::FilesHandle; use crate::cargo::CargoBuild; use crate::cargo::RustOutput; @@ -33,7 +34,7 @@ impl BuildAction for ConfigureBuild { outputs: &[RustOutput::Binary("configure")], target: None, extra_args: "-p configure", - release_override: Some(false), + release_override: Some(BuildProfile::Debug), }, )?; Ok(()) diff --git a/docs/development.md b/docs/development.md index 1c24037c8..0084e0cc0 100644 --- a/docs/development.md +++ b/docs/development.md @@ -105,7 +105,8 @@ To run Anki in optimized mode, use: ./tools/runopt ``` -Or set RELEASE=1. +Or set RELEASE=1 or RELEASE=2. The latter will further optimize the output, but make +the build much slower. ## Building redistributable wheels diff --git a/qt/bundle/Cargo.toml b/qt/bundle/Cargo.toml index ac1a8bfd8..920e890d0 100644 --- a/qt/bundle/Cargo.toml +++ b/qt/bundle/Cargo.toml @@ -55,3 +55,6 @@ build-mode-pyoxidizer-exe = [] # to the directory containing build artifacts produced by `pyoxidizer`. If not # set, OUT_DIR will be used. build-mode-prebuilt-artifacts = [] + +[profile.release] +lto = true