rust-embedded / cortex-m

Low level access to Cortex-M processors
Apache License 2.0
832 stars 152 forks source link

Cannot find linker script memory.x: cargo workspaces #461

Closed tgross35 closed 4 months ago

tgross35 commented 1 year ago

Hello all,

Does anyone have a workaround for the following error:

cannot find linker script memory.x
          >>> INCLUDE memory.x
          >>>         ^

that arises when compiling packages within workspaces?

I've tried a few things like adding println!("cargo:rustc-link-arg=-T{}/memory.x", env!("CARGO_MANIFEST_DIR")); to my build.rs, but nothing has worked so far.

Whatever the solution is, it would likely be good to document it somewhere

tgross35 commented 1 year ago

Moving memory.x to the workspace root does work, but that of course isn't doable when you have >1 target within a workspace

adamgreig commented 1 year ago

The usual thing is a build.rs script that copies your memory.x (or indeed creates it from scratch) into the output directory and adds that to the linker search path, e.g.: https://github.com/rust-embedded/cortex-m-quickstart/blob/master/build.rs

I guess you could also just put the crate path into the linker search path too, println!("cargo:rustc-link-search={}", env!("CARGO_MANIFEST_DIR"));, though I've not tried it.

franksacco commented 1 year ago

I had the same issue: I created a Cargo workspace with several binary and library packages and the linker was unable to find the memory.x files while building.

As @adamgreig pointed out, I created a build.rs file in each binary package with the following content:

use std::{env, error::Error, fs::File, io::prelude::Write, path::PathBuf};

fn main() -> Result<(), Box<dyn Error>> {
    // Make `memory.x` available to the linker.
    let out_dir = env::var("OUT_DIR")?;
    let out_dir = PathBuf::from(out_dir);

    let memory_x = include_bytes!("memory.x").as_ref();
    File::create(out_dir.join("memory.x"))?.write_all(memory_x)?;

    // Tell Cargo where to find the file.
    println!("cargo:rustc-link-search={}", out_dir.display());

    // Tell Cargo to rebuild if `memory.x` is updated.
    println!("cargo:rerun-if-changed=memory.x");

    Ok(())
}

This solved the problem for me.

newAM commented 4 months ago

I'm triaging Cortex-M issues today.

I think the original question has been resolved, feel free to re-open if not!