Skip to content

[WIP] Add CMake build system #330

New issue

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

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

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -58,21 +58,27 @@ jobs:

- name: Build libc
shell: bash
run: make -j4
run: |
cmake -DCMAKE_INSTALL_PREFIX=install-sysroot .
cmake --build . --target install
ctest
- uses: actions/upload-artifact@v1
with:
# Upload the sysroot folder. Give it a name according to the OS it was built for.
name: ${{ format( 'sysroot-{0}.tgz', matrix.os) }}
path: sysroot
path: install-sysroot

- name: Build libc + threads
# Only build the thread-capable wasi-libc in the latest supported Clang
# version; the earliest version does not have all necessary builtins
# (e.g., `__builtin_wasm_memory_atomic_notify`).
if: matrix.clang_version != '10.0.0'
shell: bash
run: make -j4 THREAD_MODEL=posix
run: |
cmake -DCMAKE_INSTALL_PREFIX=install-sysroot -DTHREAD_MODEL=posix .
cmake --build . --target install
ctest
# Disable the headerstest job for now, while WASI transitions from the
# witx snapshots to wit proposals, and we have a few manual edits to the
32 changes: 32 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
cmake_minimum_required(VERSION 3.16.3)

project(wasi-libc LANGUAGES C)

enable_testing()

if("${CMAKE_C_COMPILER}" MATCHES "(.*)clang(-[0-9]+)?$")
set(CMAKE_NM "${CMAKE_MATCH_1}llvm-nm${CMAKE_MATCH_2}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend against this. This prevents the user from specifying the name tool to use.

endif()

find_package(Python COMPONENTS Interpreter REQUIRED)

set(TARGET_TRIPLE wasm32-wasi)
set(MULTIARCH_TRIPLE wasm32-wasi)

set(CMAKE_C_COMPILER_TARGET ${TARGET_TRIPLE} CACHE STRING "The target to compile for")

# note that pthread support is still a work-in-progress.
set(THREAD_MODEL "single" CACHE STRING "single or posix")

set(MALLOC_IMPL "dlmalloc" CACHE STRING "dlmalloc or none")

option(BUILD_LIBC_TOP_HALF "Build libc top half" ON)

# 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
set(BULK_MEMORY_THRESHOLD "32" CACHE STRING "bulk memory threshold")

add_subdirectory(cmake)
1,269 changes: 601 additions & 668 deletions Makefile

Large diffs are not rendered by default.

112 changes: 112 additions & 0 deletions cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
set(LIBC_BOTTOM_HALF_HEADERS_PUBLIC_DIR ${PROJECT_SOURCE_DIR}/libc-bottom-half/headers/public)
set(LIBC_TOP_HALF_MUSL_DIR ${PROJECT_SOURCE_DIR}/libc-top-half/musl)
set(LIBC_TOP_HALF_MUSL_SRC_DIR ${LIBC_TOP_HALF_MUSL_DIR}/src)
set(LIBC_BOTTOM_HALF_DIR ${PROJECT_SOURCE_DIR}/libc-bottom-half)
set(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_DIR ${LIBC_BOTTOM_HALF_DIR}/cloudlibc/src)

set(INSTALL_LIB_DIR lib/${MULTIARCH_TRIPLE})
set(INSTALL_SHARE_DIR share/${MULTIARCH_TRIPLE})

include(global-compiler-options.cmake)
include(local-sysroot.cmake)
include(predefined-macros.cmake)
include(libc-imports.cmake)

add_subdirectory(libc-bottom-half)
add_subdirectory(libc-top-half)

if(${MALLOC_IMPL} STREQUAL "dlmalloc")
add_subdirectory(dlmalloc)
endif()

add_library(wasi-emulated-signal)
target_link_libraries(wasi-emulated-signal
wasi-emulated-signal-musl-objs
wasi-emulated-signal-objs
)
add_custom_command(TARGET wasi-emulated-signal POST_BUILD
COMMAND ${CMAKE_C_COMPILER_AR} crs $<TARGET_FILE:c>
)

add_library(c)

set (LIBC_LINK_LIBRARIES

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an anti-pattern. Prefer to directly use the targets with target_link_libraries

libc-bottom-half
)

if(${BUILD_LIBC_TOP_HALF} STREQUAL "ON")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to prefer the more concise spelling:

Suggested change
if(${BUILD_LIBC_TOP_HALF} STREQUAL "ON")
if(BUILD_LIBC_TOP_HALF)

This has the benefit of allowing the user to specify the value with a truthy value that CMake permits (ON, YES, 1).

list(APPEND LIBC_LINK_LIBRARIES
libc-top-half
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, an anti-pattern. Prefer to use a generator expression with target_link_libraries.

endif()

if(${MALLOC_IMPL} STREQUAL "dlmalloc")
list(APPEND LIBC_LINK_LIBRARIES
dlmalloc)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar

elseif(${MALLOC_IMPL} STREQUAL "none")
# nothing to do here
else()
message(FATAL_ERROR "unknown malloc implementation ${MALLOC_IMPL}")
endif()

target_link_libraries(c
PRIVATE
${LIBC_LINK_LIBRARIES}
)

add_custom_command(TARGET c POST_BUILD
COMMAND ${CMAKE_C_COMPILER_AR} crs $<TARGET_FILE:c>
)
Comment on lines +57 to +59

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do this? Add a proper target for a static archive. There is no guarantee the librarian accepts the GNU style arguments.


add_dependencies(c sysroot-headers)

# Create empty placeholder libraries.
foreach(stub m rt pthread crypt util xnet resolve dl)
set(lib_path ${SYSROOT_LIB_DIR}/lib${stub}.a)
add_custom_command(OUTPUT ${lib_path}
COMMAND ${CMAKE_COMMAND} -E make_directory ${SYSROOT_LIB_DIR}
COMMAND ${CMAKE_C_COMPILER_AR} crs ${lib_path})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to use add_library over a custom command.

add_custom_target(${stub} ALL
DEPENDS ${lib_path})
endforeach()

install(
TARGETS
c
c-printscan-long-double
c-printscan-no-floating-point
wasi-emulated-mman
wasi-emulated-process-clocks
wasi-emulated-getpid
wasi-emulated-signal
ARCHIVE DESTINATION ${INSTALL_LIB_DIR}
LIBRARY DESTINATION ${INSTALL_LIB_DIR}
)

install(
DIRECTORY ${SYSROOT_INC_DIR}
DESTINATION .

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems odd, why is the destination .?

)

install(
DIRECTORY ${SYSROOT_SHARE_DIR}
DESTINATION share
)

install(
DIRECTORY ${SYSROOT_LIB_DIR}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the custom variables rather than CMake's install variables (use include(GNUInstallDirs)).

DESTINATION lib
)

add_test(NAME check-metadata
COMMAND diff -wur

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

diff is not guaranteed to be present in the path on Windows.

${PROJECT_SOURCE_DIR}/expected/${MULTIARCH_TRIPLE}/${THREAD_MODEL}/predefined-macros.txt
${CMAKE_BINARY_DIR}/sysroot/share/${MULTIARCH_TRIPLE}/predefined-macros.txt)

add_test(NAME check-headers
COMMAND ${CMAKE_C_COMPILER}
-target ${CMAKE_C_COMPILER_TARGET}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This prevents the use of any compiler other than clang.

--sysroot=${CMAKE_BINARY_DIR}/sysroot
-fsyntax-only
"-Wno#warnings"
${CMAKE_BINARY_DIR}/sysroot/share/${MULTIARCH_TRIPLE}/include-all.c)
10 changes: 10 additions & 0 deletions cmake/dlmalloc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
set(DLMALLOC_DIR ${PROJECT_SOURCE_DIR}/dlmalloc)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the variable for a single use?


add_library(dlmalloc OBJECT
${DLMALLOC_DIR}/src/dlmalloc.c)

target_include_directories(dlmalloc
PRIVATE
${DLMALLOC_DIR}/include)

add_dependencies(dlmalloc sysroot-headers)
39 changes: 39 additions & 0 deletions cmake/global-compiler-options.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# WebAssembly floating-point match doesn't trap.
# TODO: Add -fno-signaling-nans when the compiler supports it.
add_compile_options(-fno-trapping-math)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should validate that the compiler supports the option.


# Add all warnings, but disable a few which occur in third-party code.
add_compile_options(
-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
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar


# Configure support for threads
if("${THREAD_MODEL}" STREQUAL "single")
add_compile_options(-mthread-model single)
elseif("${THREAD_MODEL}" STREQUAL "posix")
add_compile_options(-mthread-model posix -pthread -ftls-model=local-exec)
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`.
include_directories(SYSTEM ${CMAKE_BINARY_DIR}/sysroot/include)
41 changes: 41 additions & 0 deletions cmake/libc-bottom-half/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
set(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC_DIR ${LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_DIR}/include)
set(LIBC_BOTTOM_HALF_SRC_DIR ${LIBC_BOTTOM_HALF_DIR}/sources)
set(LIBC_BOTTOM_HALF_HEADERS_PRIVATE_DIR ${LIBC_BOTTOM_HALF_DIR}/headers/private)

file(GLOB_RECURSE
LIBC_BOTTOM_HALF_ALL_SOURCES
CONFIGURE_DEPENDS
${LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_DIR}/*.c
${LIBC_BOTTOM_HALF_SRC_DIR}/*.c)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a highly dubious. This will lose the ability to alter the sources. The glob is applied once at configure time and never again. You should explicitly list the sources. Similar throughout.


set(LIBC_BOTTOM_HALF_INC_DIRS
${LIBC_BOTTOM_HALF_HEADERS_PRIVATE_DIR}
${LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC_DIR}
${LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_DIR}
${LIBC_TOP_HALF_MUSL_SRC_DIR}/include
${LIBC_TOP_HALF_MUSL_SRC_DIR}/internal
)

# 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.
set(CHDIR_SRC "${LIBC_BOTTOM_HALF_SRC_DIR}/chdir.c")
list(REMOVE_ITEM LIBC_BOTTOM_HALF_ALL_SOURCES ${CHDIR_SRC})
list(APPEND LIBC_BOTTOM_HALF_ALL_SOURCES ${CHDIR_SRC})

add_library(libc-bottom-half OBJECT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is some kind of "library" that getting somehow inlined into the main libc? More like a list of object files that a library per-say?

I assume all the object files that make up libc-bottom-half will still show up as individual object files within libc.a?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they're just object files.

${LIBC_BOTTOM_HALF_ALL_SOURCES})
add_dependencies(libc-bottom-half sysroot-headers)
target_include_directories(libc-bottom-half
PRIVATE
${LIBC_BOTTOM_HALF_INC_DIRS}
SYSTEM
${SYSROOT_INC_DIR}
)

add_subdirectory(clocks)
add_subdirectory(getpid)
add_subdirectory(mman)
add_subdirectory(signal)
add_subdirectory(crt1)
16 changes: 16 additions & 0 deletions cmake/libc-bottom-half/clocks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
file(GLOB_RECURSE
CLOCKS_SOURCES
${LIBC_BOTTOM_HALF_DIR}/clocks/*.c)

add_library(wasi-emulated-process-clocks STATIC
${CLOCKS_SOURCES})

target_include_directories(wasi-emulated-process-clocks
PRIVATE
${LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_DIR})

add_dependencies(wasi-emulated-process-clocks sysroot-headers)

add_custom_command(TARGET wasi-emulated-process-clocks POST_BUILD
COMMAND ${CMAKE_C_COMPILER_AR} crs $<TARGET_FILE:c>
)
26 changes: 26 additions & 0 deletions cmake/libc-bottom-half/crt1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
file(GLOB
LIBC_BOTTOM_HALF_CRT_SOURCES
CONFIGURE_DEPENDS
${LIBC_BOTTOM_HALF_DIR}/crt/*.c)

foreach(crt_path ${LIBC_BOTTOM_HALF_CRT_SOURCES})
get_filename_component(crt_name ${crt_path} NAME_WLE)
add_library(${crt_name} OBJECT ${crt_path})

target_include_directories(${crt_name}
PRIVATE
${LIBC_BOTTOM_HALF_INC_DIRS}
)

add_dependencies(${crt_name} sysroot-headers)

add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/sysroot/lib/${crt_name}.o
COMMAND ${CMAKE_COMMAND} -E make_directory ${SYSROOT_LIB_DIR}
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_OBJECTS:${crt_name}> ${SYSROOT_LIB_DIR}/${crt_name}.o
COMMAND_EXPAND_LISTS
)

add_custom_target(${crt_name}.o ALL
DEPENDS ${CMAKE_BINARY_DIR}/sysroot/lib/${crt_name}.o)
add_dependencies(${crt_name}.o ${crt_name})
endforeach()
17 changes: 17 additions & 0 deletions cmake/libc-bottom-half/getpid/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
file(GLOB_RECURSE
GETPID_SOURCES
${LIBC_BOTTOM_HALF_DIR}/getpid/*.c)

add_library(wasi-emulated-getpid STATIC
${GETPID_SOURCES})

set_target_properties(wasi-emulated-getpid
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/sysroot/lib
)

add_dependencies(wasi-emulated-getpid sysroot-headers)

add_custom_command(TARGET wasi-emulated-getpid POST_BUILD
COMMAND ${CMAKE_C_COMPILER_AR} crs $<TARGET_FILE:c>
)
12 changes: 12 additions & 0 deletions cmake/libc-bottom-half/mman/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
file(GLOB_RECURSE
MMAN_SOURCES
${LIBC_BOTTOM_HALF_DIR}/mman/*.c)

add_library(wasi-emulated-mman STATIC
${MMAN_SOURCES})

add_dependencies(wasi-emulated-mman sysroot-headers)

add_custom_command(TARGET wasi-emulated-mman POST_BUILD
COMMAND ${CMAKE_C_COMPILER_AR} crs $<TARGET_FILE:c>
)
10 changes: 10 additions & 0 deletions cmake/libc-bottom-half/signal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
file(GLOB_RECURSE
SIGNAL_SOURCES
${LIBC_BOTTOM_HALF_DIR}/signal/*.c)

add_library(wasi-emulated-signal-objs
OBJECT
${SIGNAL_SOURCES}
)

add_dependencies(wasi-emulated-signal-objs sysroot-headers)
35 changes: 35 additions & 0 deletions cmake/libc-imports.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
add_custom_command(OUTPUT ${SYSROOT_LIB_DIR}/libc.imports
COMMAND ${CMAKE_COMMAND} -E make_directory ${SYSROOT_LIB_DIR}
COMMAND
${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/gen-imports.py
--nm ${CMAKE_NM}
--libc-imports-output ${SYSROOT_LIB_DIR}/libc.imports
--defined-symbols-output ${SYSROOT_SHARE_DIR}/defined-symbols.txt
--undefined-symbols-output ${SYSROOT_SHARE_DIR}/undefined-symbols.txt
$<TARGET_FILE:c>
$<TARGET_FILE:c-printscan-long-double>
$<TARGET_FILE:c-printscan-no-floating-point>
$<TARGET_FILE:wasi-emulated-mman>
$<TARGET_FILE:wasi-emulated-process-clocks>
$<TARGET_FILE:wasi-emulated-getpid>
$<TARGET_FILE:wasi-emulated-signal>
$<TARGET_OBJECTS:crt1>
$<TARGET_OBJECTS:crt1-command>
$<TARGET_OBJECTS:crt1-reactor>
DEPENDS
${PROJECT_SOURCE_DIR}/tools/gen-imports.py)

add_custom_target(libc.imports ALL
DEPENDS ${SYSROOT_LIB_DIR}/libc.imports)
add_dependencies(libc.imports
c
c-printscan-long-double
c-printscan-no-floating-point
wasi-emulated-mman
wasi-emulated-process-clocks
wasi-emulated-getpid
wasi-emulated-signal
crt1
crt1-command
crt1-reactor
)
264 changes: 264 additions & 0 deletions cmake/libc-top-half/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
set(LIBC_TOP_HALF_DIR ${PROJECT_SOURCE_DIR}/libc-top-half)
set(LIBC_TOP_HALF_SOURCE_DIR ${LIBC_TOP_HALF_DIR}/sources)
set(LIBC_TOP_HALF_HEADERS_PRIVATE_DIR ${LIBC_TOP_HALF_DIR}/headers/private)

set(LIBC_TOP_HALF_COMMON_COMPILE_OPTIONS
-Wno-parentheses
-Wno-shift-op-parentheses
-Wno-bitwise-op-parentheses
-Wno-logical-op-parentheses
-Wno-string-plus-int
-Wno-dangling-else
-Wno-unknown-pragmas
)

set(LIBC_TOP_HALF_COMMON_INC_DIRS
${LIBC_TOP_HALF_MUSL_SRC_DIR}/include
${LIBC_TOP_HALF_MUSL_SRC_DIR}/internal
${LIBC_TOP_HALF_MUSL_DIR}/arch/wasm32
${LIBC_TOP_HALF_MUSL_DIR}/arch/generic
${LIBC_TOP_HALF_HEADERS_PRIVATE_DIR}
)

file(GLOB_RECURSE LIBC_TOP_HALF_SOURCES
CONFIGURE_DEPENDS
${LIBC_TOP_HALF_SOURCE_DIR}/*.c
)


file(GLOB LIBC_TOP_HALF_MUSL_SOURCES
CONFIGURE_DEPENDS
${LIBC_TOP_HALF_MUSL_SRC_DIR}/internal/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/string/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/locale/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdlib/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/search/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/multibyte/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/regex/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/prng/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/conf/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/ctype/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/complex/*.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/crypt/*.c
)

list(APPEND LIBC_TOP_HALF_MUSL_SOURCES
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/a64l.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/basename.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/dirname.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/ffs.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/ffsl.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/ffsll.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/fmtmsg.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/getdomainname.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/gethostid.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/getopt.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/getopt_long.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/getsubopt.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/uname.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/misc/nftw.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/errno/strerror.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/htonl.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/htons.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/ntohl.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/ntohs.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/inet_ntop.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/inet_pton.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/inet_aton.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/in6addr_any.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/network/in6addr_loopback.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/fenv/fenv.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/fenv/fesetround.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/fenv/feupdateenv.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/fenv/fesetexceptflag.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/fenv/fegetexceptflag.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/fenv/feholdexcept.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/exit/exit.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/exit/atexit.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/exit/assert.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/exit/quick_exit.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/exit/at_quick_exit.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/strftime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/asctime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/asctime_r.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/ctime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/ctime_r.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/wcsftime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/strptime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/difftime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/timegm.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/ftime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/gmtime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/gmtime_r.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/timespec_get.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/getdate.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/localtime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/localtime_r.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/mktime.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/__tm_to_secs.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/__month_to_secs.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/__secs_to_tm.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/__year_to_secs.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/time/__tz.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/fcntl/creat.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/dirent/alphasort.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/dirent/versionsort.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/env/clearenv.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/env/getenv.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/env/putenv.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/env/setenv.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/env/unsetenv.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/unistd/posix_close.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stat/futimesat.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/legacy/getpagesize.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/thrd_sleep.c
)

list(REMOVE_ITEM LIBC_TOP_HALF_MUSL_SOURCES
${LIBC_TOP_HALF_MUSL_SRC_DIR}/internal/procfdname.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/internal/syscall.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/internal/syscall_ret.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/internal/vdso.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/internal/version.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/flockfile.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/funlockfile.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/__lockfile.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/ftrylockfile.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/rename.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/tmpnam.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/tmpfile.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/tempnam.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/popen.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/pclose.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/remove.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/stdio/gets.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/string/strsignal.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/locale/dcngettext.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/locale/textdomain.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/locale/bind_textdomain_codeset.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/__signbit.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/__signbitf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/__signbitl.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/__fpclassify.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/__fpclassifyf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/__fpclassifyl.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/ceilf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/ceil.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/floorf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/floor.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/truncf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/trunc.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/rintf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/rint.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/nearbyintf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/nearbyint.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/sqrtf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/sqrt.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/fabsf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/fabs.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/copysignf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/copysign.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/fminf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/fmaxf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/fmin.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/math/fmax.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/complex/crealf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/complex/creal.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/complex/creall.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/complex/cimagf.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/complex/cimag.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/complex/cimagl.c
)

if("${THREAD_MODEL}" STREQUAL "posix")
list(APPEND LIBC_TOP_HALF_MUSL_SOURCES
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/__wait.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/__timedwait.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_cleanup_push.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_cond_broadcast.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_cond_destroy.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_cond_init.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_cond_signal.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_cond_timedwait.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_cond_wait.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_condattr_destroy.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_condattr_init.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_condattr_setclock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_condattr_setpshared.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_create.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutex_consistent.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutex_destroy.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutex_init.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutex_getprioceiling.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutex_lock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutex_timedlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutex_trylock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutex_unlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutexattr_destroy.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutexattr_init.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutexattr_setprotocol.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutexattr_setpshared.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutexattr_setrobust.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_mutexattr_settype.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_destroy.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_init.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_rdlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_timedrdlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_timedwrlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_tryrdlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_trywrlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_unlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlock_wrlock.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlockattr_destroy.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlockattr_init.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_rwlockattr_setpshared.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_setcancelstate.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_testcancel.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/sem_destroy.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/sem_getvalue.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/sem_init.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/sem_post.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/sem_timedwait.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/sem_trywait.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/sem_wait.c
)
endif()

set_source_files_properties(
${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
PROPERTIES
COMPILE_DEFINITIONS
BULK_MEMORY_THRESHOLD=${BULK_MEMORY_THRESHOLD}
COMPILE_FLAGS
-mbulk-memory
)

if(${BUILD_LIBC_TOP_HALF} STREQUAL "ON")
add_library(libc-top-half
OBJECT
${LIBC_TOP_HALF_SOURCES}
${LIBC_TOP_HALF_MUSL_SOURCES}
)
target_include_directories(libc-top-half
PRIVATE
${LIBC_TOP_HALF_COMMON_INC_DIRS}
)

if("${THREAD_MODEL}" STREQUAL "posix")
target_include_directories(libc-top-half
PRIVATE
${LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_DIR})
endif()
target_compile_options(libc-top-half
PRIVATE
${LIBC_TOP_HALF_COMMON_COMPILE_OPTIONS}
)
add_dependencies(libc-top-half sysroot-headers)
endif()


add_subdirectory(musl)
69 changes: 69 additions & 0 deletions cmake/libc-top-half/musl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
set(LIBC_TOP_HALF_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
)

add_library(c-printscan-no-floating-point
${LIBC_TOP_HALF_MUSL_PRINTSCAN_SOURCES}
)

target_compile_definitions(c-printscan-no-floating-point PRIVATE
__wasilibc_printscan_no_floating_point
__wasilibc_printscan_floating_point_support_option="remove -lc-printscan-no-floating-point from the link command")
target_compile_options(c-printscan-no-floating-point
PRIVATE
${LIBC_TOP_HALF_COMMON_COMPILE_OPTIONS}
)

target_include_directories(c-printscan-no-floating-point PRIVATE
PRIVATE
${LIBC_TOP_HALF_COMMON_INC_DIRS}
)

add_dependencies(c-printscan-no-floating-point sysroot-headers)

add_custom_command(TARGET c-printscan-no-floating-point POST_BUILD
COMMAND ${CMAKE_C_COMPILER_AR} crs $<TARGET_FILE:c>
)

add_library(c-printscan-long-double
${LIBC_TOP_HALF_MUSL_PRINTSCAN_SOURCES}
)
target_compile_options(c-printscan-long-double
PRIVATE
${LIBC_TOP_HALF_COMMON_COMPILE_OPTIONS})

target_include_directories(c-printscan-long-double
PRIVATE
${LIBC_TOP_HALF_COMMON_INC_DIRS}
)
add_dependencies(c-printscan-long-double sysroot-headers)

add_custom_command(TARGET c-printscan-long-double POST_BUILD
COMMAND ${CMAKE_C_COMPILER_AR} crs $<TARGET_FILE:c>
)


add_library(wasi-emulated-signal-musl-objs
OBJECT
${LIBC_TOP_HALF_MUSL_SRC_DIR}/signal/psignal.c
${LIBC_TOP_HALF_MUSL_SRC_DIR}/string/strsignal.c
)
target_compile_definitions(wasi-emulated-signal-musl-objs
PRIVATE
_WASI_EMULATED_SIGNAL
)
target_compile_options(wasi-emulated-signal-musl-objs
PRIVATE
${LIBC_TOP_HALF_COMMON_COMPILE_OPTIONS})

target_include_directories(wasi-emulated-signal-musl-objs
PRIVATE
${LIBC_TOP_HALF_COMMON_INC_DIRS}
)

add_dependencies(wasi-emulated-signal-musl-objs sysroot-headers)
146 changes: 146 additions & 0 deletions cmake/local-sysroot.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# "local" sysroot for files required for building libc
# (before install step)
set(SYSROOT_DIR ${CMAKE_BINARY_DIR}/sysroot)
set(SYSROOT_INC_DIR ${SYSROOT_DIR}/include)
set(SYSROOT_SHARE_DIR ${SYSROOT_DIR}/${INSTALL_SHARE_DIR})
set(SYSROOT_LIB_DIR ${SYSROOT_DIR}/${INSTALL_LIB_DIR})


# Files from musl's include directory that we don't want to install in the
# sysroot's include directory.
set(MUSL_OMIT_HEADERS
# Remove files which aren't headers (we generate alltypes.h below).
bits/syscall.h.in
bits/alltypes.h.in
alltypes.h.in

# Use the compiler's version of these headers.
stdarg.h
stddef.h

# Use the WASI errno definitions.
bits/errno.h

# Remove headers that aren't supported yet or that aren't relevant for WASI.
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
sys/statvfs.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
netdb.h
resolv.h
pty.h
dlfcn.h
setjmp.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)

if("${THREAD_MODEL}" STREQUAL "single")
# Remove headers not supported in single-threaded mode.
list(APPEND MUSL_OMIT_HEADERS "pthread.h")
endif()

set(MUSL_REMOVE_HEADERS)
foreach(HEADER ${MUSL_OMIT_HEADERS})
list(APPEND MUSL_REMOVE_HEADERS ${SYSROOT_INC_DIR}/${HEADER})
endforeach()

add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/alltypes.h.gen
COMMAND
sed -f ${LIBC_TOP_HALF_MUSL_DIR}/tools/mkalltypes.sed ${LIBC_TOP_HALF_MUSL_DIR}/arch/wasm32/bits/alltypes.h.in ${LIBC_TOP_HALF_MUSL_DIR}/include/alltypes.h.in > ${CMAKE_BINARY_DIR}/alltypes.h.gen
DEPENDS
${LIBC_TOP_HALF_MUSL_DIR}/tools/mkalltypes.sed
${LIBC_TOP_HALF_MUSL_DIR}/arch/wasm32/bits/alltypes.h.in
${LIBC_TOP_HALF_MUSL_DIR}/include/alltypes.h.in
)

add_custom_command(
OUTPUT
${CMAKE_BINARY_DIR}/sysroot

COMMAND
${CMAKE_COMMAND} -E make_directory
${SYSROOT_INC_DIR}
${SYSROOT_DIR}/share

COMMAND
${CMAKE_COMMAND} -E copy_directory
${LIBC_BOTTOM_HALF_HEADERS_PUBLIC_DIR}
${SYSROOT_INC_DIR}

COMMAND
${CMAKE_COMMAND} -E copy_directory
${LIBC_TOP_HALF_MUSL_DIR}/include/
${SYSROOT_INC_DIR}

COMMAND
${CMAKE_COMMAND} -E copy_directory
${LIBC_TOP_HALF_MUSL_DIR}/arch/generic/bits/
${SYSROOT_INC_DIR}/bits

COMMAND
${CMAKE_COMMAND} -E copy_directory
${LIBC_TOP_HALF_MUSL_DIR}/arch/wasm32/bits/
${SYSROOT_INC_DIR}/bits

COMMAND
${CMAKE_COMMAND} -E copy_if_different
${CMAKE_BINARY_DIR}/alltypes.h.gen
${SYSROOT_INC_DIR}/bits/alltypes.h

COMMAND
${CMAKE_COMMAND} -E remove
${MUSL_REMOVE_HEADERS}

DEPENDS
${CMAKE_BINARY_DIR}/alltypes.h.gen
)

add_custom_target(sysroot-headers ALL
DEPENDS ${CMAKE_BINARY_DIR}/sysroot)
25 changes: 25 additions & 0 deletions cmake/predefined-macros.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
get_directory_property(DIR_COMPILE_OPTIONS COMPILE_OPTIONS)

add_custom_command(
OUTPUT
${CMAKE_BINARY_DIR}/sysroot/share/${MULTIARCH_TRIPLE}/include-all.c

COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/sysroot/share/${MULTIARCH_TRIPLE}

COMMAND
${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/gen-predefined-macros.py
--cc ${CMAKE_C_COMPILER}
--output-directory ${SYSROOT_DIR}/share/${MULTIARCH_TRIPLE}
--sysroot ${SYSROOT_DIR}
-target ${CMAKE_C_COMPILER_TARGET} -O2 -DNDEBUG
${DIR_COMPILE_OPTIONS}

DEPENDS
${PROJECT_SOURCE_DIR}/tools/gen-predefined-macros.py
)

add_custom_target(predefined-macros ALL
DEPENDS
${CMAKE_BINARY_DIR}/sysroot/share/${MULTIARCH_TRIPLE}/include-all.c
)
add_dependencies(predefined-macros sysroot-headers)
85 changes: 85 additions & 0 deletions tools/gen-imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# -*- encoding: utf-8 -*-
"""Generate import file for a target
This utility scans a static library to identify the undefined symbols which are
externally visible which it expects to have provided. This is used to generate
the import file definitions for WASI.
Example:
$ python gen-imports.py --nm llvm-nm --prefix __wasi_ libc.a
"""

import argparse
import os
import re
import subprocess
import sys

from subprocess import Popen
from typing import Iterator, List


class SymbolsProvider:
def __init__(self, nm: str, lib_files: List[str]) -> None:
self._nm = nm
self._lib_files = lib_files

def _get_symbols(self, args: List[str]) -> List[str]:
process = Popen([self._nm] + args + ['--just-symbol-name', '--extern-only'] + self._lib_files,
stdout=subprocess.PIPE)
output, error = process.communicate()

lines = output.decode('utf-8').splitlines()
return sorted(set([line for line in lines if not line.endswith(':') and line]))

def get_libc_imports_symbols(self, prefix: str) -> Iterator[str]:
re_prefix = re.compile(prefix)
symbols = self._get_symbols([])
return filter(lambda symbol: re_prefix.match(symbol), symbols)

def get_defined_symbols(self) -> List[str]:
return self._get_symbols(['--defined-only'])

def get_undefined_symbols(self) -> List[str]:
undefined_symbols = self._get_symbols(['--undefined-only'])
defined_symbols = set(self.get_defined_symbols())
return [
symbol for symbol in undefined_symbols
if symbol not in defined_symbols and not symbol.startswith('__mul')
]


def write_symbols(file_path: str, symbols: List[str]) -> None:
with open(file_path, 'w') as f:
f.write('\n'.join(symbols))


def main(argv) -> None:
parser = argparse.ArgumentParser('gen-imports')
parser.add_argument('--nm', default='nm')
parser.add_argument('--prefix', default='^_(.*?)imported_wasi_')
parser.add_argument('--libc-imports-output', required=True)
parser.add_argument('--defined-symbols-output', required=True)
parser.add_argument('--undefined-symbols-output', required=True)

args, unparsed = parser.parse_known_args()

args.nm = os.path.normpath(args.nm)
args.libc_imports_output = os.path.normpath(args.libc_imports_output)
args.defined_symbols_output = os.path.normpath(args.defined_symbols_output)
args.undefined_symbols_output = os.path.normpath(
args.undefined_symbols_output)

lib_files = [os.path.normpath(path) for path in unparsed]

provider = SymbolsProvider(args.nm, lib_files)

write_symbols(args.libc_imports_output,
provider.get_libc_imports_symbols(args.prefix))
write_symbols(args.defined_symbols_output, provider.get_defined_symbols())
write_symbols(args.undefined_symbols_output,
provider.get_undefined_symbols())


if __name__ == '__main__':
main(sys.argv)
135 changes: 135 additions & 0 deletions tools/gen-predefined-macros.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# -*- encoding: utf-8 -*-
"""Generate macro enumeration for WASI target
This utility generates the full list of compiler macros defined during the WASI
builds. It writes out the `predefined-macros.txt` and `include-all.c` files
into the directory specificed.
Examples:
$ python gen-predefined-macros.py --cc clang --sysroot sysroot --output-directory sysroot/share
"""

import argparse
import os
import re
import subprocess
import sys

from subprocess import Popen

def _enumerate_headers(directory):
headers = set()

for root, directories, files in os.walk(directory):
# ignore the bits directories as they are internal implementation
# details
directories[:] = [ d for d in directories if not d == 'bits' and not d == 'c++' ]

# Compute the include relative path, however special case '.' to be
# ignored as a prefix.
path = os.path.relpath(root, directory)
if path == '.':
path = ''

disabled_headers = ['mman.h', 'signal.h', 'times.h', 'resource.h']
# ignore mman.h
# XXX(compnerd) document why mman.h is being ignored
for include in filter(lambda file: file not in disabled_headers, files):
headers.add(os.path.join(path, include))

return headers

def _enumerate_defines(cc, sysroot, flags, include_all_c):
include = os.path.join(sysroot, 'include')

# Collect all the predefined macros ...
process = Popen([
cc,
include_all_c,
# ... marking the sysroot as a system include path as
# clang will include its resource directory include path
# earlier producing compiler-specific output
'-isystem', include,
'-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__GNUC__',
'-U__GNUC_MINOR__',
'-U__GNUC_PATCHLEVEL__',
'-U__VERSION__',
'-U__FLOAT128__',
'-U__NO_MATH_ERRNO__',
'-U__BITINT_MAXWIDTH__',
'-U__FLT_EVAL_METHOD__',
'-Wno-builtin-macro-redefined',
] + flags,
stdout = subprocess.PIPE,
stderr = sys.stderr)
output, error = process.communicate()

if process.returncode:
sys.exit(process.returncode)

defines = output.decode('utf-8').splitlines()

# filter out
# - __FLT16_* for now as not all versions of clang have these
# - __FLOAT128__ as it is not in clang 8.0
__FLT16_ = re.compile(r'\b__FLT16_')
__FLOAT128__ = re.compile(r'\b__FLOAT128__\b')
__WIDTH__ = re.compile(r'\b__(BOOL|INT_(LEAST|FAST)(8|16|32|64)|INT|LONG|LLONG|SHRT)_WIDTH__\b')

defines = [
define for define in defines if not (
re.search(__FLT16_, define) or
re.search(__FLOAT128__, define) or
re.search(__WIDTH__, define) or
False
)
]

# For the __*_ATOMIC_*_LOCK_FREE macros, squash individual compiler names to
# attempt to keep these files compiler-independent
defines = [
re.sub(r'__[A-Z0-9]*_ATOMIC_([A-Z0-9_]*)_LOCK_FREE',
r'__compiler_ATOMIC_\1_LOCK_FREE', define)
for define in defines
]

return defines

def main(argv):
parser = argparse.ArgumentParser('gen-predefined-macros')
parser.add_argument('--cc', default = 'clang')
parser.add_argument('--sysroot', required = True)
parser.add_argument('--output-directory', required = True, dest = 'output')

args, unparsed = parser.parse_known_args()
args.output = os.path.normpath(args.output)
args.sysroot = os.path.normpath(args.sysroot)

include = os.path.join(args.sysroot, 'include')
include_all_c = os.path.join(args.output, 'include-all.c')
predefined_macros_txt = os.path.join(args.output, 'predefined-macros.txt')

with open(include_all_c, 'w') as source:
for header in sorted(_enumerate_headers(include)):
source.write('#include <{}>\n'.format(header))

with open(predefined_macros_txt, 'w') as macros:
for define in _enumerate_defines(args.cc, args.sysroot, unparsed,
include_all_c):
if define.startswith('#define __FLT16_'):
continue
macros.write('{}\n'.format(define))

if __name__ == '__main__':
main(sys.argv)