mirror of
https://github.com/dexoron/dcr.git
synced 2026-10-21 16:59:42 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 617ba85442 |
@@ -1,5 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.2.7] - 2026-03-03
|
||||||
|
Added:
|
||||||
|
- Toolchain overrides via `[toolchain]` and env (`DCR_*`)
|
||||||
|
- ASM `.S` preprocessing via GCC/Clang (`-x assembler-with-cpp`)
|
||||||
|
|
||||||
## [0.2.6] - 2026-03-01
|
## [0.2.6] - 2026-03-01
|
||||||
Added:
|
Added:
|
||||||
- `sharedlib` build kind (shared library output)
|
- `sharedlib` build kind (shared library output)
|
||||||
|
|||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -90,7 +90,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dcr"
|
name = "dcr"
|
||||||
version = "0.2.6"
|
version = "0.2.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"self-replace",
|
"self-replace",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dcr"
|
name = "dcr"
|
||||||
version = "0.2.6"
|
version = "0.2.7"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
@@ -146,6 +146,14 @@ compiler = "clang"
|
|||||||
cflags = ["-Wall", "-Wextra"]
|
cflags = ["-Wall", "-Wextra"]
|
||||||
ldflags = ["-lm"]
|
ldflags = ["-lm"]
|
||||||
|
|
||||||
|
[toolchain]
|
||||||
|
# Optional tool overrides:
|
||||||
|
# cc = "clang"
|
||||||
|
# cxx = "clang++"
|
||||||
|
# as = "as"
|
||||||
|
# ar = "ar"
|
||||||
|
# ld = "ld"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
4
TODO.md
4
TODO.md
@@ -3,7 +3,5 @@
|
|||||||
- Add header dependency tracking for incremental builds (GCC/Clang: -MMD, MSVC: /showIncludes)
|
- Add header dependency tracking for incremental builds (GCC/Clang: -MMD, MSVC: /showIncludes)
|
||||||
- Add external package managers (Conan, vcpkg)
|
- Add external package managers (Conan, vcpkg)
|
||||||
- Multi-target
|
- Multi-target
|
||||||
- ASM support
|
|
||||||
- Linker script + direct linker control
|
- Linker script + direct linker control
|
||||||
- Custom targets/steps
|
- Custom targets/steps
|
||||||
- Tool overrides and env vars
|
|
||||||
@@ -26,6 +26,17 @@ kind = "bin"
|
|||||||
- `cflags` (string array, optional): extra compile flags.
|
- `cflags` (string array, optional): extra compile flags.
|
||||||
- `ldflags` (string array, optional): extra link flags.
|
- `ldflags` (string array, optional): extra link flags.
|
||||||
|
|
||||||
|
## Toolchain section
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[toolchain]
|
||||||
|
cc = "clang"
|
||||||
|
cxx = "clang++"
|
||||||
|
as = "as"
|
||||||
|
ar = "ar"
|
||||||
|
ld = "ld"
|
||||||
|
```
|
||||||
|
|
||||||
## Behavior notes
|
## Behavior notes
|
||||||
|
|
||||||
- Compiler backend is selected by compiler string (`gcc`, `clang`, `cl`, `clang-cl`).
|
- Compiler backend is selected by compiler string (`gcc`, `clang`, `cl`, `clang-cl`).
|
||||||
|
|||||||
@@ -39,6 +39,18 @@ If `build.platform` is set, DCR passes it as an architecture hint:
|
|||||||
- GCC/Clang: `-march=<platform>`
|
- GCC/Clang: `-march=<platform>`
|
||||||
- MSVC: maps to `/arch:*` for known values (`x86`, `i386`, `i486`, `i586`, `i686`, `sse2`, `avx`, `avx2`)
|
- MSVC: maps to `/arch:*` for known values (`x86`, `i386`, `i486`, `i586`, `i686`, `sse2`, `avx`, `avx2`)
|
||||||
|
|
||||||
|
## Toolchain overrides
|
||||||
|
|
||||||
|
If `[toolchain]` is set, DCR uses its values to override compiler/linker tools:
|
||||||
|
|
||||||
|
- `cc`, `cxx`, `as` override compilers for C/C++/ASM
|
||||||
|
- `ar` overrides the archiver (used for `staticlib`)
|
||||||
|
- `ld` overrides the linker (used by GCC/Clang/NASM/GAS backends)
|
||||||
|
|
||||||
|
Environment overrides (highest priority):
|
||||||
|
- `DCR_COMPILER` (all languages)
|
||||||
|
- `DCR_CC`, `DCR_CXX`, `DCR_AS`, `DCR_AR`, `DCR_LD`
|
||||||
|
|
||||||
## Linking
|
## Linking
|
||||||
|
|
||||||
For `kind = "bin"`:
|
For `kind = "bin"`:
|
||||||
|
|||||||
@@ -17,6 +17,13 @@ platform = "string" # optional
|
|||||||
cflags = ["string", "..."] # optional
|
cflags = ["string", "..."] # optional
|
||||||
ldflags = ["string", "..."] # optional
|
ldflags = ["string", "..."] # optional
|
||||||
|
|
||||||
|
[toolchain]
|
||||||
|
cc = "string" # optional
|
||||||
|
cxx = "string" # optional
|
||||||
|
as = "string" # optional
|
||||||
|
ar = "string" # optional
|
||||||
|
ld = "string" # optional
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
name = {
|
name = {
|
||||||
path = "string", # required for each dependency
|
path = "string", # required for each dependency
|
||||||
|
|||||||
104
src/cli/build.rs
104
src/cli/build.rs
@@ -33,6 +33,11 @@ pub fn build(args: &[String]) -> i32 {
|
|||||||
let build_target = get_config_str(&config, "build.target");
|
let build_target = get_config_str(&config, "build.target");
|
||||||
let build_kind = get_config_str(&config, "build.kind");
|
let build_kind = get_config_str(&config, "build.kind");
|
||||||
let build_platform = get_config_str(&config, "build.platform");
|
let build_platform = get_config_str(&config, "build.platform");
|
||||||
|
let tc_cc = get_config_opt(&config, "toolchain.cc");
|
||||||
|
let tc_cxx = get_config_opt(&config, "toolchain.cxx");
|
||||||
|
let tc_as = get_config_opt(&config, "toolchain.as");
|
||||||
|
let tc_ar = get_config_opt(&config, "toolchain.ar");
|
||||||
|
let tc_ld = get_config_opt(&config, "toolchain.ld");
|
||||||
let build_cflags = match get_config_list(&config, "build.cflags") {
|
let build_cflags = match get_config_list(&config, "build.cflags") {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
@@ -48,11 +53,21 @@ pub fn build(args: &[String]) -> i32 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let resolved_compiler = resolve_compiler(
|
||||||
|
&build_language,
|
||||||
|
&project_compiler,
|
||||||
|
tc_cc.as_deref(),
|
||||||
|
tc_cxx.as_deref(),
|
||||||
|
tc_as.as_deref(),
|
||||||
|
);
|
||||||
|
let resolved_linker = resolve_tool("DCR_LD", tc_ld.as_deref());
|
||||||
|
let resolved_archiver = resolve_tool("DCR_AR", tc_ar.as_deref());
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
" Building project `{}`\n Profile: {}\n Compiler: {}\n",
|
" Building project `{}`\n Profile: {}\n Compiler: {}\n",
|
||||||
colored(&project_name, BOLD_GREEN),
|
colored(&project_name, BOLD_GREEN),
|
||||||
colored(&active_profile, BOLD_GREEN),
|
colored(&active_profile, BOLD_GREEN),
|
||||||
colored(&project_compiler, BOLD_GREEN)
|
colored(&resolved_compiler, BOLD_GREEN)
|
||||||
);
|
);
|
||||||
|
|
||||||
ensure_target_dirs(&items, &active_profile, normalize_target(&build_target));
|
ensure_target_dirs(&items, &active_profile, normalize_target(&build_target));
|
||||||
@@ -74,12 +89,14 @@ pub fn build(args: &[String]) -> i32 {
|
|||||||
let ctx = BuildContext {
|
let ctx = BuildContext {
|
||||||
profile: &active_profile,
|
profile: &active_profile,
|
||||||
project_name: &project_name,
|
project_name: &project_name,
|
||||||
compiler: &project_compiler,
|
compiler: &resolved_compiler,
|
||||||
language: &build_language,
|
language: &build_language,
|
||||||
standard: &build_standard,
|
standard: &build_standard,
|
||||||
target_dir: normalize_target(&build_target),
|
target_dir: normalize_target(&build_target),
|
||||||
kind: normalize_kind(&build_kind),
|
kind: normalize_kind(&build_kind),
|
||||||
platform: normalize_platform(&build_platform),
|
platform: normalize_platform(&build_platform),
|
||||||
|
linker: resolved_linker.as_deref(),
|
||||||
|
archiver: resolved_archiver.as_deref(),
|
||||||
include_dirs: &resolved.include_dirs,
|
include_dirs: &resolved.include_dirs,
|
||||||
lib_dirs: &resolved.lib_dirs,
|
lib_dirs: &resolved.lib_dirs,
|
||||||
libs: &resolved.libs,
|
libs: &resolved.libs,
|
||||||
@@ -126,6 +143,16 @@ fn get_config_str(config: &Config, key: &str) -> String {
|
|||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_config_opt(config: &Config, key: &str) -> Option<String> {
|
||||||
|
let value = config.get(key)?.as_str()?;
|
||||||
|
let trimmed = value.trim();
|
||||||
|
if trimmed.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(trimmed.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_config_list(config: &Config, key: &str) -> Result<Vec<String>, String> {
|
fn get_config_list(config: &Config, key: &str) -> Result<Vec<String>, String> {
|
||||||
let value = match config.get(key) {
|
let value = match config.get(key) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
@@ -195,3 +222,76 @@ fn normalize_platform(platform: &str) -> Option<&str> {
|
|||||||
Some(trimmed)
|
Some(trimmed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_compiler(
|
||||||
|
language: &str,
|
||||||
|
compiler: &str,
|
||||||
|
tc_cc: Option<&str>,
|
||||||
|
tc_cxx: Option<&str>,
|
||||||
|
tc_as: Option<&str>,
|
||||||
|
) -> String {
|
||||||
|
let lang = language.to_lowercase();
|
||||||
|
env_override_compiler(&lang)
|
||||||
|
.or_else(|| toolchain_override_compiler(&lang, tc_cc, tc_cxx, tc_as))
|
||||||
|
.unwrap_or_else(|| compiler.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn env_override_compiler(lang: &str) -> Option<String> {
|
||||||
|
if let Ok(value) = std::env::var("DCR_COMPILER") {
|
||||||
|
let trimmed = value.trim();
|
||||||
|
if !trimmed.is_empty() {
|
||||||
|
return Some(trimmed.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lang == "asm" {
|
||||||
|
if let Ok(value) = std::env::var("DCR_AS") {
|
||||||
|
let trimmed = value.trim();
|
||||||
|
if !trimmed.is_empty() {
|
||||||
|
return Some(trimmed.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if (lang == "c++" || lang == "cpp" || lang == "cxx")
|
||||||
|
&& let Ok(value) = std::env::var("DCR_CXX")
|
||||||
|
{
|
||||||
|
let trimmed = value.trim();
|
||||||
|
if !trimmed.is_empty() {
|
||||||
|
return Some(trimmed.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Ok(value) = std::env::var("DCR_CC") {
|
||||||
|
let trimmed = value.trim();
|
||||||
|
if !trimmed.is_empty() {
|
||||||
|
return Some(trimmed.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toolchain_override_compiler(
|
||||||
|
lang: &str,
|
||||||
|
tc_cc: Option<&str>,
|
||||||
|
tc_cxx: Option<&str>,
|
||||||
|
tc_as: Option<&str>,
|
||||||
|
) -> Option<String> {
|
||||||
|
if lang == "asm" {
|
||||||
|
return tc_as.map(|v| v.to_string());
|
||||||
|
}
|
||||||
|
if (lang == "c++" || lang == "cpp" || lang == "cxx")
|
||||||
|
&& let Some(v) = tc_cxx
|
||||||
|
{
|
||||||
|
return Some(v.to_string());
|
||||||
|
}
|
||||||
|
tc_cc.map(|v| v.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_tool(env_key: &str, fallback: Option<&str>) -> Option<String> {
|
||||||
|
if let Ok(value) = std::env::var(env_key) {
|
||||||
|
let trimmed = value.trim();
|
||||||
|
if !trimmed.is_empty() {
|
||||||
|
return Some(trimmed.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fallback.map(|v| v.to_string())
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
|
|
||||||
if ctx.kind == "staticlib" {
|
if ctx.kind == "staticlib" {
|
||||||
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
||||||
let mut cmd = Command::new("ar");
|
let mut cmd = Command::new(ctx.archiver.unwrap_or("ar"));
|
||||||
cmd.arg("rcs").arg(&lib_path);
|
cmd.arg("rcs").arg(&lib_path);
|
||||||
for obj in &objects {
|
for obj in &objects {
|
||||||
cmd.arg(obj);
|
cmd.arg(obj);
|
||||||
@@ -33,7 +33,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cmd = Command::new(compiler);
|
let mut cmd = Command::new(ctx.linker.unwrap_or(compiler));
|
||||||
if ctx.kind == "sharedlib" {
|
if ctx.kind == "sharedlib" {
|
||||||
if cfg!(target_os = "macos") {
|
if cfg!(target_os = "macos") {
|
||||||
cmd.arg("-dynamiclib");
|
cmd.arg("-dynamiclib");
|
||||||
@@ -150,6 +150,9 @@ fn build_objects(
|
|||||||
if ctx.kind == "sharedlib" {
|
if ctx.kind == "sharedlib" {
|
||||||
cmd.arg("-fPIC");
|
cmd.arg("-fPIC");
|
||||||
}
|
}
|
||||||
|
if let Some(flag) = asm_lang_flag(source) {
|
||||||
|
cmd.arg("-x").arg(flag);
|
||||||
|
}
|
||||||
if let Some(platform) = ctx.platform
|
if let Some(platform) = ctx.platform
|
||||||
&& !platform.trim().is_empty()
|
&& !platform.trim().is_empty()
|
||||||
{
|
{
|
||||||
@@ -178,6 +181,15 @@ fn build_objects(
|
|||||||
Ok(objects)
|
Ok(objects)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn asm_lang_flag(source: &str) -> Option<&'static str> {
|
||||||
|
let ext = Path::new(source).extension().and_then(|v| v.to_str())?;
|
||||||
|
match ext {
|
||||||
|
"S" => Some("assembler-with-cpp"),
|
||||||
|
"s" | "asm" => Some("assembler"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn object_path(obj_dir: &Path, source: &str, obj_ext: &str) -> String {
|
fn object_path(obj_dir: &Path, source: &str, obj_ext: &str) -> String {
|
||||||
let src_path = Path::new(source);
|
let src_path = Path::new(source);
|
||||||
let rel = src_path
|
let rel = src_path
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
|
|
||||||
if ctx.kind == "staticlib" {
|
if ctx.kind == "staticlib" {
|
||||||
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
||||||
let mut cmd = Command::new(if cfg!(target_os = "windows") {
|
let archiver = ctx.archiver.unwrap_or(if cfg!(target_os = "windows") {
|
||||||
"lib"
|
"lib"
|
||||||
} else {
|
} else {
|
||||||
"ar"
|
"ar"
|
||||||
});
|
});
|
||||||
if cfg!(target_os = "windows") {
|
let mut cmd = Command::new(archiver);
|
||||||
|
if cfg!(target_os = "windows") && archiver == "lib" {
|
||||||
cmd.arg("/nologo").arg(format!("/OUT:{lib_path}"));
|
cmd.arg("/nologo").arg(format!("/OUT:{lib_path}"));
|
||||||
} else {
|
} else {
|
||||||
cmd.arg("rcs").arg(&lib_path);
|
cmd.arg("rcs").arg(&lib_path);
|
||||||
@@ -44,7 +45,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cmd = Command::new("cc");
|
let mut cmd = Command::new(ctx.linker.unwrap_or("cc"));
|
||||||
if ctx.kind == "sharedlib" {
|
if ctx.kind == "sharedlib" {
|
||||||
if cfg!(target_os = "macos") {
|
if cfg!(target_os = "macos") {
|
||||||
cmd.arg("-dynamiclib");
|
cmd.arg("-dynamiclib");
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
|
|
||||||
if ctx.kind == "staticlib" {
|
if ctx.kind == "staticlib" {
|
||||||
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
||||||
let mut cmd = Command::new("ar");
|
let mut cmd = Command::new(ctx.archiver.unwrap_or("ar"));
|
||||||
cmd.arg("rcs").arg(&lib_path);
|
cmd.arg("rcs").arg(&lib_path);
|
||||||
for obj in &objects {
|
for obj in &objects {
|
||||||
cmd.arg(obj);
|
cmd.arg(obj);
|
||||||
@@ -33,7 +33,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cmd = Command::new(compiler);
|
let mut cmd = Command::new(ctx.linker.unwrap_or(compiler));
|
||||||
if ctx.kind == "sharedlib" {
|
if ctx.kind == "sharedlib" {
|
||||||
if cfg!(target_os = "macos") {
|
if cfg!(target_os = "macos") {
|
||||||
cmd.arg("-dynamiclib");
|
cmd.arg("-dynamiclib");
|
||||||
@@ -150,6 +150,9 @@ fn build_objects(
|
|||||||
if ctx.kind == "sharedlib" {
|
if ctx.kind == "sharedlib" {
|
||||||
cmd.arg("-fPIC");
|
cmd.arg("-fPIC");
|
||||||
}
|
}
|
||||||
|
if let Some(flag) = asm_lang_flag(source) {
|
||||||
|
cmd.arg("-x").arg(flag);
|
||||||
|
}
|
||||||
if let Some(platform) = ctx.platform
|
if let Some(platform) = ctx.platform
|
||||||
&& !platform.trim().is_empty()
|
&& !platform.trim().is_empty()
|
||||||
{
|
{
|
||||||
@@ -178,6 +181,15 @@ fn build_objects(
|
|||||||
Ok(objects)
|
Ok(objects)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn asm_lang_flag(source: &str) -> Option<&'static str> {
|
||||||
|
let ext = Path::new(source).extension().and_then(|v| v.to_str())?;
|
||||||
|
match ext {
|
||||||
|
"S" => Some("assembler-with-cpp"),
|
||||||
|
"s" | "asm" => Some("assembler"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn object_path(obj_dir: &Path, source: &str, obj_ext: &str) -> String {
|
fn object_path(obj_dir: &Path, source: &str, obj_ext: &str) -> String {
|
||||||
let src_path = Path::new(source);
|
let src_path = Path::new(source);
|
||||||
let rel = src_path
|
let rel = src_path
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ pub struct BuildContext<'a> {
|
|||||||
pub target_dir: Option<&'a str>,
|
pub target_dir: Option<&'a str>,
|
||||||
pub kind: &'a str,
|
pub kind: &'a str,
|
||||||
pub platform: Option<&'a str>,
|
pub platform: Option<&'a str>,
|
||||||
|
pub linker: Option<&'a str>,
|
||||||
|
pub archiver: Option<&'a str>,
|
||||||
pub include_dirs: &'a [String],
|
pub include_dirs: &'a [String],
|
||||||
pub lib_dirs: &'a [String],
|
pub lib_dirs: &'a [String],
|
||||||
pub libs: &'a [String],
|
pub libs: &'a [String],
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
|
|
||||||
if ctx.kind == "staticlib" {
|
if ctx.kind == "staticlib" {
|
||||||
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
||||||
let mut cmd = Command::new("lib");
|
let mut cmd = Command::new(ctx.archiver.unwrap_or("lib"));
|
||||||
cmd.arg("/nologo").arg(format!("/OUT:{lib_path}"));
|
cmd.arg("/nologo").arg(format!("/OUT:{lib_path}"));
|
||||||
for obj in &objects {
|
for obj in &objects {
|
||||||
cmd.arg(obj);
|
cmd.arg(obj);
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
|
|
||||||
if ctx.kind == "staticlib" {
|
if ctx.kind == "staticlib" {
|
||||||
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
let lib_path = platform::lib_path(ctx.profile, ctx.project_name, ctx.target_dir);
|
||||||
let mut cmd = Command::new(if cfg!(target_os = "windows") {
|
let archiver = ctx.archiver.unwrap_or(if cfg!(target_os = "windows") {
|
||||||
"lib"
|
"lib"
|
||||||
} else {
|
} else {
|
||||||
"ar"
|
"ar"
|
||||||
});
|
});
|
||||||
if cfg!(target_os = "windows") {
|
let mut cmd = Command::new(archiver);
|
||||||
|
if cfg!(target_os = "windows") && archiver == "lib" {
|
||||||
cmd.arg("/nologo").arg(format!("/OUT:{lib_path}"));
|
cmd.arg("/nologo").arg(format!("/OUT:{lib_path}"));
|
||||||
} else {
|
} else {
|
||||||
cmd.arg("rcs").arg(&lib_path);
|
cmd.arg("rcs").arg(&lib_path);
|
||||||
@@ -44,8 +45,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let linker = "cc";
|
let mut cmd = Command::new(ctx.linker.unwrap_or("cc"));
|
||||||
let mut cmd = Command::new(linker);
|
|
||||||
if ctx.kind == "sharedlib" {
|
if ctx.kind == "sharedlib" {
|
||||||
if cfg!(target_os = "macos") {
|
if cfg!(target_os = "macos") {
|
||||||
cmd.arg("-dynamiclib");
|
cmd.arg("-dynamiclib");
|
||||||
|
|||||||
@@ -129,6 +129,15 @@ impl Config {
|
|||||||
{
|
{
|
||||||
return Err(ConfigError::Invalid("build.platform is empty".into()));
|
return Err(ConfigError::Invalid("build.platform is empty".into()));
|
||||||
}
|
}
|
||||||
|
if let Some(toolchain) = self.get("toolchain").and_then(|v| v.as_table()) {
|
||||||
|
for key in ["cc", "cxx", "as", "ar", "ld"] {
|
||||||
|
if let Some(v) = toolchain.get(key)
|
||||||
|
&& !v.as_str().map(|s| !s.trim().is_empty()).unwrap_or(false)
|
||||||
|
{
|
||||||
|
return Err(ConfigError::Invalid(format!("toolchain.{key} is invalid")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(kind) = build.get("kind").and_then(|v| v.as_str()) {
|
if let Some(kind) = build.get("kind").and_then(|v| v.as_str()) {
|
||||||
let kind = kind.trim();
|
let kind = kind.trim();
|
||||||
if kind != "bin" && kind != "staticlib" && kind != "sharedlib" {
|
if kind != "bin" && kind != "staticlib" && kind != "sharedlib" {
|
||||||
@@ -213,6 +222,7 @@ fn format_toml(value: &Value) -> Result<String, ConfigError> {
|
|||||||
.get("dependencies")
|
.get("dependencies")
|
||||||
.and_then(|v| v.as_table())
|
.and_then(|v| v.as_table())
|
||||||
.ok_or_else(|| ConfigError::Invalid("missing [dependencies]".into()))?;
|
.ok_or_else(|| ConfigError::Invalid("missing [dependencies]".into()))?;
|
||||||
|
let toolchain = root.get("toolchain").and_then(|v| v.as_table());
|
||||||
|
|
||||||
let name = package.get("name").and_then(|v| v.as_str()).unwrap_or("");
|
let name = package.get("name").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
let version = package
|
let version = package
|
||||||
@@ -251,6 +261,24 @@ fn format_toml(value: &Value) -> Result<String, ConfigError> {
|
|||||||
}
|
}
|
||||||
out.push('\n');
|
out.push('\n');
|
||||||
|
|
||||||
|
if let Some(toolchain) = toolchain {
|
||||||
|
let mut lines = Vec::new();
|
||||||
|
for key in ["cc", "cxx", "as", "ar", "ld"] {
|
||||||
|
if let Some(value) = toolchain.get(key).and_then(|v| v.as_str())
|
||||||
|
&& !value.trim().is_empty()
|
||||||
|
{
|
||||||
|
lines.push(format!("{key} = \"{value}\""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !lines.is_empty() {
|
||||||
|
out.push_str("[toolchain]\n");
|
||||||
|
for line in lines {
|
||||||
|
out.push_str(&format!("{line}\n"));
|
||||||
|
}
|
||||||
|
out.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out.push_str("[dependencies]\n");
|
out.push_str("[dependencies]\n");
|
||||||
if !deps.is_empty() {
|
if !deps.is_empty() {
|
||||||
let mut keys: Vec<&String> = deps.keys().collect();
|
let mut keys: Vec<&String> = deps.keys().collect();
|
||||||
|
|||||||
Reference in New Issue
Block a user