What would it take to get llvm libc to work on macos like it does on linux? and is there interest to make it happen?

I’ve compiled a rough plan for porting libc to macos:

Phase 1: Basic Process Control & Syscall Foundation

  1. Implement Core Syscall Interface: Create the assembly and header files for the kernel interface in __support/OSUtil/darwin/ for both aarch64 and x86_64. This is the mechanism for all subsequent syscall wrappers.
  2. Implement exit and abort: Following @michaelrj-google’s advice Implement _exit (unistd/darwin/), exit (stdlib/darwin/), and abort (stdlib/darwin/). This makes a “full build” at least runnable, as it can now terminate.
  3. Implement __assert_fail: Create the Darwin-specific handler for assert.h. This is for internal development and testing of all subsequent modules. It can be built using abort.

Phase 2: Core Synchronization Primitives

  1. Create Futex Abstraction: Following @SchrodingerZhu’s advice, implement a platform-specific futex-like wait/wake API in __support/threads/darwin/. This will be built on the macOS os_sync_wait_on_address API.
  2. Implement Mutex: Port the generic Mutex class (__support/threads/mutex.h) to use this new os_sync_wait_on_address abstraction.
  3. Port Thread Primitives: Use the new futex abstraction to implement the other core thread primitives, such as call_once and CndVar.

Phase 3: File I/O and stdio

With synchronization available, this phase implements the I/O subsystems, enabling basic functionality like printf.

  1. Implement Low-Level I/O Wrappers: Create the Darwin implementations for fcntl, unistd (read, write, lseek, close), and sys/stat (fstat). These are the syscalls needed for file operations.
  2. Implement __support::File: Create the __support/File/darwin/ implementation. This internal abstraction requires the Mutex from Phase 2 for thread-safe operations.
  3. Implement stdio: Create the stdio/darwin/ backend. This will provide the FILE* structures (including stdin, stdout, stderr) and functions (fopen, fprintf, fread), which are built on top of the __support::File abstraction.

Phase 4: Memory, Time, and Process Management

This phase adds the remaining core components required for a modern POSIX environment.

  1. Implement mman: Create sys/mman/darwin/ to provide memory management functions like mmap, munmap, and mprotect.
  2. Implement Time: Create __support/time/darwin/ for time abstractions and sys/time/darwin/ for syscalls like gettimeofday.
  3. Implement Architecture-Specifics: Implement the setjmp/darwin/aarch64/ and x86_64/ assembly functions for setjmp and longjmp.
  4. Implement Process & Signals: Create spawn/darwin/, sys/wait/darwin/, and signal/darwin/ to support process creation and signal handling.

Phase 5: Full POSIX Compliance and pthread

This final phase completes the library by implementing the remaining high-level POSIX APIs.

  1. I/O Multiplexing: Implement poll (poll/darwin/) and select (sys/select/darwin/). The poll implementation can be built on top of the macOS-native kqueue API (sys/event.h).
  2. Networking: Implement the sys/socket/darwin/ API.
  3. Complete sys/ Modules: Implement the remaining POSIX sys/ modules, such as sys/resource, sys/utsname, and termios.
  4. Implement pthreads: Build out the full pthread/ API (e.g., pthread_create) on top of the synchronization primitives from Phase 2 and the thread management APIs.
  5. Dynamic Linking: Implement dlfcn/darwin/ (dlopen, dlsym). (These are missing from linux too)

I surely missed a lot more things, please let me know your thoughts.

1 Like