sunfishcode/mustang

What might an official Rust target look like?

sunfishcode opened this issue · 8 comments

An official target could be much easier to use, with no mustang::can_run_here!() macro, no target json file, and no -Z build-std. And internally, it could avoid some of the linker hacks, and achieve much smaller code size, because it wouldn't need to force-link in all the libc symbols just to prevent the system libc from being linked in. And, this would be a natural moment to pick a new name for the target 😄 .

What might this look like? This issue is some early brainstorming in this space with many open questions, and more questions are welcome!

One big question is, should such a target use the c-scape C ABI compatibility layer?

  • If not:

    • bytecodealliance/rustix#76
    • #38
    • Figure out a plan for mutex/rwlock, DNS resolution, and possible other stuff where mustang has more dependencies than std might want.
    • Others?
  • If so:

    • I wonder if it's possible to build up c-scape and all its dependencies, including std, into a single #[crate_type = "staticlib"] library, which we'd name "libc", and then we'd have the new Rust target use that. That would mean two copies of std present in resulting programs, which might present some tricky issues, and very likely produces large binaries, but if it's not too tricky this might be a faster path to getting something working while making relatively few changes to Rust itself. And then we could work on eliminating c-scape gradually over time.

That would mean two copies of std present in resulting programs, which might present some tricky issues, and very likely produces large binaries

You will get symbol conflicts if both std copies are identical. They need to have a different -Cmetadata for that to work, which is going to be hard to integrate into the rust build system and -Zbuild-std. Especially the later would be hard I think.

You will get symbol conflicts if both std copies are identical. They need to have a different -Cmetadata for that to work, which is going to be hard to integrate into the rust build system and -Zbuild-std. Especially the later would be hard I think.

I tried a quick experiment:

  • Build c-scape with a *-mustang-* target and crate-type = ["staticlib"], which produces a libc.a.
  • Define a new custom target named *-different-*, that doesn't know anything about mustang, except that it links in the libc.a that we just built. Most of std doesn't conflict because it gets different hash strings in the mangled names, however there are multiple-definition errors on some non-mangled names:
    • __rust_alloc, __rust_dealloc, __rust_realloc, __rust_alloc_zeroed, __rust_alloc_error_handler
    • __rust_drop_panic, __rust_foreign_exception
    • rust_begin_unwind, rust_panic, rust_oom
    • __rdl_alloc, __rdl_dealloc, __rdl_realloc, __rdl_alloc_zeroed
    • __rdl_oom, __rg_oom
Urgau commented

You could maybe add the support for mustang in the libc crate, like a reexport of all c-scape functions. So that you wouldn't link with the libc of the OS while allowing crate that relies on the libc crate to continue to work like their were doing before.
But that seems like a lot of work, not sure it's worth it.

This could maybe also be extended to allow "direct" access to the underline safe functions of rsix, ... without even adding it to the Cargo.toml; extern crate rsix with use rsix::io ?

Maybe we can replace the libc dependency of std with an unconditional dependency on c-scape for all Unix targets. c-scape would then start with two configs, with one just wrapping libc and the other one wrapping rsix.

c-scape does have the beginnings of a mode where it's just a libc wrapper; see the libc! macro in c-scape, which doesn't fully work yet, but might be made to do something like this.

I think the answer to my question above is: why not both?

Long-term, I think we don't want everything built on the c-scape C compatibility layer, which in theory means porting std to rustix. I've now started an experiment for this. We'll see how that shapes up.

c-scape is still valuable though, both as a way of getting more things running on origin/rustix sooner, and even long-term, as C compatibility for crates that link with C code. So if we can figure out more convenient ways of using it, those make sense to pursue too.

This sounds great. rustix also has a libc feature, so I thing the best way to go would be to first try to get the rustix port into the official standard library. This should greatly reduce the number of functions from libc which are actually called. In a next step, one could then try to redirect all reference of libc via one common module. In addition, one might want to fork the currentlibc in a new libc and a smaller libc-freestanding library (libc reexporting it, this should be doable in a backward compatible manner). libc-freestanding would only define the C primitive type aliases and the things defined in the "freestanding" header files ("float.h", "iso646.h", "limits.h", "stdarg.h", "stdbool.h", "stddef.h", "stdint.h"), which even "mustang" may want to define.

To my knowledge, no one is actively working on this, so I'm closing this issue for now. If anyone is interested, please reach out.