From 60ec682f7394cced2b9215cb81b0a77dbcd1c6f9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 18 Nov 2025 21:59:16 -0800 Subject: [PATCH 1/3] Migrate the `Makefile` to CMake This commit migrates wasi-libc's build system from a `make`-based system to CMake. This is a complete rewrite of the build system which culminates in the deletion of the current `Makefile` and a few supporting scripts and files. The rationale/reasons for this are similar to WebAssembly/wasi-sdk#429, namely: * Building a correct and robust build system in `make` is not easy. There are many times I've found myself in a situation where I need to blow away the entire build directory between builds. Much of the this this bottoms out in subtle behavior like "this file was renamed, but didn't get deleted in the archive" or subtle things like that. CMake is responsible for handling these by default and, in general, is probably going to be more correct than what we write. * Out-of-tree builds are now supported. * Customizing CFLAGS is now supported via standard mechanisms. Previously `EXTRA_CFLAGS` was required since using `CFLAGS` could break the build. * It's easier to move more logic into CMake, such as downloading compiler-rt, than it is to codify it all in makefiles. * Platform portability is generally easier in CMake than make. Building on Windows shouldn't require a full GNU-like environment, for example. * Tests now properly rebuild themselves when wasi-libc changes. * It's easier to customize high-level options, like "enable SIMD", in CMake than it is in Makefiles. This can be documented as a single option to pass where that option affects the build, flags, etc. Personally I'm not a fan of CMake, but I'm more of a fan of it than Makefiles, hence my desire to switch. I want to make this repository easier to build, configure, and change over time. This will also make it easier to integrate this all into wasi-sdk where everything is CMake-based over there as well. I am not a CMake expert, nor am I necessarily an expert in the previous Makefiles. I've done my best here, but I'm happy to change things if someone who knows more about CMake than I (which is a lot of folks) recommends doing so. I'm also happy to adjust the libc build as desired too. Closes #46 Closes #156 Closes #295 Closes #322 Closes #330 Closes #514 Closes #605 --- .github/actions/setup/action.yml | 6 - .github/workflows/main.yml | 133 +- CMakeLists.txt | 370 ++++++ Makefile | 1111 ----------------- README.md | 65 +- cmake/Platform/WASI.cmake | 1 + cmake/ba-download.cmake | 48 + cmake/bindings.cmake | 66 + cmake/builtins.cmake | 67 + cmake/check-symbols.cmake | 53 + cmake/scripts/run-check-symbols.cmake | 178 +++ cmake/wasm-component-ld.cmake | 14 + dlmalloc/CMakeLists.txt | 4 + emmalloc/CMakeLists.txt | 8 + .../predefined-macros.txt | 6 +- expected/wasm32-wasip1/predefined-macros.txt | 3 +- expected/wasm32-wasip2/predefined-macros.txt | 5 +- fts/CMakeLists.txt | 6 + libc-bottom-half/CMakeLists.txt | 213 ++++ libc-bottom-half/clocks/CMakeLists.txt | 7 + libc-bottom-half/cloudlibc/src/common/time.h | 2 +- libc-bottom-half/getpid/CMakeLists.txt | 3 + .../headers/public/__wasi_snapshot.h | 5 - .../headers/public/__wasi_snapshot.h.in | 6 + libc-bottom-half/mman/CMakeLists.txt | 3 + libc-bottom-half/signal/CMakeLists.txt | 19 + libc-top-half/CMakeLists.txt | 560 +++++++++ scripts/install-include-headers.sh | 86 -- test/CMakeLists.txt | 89 +- 29 files changed, 1753 insertions(+), 1384 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 Makefile create mode 100644 cmake/Platform/WASI.cmake create mode 100644 cmake/ba-download.cmake create mode 100644 cmake/bindings.cmake create mode 100644 cmake/builtins.cmake create mode 100644 cmake/check-symbols.cmake create mode 100644 cmake/scripts/run-check-symbols.cmake create mode 100644 cmake/wasm-component-ld.cmake create mode 100644 dlmalloc/CMakeLists.txt create mode 100644 emmalloc/CMakeLists.txt create mode 100644 fts/CMakeLists.txt create mode 100644 libc-bottom-half/CMakeLists.txt create mode 100644 libc-bottom-half/clocks/CMakeLists.txt create mode 100644 libc-bottom-half/getpid/CMakeLists.txt delete mode 100644 libc-bottom-half/headers/public/__wasi_snapshot.h create mode 100644 libc-bottom-half/headers/public/__wasi_snapshot.h.in create mode 100644 libc-bottom-half/mman/CMakeLists.txt create mode 100644 libc-bottom-half/signal/CMakeLists.txt create mode 100644 libc-top-half/CMakeLists.txt delete mode 100755 scripts/install-include-headers.sh diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 05090de3a..d56dc9190 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -57,10 +57,4 @@ runs: echo "CC=clang-$v" >> $GITHUB_ENV echo "AR=llvm-ar-$v" >> $GITHUB_ENV echo "NM=llvm-nm-$v" >> $GITHUB_ENV - # Note: wasm-component-ld is only needed for Linux because - # currently, wasm32-wasip2 is only tested on Linux. If that changes, - # this step will have to be added to the other targets. - curl -fsSLO https://github.com/bytecodealliance/wasm-component-ld/releases/download/v0.5.15/wasm-component-ld-v0.5.15-x86_64-linux.tar.gz - tar xzf wasm-component-ld-v0.5.15-x86_64-linux.tar.gz - echo "$(pwd)/wasm-component-ld-v0.5.15-x86_64-linux" >> $GITHUB_PATH if: runner.os == 'Linux' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 575b3017e..45977c841 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,6 @@ jobs: buildlibc: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} - env: ${{ matrix.env || fromJSON('{}') }} strategy: fail-fast: false matrix: @@ -33,122 +32,101 @@ jobs: clang_version: 15.0.7 llvm_asset_suffix: arm64-apple-darwin22.0 upload: macos-clang-15 + args: -DBUILD_SHARED=OFF -DCMAKE_C_COMPILER_WORKS=ON - name: Build on Windows x86_64 os: windows-2025 clang_version: 20.1.8 upload: windows-clang-20 + args: -DBUILD_SHARED=OFF # Other versions of LLVM - name: Build with LLVM 11 os: ubuntu-22.04 clang_version: 11 upload: linux-x86_64-clang-11 - env: - BUILD_LIBSETJMP: no + args: -DSETJMP=OFF -DBUILD_SHARED=OFF - name: Build with LLVM 18 os: ubuntu-24.04 clang_version: 18 upload: linux-x86_64-clang-18 - env: - MAKE_TARGETS: "default libc_so" # Test various combinations of target triples. # - # Configuration here can happen through `env` which is inherited to - # jobs below. For now this only runs tests on Linux with Clang 16, - # but that can be expanded as necessary in the future too. Note that - # some targets run the build for the `libc_so` makefile target to - # ensure the PIC build works. + # Configuration here can happen through `args` which are all passed + # to CMake. For now this only runs tests on Linux with Clang 16, + # but that can be expanded as necessary in the future too. - name: Test wasm32-wasi os: ubuntu-24.04 clang_version: 19 test: true upload: wasm32-wasi - env: - TARGET_TRIPLE: wasm32-wasi - MAKE_TARGETS: "default libc_so" + args: -DTARGET_TRIPLE=wasm32-wasi + - name: Test wasm32-wasip1 os: ubuntu-24.04 clang_version: 19 test: true upload: wasm32-wasip1 - env: - TARGET_TRIPLE: wasm32-wasip1 - MAKE_TARGETS: "default libc_so" + args: -DTARGET_TRIPLE=wasm32-wasip1 + - name: Test wasm32-wasip2 os: ubuntu-24.04 clang_version: 19 test: true upload: wasm32-wasip2 - env: - TARGET_TRIPLE: wasm32-wasip2 - WASI_SNAPSHOT: p2 - MAKE_TARGETS: "default libc_so" + args: -DTARGET_TRIPLE=wasm32-wasip2 + - name: Test wasm32-wasip1-threads os: ubuntu-24.04 clang_version: 19 test: true upload: wasm32-wasip1-threads - env: - TARGET_TRIPLE: wasm32-wasip1-threads - THREAD_MODEL: posix + args: -DTARGET_TRIPLE=wasm32-wasip1-threads + - name: Test wasm32-wasip1 in V8 os: ubuntu-24.04 clang_version: 19 test: true test_with_v8: true - env: - TARGET_TRIPLE: wasm32-wasip1 + args: -DTARGET_TRIPLE=wasm32-wasip1 + - name: Test wasm32-wasip1-threads in V8 os: ubuntu-24.04 clang_version: 19 test: true test_with_v8: true - env: - TARGET_TRIPLE: wasm32-wasip1-threads - THREAD_MODEL: posix + args: -DTARGET_TRIPLE=wasm32-wasip1-threads - name: Test wasm32-wasi-simd os: ubuntu-24.04 clang_version: 19 test: true upload: wasm32-wasi-simd - env: - TARGET_TRIPLE: wasm32-wasip1 - MAKE_TARGETS: "no-check-symbols" - EXTRA_CFLAGS: "-O2 -DNDEBUG -msimd128 -mrelaxed-simd -mbulk-memory -D__wasilibc_simd_string" + args: -DSIMD=ON -DCHECK_SYMBOLS=OFF - name: Test wasm32-wasip1 (debug) os: ubuntu-24.04 clang_version: 19 test: true - env: - TARGET_TRIPLE: wasm32-wasip1 - DEBUG: true + args: -DCMAKE_BUILD_TYPE=Debug + - name: Test wasm32-wasip2 (debug) os: ubuntu-24.04 clang_version: 19 test: true - env: - TARGET_TRIPLE: wasm32-wasip2 - WASI_SNAPSHOT: p2 - DEBUG: true + args: -DCMAKE_BUILD_TYPE=Debug -DTARGET_TRIPLE=wasm32-wasip2 + - name: Test wasm32-wasip1-threads (debug) os: ubuntu-24.04 clang_version: 19 test: true - env: - TARGET_TRIPLE: wasm32-wasip1-threads - THREAD_MODEL: posix - DEBUG: true + args: -DCMAKE_BUILD_TYPE=Debug -DTARGET_TRIPLE=wasm32-wasip1-threads - name: Test emmalloc os: ubuntu-24.04 clang_version: 19 test: true - env: - TARGET_TRIPLE: wasm32-wasip1 - MALLOC_IMPL: emmalloc + args: -DMALLOC=emmalloc steps: - uses: actions/checkout@v4.1.7 @@ -160,9 +138,6 @@ jobs: clang_version: ${{ matrix.clang_version }} llvm_asset_suffix: ${{ matrix.llvm_asset_suffix }} - - name: Build libc - run: make -j4 $MAKE_TARGETS CHECK_SYMBOLS=yes - - name: Install V8 dependencies if: matrix.test_with_v8 run: | @@ -171,29 +146,29 @@ jobs: echo ENGINE="$PWD/test/scripts/browser-test/harness.mjs" >> $GITHUB_ENV echo CTEST_ARGS="--label-exclude v8fail" >> $GITHUB_ENV - - name: Setup testing - if: matrix.test + - name: Configure libc run: | - cmake -S test -B testbuild -G Ninja \ - -DTARGET_TRIPLE=${{ env.TARGET_TRIPLE }} \ - -DENGINE=${{ env.ENGINE }} \ - -DCMAKE_LINK_DEPENDS_USE_LINKER=OFF \ - -DMALLOC_IMPL=${{ env.MALLOC_IMPL }} + cmake -G Ninja -S . -B build \ + -DCHECK_SYMBOLS=ON \ + ${{ matrix.args }} \ + -DCMAKE_LINK_DEPENDS_USE_LINKER=OFF - - name: Build tests + - name: Configure testing if: matrix.test - run: ninja -C testbuild + run: cmake -S . -B build -DBUILD_TESTS=ON -DENGINE=${{ env.ENGINE }} + + - name: Build + run: ninja -C build -v - name: Test if: matrix.test - run: ctest --test-dir testbuild --output-on-failure -j4 $CTEST_ARGS - + run: ctest --test-dir build/test --output-on-failure -j4 $CTEST_ARGS - uses: actions/upload-artifact@v4.4.0 if: matrix.upload with: name: ${{ format( 'sysroot-{0}.tgz', matrix.upload) }} - path: sysroot + path: build/sysroot # Disable the headerstest job for now, while WASI transitions from the @@ -244,7 +219,8 @@ jobs: - uses: actions/checkout@v4.1.7 with: submodules: true - - run: make bindings + - run: CC=clang cmake -S . -B build -G Ninja + - run: ninja -C build bindings - run: git diff --exit-code # Currently wasi-libc's test suite is pretty bare-bones. To try to increase @@ -253,28 +229,25 @@ jobs: # the end this runs at least some Python tests against a from-source-built # copy of wasi-libc. python: - name: Test Python + name: Test Python ${{ matrix.name }} runs-on: ubuntu-24.04-arm - env: ${{ matrix.env || fromJSON('{}') }} strategy: fail-fast: false matrix: include: - - env: - TARGET_TRIPLE: wasm32-wasip1 - - env: - TARGET_TRIPLE: wasm32-wasip2 - WASI_SNAPSHOT: p2 - - env: - TARGET_TRIPLE: wasm32-wasip1 - MALLOC_IMPL: emmalloc + - name: wasm32-wasip1 + args: -DTARGET_TRIPLE=wasm32-wasip1 + - name: emmalloc + args: -DTARGET_TRIPLE=wasm32-wasip1 -DMALLOC=emmalloc + - name: wasm32-wasip2 + args: -DTARGET_TRIPLE=wasm32-wasip2 steps: - uses: actions/checkout@v4.1.7 with: submodules: true - run: | - curl https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-arm64-linux.tar.gz -L | tar xzvf - - echo "WASI_SDK_PATH=`pwd`/wasi-sdk-24.0-arm64-linux" >> $GITHUB_ENV + curl https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-arm64-linux.tar.gz -L | tar xzvf - + echo "WASI_SDK_PATH=`pwd`/wasi-sdk-25.0-arm64-linux" >> $GITHUB_ENV if: runner.os == 'Linux' shell: bash working-directory: ${{ runner.tool_cache }} @@ -282,13 +255,13 @@ jobs: uses: bytecodealliance/actions/wasmtime/setup@v1 with: version: "38.0.3" - - run: make -j4 CC=$WASI_SDK_PATH/bin/clang AR=$WASI_SDK_PATH/bin/llvm-ar - - name: Setup testing + - name: Setup wasi-libc run: | - cmake -S test -B testbuild -G Ninja \ - -DTARGET_TRIPLE=${{ env.TARGET_TRIPLE }} \ + cmake -S . -B build -G Ninja \ + ${{ matrix.args }} \ -DCMAKE_LINK_DEPENDS_USE_LINKER=OFF \ -DPYTHON_TESTS=ON \ - -DCMAKE_C_COMPILER=clang + -DBUILD_TESTS=ON \ + -DCMAKE_C_COMPILER=$WASI_SDK_PATH/bin/clang - name: Build and test python - run: ninja -C testbuild python + run: ninja -C build -v python diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..349656473 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,370 @@ +cmake_minimum_required(VERSION 3.26) + +# Give access to our `./cmake` local folder for `include(...)`. +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +# Use `--format=gnu` to generate identical archives regardless of the host. +set(CMAKE_C_ARCHIVE_CREATE " --format=gnu qc ") + +# If no `CMAKE_BUILD_TYPE` was specified, default to `Release`. +if(NOT CMAKE_BUILD_TYPE) + message(STATUS "Setting build type to 'Release' as none was specified.") + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type to use" FORCE) +endif() + +# Force a cross-compile to WASI at all times. +set(CMAKE_SYSTEM_NAME WASI) + +# I'm not entirely sure why this is necessary on Windows. This may be a bug in +# CMake, I'm not sure. The problem is that, at least on CI, CMake detects that +# the compiler in use in clang but doesn't understand the `SYSTEM` header +# option meaning it just pass `-I...` instead of +# `-isystem ...`. This in turn causes the build to fail for... somewhat +# unknown reasons which may also be bugs in wasi-libc. Setting this seems +# to work around the issue however. +if (CMAKE_HOST_WIN32) + set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ") +endif() + +project(wasi-libc LANGUAGES C ASM) + +if(NOT CMAKE_C_COMPILER_ID MATCHES Clang) + message(FATAL_ERROR "C compiler ${CMAKE_C_COMPILER} is not `Clang`, it is ${CMAKE_C_COMPILER_ID}") +endif() + +message(STATUS "Found executable for `nm`: ${CMAKE_NM}") +message(STATUS "Found executable for `ar`: ${CMAKE_AR}") +message(STATUS "Found executable for `ranlib`: ${CMAKE_RANLIB}") + +set(TARGET_TRIPLE "wasm32-wasip1" CACHE STRING "WASI target to test") +# Note: thin LTO here is just for experimentation. It has known issues: +# - https://github.com/llvm/llvm-project/issues/91700 +# - https://github.com/llvm/llvm-project/issues/91711 +set(LTO "" CACHE STRING "LTO mode to use") +set(MALLOC "dlmalloc" CACHE STRING "Malloc implementation to use (dlmalloc, jemalloc, or none)") +set(BUILTINS_LIB "" CACHE STRING "Path to precompiled compiler-rt builtins library") +set(BULK_MEMORY_THRESHOLD "32" CACHE STRING "Threshold to compile code with") +option(SETJMP "Build setjmp/longjmp support" ON) +option(BUILD_TESTS "Whether or not to build tests" OFF) +option(SIMD "Whether or not to build simd-enabled intrinsics into wasi-libc" OFF) +option(BUILD_SHARED "Whether or not to build shared libraries" ON) +option(CHECK_SYMBOLS "Whether or not to check the exported symbols of libc.a" ON) + +if(TARGET_TRIPLE MATCHES "-threads$") + set(WASI p1) + # TODO: As of this writing, wasi_thread_start.s uses non-position-independent + # code, and I'm not sure how to make it position-independent. Once we've + # done that, we can enable libc.so for the wasi-threads build. + set(SHARED OFF) +elseif(TARGET_TRIPLE MATCHES "-wasi$") + set(WASI p1) + set(SHARED ON) +elseif(TARGET_TRIPLE MATCHES "-wasip1$") + set(WASI p1) + set(SHARED ON) +elseif(TARGET_TRIPLE MATCHES "-wasip2$") + set(WASI p2) + set(__wasilibc_use_wasip2 ON) + add_compile_definitions(-D__wasilibc_use_wasip2) + set(SHARED ON) +else() + message(FATAL_ERROR "Unknown WASI target triple: ${TARGET_TRIPLE}") +endif() + +if(BUILD_SHARED) + if (NOT SHARED) + message(WARNING "Disabling shared library builds as target is incompatible with shared libs") + endif() +else() + if (SHARED) + message(STATUS "Disabling shared library builds as BUILD_SHARED=OFF") + endif() + set(SHARED OFF) +endif() + +if(TARGET_TRIPLE MATCHES "-threads$") + set(THREADS ON) + add_compile_options(-mthread-model posix -pthread -ftls-model=local-exec -matomics) +else() + set(THREADS OFF) + add_compile_options(-mthread-model single) +endif() + +if(MALLOC STREQUAL "dlmalloc") + message(STATUS "Using dlmalloc as the malloc implementation") + set(malloc_target dlmalloc) +elseif(MALLOC STREQUAL "emmalloc") + message(STATUS "Using emmalloc as the malloc implementation") + set(malloc_target emmalloc) +elseif(MALLOC STREQUAL "none") + message(STATUS "Using nothing as the malloc implementation") +else() + message(FATAL_ERROR "Unsupported malloc implementation: ${MALLOC}") +endif() + +execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE clang_version + OUTPUT_STRIP_TRAILING_WHITESPACE) +set(SYSROOT ${CMAKE_CURRENT_BINARY_DIR}/sysroot) +set(SYSROOT_INC ${SYSROOT}/include/${TARGET_TRIPLE}) +set(SYSROOT_LIB ${SYSROOT}/lib/${TARGET_TRIPLE}) + +add_custom_target(sysroot ALL) +add_custom_target(sysroot_inc) + +if(LTO) + message(STATUS "Enabling LTO: ${LTO}") + set(SYSROOT_LIB ${SYSROOT_LIB}/llvm-lto/${clang_version}) + if(LTO STREQUAL "thin") + add_compile_options(-flto=thin) + elseif(LTO STREQUAL "full") + add_compile_options(-flto) + else() + message(FATAL_ERROR "Unknown LTO mode: ${LTO}") + endif() +endif() + +if(SIMD) + add_compile_options(-msimd128 -mrelaxed-simd -mbulk-memory + -D__wasilibc_simd_string) +endif() + +include(bindings) +include(builtins) +if (NOT (WASI STREQUAL "p1")) + include(wasm-component-ld) +endif() +include(check-symbols) + +# ============================================================================= +# Generic top-level build flags/settings +# +add_compile_options(--target=${TARGET_TRIPLE}) + +add_link_options( + --target=${TARGET_TRIPLE} + --sysroot=${SYSROOT} + + # By default clang will try to find, locate, and link compiler-rt. To get + # this to work a `-resource-dir` argument is passed to ensure that our + # custom `tmp_resource_dir` built here locally is used instead of the system + # directory which may or may not already have compiler-rt for wasm. + -resource-dir ${tmp_resource_dir} +) + +# Expose the public headers to the implementation. We use `-isystem` for +# purpose for two reasons: +# +# 1. It only does `<...>` not `"...."` lookup. We are making a libc, +# which is a system library, so all public headers should be +# accessible via `<...>` and never also need `"..."`. `-isystem` main +# purpose is to only effect `<...>` lookup. +# +# 2. The `-I` for private headers added for specific C files below +# should come earlier in the search path, so they can "override" +# and/or `#include_next` the public headers. `-isystem` (like +# `-idirafter`) comes later in the search path than `-I`. +# add_compile_options(-isystem ${SYSROOT_INC}) +include_directories(SYSTEM ${SYSROOT_INC}) + +include_directories(libc-bottom-half/cloudlibc/src) + + +add_compile_options( + # WebAssembly floating-point match doesn't trap. + # TODO: Add -fno-signaling-nans when the compiler supports it. + -fno-trapping-math + + # Add all warnings, but disable a few which occur in third-party code. + -Wall -Wextra -Werror + -Wno-null-pointer-arithmetic + -Wno-unused-parameter + -Wno-sign-compare + -Wno-unused-variable + -Wno-unused-function + -Wno-ignored-attributes + -Wno-missing-braces + -Wno-ignored-pragmas + -Wno-unused-but-set-variable + -Wno-unknown-warning-option + -Wno-unterminated-string-initialization + + # Compiling assembly flags lots of arguments as unused but that's not too + # interesting so just ignore that. + $<$:-Wno-unused-command-line-argument> +) + +# ============================================================================= +# Helper functions for adding libraries. + +# Helper to add the `src` file to the sysroot at `dst`. Adds to the `sysroot_inc` +# list of dependencies. +function(add_sysroot_header src dst) + string(REPLACE "/" "_" target_name ${dst}) + add_custom_command( + OUTPUT ${SYSROOT_INC}/${dst} + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/${src} + ${SYSROOT_INC}/${dst} + DEPENDS ${src} + ) + add_custom_target(sysroot-header-${target_name} DEPENDS ${SYSROOT_INC}/${dst}) + add_dependencies(sysroot_inc sysroot-header-${target_name}) +endfunction() + +# Adds two object libraries named `${name}-{shared,static}` and hook them up to +# the sysroot. The `*-shared` library is compiled with `-fPIC`. +function(add_object_library name) + add_library(${name}-shared OBJECT EXCLUDE_FROM_ALL ${ARGN}) + set_target_properties(${name}-shared PROPERTIES POSITION_INDEPENDENT_CODE TRUE) + target_compile_options(${name}-shared PRIVATE -fvisibility=default) + add_dependencies(${name}-shared sysroot_inc) + + add_library(${name}-static OBJECT EXCLUDE_FROM_ALL ${ARGN}) + add_dependencies(${name}-static sysroot_inc) +endfunction() + +# Same as `add_object_library`, but also adds dependencies on +# `musl-top-half-interface` for compiler flags and include dirs. +function(add_internal_object_library name) + add_object_library(${name} ${ARGN}) + target_link_libraries(${name}-shared PUBLIC musl-top-half-interface) + target_link_libraries(${name}-static PUBLIC musl-top-half-interface) +endfunction() + +# Adds a shared library `name` with the following arguments as the +# sources. +# +# Adds a dependnecy on `musl-top-half-interface` for compiler flags, +# `sysroot-c` and `builtins` to ensure link-time dependencies are met, +# and then ensures compile options are configured. +function(add_internal_shared_library name) + add_library(${name} SHARED EXCLUDE_FROM_ALL ${ARGN}) + target_link_libraries(${name} PUBLIC musl-top-half-interface) + add_dependencies(${name} sysroot-c builtins) + target_compile_options(${name} PRIVATE -fvisibility=default) + set_target_properties(${name} PROPERTIES NO_SONAME 1) +endfunction() + +# Adds `${name}` and `${name}-static. +# +# Wrapper around `add_internal_shared_library` and then adding +# a static library as well. +function(add_internal_library_pair name) + add_internal_shared_library(${name} ${ARGN}) + + add_library(${name}-static STATIC EXCLUDE_FROM_ALL ${ARGN}) + target_link_libraries(${name}-static PUBLIC musl-top-half-interface) +endfunction() + +# Helper to add `target`, a cmake library target, to the sysroot at `file`. +# +# Copies the output into place and adds it to the top-level `sysroot` +# target. +function(sysroot_lib target file) + set(dst ${SYSROOT_LIB}/${file}) + add_custom_command( + OUTPUT ${dst} + COMMAND ${CMAKE_COMMAND} -E copy $ ${dst} + DEPENDS ${target} + ) + add_custom_target(sysroot-${target} DEPENDS ${dst}) + if (NOT (${file} MATCHES "\\.so$") OR SHARED) + add_dependencies(sysroot sysroot-${target}) + endif() +endfunction() + +# ============================================================================= +# subdirectories +# + +add_subdirectory(dlmalloc) +add_subdirectory(emmalloc) +add_subdirectory(fts) +add_subdirectory(libc-bottom-half) +add_subdirectory(libc-top-half) + +if (BUILD_TESTS) + add_subdirectory(test) +endif() + +#============================================================================== +# libc.{a,so} +# + +# TODO: if this `*.o` file is added to the `bottom-half-*` object libraries it +# doesn't make its way to the linker. I don't know if that's a bug in cmake or +# me not understanding cmake. This should ideally be bottom-half logic but it's +# here since I can't figure out anything else that works for now. +if (WASI STREQUAL "p2") + set(libc_extra_objects libc-bottom-half/sources/wasip2_component_type.o) +endif() + +add_library(c SHARED EXCLUDE_FROM_ALL + $ + $ + $ + $ + $ + $ + ${libc_extra_objects} +) +add_library(c-static STATIC EXCLUDE_FROM_ALL + $ + $ + $ + $ + $ + $ + ${libc_extra_objects} +) +add_dependencies(c sysroot-startup-objects builtins) + +target_link_options(c PRIVATE + # Note: libc.so is special because it shouldn't link to libc.so, and the + # -nodefaultlibs flag here disables the default `-lc` logic that clang has. + # Note though that this also disables linking of compiler-rt libraries so + # that is explicitly passed in via `${builtins_lib_path}` + -nodefaultlibs + ${builtins_lib_path} + + # Note: --allow-undefined-file=linker-provided-symbols.txt is a workaround + # for https://github.com/llvm/llvm-project/issues/103592 + -Wl,--allow-undefined-file=${CMAKE_CURRENT_SOURCE_DIR}/linker-provided-symbols.txt +) + +# TODO: Specify SDK version, e.g. libc.so.wasi-sdk-21, as SO_NAME once `wasm-ld` +# supports it. +set_target_properties(c PROPERTIES NO_SONAME 1) + +sysroot_lib(c-static libc.a) +sysroot_lib(c libc.so) + +# ============================================================================= +# Empty archives in the sysroot to satisfy `-l` flags + +function(empty_sysroot_archive file) + set(dst ${SYSROOT_LIB}/lib${file}.a) + add_custom_command( + OUTPUT ${dst} + COMMAND ${CMAKE_COMMAND} -E make_directory ${SYSROOT_LIB} + COMMAND ${CMAKE_AR} crs ${dst} + ) + add_custom_target(sysroot-empty-${file} DEPENDS ${dst}) + add_dependencies(sysroot sysroot-empty-${file}) +endfunction() + +empty_sysroot_archive(crypt) +empty_sysroot_archive(m) +empty_sysroot_archive(pthread) +empty_sysroot_archive(resolv) +empty_sysroot_archive(rt) +empty_sysroot_archive(util) +empty_sysroot_archive(xnet) + +# ============================================================================= +# Installation +# +include(GNUInstallDirs) +install(DIRECTORY ${SYSROOT}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +install(DIRECTORY ${SYSROOT}/lib/ DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/Makefile b/Makefile deleted file mode 100644 index 3dc301877..000000000 --- a/Makefile +++ /dev/null @@ -1,1111 +0,0 @@ -# These variables are specifically meant to be overridable via the make -# command-line. -# ?= doesn't work for CC and AR because make has a default value for them. -ifeq ($(origin CC), default) -CC := clang -endif -NM ?= $(patsubst %clang,%llvm-nm,$(filter-out ccache sccache,$(CC))) -ifeq ($(origin AR), default) -AR = $(patsubst %clang,%llvm-ar,$(filter-out ccache sccache,$(CC))) -endif -ifeq ($(origin ARFLAGS), default) -# Use `--format=gnu` to generate identical archives regardless of the host. -ARFLAGS = --format=gnu crs -endif -ifeq ($(DEBUG), true) -EXTRA_CFLAGS ?= -O0 -g -else -EXTRA_CFLAGS ?= -O2 -DNDEBUG -endif -# The directory where we build the sysroot. -SYSROOT ?= $(CURDIR)/sysroot -# A directory to install to for "make install". -INSTALL_DIR ?= /usr/local -# single or posix; note that pthread support is still a work-in-progress. -THREAD_MODEL ?= single -# p1 or p2; the latter is not (yet) compatible with multithreading -WASI_SNAPSHOT ?= p1 -# dlmalloc or none -MALLOC_IMPL ?= dlmalloc -# yes or no -BUILD_LIBC_TOP_HALF ?= yes -# yes or no -BUILD_LIBSETJMP ?= yes - -# Set the default WASI target triple. -TARGET_TRIPLE ?= wasm32-wasi - -# Threaded version necessitates a different target, as objects from different -# targets can't be mixed together while linking. -ifeq ($(THREAD_MODEL), posix) -TARGET_TRIPLE = wasm32-wasip1-threads -endif - -ifeq ($(WASI_SNAPSHOT), p2) -TARGET_TRIPLE = wasm32-wasip2 -endif - -# The directory where we will store intermediate artifacts. -OBJDIR ?= build/$(TARGET_TRIPLE) - -# LTO; no, full, or thin -# Note: thin LTO here is just for experimentation. It has known issues: -# - https://github.com/llvm/llvm-project/issues/91700 -# - https://github.com/llvm/llvm-project/issues/91711 -LTO ?= no -ifneq ($(LTO),no) -CLANG_VERSION ?= $(shell ${CC} -dumpversion) -override OBJDIR := $(OBJDIR)/llvm-lto/$(CLANG_VERSION) -endif - -# When the length is no larger than this threshold, we consider the -# overhead of bulk memory opcodes to outweigh the performance benefit, -# and fall back to the original musl implementation. See -# https://github.com/WebAssembly/wasi-libc/pull/263 for relevant -# discussion -BULK_MEMORY_THRESHOLD ?= 32 - -# Variables from this point on are not meant to be overridable via the -# make command-line. - -# These artifacts are "stamps" that we use to mark that some task (e.g., copying -# files) has been completed. -INCLUDE_DIRS := $(OBJDIR)/copy-include-headers.stamp - -# These variables describe the locations of various files and directories in -# the source tree. -DLMALLOC_DIR = dlmalloc -DLMALLOC_SRC_DIR = $(DLMALLOC_DIR)/src -DLMALLOC_SOURCES = $(DLMALLOC_SRC_DIR)/dlmalloc.c -DLMALLOC_INC = $(DLMALLOC_DIR)/include -EMMALLOC_DIR = emmalloc -EMMALLOC_SOURCES = $(EMMALLOC_DIR)/emmalloc.c -THREAD_STUB_DIR = thread-stub -LIBC_BOTTOM_HALF_DIR = libc-bottom-half -LIBC_BOTTOM_HALF_CLOUDLIBC_SRC = $(LIBC_BOTTOM_HALF_DIR)/cloudlibc/src -LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC = $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/include -LIBC_BOTTOM_HALF_HEADERS_PUBLIC = $(LIBC_BOTTOM_HALF_DIR)/headers/public -LIBC_BOTTOM_HALF_HEADERS_PRIVATE = $(LIBC_BOTTOM_HALF_DIR)/headers/private -LIBC_BOTTOM_HALF_SOURCES = $(LIBC_BOTTOM_HALF_DIR)/sources -LIBC_BOTTOM_HALF_ALL_SOURCES = \ - $(sort \ - $(shell find $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) -name \*.c) \ - $(shell find $(LIBC_BOTTOM_HALF_SOURCES) -name \*.c)) - -ifeq ($(WASI_SNAPSHOT), p1) -# Omit source files not relevant to WASIp1. As we introduce files -# supporting `wasi-sockets` for `wasm32-wasip2`, we'll add those files to -# this list. -LIBC_BOTTOM_HALF_OMIT_SOURCES := \ - $(LIBC_BOTTOM_HALF_SOURCES)/wasip2.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/descriptor_table.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/connect.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/socket.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/send.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/recv.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/sockets_utils.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/bind.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/listen.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/accept-wasip2.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/shutdown.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/sockopt.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/poll-wasip2.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/getsockpeername.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/netdb.c -LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_OMIT_SOURCES),$(LIBC_BOTTOM_HALF_ALL_SOURCES)) -# Omit p2-specific headers from include-all.c test. -# for exception-handling. -INCLUDE_ALL_CLAUSES := -not -name wasip2.h -not -name descriptor_table.h -endif - -ifeq ($(WASI_SNAPSHOT), p2) -# Omit source files not relevant to WASIp2. -LIBC_BOTTOM_HALF_OMIT_SOURCES := \ - $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/libc/sys/socket/send.c \ - $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/libc/sys/socket/recv.c \ - $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/libc/sys/socket/shutdown.c \ - $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/libc/sys/socket/getsockopt.c \ - $(LIBC_BOTTOM_HALF_SOURCES)/accept-wasip1.c -LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_OMIT_SOURCES),$(LIBC_BOTTOM_HALF_ALL_SOURCES)) -endif - -# FIXME(https://reviews.llvm.org/D85567) - due to a bug in LLD the weak -# references to a function defined in `chdir.c` only work if `chdir.c` is at the -# end of the archive, but once that LLD review lands and propagates into LLVM -# then we don't have to do this. -LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_SOURCES)/chdir.c,$(LIBC_BOTTOM_HALF_ALL_SOURCES)) -LIBC_BOTTOM_HALF_ALL_SOURCES := $(LIBC_BOTTOM_HALF_ALL_SOURCES) $(LIBC_BOTTOM_HALF_SOURCES)/chdir.c - -LIBWASI_EMULATED_MMAN_SOURCES = \ - $(sort $(shell find $(LIBC_BOTTOM_HALF_DIR)/mman -name \*.c)) -LIBWASI_EMULATED_PROCESS_CLOCKS_SOURCES = \ - $(sort $(shell find $(LIBC_BOTTOM_HALF_DIR)/clocks -name \*.c)) -LIBWASI_EMULATED_GETPID_SOURCES = \ - $(sort $(shell find $(LIBC_BOTTOM_HALF_DIR)/getpid -name \*.c)) -LIBWASI_EMULATED_SIGNAL_SOURCES = \ - $(sort $(shell find $(LIBC_BOTTOM_HALF_DIR)/signal -name \*.c)) -LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/signal/psignal.c \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/strsignal.c -LIBDL_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/dl.c -LIBSETJMP_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/setjmp/wasm32/rt.c -LIBC_BOTTOM_HALF_CRT_SOURCES = $(wildcard $(LIBC_BOTTOM_HALF_DIR)/crt/*.c) -LIBC_TOP_HALF_DIR = libc-top-half -LIBC_TOP_HALF_MUSL_DIR = $(LIBC_TOP_HALF_DIR)/musl -LIBC_TOP_HALF_MUSL_SRC_DIR = $(LIBC_TOP_HALF_MUSL_DIR)/src -LIBC_TOP_HALF_MUSL_INC = $(LIBC_TOP_HALF_MUSL_DIR)/include -LIBC_TOP_HALF_MUSL_SOURCES = \ - $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \ - misc/a64l.c \ - misc/basename.c \ - misc/dirname.c \ - misc/ffs.c \ - misc/ffsl.c \ - misc/ffsll.c \ - misc/fmtmsg.c \ - misc/getdomainname.c \ - misc/gethostid.c \ - misc/getopt.c \ - misc/getopt_long.c \ - misc/getsubopt.c \ - misc/realpath.c \ - misc/uname.c \ - misc/nftw.c \ - errno/strerror.c \ - network/htonl.c \ - network/htons.c \ - network/in6addr_any.c \ - network/in6addr_loopback.c \ - network/inet_addr.c \ - network/inet_aton.c \ - network/inet_legacy.c \ - network/inet_ntoa.c \ - network/inet_ntop.c \ - network/inet_pton.c \ - network/ntohl.c \ - network/ntohs.c \ - fenv/fenv.c \ - fenv/fesetround.c \ - fenv/feupdateenv.c \ - fenv/fesetexceptflag.c \ - fenv/fegetexceptflag.c \ - fenv/feholdexcept.c \ - exit/exit.c \ - exit/atexit.c \ - exit/assert.c \ - exit/quick_exit.c \ - exit/at_quick_exit.c \ - time/strftime.c \ - time/asctime.c \ - time/asctime_r.c \ - time/ctime.c \ - time/ctime_r.c \ - time/wcsftime.c \ - time/strptime.c \ - time/difftime.c \ - time/timegm.c \ - time/ftime.c \ - time/gmtime.c \ - time/gmtime_r.c \ - time/timespec_get.c \ - time/getdate.c \ - time/localtime.c \ - time/localtime_r.c \ - time/mktime.c \ - time/__tm_to_secs.c \ - time/__month_to_secs.c \ - time/__secs_to_tm.c \ - time/__year_to_secs.c \ - time/__tz.c \ - fcntl/creat.c \ - dirent/alphasort.c \ - dirent/versionsort.c \ - env/__stack_chk_fail.c \ - env/clearenv.c \ - env/getenv.c \ - env/putenv.c \ - env/setenv.c \ - env/unsetenv.c \ - unistd/posix_close.c \ - unistd/gethostname.c \ - stat/futimesat.c \ - legacy/getpagesize.c \ - thread/thrd_sleep.c \ - ) \ - $(filter-out %/procfdname.c %/syscall.c %/syscall_ret.c %/vdso.c %/version.c %/emulate_wait4.c, \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/*.c)) \ - $(filter-out %/flockfile.c %/funlockfile.c %/__lockfile.c %/ftrylockfile.c \ - %/rename.c \ - %/tmpnam.c %/tmpfile.c %/tempnam.c \ - %/popen.c %/pclose.c \ - %/remove.c \ - %/gets.c, \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/*.c)) \ - $(filter-out %/strsignal.c, \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/*.c)) \ - $(filter-out %/dcngettext.c %/textdomain.c %/bind_textdomain_codeset.c, \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/locale/*.c)) \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdlib/*.c) \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/search/*.c) \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/multibyte/*.c) \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/regex/*.c) \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/prng/*.c) \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/conf/*.c) \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/ctype/*.c) \ - $(filter-out %/__signbit.c %/__signbitf.c %/__signbitl.c \ - %/__fpclassify.c %/__fpclassifyf.c %/__fpclassifyl.c \ - %/ceilf.c %/ceil.c \ - %/floorf.c %/floor.c \ - %/truncf.c %/trunc.c \ - %/rintf.c %/rint.c \ - %/nearbyintf.c %/nearbyint.c \ - %/sqrtf.c %/sqrt.c \ - %/fabsf.c %/fabs.c \ - %/copysignf.c %/copysign.c \ - %/fminf.c %/fmaxf.c \ - %/fmin.c %/fmax.c, \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/math/*.c)) \ - $(filter-out %/crealf.c %/creal.c %creall.c \ - %/cimagf.c %/cimag.c %cimagl.c, \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/complex/*.c)) \ - $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/crypt/*.c) - -LIBC_NONLTO_SOURCES = \ - $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \ - exit/atexit.c \ - setjmp/wasm32/rt.c \ - ) - -ifeq ($(WASI_SNAPSHOT), p2) -LIBC_TOP_HALF_MUSL_SOURCES += \ - $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \ - network/gai_strerror.c \ - ) -endif - -# pthreads functions (possibly stub) for either thread model -LIBC_TOP_HALF_MUSL_SOURCES += \ - $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \ - env/__init_tls.c \ - thread/default_attr.c \ - thread/pthread_attr_destroy.c \ - thread/pthread_attr_get.c \ - thread/pthread_attr_init.c \ - thread/pthread_attr_setdetachstate.c \ - thread/pthread_attr_setguardsize.c \ - thread/pthread_attr_setschedparam.c \ - thread/pthread_attr_setstack.c \ - thread/pthread_attr_setstacksize.c \ - thread/pthread_barrierattr_destroy.c \ - thread/pthread_barrierattr_init.c \ - thread/pthread_barrierattr_setpshared.c \ - thread/pthread_cancel.c \ - thread/pthread_cleanup_push.c \ - thread/pthread_condattr_destroy.c \ - thread/pthread_condattr_init.c \ - thread/pthread_condattr_setclock.c \ - thread/pthread_condattr_setpshared.c \ - thread/pthread_equal.c \ - thread/pthread_getattr_np.c \ - thread/pthread_getspecific.c \ - thread/pthread_key_create.c \ - thread/pthread_mutex_destroy.c \ - thread/pthread_mutex_init.c \ - thread/pthread_mutexattr_destroy.c \ - thread/pthread_mutexattr_init.c \ - thread/pthread_mutexattr_setprotocol.c \ - thread/pthread_mutexattr_setpshared.c \ - thread/pthread_mutexattr_setrobust.c \ - thread/pthread_mutexattr_settype.c \ - thread/pthread_rwlock_destroy.c \ - thread/pthread_rwlock_init.c \ - thread/pthread_rwlockattr_destroy.c \ - thread/pthread_rwlockattr_init.c \ - thread/pthread_rwlockattr_setpshared.c \ - thread/pthread_self.c \ - thread/pthread_setcancelstate.c \ - thread/pthread_setcanceltype.c \ - thread/pthread_setspecific.c \ - thread/pthread_spin_destroy.c \ - thread/pthread_spin_init.c \ - thread/pthread_testcancel.c \ - ) -ifeq ($(THREAD_MODEL), posix) -# pthreads functions needed for actual thread support -LIBC_TOP_HALF_MUSL_SOURCES += \ - $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \ - stdio/__lockfile.c \ - stdio/flockfile.c \ - stdio/ftrylockfile.c \ - stdio/funlockfile.c \ - thread/__lock.c \ - thread/__wait.c \ - thread/__timedwait.c \ - thread/pthread_barrier_destroy.c \ - thread/pthread_barrier_init.c \ - thread/pthread_barrier_wait.c \ - thread/pthread_cond_broadcast.c \ - thread/pthread_cond_destroy.c \ - thread/pthread_cond_init.c \ - thread/pthread_cond_signal.c \ - thread/pthread_cond_timedwait.c \ - thread/pthread_cond_wait.c \ - thread/pthread_create.c \ - thread/pthread_detach.c \ - thread/pthread_join.c \ - thread/pthread_mutex_consistent.c \ - thread/pthread_mutex_getprioceiling.c \ - thread/pthread_mutex_lock.c \ - thread/pthread_mutex_timedlock.c \ - thread/pthread_mutex_trylock.c \ - thread/pthread_mutex_unlock.c \ - thread/pthread_once.c \ - thread/pthread_rwlock_rdlock.c \ - thread/pthread_rwlock_timedrdlock.c \ - thread/pthread_rwlock_timedwrlock.c \ - thread/pthread_rwlock_tryrdlock.c \ - thread/pthread_rwlock_trywrlock.c \ - thread/pthread_rwlock_unlock.c \ - thread/pthread_rwlock_wrlock.c \ - thread/pthread_spin_lock.c \ - thread/pthread_spin_trylock.c \ - thread/pthread_spin_unlock.c \ - thread/sem_destroy.c \ - thread/sem_getvalue.c \ - thread/sem_init.c \ - thread/sem_post.c \ - thread/sem_timedwait.c \ - thread/sem_trywait.c \ - thread/sem_wait.c \ - thread/wasm32/wasi_thread_start.s \ - thread/wasm32/__wasilibc_busywait.c \ - ) -endif -ifeq ($(THREAD_MODEL), single) -# pthreads stubs for single-threaded environment -LIBC_TOP_HALF_MUSL_SOURCES += \ - $(addprefix $(THREAD_STUB_DIR)/, \ - pthread_barrier_destroy.c \ - pthread_barrier_init.c \ - pthread_barrier_wait.c \ - pthread_cond_broadcast.c \ - pthread_cond_destroy.c \ - pthread_cond_init.c \ - pthread_cond_signal.c \ - pthread_cond_timedwait.c \ - pthread_cond_wait.c \ - pthread_create.c \ - pthread_detach.c \ - pthread_join.c \ - pthread_mutex_consistent.c \ - pthread_mutex_getprioceiling.c \ - pthread_mutex_lock.c \ - pthread_mutex_timedlock.c \ - pthread_mutex_trylock.c \ - pthread_mutex_unlock.c \ - pthread_once.c \ - pthread_rwlock_rdlock.c \ - pthread_rwlock_timedrdlock.c \ - pthread_rwlock_timedwrlock.c \ - pthread_rwlock_tryrdlock.c \ - pthread_rwlock_trywrlock.c \ - pthread_rwlock_unlock.c \ - pthread_rwlock_wrlock.c \ - pthread_spin_lock.c \ - pthread_spin_trylock.c \ - pthread_spin_unlock.c \ - ) -endif - -MUSL_PRINTSCAN_SOURCES = \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/floatscan.c \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/vfprintf.c \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/vfwprintf.c \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/vfscanf.c \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdlib/strtod.c \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdlib/wcstod.c -BULK_MEMORY_SOURCES = \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/memcpy.c \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/memmove.c \ - $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/memset.c -LIBC_TOP_HALF_HEADERS_PRIVATE = $(LIBC_TOP_HALF_DIR)/headers/private -LIBC_TOP_HALF_SOURCES = $(LIBC_TOP_HALF_DIR)/sources -LIBC_TOP_HALF_ALL_SOURCES = \ - $(LIBC_TOP_HALF_MUSL_SOURCES) \ - $(sort $(shell find $(LIBC_TOP_HALF_SOURCES) -name \*.[cs])) - -FTS_SRC_DIR = fts -MUSL_FTS_SRC_DIR = $(FTS_SRC_DIR)/musl-fts -FTS_SOURCES = $(MUSL_FTS_SRC_DIR)/fts.c - -# Add any extra flags -CFLAGS = $(EXTRA_CFLAGS) -# Set the target. -CFLAGS += --target=$(TARGET_TRIPLE) -ASMFLAGS += --target=$(TARGET_TRIPLE) -# WebAssembly floating-point match doesn't trap. -# TODO: Add -fno-signaling-nans when the compiler supports it. -CFLAGS += -fno-trapping-math -# Add all warnings, but disable a few which occur in third-party code. -CFLAGS += -Wall -Wextra -Werror \ - -Wno-null-pointer-arithmetic \ - -Wno-unused-parameter \ - -Wno-sign-compare \ - -Wno-unused-variable \ - -Wno-unused-function \ - -Wno-ignored-attributes \ - -Wno-missing-braces \ - -Wno-ignored-pragmas \ - -Wno-unused-but-set-variable \ - -Wno-unknown-warning-option \ - -Wno-unterminated-string-initialization - -# Configure support for threads. -ifeq ($(THREAD_MODEL), single) -CFLAGS += -mthread-model single -endif -ifeq ($(THREAD_MODEL), posix) -# Specify the tls-model until LLVM 15 is released (which should contain -# https://reviews.llvm.org/D130053). -CFLAGS += -mthread-model posix -pthread -ftls-model=local-exec -ASMFLAGS += -matomics -endif - -# Include cloudlib's directory to access the structure definition of clockid_t -CFLAGS += -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) - -ifneq ($(LTO),no) -ifeq ($(LTO),full) -CFLAGS += -flto=full -else -ifeq ($(LTO),thin) -CFLAGS += -flto=thin -else -$(error unknown LTO value: $(LTO)) -endif -endif -endif - -ifeq ($(WASI_SNAPSHOT), p2) -CFLAGS += -D__wasilibc_use_wasip2 -endif - -# Expose the public headers to the implementation. We use `-isystem` for -# purpose for two reasons: -# -# 1. It only does `<...>` not `"...."` lookup. We are making a libc, -# which is a system library, so all public headers should be -# accessible via `<...>` and never also need `"..."`. `-isystem` main -# purpose is to only effect `<...>` lookup. -# -# 2. The `-I` for private headers added for specific C files below -# should come earlier in the search path, so they can "override" -# and/or `#include_next` the public headers. `-isystem` (like -# `-idirafter`) comes later in the search path than `-I`. -CFLAGS += -isystem "$(SYSROOT_INC)" - -# These variables describe the locations of various files and directories in -# the build tree. -objs = $(patsubst %.c,$(OBJDIR)/%.o,$(1)) -asmobjs = $(patsubst %.s,$(OBJDIR)/%.o,$(1)) -DLMALLOC_OBJS = $(call objs,$(DLMALLOC_SOURCES)) -EMMALLOC_OBJS = $(call objs,$(EMMALLOC_SOURCES)) -LIBC_BOTTOM_HALF_ALL_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_ALL_SOURCES)) -LIBC_TOP_HALF_ALL_OBJS = $(call asmobjs,$(call objs,$(LIBC_TOP_HALF_ALL_SOURCES))) -FTS_OBJS = $(call objs,$(FTS_SOURCES)) -ifeq ($(WASI_SNAPSHOT), p2) -LIBC_OBJS += $(OBJDIR)/wasip2_component_type.o -endif -ifeq ($(MALLOC_IMPL),dlmalloc) -LIBC_OBJS += $(DLMALLOC_OBJS) -else ifeq ($(MALLOC_IMPL),emmalloc) -LIBC_OBJS += $(EMMALLOC_OBJS) -else ifeq ($(MALLOC_IMPL),none) -# No object files to add. -else -$(error unknown malloc implementation $(MALLOC_IMPL)) -endif -# Add libc-bottom-half's objects. -LIBC_OBJS += $(LIBC_BOTTOM_HALF_ALL_OBJS) -ifeq ($(BUILD_LIBC_TOP_HALF),yes) -# libc-top-half is musl. -LIBC_OBJS += $(LIBC_TOP_HALF_ALL_OBJS) -endif -LIBC_OBJS += $(FTS_OBJS) -MUSL_PRINTSCAN_OBJS = $(call objs,$(MUSL_PRINTSCAN_SOURCES)) -MUSL_PRINTSCAN_LONG_DOUBLE_OBJS = $(patsubst %.o,%.long-double.o,$(MUSL_PRINTSCAN_OBJS)) -MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS = $(patsubst %.o,%.no-floating-point.o,$(MUSL_PRINTSCAN_OBJS)) -BULK_MEMORY_OBJS = $(call objs,$(BULK_MEMORY_SOURCES)) -LIBWASI_EMULATED_MMAN_OBJS = $(call objs,$(LIBWASI_EMULATED_MMAN_SOURCES)) -LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS = $(call objs,$(LIBWASI_EMULATED_PROCESS_CLOCKS_SOURCES)) -LIBWASI_EMULATED_GETPID_OBJS = $(call objs,$(LIBWASI_EMULATED_GETPID_SOURCES)) -LIBWASI_EMULATED_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES)) -LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES)) -LIBDL_OBJS = $(call objs,$(LIBDL_SOURCES)) -LIBSETJMP_OBJS = $(call objs,$(LIBSETJMP_SOURCES)) -LIBC_BOTTOM_HALF_CRT_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_CRT_SOURCES)) -LIBC_NONLTO_OBJS = $(call objs,$(LIBC_NONLTO_SOURCES)) - -# These variables describe the locations of various files and -# directories in the generated sysroot tree. -SYSROOT_LIB := $(SYSROOT)/lib/$(TARGET_TRIPLE) -ifneq ($(LTO),no) -override SYSROOT_LIB := $(SYSROOT_LIB)/llvm-lto/$(CLANG_VERSION) -endif -SYSROOT_INC = $(SYSROOT)/include/$(TARGET_TRIPLE) -SYSROOT_SHARE = $(SYSROOT)/share/$(TARGET_TRIPLE) - -default: finish - -LIBC_SO_OBJS = $(patsubst %.o,%.pic.o,$(filter-out $(MUSL_PRINTSCAN_OBJS),$(LIBC_OBJS))) -MUSL_PRINTSCAN_LONG_DOUBLE_SO_OBJS = $(patsubst %.o,%.pic.o,$(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS)) -LIBWASI_EMULATED_MMAN_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_MMAN_OBJS)) -LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS)) -LIBWASI_EMULATED_GETPID_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_GETPID_OBJS)) -LIBWASI_EMULATED_SIGNAL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_OBJS)) -LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS)) -LIBDL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBDL_OBJS)) -LIBSETJMP_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBSETJMP_OBJS)) -BULK_MEMORY_SO_OBJS = $(patsubst %.o,%.pic.o,$(BULK_MEMORY_OBJS)) -DLMALLOC_SO_OBJS = $(patsubst %.o,%.pic.o,$(DLMALLOC_OBJS)) -LIBC_BOTTOM_HALF_ALL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBC_BOTTOM_HALF_ALL_OBJS)) -LIBC_TOP_HALF_ALL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBC_TOP_HALF_ALL_OBJS)) -FTS_SO_OBJS = $(patsubst %.o,%.pic.o,$(FTS_OBJS)) - -PIC_OBJS = \ - $(LIBC_SO_OBJS) \ - $(MUSL_PRINTSCAN_LONG_DOUBLE_SO_OBJS) \ - $(LIBWASI_EMULATED_MMAN_SO_OBJS) \ - $(LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS) \ - $(LIBWASI_EMULATED_GETPID_SO_OBJS) \ - $(LIBWASI_EMULATED_SIGNAL_SO_OBJS) \ - $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) \ - $(LIBDL_SO_OBJS) \ - $(LIBSETJMP_SO_OBJS) \ - $(BULK_MEMORY_SO_OBJS) \ - $(DLMALLOC_SO_OBJS) \ - $(LIBC_BOTTOM_HALF_ALL_SO_OBJS) \ - $(LIBC_TOP_HALF_ALL_SO_OBJS) \ - $(LIBC_BOTTOM_HALF_CRT_OBJS) \ - $(FTS_SO_OBJS) - -# Figure out what to do about compiler-rt. -# -# The compiler-rt library is not built here in the wasi-libc repository, but it -# is required to link artifacts. Notably `libc.so` and test and such all require -# it to exist. Currently the ways this is handled are: -# -# * If `BUILTINS_LIB` is defined at build time then that's assumed to be a path -# to the libcompiler-rt.a. That's then ingested into the build here and copied -# around to special locations to get the `*.so` rules below to work (see docs -# there). -# -# * If `BUILTINS_LIB` is not defined then a known-good copy is downloaded from -# wasi-sdk CI and used instead. -# -# In the future this may also want some form of configuration to support -# assuming the system compiler has a compiler-rt, e.g. if $(SYSTEM_BUILTINS_LIB) -# exists that should be used instead. -SYSTEM_BUILTINS_LIB := $(shell ${CC} ${CFLAGS} --print-libgcc-file-name) -SYSTEM_RESOURCE_DIR := $(shell ${CC} ${CFLAGS} -print-resource-dir) -BUILTINS_LIB_REL_1 := $(subst $(SYSTEM_RESOURCE_DIR),,$(SYSTEM_BUILTINS_LIB)) -# Substitute '/' for '\' so Windows paths work -BUILTINS_LIB_REL := $(subst \,/,$(BUILTINS_LIB_REL_1)) -TMP_RESOURCE_DIR := $(OBJDIR)/resource-dir -BUILTINS_LIB_PATH := $(TMP_RESOURCE_DIR)/$(BUILTINS_LIB_REL) -BUILTINS_LIB_DIR := $(dir $(BUILTINS_LIB_PATH)) - -ifneq ($(BUILTINS_LIB),) -$(BUILTINS_LIB_PATH): $(BUILTINS_LIB) - mkdir -p $(BUILTINS_LIB_DIR) - cp $(BUILTINS_LIB) $(BUILTINS_LIB_PATH) -else - -BUILTINS_URL := https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/libclang_rt.builtins-wasm32-wasi-25.0.tar.gz - -$(BUILTINS_LIB_PATH): -# mkdir on Windows will error if the directory already exists -ifeq ("$(wildcard $(BUILTINS_LIB_DIR))","") - mkdir -p "$(BUILTINS_LIB_DIR)" -endif - curl -sSfL $(BUILTINS_URL) | \ - tar xzf - -C $(BUILTINS_LIB_DIR) --strip-components 1 - if [ ! -f $(BUILTINS_LIB_PATH) ]; then \ - mv $(BUILTINS_LIB_DIR)/*.a $(BUILTINS_LIB_PATH); \ - fi -endif - -builtins: $(BUILTINS_LIB_PATH) - -# TODO: Specify SDK version, e.g. libc.so.wasi-sdk-21, as SO_NAME once `wasm-ld` -# supports it. -# -# Note that we collect the object files for each shared library into a .a and -# link that using `--whole-archive` rather than pass the object files directly -# to CC. This is a workaround for a Windows command line size limitation. See -# the `%.a` rule below for details. - -# Note: libc.so is special because it shouldn't link to libc.so, and the -# -nodefaultlibs flag here disables the default `-lc` logic that clang -# has. Note though that this also disables linking of compiler-rt -# libraries so that is explicitly passed in via `$(BUILTINS_LIB_PATH)` -# -# Note: --allow-undefined-file=linker-provided-symbols.txt is -# a workaround for https://github.com/llvm/llvm-project/issues/103592 -$(SYSROOT_LIB)/libc.so: $(OBJDIR)/libc.so.a $(BUILTINS_LIB_PATH) - $(CC) --target=${TARGET_TRIPLE} -nodefaultlibs \ - -shared --sysroot=$(SYSROOT) \ - -o $@ -Wl,--whole-archive $< -Wl,--no-whole-archive \ - -Wl,--allow-undefined-file=linker-provided-symbols.txt \ - $(BUILTINS_LIB_PATH) \ - $(EXTRA_CFLAGS) $(LDFLAGS) - -# Note that unlike `libc.so` above this rule does not pass `-nodefaultlibs` -# which means that libc will be linked by default. Additionally clang will try -# to find, locate, and link compiler-rt. To get compiler-rt to work a -# `-resource-dir` argument is passed to ensure that our custom -# `TMP_RESOURCE_DIR` built here locally is used instead of the system directory -# which may or may not already have compiler-rt. -$(SYSROOT_LIB)/%.so: $(OBJDIR)/%.so.a $(SYSROOT_LIB)/libc.so - $(CC) --target=${TARGET_TRIPLE} \ - -shared --sysroot=$(SYSROOT) \ - -o $@ -Wl,--whole-archive $< -Wl,--no-whole-archive \ - -Wl,--allow-undefined-file=linker-provided-symbols.txt \ - -resource-dir $(TMP_RESOURCE_DIR) \ - $(EXTRA_CFLAGS) $(LDFLAGS) - -$(OBJDIR)/libc.so.a: $(LIBC_SO_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_SO_OBJS) - -$(OBJDIR)/libwasi-emulated-mman.so.a: $(LIBWASI_EMULATED_MMAN_SO_OBJS) - -$(OBJDIR)/libwasi-emulated-process-clocks.so.a: $(LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS) - -$(OBJDIR)/libwasi-emulated-getpid.so.a: $(LIBWASI_EMULATED_GETPID_SO_OBJS) - -$(OBJDIR)/libwasi-emulated-signal.so.a: $(LIBWASI_EMULATED_SIGNAL_SO_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) - -$(OBJDIR)/libdl.so.a: $(LIBDL_SO_OBJS) - -$(OBJDIR)/libsetjmp.so.a: $(LIBSETJMP_SO_OBJS) - -$(SYSROOT_LIB)/libc.a: $(LIBC_OBJS) - -$(SYSROOT_LIB)/libc-printscan-long-double.a: $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) - -$(SYSROOT_LIB)/libc-printscan-no-floating-point.a: $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) - -$(SYSROOT_LIB)/libwasi-emulated-mman.a: $(LIBWASI_EMULATED_MMAN_OBJS) - -$(SYSROOT_LIB)/libwasi-emulated-process-clocks.a: $(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS) - -$(SYSROOT_LIB)/libwasi-emulated-getpid.a: $(LIBWASI_EMULATED_GETPID_OBJS) - -$(SYSROOT_LIB)/libwasi-emulated-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) - -$(SYSROOT_LIB)/libdl.a: $(LIBDL_OBJS) - -$(SYSROOT_LIB)/libsetjmp.a: $(LIBSETJMP_OBJS) - -%.a: - @mkdir -p "$(@D)" - # On Windows, the commandline for the ar invocation got too long, so it needs to be split up. - $(AR) $(ARFLAGS) $@ $(wordlist 1, 199, $(sort $^)) - $(AR) $(ARFLAGS) $@ $(wordlist 200, 399, $(sort $^)) - $(AR) $(ARFLAGS) $@ $(wordlist 400, 599, $(sort $^)) - $(AR) $(ARFLAGS) $@ $(wordlist 600, 799, $(sort $^)) - # This might eventually overflow again, but at least it'll do so in a loud way instead of - # silently dropping the tail. - $(AR) $(ARFLAGS) $@ $(wordlist 800, 100000, $(sort $^)) - -$(PIC_OBJS): CFLAGS += -fPIC -fvisibility=default - -$(LIBC_NONLTO_OBJS): CFLAGS := $(filter-out -flto% -fno-lto, $(CFLAGS)) -fno-lto - -$(MUSL_PRINTSCAN_OBJS): CFLAGS += \ - -D__wasilibc_printscan_no_long_double \ - -D__wasilibc_printscan_full_support_option="\"add -lc-printscan-long-double to the link command\"" - -$(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS): CFLAGS += \ - -D__wasilibc_printscan_no_floating_point \ - -D__wasilibc_printscan_floating_point_support_option="\"remove -lc-printscan-no-floating-point from the link command\"" - -# TODO: apply -mbulk-memory globally, once -# https://github.com/llvm/llvm-project/issues/52618 is resolved -$(BULK_MEMORY_OBJS) $(BULK_MEMORY_SO_OBJS): CFLAGS += \ - -mbulk-memory - -$(BULK_MEMORY_OBJS) $(BULK_MEMORY_SO_OBJS): CFLAGS += \ - -DBULK_MEMORY_THRESHOLD=$(BULK_MEMORY_THRESHOLD) - -$(LIBSETJMP_OBJS) $(LIBSETJMP_SO_OBJS): CFLAGS += \ - -mllvm -wasm-enable-sjlj - -$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS): CFLAGS += \ - -D_WASI_EMULATED_SIGNAL - -$(OBJDIR)/%.long-double.pic.o: %.c $(INCLUDE_DIRS) - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) -MD -MP -o $@ -c $< - -$(OBJDIR)/wasip2_component_type.pic.o $(OBJDIR)/wasip2_component_type.o: $(LIBC_BOTTOM_HALF_SOURCES)/wasip2_component_type.o - @mkdir -p "$(@D)" - cp $< $@ - -$(OBJDIR)/%.pic.o: %.c $(INCLUDE_DIRS) - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) -MD -MP -o $@ -c $< - -$(OBJDIR)/%.long-double.o: %.c $(INCLUDE_DIRS) - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) -MD -MP -o $@ -c $< - -$(OBJDIR)/%.no-floating-point.o: %.c $(INCLUDE_DIRS) - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) -MD -MP -o $@ -c $< - -$(OBJDIR)/%.o: %.c $(INCLUDE_DIRS) - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) -MD -MP -o $@ -c $< - -$(OBJDIR)/%.o: %.s $(INCLUDE_DIRS) - @mkdir -p "$(@D)" - $(CC) $(ASMFLAGS) -o $@ -c $< - --include $(shell find $(OBJDIR) -name \*.d) - -$(DLMALLOC_OBJS) $(DLMALLOC_SO_OBJS): CFLAGS += \ - -I$(DLMALLOC_INC) - -$(STARTUP_FILES) $(LIBC_BOTTOM_HALF_ALL_OBJS) $(LIBC_BOTTOM_HALF_ALL_SO_OBJS): CFLAGS += \ - -I$(LIBC_BOTTOM_HALF_HEADERS_PRIVATE) \ - -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC) \ - -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) \ - -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \ - -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal - -$(LIBC_TOP_HALF_ALL_OBJS) $(LIBC_TOP_HALF_ALL_SO_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_SO_OBJS) $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) $(LIBDL_OBJS) $(LIBDL_SO_OBJS) $(LIBSETJMP_OBJS) $(LIBSETJMP_SO_OBJS): CFLAGS += \ - -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \ - -I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal \ - -I$(LIBC_TOP_HALF_MUSL_DIR)/arch/wasm32 \ - -I$(LIBC_TOP_HALF_MUSL_DIR)/arch/generic \ - -I$(LIBC_TOP_HALF_HEADERS_PRIVATE) \ - -Wno-parentheses \ - -Wno-shift-op-parentheses \ - -Wno-bitwise-op-parentheses \ - -Wno-logical-op-parentheses \ - -Wno-string-plus-int \ - -Wno-dangling-else \ - -Wno-unknown-pragmas - -$(FTS_OBJS) $(FTS_SO_OBJS): CFLAGS += \ - -I$(MUSL_FTS_SRC_DIR) \ - -I$(FTS_SRC_DIR) # for config.h - -$(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS) $(LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS): CFLAGS += \ - -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) - -# emmalloc uses a lot of pointer type-punning, which is UB under strict aliasing, -# and this was found to have real miscompilations in wasi-libc#421. -$(EMMALLOC_OBJS): CFLAGS += \ - -fno-strict-aliasing - -ALL_POSSIBLE_HEADERS += $(shell find $(LIBC_TOP_HALF_MUSL_DIR) -name \*.h) -ALL_POSSIBLE_HEADERS += $(shell find $(LIBC_BOTTOM_HALF_HEADERS_PUBLIC) -name \*.h) -ALL_POSSIBLE_HEADERS += $(shell find $(MUSL_FTS_SRC_DIR) -name \*.h) -$(INCLUDE_DIRS): $(ALL_POSSIBLE_HEADERS) - # - # Install the include files. - # - SYSROOT_INC=$(SYSROOT_INC) TARGET_TRIPLE=$(TARGET_TRIPLE) \ - $(CURDIR)/scripts/install-include-headers.sh - # Stamp the include installation. - @mkdir -p $(@D) - touch $@ - -STARTUP_FILES := $(OBJDIR)/copy-startup-files.stamp -$(STARTUP_FILES): $(INCLUDE_DIRS) $(LIBC_BOTTOM_HALF_CRT_OBJS) - # - # Install the startup files (crt1.o, etc.). - # - mkdir -p "$(SYSROOT_LIB)" - cp $(LIBC_BOTTOM_HALF_CRT_OBJS) "$(SYSROOT_LIB)" - - # Stamp the startup file installation. - @mkdir -p $(@D) - touch $@ - -startup_files: $(STARTUP_FILES) - -# TODO: As of this writing, wasi_thread_start.s uses non-position-independent -# code, and I'm not sure how to make it position-independent. Once we've done -# that, we can enable libc.so for the wasi-threads build. -ifneq ($(THREAD_MODEL), posix) -LIBC_SO = \ - $(SYSROOT_LIB)/libc.so \ - $(SYSROOT_LIB)/libwasi-emulated-mman.so \ - $(SYSROOT_LIB)/libwasi-emulated-process-clocks.so \ - $(SYSROOT_LIB)/libwasi-emulated-getpid.so \ - $(SYSROOT_LIB)/libwasi-emulated-signal.so \ - $(SYSROOT_LIB)/libdl.so -ifeq ($(BUILD_LIBSETJMP),yes) -LIBC_SO += \ - $(SYSROOT_LIB)/libsetjmp.so -endif -endif - -libc_so: $(INCLUDE_DIRS) $(LIBC_SO) - -STATIC_LIBS = \ - $(SYSROOT_LIB)/libc.a \ - $(SYSROOT_LIB)/libc-printscan-long-double.a \ - $(SYSROOT_LIB)/libc-printscan-no-floating-point.a \ - $(SYSROOT_LIB)/libwasi-emulated-mman.a \ - $(SYSROOT_LIB)/libwasi-emulated-process-clocks.a \ - $(SYSROOT_LIB)/libwasi-emulated-getpid.a \ - $(SYSROOT_LIB)/libwasi-emulated-signal.a \ - $(SYSROOT_LIB)/libdl.a -ifeq ($(BUILD_LIBSETJMP),yes) -STATIC_LIBS += \ - $(SYSROOT_LIB)/libsetjmp.a -endif - -libc: $(INCLUDE_DIRS) $(STATIC_LIBS) builtins - -DUMMY := m rt pthread crypt util xnet resolv -DUMMY_LIBS := $(patsubst %,$(SYSROOT_LIB)/lib%.a,$(DUMMY)) -$(DUMMY_LIBS): - # - # Create empty placeholder libraries. - # - mkdir -p "$(SYSROOT_LIB)" - for lib in $@; do \ - $(AR) $(ARFLAGS) "$$lib"; \ - done - -no-check-symbols: $(STARTUP_FILES) libc $(DUMMY_LIBS) - # - # The build succeeded! The generated sysroot is in $(SYSROOT). - # - -finish: no-check-symbols - -ifeq ($(CHECK_SYMBOLS),yes) -finish: check-symbols -endif - -install: finish - mkdir -p "$(INSTALL_DIR)" - cp -p -r "$(SYSROOT)/lib" "$(SYSROOT)/share" "$(SYSROOT)/include" "$(INSTALL_DIR)" - -DEFINED_SYMBOLS = $(SYSROOT_SHARE)/defined-symbols.txt -UNDEFINED_SYMBOLS = $(SYSROOT_SHARE)/undefined-symbols.txt - -ifeq ($(WASI_SNAPSHOT),p2) -EXPECTED_TARGET_DIR = expected/wasm32-wasip2 -else -ifeq ($(THREAD_MODEL),posix) -EXPECTED_TARGET_DIR = expected/wasm32-wasip1-threads -else -EXPECTED_TARGET_DIR = expected/wasm32-wasip1 -endif -endif - - -check-symbols: $(STARTUP_FILES) libc - # - # Collect metadata on the sysroot and perform sanity checks. - # - mkdir -p "$(SYSROOT_SHARE)" - - # - # Collect symbol information. - # - @# TODO: Use llvm-nm --extern-only instead of grep. This is blocked on - @# LLVM PR40497, which is fixed in 9.0, but not in 8.0. - @# Ignore certain llvm builtin symbols such as those starting with __mul - @# since these dependencies can vary between llvm versions. - "$(NM)" --defined-only "$(SYSROOT_LIB)"/libc.a "$(SYSROOT_LIB)"/libwasi-emulated-*.a "$(SYSROOT_LIB)"/*.o \ - |grep ' [[:upper:]] ' |sed 's/.* [[:upper:]] //' |LC_ALL=C sort |uniq > "$(DEFINED_SYMBOLS)" - for undef_sym in $$("$(NM)" --undefined-only "$(SYSROOT_LIB)"/libc.a "$(SYSROOT_LIB)"/libc-*.a "$(SYSROOT_LIB)"/*.o \ - |grep ' U ' |sed 's/.* U //' |LC_ALL=C sort |uniq); do \ - grep -q '\<'$$undef_sym'\>' "$(DEFINED_SYMBOLS)" || echo $$undef_sym; \ - done | grep -E -v "^__mul|__memory_base|__indirect_function_table|__tls_base" > "$(UNDEFINED_SYMBOLS)" -ifneq ($(WASI_SNAPSHOT), p2) - grep '^_*imported_wasi_' "$(UNDEFINED_SYMBOLS)" \ - > "$(SYSROOT_LIB)/libc.imports" -endif - - # - # Generate a test file that includes all public C header files. - # - # setjmp.h is excluded because it requires a different compiler option - # - cd "$(SYSROOT_INC)" && \ - for header in $$(find . -type f -not -name mman.h -not -name signal.h -not -name times.h -not -name resource.h -not -name setjmp.h $(INCLUDE_ALL_CLAUSES) |grep -v /bits/ |grep -v /c++/); do \ - echo '#include <'$$header'>' | sed 's/\.\///' ; \ - done |LC_ALL=C sort >$(SYSROOT_SHARE)/include-all.c ; \ - cd - >/dev/null - - # - # Test that it compiles. - # - $(CC) $(CFLAGS) -fsyntax-only "$(SYSROOT_SHARE)/include-all.c" -Wno-\#warnings - - # - # Collect all the predefined macros, except for compiler version macros - # which we don't need to track here. - # - @# - @# For the __*_ATOMIC_*_LOCK_FREE macros, squash individual compiler names - @# to attempt, toward keeping these files compiler-independent. - @# - @# We have to add `-isystem $(SYSROOT_INC)` because otherwise clang puts - @# its builtin include path first, which produces compiler-specific - @# output. - @# - @# TODO: Filter out __NO_MATH_ERRNO_ and a few __*WIDTH__ that are new to clang 14. - @# TODO: Filter out __GCC_HAVE_SYNC_COMPARE_AND_SWAP_* that are new to clang 16. - @# TODO: Filter out __FPCLASS_* that are new to clang 17. - @# TODO: Filter out __FLT128_* that are new to clang 18. - @# TODO: Filter out __MEMORY_SCOPE_* that are new to clang 18. - @# TODO: Filter out __GCC_(CON|DE)STRUCTIVE_SIZE that are new to clang 19. - @# TODO: Filter out __STDC_EMBED_* that are new to clang 19. - @# TODO: Filter out __*_NORM_MAX__ that are new to clang 19. - @# TODO: Filter out __INT*_C() that are new to clang 20. - @# TODO: clang defined __FLT_EVAL_METHOD__ until clang 15, so we force-undefine it - @# for older versions. - @# TODO: Undefine __wasm_mutable_globals__ and __wasm_sign_ext__, that are new to - @# clang 16 for -mcpu=generic. - @# TODO: Undefine __wasm_multivalue__ and __wasm_reference_types__, that are new to - @# clang 19 for -mcpu=generic. - @# TODO: Undefine __wasm_nontrapping_fptoint__, __wasm_bulk_memory__ and - @# __wasm_bulk_memory_opt__, that are new to clang 20. - @# TODO: As of clang 16, __GNUC_VA_LIST is #defined without a value. - $(CC) $(CFLAGS) "$(SYSROOT_SHARE)/include-all.c" \ - -isystem $(SYSROOT_INC) \ - -std=gnu17 \ - -E -dM -Wno-\#warnings \ - -D_ALL_SOURCE \ - -U__llvm__ \ - -U__clang__ \ - -U__clang_major__ \ - -U__clang_minor__ \ - -U__clang_patchlevel__ \ - -U__clang_version__ \ - -U__clang_literal_encoding__ \ - -U__clang_wide_literal_encoding__ \ - -U__wasm_extended_const__ \ - -U__wasm_mutable_globals__ \ - -U__wasm_sign_ext__ \ - -U__wasm_multivalue__ \ - -U__wasm_reference_types__ \ - -U__wasm_nontrapping_fptoint__ \ - $(if $(filter-out expected/wasm32-wasip1-threads,$(EXPECTED_TARGET_DIR)),-U__wasm_bulk_memory__) \ - -U__wasm_bulk_memory_opt__ \ - -U__GNUC__ \ - -U__GNUC_MINOR__ \ - -U__GNUC_PATCHLEVEL__ \ - -U__VERSION__ \ - -U__NO_MATH_ERRNO__ \ - -U__BITINT_MAXWIDTH__ \ - -U__FLT_EVAL_METHOD__ -Wno-builtin-macro-redefined \ - | sed -e 's/__[[:upper:][:digit:]]*_ATOMIC_\([[:upper:][:digit:]_]*\)_LOCK_FREE/__compiler_ATOMIC_\1_LOCK_FREE/' \ - | sed -e 's/__GNUC_VA_LIST $$/__GNUC_VA_LIST 1/' \ - | grep -v '^#define __\(BOOL\|INT_\(LEAST\|FAST\)\(8\|16\|32\|64\)\|INT\|LONG\|LLONG\|SHRT\)_WIDTH__' \ - | grep -v '^#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_\(1\|2\|4\|8\)' \ - | grep -v '^#define __FPCLASS_' \ - | grep -v '^#define __FLT128_' \ - | grep -v '^#define __MEMORY_SCOPE_' \ - | grep -v '^#define __GCC_\(CON\|DE\)STRUCTIVE_SIZE' \ - | grep -v '^#define __STDC_EMBED_' \ - | grep -v '^#define __\(DBL\|FLT\|LDBL\)_NORM_MAX__' \ - | grep -v '^#define NDEBUG' \ - | grep -v '^#define __OPTIMIZE__' \ - | grep -v '^#define assert' \ - | grep -v '^#define __NO_INLINE__' \ - | grep -v '^#define __U\?INT.*_C(' \ - > "$(SYSROOT_SHARE)/predefined-macros.txt" - - # Check that the computed metadata matches the expected metadata. - # This ignores whitespace because on Windows the output has CRLF line endings. - diff -wur "$(EXPECTED_TARGET_DIR)" "$(SYSROOT_SHARE)" - - -##### BINDINGS ################################################################# -# The `bindings` target retrieves the necessary WIT files for the wasi-cli world -# and generates a header file used by the wasip2 target. -################################################################################ - -# The directory where we store files and tools for generating WASIp2 bindings -BINDING_WORK_DIR ?= build/bindings -# URL from which to retrieve the WIT files used to generate the WASIp2 bindings -WASI_CLI_URL ?= https://github.com/WebAssembly/wasi-cli/archive/refs/tags/v0.2.0.tar.gz -# URL from which to retrieve the `wit-bindgen` command used to generate the -# WASIp2 bindings. -WIT_BINDGEN_URL ?= https://github.com/bytecodealliance/wit-bindgen/releases/download/v0.48.0/wit-bindgen-0.48.0-x86_64-linux.tar.gz - -$(BINDING_WORK_DIR)/wasi-cli: - mkdir -p "$(BINDING_WORK_DIR)" - cd "$(BINDING_WORK_DIR)" && \ - curl -L "$(WASI_CLI_URL)" -o wasi-cli.tar.gz && \ - tar xf wasi-cli.tar.gz && \ - mv wasi-cli-* wasi-cli - -$(BINDING_WORK_DIR)/wit-bindgen: - mkdir -p "$(BINDING_WORK_DIR)" - cd "$(BINDING_WORK_DIR)" && \ - curl -L "$(WIT_BINDGEN_URL)" -o wit-bindgen.tar.gz && \ - tar xf wit-bindgen.tar.gz && \ - mv wit-bindgen-* wit-bindgen - -bindings: $(BINDING_WORK_DIR)/wasi-cli $(BINDING_WORK_DIR)/wit-bindgen - cd "$(BINDING_WORK_DIR)" && \ - ./wit-bindgen/wit-bindgen c \ - --autodrop-borrows yes \ - --rename-world wasip2 \ - --type-section-suffix __wasi_libc \ - --world wasi:cli/imports@0.2.0 \ - --rename wasi:clocks/monotonic-clock@0.2.0=monotonic_clock \ - --rename wasi:clocks/wall-clock@0.2.0=wall_clock \ - --rename wasi:filesystem/preopens@0.2.0=filesystem_preopens \ - --rename wasi:filesystem/types@0.2.0=filesystem \ - --rename wasi:io/error@0.2.0=io_error \ - --rename wasi:io/poll@0.2.0=poll \ - --rename wasi:io/streams@0.2.0=streams \ - --rename wasi:random/insecure-seed@0.2.0=random_insecure_seed \ - --rename wasi:random/insecure@0.2.0=random_insecure \ - --rename wasi:random/random@0.2.0=random \ - --rename wasi:sockets/instance-network@0.2.0=instance_network \ - --rename wasi:sockets/ip-name-lookup@0.2.0=ip_name_lookup \ - --rename wasi:sockets/network@0.2.0=network \ - --rename wasi:sockets/tcp-create-socket@0.2.0=tcp_create_socket \ - --rename wasi:sockets/tcp@0.2.0=tcp \ - --rename wasi:sockets/udp-create-socket@0.2.0=udp_create_socket \ - --rename wasi:sockets/udp@0.2.0=udp \ - --rename wasi:cli/environment@0.2.0=environment \ - --rename wasi:cli/exit@0.2.0=exit \ - --rename wasi:cli/stdin@0.2.0=stdin \ - --rename wasi:cli/stdout@0.2.0=stdout \ - --rename wasi:cli/stderr@0.2.0=stderr \ - --rename wasi:cli/terminal-input@0.2.0=terminal_input \ - --rename wasi:cli/terminal-output@0.2.0=terminal_output \ - --rename wasi:cli/terminal-stdin@0.2.0=terminal_stdin \ - --rename wasi:cli/terminal-stdout@0.2.0=terminal_stdout \ - --rename wasi:cli/terminal-stderr@0.2.0=terminal_stderr \ - ./wasi-cli/wit && \ - mv wasip2.h ../../libc-bottom-half/headers/public/wasi/ && \ - mv wasip2_component_type.o ../../libc-bottom-half/sources && \ - sed 's_#include "wasip2\.h"_#include "wasi/wasip2.h"_' \ - < wasip2.c \ - > ../../libc-bottom-half/sources/wasip2.c && \ - rm wasip2.c - sed -i 's/extern void exit_exit/_Noreturn extern void exit_exit/' libc-bottom-half/headers/public/wasi/wasip2.h - sed -i 's/extern void __wasm_import_exit_exit/_Noreturn extern void __wasm_import_exit_exit/' libc-bottom-half/sources/wasip2.c - - -clean: - $(RM) -r "$(BINDING_WORK_DIR)" - $(RM) -r "$(OBJDIR)" - $(RM) -r "$(SYSROOT)" - -.PHONY: default libc libc_so finish install clean check-symbols no-check-symbols bindings startup_files diff --git a/README.md b/README.md index 89c4eef06..e7ea7da34 100644 --- a/README.md +++ b/README.md @@ -21,18 +21,49 @@ build of `wasi-libc` in its sysroot. To build a WASI sysroot from source, obtain a WebAssembly-supporting C compiler (currently this is only clang 10+, though we'd like to support other compilers -as well), and then run: +as well). The build is configured with: ```sh -make CC=/path/to/clang/with/wasm/support \ - AR=/path/to/llvm-ar \ - NM=/path/to/llvm-nm +cmake -S . -B build ``` -This makes a directory called "sysroot" by default. See the top of the Makefile -for customization options. +You can configure the build system with the `-G` argument to `cmake`, for +example `-G Ninja`, to build with a different build system instead. + +Supported options to the configuration step are: + +* `-DCMAKE_C_COMPILER=clang` - specify a C compiler to use. +* `-DCMAKE_AR=llvm-ar` - specify a specific `ar` program to use. +* `-DCMAKE_INSTALL_PREFIX=path` - where to install the sysroot. +* `-DTARGET_TRIPLE=...` - which target to build: for example `wasm32-wasip1`, + `wasm32-wasip2`, `wasm32-wasip1-threads`, ... +* `-DMALLOC=...` - one of `dlmalloc`, `emmalloc`, or `none`. +* `-DBUILTINS_LIB=...` - optional path to compiler-rt which, if not present, + will be downloaded automatically. +* `-DBULK_MEMORY_THRESHOLD=...` - used to tune bulk-memory-related copying + functions. +* `-DSETJMP=(ON|OFF)` - whether or not to build libsetjmp.{a,so} +* `-DBUILD_TESTS=(ON|OFF)` - whether or not to build tests +* `-DSIMD=(ON|OFF)` - whether or not to enable simd-related string routines +* `-DBUILD_SHARED=(ON|OFF)` - forcibly enable or disable building shared + libraries. + +After the build is configured you can use the generated build system to build +wasi-libc. For example. -To use the sysroot, use the `--sysroot=` option: +```sh +cd build && make -j$(nproc) +``` + +This can then be installed using the `install` target of your build system. For +example: + +```sh +cd build && make install +``` + +This will install to the directory specified by `-DCMAKE_INSTALL_PREFIX=...`. +This path can then be used as a sysroot for C: ```sh /path/to/wasm/supporting/c/compiler --sysroot=/path/to/the/newly/built/sysroot ... @@ -50,22 +81,22 @@ libraries, notably `libclang_rt.builtins-wasm32.a`, by default. This is one of the things [wasi-sdk] simplifies, as it includes cross-compiled builds of compiler-rt, `libc++.a`, and `libc++abi.a`. -The build of wasi-libc itself may depend on compiler-rt, or +The build of wasi-libc itself depends on compiler-rt, or `libclang_rt.builtins-wasm32.a`. This manifests in error messages such as `undefined symbol: __muloti4` for example. Specifically the PIC build of wasi-libc will require that Clang can locate `libclang_rt.builtins-wasm32.a`, -meaning that `libc.so` requires this library to be present. To handle this the -default behavior of the build system is to download the latest version of -compiler-rt from [wasi-sdk] and use that for the build of `libc.so`. You can -also set `BUILTINS_LIB` as a path to `libclang_rt.builtins-wasm32.a` as well to -use that instead of downloading a version. +meaning that `libc.so` requires this library to be present. This library is +downloaded automatically as part of the build but it can also be manually +specified with `-DBUILTINS_LIB=...`. ## Building in pthread support -To enable pthreads support via the [wasi-threads] proposal, follow the above -build directions with one addition: `make ... THREAD_MODEL=posix`. This creates -additional artifacts in `sysroot/lib/wasm32-wasi-threads` to support `--target -wasm32-wasi-threads`. +The `wasm32-wasip1` and `wasm32-wasip2` targets have pthread-related symbols, +but they all return an error. For example spawning a thread will return an +error. Only the `wasm32-wasip1-threads` target supports spawning a thread. Note +that threading support is experimental at this time and only very lightly +tested. Much of libc needs to be modified to be threadsafe and this transition +is not fully complete. ## Arch Linux AUR package diff --git a/cmake/Platform/WASI.cmake b/cmake/Platform/WASI.cmake new file mode 100644 index 000000000..b49713f1b --- /dev/null +++ b/cmake/Platform/WASI.cmake @@ -0,0 +1 @@ +set(WASI 1) diff --git a/cmake/ba-download.cmake b/cmake/ba-download.cmake new file mode 100644 index 000000000..a5726e516 --- /dev/null +++ b/cmake/ba-download.cmake @@ -0,0 +1,48 @@ +include(ExternalProject) + +function(ba_download target repo version) + if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(arch "x86_64") + elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") + set(arch "aarch64") + elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(arch "aarch64") + elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64") + set(arch "x86_64") + else() + message(FATAL_ERROR "Unsupported architecture ${CMAKE_HOST_SYSTEM_PROCESSOR} for ${target}") + endif() + + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(os macos) + elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(os linux) + elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(os windows) + else() + message(FATAL_ERROR "Unsupported system ${CMAKE_HOST_SYSTEM_NAME} for ${target}") + endif() + + if (target STREQUAL wasmtime) + set(fmt xz) + else() + set(fmt gz) + endif() + + if (target STREQUAL wit-bindgen) + set(tag v${version}) + else() + set(tag ${version}) + endif() + + message(STATUS "Using ${target} ${version} for ${arch}-${os} from ${repo}") + + ExternalProject_Add( + ${target} + EXCLUDE_FROM_ALL ON + URL "${repo}/releases/download/${tag}/${target}-${version}-${arch}-${os}.tar.${fmt}" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) +endfunction() diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake new file mode 100644 index 000000000..e181e22c6 --- /dev/null +++ b/cmake/bindings.cmake @@ -0,0 +1,66 @@ +include(ba-download) + +ba_download( + wit-bindgen + "https://github.com/bytecodealliance/wit-bindgen" + "0.48.0" +) +ExternalProject_Get_Property(wit-bindgen SOURCE_DIR) +set(wit_bindgen "${SOURCE_DIR}/wit-bindgen") + +ExternalProject_Add( + wasi-wits + URL https://github.com/WebAssembly/wasi-cli/archive/refs/tags/v0.2.0.tar.gz + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + EXCLUDE_FROM_ALL TRUE +) +ExternalProject_Get_Property(wasi-wits SOURCE_DIR) +set(wit_dir ${SOURCE_DIR}/wit) +set(bottom_half "${CMAKE_SOURCE_DIR}/libc-bottom-half") + +add_custom_target( + bindings + COMMAND + ${wit_bindgen} c + --autodrop-borrows yes + --rename-world wasip2 + --type-section-suffix __wasi_libc + --world wasi:cli/imports@0.2.0 + --rename wasi:clocks/monotonic-clock@0.2.0=monotonic_clock + --rename wasi:clocks/wall-clock@0.2.0=wall_clock + --rename wasi:filesystem/preopens@0.2.0=filesystem_preopens + --rename wasi:filesystem/types@0.2.0=filesystem + --rename wasi:io/error@0.2.0=io_error + --rename wasi:io/poll@0.2.0=poll + --rename wasi:io/streams@0.2.0=streams + --rename wasi:random/insecure-seed@0.2.0=random_insecure_seed + --rename wasi:random/insecure@0.2.0=random_insecure + --rename wasi:random/random@0.2.0=random + --rename wasi:sockets/instance-network@0.2.0=instance_network + --rename wasi:sockets/ip-name-lookup@0.2.0=ip_name_lookup + --rename wasi:sockets/network@0.2.0=network + --rename wasi:sockets/tcp-create-socket@0.2.0=tcp_create_socket + --rename wasi:sockets/tcp@0.2.0=tcp + --rename wasi:sockets/udp-create-socket@0.2.0=udp_create_socket + --rename wasi:sockets/udp@0.2.0=udp + --rename wasi:cli/environment@0.2.0=environment + --rename wasi:cli/exit@0.2.0=exit + --rename wasi:cli/stdin@0.2.0=stdin + --rename wasi:cli/stdout@0.2.0=stdout + --rename wasi:cli/stderr@0.2.0=stderr + --rename wasi:cli/terminal-input@0.2.0=terminal_input + --rename wasi:cli/terminal-output@0.2.0=terminal_output + --rename wasi:cli/terminal-stdin@0.2.0=terminal_stdin + --rename wasi:cli/terminal-stdout@0.2.0=terminal_stdout + --rename wasi:cli/terminal-stderr@0.2.0=terminal_stderr + ${wit_dir} + COMMAND cmake -E copy wasip2.h ${bottom_half}/headers/public/wasi/ + COMMAND cmake -E copy wasip2_component_type.o ${bottom_half}/sources + COMMAND cmake -E copy wasip2.c ${bottom_half}/sources + COMMAND sed -i "'s_#include .wasip2\.h._#include \"wasi/wasip2.h\"_'" ${bottom_half}/sources/wasip2.c + COMMAND sed -i "s/extern void exit_exit/_Noreturn extern void exit_exit/" ${bottom_half}/headers/public/wasi/wasip2.h + COMMAND sed -i "s/extern void __wasm_import_exit_exit/_Noreturn extern void __wasm_import_exit_exit/" ${bottom_half}/sources/wasip2.c + DEPENDS wit-bindgen wasi-wits +) diff --git a/cmake/builtins.cmake b/cmake/builtins.cmake new file mode 100644 index 000000000..45b861f38 --- /dev/null +++ b/cmake/builtins.cmake @@ -0,0 +1,67 @@ +# +# Figure out what to do about compiler-rt. +# +# The compiler-rt library is not built here in the wasi-libc repository, but it +# is required to link artifacts. Notably `libc.so` and test and such all require +# it to exist. Currently the ways this is handled are: +# +# * If `BUILTINS_LIB` is defined at build time then that's assumed to be a path +# to the libcompiler-rt.a. That's then ingested into the build here and copied +# around to special locations to get the `*.so` rules below to work (see docs +# there). +# +# * If `BUILTINS_LIB` is not defined then a known-good copy is downloaded from +# wasi-sdk CI and used instead. +# +# In the future this may also want some form of configuration to support +# assuming the system compiler has a compiler-rt, e.g. if $(SYSTEM_BUILTINS_LIB) +# exists that should be used instead. +get_property(directory_cflags DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS) +execute_process( + COMMAND ${CMAKE_C_COMPILER} --target=${TARGET_TRIPLE} --print-libgcc-file-name + OUTPUT_VARIABLE system_builtins_lib + OUTPUT_STRIP_TRAILING_WHITESPACE +) +execute_process( + COMMAND ${CMAKE_C_COMPILER} --target=${TARGET_TRIPLE} -print-resource-dir + OUTPUT_VARIABLE system_resource_dir + OUTPUT_STRIP_TRAILING_WHITESPACE +) +cmake_path( + RELATIVE_PATH system_builtins_lib + BASE_DIRECTORY ${system_resource_dir} + OUTPUT_VARIABLE builtins_lib_rel_1 +) + + +set(tmp_resource_dir ${CMAKE_BINARY_DIR}/temp-resource-dir) +set(builtins_lib_path ${tmp_resource_dir}/${builtins_lib_rel_1}) +cmake_path(GET builtins_lib_path PARENT_PATH builtins_lib_dir) + +if(BUILTINS_LIB) + message(STATUS "Using builtins lib: ${BUILTINS_LIB}") + add_custom_command( + OUTPUT ${builtins_lib_path} + COMMAND ${CMAKE_COMMAND} -E copy ${BUILTINS_LIB} ${builtins_lib_path} + DEPENDS ${BUILTINS_LIB} + ) +else() + message(STATUS "Using historical builtins lib from wasi-sdk...") + include(ExternalProject) + ExternalProject_Add( + wasi-sdk-builtins + EXCLUDE_FROM_ALL ON + URL https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/libclang_rt.builtins-wasm32-wasi-25.0.tar.gz + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + ExternalProject_Get_Property(wasi-sdk-builtins SOURCE_DIR) + set(src ${SOURCE_DIR}/libclang_rt.builtins-wasm32.a) + add_custom_command( + OUTPUT ${builtins_lib_path} + COMMAND ${CMAKE_COMMAND} -E copy ${src} ${builtins_lib_path} + DEPENDS wasi-sdk-builtins + ) +endif() +add_custom_target(builtins DEPENDS ${builtins_lib_path}) diff --git a/cmake/check-symbols.cmake b/cmake/check-symbols.cmake new file mode 100644 index 000000000..e472f8adc --- /dev/null +++ b/cmake/check-symbols.cmake @@ -0,0 +1,53 @@ +set(SYSROOT_SHARE ${SYSROOT}/share/${TARGET_TRIPLE}) +set(undefined_symbols ${SYSROOT_SHARE}/undefined-symbols.txt) +set(defined_symbols ${SYSROOT_SHARE}/defined-symbols.txt) +set(include_all ${SYSROOT_SHARE}/include-all.c) + +add_custom_command( + OUTPUT + ${defined_symbols} + ${undefined_symbols} + ${include_all} + COMMAND + ${CMAKE_COMMAND} + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_C_FLAGS="$" + -DSYSROOT_LIB=${SYSROOT_LIB} + -DSYSROOT_INC=${SYSROOT_INC} + -DCMAKE_NM=${CMAKE_NM} + -DOUT_DIR=${SYSROOT_SHARE} + -P ${CMAKE_CURRENT_LIST_DIR}/scripts/run-check-symbols.cmake + DEPENDS + sysroot + ${CMAKE_CURRENT_LIST_DIR}/scripts/run-check-symbols.cmake +) + +if(THREADS) + set(expected "${CMAKE_SOURCE_DIR}/expected/wasm32-wasip1-threads") +elseif(WASI STREQUAL "p1") + set(expected "${CMAKE_SOURCE_DIR}/expected/wasm32-wasip1") +elseif(WASI STREQUAL "p2") + set(expected "${CMAKE_SOURCE_DIR}/expected/wasm32-wasip2") +else() + message(FATAL_ERROR "Unknown WASI version: ${WASI}") +endif() + + +add_custom_target( + check-symbols + COMMAND + diff -wur ${expected} ${SYSROOT_SHARE} + DEPENDS ${defined_symbols} ${undefined_symbols} +) + +if(CHECK_SYMBOLS) + set_target_properties(check-symbols PROPERTIES EXCLUDE_FROM_ALL FALSE) +endif() + +# Helper target to auto-update the expectations of symbols +add_custom_target( + update-symbols + COMMAND + cp -r ${SYSROOT_SHARE}/* ${expected}/ + DEPENDS ${defined_symbols} ${undefined_symbols} +) diff --git a/cmake/scripts/run-check-symbols.cmake b/cmake/scripts/run-check-symbols.cmake new file mode 100644 index 000000000..f44cc149f --- /dev/null +++ b/cmake/scripts/run-check-symbols.cmake @@ -0,0 +1,178 @@ +# A CMake-based script to populate files in `share/*` related to +# defined/undefined symbols/macros. +# +# You might rightfully recoil a bit to see such a meaty script written in CMake. +# Given the choice of using shell, which isn't portable, or something like +# Python, which would only be used for this, I opted to go with CMake. Unsure +# if that was a good idea but it's at least all here and hopefully working well +# enough. If you need to edit this it's probably gonna be at the bottom related +# to filtering out macros and such. + +file(GLOB objects ${SYSROOT_LIB}/*.[ao]) + +# =========================================== +# Generate defined-symbols.txt and undefined-symbols.txt + +set(defined_symbols) +set(undefined_symbols) + +foreach(file ${objects}) + if (file MATCHES "lib(setjmp|dl).a$") + continue() + endif() + # TODO: Use llvm-nm --extern-only instead of grep. This is blocked on + # LLVM PR40497, which is fixed in 9.0, but not in 8.0. + execute_process( + COMMAND ${CMAKE_NM} --defined-only ${file} + OUTPUT_VARIABLE nm_output + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY + ) + string(REPLACE "\n" ";" nm_lines "${nm_output}") + list(APPEND defined_symbols ${nm_lines}) + + execute_process( + COMMAND ${CMAKE_NM} --undefined-only ${file} + OUTPUT_VARIABLE nm_output + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY + ) + string(REPLACE "\n" ";" nm_lines "${nm_output}") + list(APPEND undefined_symbols ${nm_lines}) +endforeach() + +# Filter/transform/sort `defined_symbols` into `final_defined_symbols`. +list(FILTER defined_symbols INCLUDE REGEX " [A-Z] ") +foreach(line IN LISTS defined_symbols) + string(REGEX REPLACE ".* [A-Z] " "" symbol "${line}") + list(APPEND final_defined_symbols ${symbol}) +endforeach() +list(SORT final_defined_symbols) +list(REMOVE_DUPLICATES final_defined_symbols) + + +# Filter/transform/sort `undefined_symbols` into `final_undefined_symbols`. +list(FILTER undefined_symbols INCLUDE REGEX " U ") +foreach(line IN LISTS undefined_symbols) + string(REGEX REPLACE ".* U " "" symbol "${line}") + list(APPEND final_undefined_symbols ${symbol}) +endforeach() +list(SORT final_undefined_symbols) +list(REMOVE_DUPLICATES final_undefined_symbols) + +# Write out `defined-symbos.txt` with all our symbols. +set(out_defined_symbols ${OUT_DIR}/defined-symbols.txt) +string(JOIN "\n" defined_symbols_content ${final_defined_symbols}) +file(WRITE ${out_defined_symbols} "${defined_symbols_content}") + +# Write out `undefined-symbosl.txt`, but skip some symbols. +set(out_undefined_symbols ${OUT_DIR}/undefined-symbols.txt) +file(WRITE ${out_undefined_symbols} "") +foreach(symbol IN LISTS final_undefined_symbols) + list(FIND final_defined_symbols "${symbol}" found_index) + if(NOT(found_index EQUAL -1)) + continue() + endif() + # Ignore certain llvm builtin symbols such as those starting with __mul + # since these dependencies can vary between llvm versions. + if(NOT symbol MATCHES "^__mul" AND + NOT symbol STREQUAL "__memory_base" AND + NOT symbol STREQUAL "__indirect_function_table" AND + NOT symbol STREQUAL "__tls_base") + file(APPEND ${out_undefined_symbols} "${symbol}\n") + endif() +endforeach() + +# =========================================== +# Generate include-all.c + +file(GLOB_RECURSE headers RELATIVE ${SYSROOT_INC} ${SYSROOT_INC}/*.h) +set(out_include_all ${OUT_DIR}/include-all.c) +file(WRITE ${out_include_all} "") +foreach(header IN LISTS headers) + if(header MATCHES bits/ OR + header MATCHES /c\\+\\+/ OR + # setjmp.h is excluded because it requires a different compiler option + header MATCHES "^(setjmp|signal).h$" OR + # Ignore some headers that require extra options for example. + header MATCHES "/(mman|times|signal|resource|descriptor_table).h$") + continue() + endif() + file(APPEND ${out_include_all} "#include <${header}>\n") +endforeach() + +# =========================================== +# Generate predefined-macros.txt + +set(out_predefined_macros ${OUT_DIR}/predefined-macros.txt) +execute_process( + COMMAND + ${CMAKE_C_COMPILER} + ${CMAKE_C_FLAGS} + ${out_include_all} + -isystem ${SYSROOT_INC} + -std=gnu17 + -E -dM + -D_ALL_SOURCE + # Skip compiler version macros + -U__llvm__ + -U__clang__ + -U__clang_major__ + -U__clang_minor__ + -U__clang_patchlevel__ + -U__clang_version__ + -U__clang_literal_encoding__ + -U__clang_wide_literal_encoding__ + # Skip macros related to wasm features being on or off + -U__wasm_extended_const__ + -U__wasm_mutable_globals__ + -U__wasm_sign_ext__ + -U__wasm_multivalue__ + -U__wasm_reference_types__ + -U__wasm_nontrapping_fptoint__ + -U__wasm_bulk_memory__ + -U__wasm_bulk_memory_opt__ + # Skip some other macros that vary between compiler versions + -U__GNUC__ + -U__GNUC_MINOR__ + -U__GNUC_PATCHLEVEL__ + -U__VERSION__ + -U__NO_MATH_ERRNO__ + -U__BITINT_MAXWIDTH__ + -U__FLT_EVAL_METHOD__ + "-Wno-#warnings" + -Wno-builtin-macro-redefined + OUTPUT_FILE ${out_predefined_macros} + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY +) +file(STRINGS ${out_predefined_macros} predefined_macro_lines) +file(WRITE ${out_predefined_macros} "") +foreach(line IN LISTS predefined_macro_lines) + # Try to normalize some macros + if(line MATCHES "__[A-Z0-9]*_ATOMIC_[A-Z0-9_]*_LOCK_FREE") + string(REGEX REPLACE "__[A-Z0-9]*_ATOMIC_([A-Z0-9_]*)_LOCK_FREE" "__compiler_ATOMIC_\\1_LOCK_FREE" line "${line}") + endif() + if(line MATCHES "^#define __GNUC_VA_LIST $") + string(REPLACE "__GNUC_VA_LIST " "__GNUC_VA_LIST 1" line "${line}") + endif() + + # Skip a whole bunch of other macros that vary between compilers + if(line MATCHES "^#define __(BOOL|INT_(LEAST|FAST)(8|16|32|64)|INT|LONG|LLONG|SHRT)_WIDTH__" + OR line MATCHES "^#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_(1|2|4|8)" + OR line MATCHES "^#define __FPCLASS_" + OR line MATCHES "^#define __FLT128_" + OR line MATCHES "^#define __MEMORY_SCOPE_" + OR line MATCHES "^#define __GCC_(CON|DE)STRUCTIVE_SIZE" + OR line MATCHES "^#define __STDC_EMBED_" + OR line MATCHES "^#define __(DBL|FLT|LDBL)_NORM_MAX__" + OR line MATCHES "^#define NDEBUG" + OR line MATCHES "^#define __OPTIMIZE__" + OR line MATCHES "^#define assert" + OR line MATCHES "^#define __NO_INLINE__" + OR line MATCHES "^#define __U?INT.*_C\\(" + ) + continue() + endif() + file(APPEND ${out_predefined_macros} "${line}\n") +endforeach() diff --git a/cmake/wasm-component-ld.cmake b/cmake/wasm-component-ld.cmake new file mode 100644 index 000000000..7d8b711ae --- /dev/null +++ b/cmake/wasm-component-ld.cmake @@ -0,0 +1,14 @@ +find_program(WASM_COMPONENT_LD_EXECUTABLE NAMES wasm-component-ld) +include(ba-download) + +if (NOT WASM_COMPONENT_LD_EXECUTABLE) + ba_download( + wasm-component-ld + "https://github.com/bytecodealliance/wasm-component-ld" + "v0.5.19" + ) + ExternalProject_Get_Property(wasm-component-ld SOURCE_DIR) + set(WASM_COMPONENT_LD_EXECUTABLE "${SOURCE_DIR}/wasm-component-ld") + add_link_options(-fuse-ld=${WASM_COMPONENT_LD_EXECUTABLE}) + add_dependencies(sysroot_inc wasm-component-ld) +endif() diff --git a/dlmalloc/CMakeLists.txt b/dlmalloc/CMakeLists.txt new file mode 100644 index 000000000..8e2516de8 --- /dev/null +++ b/dlmalloc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_object_library(dlmalloc src/dlmalloc.c) +foreach(obj dlmalloc-shared dlmalloc-static) + target_include_directories(${obj} PRIVATE include) +endforeach() diff --git a/emmalloc/CMakeLists.txt b/emmalloc/CMakeLists.txt new file mode 100644 index 000000000..b6fd9d969 --- /dev/null +++ b/emmalloc/CMakeLists.txt @@ -0,0 +1,8 @@ +add_object_library(emmalloc emmalloc.c) + +# emmalloc uses a lot of pointer type-punning, which is UB under strict +# aliasing, and this was found to have real miscompilations in wasi-libc#421. +foreach(obj emmalloc-shared emmalloc-static) + target_include_directories(${obj} PRIVATE emmalloc) + target_compile_options(${obj} PRIVATE -fno-strict-aliasing) +endforeach() diff --git a/expected/wasm32-wasip1-threads/predefined-macros.txt b/expected/wasm32-wasip1-threads/predefined-macros.txt index f691c853a..823ef8c93 100644 --- a/expected/wasm32-wasip1-threads/predefined-macros.txt +++ b/expected/wasm32-wasip1-threads/predefined-macros.txt @@ -3091,6 +3091,7 @@ #define __WASI_ROFLAGS_RECV_DATA_TRUNCATED ((__wasi_roflags_t)(1 << 0)) #define __WASI_SDFLAGS_RD ((__wasi_sdflags_t)(1 << 0)) #define __WASI_SDFLAGS_WR ((__wasi_sdflags_t)(1 << 1)) +#define __WASI_SNAPSHOT_H #define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME ((__wasi_subclockflags_t)(1 << 0)) #define __WASI_WHENCE_CUR (UINT8_C(1)) #define __WASI_WHENCE_END (UINT8_C(2)) @@ -3128,10 +3129,10 @@ #define __tg_real_remquo(x,y,z) (__RETCAST_2(x, y)( __FLT(x) && __FLT(y) ? remquof(x, y, z) : __LDBL((x)+(y)) ? remquol(x, y, z) : remquo(x, y, z) )) #define __tm_gmtoff tm_gmtoff #define __tm_zone tm_zone -#define __va_copy(d,s) __builtin_va_copy(d,s) +#define __va_copy(d,s) __builtin_va_copy(d, s) #define __wasi__ 1 #define __wasi_api_h -#define __wasi_libc_busywait_h +#define __wasi_libc_busywait_h #define __wasi_libc_environ_h #define __wasi_libc_find_relpath_h #define __wasi_libc_h @@ -3203,7 +3204,6 @@ #define __wasm32__ 1 #define __wasm__ 1 #define __wasm_atomics__ 1 -#define __wasm_bulk_memory__ 1 #define _tolower(a) ((a)|0x20) #define _toupper(a) ((a)&0x5f) #define acos(x) __tg_real_complex(acos, (x)) diff --git a/expected/wasm32-wasip1/predefined-macros.txt b/expected/wasm32-wasip1/predefined-macros.txt index 66f4c4c88..493b767eb 100644 --- a/expected/wasm32-wasip1/predefined-macros.txt +++ b/expected/wasm32-wasip1/predefined-macros.txt @@ -3088,6 +3088,7 @@ #define __WASI_ROFLAGS_RECV_DATA_TRUNCATED ((__wasi_roflags_t)(1 << 0)) #define __WASI_SDFLAGS_RD ((__wasi_sdflags_t)(1 << 0)) #define __WASI_SDFLAGS_WR ((__wasi_sdflags_t)(1 << 1)) +#define __WASI_SNAPSHOT_H #define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME ((__wasi_subclockflags_t)(1 << 0)) #define __WASI_WHENCE_CUR (UINT8_C(1)) #define __WASI_WHENCE_END (UINT8_C(2)) @@ -3128,7 +3129,7 @@ #define __va_copy(d,s) __builtin_va_copy(d, s) #define __wasi__ 1 #define __wasi_api_h -#define __wasi_libc_busywait_h +#define __wasi_libc_busywait_h #define __wasi_libc_environ_h #define __wasi_libc_find_relpath_h #define __wasi_libc_h diff --git a/expected/wasm32-wasip2/predefined-macros.txt b/expected/wasm32-wasip2/predefined-macros.txt index 1ae2e1fd2..912b5e0f5 100644 --- a/expected/wasm32-wasip2/predefined-macros.txt +++ b/expected/wasm32-wasip2/predefined-macros.txt @@ -3240,6 +3240,7 @@ #define __WASI_ROFLAGS_RECV_DATA_TRUNCATED ((__wasi_roflags_t)(1 << 0)) #define __WASI_SDFLAGS_RD ((__wasi_sdflags_t)(1 << 0)) #define __WASI_SDFLAGS_WR ((__wasi_sdflags_t)(1 << 1)) +#define __WASI_SNAPSHOT_H #define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME ((__wasi_subclockflags_t)(1 << 0)) #define __WASI_WHENCE_CUR (UINT8_C(1)) #define __WASI_WHENCE_END (UINT8_C(2)) @@ -3280,7 +3281,7 @@ #define __va_copy(d,s) __builtin_va_copy(d, s) #define __wasi__ 1 #define __wasi_api_h -#define __wasi_libc_busywait_h +#define __wasi_libc_busywait_h #define __wasi_libc_environ_h #define __wasi_libc_find_relpath_h #define __wasi_libc_h @@ -3347,7 +3348,7 @@ #define __wasilibc___typedef_suseconds_t_h #define __wasilibc___typedef_time_t_h #define __wasilibc___typedef_uid_t_h -#define __wasilibc_use_wasip2 1 +#define __wasilibc_use_wasip2 #define __wasm 1 #define __wasm32 1 #define __wasm32__ 1 diff --git a/fts/CMakeLists.txt b/fts/CMakeLists.txt new file mode 100644 index 000000000..987f5f46a --- /dev/null +++ b/fts/CMakeLists.txt @@ -0,0 +1,6 @@ +add_internal_object_library(fts musl-fts/fts.c) +foreach(obj fts-shared fts-static) + target_include_directories(${obj} PRIVATE . musl-fts) +endforeach() + +add_sysroot_header(musl-fts/fts.h fts.h) diff --git a/libc-bottom-half/CMakeLists.txt b/libc-bottom-half/CMakeLists.txt new file mode 100644 index 000000000..b3a891871 --- /dev/null +++ b/libc-bottom-half/CMakeLists.txt @@ -0,0 +1,213 @@ +add_subdirectory(clocks) +add_subdirectory(mman) +add_subdirectory(getpid) +add_subdirectory(signal) + +# ============================================================================= +# sysroot headers from the bottom half +# +configure_file(headers/public/__wasi_snapshot.h.in ${SYSROOT_INC}/__wasi_snapshot.h) +add_custom_target(sysroot-wasi-snapshot-header DEPENDS ${SYSROOT_INC}/__wasi_snapshot.h) +add_dependencies(sysroot_inc sysroot-wasi-snapshot-header) + +file( + GLOB_RECURSE globbed_headers + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + CONFIGURE_DEPENDS + headers/public/*.h +) + +# TODO: these headers are not actually installed in the sysroot since the +# musl-sourced ones are. These should probably be deleted from the source +# tree and the musl ones used instead. +list(REMOVE_ITEM globbed_headers + headers/public/dirent.h + headers/public/errno.h + headers/public/fcntl.h + headers/public/inttypes.h + headers/public/netinet/in.h + headers/public/poll.h + headers/public/stdlib.h + headers/public/string.h + headers/public/sys/ioctl.h + headers/public/sys/resource.h + headers/public/sys/select.h + headers/public/sys/socket.h + headers/public/sys/stat.h + headers/public/sys/time.h + headers/public/sys/times.h + headers/public/sys/types.h + headers/public/sys/uio.h + headers/public/sys/un.h + headers/public/time.h + headers/public/unistd.h + headers/public/wchar.h +) + +if (WASI STREQUAL "p1") + list(REMOVE_ITEM globbed_headers headers/public/wasi/wasip2.h) +endif() + +foreach(header ${globbed_headers}) + string(REPLACE "headers/public/" "" dst ${header}) + add_sysroot_header(${header} ${dst}) +endforeach() + +# ============================================================================= +# building bottom-half sources +# +set(bottom_half_sources + cloudlibc/src/libc/dirent/closedir.c + cloudlibc/src/libc/dirent/dirfd.c + cloudlibc/src/libc/dirent/fdclosedir.c + cloudlibc/src/libc/dirent/fdopendir.c + cloudlibc/src/libc/dirent/opendirat.c + cloudlibc/src/libc/dirent/readdir.c + cloudlibc/src/libc/dirent/rewinddir.c + cloudlibc/src/libc/dirent/scandirat.c + cloudlibc/src/libc/dirent/seekdir.c + cloudlibc/src/libc/dirent/telldir.c + cloudlibc/src/libc/errno/errno.c + cloudlibc/src/libc/fcntl/fcntl.c + cloudlibc/src/libc/fcntl/openat.c + cloudlibc/src/libc/fcntl/posix_fadvise.c + cloudlibc/src/libc/fcntl/posix_fallocate.c + cloudlibc/src/libc/poll/poll.c + cloudlibc/src/libc/sched/sched_yield.c + cloudlibc/src/libc/stdio/renameat.c + cloudlibc/src/libc/stdlib/_Exit.c + cloudlibc/src/libc/sys/ioctl/ioctl.c + cloudlibc/src/libc/sys/select/pselect.c + cloudlibc/src/libc/sys/select/select.c + cloudlibc/src/libc/sys/stat/fstat.c + cloudlibc/src/libc/sys/stat/fstatat.c + cloudlibc/src/libc/sys/stat/futimens.c + cloudlibc/src/libc/sys/stat/mkdirat.c + cloudlibc/src/libc/sys/stat/utimensat.c + cloudlibc/src/libc/sys/time/gettimeofday.c + cloudlibc/src/libc/sys/uio/preadv.c + cloudlibc/src/libc/sys/uio/pwritev.c + cloudlibc/src/libc/sys/uio/readv.c + cloudlibc/src/libc/sys/uio/writev.c + cloudlibc/src/libc/time/CLOCK_MONOTONIC.c + cloudlibc/src/libc/time/CLOCK_REALTIME.c + cloudlibc/src/libc/time/clock_getres.c + cloudlibc/src/libc/time/clock_gettime.c + cloudlibc/src/libc/time/clock_nanosleep.c + cloudlibc/src/libc/time/nanosleep.c + cloudlibc/src/libc/time/time.c + cloudlibc/src/libc/unistd/faccessat.c + cloudlibc/src/libc/unistd/fdatasync.c + cloudlibc/src/libc/unistd/fsync.c + cloudlibc/src/libc/unistd/ftruncate.c + cloudlibc/src/libc/unistd/linkat.c + cloudlibc/src/libc/unistd/lseek.c + cloudlibc/src/libc/unistd/pread.c + cloudlibc/src/libc/unistd/pwrite.c + cloudlibc/src/libc/unistd/read.c + cloudlibc/src/libc/unistd/readlinkat.c + cloudlibc/src/libc/unistd/sleep.c + cloudlibc/src/libc/unistd/symlinkat.c + cloudlibc/src/libc/unistd/unlinkat.c + cloudlibc/src/libc/unistd/usleep.c + cloudlibc/src/libc/unistd/write.c + sources/__errno_location.c + sources/__main_void.c + sources/__wasilibc_dt.c + sources/__wasilibc_environ.c + sources/__wasilibc_fd_renumber.c + sources/__wasilibc_initialize_environ.c + sources/__wasilibc_random.c + sources/__wasilibc_real.c + sources/__wasilibc_rmdirat.c + sources/__wasilibc_tell.c + sources/__wasilibc_unlinkat.c + sources/abort.c + sources/at_fdcwd.c + sources/chdir.c + sources/complex-builtins.c + sources/environ.c + sources/errno.c + sources/getcwd.c + sources/getentropy.c + sources/isatty.c + sources/math/fmin-fmax.c + sources/math/math-builtins.c + sources/posix.c + sources/preopens.c + sources/reallocarray.c + sources/sbrk.c + sources/truncate.c +) + +if (WASI STREQUAL "p1") + list(APPEND bottom_half_sources + cloudlibc/src/libc/sys/socket/getsockopt.c + cloudlibc/src/libc/sys/socket/recv.c + cloudlibc/src/libc/sys/socket/send.c + cloudlibc/src/libc/sys/socket/shutdown.c + sources/accept-wasip1.c + ) +elseif(WASI STREQUAL "p2") + list(APPEND bottom_half_sources + sources/accept-wasip2.c + sources/bind.c + sources/connect.c + sources/descriptor_table.c + sources/getsockpeername.c + sources/listen.c + sources/netdb.c + sources/poll-wasip2.c + sources/recv.c + sources/send.c + sources/shutdown.c + sources/socket.c + sources/sockets_utils.c + sources/sockopt.c + sources/wasip2.c + sources/wasip2_file.c + sources/wasip2_file_utils.c + sources/wasip2_stdio.c + sources/wasip2_tcp.c + sources/wasip2_udp.c + ) +endif() + +add_object_library(bottom-half ${bottom_half_sources}) +foreach(obj bottom-half-shared bottom-half-static) + target_link_libraries(${obj} PUBLIC musl-top-half-interface) + target_include_directories(${obj} PRIVATE + cloudlibc/src/include + cloudlibc/src + headers/private + ) +endforeach() + +add_custom_target(sysroot-startup-objects) +add_dependencies(sysroot sysroot-startup-objects) + +# ============================================================================= +# startup objects +# +foreach(file crt/crt1.c + crt/crt1-command.c + crt/crt1-reactor.c) + # get the filename without the directory and extension + cmake_path(GET file STEM filename) + + # create a custom target for each file + add_library(${filename}.o OBJECT ${file}) + target_link_libraries(${filename}.o PUBLIC musl-top-half-interface) + set_target_properties(${filename}.o PROPERTIES POSITION_INDEPENDENT_CODE TRUE) + target_compile_options(${filename}.o PRIVATE -fvisibility=default) + + # add a custom command to compile the file + set(dst ${SYSROOT_LIB}/${filename}.o) + add_custom_command( + OUTPUT ${dst} + COMMAND ${CMAKE_COMMAND} -E copy $ ${dst} + DEPENDS ${filename}.o + ) + add_custom_target(sysroot-startup-${filename}.o DEPENDS ${dst}) + add_dependencies(sysroot-startup-objects sysroot-startup-${filename}.o) +endforeach() diff --git a/libc-bottom-half/clocks/CMakeLists.txt b/libc-bottom-half/clocks/CMakeLists.txt new file mode 100644 index 000000000..3a31ff350 --- /dev/null +++ b/libc-bottom-half/clocks/CMakeLists.txt @@ -0,0 +1,7 @@ +add_internal_library_pair(wasi-emulated-process-clocks + clock.c + getrusage.c + times.c) + +sysroot_lib(wasi-emulated-process-clocks-static libwasi-emulated-process-clocks.a) +sysroot_lib(wasi-emulated-process-clocks libwasi-emulated-process-clocks.so) diff --git a/libc-bottom-half/cloudlibc/src/common/time.h b/libc-bottom-half/cloudlibc/src/common/time.h index ede81012d..32bf4d2b5 100644 --- a/libc-bottom-half/cloudlibc/src/common/time.h +++ b/libc-bottom-half/cloudlibc/src/common/time.h @@ -57,7 +57,7 @@ static inline bool timespec_to_timestamp_clamp( if (timespec->tv_sec < 0) { // Timestamps before the Epoch are not supported. -#if __wasilibc_use_wasip2 +#ifdef __wasilibc_use_wasip2 timestamp->seconds = 0; timestamp->nanoseconds = 0; } else { diff --git a/libc-bottom-half/getpid/CMakeLists.txt b/libc-bottom-half/getpid/CMakeLists.txt new file mode 100644 index 000000000..c112bcc2d --- /dev/null +++ b/libc-bottom-half/getpid/CMakeLists.txt @@ -0,0 +1,3 @@ +add_internal_library_pair(wasi-emulated-getpid getpid.c) +sysroot_lib(wasi-emulated-getpid-static libwasi-emulated-getpid.a) +sysroot_lib(wasi-emulated-getpid libwasi-emulated-getpid.so) diff --git a/libc-bottom-half/headers/public/__wasi_snapshot.h b/libc-bottom-half/headers/public/__wasi_snapshot.h deleted file mode 100644 index 9a1007805..000000000 --- a/libc-bottom-half/headers/public/__wasi_snapshot.h +++ /dev/null @@ -1,5 +0,0 @@ -/* This file is (practically) empty by default. The Makefile will replace it - with a non-empty version that defines `__wasilibc_use_wasip2` if targeting - `wasm32-wasip2`. - */ - diff --git a/libc-bottom-half/headers/public/__wasi_snapshot.h.in b/libc-bottom-half/headers/public/__wasi_snapshot.h.in new file mode 100644 index 000000000..0d155a22b --- /dev/null +++ b/libc-bottom-half/headers/public/__wasi_snapshot.h.in @@ -0,0 +1,6 @@ +#ifndef __WASI_SNAPSHOT_H +#define __WASI_SNAPSHOT_H + +#cmakedefine __wasilibc_use_wasip2 + +#endif /* __WASI_SNAPSHOT_H */ diff --git a/libc-bottom-half/mman/CMakeLists.txt b/libc-bottom-half/mman/CMakeLists.txt new file mode 100644 index 000000000..8a7f1a907 --- /dev/null +++ b/libc-bottom-half/mman/CMakeLists.txt @@ -0,0 +1,3 @@ +add_internal_library_pair(wasi-emulated-mman mman.c) +sysroot_lib(wasi-emulated-mman-static libwasi-emulated-mman.a) +sysroot_lib(wasi-emulated-mman libwasi-emulated-mman.so) diff --git a/libc-bottom-half/signal/CMakeLists.txt b/libc-bottom-half/signal/CMakeLists.txt new file mode 100644 index 000000000..da43c9bf2 --- /dev/null +++ b/libc-bottom-half/signal/CMakeLists.txt @@ -0,0 +1,19 @@ +add_internal_object_library(top-half-emulated-signal + ../../libc-top-half/musl/src/signal/psignal.c + ../../libc-top-half/musl/src/string/strsignal.c) +foreach(obj top-half-emulated-signal-shared top-half-emulated-signal-static) + target_compile_definitions(${obj} PRIVATE _WASI_EMULATED_SIGNAL) +endforeach() + +add_object_library(bottom-half-emulated-signal signal.c) + +add_internal_shared_library(wasi-emulated-signal + $ + $) + +add_library(wasi-emulated-signal-static STATIC + $ + $) + +sysroot_lib(wasi-emulated-signal-static libwasi-emulated-signal.a) +sysroot_lib(wasi-emulated-signal libwasi-emulated-signal.so) diff --git a/libc-top-half/CMakeLists.txt b/libc-top-half/CMakeLists.txt new file mode 100644 index 000000000..7d76d1b2f --- /dev/null +++ b/libc-top-half/CMakeLists.txt @@ -0,0 +1,560 @@ +# Dummy interface library which helps configure headers/options for internal +# libraries below. +add_library(musl-top-half-interface INTERFACE) +target_include_directories(musl-top-half-interface INTERFACE + musl/src/include + musl/src/internal + musl/arch/wasm32 + musl/arch/generic + headers/private) +target_compile_options(musl-top-half-interface INTERFACE + -Wno-parentheses + -Wno-shift-op-parentheses + -Wno-bitwise-op-parentheses + -Wno-logical-op-parentheses + -Wno-string-plus-int + -Wno-dangling-else + -Wno-unknown-pragmas) +add_dependencies(musl-top-half-interface sysroot_inc) + +# ============================================================================= +# sysroot headers from the top-half +# + +# Generates `bits/alltypes.h` from the input sed script. +find_program(SED sed REQUIRED) +add_custom_command( + OUTPUT ${SYSROOT_INC}/bits/alltypes.h + COMMAND ${CMAKE_COMMAND} -E make_directory ${SYSROOT_INC}/bits + COMMAND + ${SED} -f musl/tools/mkalltypes.sed + musl/arch/wasm32/bits/alltypes.h.in + musl/include/alltypes.h.in + > ${SYSROOT_INC}/bits/alltypes.h + WORKING_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS + musl/tools/mkalltypes.sed + musl/arch/wasm32/bits/alltypes.h.in + musl/include/alltypes.h.in +) +add_custom_target(sysroot-bits-alltypes DEPENDS ${SYSROOT_INC}/bits/alltypes.h) +add_dependencies(sysroot_inc sysroot-bits-alltypes) + +file(GLOB_RECURSE globbed_headers RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS + # Copy in the bulk of musl's public header files. + musl/include/*.h + # Copy in the musl's "bits" header files. + musl/arch/generic/bits/*.h + musl/arch/wasm32/bits/*.h +) + +list(REMOVE_ITEM globbed_headers + # Use the compiler's version of these headers. + musl/include/stdarg.h + musl/include/stddef.h + + # Use the WASI errno definitions. + musl/arch/generic/bits/errno.h + + # Remove headers that aren't supported yet or that aren't relevant for WASI. + musl/arch/generic/bits/dirent.h + musl/arch/generic/bits/fcntl.h + musl/arch/generic/bits/ioctl.h + musl/arch/generic/bits/ipc.h + musl/arch/generic/bits/kd.h + musl/arch/generic/bits/limits.h + musl/arch/generic/bits/link.h + musl/arch/generic/bits/msg.h + musl/arch/generic/bits/ptrace.h + musl/arch/generic/bits/sem.h + musl/arch/generic/bits/shm.h + musl/arch/generic/bits/soundcard.h + musl/arch/generic/bits/statfs.h + musl/arch/generic/bits/termios.h + musl/arch/generic/bits/vt.h + musl/include/aio.h + musl/include/elf.h + musl/include/grp.h + musl/include/lastlog.h + musl/include/libintl.h + musl/include/link.h + musl/include/mntent.h + musl/include/net/ethernet.h + musl/include/net/if.h + musl/include/net/if_arp.h + musl/include/net/route.h + musl/include/netinet/ether.h + musl/include/netinet/if_ether.h + musl/include/paths.h + musl/include/pty.h + musl/include/pwd.h + musl/include/pwd.h + musl/include/resolv.h + musl/include/scsi/scsi.h + musl/include/scsi/scsi_ioctl.h + musl/include/scsi/sg.h + musl/include/shadow.h + musl/include/spawn.h + musl/include/sys/acct.h + musl/include/sys/auxv.h + musl/include/sys/cachectl.h + musl/include/sys/epoll.h + musl/include/sys/fanotify.h + musl/include/sys/fsuid.h + musl/include/sys/inotify.h + musl/include/sys/io.h + musl/include/sys/ipc.h + musl/include/sys/kd.h + musl/include/sys/klog.h + musl/include/sys/membarrier.h + musl/include/sys/mount.h + musl/include/sys/msg.h + musl/include/sys/mtio.h + musl/include/sys/personality.h + musl/include/sys/prctl.h + musl/include/sys/procfs.h + musl/include/sys/ptrace.h + musl/include/sys/quota.h + musl/include/sys/reboot.h + musl/include/sys/sem.h + musl/include/sys/sendfile.h + musl/include/sys/shm.h + musl/include/sys/signalfd.h + musl/include/sys/soundcard.h + musl/include/sys/statfs.h + musl/include/sys/swap.h + musl/include/sys/syslog.h + musl/include/sys/sysmacros.h + musl/include/sys/termios.h + musl/include/sys/timerfd.h + musl/include/sys/ucontext.h + musl/include/sys/user.h + musl/include/sys/vfs.h + musl/include/sys/vt.h + musl/include/sys/wait.h + musl/include/sys/xattr.h + musl/include/syslog.h + musl/include/termios.h + musl/include/ucontext.h + musl/include/ulimit.h + musl/include/utmp.h + musl/include/utmpx.h + musl/include/wait.h + musl/include/wordexp.h +) + +# Exclude `netdb.h` from all of the p1 targets. +if(WASI STREQUAL "p1") + list(REMOVE_ITEM globbed_headers + musl/include/netdb.h + ) +endif() + +foreach(header ${globbed_headers}) + if(${header} MATCHES "^musl/include/") + string(REPLACE "musl/include/" "" dst ${header}) + elseif(${header} MATCHES "^musl/arch/generic/bits/") + string(REPLACE "musl/arch/generic/" "" dst ${header}) + elseif(${header} MATCHES "^musl/arch/wasm32/bits/") + string(REPLACE "musl/arch/wasm32/" "" dst ${header}) + else() + message(FATAL_ERROR "Unhandled header file path: ${header}") + endif() + add_sysroot_header(${header} ${dst}) +endforeach() + +# ============================================================================= +# Object libraries for in-tree source files +# + +set(top_half_sources + musl/src/dirent/alphasort.c + musl/src/dirent/versionsort.c + musl/src/env/__init_tls.c + musl/src/env/__stack_chk_fail.c + musl/src/env/clearenv.c + musl/src/env/getenv.c + musl/src/env/putenv.c + musl/src/env/setenv.c + musl/src/env/unsetenv.c + musl/src/errno/strerror.c + musl/src/exit/assert.c + musl/src/exit/at_quick_exit.c + musl/src/exit/atexit.c + musl/src/exit/exit.c + musl/src/exit/quick_exit.c + musl/src/fcntl/creat.c + musl/src/fenv/fegetexceptflag.c + musl/src/fenv/feholdexcept.c + musl/src/fenv/fenv.c + musl/src/fenv/fesetexceptflag.c + musl/src/fenv/fesetround.c + musl/src/fenv/feupdateenv.c + musl/src/internal/defsysinfo.c + musl/src/internal/intscan.c + musl/src/internal/libc.c + musl/src/internal/shgetc.c + musl/src/legacy/getpagesize.c + musl/src/misc/a64l.c + musl/src/misc/basename.c + musl/src/misc/dirname.c + musl/src/misc/ffs.c + musl/src/misc/ffsl.c + musl/src/misc/ffsll.c + musl/src/misc/fmtmsg.c + musl/src/misc/getdomainname.c + musl/src/misc/gethostid.c + musl/src/misc/getopt.c + musl/src/misc/getopt_long.c + musl/src/misc/getsubopt.c + musl/src/misc/nftw.c + musl/src/misc/realpath.c + musl/src/misc/uname.c + musl/src/network/htonl.c + musl/src/network/htons.c + musl/src/network/in6addr_any.c + musl/src/network/in6addr_loopback.c + musl/src/network/inet_addr.c + musl/src/network/inet_aton.c + musl/src/network/inet_legacy.c + musl/src/network/inet_ntoa.c + musl/src/network/inet_ntop.c + musl/src/network/inet_pton.c + musl/src/network/ntohl.c + musl/src/network/ntohs.c + musl/src/stat/futimesat.c + musl/src/thread/default_attr.c + musl/src/thread/pthread_attr_destroy.c + musl/src/thread/pthread_attr_get.c + musl/src/thread/pthread_attr_init.c + musl/src/thread/pthread_attr_setdetachstate.c + musl/src/thread/pthread_attr_setguardsize.c + musl/src/thread/pthread_attr_setschedparam.c + musl/src/thread/pthread_attr_setstack.c + musl/src/thread/pthread_attr_setstacksize.c + musl/src/thread/pthread_barrierattr_destroy.c + musl/src/thread/pthread_barrierattr_init.c + musl/src/thread/pthread_barrierattr_setpshared.c + musl/src/thread/pthread_cancel.c + musl/src/thread/pthread_cleanup_push.c + musl/src/thread/pthread_condattr_destroy.c + musl/src/thread/pthread_condattr_init.c + musl/src/thread/pthread_condattr_setclock.c + musl/src/thread/pthread_condattr_setpshared.c + musl/src/thread/pthread_equal.c + musl/src/thread/pthread_getattr_np.c + musl/src/thread/pthread_getspecific.c + musl/src/thread/pthread_key_create.c + musl/src/thread/pthread_mutex_destroy.c + musl/src/thread/pthread_mutex_init.c + musl/src/thread/pthread_mutexattr_destroy.c + musl/src/thread/pthread_mutexattr_init.c + musl/src/thread/pthread_mutexattr_setprotocol.c + musl/src/thread/pthread_mutexattr_setpshared.c + musl/src/thread/pthread_mutexattr_setrobust.c + musl/src/thread/pthread_mutexattr_settype.c + musl/src/thread/pthread_rwlock_destroy.c + musl/src/thread/pthread_rwlock_init.c + musl/src/thread/pthread_rwlockattr_destroy.c + musl/src/thread/pthread_rwlockattr_init.c + musl/src/thread/pthread_rwlockattr_setpshared.c + musl/src/thread/pthread_self.c + musl/src/thread/pthread_setcancelstate.c + musl/src/thread/pthread_setcanceltype.c + musl/src/thread/pthread_setspecific.c + musl/src/thread/pthread_spin_destroy.c + musl/src/thread/pthread_spin_init.c + musl/src/thread/pthread_testcancel.c + musl/src/thread/thrd_sleep.c + musl/src/time/__month_to_secs.c + musl/src/time/__secs_to_tm.c + musl/src/time/__tm_to_secs.c + musl/src/time/__tz.c + musl/src/time/__year_to_secs.c + musl/src/time/asctime.c + musl/src/time/asctime_r.c + musl/src/time/ctime.c + musl/src/time/ctime_r.c + musl/src/time/difftime.c + musl/src/time/ftime.c + musl/src/time/getdate.c + musl/src/time/gmtime.c + musl/src/time/gmtime_r.c + musl/src/time/localtime.c + musl/src/time/localtime_r.c + musl/src/time/mktime.c + musl/src/time/strftime.c + musl/src/time/strptime.c + musl/src/time/timegm.c + musl/src/time/timespec_get.c + musl/src/time/wcsftime.c + musl/src/unistd/gethostname.c + musl/src/unistd/posix_close.c + sources/arc4random.c +) + +set(MUSL_PRINTSCAN_SOURCES + musl/src/internal/floatscan.c + musl/src/stdio/vfprintf.c + musl/src/stdio/vfscanf.c + musl/src/stdio/vfwprintf.c + musl/src/stdlib/strtod.c + musl/src/stdlib/wcstod.c) + +set(MUSL_BULK_MEMORY_SOURCES + musl/src/string/memcpy.c + musl/src/string/memmove.c + musl/src/string/memset.c) + +# Note that cmake generally recommends against globbing sources, but there's so +# many here and this doesn't change enough that it feels worth it... +# +# THis also pulls in too many sources, so more are removed below. +file(GLOB globbed_sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS + musl/src/complex/*.c + musl/src/conf/*.c + musl/src/crypt/*.c + musl/src/ctype/*.c + musl/src/locale/*.c + musl/src/math/*.c + musl/src/multibyte/*.c + musl/src/prng/*.c + musl/src/regex/*.c + musl/src/search/*.c + musl/src/stdio/*.c + musl/src/stdlib/*.c + musl/src/string/*.c +) +list(REMOVE_ITEM globbed_sources + # handled below during printscan/bulk-memory library handling + ${MUSL_PRINTSCAN_SOURCES} + ${MUSL_BULK_MEMORY_SOURCES} + # not needed and/or don't compile on wasi + musl/src/complex/cimag.c + musl/src/complex/cimagf.c + musl/src/complex/cimagl.c + musl/src/complex/creal.c + musl/src/complex/crealf.c + musl/src/complex/creall.c + musl/src/locale/bind_textdomain_codeset.c + musl/src/locale/dcngettext.c + musl/src/locale/textdomain.c + musl/src/math/__fpclassify.c + musl/src/math/__fpclassifyf.c + musl/src/math/__fpclassifyl.c + musl/src/math/__signbit.c + musl/src/math/__signbitf.c + musl/src/math/__signbitl.c + musl/src/math/ceil.c + musl/src/math/ceilf.c + musl/src/math/copysign.c + musl/src/math/copysignf.c + musl/src/math/fabs.c + musl/src/math/fabsf.c + musl/src/math/floor.c + musl/src/math/floorf.c + musl/src/math/fmax.c + musl/src/math/fmaxf.c + musl/src/math/fmin.c + musl/src/math/fminf.c + musl/src/math/nearbyint.c + musl/src/math/nearbyintf.c + musl/src/math/rint.c + musl/src/math/rintf.c + musl/src/math/sqrt.c + musl/src/math/sqrtf.c + musl/src/math/trunc.c + musl/src/math/truncf.c + musl/src/stdio/__lockfile.c + musl/src/stdio/flockfile.c + musl/src/stdio/ftrylockfile.c + musl/src/stdio/funlockfile.c + musl/src/stdio/gets.c + musl/src/stdio/pclose.c + musl/src/stdio/popen.c + musl/src/stdio/remove.c + musl/src/stdio/rename.c + musl/src/stdio/tempnam.c + musl/src/stdio/tmpfile.c + musl/src/stdio/tmpnam.c + musl/src/string/strsignal.c +) + +list(APPEND top_half_sources ${globbed_sources}) + +if (WASI STREQUAL "p2") + list(APPEND top_half_sources + musl/src/network/gai_strerror.c + ) +endif() + +if (THREADS) + # pthreads functions needed for actual thread support + list(APPEND top_half_sources + musl/src/stdio/__lockfile.c + musl/src/stdio/flockfile.c + musl/src/stdio/ftrylockfile.c + musl/src/stdio/funlockfile.c + musl/src/thread/__lock.c + musl/src/thread/__wait.c + musl/src/thread/__timedwait.c + musl/src/thread/pthread_barrier_destroy.c + musl/src/thread/pthread_barrier_init.c + musl/src/thread/pthread_barrier_wait.c + musl/src/thread/pthread_cond_broadcast.c + musl/src/thread/pthread_cond_destroy.c + musl/src/thread/pthread_cond_init.c + musl/src/thread/pthread_cond_signal.c + musl/src/thread/pthread_cond_timedwait.c + musl/src/thread/pthread_cond_wait.c + musl/src/thread/pthread_create.c + musl/src/thread/pthread_detach.c + musl/src/thread/pthread_join.c + musl/src/thread/pthread_mutex_consistent.c + musl/src/thread/pthread_mutex_getprioceiling.c + musl/src/thread/pthread_mutex_lock.c + musl/src/thread/pthread_mutex_timedlock.c + musl/src/thread/pthread_mutex_trylock.c + musl/src/thread/pthread_mutex_unlock.c + musl/src/thread/pthread_once.c + musl/src/thread/pthread_rwlock_rdlock.c + musl/src/thread/pthread_rwlock_timedrdlock.c + musl/src/thread/pthread_rwlock_timedwrlock.c + musl/src/thread/pthread_rwlock_tryrdlock.c + musl/src/thread/pthread_rwlock_trywrlock.c + musl/src/thread/pthread_rwlock_unlock.c + musl/src/thread/pthread_rwlock_wrlock.c + musl/src/thread/pthread_spin_lock.c + musl/src/thread/pthread_spin_trylock.c + musl/src/thread/pthread_spin_unlock.c + musl/src/thread/sem_destroy.c + musl/src/thread/sem_getvalue.c + musl/src/thread/sem_init.c + musl/src/thread/sem_post.c + musl/src/thread/sem_timedwait.c + musl/src/thread/sem_trywait.c + musl/src/thread/sem_wait.c + musl/src/thread/wasm32/wasi_thread_start.s + musl/src/thread/wasm32/__wasilibc_busywait.c + ) +else() + # pthreads stubs for single-threaded environment + list(APPEND top_half_sources + ../thread-stub/pthread_barrier_destroy.c + ../thread-stub/pthread_barrier_init.c + ../thread-stub/pthread_barrier_wait.c + ../thread-stub/pthread_cond_broadcast.c + ../thread-stub/pthread_cond_destroy.c + ../thread-stub/pthread_cond_init.c + ../thread-stub/pthread_cond_signal.c + ../thread-stub/pthread_cond_timedwait.c + ../thread-stub/pthread_cond_wait.c + ../thread-stub/pthread_create.c + ../thread-stub/pthread_detach.c + ../thread-stub/pthread_join.c + ../thread-stub/pthread_mutex_consistent.c + ../thread-stub/pthread_mutex_getprioceiling.c + ../thread-stub/pthread_mutex_lock.c + ../thread-stub/pthread_mutex_timedlock.c + ../thread-stub/pthread_mutex_trylock.c + ../thread-stub/pthread_mutex_unlock.c + ../thread-stub/pthread_once.c + ../thread-stub/pthread_rwlock_rdlock.c + ../thread-stub/pthread_rwlock_timedrdlock.c + ../thread-stub/pthread_rwlock_timedwrlock.c + ../thread-stub/pthread_rwlock_tryrdlock.c + ../thread-stub/pthread_rwlock_trywrlock.c + ../thread-stub/pthread_rwlock_unlock.c + ../thread-stub/pthread_rwlock_wrlock.c + ../thread-stub/pthread_spin_lock.c + ../thread-stub/pthread_spin_trylock.c + ../thread-stub/pthread_spin_unlock.c + ) +endif() + +add_object_library(top-half ${top_half_sources}) +foreach(obj top-half-shared top-half-static) + target_link_libraries(${obj} PUBLIC musl-top-half-interface) +endforeach() + +if (LTO) + set_source_files_properties(musl/src/exit/atexit.c + PROPERTIES COMPILE_OPTIONS -fno-lto) +endif() + +# ============================================================================= +# printscan library handling +# +# There are three copies of the printscan-related functions built: +# +# 1. `printscan_default` - long double support is disabled but float support +# is enabled. +# 2. `printscan_nofloat` - floats are entirely disabled. +# 3. `printscan_longdouble` - long double + floats enabled +# +# These are the included in various final artifacts in various ways. + +add_internal_object_library(printscan-default ${MUSL_PRINTSCAN_SOURCES}) +add_internal_object_library(printscan-nofloat ${MUSL_PRINTSCAN_SOURCES}) +add_internal_object_library(printscan-longdouble ${MUSL_PRINTSCAN_SOURCES}) + +foreach(obj printscan-default-shared printscan-default-static) + target_compile_definitions(${obj} PRIVATE + __wasilibc_printscan_no_long_double + __wasilibc_printscan_full_support_option="add -lc-printscan-long-double to the link command") +endforeach() + +foreach(obj printscan-nofloat-shared printscan-nofloat-static) + target_compile_definitions(${obj} PRIVATE + __wasilibc_printscan_no_floating_point + __wasilibc_printscan_floating_point_support_option="remove -lc-printscan-no-floating-point from the link command") +endforeach() + +# Add explicit `*.a` files to the sysroot which can be manually selected by +# consumers via `-l`. +add_library(c-printscan-long-double STATIC EXCLUDE_FROM_ALL $) +add_library(c-printscan-no-floating-point STATIC EXCLUDE_FROM_ALL $) +sysroot_lib(c-printscan-long-double libc-printscan-long-double.a) +sysroot_lib(c-printscan-no-floating-point libc-printscan-no-floating-point.a) + +# ============================================================================= +# bulk memory handling +# +# TODO: apply -mbulk-memory globally, once +# https://github.com/llvm/llvm-project/issues/52618 is resolved +add_internal_object_library(bulk-memory ${MUSL_BULK_MEMORY_SOURCES}) + +foreach(obj bulk-memory-shared bulk-memory-static) + target_compile_definitions(${obj} PRIVATE -DBULK_MEMORY_THRESHOLD=${BULK_MEMORY_THRESHOLD}) + target_compile_options(${obj} PRIVATE -mbulk-memory) +endforeach() + +# ============================================================================= +# libsetjmp.{a,so} +# +add_internal_library_pair(setjmp musl/src/setjmp/wasm32/rt.c) + +if (LTO) + set_source_files_properties(musl/src/setjmp/wasm32/rt.c + PROPERTIES COMPILE_OPTIONS -fno-lto) +endif() + +foreach(obj setjmp setjmp-static) + target_compile_options(${obj} PRIVATE -mllvm -wasm-enable-sjlj) + target_link_options(${obj} PRIVATE + -Wl,--allow-undefined-file=${CMAKE_SOURCE_DIR}/linker-provided-symbols.txt) +endforeach() + +if (SETJMP) + sysroot_lib(setjmp libsetjmp.so) + sysroot_lib(setjmp-static libsetjmp.a) +endif() + +# ============================================================================= +# libdl.{a,so} +# +add_internal_library_pair(dl musl/src/misc/dl.c) + +sysroot_lib(dl libdl.so) +sysroot_lib(dl-static libdl.a) diff --git a/scripts/install-include-headers.sh b/scripts/install-include-headers.sh deleted file mode 100755 index efa48aa6d..000000000 --- a/scripts/install-include-headers.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env bash -# -# Install all the necessary necessary include files from wasi-libc -# (`$WASI_LIBC`) into the sysroot include directory (`$SYSROOT_INC`). It uses a -# passed target triple (`$TARGET_TRIPLE`) to condition some of the -# copied/generated files. -# -# Usage: SYSROOT_INC=... TARGET_TRIPLE=... ./install-include-headers.sh - -set -euo pipefail - -PARENT_DIR=$(dirname $(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)) -WASI_LIBC="${WASI_LIBC:-$PARENT_DIR}" -if [[ -z "${SYSROOT_INC}" || -z "${TARGET_TRIPLE}" ]]; then - echo "usage: SYSROOT_INC=... TARGET_TRIPLE=... ./install-include-headers.sh" - exit 1 -fi -# The commands are available for override to allow dry runs. -CP="${CP:-cp -v}" -RM="${RM:-rm -v}" -MKDIR="${MKDIR:-mkdir}" -SED="${SED:-sed}" - -# Copy in the bottom half's public headers. -$MKDIR -p $SYSROOT_INC -$CP -r $WASI_LIBC/libc-bottom-half/headers/public/* $SYSROOT_INC - -# Copy in the bulk of musl's public header files. -$CP -r $WASI_LIBC/libc-top-half/musl/include/* $SYSROOT_INC - -# Copy in the musl's "bits" header files. -$MKDIR -p $SYSROOT_INC/bits -$CP -r $WASI_LIBC/libc-top-half/musl/arch/generic/bits/* $SYSROOT_INC/bits -$CP -r $WASI_LIBC/libc-top-half/musl/arch/wasm32/bits/* $SYSROOT_INC/bits - -# Generate musl's bits/alltypes.h header. -(set -x; $SED -f $WASI_LIBC/libc-top-half/musl/tools/mkalltypes.sed \ - $WASI_LIBC/libc-top-half/musl/arch/wasm32/bits/alltypes.h.in \ - $WASI_LIBC/libc-top-half/musl/include/alltypes.h.in \ - > $SYSROOT_INC/bits/alltypes.h) - -# Copy in the fts header files. -$CP $WASI_LIBC/fts/musl-fts/fts.h $SYSROOT_INC/fts.h - -# Remove selected header files. These are files from musl's include directory -# that we don't want to install in the sysroot's include directory. -MUSL_OMIT_HEADERS=() -# Remove files which aren't headers (we generate `alltypes.h` above). -MUSL_OMIT_HEADERS+=("bits/syscall.h.in" "bits/alltypes.h.in" "alltypes.h.in") -# Use the compiler's version of these headers. -MUSL_OMIT_HEADERS+=("stdarg.h" "stddef.h") -# Use the WASI errno definitions. -MUSL_OMIT_HEADERS+=("bits/errno.h") -# Remove headers that aren't supported yet or that aren't relevant for WASI. -MUSL_OMIT_HEADERS+=("sys/procfs.h" "sys/user.h" "sys/kd.h" "sys/vt.h" \ - "sys/soundcard.h" "sys/sem.h" "sys/shm.h" "sys/msg.h" "sys/ipc.h" \ - "sys/ptrace.h" "sys/statfs.h" "bits/kd.h" "bits/vt.h" "bits/soundcard.h" \ - "bits/sem.h" "bits/shm.h" "bits/msg.h" "bits/ipc.h" "bits/ptrace.h" \ - "bits/statfs.h" "sys/vfs.h" "syslog.h" "sys/syslog.h" "wait.h" \ - "sys/wait.h" "ucontext.h" "sys/ucontext.h" "paths.h" "utmp.h" "utmpx.h" \ - "lastlog.h" "sys/acct.h" "sys/cachectl.h" "sys/epoll.h" "sys/reboot.h" \ - "sys/swap.h" "sys/sendfile.h" "sys/inotify.h" "sys/quota.h" "sys/klog.h" \ - "sys/fsuid.h" "sys/io.h" "sys/prctl.h" "sys/mtio.h" "sys/mount.h" \ - "sys/fanotify.h" "sys/personality.h" "elf.h" "link.h" "bits/link.h" \ - "scsi/scsi.h" "scsi/scsi_ioctl.h" "scsi/sg.h" "sys/auxv.h" "pwd.h" \ - "shadow.h" "grp.h" "mntent.h" "resolv.h" "pty.h" "ulimit.h" "sys/xattr.h" \ - "wordexp.h" "spawn.h" "sys/membarrier.h" "sys/signalfd.h" "termios.h" \ - "sys/termios.h" "bits/termios.h" "net/if.h" "net/if_arp.h" \ - "net/ethernet.h" "net/route.h" "netinet/if_ether.h" "netinet/ether.h" \ - "sys/timerfd.h" "libintl.h" "sys/sysmacros.h" "aio.h") -# Exclude `netdb.h` from all of the p1 targets. -if [[ $TARGET_TRIPLE == *"wasi" || $TARGET_TRIPLE == *"wasi-threads" || \ - $TARGET_TRIPLE == *"wasip1" || $TARGET_TRIPLE == *"wasip1-threads" ]]; then - MUSL_OMIT_HEADERS+=("netdb.h") -fi - -# Remove all the `MUSL_OMIT_HEADERS` previously copied over. -for OMIT_HEADER in "${MUSL_OMIT_HEADERS[@]}"; do - $RM -f $SYSROOT_INC/$OMIT_HEADER -done - -# Update the `__wasi_snapshot.h` with some additional p2 definitions. -if [[ $TARGET_TRIPLE == *"p2" ]]; then - printf '#ifndef __wasilibc_use_wasip2\n#define __wasilibc_use_wasip2\n#endif\n' \ - > $SYSROOT_INC/__wasi_snapshot.h -fi diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2f53c7b5e..97582e09d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,40 +1,10 @@ -cmake_minimum_required(VERSION 3.26) -project(wasi-libc-tests) - -if(NOT CMAKE_C_COMPILER_ID MATCHES Clang) - message(FATAL_ERROR "C compiler ${CMAKE_C_COMPILER} is not `Clang`, it is ${CMAKE_C_COMPILER_ID}") -endif() - -message(STATUS "Found executable for `nm`: ${CMAKE_NM}") -message(STATUS "Found executable for `ar`: ${CMAKE_AR}") -message(STATUS "Found executable for `ranlib`: ${CMAKE_RANLIB}") - include(FetchContent) include(ExternalProject) include(CTest) enable_testing() -set(TARGET_TRIPLE "wasm32-wasi" CACHE STRING "WASI target to test") -set(MALLOC_IMPL "" CACHE STRING "Malloc implementation in use") option(PYTHON_TESTS "Build Python with this wasi-libc and run its tests" OFF) -# ========= Sysroot sanity check ================================ - -cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH LIBC_SRC_DIR) -set(SYSROOT_DIR "${LIBC_SRC_DIR}/sysroot") -set(SYSROOT "${SYSROOT_DIR}/lib/${TARGET_TRIPLE}") - -# This build configuration does not currently manage the sysroot itself (but -# ideally it will one day). Double-check that the sysroot exists before actually -# trying to build any tests. -if (NOT EXISTS "${SYSROOT_DIR}") - message(FATAL_ERROR " - No sysroot for ${TARGET_TRIPLE} available at ${SYSROOT_DIR}; to build it, e.g.: - cd ${LIBC_SRC_DIR} - make TARGET_TRIPLE=${TARGET_TRIPLE} - ") -endif() - # ========= Clone libc-test ===================================== FetchContent_Declare( @@ -48,39 +18,18 @@ set(LIBC_TEST "${libc-test_SOURCE_DIR}") message(STATUS "libc-test source directory: ${LIBC_TEST}") # ========= Download wasmtime as a test runner ================== +include(ba-download) if(NOT ENGINE OR ENGINE STREQUAL "") - set(WASMTIME_VERSION "v38.0.2") - set(WASMTIME_REPO "https://github.com/bytecodealliance/wasmtime") - - if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") - set(WASMTIME_ARCH "x86_64") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") - set(WASMTIME_ARCH "aarch64") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64") - set(WASMTIME_ARCH "aarch64") - else() - message(FATAL_ERROR "Unsupported architecture ${CMAKE_HOST_SYSTEM_PROCESSOR} for Wasmtime") - endif() - - if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") - set(WASMTIME_OS macos) - elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") - set(WASMTIME_OS linux) - else() - message(FATAL_ERROR "Unsupported system ${CMAKE_SYSTEM_NAME} for Wasmtime") - endif() - - ExternalProject_Add( - engine - URL "${WASMTIME_REPO}/releases/download/${WASMTIME_VERSION}/wasmtime-${WASMTIME_VERSION}-${WASMTIME_ARCH}-${WASMTIME_OS}.tar.xz" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" + ba_download( + wasmtime + "https://github.com/bytecodealliance/wasmtime" + "v38.0.2" ) - ExternalProject_Get_Property(engine SOURCE_DIR) + ExternalProject_Get_Property(wasmtime SOURCE_DIR) set(ENGINE "${SOURCE_DIR}/wasmtime") message(STATUS "Wasmtime executable: ${ENGINE}") + add_custom_target(engine ALL DEPENDS wasmtime) else() add_custom_target(engine) endif() @@ -88,17 +37,12 @@ endif() # ========= libc-test defined tests ============================= function(add_wasilibc_flags target) - target_compile_options(${target} PRIVATE - "--target=${TARGET_TRIPLE}" - "--sysroot=${SYSROOT_DIR}" - ) - target_link_options(${target} PRIVATE - "--target=${TARGET_TRIPLE}" - "--sysroot=${SYSROOT_DIR}" - "-resource-dir=${LIBC_SRC_DIR}/build/${TARGET_TRIPLE}/resource-dir" - ) + add_dependencies(${target} sysroot builtins) + # Using an `INTERFACE` looks to get what we want here which is to rebuild this + # if the library changes but not actually add any arguments to the link-line. + target_link_libraries(${target} INTERFACE c-static) + if (TARGET_TRIPLE MATCHES "-threads") - target_compile_options(${target} PRIVATE -pthread) target_link_options(${target} PRIVATE -pthread -Wl,--import-memory,--export-memory,--shared-memory,--max-memory=1073741824) endif() @@ -131,7 +75,7 @@ function(add_test_executable executable_name src) # Build the test exeutable itself and apply all custom options as applicable. add_executable(${executable_name} ${src}) add_wasilibc_flags(${executable_name}) - target_link_libraries(${executable_name} libc_test_support) + target_link_libraries(${executable_name} PRIVATE libc_test_support) foreach(flag IN LISTS arg_CFLAGS) target_compile_options(${executable_name} PRIVATE ${flag}) endforeach() @@ -235,14 +179,14 @@ add_libc_test(functional/memstream.c) add_libc_test(functional/qsort.c) add_libc_test(functional/random.c) add_libc_test(functional/search_hsearch.c) -if (MALLOC_IMPL STREQUAL "emmalloc") +if (MALLOC STREQUAL "emmalloc") set_tests_properties(libc_test_functional_search_hsearch.wasm PROPERTIES WILL_FAIL TRUE) endif() add_libc_test(functional/search_insque.c) add_libc_test(functional/search_lsearch.c) add_libc_test(functional/search_tsearch.c) add_libc_test(functional/snprintf.c) -add_libc_test(functional/sscanf.c) +add_libc_test(functional/sscanf.c CFLAGS -Wno-literal-range) add_libc_test(functional/strftime.c) add_libc_test(functional/string.c) add_libc_test(functional/string_memcpy.c) @@ -451,7 +395,7 @@ if (PYTHON_TESTS) find_program(PYTHON python3 python REQUIRED) find_program(MAKE make REQUIRED) - set(flags "--target=${TARGET_TRIPLE} --sysroot=${SYSROOT_DIR}") + set(flags "--target=${TARGET_TRIPLE} --sysroot=${SYSROOT}") ExternalProject_Add( python @@ -514,4 +458,5 @@ if (PYTHON_TESTS) -E env CFLAGS=${flags} LDFLAGS=${flags} -- ${MAKE} --directory cross-build/wasm32-wasip1 test ) + ExternalProject_Add_StepDependencies(python configure sysroot) endif() From 3d470813aca69c1fffd31c1f3f404e0775ea5e22 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 21 Nov 2025 16:48:39 -0800 Subject: [PATCH 2/3] Disable check-symbols by default --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 349656473..ec27d77df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,7 @@ option(SETJMP "Build setjmp/longjmp support" ON) option(BUILD_TESTS "Whether or not to build tests" OFF) option(SIMD "Whether or not to build simd-enabled intrinsics into wasi-libc" OFF) option(BUILD_SHARED "Whether or not to build shared libraries" ON) -option(CHECK_SYMBOLS "Whether or not to check the exported symbols of libc.a" ON) +option(CHECK_SYMBOLS "Whether or not to check the exported symbols of libc.a" OFF) if(TARGET_TRIPLE MATCHES "-threads$") set(WASI p1) From d26d5756b04bba161ce1619e3c9f33f7601c10ad Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 2 Dec 2025 18:49:46 -0800 Subject: [PATCH 3/3] Fix typo --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec27d77df..a4afe0826 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set(CMAKE_SYSTEM_NAME WASI) # I'm not entirely sure why this is necessary on Windows. This may be a bug in # CMake, I'm not sure. The problem is that, at least on CI, CMake detects that -# the compiler in use in clang but doesn't understand the `SYSTEM` header +# the compiler in use is clang but doesn't understand the `SYSTEM` header # option meaning it just pass `-I...` instead of # `-isystem ...`. This in turn causes the build to fail for... somewhat # unknown reasons which may also be bugs in wasi-libc. Setting this seems