use std::fs;
use std::path::PathBuf;
use crate::utils::{
get_project_app_dir,
COMPILED_LIBS_DIR_NAME
};
const BUILD_FILE_NAME: &str = "build.rs";
pub fn write_build_configuration(proj_path: &PathBuf, lib_names: &Vec<String>) -> Result<(), String> {
let build_file = proj_path.join(BUILD_FILE_NAME);
let libs_dir = get_project_app_dir(proj_path)?.join(COMPILED_LIBS_DIR_NAME);
match fs::write(build_file, get_build_content(&libs_dir, lib_names)) {
Ok(_) => (),
Err(_) => {
return Err(String::from("Failed to write build.rs file."));
}
};
Ok(())
}
fn get_build_content(lib_dir: &PathBuf, lib_names: &Vec<String>) -> String {
let mut content = String::from("fn main() {\n");
content += format!(" println!(\"cargo:rustc-link-search=native={}\");\n", lib_dir.display()).as_str();
content += format!(" println!(\"cargo:rustc-link-arg={}/wrapper.cpp.o\");", lib_dir.display()).as_str();
for name in lib_names {
content += format!("\n println!(\"cargo:rustc-link-arg=-l{}\");", name).as_str();
}
content += "\n println!(\"cargo:rustc-link-arg=-lc\");";
content += "\n println!(\"cargo:rustc-link-arg=-lm\");";
content += "\n println!(\"cargo:rustc-link-arg=-lgcc\");";
content += "\n}";
content
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
use std::fs;
#[test]
fn test_get_build_content_empty_libs() {
let lib_dir = PathBuf::from("/mock/built_libs");
let lib_names = vec![];
let content = get_build_content(&lib_dir, &lib_names);
assert!(content.contains(&format!("cargo:rustc-link-search=native={}", lib_dir.display())));
assert!(content.contains(&format!("cargo:rustc-link-arg={}/wrapper.cpp.o", lib_dir.display())));
assert!(content.contains("cargo:rustc-link-arg=-lc"));
assert!(content.contains("cargo:rustc-link-arg=-lm"));
assert!(content.contains("cargo:rustc-link-arg=-lgcc"));
}
#[test]
fn test_get_build_content_with_libs() {
let lib_dir = PathBuf::from("/mock/built_libs");
let lib_names = vec!["FrameworkArduino".to_string(), "Wire".to_string()];
let content = get_build_content(&lib_dir, &lib_names);
assert!(content.contains("cargo:rustc-link-arg=-lFrameworkArduino"));
assert!(content.contains("cargo:rustc-link-arg=-lWire"));
assert!(content.contains("cargo:rustc-link-arg=-lc"));
}
#[test]
fn test_write_build_configuration_success() {
let temp_dir = tempdir().unwrap();
let proj_path = temp_dir.path().to_path_buf();
let lib_names = vec!["custom_lib".to_string()];
let result = write_build_configuration(&proj_path, &lib_names);
assert!(result.is_ok());
let build_file_path = proj_path.join(BUILD_FILE_NAME);
assert!(build_file_path.exists());
let content = fs::read_to_string(build_file_path).expect("Could not read generated build.rs");
assert!(content.contains("cargo:rustc-link-arg=-lcustom_lib"));
assert!(proj_path.join(crate::utils::PROJECT_APP_DIR_NAME).exists());
}
#[test]
fn test_write_build_configuration_failure() {
let proj_path = PathBuf::from("/invalid/path/that/does/not/exist");
let lib_names = vec!["custom_lib".to_string()];
let result = write_build_configuration(&proj_path, &lib_names);
assert!(result.is_err());
}
}