From e6025a1b86f80dc4e67637bcf1c8d2b221200da5 Mon Sep 17 00:00:00 2001 From: Yonas Jongkind Date: Sat, 11 Apr 2020 18:03:01 -0700 Subject: [PATCH 1/8] Add a build.rs to replace/supplant the Makefile. This way cargo can build without any manual steps (running make). One mystery is that newlines are not showing up in the generated files. lib.rs is just a stub required by Cargo.toml that is over-written. --- .gitignore | 1 - Cargo.toml | 10 ++++++- build.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 build.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore index 99966711..ba99d3b5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ **/*.rs.bk Cargo.lock svd/esp32.svd -src/ diff --git a/Cargo.toml b/Cargo.toml index c2048e99..e6141f0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,4 +21,12 @@ license = "MIT OR Apache-2.0" [dependencies] bare-metal = "0.2" -vcell = "0.1" \ No newline at end of file +vcell = "0.1" + +[build-dependencies] +form = "0.7.0" +svd2rust = "0.17" +fmt = "0.1.0" +log = "0.4.1" +env_logger = "0.6" +failure = "0.1.1" \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 00000000..355d63f7 --- /dev/null +++ b/build.rs @@ -0,0 +1,84 @@ +// OUTPUT=esp32.svd +// BASE=esp32.base.svd +// +// all: clean patch generate form fmt build +// +// clean: +// rm -rf src/ +// +// patch: +// rm -f svd/$(OUTPUT) +// svd patch svd/patches/esp32.yaml +// mv svd/$(BASE).patched svd/$(OUTPUT) +// +// generate: +// svd2rust --target none -i svd/$(OUTPUT) +// +// form: +// form -i lib.rs -o src/ +// rm lib.rs +// +// fmt: +// cargo fmt +// +// build: +// cargo clean +// cargo build +use std::process::Command; +use std::fs; +use std::path::Path; +use std::fs::File; +use std::io::{Read, Write as IoWrite}; +use std::fmt::Write; + +fn svd2rust(svd_path:&str) -> std::io::Result { + let mut svd_xml = String::new(); + File::open(svd_path)?.read_to_string(&mut svd_xml)?; + let generated = svd2rust::generate(svd_xml.as_str(), svd2rust::Target::None, false).unwrap(); + + let mut file = File::create("svd/esp32.svd.rs").expect("Couldn't create lib.rs file"); + let mut data = String::new(); + write!(data, "{}", generated.lib_rs).expect("Could not output code"); + + let newlined = data.replace("] ", "]\n"); + file.write_all(newlined.as_ref()).expect("Could not write code to lib.rs"); + + Ok(newlined) +} + +// Example custom build script. +fn main() -> std::io::Result<()> { + // Tell Cargo that if the given file changes, to rerun this build script. + let svd = "svd/esp32.base.svd"; + let svd_patched = "svd/esp32.base.svd.patched"; + let yaml = "svd/patches/esp32.yaml"; + let svd_final = "svd/esp32.svd"; + + println!("cargo:rerun-if-changed={}", svd); + println!("cargo:rerun-if-changed={}", svd_patched); + println!("cargo:rerun-if-changed={}", yaml); + + // Delete the output if it exists. + if Path::new(svd_patched).exists() { + fs::remove_file(svd_patched)?; + } + + println!("Patching SVD {} -> {}", svd, svd_final); + // generate patched file. + Command::new("svd").arg("patch").arg(yaml) + .output() + .expect("failed to run svd tool. This is a python tool that should have been installed via: pip3 install --upgrade --user svdtools"); + fs::copy(svd_patched, svd_final)?; + + println!("Generating rust source from AVD"); + let rs = svd2rust(svd_final)?; + + // convert it into the rust form. + println!("Converting sources into commonly accepted rust format."); + if form::create_directory_structure("src", rs).is_err() { + println!("Unable to convert to common rust format."); + } + + Ok(()) + +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..761fc446 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +// Just a placeholder. Will be over-written by build.sh when you run cargo build \ No newline at end of file From daed5f2f7fd20026ddd94176e26d1fdfabb3ec4c Mon Sep 17 00:00:00 2001 From: Yonas Jongkind Date: Sat, 11 Apr 2020 19:03:09 -0700 Subject: [PATCH 2/8] Added .gitingnore and call to cargo format. --- build.rs | 20 +++++++++++++------- src/.gitignore | 25 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 src/.gitignore diff --git a/build.rs b/build.rs index 355d63f7..1ee862a8 100644 --- a/build.rs +++ b/build.rs @@ -24,14 +24,14 @@ // build: // cargo clean // cargo build -use std::process::Command; +use std::fmt::Write; use std::fs; -use std::path::Path; use std::fs::File; use std::io::{Read, Write as IoWrite}; -use std::fmt::Write; +use std::path::Path; +use std::process::Command; -fn svd2rust(svd_path:&str) -> std::io::Result { +fn svd2rust(svd_path: &str) -> std::io::Result { let mut svd_xml = String::new(); File::open(svd_path)?.read_to_string(&mut svd_xml)?; let generated = svd2rust::generate(svd_xml.as_str(), svd2rust::Target::None, false).unwrap(); @@ -41,7 +41,8 @@ fn svd2rust(svd_path:&str) -> std::io::Result { write!(data, "{}", generated.lib_rs).expect("Could not output code"); let newlined = data.replace("] ", "]\n"); - file.write_all(newlined.as_ref()).expect("Could not write code to lib.rs"); + file.write_all(newlined.as_ref()) + .expect("Could not write code to lib.rs"); Ok(newlined) } @@ -79,6 +80,11 @@ fn main() -> std::io::Result<()> { println!("Unable to convert to common rust format."); } - Ok(()) + println!("Formatting rust source files."); + Command::new("cargo") + .arg("format") + .output() + .expect("failed to run cargo format"); -} \ No newline at end of file + Ok(()) +} diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 00000000..d25b5d23 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,25 @@ +/*.rs +/hinf +/i2c +/i2s +/io_mux +/ledc +/mcpwm +/pcnt +/rmt +/rtc_i2c +/rtccntl +/rtcio +/sens +/slc +/slchost +/spi +/syscon +/timg +/uart +/uhci +/apb_ctrl +/dport +/efuse +/gpio +/gpio_sd From 54a3a7f36d9d2c9066f7d3cc721fe99cc770b177 Mon Sep 17 00:00:00 2001 From: Yonas Jongkind Date: Sat, 11 Apr 2020 19:14:02 -0700 Subject: [PATCH 3/8] Cleaned up the output, and removed dependencies on files that should not be there, so it does not compile as often. --- build.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/build.rs b/build.rs index 1ee862a8..73b1f7dc 100644 --- a/build.rs +++ b/build.rs @@ -56,31 +56,29 @@ fn main() -> std::io::Result<()> { let svd_final = "svd/esp32.svd"; println!("cargo:rerun-if-changed={}", svd); - println!("cargo:rerun-if-changed={}", svd_patched); - println!("cargo:rerun-if-changed={}", yaml); // Delete the output if it exists. if Path::new(svd_patched).exists() { fs::remove_file(svd_patched)?; } - println!("Patching SVD {} -> {}", svd, svd_final); + // println!("Patching SVD {} -> {}", svd, svd_final); // generate patched file. Command::new("svd").arg("patch").arg(yaml) .output() .expect("failed to run svd tool. This is a python tool that should have been installed via: pip3 install --upgrade --user svdtools"); fs::copy(svd_patched, svd_final)?; - println!("Generating rust source from AVD"); + // println!("Generating rust source from AVD"); let rs = svd2rust(svd_final)?; // convert it into the rust form. - println!("Converting sources into commonly accepted rust format."); + // println!("Converting sources into commonly accepted rust format."); if form::create_directory_structure("src", rs).is_err() { println!("Unable to convert to common rust format."); } - println!("Formatting rust source files."); + // println!("Formatting rust source files."); Command::new("cargo") .arg("format") .output() From 1252b24965451026dcac48ff1e78e2a714a6c0eb Mon Sep 17 00:00:00 2001 From: Yonas Jongkind Date: Sat, 11 Apr 2020 19:19:01 -0700 Subject: [PATCH 4/8] Corrected call to cargo fmt --- build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 73b1f7dc..10656240 100644 --- a/build.rs +++ b/build.rs @@ -80,7 +80,7 @@ fn main() -> std::io::Result<()> { // println!("Formatting rust source files."); Command::new("cargo") - .arg("format") + .arg("fmt") .output() .expect("failed to run cargo format"); From bb696d94592de64352052f6e27ee90580b3f5974 Mon Sep 17 00:00:00 2001 From: Yonas Jongkind Date: Sat, 11 Apr 2020 19:41:31 -0700 Subject: [PATCH 5/8] Added gaurd code to reduce build frequency. --- build.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.rs b/build.rs index 10656240..fca21b5f 100644 --- a/build.rs +++ b/build.rs @@ -54,7 +54,17 @@ fn main() -> std::io::Result<()> { let svd_patched = "svd/esp32.base.svd.patched"; let yaml = "svd/patches/esp32.yaml"; let svd_final = "svd/esp32.svd"; + let generate_file_sample = "src/gpio.rs"; + if Path::new(generate_file_sample).exists() { + let in_m = fs::metadata("svd/esp32.base.svd")?; + let out_m = fs::metadata(generate_file_sample)?; + if in_m.modified()? < out_m.modified()? { + println!("No need for changes."); + return Ok(()); + } + + } println!("cargo:rerun-if-changed={}", svd); // Delete the output if it exists. From 489621897003ab7faa88a29ee675287ae4d0df5b Mon Sep 17 00:00:00 2001 From: Yonas Jongkind Date: Sat, 11 Apr 2020 19:52:29 -0700 Subject: [PATCH 6/8] Version that works well. Doesn't run too often anymore, and correctly formats the code. --- build.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.rs b/build.rs index fca21b5f..b8864378 100644 --- a/build.rs +++ b/build.rs @@ -56,23 +56,23 @@ fn main() -> std::io::Result<()> { let svd_final = "svd/esp32.svd"; let generate_file_sample = "src/gpio.rs"; + println!("cargo:rerun-if-changed={}", svd); + if Path::new(generate_file_sample).exists() { let in_m = fs::metadata("svd/esp32.base.svd")?; let out_m = fs::metadata(generate_file_sample)?; if in_m.modified()? < out_m.modified()? { - println!("No need for changes."); + println!("src/* files newer than {}, skipping any regeneration.", svd); return Ok(()); } - } - println!("cargo:rerun-if-changed={}", svd); // Delete the output if it exists. if Path::new(svd_patched).exists() { fs::remove_file(svd_patched)?; } - // println!("Patching SVD {} -> {}", svd, svd_final); + println!("Patching SVD {} -> {}", svd, svd_final); // generate patched file. Command::new("svd").arg("patch").arg(yaml) .output() @@ -83,12 +83,12 @@ fn main() -> std::io::Result<()> { let rs = svd2rust(svd_final)?; // convert it into the rust form. - // println!("Converting sources into commonly accepted rust format."); + println!("Converting sources into commonly accepted rust format."); if form::create_directory_structure("src", rs).is_err() { println!("Unable to convert to common rust format."); } - // println!("Formatting rust source files."); + println!("Formatting rust source files."); Command::new("cargo") .arg("fmt") .output() From ec94a332e3810c877febe1e9b04809aa862fdfd1 Mon Sep 17 00:00:00 2001 From: Yonas Jongkind Date: Tue, 21 Apr 2020 10:46:31 -0700 Subject: [PATCH 7/8] Updated to also tell git to ignore the over-written file. --- build.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.rs b/build.rs index b8864378..35518abf 100644 --- a/build.rs +++ b/build.rs @@ -94,5 +94,13 @@ fn main() -> std::io::Result<()> { .output() .expect("failed to run cargo format"); + // Tell git to ignore changes to the generated src/lib.rs + Command::new("git") + .arg("update-index") + .arg("--assume-unchanged") + .arg("src/lib.rs") + .output() + .expect("failed to suppress change notification on generated lib.rs"); + Ok(()) } From 91ae13bfa544ca5a145ff88aaa0cf0d6f3ca5b8e Mon Sep 17 00:00:00 2001 From: Yonas Jongkind Date: Wed, 29 Apr 2020 13:29:59 -0700 Subject: [PATCH 8/8] Added to the script some code to clean up some no-longer-supported linker warnings produced by svd2rust. --- .gitignore | 3 ++ Cargo.toml | 13 ++++---- build.rs | 93 ++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 69 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index ba99d3b5..b3f34e19 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ **/*.rs.bk Cargo.lock svd/esp32.svd +svd/esp32.base.svd.patched +svd/esp32.svd.rs +.cargo/config diff --git a/Cargo.toml b/Cargo.toml index e6141f0a..792c31b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,9 +24,10 @@ bare-metal = "0.2" vcell = "0.1" [build-dependencies] -form = "0.7.0" -svd2rust = "0.17" -fmt = "0.1.0" -log = "0.4.1" -env_logger = "0.6" -failure = "0.1.1" \ No newline at end of file +form = "^0" +svd2rust = "^0" +fmt = "^0" +log = "^0" +env_logger = "^0" +failure = "^0" +ex = "^0" \ No newline at end of file diff --git a/build.rs b/build.rs index 35518abf..ed5e5bfc 100644 --- a/build.rs +++ b/build.rs @@ -24,16 +24,16 @@ // build: // cargo clean // cargo build -use std::fmt::Write; -use std::fs; -use std::fs::File; -use std::io::{Read, Write as IoWrite}; -use std::path::Path; -use std::process::Command; - -fn svd2rust(svd_path: &str) -> std::io::Result { +use ex::{fs, fs::File}; +use std::{env, + fmt::Write, + io::{Read, Write as IoWrite}, + path::Path, + process::Command}; + +fn svd2rust(svd_path: &str) -> ex::io::Result { let mut svd_xml = String::new(); - File::open(svd_path)?.read_to_string(&mut svd_xml)?; + File::open(svd_path)?.read_to_string(&mut svd_xml).unwrap(); let generated = svd2rust::generate(svd_xml.as_str(), svd2rust::Target::None, false).unwrap(); let mut file = File::create("svd/esp32.svd.rs").expect("Couldn't create lib.rs file"); @@ -41,24 +41,36 @@ fn svd2rust(svd_path: &str) -> std::io::Result { write!(data, "{}", generated.lib_rs).expect("Could not output code"); let newlined = data.replace("] ", "]\n"); - file.write_all(newlined.as_ref()) - .expect("Could not write code to lib.rs"); + file.write_all(newlined.as_ref()).expect("Could not write code to lib.rs"); Ok(newlined) } // Example custom build script. -fn main() -> std::io::Result<()> { +fn main() -> ex::io::Result<()> { + println!("BEGIN generate_bindings_from_build_rs: {:?}", std::env::current_exe().unwrap()); + if env::var("CARGO_MANIFEST_DIR").is_err() { + env::set_var("CARGO_MANIFEST_DIR", env::current_dir().unwrap().to_str().unwrap()); + } + let base_dir: String = env::var("CARGO_MANIFEST_DIR").unwrap(); + // Tell Cargo that if the given file changes, to rerun this build script. - let svd = "svd/esp32.base.svd"; - let svd_patched = "svd/esp32.base.svd.patched"; - let yaml = "svd/patches/esp32.yaml"; - let svd_final = "svd/esp32.svd"; - let generate_file_sample = "src/gpio.rs"; + let svd = format!("{}/svd/esp32.base.svd", base_dir); + let svd_patched = format!("{}/svd/esp32.base.svd.patched", base_dir); + let yaml = format!("{}/svd/patches/esp32.yaml", base_dir); + let svd_final = format!("{}/svd/esp32.svd", base_dir); + let generate_file_sample = format!("{}/src/gpio.rs", base_dir); + let lib_rs = format!("{}/src/lib.rs", base_dir); println!("cargo:rerun-if-changed={}", svd); + println!("cargo:rerun-if-changed={}", svd_patched); + println!("cargo:rerun-if-changed={}", yaml); + println!("cargo:rerun-if-changed={}", svd_final); + println!("cargo:rerun-if-changed=build.rs"); - if Path::new(generate_file_sample).exists() { + println!("cargo:rerun-if-changed={}", svd); + + if Path::new(generate_file_sample.as_str()).exists() { let in_m = fs::metadata("svd/esp32.base.svd")?; let out_m = fs::metadata(generate_file_sample)?; if in_m.modified()? < out_m.modified()? { @@ -68,8 +80,8 @@ fn main() -> std::io::Result<()> { } // Delete the output if it exists. - if Path::new(svd_patched).exists() { - fs::remove_file(svd_patched)?; + if Path::new(&svd_patched).exists() { + fs::remove_file(&svd_patched)?; } println!("Patching SVD {} -> {}", svd, svd_final); @@ -77,10 +89,10 @@ fn main() -> std::io::Result<()> { Command::new("svd").arg("patch").arg(yaml) .output() .expect("failed to run svd tool. This is a python tool that should have been installed via: pip3 install --upgrade --user svdtools"); - fs::copy(svd_patched, svd_final)?; + fs::copy(&svd_patched, &svd_final)?; // println!("Generating rust source from AVD"); - let rs = svd2rust(svd_final)?; + let rs = svd2rust(&svd_final)?; // convert it into the rust form. println!("Converting sources into commonly accepted rust format."); @@ -89,18 +101,31 @@ fn main() -> std::io::Result<()> { } println!("Formatting rust source files."); - Command::new("cargo") - .arg("fmt") - .output() - .expect("failed to run cargo format"); + Command::new("cargo").arg("fmt").output().expect("failed to run cargo format"); + + println!("Cleaning up some lint warnings that are no longer supported in generated cdde."); + clean_up_some_lint_warnings_in_the_generated_code(&lib_rs)?; + + // Tell git to ignore changes to the generated src/lib.rs + Command::new("git").arg("update-index") + .arg("--assume-unchanged") + .arg("src/lib.rs") + .output() + .expect("failed to suppress change notification on generated lib.rs"); + + println!("All done."); + Ok(()) +} + +fn clean_up_some_lint_warnings_in_the_generated_code(lib_rs: &String) -> ex::io::Result<()> { + let mut lib_src = String::new(); + File::open(&lib_rs)?.read_to_string(&mut lib_src).unwrap(); + let cleaned_some_invalid_lints = lib_src.replace("#![deny(legacy_directory_ownership)]", "//#![deny(legacy_directory_ownership)]") + .replace("#![deny(plugin_as_library)]", "//#![deny(plugin_as_library)]") + .replace("#![deny(safe_extern_statics)]", "//#![deny(safe_extern_statics)]") + .replace("#![deny(unions_with_drop_fields)]", "//#![deny(unions_with_drop_fields)]"); + + File::create(&lib_rs)?.write_all(cleaned_some_invalid_lints.as_bytes()).unwrap(); - // Tell git to ignore changes to the generated src/lib.rs - Command::new("git") - .arg("update-index") - .arg("--assume-unchanged") - .arg("src/lib.rs") - .output() - .expect("failed to suppress change notification on generated lib.rs"); - Ok(()) }