From f9d135e2007177d60ed96f8f290aaccad4302103 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Tue, 20 Sep 2022 11:02:03 +0100 Subject: [PATCH] Add CMake build system --- CMakeLists.txt | 32 +++ cmake/CMakeLists.txt | 112 ++++++++ cmake/dlmalloc/CMakeLists.txt | 10 + cmake/global-compiler-options.cmake | 39 +++ cmake/libc-bottom-half/CMakeLists.txt | 41 +++ cmake/libc-bottom-half/clocks/CMakeLists.txt | 16 ++ cmake/libc-bottom-half/crt1/CMakeLists.txt | 26 ++ cmake/libc-bottom-half/getpid/CMakeLists.txt | 17 ++ cmake/libc-bottom-half/mman/CMakeLists.txt | 12 + cmake/libc-bottom-half/signal/CMakeLists.txt | 10 + cmake/libc-imports.cmake | 34 +++ cmake/libc-top-half/CMakeLists.txt | 263 +++++++++++++++++++ cmake/libc-top-half/musl/CMakeLists.txt | 69 +++++ cmake/local-sysroot.cmake | 146 ++++++++++ cmake/predefined-macros.cmake | 25 ++ tools/gen-imports.py | 85 ++++++ tools/gen-predefined-macros.py | 135 ++++++++++ 17 files changed, 1072 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 cmake/CMakeLists.txt create mode 100644 cmake/dlmalloc/CMakeLists.txt create mode 100644 cmake/global-compiler-options.cmake create mode 100644 cmake/libc-bottom-half/CMakeLists.txt create mode 100644 cmake/libc-bottom-half/clocks/CMakeLists.txt create mode 100644 cmake/libc-bottom-half/crt1/CMakeLists.txt create mode 100644 cmake/libc-bottom-half/getpid/CMakeLists.txt create mode 100644 cmake/libc-bottom-half/mman/CMakeLists.txt create mode 100644 cmake/libc-bottom-half/signal/CMakeLists.txt create mode 100644 cmake/libc-imports.cmake create mode 100644 cmake/libc-top-half/CMakeLists.txt create mode 100644 cmake/libc-top-half/musl/CMakeLists.txt create mode 100644 cmake/local-sysroot.cmake create mode 100644 cmake/predefined-macros.cmake create mode 100755 tools/gen-imports.py create mode 100644 tools/gen-predefined-macros.py diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..d2abb6753 --- /dev/null +++ b/CMakeLists.txt @@ -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}") +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) \ No newline at end of file diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt new file mode 100644 index 000000000..426d46165 --- /dev/null +++ b/cmake/CMakeLists.txt @@ -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 $ +) + +add_library(c) + +set (LIBC_LINK_LIBRARIES + libc-bottom-half +) + +if(${BUILD_LIBC_TOP_HALF} STREQUAL "ON") + list(APPEND LIBC_LINK_LIBRARIES + libc-top-half + ) +endif() + +if(${MALLOC_IMPL} STREQUAL "dlmalloc") + list(APPEND LIBC_LINK_LIBRARIES + dlmalloc) +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 $ +) + +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}) + 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 . +) + +install( + DIRECTORY ${SYSROOT_SHARE_DIR} + DESTINATION share +) + +install( + DIRECTORY ${SYSROOT_LIB_DIR} + DESTINATION lib +) + +add_test(NAME check-metadata + COMMAND diff -wur + ${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} + --sysroot=${CMAKE_BINARY_DIR}/sysroot + -fsyntax-only + "-Wno#warnings" + ${CMAKE_BINARY_DIR}/sysroot/share/${MULTIARCH_TRIPLE}/include-all.c) diff --git a/cmake/dlmalloc/CMakeLists.txt b/cmake/dlmalloc/CMakeLists.txt new file mode 100644 index 000000000..04c139d26 --- /dev/null +++ b/cmake/dlmalloc/CMakeLists.txt @@ -0,0 +1,10 @@ +set(DLMALLOC_DIR ${PROJECT_SOURCE_DIR}/dlmalloc) + +add_library(dlmalloc OBJECT + ${DLMALLOC_DIR}/src/dlmalloc.c) + +target_include_directories(dlmalloc + PRIVATE + ${DLMALLOC_DIR}/include) + +add_dependencies(dlmalloc sysroot-headers) \ No newline at end of file diff --git a/cmake/global-compiler-options.cmake b/cmake/global-compiler-options.cmake new file mode 100644 index 000000000..05804d430 --- /dev/null +++ b/cmake/global-compiler-options.cmake @@ -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) + +# 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 +) + +# 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) diff --git a/cmake/libc-bottom-half/CMakeLists.txt b/cmake/libc-bottom-half/CMakeLists.txt new file mode 100644 index 000000000..88c731c79 --- /dev/null +++ b/cmake/libc-bottom-half/CMakeLists.txt @@ -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) + +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 + ${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) \ No newline at end of file diff --git a/cmake/libc-bottom-half/clocks/CMakeLists.txt b/cmake/libc-bottom-half/clocks/CMakeLists.txt new file mode 100644 index 000000000..2045cea92 --- /dev/null +++ b/cmake/libc-bottom-half/clocks/CMakeLists.txt @@ -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 $ +) diff --git a/cmake/libc-bottom-half/crt1/CMakeLists.txt b/cmake/libc-bottom-half/crt1/CMakeLists.txt new file mode 100644 index 000000000..95a778bee --- /dev/null +++ b/cmake/libc-bottom-half/crt1/CMakeLists.txt @@ -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 $ ${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() diff --git a/cmake/libc-bottom-half/getpid/CMakeLists.txt b/cmake/libc-bottom-half/getpid/CMakeLists.txt new file mode 100644 index 000000000..313213efb --- /dev/null +++ b/cmake/libc-bottom-half/getpid/CMakeLists.txt @@ -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 $ +) diff --git a/cmake/libc-bottom-half/mman/CMakeLists.txt b/cmake/libc-bottom-half/mman/CMakeLists.txt new file mode 100644 index 000000000..521746495 --- /dev/null +++ b/cmake/libc-bottom-half/mman/CMakeLists.txt @@ -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 $ +) diff --git a/cmake/libc-bottom-half/signal/CMakeLists.txt b/cmake/libc-bottom-half/signal/CMakeLists.txt new file mode 100644 index 000000000..c8dcfbd0b --- /dev/null +++ b/cmake/libc-bottom-half/signal/CMakeLists.txt @@ -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) diff --git a/cmake/libc-imports.cmake b/cmake/libc-imports.cmake new file mode 100644 index 000000000..f0db9e971 --- /dev/null +++ b/cmake/libc-imports.cmake @@ -0,0 +1,34 @@ +add_custom_command(OUTPUT ${SYSROOT_LIB_DIR}/libc.imports + 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 + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + 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 +) \ No newline at end of file diff --git a/cmake/libc-top-half/CMakeLists.txt b/cmake/libc-top-half/CMakeLists.txt new file mode 100644 index 000000000..495d09306 --- /dev/null +++ b/cmake/libc-top-half/CMakeLists.txt @@ -0,0 +1,263 @@ +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_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_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 + ${LIBC_TOP_HALF_MUSL_SRC_DIR}/thread/pthread_setcancelstate.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) \ No newline at end of file diff --git a/cmake/libc-top-half/musl/CMakeLists.txt b/cmake/libc-top-half/musl/CMakeLists.txt new file mode 100644 index 000000000..3caa04de4 --- /dev/null +++ b/cmake/libc-top-half/musl/CMakeLists.txt @@ -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 $ +) + +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 $ +) + + +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) \ No newline at end of file diff --git a/cmake/local-sysroot.cmake b/cmake/local-sysroot.cmake new file mode 100644 index 000000000..5e3f2d5df --- /dev/null +++ b/cmake/local-sysroot.cmake @@ -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) \ No newline at end of file diff --git a/cmake/predefined-macros.cmake b/cmake/predefined-macros.cmake new file mode 100644 index 000000000..f364eb117 --- /dev/null +++ b/cmake/predefined-macros.cmake @@ -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) \ No newline at end of file diff --git a/tools/gen-imports.py b/tools/gen-imports.py new file mode 100755 index 000000000..99ceea04f --- /dev/null +++ b/tools/gen-imports.py @@ -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) diff --git a/tools/gen-predefined-macros.py b/tools/gen-predefined-macros.py new file mode 100644 index 000000000..5cc688727 --- /dev/null +++ b/tools/gen-predefined-macros.py @@ -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)