Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add x86_64-unikraft-linux-musl target #113411

Merged
merged 5 commits into from Jul 25, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Expand Up @@ -85,6 +85,7 @@ mod solaris_base;
mod solid_base;
mod thumb_base;
mod uefi_msvc_base;
mod unikraft_linux_musl_base;
mod vxworks_base;
mod wasm_base;
mod windows_gnu_base;
Expand Down Expand Up @@ -1421,6 +1422,8 @@ supported_targets! {
("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
("x86_64-unknown-hermit", x86_64_unknown_hermit),

("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),

("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs
@@ -0,0 +1,15 @@
use crate::spec::{cvs, PanicStrategy, RelocModel, TargetOptions};

pub fn opts() -> TargetOptions {
TargetOptions {
os: "linux".into(),
env: "musl".into(),
vendor: "unikraft".into(),
linker: Some("kraftld".into()),
relocation_model: RelocModel::Static,
families: cvs!["unix"],
has_thread_local: true,
panic_strategy: PanicStrategy::Abort,
..Default::default()
}
}
19 changes: 19 additions & 0 deletions compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs
@@ -0,0 +1,19 @@
use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};

pub fn target() -> Target {
Target {
llvm_target: "x86_64-unknown-linux-musl".into(),
pointer_width: 64,
arch: "x86_64".into(),
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.into(),
options: TargetOptions {
cpu: "x86-64".into(),
plt_by_default: false,
pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]),
max_atomic_width: Some(64),
stack_probes: StackProbeType::X86,
..super::unikraft_linux_musl_base::opts()
},
}
}
14 changes: 13 additions & 1 deletion library/std/src/sys/unix/mod.rs
Expand Up @@ -110,6 +110,11 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 {
match errno() {
libc::EINTR => continue,
#[cfg(target_vendor = "unikraft")]
libc::ENOSYS => {
// Not all configurations of Unikraft enable `LIBPOSIX_EVENT`.
break 'poll;
}
libc::EINVAL | libc::EAGAIN | libc::ENOMEM => {
// RLIMIT_NOFILE or temporary allocation failures
// may be preventing use of poll(), fall back to fcntl
Expand Down Expand Up @@ -165,7 +170,14 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
}

unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
#[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
#[cfg(not(any(
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon",
// Unikraft's `signal` implementation is currently broken:
// https://github.com/unikraft/lib-musl/issues/57
target_vendor = "unikraft",
)))]
{
// We don't want to add this as a public type to std, nor do we
// want to `include!` a file from the compiler (which would break
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/compile.rs
Expand Up @@ -261,7 +261,7 @@ fn copy_self_contained_objects(
// to using gcc from a glibc-targeting toolchain for linking.
// To do that we have to distribute musl startup objects as a part of Rust toolchain
// and link with them manually in the self-contained mode.
if target.contains("musl") {
if target.contains("musl") && !target.contains("unikraft") {
let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
});
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/lib.rs
Expand Up @@ -131,6 +131,8 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
(Some(Mode::Std), "freebsd13", None),
(Some(Mode::Std), "backtrace_in_libstd", None),
/* Extra values not defined in the built-in targets yet, but used in std */
// #[cfg(bootstrap)]
(Some(Mode::Std), "target_vendor", Some(&["unikraft"])),
mkroening marked this conversation as resolved.
Show resolved Hide resolved
(Some(Mode::Std), "target_env", Some(&["libnx"])),
// (Some(Mode::Std), "target_os", Some(&[])),
// #[cfg(bootstrap)] mips32r6, mips64r6
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/sanity.rs
Expand Up @@ -206,7 +206,7 @@ than building it.
}

// Make sure musl-root is valid
if target.contains("musl") {
if target.contains("musl") && !target.contains("unikraft") {
// If this is a native target (host is also musl) and no musl-root is given,
// fall back to the system toolchain in /usr before giving up
if build.musl_root(*target).is_none() && build.config.build == *target {
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Expand Up @@ -42,6 +42,7 @@
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
- [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
- [*-unknown-hermit](platform-support/hermit.md)
- [\*-unknown-netbsd\*](platform-support/netbsd.md)
- [*-unknown-openbsd](platform-support/openbsd.md)
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/platform-support.md
Expand Up @@ -326,6 +326,7 @@ target | std | host | notes
[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
`x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support
`x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos
[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl
`x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
`x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
[`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit
Expand Down
67 changes: 67 additions & 0 deletions src/doc/rustc/src/platform-support/unikraft-linux-musl.md
@@ -0,0 +1,67 @@
# `*-unikraft-linux-musl`

**Tier: 3**

Targets for the [Unikraft] Unikernel Development Kit (with musl).

[Unikraft]: https://unikraft.org/

Target triplets available so far:

- `x86_64-unikraft-linux-musl`

## Target maintainers

- Martin Kröning ([@mkroening](https://github.com/mkroening))

## Requirements

These targets only support cross-compilation.
The targets do support std.

Unikraft pretends to behave exactly like Linux.
How much of that functionality is available depends on the individual unikernel configuration.
For example, the basic Unikraft + musl config does not support `poll` or networking out of the box.
That functionality requires enabling [`LIBPOSIX_EVENT`] or [lwIP] respectively.

[`LIBPOSIX_EVENT`]: https://github.com/unikraft/unikraft/blob/RELEASE-0.13.1/lib/posix-event/Config.uk
[lwIP]: https://github.com/unikraft/lib-lwip

The Unikraft targets follow Linux's `extern "C"` calling convention.

For these targets, `rustc` does not perform the final linking step.
Instead, the Unikraft build system will produce the final Unikernel image for the selected platform (e.g., KVM, Linux user space, and Xen).

## Building the targets

You can build Rust with support for the targets by adding it to the `target` list in `config.toml`:

```toml
[build]
build-stage = 1
target = [ "x86_64-unikraft-linux-musl" ]
```

## Building Rust programs

Rust does not yet ship pre-compiled artifacts for these targets.
To compile for these targets, you will either need to build Rust with the targets enabled
(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar.

Linking requires a [KraftKit] shim.
See [unikraft/kraftkit#612] for more information.

[KraftKit]: https://github.com/unikraft/kraftkit
[unikraft/kraftkit#612]: https://github.com/unikraft/kraftkit/issues/612

## Testing

The targets do support running binaries in the form of unikernel images.
How the unikernel image is run depends on the specific platform (e.g., KVM, Linux user space, and Xen).
The targets do not support running the Rust test suite.

## Cross-compilation toolchains and C code

The targets do support C code.
To build compatible C code, you have to use the same compiler and flags as does the Unikraft build system for your specific configuration.
The easiest way to achieve that, is to build the C code with the Unikraft build system when building your unikernel image.
1 change: 1 addition & 0 deletions src/tools/build-manifest/src/main.rs
Expand Up @@ -148,6 +148,7 @@ static TARGETS: &[&str] = &[
"x86_64-pc-windows-msvc",
"x86_64-sun-solaris",
"x86_64-pc-solaris",
"x86_64-unikraft-linux-musl",
"x86_64-unknown-freebsd",
"x86_64-unknown-illumos",
"x86_64-unknown-linux-gnu",
Expand Down