mirror of
https://github.com/dexoron/dcr.git
synced 2026-10-21 14:48:30 +00:00
Implement incremental linking and add DragonFly BSD VM build
This commit is contained in:
19
.github/workflows/release.yml
vendored
19
.github/workflows/release.yml
vendored
@@ -360,7 +360,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
system: [freebsd, openbsd, netbsd]
|
system: [freebsd, openbsd, netbsd, dragonfly]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -428,6 +428,23 @@ jobs:
|
|||||||
cp target/release/dcr "$ASSET"
|
cp target/release/dcr "$ASSET"
|
||||||
echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV"
|
echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
# --- DRAGONFLYBSD ---
|
||||||
|
- name: Build in DragonFly BSD VM
|
||||||
|
if: matrix.system == 'dragonfly'
|
||||||
|
uses: vmactions/dragonflybsd-vm@v1
|
||||||
|
with:
|
||||||
|
usesh: true
|
||||||
|
run: |
|
||||||
|
pkg install -y rust perl5 gmake
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
- name: Prepare DragonFly BSD Artifact
|
||||||
|
if: matrix.system == 'dragonfly'
|
||||||
|
run: |
|
||||||
|
ASSET="dcr-x86_64-unknown-dragonfly-${{ needs.setup.outputs.version }}"
|
||||||
|
cp target/release/dcr "$ASSET"
|
||||||
|
echo "BSD_ASSET=${ASSET}" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
# --- UPLOAD TARGET ---
|
# --- UPLOAD TARGET ---
|
||||||
- name: Upload BSD Asset to Release
|
- name: Upload BSD Asset to Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
|
|||||||
@@ -316,6 +316,31 @@ pub fn needs_rebuild(source: &str, object: &str) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn needs_link(objects: &[String], output_path: &str) -> bool {
|
||||||
|
let out_meta = match fs::metadata(output_path) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(_) => return true,
|
||||||
|
};
|
||||||
|
let out_time = match out_meta.modified() {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(_) => return true,
|
||||||
|
};
|
||||||
|
for obj in objects {
|
||||||
|
let obj_meta = match fs::metadata(obj) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(_) => return true,
|
||||||
|
};
|
||||||
|
let obj_time = match obj_meta.modified() {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(_) => return true,
|
||||||
|
};
|
||||||
|
if obj_time > out_time {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_d_file(content: &str) -> Vec<String> {
|
fn parse_d_file(content: &str) -> Vec<String> {
|
||||||
let mut deps = Vec::new();
|
let mut deps = Vec::new();
|
||||||
let text = content.replace("\\\n", " ").replace("\\\r\n", " ");
|
let text = content.replace("\\\n", " ").replace("\\\r\n", " ");
|
||||||
@@ -418,6 +443,55 @@ mod tests {
|
|||||||
assert_eq!(result, "target/debug/obj/main.c.obj");
|
assert_eq!(result, "target/debug/obj/main.c.obj");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn needs_link_no_output() {
|
||||||
|
let dir = temp_dir("link_no_out");
|
||||||
|
let obj1 = dir.join("test1.o");
|
||||||
|
let obj2 = dir.join("test2.o");
|
||||||
|
let out = dir.join("app");
|
||||||
|
fs::write(&obj1, "").unwrap();
|
||||||
|
fs::write(&obj2, "").unwrap();
|
||||||
|
let objs = vec![
|
||||||
|
obj1.to_string_lossy().to_string(),
|
||||||
|
obj2.to_string_lossy().to_string(),
|
||||||
|
];
|
||||||
|
assert!(needs_link(&objs, &out.to_string_lossy()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn needs_link_fresh() {
|
||||||
|
let dir = temp_dir("link_fresh");
|
||||||
|
let obj1 = dir.join("test1.o");
|
||||||
|
let obj2 = dir.join("test2.o");
|
||||||
|
let out = dir.join("app");
|
||||||
|
fs::write(&obj1, "").unwrap();
|
||||||
|
fs::write(&obj2, "").unwrap();
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
|
fs::write(&out, "").unwrap();
|
||||||
|
let objs = vec![
|
||||||
|
obj1.to_string_lossy().to_string(),
|
||||||
|
obj2.to_string_lossy().to_string(),
|
||||||
|
];
|
||||||
|
assert!(!needs_link(&objs, &out.to_string_lossy()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn needs_link_stale() {
|
||||||
|
let dir = temp_dir("link_stale");
|
||||||
|
let obj1 = dir.join("test1.o");
|
||||||
|
let obj2 = dir.join("test2.o");
|
||||||
|
let out = dir.join("app");
|
||||||
|
fs::write(&obj1, "").unwrap();
|
||||||
|
fs::write(&out, "").unwrap();
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
|
fs::write(&obj2, "").unwrap();
|
||||||
|
let objs = vec![
|
||||||
|
obj1.to_string_lossy().to_string(),
|
||||||
|
obj2.to_string_lossy().to_string(),
|
||||||
|
];
|
||||||
|
assert!(needs_link(&objs, &out.to_string_lossy()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn needs_rebuild_no_object() {
|
fn needs_rebuild_no_object() {
|
||||||
let dir = temp_dir("rebuild_no_obj");
|
let dir = temp_dir("rebuild_no_obj");
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ 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);
|
||||||
|
if !common::needs_link(&objects, &lib_path) {
|
||||||
|
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||||
|
return Ok(elapsed);
|
||||||
|
}
|
||||||
let archiver = ctx.archiver.unwrap_or(if cfg!(target_os = "windows") {
|
let archiver = ctx.archiver.unwrap_or(if cfg!(target_os = "windows") {
|
||||||
"lib"
|
"lib"
|
||||||
} else {
|
} else {
|
||||||
@@ -105,6 +109,11 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
} else {
|
} else {
|
||||||
platform::bin_path(ctx.profile, &final_name, ctx.target_dir)
|
platform::bin_path(ctx.profile, &final_name, ctx.target_dir)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !common::needs_link(&objects, &out_path) {
|
||||||
|
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||||
|
return Ok(elapsed);
|
||||||
|
}
|
||||||
cmd.arg("-o").arg(out_path);
|
cmd.arg("-o").arg(out_path);
|
||||||
|
|
||||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ 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);
|
||||||
|
if !common::needs_link(&objects, &lib_path) {
|
||||||
|
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||||
|
return Ok(elapsed);
|
||||||
|
}
|
||||||
let mut cmd = Command::new(ctx.archiver.unwrap_or("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 {
|
||||||
@@ -117,6 +121,11 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
} else {
|
} else {
|
||||||
platform::bin_path(ctx.profile, ctx.project_name, ctx.target_dir)
|
platform::bin_path(ctx.profile, ctx.project_name, ctx.target_dir)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !common::needs_link(&objects, &out_path) {
|
||||||
|
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||||
|
return Ok(elapsed);
|
||||||
|
}
|
||||||
cmd.arg(format!("/Fe:{out_path}"));
|
cmd.arg(format!("/Fe:{out_path}"));
|
||||||
|
|
||||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ 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);
|
||||||
|
if !common::needs_link(&objects, &lib_path) {
|
||||||
|
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||||
|
return Ok(elapsed);
|
||||||
|
}
|
||||||
let archiver = ctx.archiver.unwrap_or(if cfg!(target_os = "windows") {
|
let archiver = ctx.archiver.unwrap_or(if cfg!(target_os = "windows") {
|
||||||
"lib"
|
"lib"
|
||||||
} else {
|
} else {
|
||||||
@@ -105,6 +109,11 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
} else {
|
} else {
|
||||||
platform::bin_path(ctx.profile, &final_name, ctx.target_dir)
|
platform::bin_path(ctx.profile, &final_name, ctx.target_dir)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !common::needs_link(&objects, &out_path) {
|
||||||
|
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||||
|
return Ok(elapsed);
|
||||||
|
}
|
||||||
cmd.arg("-o").arg(out_path);
|
cmd.arg("-o").arg(out_path);
|
||||||
|
|
||||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ 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);
|
||||||
|
if !common::needs_link(&objects, &lib_path) {
|
||||||
|
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||||
|
return Ok(elapsed);
|
||||||
|
}
|
||||||
let mut cmd = Command::new(ctx.archiver.unwrap_or("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 {
|
||||||
@@ -106,6 +110,11 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
|||||||
} else {
|
} else {
|
||||||
platform::bin_path(ctx.profile, &final_name, ctx.target_dir)
|
platform::bin_path(ctx.profile, &final_name, ctx.target_dir)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !common::needs_link(&objects, &out_path) {
|
||||||
|
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||||
|
return Ok(elapsed);
|
||||||
|
}
|
||||||
cmd.arg("-o").arg(out_path);
|
cmd.arg("-o").arg(out_path);
|
||||||
|
|
||||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||||
|
|||||||
Reference in New Issue
Block a user