twizzler-operating-system / twizzler

The Twizzler Operating System
BSD 3-Clause "New" or "Revised" License
66 stars 13 forks source link

Support building on MacOS, fix libunwind building, add basic support for Twizzler in clang #129

Closed dbittman closed 1 year ago

dbittman commented 1 year ago

If that sounds like a lot for a PR, that's because they're all intertwined and most of the work happened in the llvm and rust repos, not this one.

Currently, macos fails to build Twizzler for two reasons:

  1. The config.toml file that rust uses for configuring the toolchain build is static and only contains the targets for twizzler and x86_64 linux.
  2. The build of crtbegin and crtend in llvm fails because we try to use the system compiler, which on mac produces a mach-o file, not an ELF file. As a result, we'd get this fun error:
running: "cc" "-O3" "-ffunction-sections" "-fdata-sections" "-fPIC" "-m64" "-std=c11" "-DCRT_HAS_INITFINI_ARRAY" "-DEH_USE_FRAME_REGISTRY" "-o" "/Users/dbittman/src/test/twizzler/toolchain/src/rust/build/x86_64-unknown-twizzler/native/crt/crtbegin.o" "-c" "/Users/dbittman/src/test/twizzler/toolchain/src/rust/src/llvm-project/compiler-rt/lib/crt/crtbegin.c"
cargo:warning=/Users/dbittman/src/test/twizzler/toolchain/src/rust/src/llvm-project/compiler-rt/lib/crt/crtbegin.c:15:28: error: argument to 'section' attribute is not valid for this target: mach-o section specifier requires a segment and section separated by a comma
cargo:warning=    __attribute__((section(".eh_frame"), aligned(sizeof(void *)))) = {};

The fix for this has several components.

Fixing config.toml

Instead of just hard linking toolchain/src/config.toml to toolchain/src/rust/config.toml, we now generate toolchain/src/rust/config.toml using toolchain/src/config.toml as a template. When xtask does the bootstrapping step, it reads the template, adds the necessary targets (e.g. the current host triple) to the list of targets, and adds explicit tool paths to the twizzler target for cc, cxx, linker, and ar.

This is useful anyway, since we'll want to support building on and for arm and x86, and generating the necessary targets makes this all more flexible.

Fixing crt

The crt files are built manually by the rust bootstrap program, so we can just modify that by providing paths to the C compiler built by llvm during the bootstrapping phase (if we tell rust to not worry that those tools aren't there ahead of time). This fixes the error above because clang will make us a nice ELF file if we tell it to target twizzler.

And we're telling clang to generate code for twizzler, so we (sigh) probably should add support to clang for Twizzler as well. Our llvm fork is updated with this, mostly just copied from other targets, based off of fuchsia and linux.

This works, but it makes libunwind be compiled by the clang we build. Which is the point, but the side effect is that now we have no headers. Actually, this has always been a latent bug, that we were using system headers on linux for compiling libunwind for twizzler, but it's okay because although libunwind is not necessarily freestanding and does depend on libc, in practice we can turn almost all of that off and make it (mostly) freestanding.

However, to avoid modifying libunwind as well, we'll need to provide some basic C headers that libunwind unconditionally includes. These are mostly for memset etc and stddef.h. C sucks. Anyway, we provide the minimal files to get libunwind to compile. Maybe in the future we'll have a real C library and we can use that instead.

Alternatives

This isn't necessary, since macos is not currently a supported target. But I'd like to make it one. Or at least, make it work, even if not officially supported.

The header files are an ugly solution to get libunwind to compile, but it's better that modifying libunwind. I'd like to keep modifications to upstream toolchain software to a minimum. At least, as much as is reasonable.

Finally, clang support. This makes it harder to update llvm, since many more files are modified. But there's a good chance we'll eventually need a C compiler for twizzler anyway, so this is probably the best approach. And it makes libunwind compile "more correctly".

Future plans

I'd like to improve the way we generate the config.toml file. We'll probably want to add support for arm to that soon, so @PandaZ3D should take a look at that.

The clang support is super minimal; we'll want to expand that (adding sanitizers, etc).

Conclusion

Now my mac can compile twizzler. Still can't run it, though, since KVM doesn't work (obvs). That'll come later.

dbittman commented 1 year ago

Relevant rustc repo commits:

Relevant llvm repo commits: