wg icon indicating copy to clipboard operation
wg copied to clipboard

Support linker scripts in Cargo.toml / build.rs

Open xobs opened this issue 5 years ago • 4 comments

As per https://github.com/rust-embedded/wg/pull/24#issuecomment-464469319_, I'm opening a new issue.

The current recommendation for making custom linker scripts is to create a .cargo/config file and add a reference to the linker script there. The previous discussion identified a number of issues with this:

  1. It puts configuration data in a file that's ostensibly not going to be checked in
  2. It's difficult to change it on a per-device basis

Additionally, I would like to add some more issues I see with it, particularly with workspaces:

  1. The build depends on the directory you're in. For example, here the data section moved, which was a subtle bug to track down:
$ cargo build -p kernel --target riscv32imac-unknown-none-elf
$ riscv64-unknown-elf-readelf -S target/riscv32imac-unknown-none-elf/debug/kernel
There are 24 section headers, starting at offset 0x117724:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .rodata           PROGBITS        000100e0 0000e0 002f38 00  AM  0   0 16
  [ 2] .text             PROGBITS        00014000 004000 00ebe2 00  AX  0   0  2
  [ 3] .trap             PROGBITS        00022be2 012be2 000104 00  AX  0   0  1
  [ 4] .data             PROGBITS        00023000 013000 002bc8 00  WA  0   0  4
  [ 5] .sdata            PROGBITS        00025bc8 015bc8 000004 00  WA  0   0  4
...
$ cd kernel
$ cargo build -p kernel --target riscv32imac-unknown-none-elf
$  riscv64-unknown-elf-readelf -S ../target/riscv32imac-unknown-none-elf/debug/kernel      There are 21 section headers, starting at offset 0xfd404:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        ffd00000 001000 00c0c0 00  AX  0   0  4
  [ 2] .rodata           PROGBITS        ffd0c0c0 00d0c0 002f34 00  AM  0   0 16
  [ 3] .data             PROGBITS        ffd80000 010000 002bcc 00  WA  0   0 4096
  [ 4] .bss              NOBITS          ffd82bcc 012bcc 000210 00  WA  0   0  4
...
$
  1. It is required to copy the linker args on a per-target basis. For example, duplicate arguments need to be made for riscv32imac-unknown-none-elf and riscv32i-unknown-none-elf, even though they're identical.
  2. It isn't possible to do a cargo build --target riscv32imac-unknown-none from the root, since cargo appears to ignore the .cargo/config setting.

Some of these could be fixed if cargo read .cargo/config from the crate root, which may be an acceptible workaround, however it seems to me that's just working around the problem.

I think it would be much better if cargo supported setting the linker flags from e.g. build.rs so they can be set on a per-crate basis, possibly based on the build environment in something like a CI infrastructure.

xobs avatar Mar 10 '20 06:03 xobs

Big :+1: from me, but this should probably be filed as a Cargo issue at https://github.com/rust-lang/cargo

jonas-schievink avatar Mar 10 '20 15:03 jonas-schievink

I'm probably misunderstanding something, but it's absolutely possible to check in .cargo/config, and cargo will read it just fine. Cargo walks the path from the current working directory upwards to find .cargo/config.

I'm 100% on board with a build-script mechanism to set linker flags though.

roblabla avatar Mar 10 '20 17:03 roblabla

My understanding is that, you need to check in .cargo/config in a workspace targeting multiple architectures at once. Consider a workspace containing:

  • x86_64 testing application
  • An ARM micrcocontroller testing firmware
  • A serialization crate to send data back and forth, compiled for both x86_64 and ARM.

Setting the architecture to .cargo/config is required for the x86_64 testing application and firmware crate for cargo build, without an explicit target architecture to "do the right thing".

cr1901 avatar Mar 10 '20 19:03 cr1901

I created an issue in the cargo repository: https://github.com/rust-lang/cargo/issues/7984

xobs avatar Mar 11 '20 03:03 xobs