问题
I have a Rust project which I am currently compiling and linking by hand:
rustc --target=avr-atmel-none src/main.rs --emit=obj -o _build/main.rs.o -C opt-level=3
avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p -o _build/image.elf _build/main.rs.o
avr-objcopy -Oihex -R.eeprom _build/image.elf _build/image.hex
I would like to automate this with Cargo, so I started by setting avr-gcc
as the linker, by adding the following to .cargo/config
:
[build]
target = "avr-atmel-none"
[target.avr-atmel-none]
linker = "avr-gcc"
However, it seems cargo
passes some extra arguments to the linker that avr-gcc
cannot handle:
11:47:10 [cactus@galaxy interrupt-bug]$ cargo build --release
Compiling hello-avr v0.1.0 (file:///home/cactus/prog/rust/avr/interrupt-bug)
error: linking with `avr-gcc` failed: exit code: 1
|
= note: "avr-gcc" "-Wl,--as-needed" "-L" "/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/avr-atmel-none/lib" "/home/cactus/prog/rust/avr/interrupt-bug/target/avr-atmel-none/release/deps/hello_avr-8bce8eb24807f5a8.0.o" "-o" "/home/cactus/prog/rust/avr/interrupt-bug/target/avr-atmel-none/release/deps/hello_avr-8bce8eb24807f5a8" "-Wl,--gc-sections" "-pie" "-Wl,-O1" "-nodefaultlibs" "-L" "/home/cactus/prog/rust/avr/interrupt-bug/target/avr-atmel-none/release/deps" "-L" "/home/cactus/prog/rust/avr/interrupt-bug/target/release/deps" "-L" "/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/avr-atmel-none/lib"
= note: /usr/lib/gcc/avr/4.8.2/../../../avr/bin/ld: -pie not supported
collect2: error: ld returned 1 exit status
How do I remove these extra arguments from the avr-gcc
invocation? Moreover, is there a way to integrate the third step, i.e. the avr-objcopy
call, into the Cargo workflow?
回答1:
A word of warning: development on avr-rust can politely be said to be cutting edge. It's very likely something that works one day may not the next, so answers like this are likely to go out of date quickly. We welcome all contributors to the project to help make it more usable.
You need to specify a target JSON file and the full set of linker arguments. Here's an example from an older project of mine (some of the exact values may now be incorrect):
{
"llvm-target": "avr-atmel-none",
"target-endian": "little",
"target-pointer-width": "16",
"os": "none",
"target-env": "gnu",
"target-vendor": "unknown",
"arch": "avr",
"data-layout": "e-p:16:16:16-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-n8",
"executables": true,
"linker": "avr-gcc",
"linker-flavor": "gcc",
"pre-link-args": {
"gcc": ["-mmcu=atmega328p", "-nostartfiles", "../interrupt_vector.S"]
},
"exe-suffix": ".elf",
"post-link-args": {
"gcc": ["-Wl,--no-gc-sections"]
},
"no-compiler-rt": true
}
For a full example see my example repository. This project used to work (see my blog series). I have recently updated it so it compiles against the master branch of avr-rust, but haven't tested the compiled code on a real device.
There's an open RFC for having Cargo post build scripts, but it doesn't seem likely to be merged. I continue to use a Makefile. xargo might be an alternative. There were also rumbles about a cargo subcommand that could be created.
来源:https://stackoverflow.com/questions/43702724/linking-avr-programs-with-cargo