feat(build): add freestanding, lto, strip, panic-abort, and codegen-units support in dcr.toml

This commit is contained in:
2026-06-16 16:42:56 +08:00
parent 3d596d7280
commit 21932ac94a
18 changed files with 242 additions and 73 deletions

View File

@@ -93,20 +93,22 @@ jobs:
set -euo pipefail set -euo pipefail
tag="${{ needs.setup.outputs.version }}" tag="${{ needs.setup.outputs.version }}"
notes_file=".github/release-notes.md" notes_file=".github/release-notes.md"
if grep -q "^## \\[${tag}\\]" CHANGELOG.md; then # Strip -dev suffix to match base version in CHANGELOG
changelog_tag="${tag%-dev}"
if grep -q "^## \\[${changelog_tag}\\]" CHANGELOG.md; then
# Extract release name from header: ## [0.7.1] - 2026-06-02 "Title" # Extract release name from header: ## [0.7.1] - 2026-06-02 "Title"
release_name=$(awk -v ver="$tag" ' release_name=$(awk -v search_ver="$changelog_tag" -v display_ver="$tag" '
$0 ~ "^## \\[" ver "\\]" { $0 ~ "^## \\[" search_ver "\\]" {
match($0, /"([^"]+)"/, arr) match($0, /"([^"]+)"/, arr)
if (arr[1] != "") { if (arr[1] != "") {
print "v" ver " - " arr[1] print "v" display_ver " - " arr[1]
} else { } else {
print "v" ver print "v" display_ver
} }
} }
' CHANGELOG.md) ' CHANGELOG.md)
echo "release_name=${release_name}" >> "$GITHUB_OUTPUT" echo "release_name=${release_name}" >> "$GITHUB_OUTPUT"
awk -v ver="$tag" ' awk -v ver="$changelog_tag" '
$0 ~ "^## \\[" ver "\\]" {found=1; next} $0 ~ "^## \\[" ver "\\]" {found=1; next}
found && $0 ~ "^## \\[" {exit} found && $0 ~ "^## \\[" {exit}
found {print} found {print}

View File

@@ -1,5 +1,35 @@
# Changelog # Changelog
## [0.7.4] - 2026-06-16 "Bare-Metal и Оптимизация Сборки / Bare-Metal & Build Optimization"
### RU
**Добавлено:**
- **Полноценная автоматизация Bare-Metal / Freestanding** — добавлен конфигурационный флаг `build.freestanding = true`. При его включении (или при обнаружении bare-metal таргета) DCR автоматически инжектирует флаг `-ffreestanding` на этапе компиляции, а также `-nostdlib` и `-static` на этапе линковки.
- **Оптимизация артефактов (LTO и Strip)** — в `dcr.toml` добавлены параметры `build.lto` (авто-инжекция флага `-flto` для компилятора и линкера) и `build.strip` (автоматическое отсекание отладочной информации через флаг `-s` линкера).
- **Контроль многопоточности сборки** — добавлен параметр `build.codegen-units`, позволяющий жестко ограничить максимальное количество параллельных потоков сборки для кастомного движка `parallel_build`.
- **Управление паникой (Panic Abort)** — добавлен параметр `build.panic = "abort"`. Для C++ проектов он автоматически отключает генерацию таблиц раскрутки стека и исключений через флаги `-fno-exceptions`, `-fno-unwind-tables` и `-fno-asynchronous-unwind-tables`.
**Изменено:**
- **Интеллектуальные дефолтные флаги (DCR Defaults)** — генерация дефолтных флагов оптимизации (`-O3`/`-O0`), отладки (`-g`) и предупреждений (`-Wall -Wextra`) теперь автоматически отключается для bare-metal и freestanding целей, если пользователь переопределил `build.cflags`.
- **Глобальный вынос bare-metal детектора** — функция `is_bare_metal_target` вынесена в общие утилиты `src/utils/build.rs` для сквозного использования в конвейере сборки.
### EN
**Added:**
- **Full Bare-Metal / Freestanding Automation** — introduced the `build.freestanding = true` configuration option. When enabled (or when a bare-metal target is detected), DCR automatically injects `-ffreestanding` during compilation and both `-nostdlib` and `-static` during linking.
- **Artifact Optimization (LTO & Strip)** — added `build.lto` (auto-injects `-flto` for compiler and linker) and `build.strip` (automatically strips debug symbols via linker `-s` flag) options to `dcr.toml`.
- **Compilation Thread Control** — added the `build.codegen-units` option to strictly limit the maximum number of parallel jobs utilized by the custom `parallel_build` worker pool.
- **Panic Behavior Management** — added `build.panic = "abort"` support. For C++ targets, it automatically strips exception handling and unwind tables via `-fno-exceptions`, `-fno-unwind-tables`, and `-fno-asynchronous-unwind-tables`.
**Changed:**
- **Intelligent Default Flags Generation** — automated injection of fallback optimization (`-O3`/`-O0`), debug (`-g`), and warning (`-Wall -Wextra`) flags is now suppressed for bare-metal and freestanding builds if `build.cflags` are overridden.
- **Centralized Bare-Metal Detection** — relocated the `is_bare_metal_target` helper to common build utilities (`src/utils/build.rs`) for unified access across the building core.
## [0.7.3] - 2026-06-13 "Оптимизация Зависимостей и VCS / Dependency Optimization & VCS" ## [0.7.3] - 2026-06-13 "Оптимизация Зависимостей и VCS / Dependency Optimization & VCS"
### RU ### RU

2
Cargo.lock generated
View File

@@ -98,7 +98,7 @@ dependencies = [
[[package]] [[package]]
name = "dcr" name = "dcr"
version = "0.7.3" version = "0.7.4"
dependencies = [ dependencies = [
"ctrlc", "ctrlc",
"glob", "glob",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "dcr" name = "dcr"
version = "0.7.3" version = "0.7.4"
edition = "2024" edition = "2024"
build = "build.rs" build = "build.rs"
description = "DCR is a utility for managing C/C++ projects in a Cargo-like style." description = "DCR is a utility for managing C/C++ projects in a Cargo-like style."

60
TODO.md
View File

@@ -2,38 +2,35 @@
Priority list of tasks to turn DCR into a true Cargo killer for C/C++ developers. Priority list of tasks to turn DCR into a true Cargo killer for C/C++ developers.
## 🔥 High Priority (Next Releases) **Legend:** `[ ]` — not implemented | `[-]` — partially implemented | `[x]` — implemented
- [x] **Git dependencies support** ## 🔥 High Priority
`git = "https://github.com/user/repo.git#branch"` and `git = "..."@tag`
- [ ] **Conan and vcpkg integration** - [ ] **CLI Output Refactoring & Cleanup**
Automatic download, installation and linking of packages - [ ] Move all terminal strings to a dedicated module (`src/ui/messages.rs`)
- [ ] **Full freestanding / embedded support** - [ ] Standardize logging formats (`error:`, `warning:`, `status:`)
`-nostdlib`, linker scripts, bare-metal targets (i686-elf, aarch64-none-elf, etc.) - [x] Add build execution time statistics to the final output (e.g., `Finished in 4.23s`)
- [ ] **EFI support** - [ ] **Internationalization (i18n) / Localization**
Dedicated platform configuration for EFI targets - [ ] Integrate a lightweight localization engine (`fluent` or `gettext` pure-Rust port)
- [ ] **Custom project name** - [ ] Create initial translation catalogs (`en.ftl`, `ru.ftl`)
Override binary name in `dcr.toml` - [x] **Self-Update Stability Validation**
- [ ] **Custom build steps / targets** - [x] Self-update implemented via `self-replace` + `ureq` in `flag_update.rs`
Ability to define custom pre-build, post-build, codegen steps in `dcr.toml` - [-] **Freestanding / Embedded Automation**
- [ ] **Improved mixed C/C++/ASM projects** - *`-ffreestanding` injected at compile time, `-nostdlib -static` at link time for bare-metal targets or `build.freestanding = true`. Config option `build.freestanding` (bool) added.*
Better handling of `.S` and `.asm` files with correct flags - [ ] **Conan and vcpkg integration** Automatic download, installation and linking of packages
- [ ] **dcr publish + official package registry**
Publish and fetch your own libraries easily
## ✅ Medium Priority ## ✅ Medium Priority
- [ ] **Static analysis** (`dcr check`) - [ ] **Static analysis** (`dcr check`)
Integration with clang-tidy, cppcheck, include-what-you-use Integration with clang-tidy, cppcheck, include-what-you-use
- [ ] **Linter + Formatter** (`dcr fmt`, `dcr lint`) - [-] **Linter + Formatter** (`dcr fmt`, `dcr lint`)
*`dcr fmt` (clang-format) implemented; `dcr lint` does not exist yet*
- [ ] **Hot reload / Live reload** for applications (raylib, SFML, SDL, etc.) - [ ] **Hot reload / Live reload** for applications (raylib, SFML, SDL, etc.)
- [ ] **Better cross-compilation experience** - [-] **Workspaces improvements** Per-member include directories, selective builds, better dependency graph
Ready-to-use toolchains + automatic download *Basic workspaces with dep ordering + topological sort work; advanced features missing*
- [ ] **Linker script support** + direct linker control - [-] **Build-time code generation** Support for protobuf, flatbuffers, Qt moc, custom generators
- [ ] **Workspaces improvements** *Generic `build.steps` machinery + Qt toolchain (uic/moc/rcc) work; no dedicated protobuf/flatbuffers generators*
Per-member include directories, selective builds, better dependency graph - [-] **dcr publish + official package registry** *Registry consumption (fetch, resolve, link) works; `dcr publish` command / local packing missing*
- [ ] **Build-time code generation**
Support for protobuf, flatbuffers, Qt moc, custom generators
## 📌 Low Priority / Nice to Have ## 📌 Low Priority / Nice to Have
@@ -57,13 +54,12 @@ Priority list of tasks to turn DCR into a true Cargo killer for C/C++ developers
--- ---
**Currently in progress:** **Currently in progress:**
- UI/UX terminal output unification and benchmarking metrics.
- ...
**Completed in recent releases:** **Completed in recent releases:**
- Extreme binary size optimization (-50% weight reduction via `ureq` + `native-certs`)
- Workspaces - Complete removal of `git2` and `openssl` in favor of system Git execution
- Cross-compilation - Workspaces & Cross-compilation (`--target <triple>`)
- IDE config generation (VS Code, CLion, compile_commands.json) - IDE config generation (VS Code, CLion, compile_commands.json)
- Self-update (`dcr --update`) - EFI support & Linker script support (`build.ldscript`)
- Header tracking - Mixed C/C++/ASM compilation with custom `std::thread::scope` work-stealing engine

View File

@@ -37,6 +37,23 @@ Set `inherit = false` to disable array inheritance (only profile's own arrays ar
| `debug` | `-O0 -g -Wall -Wextra -fno-omit-frame-pointer -DDCR_DEBUG` | | `debug` | `-O0 -g -Wall -Wextra -fno-omit-frame-pointer -DDCR_DEBUG` |
| `release` | `-O3 -DNDEBUG` | | `release` | `-O3 -DNDEBUG` |
These defaults are composed from the `opt_level`, `debug`, and `warnings` fields and can
be overridden per-profile:
```toml
[build.release]
opt_level = "z"
lto = true
strip = true
panic = "abort"
codegen-units = "1"
[build.debug]
opt_level = "1"
debug = false
warnings = ["all", "error"]
```
## Target-specific profiles ## Target-specific profiles
```toml ```toml

View File

@@ -20,6 +20,10 @@ DCR supports 4 compilation backends. Selection is automatic based on file extens
- Compiler resolved via `resolve_compiler()`: `DCR_COMPILER` > `DCR_CC` > `[toolchain]` > `build.compiler` > `PATH` - Compiler resolved via `resolve_compiler()`: `DCR_COMPILER` > `DCR_CC` > `[toolchain]` > `build.compiler` > `PATH`
- Supports `.d` files for header dependency tracking - Supports `.d` files for header dependency tracking
- Flags: `-std=`, `-MMD -MF`, `-c -o`, `-I`, `-L`, `-l` - Flags: `-std=`, `-MMD -MF`, `-c -o`, `-I`, `-L`, `-l`
- Conditional flags based on config:
- `freestanding` or bare-metal target: `-ffreestanding` (compile), `-nostdlib -static` (link)
- `lto`: `-flto` (compile + link)
- `panic = "abort"`: `-fno-exceptions` (C++ only), `-fno-unwind-tables`, `-fno-asynchronous-unwind-tables`
### MSVC ### MSVC

View File

@@ -37,9 +37,19 @@ target = "aarch64-unknown-linux-gnu"
# Auto: cflags += ["--target=aarch64-unknown-linux-gnu"] # Auto: cflags += ["--target=aarch64-unknown-linux-gnu"]
``` ```
## Bare-Metal ## Bare-Metal / Freestanding
For targets containing `none`, `-elf`, `eabi`, or `baremetal`, DCR default flags are disabled (no system include paths, no `-l` libc). For targets containing `none`, `-elf`, `eabi`, or `baremetal`, DCR automatically:
1. **Disables default flags** — no system include paths, no `-l` libc
2. **Injects `-ffreestanding`** at compile time and `-nostdlib -static` at link time
You can also enable freestanding mode explicitly:
```toml
[build]
freestanding = true
```
```bash ```bash
dcr build --target aarch64-none-elf dcr build --target aarch64-none-elf

View File

@@ -64,7 +64,7 @@ author = "John Doe"
| `compiler` | `"clang"` | Preferred compiler | | `compiler` | `"clang"` | Preferred compiler |
| `kind` | `"bin"` | `bin`, `staticlib`, `sharedlib`, `efi`, `elf`, `none`, `custom` | | `kind` | `"bin"` | `bin`, `staticlib`, `sharedlib`, `efi`, `elf`, `none`, `custom` |
| `target` | host | Target triple for cross-compilation | | `target` | host | Target triple for cross-compilation |
| `platform` | `"native"` | `native`, `efi`, `freestanding` | | `platform` | `"native"` | `native`, `efi` |
| `cflags` | `[]` | Additional C/C++/ASM flags | | `cflags` | `[]` | Additional C/C++/ASM flags |
| `ldflags` | `[]` | Additional linker flags | | `ldflags` | `[]` | Additional linker flags |
| `filename` | `""` | Custom output file name | | `filename` | `""` | Custom output file name |
@@ -77,6 +77,14 @@ author = "John Doe"
| `clean` | `[]` | Glob patterns for custom clean paths | | `clean` | `[]` | Glob patterns for custom clean paths |
| `out_dir` | `""` | Custom output directory | | `out_dir` | `""` | Custom output directory |
| `workspace_only` | `false` | Workspace-only, not built standalone | | `workspace_only` | `false` | Workspace-only, not built standalone |
| `freestanding` | `false` | Compile in freestanding mode (`-ffreestanding` + `-nostdlib -static`) |
| `opt_level` | `"0"` (debug) / `"3"` (release) | Optimization level: `0`-`3`, `"s"`, `"z"` |
| `debug` | `true` (debug) / `false` (release) | Emit debug symbols (`-g`) |
| `lto` | `false` | Link-time optimization (`-flto` for both compiler and linker) |
| `strip` | `false` | Strip symbols from output (`-s` in ldflags) |
| `warnings` | `["all", "extra"]` (debug) / `[]` (release) | Warning flags (e.g. `"all"`, `"extra"`, `"pedantic"`) |
| `panic` | `""` | Panic strategy: `"abort"` disables exceptions and unwind tables |
| `codegen-units` | `""` | Max parallel compilation jobs (`"0"` = auto) |
Settings from raw config (not in typed struct): Settings from raw config (not in typed struct):
- `pkg_config` — list of pkg-config packages - `pkg_config` — list of pkg-config packages

View File

@@ -24,8 +24,9 @@ use crate::core::deps::{register, resolve_deps};
use crate::core::workspace::parse_workspace; use crate::core::workspace::parse_workspace;
use crate::utils::build::{ use crate::utils::build::{
default_target_triple, get_bool_with_profile, get_config_opt, get_config_str, 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, get_language_with_profile, is_bare_metal_target, normalize_target_os, parse_version_info,
profile_table, resolve_compiler, resolve_pkg_config_flags, resolve_tool, 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::fs::{check_dir, find_project_root, with_dir};
use crate::utils::log::error; use crate::utils::log::error;
@@ -682,6 +683,63 @@ fn build_project_at(
let build_roots = let build_roots =
get_list_with_profile_and_target(&config, "roots", profile, build_target)?; get_list_with_profile_and_target(&config, "roots", profile, build_target)?;
let src_disable = get_bool_with_profile(&config, "src_disable", profile, false); 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 = let build_expects =
get_list_with_profile_and_target(&config, "expect", profile, build_target)?; get_list_with_profile_and_target(&config, "expect", profile, build_target)?;
let pkg_configs = let pkg_configs =
@@ -909,6 +967,9 @@ fn build_project_at(
} else { } else {
Some(build_type.as_str()) Some(build_type.as_str())
}, },
freestanding,
panic_abort,
codegen_units,
source_roots: &source_roots, source_roots: &source_roots,
exclude_dirs: &combined_excludes, exclude_dirs: &combined_excludes,
include_paths: &combined_includes, include_paths: &combined_includes,

View File

@@ -367,6 +367,9 @@ fn collect_project_info_inner(root: &Path, profile: &str) -> Result<ProjectInfo,
linker: resolved_linker.as_deref(), linker: resolved_linker.as_deref(),
archiver: resolved_archiver.as_deref(), archiver: resolved_archiver.as_deref(),
package_type: None, package_type: None,
freestanding: false,
panic_abort: false,
codegen_units: 0,
source_roots: &source_roots, source_roots: &source_roots,
exclude_dirs: &combined_excludes, exclude_dirs: &combined_excludes,
include_paths: &combined_includes, include_paths: &combined_includes,

View File

@@ -164,13 +164,18 @@ pub fn has_glob_magic(value: &str) -> bool {
value.chars().any(|c| matches!(c, '*' | '?' | '[')) 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 where
F: Fn(usize) -> Result<(), String> + Sync + Send, F: Fn(usize) -> Result<(), String> + Sync + Send,
{ {
let num_threads = std::thread::available_parallelism() let available = std::thread::available_parallelism()
.map(|n| n.get()) .map(|n| n.get())
.unwrap_or(1); .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 counter = std::sync::atomic::AtomicUsize::new(0);
let err_msg = std::sync::Mutex::new(None); let err_msg = std::sync::Mutex::new(None);

View File

@@ -151,9 +151,11 @@ fn build_objects(
.map(|s| common::object_path(obj_dir, s, obj_ext)) .map(|s| common::object_path(obj_dir, s, obj_ext))
.collect(); .collect();
common::parallel_build(sources.len(), |i| { common::parallel_build(
build_object(assembler, &sources[i], &objects[i], ctx) sources.len(),
})?; |i| build_object(assembler, &sources[i], &objects[i], ctx),
ctx.codegen_units,
)?;
Ok(objects) Ok(objects)
} }

View File

@@ -35,6 +35,9 @@ pub struct BuildContext<'a> {
pub linker: Option<&'a str>, pub linker: Option<&'a str>,
pub archiver: Option<&'a str>, pub archiver: Option<&'a str>,
pub package_type: 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 source_roots: &'a [std::path::PathBuf],
pub exclude_dirs: &'a [std::path::PathBuf], pub exclude_dirs: &'a [std::path::PathBuf],
pub include_paths: &'a [String], pub include_paths: &'a [String],

View File

@@ -228,9 +228,11 @@ fn build_objects(
.map(|s| common::object_path(obj_dir, s, obj_ext)) .map(|s| common::object_path(obj_dir, s, obj_ext))
.collect(); .collect();
common::parallel_build(sources.len(), |i| { common::parallel_build(
build_object(compiler, &sources[i], &objects[i], ctx) sources.len(),
})?; |i| build_object(compiler, &sources[i], &objects[i], ctx),
ctx.codegen_units,
)?;
Ok(objects) Ok(objects)
} }

View File

@@ -153,9 +153,11 @@ fn build_objects(
let format = nasm_format(ctx.platform); let format = nasm_format(ctx.platform);
common::parallel_build(sources.len(), |i| { common::parallel_build(
build_object(assembler, &sources[i], &objects[i], format, ctx) sources.len(),
})?; |i| build_object(assembler, &sources[i], &objects[i], format, ctx),
ctx.codegen_units,
)?;
Ok(objects) Ok(objects)
} }

View File

@@ -18,6 +18,7 @@
use crate::core::builder::BuildContext; use crate::core::builder::BuildContext;
use crate::core::builder::common; use crate::core::builder::common;
use crate::platform; use crate::platform;
use crate::utils::build::is_bare_metal_target;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
@@ -80,6 +81,9 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
cmd.arg("-nostdlib"); cmd.arg("-nostdlib");
cmd.arg("-Wl,-dll"); cmd.arg("-Wl,-dll");
cmd.arg("-Wl,--subsystem,10"); 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 { for obj in &objects {
cmd.arg(obj); 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( fn build_objects(
compiler: &str, compiler: &str,
sources: &[String], sources: &[String],
@@ -197,9 +188,11 @@ fn build_objects(
.map(|s| common::object_path(obj_dir, s, obj_ext)) .map(|s| common::object_path(obj_dir, s, obj_ext))
.collect(); .collect();
common::parallel_build(sources.len(), |i| { common::parallel_build(
build_object(compiler, &sources[i], &objects[i], ctx) sources.len(),
})?; |i| build_object(compiler, &sources[i], &objects[i], ctx),
ctx.codegen_units,
)?;
Ok(objects) Ok(objects)
} }
@@ -231,6 +224,23 @@ fn build_object(
cmd.arg("-fPIC"); 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 if let Some(platform) = ctx.platform
&& !platform.trim().is_empty() && !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 { if use_dcr_defaults {
for flag in default_flags(ctx.profile) { for flag in default_flags(ctx.profile) {
cmd.arg(flag); cmd.arg(flag);

View File

@@ -187,6 +187,19 @@ pub fn get_list_with_profile(config: &Config, field: &str, profile: &str) -> Vec
out 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 { pub fn get_bool_with_profile(config: &Config, field: &str, profile: &str, default: bool) -> bool {
let base = config let base = config
.get(&format!("build.{field}")) .get(&format!("build.{field}"))