add change to hash and build to hash and build each file independently
This commit is contained in:
101
src/app.rs
101
src/app.rs
@@ -248,53 +248,87 @@ fn build(mode: &Option<String>, force_recompile: bool) -> std::io::Result<()> {
|
|||||||
|
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
std::fs::create_dir_all(format!("target/{}", build_config.name))?;
|
let obj_dir = format!("target/{}/obj", build_config.name);
|
||||||
|
|
||||||
let hash = hash_src_tree()?;
|
std::fs::create_dir_all(&obj_dir)?;
|
||||||
|
|
||||||
let old_compute_path = PathBuf::from(format!("target/{}/.build_hash", build_config.name));
|
let compiler = conf.compiler.as_deref().unwrap_or("gcc");
|
||||||
|
|
||||||
if old_compute_path.exists() && !force_recompile {
|
let source_files: Vec<PathBuf> = glob("src/*.c")
|
||||||
let text = std::fs::read_to_string(old_compute_path)?;
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, format!("{e}")))?
|
||||||
|
.filter_map(|e| e.ok())
|
||||||
|
.collect();
|
||||||
|
|
||||||
if hash.trim() == text.trim() {
|
let mut any_changed = false;
|
||||||
|
|
||||||
|
for src in &source_files {
|
||||||
|
let stem = src.file_stem().unwrap().to_string_lossy();
|
||||||
|
let obj_path = format!("{}/{}.o", obj_dir, stem);
|
||||||
|
let hash_path = format!("{}/{}.c.hash", obj_dir, stem);
|
||||||
|
|
||||||
|
let hash = hash_file(src)?;
|
||||||
|
|
||||||
|
let needs_compile = force_recompile
|
||||||
|
|| match std::fs::read_to_string(&hash_path) {
|
||||||
|
Ok(old) => old.trim() != hash.trim(),
|
||||||
|
Err(_) => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if needs_compile {
|
||||||
|
println!(" {} {}", "Compiling".green().bold(), src.display());
|
||||||
|
|
||||||
|
let status = Command::new(compiler)
|
||||||
|
.args(&build_config.args)
|
||||||
|
.arg("-c")
|
||||||
|
.arg(src)
|
||||||
|
.arg("-o")
|
||||||
|
.arg(&obj_path)
|
||||||
|
.status()?;
|
||||||
|
|
||||||
|
if !status.success() {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
format!("failed to compile {}", src.display()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fs::write(&hash_path, &hash)?;
|
||||||
|
any_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let binary = format!("target/{}/{}", build_config.name, conf.name);
|
||||||
|
let binary_exists = PathBuf::from(&binary).exists();
|
||||||
|
|
||||||
|
if !any_changed && binary_exists {
|
||||||
println!(
|
println!(
|
||||||
" {} (code not changed, recompile not made)",
|
" {} (code not changed, recompile not made)",
|
||||||
"Finished".green().bold()
|
"Finished".green().bold()
|
||||||
);
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut command = Command::new(conf.compiler.as_deref().unwrap_or("gcc"));
|
let obj_files: Vec<String> = source_files
|
||||||
|
.iter()
|
||||||
|
.map(|src| {
|
||||||
|
let stem = src.file_stem().unwrap().to_string_lossy();
|
||||||
|
format!("{}/{}.o", obj_dir, stem)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
for arg in &build_config.args {
|
let status = Command::new(compiler)
|
||||||
command.arg(arg);
|
.args(&obj_files)
|
||||||
}
|
|
||||||
|
|
||||||
for entry in glob("src/*.c")
|
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, format!("{e}").as_str()))?
|
|
||||||
{
|
|
||||||
if let Ok(path) = entry {
|
|
||||||
command.arg(path.to_string_lossy().to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
command
|
|
||||||
.arg("-o")
|
.arg("-o")
|
||||||
.arg(format!("target/{}/{}", build_config.name, conf.name));
|
.arg(&binary)
|
||||||
|
.status()?;
|
||||||
let status = command.status()?;
|
|
||||||
|
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
return Err(std::io::Error::new(
|
return Err(std::io::Error::new(
|
||||||
std::io::ErrorKind::Other,
|
std::io::ErrorKind::Other,
|
||||||
format!("compiler exited with status {status}"),
|
"linking failed",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fs::write(format!("target/{}/.build_hash", build_config.name), hash)?;
|
|
||||||
|
|
||||||
let stop = start.elapsed();
|
let stop = start.elapsed();
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
@@ -308,16 +342,9 @@ fn build(mode: &Option<String>, force_recompile: bool) -> std::io::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_src_tree() -> std::io::Result<String> {
|
fn hash_file(path: &Path) -> std::io::Result<String> {
|
||||||
let mut hashes = String::new();
|
let contents = std::fs::read_to_string(path)?;
|
||||||
for entry in glob("src/**/*").expect("a valid glob pattern") {
|
Ok(sha256::digest(contents))
|
||||||
if let Ok(file) = entry {
|
|
||||||
let text = std::fs::read_to_string(file)?;
|
|
||||||
let hash = sha256::digest(text);
|
|
||||||
hashes.push_str(hash.as_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(sha256::digest(hashes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(mode: &Option<String>, args: Option<Vec<String>>) -> std::io::Result<()> {
|
fn run(mode: &Option<String>, args: Option<Vec<String>>) -> std::io::Result<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user