Skip to content

Instantly share code, notes, and snippets.

@lupyuen
Last active July 24, 2024 05:12
Show Gist options
  • Save lupyuen/69da35a027cf780680944010b4a85fe7 to your computer and use it in GitHub Desktop.
Save lupyuen/69da35a027cf780680944010b4a85fe7 to your computer and use it in GitHub Desktop.
Apache NuttX RTOS: Build Rust App for QEMU RISC-V 32-bit with Rust Custom Target. See https://lupyuen.github.io/articles/rust4
#!/usr/bin/env bash
# Build NuttX for QEMU RISC-V 32-bit with Rust App
## TODO: Set PATH
export PATH="$HOME/xpack-riscv-none-elf-gcc-13.2.0-2/bin:$PATH"
set -e # Exit when any command fails
set -x # Echo commands
## Build NuttX
function build_nuttx {
## Go to NuttX Folder
pushd ../nuttx
## Build NuttX
make -j 8
## Return to previous folder
popd
}
## Build Rust App for QEMU RISC-V 32-bit with Rust Custom Target
function build_rust_riscv32 {
## Go to NuttX Folder
pushd ../nuttx
## Download our Custom Target for `riscv32gc`
rm -f riscv32gc-unknown-none-elf.json
wget https://raw.githubusercontent.com/lupyuen/nuttx-rust-app/main/riscv32gc-unknown-none-elf.json
## Custom Target needs Nightly Build of Rust Compiler
rustup override set nightly
rustup component add rust-src --toolchain nightly
## Verify our Custom Target, make sure it's OK
rustc \
--print cfg \
--target riscv32gc-unknown-none-elf.json
## `cargo build` requires a Rust Project, so we create an empty one.
rm -rf app
cargo new app
## Build the Rust Core Library for `riscv32gc`
## Include the `alloc` library, which will support Heap Memory in future.
## Ignore the error: `can't find crate for std`
pushd app
cargo build \
-Zbuild-std=core,alloc \
--target ../riscv32gc-unknown-none-elf.json \
|| true
popd
## Compile our Rust App with Rust Core Library for `riscv32gc`
## We changed the Target to `riscv32gc-unknown-none-elf.json`
rustc \
--target riscv32gc-unknown-none-elf.json \
--edition 2021 \
--emit obj \
-g \
-C panic=abort \
-O \
../apps/examples/hello_rust/hello_rust_main.rs \
-o ../apps/examples/hello_rust/*hello_rust.o \
\
-C incremental=app/target/riscv32gc-unknown-none-elf/debug/incremental \
-L dependency=app/target/riscv32gc-unknown-none-elf/debug/deps \
-L dependency=app/target/debug/deps \
--extern noprelude:alloc=`ls app/target/riscv32gc-unknown-none-elf/debug/deps/liballoc-*.rlib` \
--extern noprelude:compiler_builtins=`ls app/target/riscv32gc-unknown-none-elf/debug/deps/libcompiler_builtins-*.rlib` \
--extern noprelude:core=`ls app/target/riscv32gc-unknown-none-elf/debug/deps/libcore-*.rlib` \
-Z unstable-options
## NuttX Build need us to copy hello_rust.o to hello_rust_1.o
cp \
../apps/examples/hello_rust/*hello_rust.o \
../apps/examples/hello_rust/*hello_rust_1.o
## Return to previous folder
popd
}
## Obsolete: Fix the Rust Build for QEMU RISC-V 32-bit by patching the ELF Header
function old_build_rust_riscv32 {
## Add the Rust Target
rustup target add riscv32i-unknown-none-elf
## Go to NuttX Folder
pushd ../nuttx
## Patch the ELF Header, changing it from Software Floating-Point to Double Precision Hardware Floating-Point
## https://gist.github.com/lupyuen/7be4bedc6a109b2c3d1201aee6030428
xxd -c 1 ../apps/examples/hello_rust/*hello_rust_1.o \
| sed 's/00000024: 00/00000024: 04/' \
| xxd -r -c 1 - /tmp/hello_rust_1.o
cp /tmp/hello_rust_1.o ../apps/examples/hello_rust/*hello_rust_1.o
## Return to previous folder
popd
}
## Pull updates
git pull && git status && hash1=`git rev-parse HEAD`
pushd ../apps
git pull && git status && hash2=`git rev-parse HEAD`
popd
echo NuttX Source: https://github.com/apache/nuttx/tree/$hash1 >nuttx.hash
echo NuttX Apps: https://github.com/apache/nuttx-apps/tree/$hash2 >>nuttx.hash
## Show the versions of GCC and Zig
riscv-none-elf-gcc -v
## Configure the NuttX Build
make distclean
tools/configure.sh rv-virt:nsh
## Enable the Hello Rust App
kconfig-tweak --enable CONFIG_EXAMPLES_HELLO_RUST
## Update the Kconfig Dependencies
make olddefconfig
## Build NuttX. Ignore the error: `can't link soft-float modules with double-float modules`
build_nuttx || true
## Build the Rust App with Custom Target
build_rust_riscv32
# Previously: old_build_rust_riscv32
## Link the Rust App with NuttX
build_nuttx
## Show the size
riscv-none-elf-size nuttx
## Export the Binary Image to nuttx.bin
riscv-none-elf-objcopy \
-O binary \
nuttx \
nuttx.bin
## Copy the config
cp .config nuttx.config
## Dump the NuttX Kernel Disassembly to nuttx.S
riscv-none-elf-objdump \
--syms --source --reloc --demangle --line-numbers --wide \
--debugging \
nuttx \
>nuttx.S \
2>&1
## Dump the Rust App Disassembly to hello_rust_1.S
riscv-none-elf-objdump \
--syms --source --reloc --demangle --line-numbers --wide \
--debugging \
../apps/examples/hello_rust/*1.o \
>hello_rust_1.S \
2>&1
## Check coding style
# ../nxstyle arch/risc-v/src/bl808/bl808_mm_init.c
## Start the emulator
qemu-system-riscv32 \
-semihosting \
-M virt,aclint=on \
-cpu rv32 \
-kernel nuttx \
-nographic \
-bios none
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment