mirror of
https://github.com/dexoron/dcr.git
synced 2026-10-21 16:29:41 +00:00
feat(build): add freestanding, lto, strip, panic-abort, and codegen-units support in dcr.toml
This commit is contained in:
@@ -24,8 +24,9 @@ use crate::core::deps::{register, resolve_deps};
|
||||
use crate::core::workspace::parse_workspace;
|
||||
use crate::utils::build::{
|
||||
default_target_triple, get_bool_with_profile, get_config_opt, get_config_str,
|
||||
get_language_with_profile, normalize_target_os, parse_version_info, prepend_clang_target_flag,
|
||||
profile_table, resolve_compiler, resolve_pkg_config_flags, resolve_tool,
|
||||
get_language_with_profile, is_bare_metal_target, normalize_target_os, parse_version_info,
|
||||
prepend_clang_target_flag, profile_table, resolve_compiler, resolve_pkg_config_flags,
|
||||
resolve_tool,
|
||||
};
|
||||
use crate::utils::fs::{check_dir, find_project_root, with_dir};
|
||||
use crate::utils::log::error;
|
||||
@@ -682,6 +683,63 @@ fn build_project_at(
|
||||
let build_roots =
|
||||
get_list_with_profile_and_target(&config, "roots", profile, build_target)?;
|
||||
let src_disable = get_bool_with_profile(&config, "src_disable", profile, false);
|
||||
let freestanding = get_bool_with_profile(&config, "freestanding", profile, false);
|
||||
let lto = get_bool_with_profile(&config, "lto", profile, false);
|
||||
let strip = get_bool_with_profile(&config, "strip", profile, false);
|
||||
let opt_level =
|
||||
get_string_with_profile_and_target(&config, "opt_level", profile, build_target);
|
||||
let debug = get_bool_with_profile(&config, "debug", profile, profile != "release");
|
||||
let warnings =
|
||||
get_list_with_profile_and_target(&config, "warnings", profile, build_target)?;
|
||||
let panic_val = get_string_with_profile_and_target(&config, "panic", profile, build_target);
|
||||
let panic_abort = panic_val == "abort";
|
||||
let codegen_units: usize =
|
||||
get_string_with_profile_and_target(&config, "codegen-units", profile, build_target)
|
||||
.parse()
|
||||
.unwrap_or(0);
|
||||
|
||||
if build_cflags.is_empty() && !freestanding && !is_bare_metal_target(build_target) {
|
||||
if !opt_level.is_empty() {
|
||||
build_cflags.push(format!("-O{opt_level}"));
|
||||
} else {
|
||||
build_cflags.push(match profile {
|
||||
"release" => "-O3".to_string(),
|
||||
_ => "-O0".to_string(),
|
||||
});
|
||||
}
|
||||
if debug {
|
||||
build_cflags.push("-g".to_string());
|
||||
}
|
||||
if warnings.is_empty() {
|
||||
if profile == "debug" {
|
||||
build_cflags.push("-Wall".to_string());
|
||||
build_cflags.push("-Wextra".to_string());
|
||||
}
|
||||
} else {
|
||||
for w in &warnings {
|
||||
build_cflags.push(format!("-W{w}"));
|
||||
}
|
||||
}
|
||||
match profile {
|
||||
"debug" => {
|
||||
build_cflags.push("-fno-omit-frame-pointer".to_string());
|
||||
build_cflags.push("-DDCR_DEBUG".to_string());
|
||||
}
|
||||
"release" => {
|
||||
build_cflags.push("-DNDEBUG".to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if lto {
|
||||
build_cflags.push("-flto".to_string());
|
||||
build_ldflags.push("-flto".to_string());
|
||||
}
|
||||
if strip {
|
||||
build_ldflags.push("-s".to_string());
|
||||
}
|
||||
|
||||
let build_expects =
|
||||
get_list_with_profile_and_target(&config, "expect", profile, build_target)?;
|
||||
let pkg_configs =
|
||||
@@ -909,6 +967,9 @@ fn build_project_at(
|
||||
} else {
|
||||
Some(build_type.as_str())
|
||||
},
|
||||
freestanding,
|
||||
panic_abort,
|
||||
codegen_units,
|
||||
source_roots: &source_roots,
|
||||
exclude_dirs: &combined_excludes,
|
||||
include_paths: &combined_includes,
|
||||
|
||||
@@ -367,6 +367,9 @@ fn collect_project_info_inner(root: &Path, profile: &str) -> Result<ProjectInfo,
|
||||
linker: resolved_linker.as_deref(),
|
||||
archiver: resolved_archiver.as_deref(),
|
||||
package_type: None,
|
||||
freestanding: false,
|
||||
panic_abort: false,
|
||||
codegen_units: 0,
|
||||
source_roots: &source_roots,
|
||||
exclude_dirs: &combined_excludes,
|
||||
include_paths: &combined_includes,
|
||||
|
||||
@@ -164,13 +164,18 @@ pub fn has_glob_magic(value: &str) -> bool {
|
||||
value.chars().any(|c| matches!(c, '*' | '?' | '['))
|
||||
}
|
||||
|
||||
pub fn parallel_build<F>(total_tasks: usize, task_fn: F) -> Result<(), String>
|
||||
pub fn parallel_build<F>(total_tasks: usize, task_fn: F, max_jobs: usize) -> Result<(), String>
|
||||
where
|
||||
F: Fn(usize) -> Result<(), String> + Sync + Send,
|
||||
{
|
||||
let num_threads = std::thread::available_parallelism()
|
||||
let available = std::thread::available_parallelism()
|
||||
.map(|n| n.get())
|
||||
.unwrap_or(1);
|
||||
let num_threads = if max_jobs > 0 {
|
||||
max_jobs.min(available)
|
||||
} else {
|
||||
available
|
||||
};
|
||||
|
||||
let counter = std::sync::atomic::AtomicUsize::new(0);
|
||||
let err_msg = std::sync::Mutex::new(None);
|
||||
|
||||
@@ -151,9 +151,11 @@ fn build_objects(
|
||||
.map(|s| common::object_path(obj_dir, s, obj_ext))
|
||||
.collect();
|
||||
|
||||
common::parallel_build(sources.len(), |i| {
|
||||
build_object(assembler, &sources[i], &objects[i], ctx)
|
||||
})?;
|
||||
common::parallel_build(
|
||||
sources.len(),
|
||||
|i| build_object(assembler, &sources[i], &objects[i], ctx),
|
||||
ctx.codegen_units,
|
||||
)?;
|
||||
|
||||
Ok(objects)
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ pub struct BuildContext<'a> {
|
||||
pub linker: Option<&'a str>,
|
||||
pub archiver: Option<&'a str>,
|
||||
pub package_type: Option<&'a str>,
|
||||
pub freestanding: bool,
|
||||
pub panic_abort: bool,
|
||||
pub codegen_units: usize,
|
||||
pub source_roots: &'a [std::path::PathBuf],
|
||||
pub exclude_dirs: &'a [std::path::PathBuf],
|
||||
pub include_paths: &'a [String],
|
||||
|
||||
@@ -228,9 +228,11 @@ fn build_objects(
|
||||
.map(|s| common::object_path(obj_dir, s, obj_ext))
|
||||
.collect();
|
||||
|
||||
common::parallel_build(sources.len(), |i| {
|
||||
build_object(compiler, &sources[i], &objects[i], ctx)
|
||||
})?;
|
||||
common::parallel_build(
|
||||
sources.len(),
|
||||
|i| build_object(compiler, &sources[i], &objects[i], ctx),
|
||||
ctx.codegen_units,
|
||||
)?;
|
||||
|
||||
Ok(objects)
|
||||
}
|
||||
|
||||
@@ -153,9 +153,11 @@ fn build_objects(
|
||||
|
||||
let format = nasm_format(ctx.platform);
|
||||
|
||||
common::parallel_build(sources.len(), |i| {
|
||||
build_object(assembler, &sources[i], &objects[i], format, ctx)
|
||||
})?;
|
||||
common::parallel_build(
|
||||
sources.len(),
|
||||
|i| build_object(assembler, &sources[i], &objects[i], format, ctx),
|
||||
ctx.codegen_units,
|
||||
)?;
|
||||
|
||||
Ok(objects)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
use crate::core::builder::BuildContext;
|
||||
use crate::core::builder::common;
|
||||
use crate::platform;
|
||||
use crate::utils::build::is_bare_metal_target;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
@@ -80,6 +81,9 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
cmd.arg("-nostdlib");
|
||||
cmd.arg("-Wl,-dll");
|
||||
cmd.arg("-Wl,--subsystem,10");
|
||||
} else if ctx.freestanding || is_bare_metal_target(ctx.target) {
|
||||
cmd.arg("-nostdlib");
|
||||
cmd.arg("-static");
|
||||
}
|
||||
for obj in &objects {
|
||||
cmd.arg(obj);
|
||||
@@ -172,19 +176,6 @@ fn default_flags(profile: &str) -> &'static [&'static str] {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_bare_metal_target(target: Option<&str>) -> bool {
|
||||
if let Some(t) = target {
|
||||
let lower = t.to_lowercase();
|
||||
lower.contains("none")
|
||||
|| lower.contains("-elf")
|
||||
|| lower.contains("eabi")
|
||||
|| lower.contains("baremetal")
|
||||
|| lower.contains("bare-metal")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn build_objects(
|
||||
compiler: &str,
|
||||
sources: &[String],
|
||||
@@ -197,9 +188,11 @@ fn build_objects(
|
||||
.map(|s| common::object_path(obj_dir, s, obj_ext))
|
||||
.collect();
|
||||
|
||||
common::parallel_build(sources.len(), |i| {
|
||||
build_object(compiler, &sources[i], &objects[i], ctx)
|
||||
})?;
|
||||
common::parallel_build(
|
||||
sources.len(),
|
||||
|i| build_object(compiler, &sources[i], &objects[i], ctx),
|
||||
ctx.codegen_units,
|
||||
)?;
|
||||
|
||||
Ok(objects)
|
||||
}
|
||||
@@ -231,6 +224,23 @@ fn build_object(
|
||||
cmd.arg("-fPIC");
|
||||
}
|
||||
|
||||
if (ctx.freestanding || is_bare_metal_target(ctx.target))
|
||||
&& ctx.language.to_lowercase() != "asm"
|
||||
{
|
||||
cmd.arg("-ffreestanding");
|
||||
}
|
||||
|
||||
if ctx.panic_abort && ctx.language.to_lowercase() != "asm" {
|
||||
if ctx.language.contains("++")
|
||||
|| ctx.language.contains("cpp")
|
||||
|| ctx.language.contains("cxx")
|
||||
{
|
||||
cmd.arg("-fno-exceptions");
|
||||
}
|
||||
cmd.arg("-fno-unwind-tables");
|
||||
cmd.arg("-fno-asynchronous-unwind-tables");
|
||||
}
|
||||
|
||||
if let Some(platform) = ctx.platform
|
||||
&& !platform.trim().is_empty()
|
||||
{
|
||||
@@ -250,7 +260,8 @@ fn build_object(
|
||||
}
|
||||
}
|
||||
|
||||
let use_dcr_defaults = ctx.cflags.is_empty() && !is_bare_metal_target(ctx.target);
|
||||
let use_dcr_defaults =
|
||||
ctx.cflags.is_empty() && !(ctx.freestanding || is_bare_metal_target(ctx.target));
|
||||
if use_dcr_defaults {
|
||||
for flag in default_flags(ctx.profile) {
|
||||
cmd.arg(flag);
|
||||
|
||||
@@ -187,6 +187,19 @@ pub fn get_list_with_profile(config: &Config, field: &str, profile: &str) -> Vec
|
||||
out
|
||||
}
|
||||
|
||||
pub fn is_bare_metal_target(target: Option<&str>) -> bool {
|
||||
if let Some(t) = target {
|
||||
let lower = t.to_lowercase();
|
||||
lower.contains("none")
|
||||
|| lower.contains("-elf")
|
||||
|| lower.contains("eabi")
|
||||
|| lower.contains("baremetal")
|
||||
|| lower.contains("bare-metal")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bool_with_profile(config: &Config, field: &str, profile: &str, default: bool) -> bool {
|
||||
let base = config
|
||||
.get(&format!("build.{field}"))
|
||||
|
||||
Reference in New Issue
Block a user