Rust: build for atmega16 - rust

I would like to write a simple program and compile it for atmega16. How do I add atmega16 as a compilation target? There are little to no docs about this...
Thanks

The only built-in AVR target is avr-unknown-gnu-atmega328. If you are using a different AVR microcontroller, you need a custom target.
The AVR-Rust Guidebook describes how to add custom targets for different AVR microcontrollers. The process boils down to:
Export the JSON specification for the built-in atmega328 target, to use as a template
rustc --print target-spec-json -Z unstable-options --target avr-unknown-gnu-atmega328 > avr-unknown-gnu-atmega16.json
Edit this JSON file. I found that to get it to compile for atmega16, I had to change the following:
"cpu": "atmega16",
"is-builtin": false,
"-mmcu=atmega16"
Note:
The CPU is specified as "atmega16" not "atmega16p" as you had attempted to use
I don't have any atmega16 MCU to hand so I have not been able to test the resulting binary. You may need to tweak other elements of the file.
You will also need to install avr-gcc, as Rust uses it to link the resulting binary. You can get that here.
You should then be able to build your project like this:
cargo build -Z build-std=core --target ./avr-unknown-gnu-atmega16.json --release
Note that --target is specified as the path to the JSON file. If in the same directory, prefix with ./.

Related

How to pass rustflags to artifact dependency binary?

I want to find a way to pass rustflags to artifact dependency bin.
Below is the story.
I write my toy OS currently, and using artifact dependency because this is suggested at rust-osdev/bootloader repositiory(descriptions are Booting section of this README) and I thought this is a useful way. However, I find that this way seems not to pass rustflags I attached in .cargo/config.toml in my kernel workspace like below.
[build]
target = "x86_64-unknown-none"
rustflags = ["-C", "relocation-model=static", "-C", "link-arg=-no-pie"]
[unstable]
build-std = ["core", "compiler_builtins"]
build-std-features = ["compiler-builtins-mem"]
In above config, I expect that kernel elf type is EXEC, but actually, that type is DYN, i.e. I got PIE Elf file even though I write static and no pie flags.
I tried some patterns like below.
run cargo build directly in kernel workspace directory
set invalid rustflags like link-args=hoge and run cargo build in root project directory
As a result
non pie elf (Elf type is EXEC) is created with no errors.
no errors appeared while compile even if I run cargo clean before build.
That's why, I suspect the rustflags I wrote in .cargo/config.toml does not work when its workspace is treated as binary artifact dependency.
Reproduction code is here.
If there is a way to pass rustflags, please teach me.
Add your build.rs in workspace, <project root path>/<kernel workspace name>/build.rs in my case, and put script like below in it.
fn main() {
println!("cargo:rust-link-arg=-no-pie");
}

How to add custom llvm pass into rustc

I am trying to add my llvm pass into Rustc. Rustc has one compiling option -C passes=val where we could add extra LLVM passes to run. However, as my try, this option can only accept the pass when the pass code is placed inside the LLVM code tree, but I want to add my pass out-of-tree into Rustc.
When I add my pass via this option:
RUSTFLAGS="-C passes=my-pass" cargo build
Compiler reports errors:
error: failed to run LLVM passes: unknown pass name 'my-pass'
Then I try to load my pass via -C llvm-args=-fpass-plugin=/opt/new-pass/mypass.so -C passes=my-pass in the clang way. It reports: rustc -Cllvm-args="..." with: Unknown command line argument '-fpass-plugin=/opt/new-pass/mypass.so'. Also tried to replace -fpass-plugin with other options like -load and -load-pass-plugin, but they still cannot be recognized by rustc.
How could I add my custom pass into Rustc?
I was trying to find a solution to this exact problem too. According to a rust developer on their Zulip Chat, it looks like you need to build a custom rustc with plugin support.

How do I remove the dependency on libunwind when cross-compiling Rust programs with the panic_abort option?

I'm specifying the -Cpanic=abort and -Zbuild-std=panic_abort when compiling. Why does the linker still say it needs libunwind to compile a program?
I'm experimenting with various ways to cross-compile Rust programs as small as possible (using the min-sized-rust repo as a reference). Right now I'm trying to compile the powerpc64-unknown-linux-musl target and I'm stuck on trying to remove a dependency on libunwind.
Here's my setup:
# 1. Install the Rust std source code
rustup component add rust-src --toolchain nightly
# 2. Setup a simple rust repo
cargo init testing
cd testing
# 3. Download a musl toolchain
wget https://musl.cc/powerpc64-linux-musl-cross.tgz
tar xzf powerpc64-linux-musl-cross.tgz
# 4. Try to compile the project (options on the command line instead of in files for
# maximum obviousness).
# RUSTFLAGS:
# -Cpanic=abort - abort immediately on panic
# -Clink-self-contained=no - don't use rustc's builtin libraries and objects (this
# is needed because powerpc64-unknown-linux-musl is a tier 3 target)
# -Clink-arg=--sysroot and -Clink-arg=/path/to/sysroot - pass the option to the linker
# to specify the sysroot of cross-compilation toolchain
# Cargo options:
# --config target.<triple>.linker - specify the linker to use
# -Zbuild-std=std,panic_abort - build the standard library from source. Specify
# panic_abort to make the abort on panic work
RUSTFLAGS="-Cpanic=abort -Clink-self-contained=no -Clink-arg=--sysroot -Clink-arg=powerpc64-linux-musl-cross/powerpc64-linux-musl/" \
cargo +nightly build \
--config "target.powerpc64-unknown-linux-musl.linker=\"powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-gcc\"" \
--target powerpc64-unknown-linux-musl -Zbuild-std=panic_abort,std --release
This fails with the following error:
error: linking with `/home/user/Projects/testing/powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-gcc` failed: exit status: 1
<output snipped>
= note: /home/user/Projects/testing/powerpc64-linux-musl-cross/bin/../lib/gcc/powerpc64-linux-musl/11.2.1/../../../../powerpc64-linux-musl/bin/ld: cannot find -lunwind
From min-size-rust repository:
"Even if panic = "abort" is specified in Cargo.toml, rustc will still include panic strings and formatting code in final binary by default. An unstable panic_immediate_abort feature has been merged into the nightly rustc compiler to address this.
To use this, repeat the instructions above to use build-std, but also pass the following -Z build-std-features=panic_immediate_abort option."
Still, you will get "cannot find -lunwind", because the linker still uses libunwind, even though it's truly unneeded,why! I do not know, maybe it's a bug.(Maybe someone with fair knowledge about linkers can easily solve that.I tried a naive solution which is "cargo .... --verbose", copy , remove "libunwind" then relinking which failed)
I verified that is indeed the missing piece by build from source(--target=x86_64-unknown-linux-musl) AND using an old simple trick which is "touch libunwind.a" in the "self-contained" directory inside a target lib folder.(because the linker would still use it even though it's now truly unneeded, then I gave him a dummy libunwind.a)
In your case, I really tried to build it to your target until I got a headache, but couldn't and stopped, but here is possible solutions:
Giving that you're using "-Z build-std-features=panic_immediate_abort"
-If you can custom the linking process, then solve it (until what seems to be a bug is solved)
-Create a dummy(empty) libunwind.a where it should be in your toolchain

Determine Cargo build configuration

I'm implementing a custom Cargo subcommand that mostly runs cargo build followed by some processing on a successful invocation. Cargo itself supports several ways to customize defaults, (e.g. the --target selected when omitted), which this subcommand exposes as well.
The challenge now is to find the defaults that cargo build uses from the subcommand implementation. With build scripts getting access to all sorts of information, this isn't the case for subcommands. Running cargo metadata doesn't seem to produce that information either (such as the TARGET).
Is there any way to query Cargo about the configuration it will be using for a cargo build invocation, and make that available to a Cargo custom subcommand?

Run `rustc` to check a program without generating any files

As cargo check shows, it's often useful to check if your program is well-formed without actually generating code (an often pretty time-consuming task). I want to check a single (library) Rust file with rustc directly (I cannot use Cargo!).
cargo check apparently works by calling this:
rustc --emit=metadata -Z no-codegen
This only emits metadata, a .rmeta file. Cargo actually needs that to check crates dependent on the checked crate. In my case I really don't need the metadata file.
I tried the following:
rustc --crate-type=lib --emit=
rustc --crate-type=lib --emit=nothing
But both didn't work. I use --crate-type=lib because my file doesn't have a main function. I need a platform-independent solution (I don't just want to use it on my machine, but use it in a public script).
How do I make rustc not write a single file?
You can just skip the --emit flag.
The final command would then be: rustc -Z no-codegen rust.rs
To quote my own GitHub comment about this very question, there are a few options for stable Rust:
rustc --emit=mir -o /dev/null seems to work in 1.18 and newer, writing nothing. (--emit=mir is the only helpful --emit option—the others try to create silly files like /dev/null.foo0.rcgu.o, except --emit=dep-info, which does no checking.)
rustc -C extra-filename=-tmp -C linker=true (i.e. use /bin/true as a “linker”) seems to work in all versions, writing some intermediate files but cleaning them up.
rustc --out-dir=<new empty temporary directory> is less clever and therefore perhaps less likely to break?
Note that linker errors, if any, will not be found by the first two options (nor by the nightly-only -Zno-codegen option).

Resources