diff --git a/src/options.rs b/src/options.rs index 677b0e7..a653ad9 100644 --- a/src/options.rs +++ b/src/options.rs @@ -50,14 +50,17 @@ pub enum BuildMode { #[derive(Clone, Debug, Eq, PartialEq, Parser)] pub struct BuildOptions { - #[arg(short = 'D', long, conflicts_with = "release")] + #[arg(short = 'D', long, conflicts_with_all = ["release", "profile"])] /// Build artifacts in development mode, without optimizations pub dev: bool, - #[arg(short = 'O', long, conflicts_with = "dev")] + #[arg(short = 'O', long, conflicts_with_all = ["dev", "profile"])] /// Build artifacts in release mode, with optimizations pub release: bool, + #[arg(long, conflicts_with_all = ["dev", "release"])] + pub profile: Option, + #[arg(short = 'a', long)] /// Build artifacts with debug assertions and overflow checks enabled (default if not -O) pub debug_assertions: bool, @@ -167,6 +170,20 @@ pub struct BuildOptions { pub disable_branch_folding: Option, } +impl BuildOptions { + pub fn profile_name(&self) -> &str { + // if no explicit profile is given then we default to release + // mode unless debug mode is explicitly requested. + if let Some(profile) = &self.profile { + profile + } else if !self.dev { + "release" + } else { + "dev" + } + } +} + impl stdfmt::Display for BuildOptions { fn fmt(&self, f: &mut stdfmt::Formatter) -> stdfmt::Result { if self.dev { @@ -177,6 +194,10 @@ impl stdfmt::Display for BuildOptions { write!(f, " -O")?; } + if let Some(profile) = &self.profile { + write!(f, " --profile {profile}")?; + } + if self.debug_assertions { write!(f, " -a")?; } @@ -249,6 +270,7 @@ mod test { let default_opts = BuildOptions { dev: false, release: false, + profile: None, debug_assertions: false, verbose: false, no_default_features: false, @@ -277,6 +299,10 @@ mod test { release: true, ..default_opts.clone() }, + BuildOptions { + profile: Some("fuzz".to_string()), + ..default_opts.clone() + }, BuildOptions { debug_assertions: true, ..default_opts.clone() diff --git a/src/project.rs b/src/project.rs index c62bfe9..1afd983 100644 --- a/src/project.rs +++ b/src/project.rs @@ -140,10 +140,16 @@ impl FuzzProject { // --target= won't pass rustflags to build scripts .arg("--target") .arg(&build.triple); - // we default to release mode unless debug mode is explicitly requested - if !build.dev { - cmd.args(["--release", "--config", "profile.release.debug=true"]); - } + let profile = build.profile_name(); + + cmd.args([ + &format!("--profile={profile}"), + "--config", + &format!("profile.{profile}.debug=true"), + "--config", + &format!("profile.{profile}.lto=false"), + ]); + if build.verbose { cmd.arg("--verbose"); } @@ -740,10 +746,11 @@ impl FuzzProject { corpus_dir: &Path, ) -> Result<(Command, tempfile::TempDir)> { let bin_path = { - let profile_subdir = if coverage.build.dev { - "debug" - } else { - "release" + // See https://doc.rust-lang.org/cargo/guide/build-cache.html for the mapping. + let profile_subdir = match coverage.build.profile_name() { + "dev" | "test" => "debug", + "release" | "bench" => "release", + other => other, }; let target_dir = self