Files
u-boot/examples/rust/build.rs
Simon Glass 44127a8185 ulib: Add a Rust example
The U-Boot library can be used from Rust fairly easily. Add an example
for this, following along the lines of the existing ulib example.

Note that the new way of representing C strings is not used for now,
since it is not available in v1.75 of cargo, as shipped by Ubuntu 24.04

Co-developed-by: Claude <noreply@anthropic.com>
Co-developed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
2025-09-11 15:19:22 -06:00

106 lines
4.1 KiB
Rust

// SPDX-License-Identifier: GPL-2.0+
/*
* Build script for U-Boot Rust demo
*
* This configures linking with the U-Boot library, similar to how
* the C examples are built in examples/ulib
*
* Copyright 2025 Canonical Ltd.
* Written by Simon Glass <simon.glass@canonical.com>
*/
use std::env;
use std::path::PathBuf;
use std::process::Command;
fn main() {
// Get the U-Boot build directory from environment or use default
let uboot_build = env::var("UBOOT_BUILD")
.unwrap_or_else(|_| "/tmp/b/sandbox".to_string());
let uboot_build_path = PathBuf::from(&uboot_build);
println!("cargo:rerun-if-env-changed=UBOOT_BUILD");
println!("cargo:rerun-if-changed=build.rs");
// Add library search path
println!("cargo:rustc-link-search=native={}", uboot_build_path.display());
// Check if dynamic linking is requested
if env::var("UBOOT_DYNAMIC").is_ok() {
// Dynamic linking with libu-boot.so
println!("cargo:rustc-link-lib=dylib=u-boot");
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", uboot_build_path.display());
} else {
// Static linking with libu-boot.a using whole-archive to ensure
// all symbols are included (required for U-Boot linker lists)
// Use the same linker script as the C examples for proper linker list ordering
let static_lib_path = uboot_build_path.join("libu-boot.a");
// Use absolute path to the linker script in the source tree
let current_dir = env::current_dir().expect("Failed to get current directory");
let linker_script_path = current_dir.join("../ulib/static.lds");
println!("cargo:rustc-link-arg=-Wl,-T,{}", linker_script_path.display());
println!("cargo:rustc-link-arg=-Wl,--whole-archive");
println!("cargo:rustc-link-arg={}", static_lib_path.display());
println!("cargo:rustc-link-arg=-Wl,--no-whole-archive");
println!("cargo:rustc-link-arg=-Wl,-z,noexecstack");
// Add required system libraries AFTER --no-whole-archive like the C version
println!("cargo:rustc-link-arg=-lpthread");
println!("cargo:rustc-link-arg=-ldl");
// Get SDL libraries using sdl2-config like the C version does
if let Ok(output) = Command::new("sdl2-config").arg("--libs").output() {
if output.status.success() {
let libs_str = String::from_utf8_lossy(&output.stdout);
for lib_flag in libs_str.split_whitespace() {
if lib_flag.starts_with("-l") {
println!("cargo:rustc-link-arg={}", lib_flag);
}
}
}
} else {
// Fallback to just SDL2 if sdl2-config is not available
println!("cargo:rustc-link-arg=-lSDL2");
}
}
// For dynamic linking, link required system libraries normally
if env::var("UBOOT_DYNAMIC").is_ok() {
println!("cargo:rustc-link-lib=pthread");
println!("cargo:rustc-link-lib=dl");
println!("cargo:rustc-link-lib=rt");
}
// Optional SDL2 support (if available) - only for dynamic linking
if env::var("UBOOT_DYNAMIC").is_ok() {
if let Ok(sdl_libs) = env::var("SDL_LIBS") {
for lib in sdl_libs.split_whitespace() {
if let Some(lib_name) = lib.strip_prefix("-l") {
println!("cargo:rustc-link-lib={}", lib_name);
}
}
}
}
// Define symbols that may be missing (from U-Boot troubleshooting docs)
// Note: __stack_chk_guard is provided by U-Boot's common/stackprot.c
println!("cargo:rustc-link-arg=-Wl,--defsym,sandbox_sdl_sync=0");
// For static linking, we need to ensure libc is available for atexit and other functions
if env::var("UBOOT_DYNAMIC").is_err() {
println!("cargo:rustc-link-arg=-lc");
}
// Add include path for headers if needed for bindgen (future enhancement)
let uboot_include = uboot_build_path.join("include");
if uboot_include.exists() {
println!("cargo:include={}", uboot_include.display());
}
// Recompile if main source changes
println!("cargo:rerun-if-changed=src/demo.rs");
}