Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/fbuild-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ async-trait = { workspace = true }
regex = { workspace = true }
walkdir = { workspace = true }
sha2 = { workspace = true }
tempfile = { workspace = true }

[dev-dependencies]
tempfile = { workspace = true }
5 changes: 4 additions & 1 deletion crates/fbuild-build/src/avr/avr_linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use fbuild_core::subprocess::run_command;
use fbuild_core::{BuildProfile, Result, SizeInfo};

use super::mcu_config::AvrMcuConfig;
use crate::linker::Linker;
use crate::linker::{LinkExtraArgs, Linker};

/// AVR-specific linker using avr-gcc (link driver), avr-ar, avr-objcopy, avr-size.
pub struct AvrLinker {
Expand Down Expand Up @@ -64,6 +64,7 @@ impl Linker for AvrLinker {
objects: &[PathBuf],
archives: &[PathBuf],
output_dir: &Path,
extra: &LinkExtraArgs,
) -> Result<PathBuf> {
std::fs::create_dir_all(output_dir)?;
let elf_path = output_dir.join("firmware.elf");
Expand All @@ -80,6 +81,7 @@ impl Linker for AvrLinker {
if let Some(profile) = self.mcu_config.get_profile(self.profile.as_dir_name()) {
args.extend(profile.link_flags.iter().cloned());
}
args.extend(extra.flags.iter().cloned());

args.extend(["-o".to_string(), elf_path.to_string_lossy().to_string()]);

Expand All @@ -97,6 +99,7 @@ impl Linker for AvrLinker {
// Group for circular deps + libraries from config
args.push("-Wl,--start-group".to_string());
args.extend(self.mcu_config.linker_libs.iter().cloned());
args.extend(extra.libs.iter().cloned());
args.push("-Wl,--end-group".to_string());

if self.verbose {
Expand Down
5 changes: 4 additions & 1 deletion crates/fbuild-build/src/ch32v/ch32v_linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use fbuild_core::subprocess::run_command;
use fbuild_core::{BuildProfile, Result, SizeInfo};

use super::mcu_config::Ch32vMcuConfig;
use crate::linker::Linker;
use crate::linker::{LinkExtraArgs, Linker};

/// CH32V-specific linker using riscv-none-elf-gcc (link driver), ar, objcopy, size.
pub struct Ch32vLinker {
Expand Down Expand Up @@ -64,6 +64,7 @@ impl Linker for Ch32vLinker {
objects: &[PathBuf],
archives: &[PathBuf],
output_dir: &Path,
extra: &LinkExtraArgs,
) -> Result<PathBuf> {
std::fs::create_dir_all(output_dir)?;
let elf_path = output_dir.join("firmware.elf");
Expand All @@ -77,6 +78,7 @@ impl Linker for Ch32vLinker {
if let Some(profile) = self.mcu_config.get_profile(self.profile.as_dir_name()) {
args.extend(profile.link_flags.iter().cloned());
}
args.extend(extra.flags.iter().cloned());

args.extend([
format!("-T{}", self.linker_script_path.display()),
Expand All @@ -96,6 +98,7 @@ impl Linker for Ch32vLinker {

// Linker libraries from config
args.extend(self.mcu_config.linker_libs.iter().cloned());
args.extend(extra.libs.iter().cloned());

if self.verbose {
tracing::info!("link: {}", args.join(" "));
Expand Down
42 changes: 38 additions & 4 deletions crates/fbuild-build/src/compile_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use std::path::{Path, PathBuf};

use fbuild_core::Result;

use crate::flag_overlay::LanguageExtraFlags;

/// A single entry in the compile database.
#[derive(Debug, Clone, serde::Serialize)]
pub struct CompileEntry {
Expand Down Expand Up @@ -355,7 +357,7 @@ pub fn generate_entries(
c_flags: &[String],
cpp_flags: &[String],
include_flags: &[String],
extra_flags: &[String],
extra_flags: &LanguageExtraFlags,
sources: &[PathBuf],
build_dir: &Path,
project_dir: &Path,
Expand All @@ -377,13 +379,15 @@ pub fn generate_entries(
};

let obj = crate::compiler::CompilerBase::object_path(source, build_dir);
let source_extra_flags = extra_flags.for_source(source);

let mut arguments =
Vec::with_capacity(1 + flags.len() + include_flags.len() + extra_flags.len() + 4);
let mut arguments = Vec::with_capacity(
1 + flags.len() + include_flags.len() + source_extra_flags.len() + 4,
);
arguments.push(compiler.to_string_lossy().to_string());
arguments.extend(flags.iter().cloned());
arguments.extend(include_flags.iter().cloned());
arguments.extend(extra_flags.iter().cloned());
arguments.extend(source_extra_flags);
arguments.push("-c".to_string());
arguments.push(source.to_string_lossy().to_string());
arguments.push("-o".to_string());
Expand All @@ -403,6 +407,36 @@ pub fn generate_entries(
mod tests {
use super::*;

#[allow(clippy::too_many_arguments)]
fn generate_entries(
gcc_path: &Path,
gxx_path: &Path,
c_flags: &[String],
cpp_flags: &[String],
include_flags: &[String],
extra_flags: &[String],
sources: &[PathBuf],
build_dir: &Path,
project_dir: &Path,
) -> Vec<CompileEntry> {
super::generate_entries(
gcc_path,
gxx_path,
c_flags,
cpp_flags,
include_flags,
&LanguageExtraFlags {
common: extra_flags.to_vec(),
c: Vec::new(),
cxx: Vec::new(),
asm: Vec::new(),
},
sources,
build_dir,
project_dir,
)
}

// --- Serialization tests ---

#[test]
Expand Down
5 changes: 4 additions & 1 deletion crates/fbuild-build/src/esp32/esp32_linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use fbuild_core::{BuildProfile, Result, SizeInfo};
use crate::build_fingerprint::{
load_json, save_json, BinArtifactCache, FileStamp, SizeArtifactCache, BUILD_FINGERPRINT_VERSION,
};
use crate::linker::{Linker, LinkerScripts};
use crate::linker::{LinkExtraArgs, Linker, LinkerScripts};

use super::mcu_config::Esp32McuConfig;

Expand Down Expand Up @@ -241,6 +241,7 @@ impl Linker for Esp32Linker {
objects: &[PathBuf],
archives: &[PathBuf],
output_dir: &Path,
extra: &LinkExtraArgs,
) -> Result<PathBuf> {
std::fs::create_dir_all(output_dir)?;
let elf_path = output_dir.join("firmware.elf");
Expand All @@ -252,6 +253,7 @@ impl Linker for Esp32Linker {

// Linker flags (from SDK flags/ld_flags or MCU config fallback)
link_args.extend(self.linker_flags());
link_args.extend(extra.flags.iter().cloned());

// Linker scripts (search dirs + script names from SDK)
link_args.extend(self.linker_scripts.to_args());
Expand All @@ -277,6 +279,7 @@ impl Linker for Esp32Linker {

// SDK precompiled libraries (ordered flags from flags/ld_libs)
link_args.extend(self.sdk_lib_flags.clone());
link_args.extend(extra.libs.iter().cloned());

link_args.push("-Wl,--end-group".to_string());

Expand Down
71 changes: 53 additions & 18 deletions crates/fbuild-build/src/esp32/orchestrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::build_fingerprint::{
hash_watch_set_stamps, load_json, normalize_path, save_json, stable_hash_json,
PersistedBuildFingerprint, BUILD_FINGERPRINT_VERSION,
};
use crate::flag_overlay::LanguageExtraFlags;
use crate::linker::LinkerScripts;
use crate::zccache::FingerprintWatch;

Expand Down Expand Up @@ -503,6 +504,26 @@ impl BuildOrchestrator for Esp32Orchestrator {
let mut user_build_flags = ctx.config.get_build_flags(&params.env_name)?;
user_build_flags.extend(params.extra_build_flags.clone());
user_flags.extend(user_build_flags.clone());
let user_overlay = LanguageExtraFlags {
common: user_flags
.iter()
.cloned()
.chain(ctx.global_compile_overlay.common.iter().cloned())
.collect(),
c: ctx.global_compile_overlay.c.clone(),
cxx: ctx.global_compile_overlay.cxx.clone(),
asm: ctx.global_compile_overlay.asm.clone(),
};
let src_overlay = LanguageExtraFlags::combined(&[
&user_overlay,
&LanguageExtraFlags {
common: ctx.src_flags.clone(),
c: Vec::new(),
cxx: Vec::new(),
asm: Vec::new(),
},
&ctx.project_compile_overlay,
]);

// Emit a warning if CDC on boot is effectively enabled (may cause Serial to block
// when no USB host is connected).
Expand Down Expand Up @@ -533,8 +554,9 @@ impl BuildOrchestrator for Esp32Orchestrator {
);
// Apply user build_flags to library compilation (matching PlatformIO behavior).
// User flags like -std=gnu++2a replace the MCU config's -std=gnu++2b.
let c_flags = apply_user_flags(&temp_compiler.c_flags(), &user_flags);
let cpp_flags = apply_user_flags(&temp_compiler.cpp_flags(), &user_flags);
let c_flags = apply_overlay_flags(&temp_compiler.c_flags(), &user_overlay, "dummy.c");
let cpp_flags =
apply_overlay_flags(&temp_compiler.cpp_flags(), &user_overlay, "dummy.cpp");

let jobs = crate::parallel::effective_jobs(params.jobs);
// Use gcc-ar for LTO archives so the linker-plugin index is written.
Expand Down Expand Up @@ -594,8 +616,9 @@ impl BuildOrchestrator for Esp32Orchestrator {
params.verbose,
build_dir.join("tmp"),
);
let p_c_flags = apply_user_flags(&p_compiler.c_flags(), &user_flags);
let p_cpp_flags = apply_user_flags(&p_compiler.cpp_flags(), &user_flags);
let p_c_flags = apply_overlay_flags(&p_compiler.c_flags(), &src_overlay, "dummy.c");
let p_cpp_flags =
apply_overlay_flags(&p_compiler.cpp_flags(), &src_overlay, "dummy.cpp");

// Collect lib/* names so the helper can detect collisions with project-as-library.
let mut existing_lib_names = std::collections::HashSet::new();
Expand Down Expand Up @@ -677,8 +700,10 @@ impl BuildOrchestrator for Esp32Orchestrator {
params.verbose,
build_dir.join("tmp"),
);
let fw_c_flags = apply_user_flags(&fw_compiler.c_flags(), &user_flags);
let fw_cpp_flags = apply_user_flags(&fw_compiler.cpp_flags(), &user_flags);
let fw_c_flags =
apply_overlay_flags(&fw_compiler.c_flags(), &user_overlay, "dummy.c");
let fw_cpp_flags =
apply_overlay_flags(&fw_compiler.cpp_flags(), &user_overlay, "dummy.cpp");
let fw_signature = framework_signature(&include_dirs, &fw_c_flags, &fw_cpp_flags);

let mut fw_lib_count = 0;
Expand Down Expand Up @@ -836,10 +861,6 @@ impl BuildOrchestrator for Esp32Orchestrator {
all_core_sources.extend(sources.core_sources.iter().cloned());
all_core_sources.extend(sources.variant_sources.iter().cloned());

let src_flags = ctx.config.get_build_src_flags(&params.env_name)?;
let all_src_flags: Vec<String> =
user_flags.iter().chain(src_flags.iter()).cloned().collect();

// Precompute values needed for compile_commands.json in both paths
let include_flags = compiler.base.build_include_flags();
let arch = if mcu_config.is_xtensa() {
Expand All @@ -856,8 +877,8 @@ impl BuildOrchestrator for Esp32Orchestrator {
&compiler.c_flags(),
&compiler.cpp_flags(),
&include_flags,
&user_flags,
&all_src_flags,
&user_overlay,
&src_overlay,
&all_core_sources,
&sources.sketch_sources,
core_build_dir,
Expand Down Expand Up @@ -889,7 +910,7 @@ impl BuildOrchestrator for Esp32Orchestrator {
&compiler,
&all_core_sources,
core_build_dir,
&user_flags,
&user_overlay,
jobs,
Some(&build_log_mutex),
)?;
Expand All @@ -899,7 +920,7 @@ impl BuildOrchestrator for Esp32Orchestrator {
&compiler,
&sources.sketch_sources,
src_build_dir,
&all_src_flags,
&src_overlay,
jobs,
Some(&build_log_mutex),
)?;
Expand Down Expand Up @@ -947,8 +968,10 @@ impl BuildOrchestrator for Esp32Orchestrator {
// Use gcc-ar for LTO archives so the linker-plugin index is written.
let local_ar_path = toolchain.get_ar_path();
let local_gcc_ar_path = toolchain.get_gcc_ar_path();
let local_c_flags = apply_user_flags(&compiler.c_flags(), &all_src_flags);
let local_cpp_flags = apply_user_flags(&compiler.cpp_flags(), &all_src_flags);
let local_c_flags =
apply_overlay_flags(&compiler.c_flags(), &src_overlay, "dummy.c");
let local_cpp_flags =
apply_overlay_flags(&compiler.cpp_flags(), &src_overlay, "dummy.cpp");
let local_lib_ar_path = crate::pipeline::pick_archiver(
&local_ar_path,
&local_gcc_ar_path,
Expand Down Expand Up @@ -1017,8 +1040,8 @@ impl BuildOrchestrator for Esp32Orchestrator {
&compiler.c_flags(),
&compiler.cpp_flags(),
&include_flags,
&user_flags,
&all_src_flags,
&user_overlay,
&src_overlay,
&all_core_sources,
&sources.sketch_sources,
core_build_dir,
Expand Down Expand Up @@ -1055,6 +1078,10 @@ impl BuildOrchestrator for Esp32Orchestrator {
&sketch_objects,
&all_archives,
build_dir,
&crate::linker::LinkExtraArgs {
flags: ctx.overlay_link_flags.clone(),
libs: ctx.overlay_link_libs.clone(),
},
params.symbol_analysis,
)?;

Expand Down Expand Up @@ -1275,6 +1302,14 @@ fn apply_user_flags(base_flags: &[String], user_flags: &[String]) -> Vec<String>
result
}

fn apply_overlay_flags(
base_flags: &[String],
overlay: &LanguageExtraFlags,
probe_name: &str,
) -> Vec<String> {
apply_user_flags(base_flags, &overlay.for_source(Path::new(probe_name)))
}

fn define_flag_name(flag: &str) -> Option<&str> {
let define = flag.strip_prefix("-D")?;
let name = define
Expand Down
5 changes: 4 additions & 1 deletion crates/fbuild-build/src/esp8266/esp8266_linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use fbuild_core::subprocess::run_command;
use fbuild_core::{BuildProfile, Result, SizeInfo};

use super::mcu_config::Esp8266McuConfig;
use crate::linker::{Linker, LinkerScripts};
use crate::linker::{LinkExtraArgs, Linker, LinkerScripts};

/// ESP8266-specific linker using Xtensa LX106 GCC as the link driver.
pub struct Esp8266Linker {
Expand Down Expand Up @@ -140,6 +140,7 @@ impl Linker for Esp8266Linker {
objects: &[PathBuf],
archives: &[PathBuf],
output_dir: &Path,
extra: &LinkExtraArgs,
) -> Result<PathBuf> {
std::fs::create_dir_all(output_dir)?;

Expand Down Expand Up @@ -184,6 +185,7 @@ impl Linker for Esp8266Linker {
if let Some(profile) = self.mcu_config.profiles.get(self.profile.as_dir_name()) {
args.extend(profile.link_flags.iter().cloned());
}
args.extend(extra.flags.iter().cloned());

// Build output dir — contains generated local.eagle.app.v6.common.ld
args.push(format!("-L{}", output_dir.to_string_lossy()));
Expand All @@ -210,6 +212,7 @@ impl Linker for Esp8266Linker {
args.push(archive.to_string_lossy().to_string());
}
args.extend(self.mcu_config.linker_libs.iter().cloned());
args.extend(extra.libs.iter().cloned());
args.push("-Wl,--end-group".to_string());

if self.verbose {
Expand Down
Loading
Loading