From a29faf283d5e6eeb24c2ce5b5bd51e026853d1e9 Mon Sep 17 00:00:00 2001 From: Dominik Gschwind Date: Wed, 11 Aug 2021 19:19:31 +0200 Subject: [PATCH] Workaround relative linker args This workaround currently simply copies the esp-idf build output to the workspace directory, this creates the folder `esp-idf` in the workspace root after a build, which should be added to the gitignore. It is currently the simplest solution as this doesn't require any additional tools. Also improved the code a bit. --- sdk_build_support/cmake_file_api.rs | 6 +++ sdk_build_support/main.rs | 80 +++++++++++------------------ sdk_build_support/utils.rs | 51 ++---------------- 3 files changed, 41 insertions(+), 96 deletions(-) diff --git a/sdk_build_support/cmake_file_api.rs b/sdk_build_support/cmake_file_api.rs index 46fa3aa219..ed60d4d48a 100644 --- a/sdk_build_support/cmake_file_api.rs +++ b/sdk_build_support/cmake_file_api.rs @@ -84,6 +84,12 @@ impl IndexReply { CodemodelTarget::from_file(&path_buf![&self.reply_dir, &self.json_file]) } + /// Try to get the target with name `target_name`. + /// + /// Note: + /// This method takes a `&mut self` because it caches all references to the json files + /// which actually contain all information about the target (Please look at the + /// cmake-file-api documentation for more information). pub fn get_target(&mut self, target_name: &str) -> Result> { if self.targets.is_empty() { self.targets = self.get_targets()?; diff --git a/sdk_build_support/main.rs b/sdk_build_support/main.rs index b28e6c8fa1..81a2758b49 100644 --- a/sdk_build_support/main.rs +++ b/sdk_build_support/main.rs @@ -28,11 +28,10 @@ pub mod consts; use chip::*; use utils::*; -use std::array::{self}; +use std::array; use std::fs; use std::io::Write; use std::path::Path; -use std::process::Stdio; use std::{env, path::PathBuf}; use anyhow::*; @@ -190,11 +189,15 @@ pub fn build(build_env: &BuildEnv) -> Result<()> { .map(|s| s.to_owned()) .collect(); bin_paths.pop(); - let bin_paths: Vec<_> = bin_paths.into_iter().map(|s| to_win_path(s)).collect(); + let bin_paths: Vec<_> = bin_paths + .into_iter() + .map(|s| PathBuf::from(to_win_path(s))) + .chain(env::split_paths(&env::var("PATH")?)) + .collect(); let gcc_bin_dir = PathBuf::from( bin_paths .iter() - .find(|s| s.contains(chip.target_triple())) + .find(|s| s.to_string_lossy().contains(chip.target_triple())) .ok_or_else(|| { anyhow!( "Could not get the path to the toolchain of chip '{}'.", @@ -202,6 +205,7 @@ pub fn build(build_env: &BuildEnv) -> Result<()> { ) })?, ); + let paths = env::join_paths(bin_paths.iter())?; // Create dummy cmake project (copies from `cmake_project`). let libespidf_dir = path_buf![out_dir, "libespidf"]; @@ -215,13 +219,6 @@ pub fn build(build_env: &BuildEnv) -> Result<()> { &libespidf_dir )?; - let paths = env::join_paths( - bin_paths - .iter() - .map(PathBuf::from) - .chain(env::split_paths(&env::var("PATH")?)), - )?; - // Create cmake-file-api query file. let file_api_dir = path_buf![&libespidf_build_dir, ".cmake", "api", "v1"]; let query_dir = path_buf![&file_api_dir, "query", "client-esp_idf_sys"]; @@ -269,7 +266,15 @@ pub fn build(build_env: &BuildEnv) -> Result<()> { // Note: This unconditionally adds `/build` to the here specified path. .out_dir(&libespidf_dir) .build_target("all") - .define("CMAKE_TOOLCHAIN_FILE", path_buf![&esp_idf_dir, "tools", "cmake", &format!("toolchain-{}.cmake", &mcu)]) + .define( + "CMAKE_TOOLCHAIN_FILE", + path_buf![ + &esp_idf_dir, + "tools", + "cmake", + &format!("toolchain-{}.cmake", &mcu) + ], + ) .always_configure(false) .pic(false) .asmflag(chip.asmflags()) @@ -338,53 +343,30 @@ pub fn build(build_env: &BuildEnv) -> Result<()> { // Create archive of all libraries and write linker args to file. env::set_current_dir(&libespidf_build_dir)?; - let args = utils::parse_linker_args(target.link); - let mut espidf_ar_mri = vec![]; let linker_args_file = out_dir.join("linker_args.rsp"); let mut linker_args_rsp = fs::File::create(&linker_args_file)?; - let espidf_lib = "libespidf.a"; - write!( - &mut linker_args_rsp, - "\"{}\" ", - libespidf_build_dir - .join(&espidf_lib) - .to_string_lossy() - .replace('\\', "/") - )?; - - espidf_ar_mri.push(format!("CREATE {}", espidf_lib)); - for (arg, arg_type) in args { - match arg_type { - LinkArgType::Library => { - espidf_ar_mri.push(format!("ADDLIB {}", arg)); - } - LinkArgType::Flags => { - write!(&mut linker_args_rsp, "{} ", arg)?; - } - } + for f in target.link.command_fragments { + write!(&mut linker_args_rsp, "{} ", f.fragment.replace('\\', "/"))?; } - espidf_ar_mri.push("SAVE".into()); - espidf_ar_mri.push("END".into()); - drop(linker_args_rsp); - let ar = format!("{}-ar", &chip_target_triple); - let mut handle = cmd_spawn!(ar, "-M"; - env=("PATH", &paths), - stdin=(Stdio::piped()), - stdout=(Stdio::inherit()), - stderr=(Stdio::inherit()) - )?; - write!( - &mut handle.stdin.take().unwrap(), - "{}", - espidf_ar_mri.join("\n") + cmd!("cmake", "-E", "rm", "-rf", workspace_dir.join("esp-idf")).ok(); + cmd!( + "cmake", + "-E", + "copy_directory", + libespidf_build_dir.join("esp-idf"), + workspace_dir.join("esp-idf") )?; - handle.wait()?; println!("cargo:LINKER_ARG=@{}", linker_args_file.display()); + println!( + "cargo:LINKER={}/{}-gcc", + gcc_bin_dir.display(), + chip_target_triple + ); Ok(()) } diff --git a/sdk_build_support/utils.rs b/sdk_build_support/utils.rs index 6ef29be2ba..935ae8c5bb 100644 --- a/sdk_build_support/utils.rs +++ b/sdk_build_support/utils.rs @@ -5,8 +5,6 @@ use std::{ use anyhow::Result; -use crate::cmake_file_api::{self, target::Role}; - /// Build a [`PathBuf`]. /// /// # Examples @@ -35,7 +33,7 @@ macro_rules! cmd_spawn { $(builder.arg($cmdarg);)* $(builder. $k $v;)* - Ok::<_, std::io::Error>(builder.spawn()?) + builder.spawn() }}; ($cmd:expr $(,$cmdarg:expr)*) => { cmd_spawn!($cmd, $($cmdarg),*;) @@ -54,7 +52,7 @@ macro_rules! cmd { Err(err) => Err(err.into()), Ok(result) => { if !result.success() { - Err(anyhow::anyhow!("Command '{:?}' (args = [{}]) failed with exit code {:?}.", cmd, stringify!($($cmdarg),*), result.code())) + Err(anyhow::anyhow!("Command '{:?}' failed with exit code {:?}.", &builder, result.code())) } else { Ok(result) @@ -95,7 +93,7 @@ macro_rules! cmd_output { std::io::stdout().write_all(&result.stdout[..]).ok(); std::io::stderr().write_all(&result.stderr[..]).ok(); - Err(anyhow::anyhow!("Command '{:?}' (args = [{}]) failed with exit code {:?}.", cmd, stringify!($($cmdarg),*), result.status.code())) + Err(anyhow::anyhow!("Command '{:?}' failed with exit code {:?}.", &builder, result.status.code())) } else { Ok(String::from_utf8_lossy(&result.stdout[..]).trim_end_matches(&['\n', '\r'][..]).to_string()) @@ -129,7 +127,7 @@ pub fn abspath(file: impl AsRef) -> Result { if file.as_ref().is_absolute() { return Ok(file.as_ref().to_owned()); } - + Ok(env::current_dir()?.join(file)) } @@ -152,45 +150,4 @@ pub fn push_current_dir(path: impl AsRef) -> Result { env::set_current_dir(path)?; Ok(PushedPathGuard(last_dir)) -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum LinkArgType { - Flags, - Library, -} - -pub fn parse_linker_args(link: cmake_file_api::target::Link) -> Vec<(String, LinkArgType)> { - let mut args: Vec<(String, LinkArgType)> = vec![]; - - link.command_fragments.into_iter().rev().map(|f| { - let frag = f.fragment; - if f.role != Role::Libraries { - return (frag, LinkArgType::Flags); - } - - if frag.starts_with("-") { - (frag, LinkArgType::Flags) - } - else if Path::new(&frag).exists() { - (frag, LinkArgType::Library) - } - else { - (frag, LinkArgType::Flags) - } - }).for_each(|arg| { - if args.iter().find(|v| v.1 == arg.1 && &v.0 == &arg.0).is_none() { - args.push(arg) - } - }); - args.reverse(); - - #[cfg(windows)] - { - for (f, _) in args.iter_mut() { - *f = f.replace('\\', "/"); - } - } - - args } \ No newline at end of file