Skip to content

Commit e163548

Browse files
committed
[rust] Allow modules to declare themselves as Rust crates
The variable RUST_CRATES contains a list of paths (from the build root) to crates to add. For each crate: generate a call to `cratename::must_link()` to force the crate to be linked in, allowing lk init blocks to be included. This makes the pl011 crate a module, so the crate will be included when the module is included. Signed-off-by: David Brown <[email protected]>
1 parent 533bdbe commit e163548

File tree

10 files changed

+93
-30
lines changed

10 files changed

+93
-30
lines changed

engine.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ TARGET :=
141141
PLATFORM :=
142142
ARCH :=
143143
ALLMODULES :=
144+
RUST_CRATES :=
144145

145146
# add any external module dependencies
146147
MODULES := $(EXTERNAL_MODULES)

lib/rust_support/Cargo.toml.in

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ crate-type = ["staticlib"]
1717
version = "0.1.0"
1818
path = "@BUILDROOT@/rust/lk" # Relative to build directory.
1919

20-
[dependencies.dev-pl011]
21-
version = "0.1.0"
22-
path = "@BUILDROOT@/rust/dev-pl011" # Relative to build directory.
23-
2420
[profile.release]
2521
debug-assertions = true
2622
overflow-checks = true
@@ -30,3 +26,5 @@ codegen-units = 1
3026
[profile.dev]
3127
opt-level = 2
3228
codegen-units = 1
29+
30+
@DEPCRATES@

lib/rust_support/expand.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#! /usr/bin/env python3
2+
3+
import fileinput
4+
import os
5+
6+
# This script reads a template from standard input or the named file, and
7+
# outputs this with some template insertions, based on some values coming from
8+
# the make invocation.
9+
10+
class Substr():
11+
def __init__(self):
12+
self.subs = []
13+
14+
def add(self, name):
15+
value = os.environ.get(name)
16+
if value is None:
17+
raise Exception(f"Environment variable {name} not set")
18+
self.subs.append( (f"@{name}@", value) )
19+
20+
if name == "BUILDROOT":
21+
self.buildroot = value
22+
23+
# Generate a substitution rules for a list of crates.
24+
def add_depcrates(self, name):
25+
crates = os.environ.get(name)
26+
if crates is None:
27+
raise Exception(f"Environment variable {name} not set")
28+
value = ""
29+
for crate in crates.split():
30+
base = os.path.basename(crate)
31+
value += f"[dependencies.{base}]\npath = \"{self.buildroot}/{crate}\"\n"
32+
# TODO: Get the crate version from the crate's Cargo.toml file.
33+
value += f"version = \"0.1.0\"\n\n"
34+
self.subs.append( ("@DEPCRATES@", value) )
35+
36+
def add_deplinks(self, name):
37+
crates = os.environ.get(name)
38+
if crates is None:
39+
raise Exception(f"Environment variable {name} not set")
40+
value = ""
41+
for crate in crates.split():
42+
base = os.path.basename(crate)
43+
base = base.replace("-", "_")
44+
if value != "":
45+
value += " "
46+
value += f"{base}::must_link();"
47+
self.subs.append( (f"@DEPLINKS@", value) )
48+
49+
def sub(self, line):
50+
for (k,v) in self.subs:
51+
line = line.replace(k, v)
52+
return line
53+
54+
def subst(name):
55+
value = os.environ.get(name)
56+
57+
subber = Substr();
58+
59+
subber.add("BUILDROOT")
60+
subber.add_depcrates("RUST_CRATES")
61+
subber.add_deplinks("RUST_CRATES")
62+
63+
for line in fileinput.input():
64+
line = subber.sub(line.rstrip())
65+
print(line)

lib/rust_support/rules.mk

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ HAVE_RUST := 1
3333

3434
GLOBAL_DEFINES += HAVE_RUST=$(HAVE_RUST)
3535

36+
# Modules that contain crates should define ${RUST_CRATES} with a path from the
37+
# build directory to the crate. We make the assumption that the crate name
38+
# matches the directory name.
39+
3640
ifeq ($(RUST_TARGET),)
3741
$(error RUST_TARGET is not set for rust support)
3842
endif
@@ -64,15 +68,16 @@ EXTRA_OBJS := $(EXTRA_OBJS) $(MODULE_OBJECT)
6468

6569
# Bring in the source files via copy.
6670
# The toml file will have a substitution to fix up references to the buildroot.
71+
$(MODULE_BUILDDIR)/%: MODULE_SRCDIR:=$(MODULE_SRCDIR)
72+
6773
$(MODULE_BUILDDIR)/%: $(MODULE_SRCDIR)/%.in target.phony
6874
$(NOECHO)echo generating $@
6975
$(NOECHO)mkdir -p $(dir $@)
70-
$(NOECHO)sed 's|@BUILDROOT@|$(call TOML_ESC,$(abspath $(BUILDROOT)))|g' $< > $@.tmp
71-
$(NOECHO)$(call TESTANDREPLACEFILE,$@.tmp,$@)
72-
$(MODULE_BUILDDIR)/src/%: $(MODULE_SRCDIR)/src/%.in target.phony
73-
$(NOECHO)echo generating $@
74-
$(NOECHO)mkdir -p $(dir $@)
75-
$(NOECHO)cp $< $@.tmp
76+
$(NOECHO)env \
77+
BUILDROOT="$(abspath $(BUILDROOT))" \
78+
RUST_CRATES="$(RUST_CRATES)" \
79+
python3 $(MODULE_SRCDIR)/expand.py $< > $@.tmp
80+
# $(NOECHO)sed 's|@BUILDROOT@|$(call TOML_ESC,$(abspath $(BUILDROOT)))|g' $< > [email protected]
7681
$(NOECHO)$(call TESTANDREPLACEFILE,$@.tmp,$@)
7782

7883
.PHONY: target.phony

lib/rust_support/src/lib.rs.in

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
#![no_std]
1010

1111
#[unsafe(no_mangle)]
12-
extern "C" fn setup_rust() {
12+
extern "C" fn must_link_rust() {
1313
// Any crate that relies entirely on initialization through LK's init
1414
// mechanisms will need a call to some piece of code in that create to cause
1515
// the crate to be brought in.
1616
// Due to link ordering, symbols from C code referencing into rust code
1717
// isn't usually sufficient to bring a crate in.
18-
lk::init();
19-
dev_pl011::init();
18+
lk::must_link();
19+
@DEPLINKS@
2020
}

platform/qemu-virt-arm/platform.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,15 @@ void platform_early_init(void) {
8888
}
8989

9090
#if HAVE_RUST
91-
void setup_rust(void);
91+
void must_link_rust(void);
9292
#else
93-
static void setup_rust(void) {}
93+
static void must_link_rust(void) {}
9494
#endif
9595

9696
void platform_init(void) {
9797
pl011_init(0);
9898

99-
setup_rust();
99+
must_link_rust();
100100

101101
// start secondary cores
102102
fdtwalk_setup_cpus_arm(fdt);

platform/qemu-virt-arm/rules.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ USE_RUST ?= 0
4343

4444
ifeq ($(USE_RUST),1)
4545
MODULE_DEPS += lib/rust_support
46+
MODULE_DEPS += rust/dev-pl011
4647
endif
4748

4849
GLOBAL_DEFINES += \

rust/dev-pl011/rules.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
LOCAL_DIR := $(GET_LOCAL_DIR)
2+
RUST_CRATES += $(LOCAL_DIR)
3+
MODULES += $(LOCAL_DIR)

rust/dev-pl011/src/lib.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,8 @@ fn get_console_input_cbuf() -> Cbuf {
3131
unsafe { Cbuf::new(&raw mut console_input_cbuf) }
3232
}
3333

34-
/// Init function to ensure crate is linked.
35-
/// This might not be needed once we provide something actually linked.
36-
pub fn init() {
37-
// Nothing to do yet.
38-
}
34+
/// Referenced from rust_support to ensure linking.
35+
pub fn must_link() {}
3936

4037
/// Representation of the UART registers for MMIO access.
4138
#[repr(C)]

rust/lk/src/lib.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,8 @@ pub mod lkonce;
2626
pub mod log;
2727
pub mod macros;
2828

29-
/// Initialize the rust side of the code.
30-
///
31-
/// Due to linker optimization, without a direct call into this code, the linker will not bring in
32-
/// anything.
33-
pub fn init() {
34-
unsafe {
35-
sys::fputs(c"*** Rust init ***\n".as_ptr(), lk_stderr());
36-
}
37-
}
29+
// Enforce linking.
30+
pub fn must_link() {}
3831

3932
/// Return the current stderr from lk's simple stdio implementation.
4033
#[inline(always)]

0 commit comments

Comments
 (0)