Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/RustNightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
- name: Install cargo-hyperlight
uses: taiki-e/install-action@5939f3337e40968c39aa70f5ecb1417a92fb25a0 # v2.75.15
with:
tool: cargo-hyperlight@0.1.8
tool: cargo-hyperlight@0.1.9

- name: Build and move Rust guests
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dep_build_guests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
- name: Install cargo-hyperlight
uses: taiki-e/install-action@5939f3337e40968c39aa70f5ecb1417a92fb25a0 # v2.75.15
with:
tool: cargo-hyperlight@0.1.8
tool: cargo-hyperlight@0.1.9

- name: Build Rust guests
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/dep_code_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
- name: Install cargo-hyperlight
uses: taiki-e/install-action@5939f3337e40968c39aa70f5ecb1417a92fb25a0 # v2.75.15
with:
tool: cargo-hyperlight@0.1.8
tool: cargo-hyperlight@0.1.9

- name: clippy exhaustive check (debug)
run: just clippy-exhaustive debug
Expand Down Expand Up @@ -149,7 +149,7 @@ jobs:
- name: Install cargo-hyperlight
uses: taiki-e/install-action@5939f3337e40968c39aa70f5ecb1417a92fb25a0 # v2.75.15
with:
tool: cargo-hyperlight@0.1.8
tool: cargo-hyperlight@0.1.9

- name: clippy (debug)
run: |
Expand Down
2 changes: 1 addition & 1 deletion c.just
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mkdir := if os() == "windows" { "mkdir -f -p" } else { "mkdir -p"}
# Elf options
# We don't support stack protectors at the moment, but Arch Linux clang auto-enables them for -linux platforms, so explicitly disable them.
c-compile-options-elf := '-nostdlibinc -H --target=x86_64-unknown-linux-none -fno-stack-protector -fstack-clash-protection -mstack-probe-size=4096 -fPIC'
c-include-flags-elf := "-I " + root / "src/hyperlight_guest_capi/include/" + " -I " + root / "src/hyperlight_guest_bin/third_party/picolibc/libc/include/" + " -I " + root / "src/hyperlight_guest_bin/third_party/picolibc/libc/stdio/"
c-include-flags-elf := "-I " + root / "src/hyperlight_guest_capi/include/" + " -I " + root / "src/hyperlight_guest_bin/third_party/picolibc/libc/include/" + " -I " + root / "src/hyperlight_guest_bin/third_party/picolibc/libc/stdio/" + " -I " + root / "src/hyperlight_guest_bin/include/"
c-linker-options-elf := '--entry "entrypoint" --nostdlib -pie --no-dynamic-linker'
c-flags-debug-elf := '-O0'
c-flags-release-elf := '-O3'
Expand Down
160 changes: 12 additions & 148 deletions src/hyperlight_guest_bin/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ limitations under the License.

mod build_files;

use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::process::Command;
use std::{env, fs};

use anyhow::{Context, Result, bail};
Expand Down Expand Up @@ -51,144 +50,6 @@ fn copy_includes<P: AsRef<Path>, Q: AsRef<Path> + std::fmt::Debug>(
Ok(())
}

fn detect_cc_feature(test_code: &str) -> Result<bool> {
let cc = std::env::var("HYPERLIGHT_GUEST_clang").unwrap_or_else(|_| "clang".into());

let mut cmd = Command::new(&cc)
.arg("-std=c18")
.arg("-x")
.arg("c")
.arg("-")
.arg("-fsyntax-only")
.stdin(Stdio::piped())
.stderr(Stdio::null())
.stdout(Stdio::null())
.spawn()
.with_context(|| "failed to spawn compiler for feature test")?;

cmd.stdin
.as_mut()
.unwrap()
.write_all(test_code.as_bytes())
.with_context(|| "failed to write test code")?;

Ok(cmd
.wait()
.with_context(|| "failed to wait on cc command")?
.success())
}

fn gen_config_file(config_dir: &Path) -> Result<()> {
let config_h = config_dir.join("picolibc.h");

let mut file = fs::File::create(&config_h)
.with_context(|| format!("Could not create config file {:?}", config_h))?;

writeln!(file, "/* Generated by hyperlight build script */")?;
writeln!(file, "#pragma once")?;
writeln!(file)?;

writeln!(file, "#define _NEWLIB_VERSION \"4.3.0\"")?;
writeln!(file, "#define __NEWLIB_VERSION__ \"4.3.0\"")?;
writeln!(file, "#define __NEWLIB__ 4")?;
writeln!(file, "#define __NEWLIB_MINOR__ 3")?;
writeln!(file, "#define __NEWLIB_PATCHLEVEL__ 0")?;
writeln!(file, "#define __PICOLIBC_VERSION__ \"1.8.11\"")?;
writeln!(file, "#define __PICOLIBC__ 1")?;
writeln!(file, "#define __PICOLIBC_MINOR__ 8")?;
writeln!(file, "#define __PICOLIBC_PATCHLEVEL__ 11")?;
writeln!(file)?;

// Static configuration
writeln!(file, "#define __ASSERT_VERBOSE")?;
writeln!(file, "#define __SINGLE_THREAD")?; // -Dsingle-thread=true
writeln!(file, "#define __GLOBAL_ERRNO")?; // -Dnewlib-global-errno=true
writeln!(file, "#define __INIT_FINI_ARRAY")?; // -Dinitfini-array=true
writeln!(file, "#define __TINY_STDIO")?; // tinystdio is now the only stdio
writeln!(file, "#define __IO_DEFAULT 'd'")?; // -Dformat-default=double
writeln!(file, "#define __IO_FLOAT_EXACT")?; // default
writeln!(file, "#define __IO_WCHAR")?; // -Dio-wchar=true
writeln!(file, "#define __IEEE_LIBM")?; // math library without errno
writeln!(file, "#define __FAST_STRCMP")?; // default optimization
writeln!(file, "#define __FAST_BUFIO")?; // -Dfast-bufio=true
writeln!(file, "#define __IO_SMALL_ULTOA")?; // avoid division in conversion

for test in &[
"__builtin_alloca",
"__builtin_ffs",
"__builtin_ffsl",
"__builtin_ffsll",
"__builtin_ctz",
"__builtin_ctzl",
"__builtin_ctzll",
"__builtin_copysign",
"__builtin_copysignl",
"__builtin_isinf",
"__builtin_isinfl",
"__builtin_isnan",
"__builtin_isnanl",
"__builtin_isfinite",
"__builtin_finitel",
"__builtin_issignalingl",
"__builtin_expect",
"__builtin_complex",
"__builtin_add_overflow",
"__builtin_mul_overflow",
] {
let code = format!(
r#"
#if __has_builtin({test})
int main() {{ return 0; }}
#else
#error "Builtin not supported"
#endif
"#
);

let has = if detect_cc_feature(&code)? { 1 } else { 0 };
writeln!(
file,
"#define __HAVE_BUILTIN_{} {has}",
test.trim_start_matches("__builtin_").to_uppercase()
)?;
}

let code = r#"_Complex double x = 1.0 + 2.0*I; int main() { return 0; }"#;
let has = if detect_cc_feature(code)? { 1 } else { 0 };
writeln!(file, "#define __HAVE_COMPLEX {has}")?;

// Static undefs
writeln!(file, "#undef __ARM_SEMIHOST")?; // -Dsemihost=false
writeln!(file, "#undef __SEMIHOST")?; // -Dsemihost=false
writeln!(file, "#undef __THREAD_LOCAL_STORAGE")?; // -Dthread-local-storage=false
writeln!(file, "#undef __THREAD_LOCAL_STORAGE_API")?;
writeln!(file, "#undef __THREAD_LOCAL_STORAGE_RP2040")?;
writeln!(file, "#undef __THREAD_LOCAL_STORAGE_STACK_GUARD")?;
writeln!(file, "#undef __ENABLE_MALLOC")?; // -Denable-malloc=false
writeln!(file, "#undef __MALLOC_CLEAR_FREED")?;
writeln!(file, "#undef __MB_CAPABLE")?; // no multibyte support
writeln!(file, "#undef __HAVE_FCNTL")?; // freestanding environment
writeln!(file, "#undef __STDIO_LOCKING")?; // single-thread
writeln!(file, "#undef __IO_C99_FORMATS")?; // -Dio-c99-formats=false
writeln!(file, "#undef __IO_LONG_DOUBLE")?; // not enabled
writeln!(file, "#undef __IO_LONG_LONG")?; // minimal format
writeln!(file, "#undef __IO_MINIMAL_LONG_LONG")?;
writeln!(file, "#undef __IO_PERCENT_B")?; // not enabled
writeln!(file, "#undef __IO_PERCENT_N")?; // not enabled
writeln!(file, "#undef __IO_POS_ARGS")?; // not enabled
writeln!(file, "#undef __MATH_ERRNO")?; // IEEE math only
writeln!(file, "#undef __OBSOLETE_MATH")?;
writeln!(file, "#undef __OBSOLETE_MATH_DOUBLE")?;
writeln!(file, "#undef __OBSOLETE_MATH_FLOAT")?;
writeln!(file, "#undef __PREFER_SIZE_OVER_SPEED")?; // release build
writeln!(file, "#undef __ATOMIC_UNGETC")?; // single-thread
writeln!(file, "#undef __IEEEFP_FUNCS")?;
writeln!(file, "#undef __INIT_FINI_FUNCS")?; // using INIT_FINI_ARRAY instead
writeln!(file, "#undef __HAVE_BITFIELDS_IN_PACKED_STRUCTS")?;

Ok(())
}

fn cc_build(picolibc_dir: &PathBuf, target: &str) -> Result<cc::Build> {
let mut build = cc::Build::new();
let compiler = env::var("HYPERLIGHT_GUEST_clang").unwrap_or("clang".to_string());
Expand Down Expand Up @@ -252,11 +113,6 @@ fn cc_build(picolibc_dir: &PathBuf, target: &str) -> Result<cc::Build> {
.define("_LIBC", None)
.define("_FILE_OFFSET_BITS", "64");

// TODO: this is wrong, it should generate config file to out_dir/include
// but how downstream crates get at it then? And TBH I think having piclibc
// headers (features.h) depend on a build time header is odd
gen_config_file(&picolibc_dir.join("libc/include"))?;

match target {
"x86" | "x86_64" => {
build.include(picolibc_dir.join("libm/machine/x86"));
Expand Down Expand Up @@ -323,6 +179,7 @@ fn init_submodule() -> Result<()> {
fn cargo_main() -> Result<()> {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=third_party/picolibc");
println!("cargo:rerun-if-changed=include/picolibc.h");
println!("cargo:rerun-if-env-changed=HYPERLIGHT_GUEST_TOOLCHAIN_ROOT");

let out_dir = env::var("OUT_DIR").expect("cargo OUT_DIR not set");
Expand All @@ -332,15 +189,21 @@ fn cargo_main() -> Result<()> {
fs::create_dir_all(&include_dir)
.with_context(|| format!("Could not create include dir {include_dir:?}"))?;

let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("cargo MANIFEST_DIR not set");
let manifest_dir = PathBuf::from(manifest_dir);
let picolibc_dir = manifest_dir.join("third_party/picolibc");

if cfg!(feature = "libc") {
if !Path::new("third_party/picolibc/COPYING.picolibc").exists() {
if !picolibc_dir.join("COPYING.picolibc").exists() {
eprintln!("Setting up submodules");
init_submodule().with_context(|| "failed to init picolibc submodule")?;
}

let picolibc_dir = PathBuf::from("third_party/picolibc");
let mut build = cc_build(&picolibc_dir, &target)?;

// include for picolibc configuration: picolibc.h
build.include(manifest_dir.join("include"));

add_libc(&mut build, &picolibc_dir, &target)?;
add_libm(&mut build, &picolibc_dir, &target)?;

Expand All @@ -349,7 +212,8 @@ fn cargo_main() -> Result<()> {
}

build.compile("hyperlight_guest_bin");
copy_includes(&include_dir, "third_party/picolibc/libc/include")?;
copy_includes(&include_dir, picolibc_dir.join("libc/include"))?;
copy_includes(&include_dir, manifest_dir.join("include"))?;
}

let include_str = include_dir
Expand Down
Loading
Loading