lupyuen.org/articles/rust4.html

933 lines
48 KiB
HTML
Raw Normal View History

2024-04-12 19:18:02 +08:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<title>Rust Custom Target for QEMU RISC-V on Apache NuttX RTOS</title>
<!-- Begin scripts/articles/*-header.html: Article Header for Custom Markdown files processed by rustdoc, like chip8.md -->
<meta property="og:title"
content="Rust Custom Target for QEMU RISC-V on Apache NuttX RTOS"
data-rh="true">
<meta property="og:description"
2024-04-18 23:36:42 +08:00
content="Our Rust App compiles for Software Floating-Point, but Apache NuttX RTOS expects Hardware Floating-Point... Let's fix this with a Rust Custom Target for QEMU RISC-V"
2024-04-12 19:18:02 +08:00
data-rh="true">
<meta name="description"
2024-04-18 23:36:42 +08:00
content="Our Rust App compiles for Software Floating-Point, but Apache NuttX RTOS expects Hardware Floating-Point... Let's fix this with a Rust Custom Target for QEMU RISC-V">
2024-04-12 19:18:02 +08:00
<meta property="og:image"
content="https://lupyuen.github.io/images/rust4-title.jpg">
<meta property="og:type"
content="article" data-rh="true">
<link rel="canonical"
href="https://lupyuen.codeberg.page/articles/rust4.html" />
<!-- End scripts/articles/*-header.html -->
<!-- Begin scripts/rustdoc-header.html: Header for Custom Markdown files processed by rustdoc, like chip8.md -->
<link rel="alternate" type="application/rss+xml" title="RSS Feed for lupyuen" href="/rss.xml" />
<link rel="stylesheet" type="text/css" href="../normalize.css">
<link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle">
<link rel="stylesheet" type="text/css" href="../dark.css">
<link rel="stylesheet" type="text/css" href="../light.css" id="themeStyle">
<link rel="stylesheet" type="text/css" href="../prism.css">
<script src="../storage.js"></script><noscript>
<link rel="stylesheet" href="../noscript.css"></noscript>
<link rel="shortcut icon" href="../favicon.ico">
<style type="text/css">
#crate-search {
background-image: url("../down-arrow.svg");
}
</style>
<!-- End scripts/rustdoc-header.html -->
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<!-- Begin scripts/rustdoc-before.html: Pre-HTML for Custom Markdown files processed by rustdoc, like chip8.md -->
<!-- Begin Theme Picker -->
<div class="theme-picker" style="left: 0"><button id="theme-picker" aria-label="Pick another theme!"><img src="../brush.svg"
width="18" alt="Pick another theme!"></button>
<div id="theme-choices"></div>
</div>
<!-- Theme Picker -->
<!-- End scripts/rustdoc-before.html -->
<h1 class="title">Rust Custom Target for QEMU RISC-V on Apache NuttX RTOS</h1>
<nav id="TOC"><ul>
2024-04-13 00:51:30 +08:00
<li><a href="#software-vs-hardware-floating-point">1 Software vs Hardware Floating-Point</a><ul></ul></li>
2024-04-15 08:44:59 +08:00
<li><a href="#rust-wont-double-float">2 Rust Wont Double-Float</a><ul></ul></li>
2024-04-13 23:25:52 +08:00
<li><a href="#custom-target-for-rust">3 Custom Target for Rust</a><ul></ul></li>
<li><a href="#build-the-rust-core-library">4 Build the Rust Core Library</a><ul></ul></li>
<li><a href="#nuttx-links-ok-with-rust">5 NuttX Links OK with Rust</a><ul></ul></li>
<li><a href="#rust-build-for-64-bit-risc-v">6 Rust Build for 64-bit RISC-V</a><ul></ul></li>
2024-04-15 07:36:02 +08:00
<li><a href="#whats-next">7 Whats Next</a><ul></ul></li>
<li><a href="#appendix-rust-compiler-options">8 Appendix: Rust Compiler Options</a><ul></ul></li></ul></nav><p>📝 <em>22 Apr 2024</em></p>
2024-04-12 19:18:02 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-title.jpg" alt="Rust Apps on Apache NuttX RTOS and QEMU RISC-V" /></p>
2024-04-12 19:40:46 +08:00
<div style="text-align: center">
<p><a href="https://github.com/Swordfish90/cool-retro-term"><em>Thanks to cool-retro-term!</em></a></p>
</div>
2024-04-19 14:03:39 +08:00
<p>Last article we were compiling <a href="https://lupyuen.github.io/articles/rust3"><strong>Rust Apps</strong></a> for <a href="https://nuttx.apache.org/docs/latest/index.html"><strong>Apache NuttX RTOS</strong></a> (QEMU Emulator, RISC-V 32-bit). And we hit a <strong>baffling error</strong></p>
2024-04-13 00:51:30 +08:00
<div class="example-wrap"><pre class="language-bash"><code>$ make
riscv64-unknown-elf-ld: libapps.a
hello_rust_1.o:
can&#39;t link soft-float modules with double-float modules
</code></pre></div>
<p>Lets solve the problem! We dive inside the internals of <strong>C-to-Rust Interop</strong></p>
<ul>
<li>
2024-04-18 18:55:16 +08:00
<p>Rust compiles for <strong>Soft-Float</strong>, NuttX expects <strong>Double-Float</strong></p>
2024-04-13 00:51:30 +08:00
<p>(Software vs Hardware Floating-Point)</p>
</li>
<li>
<p>But Rust <strong>doesnt support Double-Float</strong> (by default)</p>
</li>
<li>
<p>So we create a <strong>Rust Custom Target</strong> for Double-Float</p>
</li>
<li>
<p>Rebuild the <strong>Rust Core Library</strong> for Double-Float</p>
</li>
<li>
<p>And our Rust App <strong>builds OK with NuttX</strong>!</p>
</li>
</ul>
2024-04-17 22:56:36 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-flow2a.jpg" alt="Double-Float vs Soft-Float: GCC Linker wont link the binaries" /></p>
2024-04-13 00:51:30 +08:00
<h1 id="software-vs-hardware-floating-point"><a class="doc-anchor" href="#software-vs-hardware-floating-point">§</a>1 Software vs Hardware Floating-Point</h1>
2024-04-18 23:36:42 +08:00
<p><em>Why did our NuttX Build fail? (Pic above)</em></p>
2024-04-18 14:50:16 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Download the NuttX Source Code
$ mkdir nuttx
$ cd nuttx
$ git clone https://github.com/apache/nuttx nuttx
$ git clone https://github.com/apache/nuttx-apps apps
2024-04-18 23:36:42 +08:00
## Configure NuttX for QEMU RISC-V 32-bit
2024-04-18 14:50:16 +08:00
$ cd nuttx
$ tools/configure.sh rv-virt:nsh
$ make menuconfig
## TODO: Enable &quot;Hello Rust Example&quot;
## Build NuttX bundled with the Rust App
2024-04-18 00:38:42 +08:00
$ make
2024-04-16 03:01:04 +08:00
riscv64-unknown-elf-ld: libapps.a
hello_rust_1.o:
can&#39;t link soft-float modules with double-float modules
</code></pre></div>
2024-04-18 23:36:42 +08:00
<p><a href="https://lupyuen.github.io/articles/rust3#build-nuttx-for-qemu-risc-v">(See the <strong>Complete Steps</strong>)</a></p>
2024-04-18 00:38:42 +08:00
<p><strong>GCC Linker</strong> failed because it couldnt link the NuttX Binaries with the Rust Binaries. </p>
<p>Heres Why: NuttX Build calls <strong>GCC Compiler</strong> to compile our C Modules…</p>
<div class="example-wrap"><pre class="language-bash"><code>## Build NuttX Firmware with Tracing Enabled
$ make --trace
2024-04-12 19:40:46 +08:00
...
2024-04-16 03:01:04 +08:00
## GCC compiles `hello_main.c` to `hello.o`
2024-04-18 00:38:42 +08:00
## for RISC-V 32-bit with Double-Float
2024-04-12 19:40:46 +08:00
riscv64-unknown-elf-gcc \
2024-04-16 23:00:41 +08:00
-march=rv32imafdc \
-mabi=ilp32d \
2024-04-12 19:40:46 +08:00
-c \
hello_main.c \
2024-04-18 00:38:42 +08:00
-o ...hello.o \
...
2024-04-15 10:45:47 +08:00
</code></pre></div>
2024-04-18 00:38:42 +08:00
<p><a href="https://gist.github.com/lupyuen/7e68b69d0d5879f77b1404ae2db6fb9d">(See the <strong>GCC Options</strong>)</a></p>
2024-04-16 03:21:05 +08:00
<p>Then NuttX Build calls <strong>Rust Compiler</strong> to compile our Rust App…</p>
2024-04-18 00:38:42 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Build NuttX Firmware with Tracing Enabled
$ make --trace
2024-04-16 03:01:04 +08:00
...
## Rust Compiler compiles `hello_rust_main.rs` to `hello_rust.o`
2024-04-18 00:38:42 +08:00
## for RISC-V 32-bit with Soft-Float
2024-04-15 10:45:47 +08:00
rustc \
2024-04-16 23:00:41 +08:00
--target riscv32i-unknown-none-elf \
2024-04-15 10:45:47 +08:00
--edition 2021 \
--emit obj \
-g \
-C panic=abort \
-O \
hello_rust_main.rs \
2024-04-18 00:38:42 +08:00
-o ...hello_rust.o
2024-04-15 10:45:47 +08:00
</code></pre></div>
2024-04-18 00:38:42 +08:00
<p>Which looks like this…</p>
2024-04-17 23:16:58 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-flow2b.jpg" alt="Double-Float vs Soft-Float: GCC Linker wont link the binaries" /></p>
2024-04-16 03:21:05 +08:00
<p><em>Is there a problem?</em></p>
2024-04-17 23:16:58 +08:00
<p>Watch closely as we compare <strong>GCC Compiler</strong> with <strong>Rust Compiler</strong> (pic above)…</p>
2024-04-15 11:32:01 +08:00
<span style="font-size:90%">
2024-04-18 00:38:42 +08:00
<div><table><thead><tr><th style="text-align: left">GCC Compiler</th><th style="text-align: left">Rust Compiler</th></tr></thead><tbody>
<tr><td style="text-align: left"><em>riscv64-unknown-elf-gcc</em> <br>      <em>hello_main.c</em></td><td style="text-align: left"><em>rustc</em> <br>      <em>hello_rust_main.rs</em></td></tr>
<tr><td style="text-align: left"><em>-march</em> <br>     <strong>rv32imafdc</strong></td><td style="text-align: left"><em>target</em> <br>    <strong>riscv32i-unknown-none-elf</strong></td></tr>
<tr><td style="text-align: left"><em>-mabi</em> <br>     <strong>ilp32d</strong></td><td style="text-align: left"></td></tr>
2024-04-15 10:45:47 +08:00
</tbody></table>
2024-04-15 11:32:01 +08:00
</div></span>
2024-04-18 15:24:37 +08:00
<p><em>Hmmm the Floats look different…</em></p>
2024-04-18 23:36:42 +08:00
<p>GCC compiles for (Double-Precision) <strong>Hardware Floating-Point</strong></p>
2024-04-19 14:03:39 +08:00
<p>But Rust Compiler emits <strong>Software Floating-Point</strong>.</p>
<p>Thats why GCC Linker <strong>wont link the binaries</strong>: Hard-Float vs Soft-Float!</p>
2024-04-15 11:32:01 +08:00
<span style="font-size:90%">
2024-04-18 00:38:42 +08:00
<div><table><thead><tr><th style="text-align: left">GCC Compiler</th><th style="text-align: left">Rust Compiler</th></tr></thead><tbody>
<tr><td style="text-align: left"><strong>rv32imafdc</strong></td><td style="text-align: left"><strong>riscv32i</strong></td></tr>
<tr><td style="text-align: left">- <strong>I</strong>: Integer</td><td style="text-align: left">- <strong>I</strong>: Integer</td></tr>
<tr><td style="text-align: left">- <strong>F</strong>: Single Hard-Float</td><td style="text-align: left"><em>(Default is Soft-Float)</em></td></tr>
<tr><td style="text-align: left">- <strong>D</strong>: Double Hard-Float</td><td style="text-align: left"><em>(Default is Soft-Float)</em></td></tr>
2024-04-15 11:32:01 +08:00
</tbody></table>
</div></span>
2024-04-16 16:51:10 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-flow2.jpg" alt="Double-Float vs Soft-Float: GCC Linker wont link the binaries" /></p>
2024-04-19 14:03:39 +08:00
<p>To verify, we dump the <a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header"><strong>ELF Header</strong></a> for <strong>GCC Compiler Output</strong></p>
2024-04-18 00:38:42 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Dump the ELF Header for GCC Output
2024-04-15 10:45:47 +08:00
$ riscv64-unknown-elf-readelf \
--file-header --arch-specific \
../apps/examples/hello/*hello.o
2024-04-19 14:03:39 +08:00
## GCC Compiler Output is
## Double-Precision Hardware Floating-Point
2024-04-18 00:38:42 +08:00
Flags: 0x5, RVC, double-float ABI
</code></pre></div>
<p><a href="https://gist.github.com/lupyuen/d8b4f793cd463230393326cef7dbedbe">(See the <strong>GCC ELF Header</strong>)</a></p>
<p>And the ELF Header for <strong>Rust Compiler Output</strong></p>
<div class="example-wrap"><pre class="language-bash"><code>## Dump the ELF Header for Rust Compiler Output
2024-04-15 10:45:47 +08:00
$ riscv64-unknown-elf-readelf \
--file-header --arch-specific \
../apps/examples/hello_rust/*hello_rust.o
2024-04-19 14:03:39 +08:00
## Rust Compiler Output is
## Software Floating-Point
2024-04-18 00:38:42 +08:00
Flags: 0x0
2024-04-15 10:45:47 +08:00
</code></pre></div>
2024-04-18 00:38:42 +08:00
<p><a href="https://gist.github.com/lupyuen/413830fed9cdb2b02d5f9d0d062beb3e">(See the <strong>Rust ELF Header</strong>)</a></p>
2024-04-16 23:00:41 +08:00
<p>Indeed we have a problem: Double-Float and Soft-Float wont mix! Lets fix this…</p>
2024-04-17 22:35:27 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-flow3.jpg" alt="Rust Wont Double-Float" /></p>
2024-04-15 08:44:59 +08:00
<h1 id="rust-wont-double-float"><a class="doc-anchor" href="#rust-wont-double-float">§</a>2 Rust Wont Double-Float</h1>
2024-04-17 22:35:27 +08:00
<p><em>What if we ask Rust Compiler to compile for Double-Float? RV32IMAFDC (Pic above)</em></p>
2024-04-18 11:53:04 +08:00
<p>Lets harmonise Rust Compiler with GCC Compiler…</p>
<ul>
<li>
2024-04-20 00:10:31 +08:00
<p>Our Build Target is <a href="https://www.qemu.org/docs/master/system/riscv/virt.html"><strong>QEMU Emulator</strong></a></p>
</li>
<li>
<p>Which offically supports <a href="https://www.qemu.org/docs/master/system/riscv/virt.html#supported-devices"><strong><code>riscv32gc</code></strong></a></p>
2024-04-18 11:53:04 +08:00
</li>
<li>
<p><strong><code>gc</code></strong>” in “<strong><code>riscv32gc</code></strong>” denotes <a href="https://en.wikipedia.org/wiki/RISC-V#ISA_base_and_extensions"><strong>IMAFDC</strong></a></p>
</li>
</ul>
2024-04-18 15:24:37 +08:00
<p>Hence we could do this…</p>
2024-04-16 23:00:41 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Compile `hello_rust_main.rs` to `hello_rust.o`
## for Double-Precision Hardware Floating-Point
rustc \
--target riscv32gc-unknown-none-elf \
--edition 2021 \
--emit obj \
-g \
-C panic=abort \
-O \
hello_rust_main.rs \
-o hello_rust.o
</code></pre></div>
2024-04-18 15:24:37 +08:00
<p>Sorry nope it <strong>wont work</strong></p>
2024-04-16 23:00:41 +08:00
<div class="example-wrap"><pre class="language-bash"><code>Error loading target specification:
Could not find specification for target &quot;riscv32gc-unknown-none-elf&quot;.
Run `rustc --print target-list` for a list of built-in targets
</code></pre></div>
2024-04-17 22:56:36 +08:00
<p>Thats because <strong><code>riscv32gc</code></strong> isnt a <strong>Built-In Rust Target</strong></p>
2024-04-19 14:03:39 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## List the Built-In Rust Targets for RISC-V
2024-04-16 23:00:41 +08:00
$ rustup target list | grep riscv
2024-04-19 14:03:39 +08:00
## Nope no riscv32gc!
2024-04-12 19:40:46 +08:00
riscv32i-unknown-none-elf
riscv32imac-unknown-none-elf
riscv32imc-unknown-none-elf
riscv64gc-unknown-linux-gnu
riscv64gc-unknown-none-elf
riscv64imac-unknown-none-elf
</code></pre></div>
2024-04-19 15:32:50 +08:00
<p>But we can create a <a href="https://docs.rust-embedded.org/embedonomicon/custom-target.html"><strong>Custom Rust Target</strong></a> for <strong><code>riscv32gc</code></strong>.</p>
2024-04-18 15:24:37 +08:00
<p>(Coming up next section)</p>
2024-04-16 23:00:41 +08:00
<p><em>Wont GCC Compiler have the same problem with Double-Float?</em></p>
2024-04-17 22:56:36 +08:00
<p>When we list the <strong>Built-In GCC Targets</strong></p>
<div class="example-wrap"><pre class="language-bash"><code>## List the Built-In Targets for GCC RISC-V.
2024-04-16 23:00:41 +08:00
## ABI means Application Binary Interface
$ riscv64-unknown-elf-gcc --target-help
Supported ABIs (for use with the -mabi= option):
ilp32 ilp32d ilp32e ilp32f lp64 lp64d lp64f
</code></pre></div>
<p>We see that <strong>GCC supports Double-Float</strong>: <strong><code>ilp32d</code></strong></p>
2024-04-12 19:40:46 +08:00
<ul>
2024-04-16 23:00:41 +08:00
<li><strong><code>ilp32</code></strong>: <strong>32-bit</strong> Int, Long and Pointer</li>
<li><strong><code>d</code></strong>: <strong>Double-Precision</strong> Hardware Floating-Point</li>
2024-04-12 19:40:46 +08:00
</ul>
2024-04-16 23:00:41 +08:00
<p>Thats why we saw <strong><code>ilp32d</code></strong> earlier…</p>
2024-04-16 23:55:48 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## GCC compiles for RISC-V 32-bit (Double-Float)
2024-04-16 23:00:41 +08:00
riscv64-unknown-elf-gcc \
-march=rv32imafdc \
-mabi=ilp32d \
...
2024-04-15 07:36:02 +08:00
</code></pre></div>
2024-04-18 15:24:37 +08:00
<p>Well make something similar for Rust Compiler…</p>
2024-04-19 14:03:39 +08:00
<p><a href="https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html#index-mabi-5">(More about <strong>Application Binary Interface</strong>)</a></p>
2024-04-17 22:56:36 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-flow1a.jpg" alt="Custom Target for Rust" /></p>
2024-04-15 07:36:02 +08:00
<h1 id="custom-target-for-rust"><a class="doc-anchor" href="#custom-target-for-rust">§</a>3 Custom Target for Rust</h1>
2024-04-16 23:55:48 +08:00
<p><em>To compile Rust for Double-Float, we need a Custom Target: riscv32gc</em></p>
<p><em>How to create the Custom Target?</em></p>
2024-04-17 08:49:53 +08:00
<p>According to the <a href="https://docs.rust-embedded.org/embedonomicon/custom-target.html"><strong>Official Rust Docs</strong></a>, we shall…</p>
<ul>
<li>
2024-04-17 22:56:36 +08:00
<p>Copy from a <strong>Built-In Rust Target</strong></p>
2024-04-17 08:49:53 +08:00
<p>(Like <strong><code>riscv32i</code></strong>)</p>
</li>
<li>
<p>Tweak it to fit our <strong>Custom Rust Target</strong></p>
<p>(Which becomes <strong><code>riscv32gc</code></strong>)</p>
</li>
</ul>
2024-04-18 23:36:42 +08:00
<p>This is how we dump a Built-In Rust Target: <a href="https://gist.github.com/lupyuen/dd6a2ee58902e7925efd2a889bc0a833"><strong><code>riscv32i</code></strong></a></p>
2024-04-17 22:56:36 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Dump the Built-In Rust Target:
2024-04-16 23:55:48 +08:00
## riscv32i (32-bit RISC-V with Soft-Float)
$ rustc \
2024-04-12 19:40:46 +08:00
+nightly \
-Z unstable-options \
--print target-spec-json \
--target riscv32i-unknown-none-elf
{
2024-04-16 23:55:48 +08:00
&quot;arch&quot;: &quot;riscv32&quot;,
&quot;atomic-cas&quot;: false,
&quot;cpu&quot;: &quot;generic-rv32&quot;,
2024-04-12 19:40:46 +08:00
&quot;data-layout&quot;: &quot;e-m:e-p:32:32-i64:64-n32-S128&quot;,
2024-04-16 23:55:48 +08:00
&quot;eh-frame-header&quot;: false,
2024-04-12 19:40:46 +08:00
&quot;emit-debug-gdb-scripts&quot;: false,
2024-04-16 23:55:48 +08:00
&quot;is-builtin&quot;: true,
&quot;linker&quot;: &quot;rust-lld&quot;,
&quot;linker-flavor&quot;: &quot;ld.lld&quot;,
&quot;llvm-target&quot;: &quot;riscv32&quot;,
&quot;max-atomic-width&quot;: 0,
&quot;panic-strategy&quot;: &quot;abort&quot;,
&quot;relocation-model&quot;: &quot;static&quot;,
2024-04-12 19:40:46 +08:00
&quot;target-pointer-width&quot;: &quot;32&quot;
}
2024-04-16 23:55:48 +08:00
</code></pre></div>
2024-04-18 23:36:42 +08:00
<p>Thats the Rust Definition of <a href="https://gist.github.com/lupyuen/dd6a2ee58902e7925efd2a889bc0a833"><strong><code>riscv32i</code></strong></a>: <strong>32-bit</strong> RISC-V with <strong>Soft-Float</strong>.</p>
<p>We do the same for <a href="https://gist.github.com/lupyuen/9f269598bda11215832bd91a592d00a2"><strong><code>riscv64gc</code></strong></a>: <strong>64-bit</strong> RISC-V with <strong>Double-Float</strong></p>
2024-04-17 22:56:36 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Dump the Built-In Rust Target:
2024-04-18 23:36:42 +08:00
## riscv64gc (64-bit RISC-V with Double-Float)
2024-04-12 19:40:46 +08:00
$ rustc \
+nightly \
-Z unstable-options \
--print target-spec-json \
--target riscv64gc-unknown-none-elf
{
2024-04-16 23:55:48 +08:00
&quot;arch&quot;: &quot;riscv64&quot;,
&quot;code-model&quot;: &quot;medium&quot;,
&quot;cpu&quot;: &quot;generic-rv64&quot;,
2024-04-12 19:40:46 +08:00
&quot;data-layout&quot;: &quot;e-m:e-p:64:64-i64:64-i128:128-n32:64-S128&quot;,
2024-04-16 23:55:48 +08:00
&quot;eh-frame-header&quot;: false,
2024-04-12 19:40:46 +08:00
&quot;emit-debug-gdb-scripts&quot;: false,
2024-04-16 23:55:48 +08:00
&quot;features&quot;: &quot;+m,+a,+f,+d,+c&quot;,
&quot;is-builtin&quot;: true,
&quot;linker&quot;: &quot;rust-lld&quot;,
2024-04-12 19:40:46 +08:00
&quot;linker-flavor&quot;: &quot;ld.lld&quot;,
2024-04-16 23:55:48 +08:00
&quot;llvm-abiname&quot;: &quot;lp64d&quot;,
&quot;llvm-target&quot;: &quot;riscv64&quot;,
&quot;max-atomic-width&quot;: 64,
&quot;panic-strategy&quot;: &quot;abort&quot;,
&quot;relocation-model&quot;: &quot;static&quot;,
&quot;supported-sanitizers&quot;: [ &quot;kernel-address&quot; ],
2024-04-12 19:40:46 +08:00
&quot;target-pointer-width&quot;: &quot;64&quot;
}
</code></pre></div>
2024-04-20 00:07:45 +08:00
<p>Which has more goodies inside: features, llvm-abiname, …</p>
2024-04-19 15:32:50 +08:00
<p><em>Were mashing the Two Targets into a New Target?</em></p>
2024-04-16 23:55:48 +08:00
<p>Exactly! Based on the above, we create our <strong>Rust Custom Target</strong>: <a href="https://github.com/lupyuen/nuttx-rust-app/blob/main/riscv32gc-unknown-none-elf.json"><em>riscv32gc-unknown-none-elf.json</em></a></p>
2024-04-12 19:40:46 +08:00
<div class="example-wrap"><pre class="language-json"><code>{
2024-04-16 23:55:48 +08:00
&quot;arch&quot;: &quot;riscv32&quot;,
&quot;cpu&quot;: &quot;generic-rv32&quot;,
2024-04-12 19:40:46 +08:00
&quot;data-layout&quot;: &quot;e-m:e-p:32:32-i64:64-n32-S128&quot;,
2024-04-16 23:55:48 +08:00
&quot;eh-frame-header&quot;: false,
2024-04-12 19:40:46 +08:00
&quot;emit-debug-gdb-scripts&quot;: false,
2024-04-16 23:55:48 +08:00
&quot;features&quot;: &quot;+m,+a,+f,+d,+c&quot;,
&quot;linker&quot;: &quot;rust-lld&quot;,
2024-04-12 19:40:46 +08:00
&quot;linker-flavor&quot;: &quot;ld.lld&quot;,
2024-04-16 23:55:48 +08:00
&quot;llvm-abiname&quot;: &quot;ilp32d&quot;,
&quot;llvm-target&quot;: &quot;riscv32&quot;,
&quot;max-atomic-width&quot;: 0,
&quot;panic-strategy&quot;: &quot;abort&quot;,
&quot;relocation-model&quot;: &quot;static&quot;,
2024-04-12 19:40:46 +08:00
&quot;target-pointer-width&quot;: &quot;32&quot;
}
</code></pre></div>
2024-04-18 23:36:42 +08:00
<p>Which is <a href="https://gist.github.com/lupyuen/dd6a2ee58902e7925efd2a889bc0a833"><strong><code>riscv32i</code></strong></a> plus these changes…</p>
2024-04-12 19:40:46 +08:00
<ul>
<li>
2024-04-17 13:08:40 +08:00
<p>Remove <em>“is-builtin”: true</em></p>
2024-04-17 22:56:36 +08:00
<p>(Its a <strong>Custom Target</strong>, not Built-In)</p>
2024-04-12 19:40:46 +08:00
</li>
<li>
2024-04-17 13:08:40 +08:00
<p>Remove <em>“atomic-cas”: false</em></p>
2024-04-18 14:50:16 +08:00
<p><a href="https://en.m.wikipedia.org/wiki/Compare-and-swap">(Enable <strong>Atomic Compare-And-Swap</strong>)</a></p>
2024-04-12 19:40:46 +08:00
</li>
<li>
2024-04-17 13:08:40 +08:00
<p>Add <em>“features”: “+m,+a,+f,+d,+c”</em></p>
2024-04-19 12:39:45 +08:00
<p><a href="https://lupyuen.github.io/articles/rust4#software-vs-hardware-floating-point">(Because we need <strong>IMAFDC</strong>)</a></p>
2024-04-12 19:40:46 +08:00
</li>
<li>
2024-04-17 13:08:40 +08:00
<p>Add <em>“llvm-abiname”: “ilp32d”</em></p>
2024-04-20 00:07:45 +08:00
<p><a href="https://lupyuen.github.io/articles/rust4#software-vs-hardware-floating-point">(<strong><code>ilp32d</code></strong> comes from <strong><code>make</code> <code>--trace</code></strong>)</a></p>
2024-04-16 23:55:48 +08:00
<p><a href="https://lupyuen.github.io/articles/rust#custom-rust-target-for-bl602">(More about <strong><code>llvm-abiname</code></strong>)</a></p>
2024-04-12 19:40:46 +08:00
</li>
</ul>
2024-04-19 15:32:50 +08:00
<p>In Summary: We spliced Two Built-In Targets into Custom Target <strong><code>riscv32gc</code></strong></p>
2024-04-17 10:28:26 +08:00
<span style="font-size:80%">
2024-04-18 23:36:42 +08:00
<div><table><thead><tr><th></th><th style="text-align: center"><a href="https://gist.github.com/lupyuen/dd6a2ee58902e7925efd2a889bc0a833">riscv32i</a> <br> <em>(Built-In)</em></th><th style="text-align: center"><a href="https://gist.github.com/lupyuen/9f269598bda11215832bd91a592d00a2">riscv64gc</a> <br> <em>(Built-In)</em></th><th style="text-align: center"><a href="https://github.com/lupyuen/nuttx-rust-app/blob/main/riscv32gc-unknown-none-elf.json">riscv32gc</a> <br> <em>(Custom)</em></th></tr></thead><tbody>
2024-04-17 08:49:53 +08:00
<tr><td><em>arch</em></td><td style="text-align: center"><strong>riscv32</strong></td><td style="text-align: center">riscv64</td><td style="text-align: center"><strong>riscv32</strong></td></tr>
<tr><td><em>atomic-cas</em></td><td style="text-align: center">false</td><td style="text-align: center"></td><td style="text-align: center"></td></tr>
<tr><td><em>cpu</em></td><td style="text-align: center"><strong>generic-rv32</strong></td><td style="text-align: center">generic-rv64</td><td style="text-align: center"><strong>generic-rv32</strong></td></tr>
<tr><td><em>data-layout</em></td><td style="text-align: center"><strong>e-m:e-p:32…</strong></td><td style="text-align: center">e-m:e-p:64…</td><td style="text-align: center"><strong>e-m:e-p:32…</strong></td></tr>
<tr><td><em>features</em></td><td style="text-align: center"></td><td style="text-align: center"><strong>+m,+a,+f,+d,+c</strong></td><td style="text-align: center"><strong>+m,+a,+f,+d,+c</strong></td></tr>
<tr><td><em>is-builtin</em></td><td style="text-align: center">true</td><td style="text-align: center">true</td><td style="text-align: center"></td></tr>
<tr><td><em>llvm-abiname</em></td><td style="text-align: center"></td><td style="text-align: center">lp64d</td><td style="text-align: center">ilp32d</td></tr>
<tr><td><em>llvm-target</em></td><td style="text-align: center"><strong>riscv32</strong></td><td style="text-align: center">riscv64</td><td style="text-align: center"><strong>riscv32</strong></td></tr>
<tr><td><em>max-atomic-width</em></td><td style="text-align: center"></td><td style="text-align: center">64</td><td style="text-align: center">0</td></tr>
<tr><td><em>target-pointer-width</em></td><td style="text-align: center"><strong>32</strong></td><td style="text-align: center">64</td><td style="text-align: center"><strong>32</strong></td></tr>
2024-04-16 23:55:48 +08:00
</tbody></table>
</div></span>
2024-04-17 22:56:36 +08:00
<blockquote>
<p><img src="https://lupyuen.github.io/images/rust4-flow1b.jpg" alt="Build the Rust Core Library" /></p>
</blockquote>
2024-04-15 07:36:02 +08:00
<h1 id="build-the-rust-core-library"><a class="doc-anchor" href="#build-the-rust-core-library">§</a>4 Build the Rust Core Library</h1>
2024-04-18 15:24:37 +08:00
<p><em>Are we ready to rebuild with Double-Float?</em></p>
<p>Not quite, were not done with the <strong>System Library</strong></p>
2024-04-17 13:51:00 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Rust Compiler fails to compile with our Custom Target `riscv32gc`
2024-04-17 13:33:17 +08:00
$ rustc \
2024-04-17 13:08:40 +08:00
--target riscv32gc-unknown-none-elf.json \
--edition 2021 \
--emit obj \
-g \
-C panic=abort \
-O \
hello_rust_main.rs \
-o hello_rust.o
2024-04-17 13:51:00 +08:00
## That&#39;s because Rust Core Library for `riscv32gc` is missing
2024-04-17 13:08:40 +08:00
error[E0463]: can&#39;t find crate for `core`
</code></pre></div>
<p>Why? Remember…</p>
2024-04-17 08:49:53 +08:00
<ul>
<li>
<p><strong>GCC Compiler</strong> supports Double-Float…</p>
2024-04-18 15:24:37 +08:00
<p>Because its bundled with <strong>C Standard Library</strong> for Double-Float</p>
2024-04-17 08:49:53 +08:00
</li>
<li>
2024-04-18 15:24:37 +08:00
<p>Thus <strong>Rust Compiler</strong> will support Double-Float…</p>
2024-04-18 23:36:42 +08:00
<p>Only when it has the <a href="https://lupyuen.github.io/articles/rust3#standard-vs-embedded-rust"><strong>Rust Core Library</strong></a> for Double-Float</p>
2024-04-17 08:49:53 +08:00
</li>
</ul>
2024-04-17 10:28:26 +08:00
<p><em>And the Rust Core Library comes from?</em></p>
<p>We call Rust Compiler to build the <strong>Rust Core Library</strong> for Double-Float <strong><code>riscv32gc</code></strong></p>
2024-04-17 13:08:40 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Download our Custom Target for `riscv32gc`
2024-04-18 18:55:16 +08:00
rm -f riscv32gc-unknown-none-elf.json
2024-04-17 13:08:40 +08:00
wget https://raw.githubusercontent.com/lupyuen/nuttx-rust-app/main/riscv32gc-unknown-none-elf.json
2024-04-17 10:28:26 +08:00
## Verify our Custom Target, make sure it&#39;s OK
2024-04-12 19:40:46 +08:00
rustc \
--print cfg \
--target riscv32gc-unknown-none-elf.json
2024-04-17 17:19:16 +08:00
## `cargo build` requires a Rust Project, so we create an empty one.
## If the Rust Project exists, erase the binaries.
2024-04-12 19:40:46 +08:00
## Ignore the error: `app already exists`
cargo new app
pushd app
cargo clean
2024-04-17 10:28:26 +08:00
## Build the Rust Core Library for `riscv32gc`
2024-04-17 13:08:40 +08:00
## Include the `alloc` library, which will support Heap Memory in future.
2024-04-12 19:40:46 +08:00
## Ignore the error: `can&#39;t find crate for std`
cargo build \
-Zbuild-std=core,alloc \
--target ../riscv32gc-unknown-none-elf.json
popd
</code></pre></div>
2024-04-17 13:08:40 +08:00
<p><strong>Rust Core Library</strong> for Double-Float <strong><code>riscv32gc</code></strong> is done!</p>
<div class="example-wrap"><pre class="language-bash"><code>## Show the Rust Core Library for `riscv32gc`
$ ls app/target/riscv32gc-unknown-none-elf/debug/deps
alloc-254848389e7e2c53.d
app-cf88b81a5fca23b3.d
compiler_builtins-d5922d64507adf16.d
core-ec2ec78e26b8c830.d
liballoc-254848389e7e2c53.rlib
liballoc-254848389e7e2c53.rmeta
libcompiler_builtins-d5922d64507adf16.rlib
libcompiler_builtins-d5922d64507adf16.rmeta
libcore-ec2ec78e26b8c830.rlib
libcore-ec2ec78e26b8c830.rmeta
librustc_std_workspace_core-3cc5bcc9f701a6e7.rlib
librustc_std_workspace_core-3cc5bcc9f701a6e7.rmeta
rustc_std_workspace_core-3cc5bcc9f701a6e7.d
</code></pre></div>
2024-04-18 15:24:37 +08:00
<p>Now we <strong>rebuild our Rust App</strong> with the Custom Target (linked to our Rust Core Library)…</p>
2024-04-17 18:55:50 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Compile our Rust App with Rust Core Library for `riscv32gc`
2024-04-17 13:08:40 +08:00
## We changed the Target to `riscv32gc-unknown-none-elf.json`
## TODO: Change `../apps` to the NuttX Apps Folder
2024-04-12 19:40:46 +08:00
rustc \
2024-04-16 23:00:41 +08:00
--target riscv32gc-unknown-none-elf.json \
2024-04-12 19:40:46 +08:00
--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
2024-04-17 13:08:40 +08:00
</code></pre></div>
2024-04-17 13:28:53 +08:00
<p>(Well talk about the loooong options)</p>
<p><em>Are we Double-Floating yet?</em></p>
2024-04-18 15:24:37 +08:00
<p>Yep we have a <strong>Yummy Double-Float</strong> with 2 scoops of ice cream…</p>
2024-04-17 13:28:53 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Dump the ELF Header of our Compiled Rust App
2024-04-17 13:08:40 +08:00
## TODO: Change `../apps` to the NuttX Apps Folder
2024-04-17 13:28:53 +08:00
$ riscv64-unknown-elf-readelf \
2024-04-15 10:45:47 +08:00
--file-header --arch-specific \
2024-04-12 19:40:46 +08:00
../apps/examples/hello_rust/*hello_rust.o
2024-04-17 13:28:53 +08:00
## We have Double-Float `riscv32gc` yay!
Flags: 0x5, RVC, double-float ABI
2024-04-17 13:08:40 +08:00
</code></pre></div>
2024-04-18 00:38:42 +08:00
<p><a href="https://gist.github.com/lupyuen/e7cdef603bdb16fbc82c2bf940b5d2d8">(See the <strong>ELF Header</strong>)</a></p>
2024-04-18 11:31:42 +08:00
<p><em>How did we get the Rust Compiler Options?</em></p>
2024-04-19 15:37:50 +08:00
<p>We copied the above options from <strong><code>cargo</code> <code>build</code> <code>-v</code></strong></p>
2024-04-18 11:31:42 +08:00
<ul>
2024-04-19 12:39:45 +08:00
<li><a href="https://lupyuen.github.io/articles/rust4#appendix-rust-compiler-options"><strong>“Rust Compiler Options”</strong></a></li>
2024-04-18 11:31:42 +08:00
</ul>
2024-04-18 10:21:21 +08:00
<p><em>rustc vs cargo build: Whats the diff?</em></p>
<ul>
<li>
<p><strong><code>rustc</code></strong> is the Rust Compiler that compiles Rust Programs to Rust Binaries</p>
<p>(Works like GCC Compiler)</p>
</li>
<li>
2024-04-19 15:37:50 +08:00
<p><strong><code>cargo</code> <code>build</code></strong> wraps around <strong><code>rustc</code></strong> for Multi-Step Builds</p>
2024-04-18 23:36:42 +08:00
<p><a href="https://lupyuen.github.io/articles/rust3#standard-vs-embedded-rust">(Like for <strong>Rust Core Library</strong>)</a></p>
2024-04-18 10:21:21 +08:00
</li>
</ul>
2024-04-19 12:39:45 +08:00
<p>We could have called <strong><code>rustc</code></strong> for building the Rust Core Library. But it will be a bunch of steps with <a href="https://lupyuen.github.io/articles/rust4#appendix-rust-compiler-options"><strong>many many options</strong></a>.</p>
2024-04-17 17:19:16 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-flow.jpg" alt="NuttX Links OK with Rust" /></p>
<h1 id="nuttx-links-ok-with-rust"><a class="doc-anchor" href="#nuttx-links-ok-with-rust">§</a>5 NuttX Links OK with Rust</h1>
2024-04-18 14:50:16 +08:00
<p><em>We compiled our Rust App with Double-Float riscv32gc…</em></p>
2024-04-17 17:19:16 +08:00
<p><em>Is our NuttX Build hunky dory now?</em></p>
2024-04-17 18:55:50 +08:00
<p>Yep <strong>NuttX builds OK now</strong>! GCC Compiler and Rust Compiler are harmonised to Double-Float…</p>
2024-04-17 17:19:16 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Copy the Rust Binary that will be linked with NuttX
## TODO: Change `../apps` to the NuttX Apps Folder
cp \
../apps/examples/hello_rust/*hello_rust.o \
../apps/examples/hello_rust/*hello_rust_1.o
## NuttX should link correctly now.
## TODO: Change `../nuttx` to the NuttX Kernel Folder
pushd ../nuttx
make
popd
</code></pre></div>
<p>We boot <strong>NuttX in QEMU Emulator</strong> for 32-bit RISC-V…</p>
2024-04-19 15:32:50 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## For macOS:
brew install qemu
## For Debian and Ubuntu:
sudo apt install qemu-system-riscv32
## Boot NuttX in QEMU RISC-V (32-bit)
2024-04-17 17:19:16 +08:00
## TODO: Change `../nuttx` to the NuttX Kernel Folder
pushd ../nuttx
qemu-system-riscv32 \
-semihosting \
-M virt,aclint=on \
-cpu rv32 \
-smp 8 \
-bios none \
-kernel nuttx \
-nographic
popd
</code></pre></div>
<p>Our <strong>Rust App</strong> works wonderfully on NuttX! (Pic below)</p>
<div class="example-wrap"><pre class="language-bash"><code>NuttShell (NSH) NuttX-12.4.0-RC0
nsh&gt; hello_rust
Hello, Rust!!
## Exit QEMU: Press `Ctrl-A` then `x`
</code></pre></div>
<p><a href="https://gist.github.com/lupyuen/31c78de72ade71bbdf63372b44749cd4#file-rust-on-nuttx-build-log-L356-L384">(See the <strong>NuttX Log</strong>)</a></p>
2024-04-18 17:04:05 +08:00
<p><em>Phew so much work to build a tiny Rust App?</em></p>
2024-04-17 17:44:28 +08:00
<p>Yeah. And integrating this into the <strong>NuttX Makefiles</strong> will be challenging.</p>
2024-04-18 23:36:42 +08:00
<p>(How would <a href="https://rust-for-linux.com/"><strong>Linux Kernel</strong></a> handle Custom Rust Targets?)</p>
2024-04-17 17:44:28 +08:00
<p>TODO: <a href="https://github.com/rust-lang/rust/issues/65024">Allow building for hard-float targets in RISC-V</a></p>
2024-04-17 17:19:16 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-title.jpg" alt="Rust Apps on Apache NuttX RTOS and QEMU RISC-V" /></p>
2024-04-15 07:36:02 +08:00
<h1 id="rust-build-for-64-bit-risc-v"><a class="doc-anchor" href="#rust-build-for-64-bit-risc-v">§</a>6 Rust Build for 64-bit RISC-V</h1>
2024-04-19 15:32:50 +08:00
<p>From 32-bit to 64-bit: We tried compiling our Rust App for <strong>64-bit RISC-V QEMU</strong></p>
2024-04-18 14:50:16 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Build NuttX for QEMU RISC-V 64-bit
$ tools/configure.sh rv-virt:nsh64
2024-04-15 07:36:02 +08:00
$ make menuconfig
## TODO: Enable &quot;Hello Rust Example&quot;
$ make
RUSTC: hello_rust_main.rs error: Error loading target specification:
Could not find specification for target &quot;riscv64i-unknown-none-elf&quot;.
Run `rustc --print target-list` for a list of built-in targets
</code></pre></div>
2024-04-18 14:50:16 +08:00
<p>But Rust Compiler says that <strong><code>riscv64i</code></strong> isnt a valid Rust Target for 64-bit RISC-V.</p>
<p><strong>Exercise for the Reader:</strong></p>
<ol>
<li>
<p>Is <strong><code>riscv64i</code></strong> the correct target for QEMU?</p>
2024-04-19 12:39:45 +08:00
<p><a href="https://www.qemu.org/docs/master/system/riscv/virt.html#supported-devices">(<strong>Hint:</strong> See this)</a></p>
2024-04-18 14:50:16 +08:00
<p><em>[10 points]</em></p>
2024-04-18 17:04:05 +08:00
<hr>
2024-04-18 14:50:16 +08:00
</li>
<li>
<p>How should we <strong>Fix the Build</strong>?</p>
<p><em>[10 points]</em></p>
2024-04-18 17:04:05 +08:00
<hr>
2024-04-18 14:50:16 +08:00
</li>
<li>
<p>Do we need a <strong>Custom Target</strong>?</p>
<p>(<strong>Hint:</strong> Answer is printed in this article somewhere)</p>
<p><em>[10 points]</em></p>
2024-04-18 17:04:05 +08:00
<hr>
2024-04-18 14:50:16 +08:00
</li>
<li>
2024-04-18 23:36:42 +08:00
<p>Will it run on <a href="https://www.hackster.io/lupyuen/8-risc-v-sbc-on-a-real-time-operating-system-ox64-nuttx-474358"><strong>Ox64 BL808 SBC</strong></a>?</p>
2024-04-18 14:50:16 +08:00
<p><em>[10 points]</em></p>
2024-04-18 17:04:05 +08:00
<hr>
2024-04-18 14:50:16 +08:00
</li>
</ol>
2024-04-18 17:06:07 +08:00
<p><img src="https://lupyuen.github.io/images/rust4-flow.jpg" alt="NuttX Links OK with Rust" /></p>
2024-04-15 07:36:02 +08:00
<h1 id="whats-next"><a class="doc-anchor" href="#whats-next">§</a>7 Whats Next</h1>
2024-04-20 00:07:45 +08:00
<p>Today we learnt a bit more about <strong>C-to-Rust Interop</strong> (pic above)…</p>
<ul>
<li>
<p>TODO: Rust compiles for <strong>Soft-Float</strong>, NuttX expects <strong>Double-Float</strong></p>
<p>(Software vs Hardware Floating-Point)</p>
</li>
<li>
<p>TODO: But Rust <strong>doesnt support Double-Float</strong> (by default)</p>
</li>
<li>
<p>TODO: So we create a <strong>Rust Custom Target</strong> for Double-Float</p>
</li>
<li>
<p>TODO: Rebuild the <strong>Rust Core Library</strong> for Double-Float</p>
</li>
<li>
<p>TODO: And our Rust App <strong>builds OK with NuttX</strong>!</p>
</li>
</ul>
2024-04-15 07:36:02 +08:00
<p>Many Thanks to my <a href="https://github.com/sponsors/lupyuen"><strong>GitHub Sponsors</strong></a> (and the awesome NuttX Community) for supporting my work! This article wouldnt have been possible without your support.</p>
<ul>
<li>
<p><a href="https://github.com/sponsors/lupyuen"><strong>Sponsor me a coffee</strong></a></p>
</li>
<li>
<p><a href="https://github.com/lupyuen/nuttx-ox64"><strong>My Current Project: “Apache NuttX RTOS for Ox64 BL808”</strong></a></p>
</li>
<li>
<p><a href="https://github.com/lupyuen/nuttx-star64"><strong>My Other Project: “NuttX for Star64 JH7110”</strong></a></p>
</li>
<li>
<p><a href="https://github.com/lupyuen/pinephone-nuttx"><strong>Older Project: “NuttX for PinePhone”</strong></a></p>
</li>
<li>
<p><a href="https://lupyuen.github.io"><strong>Check out my articles</strong></a></p>
</li>
<li>
<p><a href="https://lupyuen.github.io/rss.xml"><strong>RSS Feed</strong></a></p>
</li>
</ul>
<p><em>Got a question, comment or suggestion? Create an Issue or submit a Pull Request here…</em></p>
<p><a href="https://github.com/lupyuen/lupyuen.github.io/blob/master/src/rust4.md"><strong>lupyuen.github.io/src/rust4.md</strong></a></p>
2024-04-17 23:16:58 +08:00
<blockquote>
<p><img src="https://lupyuen.github.io/images/rust4-flow1b.jpg" alt="Building our Rust App" /></p>
</blockquote>
2024-04-15 07:36:02 +08:00
<h1 id="appendix-rust-compiler-options"><a class="doc-anchor" href="#appendix-rust-compiler-options">§</a>8 Appendix: Rust Compiler Options</h1>
2024-04-18 10:21:21 +08:00
<p><em>How did we get the Rust Compiler Options for riscv32gc?</em></p>
<p>Earlier we compiled our Rust App with Rust Core Library for <strong><code>riscv32gc</code></strong></p>
<ul>
2024-04-19 12:39:45 +08:00
<li><a href="https://lupyuen.github.io/articles/rust4#build-the-rust-core-library"><strong>“Build the Rust Core Library”</strong></a></li>
2024-04-18 10:21:21 +08:00
</ul>
<p>And we saw these <strong>Rust Compiler Options</strong></p>
2024-04-17 18:55:50 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Compile our Rust App with Rust Core Library for `riscv32gc`
## We changed the Target to `riscv32gc-unknown-none-elf.json`
## TODO: Change `../apps` to the NuttX Apps Folder
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
</code></pre></div>
2024-04-19 15:37:50 +08:00
<p>The above options were copied from <strong><code>cargo</code> <code>build</code> <code>-v</code></strong>, heres how…</p>
<p>Remember we ran <a href="https://lupyuen.github.io/articles/rust4#build-the-rust-core-library"><strong><code>cargo</code> <code>build</code></strong></a> to compile the <a href="https://lupyuen.github.io/articles/rust3#standard-vs-embedded-rust"><strong>Rust Core Library</strong></a>?</p>
2024-04-18 18:55:16 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## 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
## Verify our Custom Target, make sure it&#39;s OK
rustc \
--print cfg \
--target riscv32gc-unknown-none-elf.json
## `cargo build` requires a Rust Project, so we create an empty one.
## If the Rust Project exists, erase the binaries.
## Ignore the error: `app already exists`
cargo new app
pushd app
cargo clean
## Build the Rust Core Library for `riscv32gc`
## Include the `alloc` library, which will support Heap Memory in future.
## Ignore the error: `can&#39;t find crate for std`
cargo build \
2024-04-17 18:55:50 +08:00
-Zbuild-std=core,alloc \
--target ../riscv32gc-unknown-none-elf.json
2024-04-18 18:55:16 +08:00
popd
2024-04-17 18:55:50 +08:00
</code></pre></div>
2024-04-18 18:55:16 +08:00
<ul>
<li>
2024-04-19 15:37:50 +08:00
<p><strong><code>cargo</code> <code>build</code></strong> will call <strong><code>rustc</code></strong> with a whole bunch of options.</p>
2024-04-18 18:55:16 +08:00
</li>
<li>
2024-04-19 15:37:50 +08:00
<p>We switched it to <strong><code>cargo</code> <code>build</code> <code>-v</code></strong>, which will dump the <strong><code>rustc</code></strong> options.</p>
2024-04-18 18:55:16 +08:00
</li>
<li>
2024-04-17 18:55:50 +08:00
<p>Hence we see the options that will compile a Rust App with our Rust Core Library for <strong><code>riscv32gc</code></strong></p>
2024-04-17 22:56:36 +08:00
<p>(TODO: Will these options change in future versions of <strong><code>cargo</code></strong>?)</p>
2024-04-18 18:55:16 +08:00
</li>
</ul>
2024-04-17 18:55:50 +08:00
<div class="example-wrap"><pre class="language-bash"><code>## Build the Rust Core Library for `riscv32gc`
## And the Empty Rust Project for `riscv32gc`
## `-v` will dump the `rustc` options
$ cargo build -v \
2024-04-12 19:40:46 +08:00
-Zbuild-std=core,alloc \
--target ../riscv32gc-unknown-none-elf.json
Compiling compiler_builtins v0.1.101
Compiling core v0.0.0 ($HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/core)
2024-04-17 18:55:50 +08:00
## Generate the Rust Build Script for `riscv32gc`
Running `$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/bin/rustc
--crate-name build_script_build
2024-04-17 22:56:36 +08:00
--edition=2018
$HOME/.cargo/registry/src/index.crates.io-6f17d22bba15001f/compiler_builtins-0.1.101/build.rs
2024-04-17 18:55:50 +08:00
--error-format=json
--json=diagnostic-rendered-ansi,artifacts,future-incompat
--diagnostic-width=94
--crate-type bin
--emit=dep-info,link
-C embed-bitcode=no
-C debuginfo=2
-C split-debuginfo=unpacked
--cfg &#39;feature=&quot;compiler-builtins&quot;&#39;
--cfg &#39;feature=&quot;core&quot;&#39;
--cfg &#39;feature=&quot;default&quot;&#39;
--cfg &#39;feature=&quot;rustc-dep-of-std&quot;&#39;
-C metadata=9bd0bac7535b33a8
-C extra-filename=-9bd0bac7535b33a8
--out-dir $HOME/riscv/nuttx-rust-app/app/target/debug/build/compiler_builtins-9bd0bac7535b33a8
-Z force-unstable-if-unmarked
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/debug/deps
--cap-lints allow`
## Build the Rust Core Library for `riscv32gc`
Running `$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/bin/rustc
--crate-name core
2024-04-17 22:56:36 +08:00
--edition=2021
$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/lib.rs
2024-04-17 18:55:50 +08:00
--error-format=json
--json=diagnostic-rendered-ansi,artifacts,future-incompat
--diagnostic-width=94
--crate-type lib
--emit=dep-info,metadata,link
-C embed-bitcode=no
-C debuginfo=2
-C metadata=d271c6ebb87f9b41
-C extra-filename=-d271c6ebb87f9b41
--out-dir $HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
--target $HOME/riscv/nuttx-rust-app/riscv32gc-unknown-none-elf.json
-Z force-unstable-if-unmarked
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/debug/deps
--cap-lints allow`
2024-04-12 19:40:46 +08:00
Running `$HOME/riscv/nuttx-rust-app/app/target/debug/build/compiler_builtins-9bd0bac7535b33a8/build-script-build`
2024-04-17 18:55:50 +08:00
2024-04-12 19:40:46 +08:00
Compiling rustc-std-workspace-core v1.99.0 ($HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/rustc-std-workspace-core)
2024-04-17 18:55:50 +08:00
## Build the Rust Workspace Core for `riscv32gc`
Running `$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/bin/rustc
--crate-name rustc_std_workspace_core
2024-04-17 22:56:36 +08:00
--edition=2021
$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/rustc-std-workspace-core/lib.rs
2024-04-17 18:55:50 +08:00
--error-format=json
--json=diagnostic-rendered-ansi,artifacts,future-incompat
--diagnostic-width=94
--crate-type lib
--emit=dep-info,metadata,link
-C embed-bitcode=no
-C debuginfo=2
-C metadata=52e0df2b2cc19b6e
-C extra-filename=-52e0df2b2cc19b6e
--out-dir $HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
--target $HOME/riscv/nuttx-rust-app/riscv32gc-unknown-none-elf.json
-Z force-unstable-if-unmarked
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/debug/deps
--extern core=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/libcore-d271c6ebb87f9b41.rmeta
--cap-lints allow`
## Build the Rust Compiler Builtins for `riscv32gc`
Running `$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/bin/rustc
--crate-name compiler_builtins
2024-04-17 22:56:36 +08:00
--edition=2018
$HOME/.cargo/registry/src/index.crates.io-6f17d22bba15001f/compiler_builtins-0.1.101/src/lib.rs
2024-04-17 18:55:50 +08:00
--error-format=json
--json=diagnostic-rendered-ansi,artifacts,future-incompat
--diagnostic-width=94
--crate-type lib
--emit=dep-info,metadata,link
-C embed-bitcode=no
-C debuginfo=2
--cfg &#39;feature=&quot;compiler-builtins&quot;&#39;
--cfg &#39;feature=&quot;core&quot;&#39;
--cfg &#39;feature=&quot;default&quot;&#39;
--cfg &#39;feature=&quot;rustc-dep-of-std&quot;&#39;
-C metadata=cd0d33c2bd30ca51
-C extra-filename=-cd0d33c2bd30ca51
--out-dir $HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
--target $HOME/riscv/nuttx-rust-app/riscv32gc-unknown-none-elf.json
-Z force-unstable-if-unmarked
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/debug/deps
--extern core=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/librustc_std_workspace_core-52e0df2b2cc19b6e.rmeta
--cap-lints allow
--cfg &#39;feature=&quot;unstable&quot;&#39;
--cfg &#39;feature=&quot;mem&quot;&#39;`
2024-04-12 19:40:46 +08:00
Compiling alloc v0.0.0 ($HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc)
2024-04-17 18:55:50 +08:00
## Build the Rust Alloc Library for `riscv32gc`
## Which will support Heap Memory in future
Running `$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/bin/rustc
--crate-name alloc
2024-04-17 22:56:36 +08:00
--edition=2021
$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/lib.rs
2024-04-17 18:55:50 +08:00
--error-format=json
--json=diagnostic-rendered-ansi,artifacts,future-incompat
--diagnostic-width=94
--crate-type lib
--emit=dep-info,metadata,link
-C embed-bitcode=no
-C debuginfo=2
-C metadata=5d7bc2e4f3c29e08
-C extra-filename=-5d7bc2e4f3c29e08
--out-dir $HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
--target $HOME/riscv/nuttx-rust-app/riscv32gc-unknown-none-elf.json
-Z force-unstable-if-unmarked
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/debug/deps
--extern compiler_builtins=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/libcompiler_builtins-cd0d33c2bd30ca51.rmeta
--extern core=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/libcore-d271c6ebb87f9b41.rmeta
--cap-lints allow`
2024-04-12 19:40:46 +08:00
Compiling app v0.1.0 ($HOME/riscv/nuttx-rust-app/app)
2024-04-17 18:55:50 +08:00
## Compile our Empty Rust Project with Rust Core Library for `riscv32gc`
2024-04-19 15:32:50 +08:00
## These are the options that we copied into NuttX Build...
2024-04-17 18:55:50 +08:00
Running `$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/bin/rustc
--crate-name app
2024-04-17 22:56:36 +08:00
--edition=2021
src/main.rs
2024-04-17 18:55:50 +08:00
--error-format=json
--json=diagnostic-rendered-ansi,artifacts,future-incompat
--diagnostic-width=94
--crate-type bin
--emit=dep-info,link
-C embed-bitcode=no
-C debuginfo=2
-C metadata=1ff442e6481e1397
-C extra-filename=-1ff442e6481e1397
--out-dir $HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
--target $HOME/riscv/nuttx-rust-app/riscv32gc-unknown-none-elf.json
-C incremental=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/incremental
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps
-L dependency=$HOME/riscv/nuttx-rust-app/app/target/debug/deps
--extern &#39;noprelude:alloc=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/liballoc-5d7bc2e4f3c29e08.rlib&#39;
--extern &#39;noprelude:compiler_builtins=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/libcompiler_builtins-cd0d33c2bd30ca51.rlib&#39;
--extern &#39;noprelude:core=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/libcore-d271c6ebb87f9b41.rlib&#39;
-Z unstable-options`
## Ignore this error. Rust Standard Library and `println` won&#39;t work for `riscv32gc`
2024-04-12 19:40:46 +08:00
error[E0463]: can&#39;t find crate for `std`
|
= note: the `riscv32gc-unknown-none-elf` target may not support the standard library
= note: `std` is required by `app` because it does not declare `#![no_std]`
= help: consider building the standard library from source with `cargo build -Zbuild-std`
error: cannot find macro `println` in this scope
--&gt; src/main.rs:2:5
|
2 | println!(&quot;Hello, world!&quot;);
| ^^^^^^^
error: `#[panic_handler]` function required, but not found
For more information about this error, try `rustc --explain E0463`.
error: could not compile `app` (bin &quot;app&quot;) due to 3 previous errors
Caused by:
process didn&#39;t exit successfully: `$HOME/.rustup/toolchains/nightly-x86_64-apple-darwin/bin/rustc --crate-name app --edition=2021 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=94 --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C metadata=1ff442e6481e1397 -C extra-filename=-1ff442e6481e1397 --out-dir $HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps --target $HOME/riscv/nuttx-rust-app/riscv32gc-unknown-none-elf.json -C incremental=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/incremental -L dependency=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps -L dependency=$HOME/riscv/nuttx-rust-app/app/target/debug/deps --extern &#39;noprelude:alloc=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/liballoc-5d7bc2e4f3c29e08.rlib&#39; --extern &#39;noprelude:compiler_builtins=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/libcompiler_builtins-cd0d33c2bd30ca51.rlib&#39; --extern &#39;noprelude:core=$HOME/riscv/nuttx-rust-app/app/target/riscv32gc-unknown-none-elf/debug/deps/libcore-d271c6ebb87f9b41.rlib&#39; -Z unstable-options` (exit status: 1)
</code></pre></div>
2024-04-12 19:18:02 +08:00
<!-- Begin scripts/rustdoc-after.html: Post-HTML for Custom Markdown files processed by rustdoc, like chip8.md -->
<!-- Begin Theme Picker and Prism Theme -->
<script src="../theme.js"></script>
<script src="../prism.js"></script>
<!-- Theme Picker and Prism Theme -->
<!-- End scripts/rustdoc-after.html -->
</body>
</html>