Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
fa1b9ce
[rust] Add initial Rust support
d3zd3z Oct 14, 2025
7db7396
[rust] Add lk-sys
d3zd3z Oct 14, 2025
55bd31e
[rust] basic "lk" crate
d3zd3z Oct 14, 2025
b06339d
[rust] Conditionalize rust support
d3zd3z Oct 14, 2025
57629d2
[rust][pl011] Add a Rust PL011 driver
d3zd3z Oct 14, 2025
9204f8c
rust: build.mk: Suppress llvm-objdump warnings
d3zd3z Oct 8, 2025
67a4ebf
[rust] Only ignore target within the rust directory
d3zd3z Oct 16, 2025
a06d58f
[rust] Use abspath for crate references
d3zd3z Oct 16, 2025
2ab36a1
fix [rust] module definitions in rules.mk
d3zd3z Oct 16, 2025
c084925
[github][rust] Add a workflow to test Rust builds
d3zd3z Oct 17, 2025
3487e39
[rust] Add MIT license headers and declarations
d3zd3z Oct 17, 2025
f1e1d9c
[rust] Build core/alloc
d3zd3z Oct 21, 2025
3679b33
[rust] Disable neon in aarch64 builds
d3zd3z Oct 21, 2025
ad4f90a
[ci][rust] Install nightly compiler for rust
d3zd3z Oct 21, 2025
4a3f1cf
[rust][arm64] Build properly for softfloat
d3zd3z Oct 22, 2025
97e3dc9
[rust][lk][log] Rename Trusty to LK
d3zd3z Oct 23, 2025
29722ec
[rust] Clean up HAVE/USE RUST configuration
d3zd3z Oct 27, 2025
6ea66e6
[rust] Allow modules to declare themselves as Rust crates
d3zd3z Oct 28, 2025
e0dae4b
[rust][rust_hello] Very basic Rust hello world app
d3zd3z Oct 28, 2025
c6ff4e1
[rust] Enhance app framework within Rust
d3zd3z Oct 31, 2025
5f59a70
[build] allow modules with no source files defined
travisg Nov 18, 2025
1d4af64
[rust] move the anchor function to top/main.c
travisg Nov 18, 2025
e011fe6
[rust] a few intertwined rust build details
travisg Nov 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .github/workflows/github-ci-rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: LK CI (Rust)

# Build targets that support `USE_RUST=1`

on:
pull_request:
push:
branches-ignore:
- 'wip/**'
- 'docs/**' # Skip builds for documentation branches
paths-ignore:
- '**.md' # Skip builds when only markdown files change
- 'docs/**' # Skip builds for docs directory changes

jobs:
build:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
toolchain-ver: [19]
debug: [2, 0]
project:
# Currently, this is hard-coded here, but should probably be gathered
# from the source.
- qemu-virt-arm64-test
env:
PROJECT: ${{ matrix.project }}
TOOLCHAIN_VER: ${{ matrix.toolchain-ver }}
DEBUG: ${{ matrix.debug }}
UBSAN: 0 # UBSan runtimes for baremetal are not part of the toolchain
steps:
- name: banner
shell: bash
run: |
printf "Building with %d processors\n" "$(nproc)"
grep -oP '(?<=model name\t: ).*' /proc/cpuinfo|head -n1
echo PROJECT = $PROJECT
echo TOOLCHAIN_VER = $TOOLCHAIN_VER
echo DEBUG = $DEBUG
echo UBSAN = $UBSAN

- name: checkout
uses: actions/checkout@v4

# Install LLVM and set up the required environment variables
- name: compute toolchain
shell: bash
run: |
sudo apt-get install -y clang-${{ matrix.toolchain-ver }} lld-${{ matrix.toolchain-ver }}
GCC_TOOLCHAIN_PREFIX=$(make list-toolchain | grep TOOLCHAIN_PREFIX | tail -1 | cut -d ' ' -f 3)
# Map the GCC toolchain prefix to a clang --target argument:
CLANG_TRIPLE=$(echo "${GCC_TOOLCHAIN_PREFIX}" | sed 's/-elf-/-unknown-elf/g')
LLVM_BINDIR=/usr/lib/llvm-${{ matrix.toolchain-ver }}/bin
echo "CC=${LLVM_BINDIR}/clang --target=${CLANG_TRIPLE}" >> $GITHUB_ENV
echo "LD=${LLVM_BINDIR}/ld.lld" >> $GITHUB_ENV
echo "OBJDUMP=${LLVM_BINDIR}/llvm-objdump" >> $GITHUB_ENV
echo "OBJCOPY=${LLVM_BINDIR}/llvm-objcopy" >> $GITHUB_ENV
echo "CPPFILT=${LLVM_BINDIR}/llvm-cxxfilt" >> $GITHUB_ENV
echo "SIZE=${LLVM_BINDIR}/llvm-size" >> $GITHUB_ENV
echo "NM=${LLVM_BINDIR}/llvm-nm" >> $GITHUB_ENV
echo "STRIP=${LLVM_BINDIR}/llvm-strip" >> $GITHUB_ENV
echo "TOOLCHAIN_PREFIX=/invalid/prefix/should/not/be/used" >> $GITHUB_ENV
echo "LIBGCC=" >> $GITHUB_ENV
cat "$GITHUB_ENV"

# Install Rust
# Note that rustup is already included in the image, and we just need to add our target.
- name: install rust
shell: bash
run: |
rustup install nightly
rustup component add rust-src --toolchain nightly
rustup target add aarch64-unknown-linux-gnu
rustup target add aarch64-unknown-none

# build it
- name: build
shell: bash
run: |
make -j $(nproc) USE_RUST=1
# When LK is compiled with DEBUG=0, there's no console and no way for us
# to read test output
- name: qemu
if: ${{ matrix.project == 'qemu-virt-arm64-test' }}
shell: bash
run: |
env -i DEBIAN_FRONTEND=noninteractive sudo apt-get update
env -i DEBIAN_FRONTEND=noninteractive sudo apt-get install -y qemu-system-arm
- name: unittest
if: ${{ matrix.project == 'qemu-virt-arm64-test' }}
shell: bash
run: |
python3 scripts/unittest.py

# vim: ts=2 sw=2 expandtab
17 changes: 17 additions & 0 deletions app/rust_hello/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Rust sample hello world application crate.

[package]
name = "rust_hello"
version = "0.1.0"
edition = "2024"
description = """
Rust LK hello world application.
"""
license = "MIT"

[dependencies.lk]
version = "0.1.0"
path = "../../rust/lk"

[dependencies.log]
version = "0.4.27"
10 changes: 10 additions & 0 deletions app/rust_hello/rules.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
LOCAL_DIR := $(GET_LOCAL_DIR)

RUST_CRATES += $(LOCAL_DIR)
$(info "Adding rust crate $(LOCAL_DIR)")

MODULE := $(LOCAL_DIR)

MODULE_DEPS := lib/rust_support

include make/module.mk
31 changes: 31 additions & 0 deletions app/rust_hello/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Sample application.

#![no_std]

extern crate alloc;

use alloc::boxed::Box;

use lk::{app::LkApp, lkapp};

pub fn must_link() {}

struct MyApp {
count: usize,
}

impl LkApp for MyApp {
fn new() -> Option<Self> {
Some(MyApp { count: 0 })
}

fn main(&mut self) {
self.count += 1;
log::info!("App has been invoked {} times", self.count);
}
}

lkapp!(
c"rust_hello",
APP_RUST_HELLO,
pub static MY_APP: MyApp);
28 changes: 28 additions & 0 deletions arch/arm64/arm64-llvm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"abi": "softfloat",
"arch": "aarch64",
"crt-objects-fallback": "false",
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
"disable-redzone": true,
"features": "+v8a,+strict-align,-neon,-fp-armv8,+reserve-x18",
"linker": "rust-lld",
"linker-flavor": "gnu-lld",
"llvm-target": "aarch64-unknown-none",
"max-atomic-width": 128,
"metadata": {
"description": "Bare ARM64, softfloat",
"host_tools": false,
"std": false,
"tier": 2
},
"panic-strategy": "abort",
"relocation-model": "static",
"stack-probes": {
"kind": "inline"
},
"supported-sanitizers": [
"kcfi",
"kernel-address"
],
"target-pointer-width": 64
}
1 change: 0 additions & 1 deletion dev/uart/pl011/include/dev/uart/pl011.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/
#pragma once

#include <dev/uart.h>
#include <stdint.h>

// Set this flag if the UART is a debug UART, which routes input
Expand Down
1 change: 1 addition & 0 deletions engine.mk
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ TARGET :=
PLATFORM :=
ARCH :=
ALLMODULES :=
RUST_CRATES :=

# add any external module dependencies
MODULES := $(EXTERNAL_MODULES)
Expand Down
30 changes: 30 additions & 0 deletions lib/rust_support/Cargo.toml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Rust meta crate

# This crate brings in the other dependencies needed so that cargo builds all of the Rust code that
# we need.

[package]
name = "rust_support"
version = "0.1.0"
edition = "2024"
description = "Rust support meta crate for lk"
license = "MIT"

[lib]
crate-type = ["staticlib"]

[dependencies.lk]
version = "0.1.0"
path = "@BUILDROOT@/rust/lk" # Relative to build directory.

[profile.release]
debug-assertions = true
overflow-checks = true
debug = true
codegen-units = 1

[profile.dev]
opt-level = 2
codegen-units = 1

@DEPCRATES@
65 changes: 65 additions & 0 deletions lib/rust_support/expand.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#! /usr/bin/env python3

import fileinput
import os

# This script reads a template from standard input or the named file, and
# outputs this with some template insertions, based on some values coming from
# the make invocation.

class Substr():
def __init__(self):
self.subs = []

def add(self, name):
value = os.environ.get(name)
if value is None:
raise Exception(f"Environment variable {name} not set")
self.subs.append( (f"@{name}@", value) )

if name == "BUILDROOT":
self.buildroot = value

# Generate a substitution rules for a list of crates.
def add_depcrates(self, name):
crates = os.environ.get(name)
if crates is None:
raise Exception(f"Environment variable {name} not set")
value = ""
for crate in crates.split():
base = os.path.basename(crate)
value += f"[dependencies.{base}]\npath = \"{self.buildroot}/{crate}\"\n"
# TODO: Get the crate version from the crate's Cargo.toml file.
value += f"version = \"0.1.0\"\n\n"
self.subs.append( ("@DEPCRATES@", value) )

def add_deplinks(self, name):
crates = os.environ.get(name)
if crates is None:
raise Exception(f"Environment variable {name} not set")
value = ""
for crate in crates.split():
base = os.path.basename(crate)
base = base.replace("-", "_")
if value != "":
value += " "
value += f"{base}::must_link();"
self.subs.append( (f"@DEPLINKS@", value) )

def sub(self, line):
for (k,v) in self.subs:
line = line.replace(k, v)
return line

def subst(name):
value = os.environ.get(name)

subber = Substr();

subber.add("BUILDROOT")
subber.add_depcrates("RUST_CRATES")
subber.add_deplinks("RUST_CRATES")

for line in fileinput.input():
line = subber.sub(line.rstrip())
print(line)
Loading