From 2110e7cf85e1dbbcc4974707c64c6147b15d9bd2 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Sun, 20 Nov 2022 06:53:14 +0330 Subject: [PATCH] Everywhere: Add support for compilation under emscripten Co-Authored-By: Andrew Kaster --- AK/Platform.h | 8 +++++++ AK/StackInfo.cpp | 4 +++- Meta/Lagom/CMakeLists.txt | 24 +++++++++++++------ Tests/LibJS/test262-runner.cpp | 8 +++++-- .../LibCompress/BrotliDictionary.cpp | 8 +++++++ Userland/Libraries/LibCore/CMakeLists.txt | 2 +- Userland/Libraries/LibCore/MappedFile.cpp | 4 +++- Userland/Libraries/LibCore/System.cpp | 4 ++-- Userland/Libraries/LibTest/CrashTest.cpp | 4 ++-- 9 files changed, 50 insertions(+), 16 deletions(-) diff --git a/AK/Platform.h b/AK/Platform.h index 9208c4dcc0..6bd0082897 100644 --- a/AK/Platform.h +++ b/AK/Platform.h @@ -19,6 +19,10 @@ # define AK_ARCH_AARCH64 1 #endif +#ifdef __wasm32__ +# define AK_ARCH_WASM32 1 +#endif + #if (defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8) || defined(_WIN64) # define AK_ARCH_64_BIT #else @@ -83,6 +87,10 @@ #endif // clang-format on +#if defined(__EMSCRIPTEN__) +# define AK_OS_EMSCRIPTEN +#endif + #define ARCH(arch) (defined(AK_ARCH_##arch) && AK_ARCH_##arch) #if ARCH(I386) || ARCH(X86_64) diff --git a/AK/StackInfo.cpp b/AK/StackInfo.cpp index 7160f0e6a6..80e1d4271c 100644 --- a/AK/StackInfo.cpp +++ b/AK/StackInfo.cpp @@ -68,7 +68,9 @@ StackInfo::StackInfo() } m_base = top_of_stack - m_size; #else - VERIFY_NOT_REACHED(); +# pragma message "StackInfo not supported on this platform! Recursion checks and stack scans may not work properly" + m_size = (size_t)~0; + m_base = 0; #endif m_top = m_base + m_size; diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index 5b9730a77d..af7e4eb714 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -93,6 +93,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_INSTALL_MESSAGE NEVER) +if (EMSCRIPTEN) + set(CMAKE_EXECUTABLE_SUFFIX ".js") + add_compile_options(-gsource-map) + add_link_options(--emrun "SHELL:-s ALLOW_MEMORY_GROWTH") +endif() + if (ENABLE_ADDRESS_SANITIZER) add_compile_options(-fsanitize=address -fno-omit-frame-pointer) set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address") @@ -290,7 +296,7 @@ endif() add_library(LibC INTERFACE) add_library(LibCrypt INTERFACE) add_library(LibSystem INTERFACE) -if (NOT APPLE AND NOT ANDROID AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") +if (NOT APPLE AND NOT ANDROID AND NOT EMSCRIPTEN AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") target_link_libraries(LibCrypt INTERFACE crypt) # LibCore::Account uses crypt() but it's not in libcrypt on macOS endif() if (SERENITYOS) @@ -395,7 +401,7 @@ if (BUILD_LAGOM) # FIXME: Excluding arm64 is a temporary hack to circumvent a build problem # for Lagom on Apple M1 - if (NOT CMAKE_SYSTEM_PROCESSOR MATCHES "arm64") + if (NOT CMAKE_SYSTEM_PROCESSOR MATCHES "arm64" AND NOT EMSCRIPTEN) # FIXME: Create a LIBELF_SOURCES macro similar to AK file(GLOB LIBELF_SOURCES CONFIGURE_DEPENDS "../../Userland/Libraries/LibELF/*.cpp") # There's no way we can reliably make the dynamic loading classes cross platform @@ -446,12 +452,14 @@ if (BUILD_LAGOM) target_link_libraries(TestJson LibCore) # Lagom Utilities - add_executable(adjtime ../../Userland/Utilities/adjtime.cpp) - target_link_libraries(adjtime LibCore LibMain) + if (NOT EMSCRIPTEN) + add_executable(adjtime ../../Userland/Utilities/adjtime.cpp) + target_link_libraries(adjtime LibCore LibMain) + endif() # FIXME: Excluding arm64 is a temporary hack to circumvent a build problem # for Lagom on Apple M1 - if (NOT CMAKE_SYSTEM_PROCESSOR MATCHES "arm64") + if (NOT CMAKE_SYSTEM_PROCESSOR MATCHES "arm64" AND NOT EMSCRIPTEN) add_executable(disasm ../../Userland/Utilities/disasm.cpp) target_link_libraries(disasm LibCore LibELF LibX86 LibMain) endif() @@ -470,8 +478,10 @@ if (BUILD_LAGOM) add_executable(markdown-check ../../Userland/Utilities/markdown-check.cpp) target_link_libraries(markdown-check LibMarkdown LibMain) - add_executable(ntpquery ../../Userland/Utilities/ntpquery.cpp) - target_link_libraries(ntpquery LibCore LibMain) + if (NOT EMSCRIPTEN) + add_executable(ntpquery ../../Userland/Utilities/ntpquery.cpp) + target_link_libraries(ntpquery LibCore LibMain) + endif() add_executable(test262-runner ../../Tests/LibJS/test262-runner.cpp) target_link_libraries(test262-runner LibJS LibCore) diff --git a/Tests/LibJS/test262-runner.cpp b/Tests/LibJS/test262-runner.cpp index ea63d79822..302fbc6155 100644 --- a/Tests/LibJS/test262-runner.cpp +++ b/Tests/LibJS/test262-runner.cpp @@ -26,7 +26,7 @@ #include #include -#ifndef AK_OS_MACOS +#if !defined(AK_OS_MACOS) && !defined(AK_OS_EMSCRIPTEN) // Only used to disable core dumps # include #endif @@ -560,7 +560,11 @@ void __assertion_failed(char const* assertion) handle_failed_assert(assertion); } #else +# if AK_OS_EMSCRIPTEN +extern "C" __attribute__((__noreturn__)) void __assert_fail(char const* assertion, char const* file, int line, char const* function) +# else extern "C" __attribute__((__noreturn__)) void __assert_fail(char const* assertion, char const* file, unsigned int line, char const* function) +# endif { auto full_message = String::formatted("{}:{}: {}: Assertion `{}' failed.", file, line, function, assertion); handle_failed_assert(full_message.characters()); @@ -588,7 +592,7 @@ int main(int argc, char** argv) args_parser.add_option(disable_core_dumping, "Disable core dumping", "disable-core-dump", 0); args_parser.parse(argc, argv); -#ifndef AK_OS_MACOS +#if !defined(AK_OS_MACOS) && !defined(AK_OS_EMSCRIPTEN) if (disable_core_dumping && prctl(PR_SET_DUMPABLE, 0, 0) < 0) { perror("prctl(PR_SET_DUMPABLE)"); return exit_wrong_arguments; diff --git a/Userland/Libraries/LibCompress/BrotliDictionary.cpp b/Userland/Libraries/LibCompress/BrotliDictionary.cpp index 577012647e..15102202cd 100644 --- a/Userland/Libraries/LibCompress/BrotliDictionary.cpp +++ b/Userland/Libraries/LibCompress/BrotliDictionary.cpp @@ -13,13 +13,21 @@ extern u8 const brotli_dictionary_data[]; asm(".const_data\n" ".globl _brotli_dictionary_data\n" "_brotli_dictionary_data:\n"); +#elif defined(AK_OS_EMSCRIPTEN) +asm(".section .data, \"\",@\n" + ".global brotli_dictionary_data\n" + "brotli_dictionary_data:\n"); #else asm(".section .rodata\n" ".global brotli_dictionary_data\n" "brotli_dictionary_data:\n"); #endif asm(".incbin \"LibCompress/BrotliDictionaryData.bin\"\n" +#if (!defined(AK_OS_WINDOWS) && !defined(AK_OS_EMSCRIPTEN)) ".previous\n"); +#else +); +#endif namespace Compress { diff --git a/Userland/Libraries/LibCore/CMakeLists.txt b/Userland/Libraries/LibCore/CMakeLists.txt index 3337cc8e9a..62f3a3e91b 100644 --- a/Userland/Libraries/LibCore/CMakeLists.txt +++ b/Userland/Libraries/LibCore/CMakeLists.txt @@ -34,7 +34,7 @@ set(SOURCES UDPServer.cpp Version.cpp ) -if (NOT ANDROID AND NOT WIN32) +if (NOT ANDROID AND NOT WIN32 AND NOT EMSCRIPTEN) list(APPEND SOURCES Account.cpp FilePermissionsMask.cpp diff --git a/Userland/Libraries/LibCore/MappedFile.cpp b/Userland/Libraries/LibCore/MappedFile.cpp index b12573dae4..eca51683cb 100644 --- a/Userland/Libraries/LibCore/MappedFile.cpp +++ b/Userland/Libraries/LibCore/MappedFile.cpp @@ -44,7 +44,9 @@ MappedFile::MappedFile(void* ptr, size_t size) MappedFile::~MappedFile() { - MUST(Core::System::munmap(m_data, m_size)); + auto res = Core::System::munmap(m_data, m_size); + if (res.is_error()) + dbgln("Failed to unmap MappedFile (@ {:p}): {}", m_data, res.error()); } } diff --git a/Userland/Libraries/LibCore/System.cpp b/Userland/Libraries/LibCore/System.cpp index 2a0e345e6c..39602c5846 100644 --- a/Userland/Libraries/LibCore/System.cpp +++ b/Userland/Libraries/LibCore/System.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -29,6 +28,7 @@ # include # include # include +# include #endif #if defined(AK_OS_LINUX) && !defined(MFD_CLOEXEC) @@ -319,7 +319,7 @@ ErrorOr anon_create([[maybe_unused]] size_t size, [[maybe_unused]] int opti TRY(close(fd)); return Error::from_errno(saved_errno); } -#elif defined(AK_OS_MACOS) +#elif defined(AK_OS_MACOS) || defined(AK_OS_EMSCRIPTEN) struct timespec time; clock_gettime(CLOCK_REALTIME, &time); auto name = String::formatted("/shm-{}{}", (unsigned long)time.tv_sec, (unsigned long)time.tv_nsec); diff --git a/Userland/Libraries/LibTest/CrashTest.cpp b/Userland/Libraries/LibTest/CrashTest.cpp index f77a1de069..894511cd0d 100644 --- a/Userland/Libraries/LibTest/CrashTest.cpp +++ b/Userland/Libraries/LibTest/CrashTest.cpp @@ -12,7 +12,7 @@ #include #include -#ifndef AK_OS_MACOS +#if !defined(AK_OS_MACOS) && !defined(AK_OS_EMSCRIPTEN) # include #endif @@ -38,7 +38,7 @@ bool Crash::run(RunType run_type) perror("fork"); VERIFY_NOT_REACHED(); } else if (pid == 0) { -#ifndef AK_OS_MACOS +#if !defined(AK_OS_MACOS) && !defined(AK_OS_EMSCRIPTEN) if (prctl(PR_SET_DUMPABLE, 0, 0) < 0) perror("prctl(PR_SET_DUMPABLE)"); #endif