From 2d7df726fdeeeaa516a6e76fefa4fb5e19d45001 Mon Sep 17 00:00:00 2001 From: dave caruso Date: Thu, 8 Feb 2024 17:56:26 -0800 Subject: [PATCH] fix: get bun build working on window (#8712) * work on bundler * a * YAAAAYYAYAYAYYAYA * get some more bundler tests working * Update src/bundler/bundle_v2.zig * rev * ok * i converted the cmakelists into LF * personal review * we didnt win * okey they pass * revert :( * a --------- Co-authored-by: Jarred Sumner --- CMakeLists.txt | 2672 ++++++++++++------------ src/StandaloneModuleGraph.zig | 33 +- src/allocators.zig | 11 +- src/async/windows_event_loop.zig | 2 +- src/bun.js/api/bun/subprocess.zig | 8 +- src/bun.js/bindings/BunProcess.cpp | 8 +- src/bun.js/node/node_fs.zig | 9 +- src/bun.js/webcore/blob.zig | 2 +- src/bun.js/webcore/blob/ReadFile.zig | 13 +- src/bun.zig | 6 +- src/bundler/bundle_v2.zig | 93 +- src/cli/build_command.zig | 11 +- src/cli/install.ps1 | 19 +- src/cli/test_command.zig | 23 +- src/fs.zig | 10 + src/install/semver.zig | 4 +- src/js_lexer.zig | 2 +- src/options.zig | 27 +- src/resolver/resolve_path.zig | 12 +- src/resolver/resolver.zig | 11 +- src/string_immutable.zig | 6 +- src/string_mutable.zig | 2 +- test/bundler/bun-build-api.test.ts | 6 +- test/bundler/bundler_compile.test.ts | 12 +- test/bundler/bundler_npm.test.ts | 2 +- test/bundler/bundler_plugin.test.ts | 4 +- test/bundler/esbuild/default.test.ts | 11 +- test/bundler/esbuild/loader.test.ts | 3 + test/bundler/expectBundled.ts | 63 +- test/cli/test/bun-test.test.ts | 2 +- test/harness.ts | 4 + test/js/node/v8/v8-date-parser.test.js | 5 +- 32 files changed, 1617 insertions(+), 1479 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9fd51864c..30f0b5fe22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1337 +1,1337 @@ -cmake_minimum_required(VERSION 3.22) -cmake_policy(SET CMP0091 NEW) -cmake_policy(SET CMP0067 NEW) - -set(Bun_VERSION "1.0.26") -set(WEBKIT_TAG c3712c13dcdc091cfe4c7cb8f2c1fd16472e6f92) - -set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}") -message(STATUS "Configuring Bun ${Bun_VERSION} in ${BUN_WORKDIR}") - -# --- Build Type --- -if(NOT CMAKE_BUILD_TYPE) - message(WARNING "No CMAKE_BUILD_TYPE value specified, defaulting to Debug.\nSet a build type with -DCMAKE_BUILD_TYPE=") - set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build (Debug, Release)" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release)$") - message(FATAL_ERROR - "Invalid CMAKE_BUILD_TYPE value specified: ${CMAKE_BUILD_TYPE}\n" - "CMAKE_BUILD_TYPE must be Debug or Release.") - endif() - - message(STATUS "The CMake build type is: ${CMAKE_BUILD_TYPE}") -endif() - -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(DEBUG ON) - set(DEFAULT_ZIG_OPTIMIZE "Debug") - set(bun "bun-debug") - - # COMPILE_COMMANDS - set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -elseif(CMAKE_BUILD_TYPE STREQUAL "Release") - set(DEBUG OFF) - set(DEFAULT_ZIG_OPTIMIZE "ReleaseFast") - - if(WIN32) - # lld-link will strip it for you, so we can build directly to bun.exe - set(bun "bun") - - # TODO(@paperdave): Remove this - # it is enabled for the time being to make sure to catch more bugs in the experimental windows builds - set(DEFAULT_ZIG_OPTIMIZE "ReleaseSafe") - else() - set(bun "bun-profile") - endif() -endif() - -# --- LLVM --- -# This detection is a little overkill, but it ensures that the set LLVM_VERSION matches under -# any case possible. Sorry for the complexity... -# -# Bun and WebKit must be compiled with the same compiler, so we do as much as we can to ensure that -# the compiler used for the prebuilt WebKit, LLVM 16, is the one that we detect in this process. -# -# It has to be done before project() is called, so that CMake doesnt pick a compiler for us, but even then -# we do some extra work afterwards to double-check, and we will rerun BUN_FIND_LLVM if the compiler did not match. -# -# If the user passes -DLLVM_PREFIX, most of this logic is skipped, but we still warn if invalid. -set(LLVM_VERSION 16) - -macro(BUN_FIND_LLVM) - find_program( - _LLVM_CXX_PATH - NAMES clang++-${LLVM_VERSION} clang++ - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s clang++ binary. Please pass -DLLVM_PREFIX with the path to LLVM" - ) - - if(NOT _LLVM_CXX_PATH) - message(FATAL_ERROR "Could not find LLVM ${LLVM_VERSION}, search paths: ${PLATFORM_LLVM_SEARCH_PATHS}") - endif() - - set(CMAKE_CXX_COMPILER "${_LLVM_CXX_PATH}") - find_program( - _LLVM_C_PATH - NAMES clang-${LLVM_VERSION} clang - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s clang binary. Please pass -DLLVM_PREFIX with the path to LLVM" - ) - - if(NOT _LLVM_C_PATH) - message(FATAL_ERROR "Could not find LLVM ${LLVM_VERSION}, search paths: ${PLATFORM_LLVM_SEARCH_PATHS}") - endif() - - set(CMAKE_C_COMPILER "${_LLVM_C_PATH}") - - find_program( - STRIP - NAMES llvm-strip - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" - ) - find_program( - STRIP - NAMES strip - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" - ) - find_program( - DSYMUTIL - NAMES dsymutil - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s dsymutil binary" - ) - find_program( - AR - NAMES llvm-ar - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" - ) - find_program( - AR - NAMES ar - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" - ) - find_program( - RANLIB - NAMES llvm-ranlib - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" - ) - - execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE _tmp) - string(REGEX MATCH "version ([0-9]+)\\.([0-9]+)\\.([0-9]+)" CMAKE_CXX_COMPILER_VERSION "${_tmp}") - set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") -endmacro() - -if(UNIX) - if(LLVM_PREFIX) - set(PLATFORM_LLVM_SEARCH_PATHS ${LLVM_PREFIX}/bin) - else() - set(PLATFORM_LLVM_SEARCH_PATHS /usr/lib/llvm-${LLVM_VERSION}/bin /usr/lib/llvm${LLVM_VERSION}/bin /usr/bin /usr/local/bin) - - if(APPLE) - set(PLATFORM_LLVM_SEARCH_PATHS /opt/homebrew/opt/llvm@${LLVM_VERSION}/bin /opt/homebrew/bin ${PLATFORM_LLVM_SEARCH_PATHS}) - endif() - endif() - - if(CMAKE_CXX_COMPILER) - set(_LLVM_CXX_PATH "${CMAKE_CXX_COMPILER}") - endif() - - if(CMAKE_C_COMPILER) - set(_LLVM_C_PATH "${CMAKE_C_COMPILER}") - endif() - - BUN_FIND_LLVM() -else() - # Windows uses Clang-CL - # TODO: good configuration in this regard. -G Ninja will pick clang-cl if possible, which should be fine for most users. - if(NOT CMAKE_C_COMPILER) - set(CMAKE_C_COMPILER "clang-cl") - endif() - - if(NOT CMAKE_CXX_COMPILER) - set(CMAKE_CXX_COMPILER "clang-cl") - endif() - - find_program( - STRIP - NAMES llvm-strip - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" - ) - find_program( - AR - NAMES llvm-ar - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" - ) -endif() - -set(CMAKE_COLOR_DIAGNOSTICS ON) -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_C_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_C_STANDARD_REQUIRED ON) - -project(Bun VERSION "${Bun_VERSION}") - -# if(MSVC) -# message(FATAL_ERROR "Bun does not support building with MSVC. Please use `cmake -G Ninja` with LLVM ${LLVM_VERSION} and Ninja.") -# endif() - -# More effort to prevent using the wrong C++ compiler -if(UNIX) - if((NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR(NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${LLVM_VERSION}\.")) - # Attempt to auto-correct the compiler - message(STATUS "Compiler mismatch, attempting to auto-correct") - unset(_LLVM_CXX_PATH) - BUN_FIND_LLVM() - - if((NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR(NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${LLVM_VERSION}\.")) - message(WARNING "Expected LLVM ${LLVM_VERSION} as the C++ compiler, build may fail or break at runtime.") - endif() - endif() -endif() - -message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} at ${CMAKE_CXX_COMPILER}") - -# --- End LLVM --- -if(NOT WIN32) - set(SHELL "bash") - set(SCRIPT_EXTENSION "sh") -else() - set(SCRIPT_EXTENSION "ps1") - - # pwsh is the new powershell, powershell is the old one. - find_program(SHELL NAMES pwsh powershell) -endif() - -set(DEFAULT_ON_UNLESS_APPLE ON) - -if(APPLE) - set(DEFAULT_ON_UNLESS_APPLE OFF) -endif() - -set(CI OFF) - -if(DEFINED ENV{CI} OR DEFINED ENV{GITHUB_ACTIONS}) - set(CI ON) -endif() - -set(DEFAULT_USE_STATIC_LIBATOMIC ON) -set(DEFAULT_USE_DEBUG_JSC, OFF) - -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(DEFAULT_USE_DEBUG_JSC ON) -endif() - -if(WIN32) - set(DEFAULT_USE_DEBUG_JSC OFF) -endif() - -if(UNIX AND NOT APPLE) - execute_process(COMMAND cat /etc/os-release COMMAND head -n1 OUTPUT_VARIABLE LINUX_DISTRO) - - if(${LINUX_DISTRO} MATCHES "NAME=\"(Arch|Manjaro|Artix) Linux\"\n") - set(DEFAULT_USE_STATIC_LIBATOMIC OFF) - endif() -endif() - -# -- Build Flags -- -option(USE_STATIC_SQLITE "Statically link SQLite?" ${DEFAULT_ON_UNLESS_APPLE}) -option(USE_CUSTOM_ZLIB "Use Bun's recommended version of zlib" ON) -option(USE_CUSTOM_BORINGSSL "Use Bun's recommended version of BoringSSL" ON) -option(USE_CUSTOM_LIBARCHIVE "Use Bun's recommended version of libarchive" ON) -option(USE_CUSTOM_MIMALLOC "Use Bun's recommended version of Mimalloc" ON) -option(USE_CUSTOM_ZSTD "Use Bun's recommended version of zstd" ON) -option(USE_CUSTOM_CARES "Use Bun's recommended version of c-ares" ON) -option(USE_CUSTOM_BASE64 "Use Bun's recommended version of libbase64" ON) -option(USE_CUSTOM_LOLHTML "Use Bun's recommended version of lolhtml" ON) -option(USE_CUSTOM_TINYCC "Use Bun's recommended version of tinycc" ON) -option(USE_CUSTOM_LIBUV "Use Bun's recommended version of libuv (Windows only)" ON) -option(USE_CUSTOM_LSHPACK "Use Bun's recommended version of ls-hpack" ON) -option(USE_BASELINE_BUILD "Build Bun for baseline (older) CPUs" OFF) - -option(USE_VALGRIND "Build Bun with Valgrind support (Linux only)" OFF) - -option(ZIG_OPTIMIZE "Optimization level for Zig" ${DEFAULT_ZIG_OPTIMIZE}) -option(USE_DEBUG_JSC "Enable assertions and use a debug build of JavaScriptCore" ${DEFAULT_USE_DEBUG_JSC}) -option(USE_UNIFIED_SOURCES "Use unified sources to speed up the build" OFF) -option(USE_STATIC_LIBATOMIC "Statically link libatomic, requires the presence of libatomic.a" ${DEFAULT_USE_STATIC_LIBATOMIC}) - -if(USE_VALGRIND) - # Disable SIMD - set(USE_BASELINE_BUILD ON) - - if(ARCH STREQUAL "x86_64") - # This is for picohttpparser - # Valgrind cannot handle SSE4.2 instructions - add_compile_definitions("__SSE4_2__=0") - endif() -endif() - -if(NOT CANARY) - set(CANARY 0) -endif() - -if(NOT ZIG_OPTIMIZE) - set(ZIG_OPTIMIZE ${DEFAULT_ZIG_OPTIMIZE}) -endif() - -set(ERROR_LIMIT 100 CACHE STRING "Maximum number of errors to show when compiling C++ code") - -set(ARCH x86_64) - -if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|arm") - set(ARCH aarch64) -endif() - -if(NOT CPU_TARGET) - if(DEFINED ENV{CPU_TARGET}) - set(CPU_TARGET $ENV{CPU_TARGET}) - else() - set(CPU_TARGET "native" CACHE STRING "CPU target for the compiler" FORCE) - - if(ARCH STREQUAL "x86_64") - if(USE_BASELINE_BUILD) - set(CPU_TARGET "nehalem") - else() - set(CPU_TARGET "haswell") - endif() - endif() - endif() -endif() - -message(STATUS "Building for CPU Target: ${CPU_TARGET}") - -if(NOT ZIG_TARGET) - set(ZIG_TARGET "native") - - if(WIN32) - set(ZIG_TARGET "${ARCH}-windows-msvc") - endif() -endif() - -set(CONFIGURE_DEPENDS "CONFIGURE_DEPENDS") - -if(NO_CONFIGURE_DEPENDS) - set(CONFIGURE_DEPENDS "") -endif() - -# --- CLI Paths --- -set(REQUIRED_IF_NOT_ONLY_CPP_OR_LINK "") - -if(NOT BUN_CPP_ONLY AND NOT BUN_LINK_ONLY) - set(REQUIRED_IF_NOT_ONLY_CPP_OR_LINK "REQUIRED") -endif() - -# Zig Compiler -function(validate_zig validator_result_var item) - set(${validator_result_var} FALSE PARENT_SCOPE) - - # We will allow any valid zig compiler, as long as it contains some text from `zig zen` - # Ideally we would do a version or feature check, but that would be quite slow - execute_process(COMMAND ${item} zen OUTPUT_VARIABLE ZIG_ZEN_OUTPUT) - - if(ZIG_ZEN_OUTPUT MATCHES "Together we serve the users") - set(${validator_result_var} TRUE PARENT_SCOPE) - else() - set(${validator_result_var} FALSE PARENT_SCOPE) - endif() -endfunction() - -if(ZIG_COMPILER) - if(ZIG_COMPILER STREQUAL "system") - message(STATUS "Using system Zig compiler") - unset(ZIG_COMPILER_) - endif() - - find_program(ZIG_COMPILER_ zig ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to the Zig compiler" VALIDATOR validate_zig) - set(ZIG_COMPILER "${ZIG_COMPILER_}") - message(STATUS "Found Zig Compiler: ${ZIG_COMPILER}") -elseif(NOT BUN_CPP_ONLY AND NOT BUN_LINK_ONLY) - execute_process( - COMMAND "${SHELL}" - "${CMAKE_CURRENT_SOURCE_DIR}/scripts/download-zig.${SCRIPT_EXTENSION}" - ) - set(ZIG_COMPILER "${CMAKE_CURRENT_SOURCE_DIR}/.cache/zig/zig") - - if(WIN32) - set(ZIG_COMPILER "${ZIG_COMPILER}.exe") - endif() - - if(NOT EXISTS "${ZIG_COMPILER}") - unset(ZIG_COMPILER) - message(FATAL_ERROR "Auto-installation of Zig failed. Please pass -DZIG_COMPILER=system or a path to the Zig") - endif() - - message(STATUS "Installed Zig Compiler: ${ZIG_COMPILER}") - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "build.zig") -endif() - -# Bun -if(NOT WIN32) - find_program(BUN_EXECUTABLE bun ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to an already built release of Bun") - message(STATUS "Found Bun: ${BUN_EXECUTABLE}") -else() - set(BUN_EXECUTABLE "echo") -endif() - -# Prettier -find_program(PRETTIER prettier DOC "Path to prettier" PATHS ./node_modules/.bin ENV PATH) - -# Esbuild (TODO: switch these to "bun build") -find_program(ESBUILD esbuild DOC "Path to esbuild" PATHS ./node_modules/.bin ENV PATH) - -# Ruby (only needed for unified sources) -if(USE_UNIFIED_SOURCES) - # ruby 'WebKit/Source/WTF/Scripts/generate-unified-source-bundles.rb' source_list.txt --source-tree-path . --derived-sources-path build/unified-sources - find_program(RUBY ruby DOC "Path to ruby") -endif() - -# CCache -find_program(CCACHE_PROGRAM sccache) -find_program(CCACHE_PROGRAM ccache) - -if(CCACHE_PROGRAM) - set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") - set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") - message(STATUS "Using ccache: ${CCACHE_PROGRAM}") -endif() - -# --- WebKit --- -# WebKit is either prebuilt and distributed via NPM, or you can pass WEBKIT_DIR to use a local build. -# We cannot include their CMake build files (TODO: explain why, for now ask @paperdave why) -# -# On Unix, this will pull from NPM the single package that is needed and use that -if(WIN32) - set(STATIC_LIB_EXT "lib") - set(libJavaScriptCore "JavaScriptCore") - set(libWTF "WTF") -else() - set(STATIC_LIB_EXT "a") - set(libJavaScriptCore "libJavaScriptCore") - set(libWTF "libWTF") -endif() - -if(NOT WEBKIT_DIR) - set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "") - set(ASSERT_ENABLED "0") - - if(USE_DEBUG_JSC) - add_compile_definitions("BUN_DEBUG=1") - set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "-debug") - set(ASSERT_ENABLED "1") - elseif(NOT DEBUG AND NOT WIN32) - set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "-lto") - set(ASSERT_ENABLED "0") - endif() - - if(WIN32) - set(BUN_WEBKIT_PACKAGE_PLATFORM "windows") - elseif(APPLE) - set(BUN_WEBKIT_PACKAGE_PLATFORM "macos") - else() - set(BUN_WEBKIT_PACKAGE_PLATFORM "linux") - endif() - - if(ARCH STREQUAL "x86_64") - set(BUN_WEBKIT_PACKAGE_ARCH "amd64") - elseif(ARCH MATCHES "aarch64|arm64|arm") - set(BUN_WEBKIT_PACKAGE_ARCH "arm64") - endif() - - set(BUN_WEBKIT_PACKAGE_NAME "bun-webkit-${BUN_WEBKIT_PACKAGE_PLATFORM}-${BUN_WEBKIT_PACKAGE_ARCH}${BUN_WEBKIT_PACKAGE_NAME_SUFFIX}") - - message(STATUS "Using Pre-built WebKit: ${BUN_WEBKIT_PACKAGE_NAME}") - execute_process( - COMMAND "${SHELL}" - "${CMAKE_CURRENT_SOURCE_DIR}/scripts/download-webkit.${SCRIPT_EXTENSION}" - "${BUN_WORKDIR}/bun-webkit" - "${WEBKIT_TAG}" - "${BUN_WEBKIT_PACKAGE_NAME}" - WORKING_DIRECTORY ${BUN_WORKDIR} - ) - - if(NOT EXISTS "${BUN_WORKDIR}/bun-webkit") - message(FATAL_ERROR "Prebuilt WebKit package ${BUN_WEBKIT_PACKAGE_NAME} failed to install") - endif() - - set(WEBKIT_INCLUDE_DIR "${BUN_WORKDIR}/bun-webkit/include") - set(WEBKIT_LIB_DIR "${BUN_WORKDIR}/bun-webkit/lib") -elseif(WEBKIT_DIR STREQUAL "omit") - message(STATUS "Not using WebKit. This is only valid if you are only trying to build Zig code") -else() - # Expected to be WebKit/WebKitBuild/${CMAKE_BUILD_TYPE} - if(EXISTS "${WEBKIT_DIR}/cmakeconfig.h") - # You may need to run: - # make jsc-compile-debug jsc-copy-headers - include_directories( - "${WEBKIT_DIR}/" - "${WEBKIT_DIR}/JavaScriptCore/Headers/JavaScriptCore" - "${WEBKIT_DIR}/JavaScriptCore/PrivateHeaders" - "${WEBKIT_DIR}/bmalloc/Headers" - "${WEBKIT_DIR}/WTF/Headers" - ) - set(WEBKIT_LIB_DIR "${WEBKIT_DIR}/lib") - - if(USE_DEBUG_JSC) - add_compile_definitions("BUN_DEBUG=1") - set(ASSERT_ENABLED "1") - endif() - else() - if(NOT EXISTS "${WEBKIT_DIR}/lib/${libWTF}.${STATIC_LIB_EXT}" OR NOT EXISTS "${WEBKIT_DIR}/lib/${libJavaScriptCore}.${STATIC_LIB_EXT}") - if(WEBKIT_DIR MATCHES "src/bun.js/WebKit$") - message(FATAL_ERROR "WebKit directory ${WEBKIT_DIR} does not contain all the required files for Bun. Did you forget to init submodules?") - endif() - - message(FATAL_ERROR "WebKit directory ${WEBKIT_DIR} does not contain all the required files for Bun. Expected a path to the oven-sh/WebKit repository, or a path to a folder containing `include` and `lib`.") - endif() - - set(WEBKIT_INCLUDE_DIR "${WEBKIT_DIR}/include") - set(WEBKIT_LIB_DIR "${WEBKIT_DIR}/lib") - - message(STATUS "Using specified WebKit directory: ${WEBKIT_DIR}") - - set(ASSERT_ENABLED "0") - message(STATUS "WebKit assertions: OFF") - endif() -endif() - -# --- CMake Macros --- - -# Append the given dependencies to the source file -macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps) - set(_tmp) - get_source_file_property(_tmp ${_source} OBJECT_DEPENDS) - - if(NOT _tmp) - set(_tmp "") - endif() - - foreach(f ${_deps}) - list(APPEND _tmp "${f}") - endforeach() - - set_source_files_properties(${_source} PROPERTIES OBJECT_DEPENDS "${_tmp}") - unset(_tmp) -endmacro() - -# --- BUILD --- -set(BUN_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src") -set(BUN_DEPS_DIR "${BUN_SRC}/deps") -set(BUN_CODEGEN_SRC "${BUN_SRC}/codegen") - -if(NOT BUN_DEPS_OUT_DIR) - set(BUN_DEPS_OUT_DIR "${BUN_DEPS_DIR}") -endif() - -set(BUN_RAW_SOURCES, "") - -file(GLOB BUN_CPP ${CONFIGURE_DEPENDS} - "${BUN_SRC}/deps/*.cpp" - "${BUN_SRC}/io/*.cpp" - "${BUN_SRC}/bun.js/modules/*.cpp" - "${BUN_SRC}/bun.js/bindings/*.cpp" - "${BUN_SRC}/bun.js/bindings/webcore/*.cpp" - "${BUN_SRC}/bun.js/bindings/sqlite/*.cpp" - "${BUN_SRC}/bun.js/bindings/webcrypto/*.cpp" - "${BUN_SRC}/bun.js/bindings/webcrypto/*/*.cpp" - "${BUN_SRC}/deps/picohttpparser/picohttpparser.c" -) -list(APPEND BUN_RAW_SOURCES ${BUN_CPP}) - -# -- Brotli -- -set(BROTLI_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/deps/brotli") -file(GLOB BROTLI_FILES ${CONFIGURE_DEPENDS} - "${BROTLI_SRC}/common/*.c" - "${BROTLI_SRC}/enc/*.c" - "${BROTLI_SRC}/dec/*.c" -) -list(APPEND BUN_RAW_SOURCES ${BROTLI_FILES}) -include_directories("${BUN_DEPS_DIR}/brotli/include") - -# -- uSockets -- -set(USOCKETS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src") -file(GLOB USOCKETS_FILES ${CONFIGURE_DEPENDS} - "${USOCKETS_SRC}/*.c" - "${USOCKETS_SRC}/eventing/*.c" - "${USOCKETS_SRC}/internal/*.c" - "${USOCKETS_SRC}/crypto/*.c" - "${USOCKETS_SRC}/crypto/*.cpp" -) -list(APPEND BUN_RAW_SOURCES ${USOCKETS_FILES}) - -# --- Classes Generator --- -file(GLOB BUN_CLASSES_TS ${CONFIGURE_DEPENDS} - "${BUN_SRC}/bun.js/*.classes.ts" - "${BUN_SRC}/bun.js/api/*.classes.ts" - "${BUN_SRC}/bun.js/test/*.classes.ts" - "${BUN_SRC}/bun.js/webcore/*.classes.ts" - "${BUN_SRC}/bun.js/node/*.classes.ts" -) -add_custom_command( - OUTPUT "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureHeader.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMClientIsoSubspaces.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMIsoSubspaces.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureImpl.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" - COMMAND ${BUN_EXECUTABLE} "${BUN_CODEGEN_SRC}/generate-classes.ts" ${BUN_CLASSES_TS} "${BUN_WORKDIR}/codegen" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - MAIN_DEPENDENCY "${BUN_CODEGEN_SRC}/generate-classes.ts" - DEPENDS ${BUN_CLASSES_TS} - VERBATIM - COMMENT "Generating *.classes.ts bindings" -) -list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp") - -# --- JSSink Generator --- -add_custom_command( - OUTPUT "${BUN_WORKDIR}/codegen/JSSink.cpp" - "${BUN_WORKDIR}/codegen/JSSink.h" - COMMAND ${BUN_EXECUTABLE} "src/codegen/generate-jssink.ts" "${BUN_WORKDIR}/codegen" - VERBATIM - MAIN_DEPENDENCY "src/codegen/generate-jssink.ts" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Generating JSSink" -) -list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/JSSink.cpp") - -# --- .lut.h Generator --- -set(BUN_OBJECT_LUT_SOURCES - bun.js/bindings/BunObject.cpp - bun.js/bindings/ZigGlobalObject.lut.txt - bun.js/bindings/JSBuffer.cpp - bun.js/bindings/BunProcess.cpp - bun.js/bindings/ProcessBindingConstants.cpp - bun.js/bindings/ProcessBindingNatives.cpp -) -set(BUN_OBJECT_LUT_OUTPUTS "") -set(BUN_HASH_LUT_GENERATOR "${BUN_CODEGEN_SRC}/create-hash-table.ts") - -if(NOT BUN_LINK_ONLY) - macro(GENERATE_HASH_LUT _input _output _display_name) - if(NOT NO_CODEGEN) - add_custom_command( - OUTPUT ${_output} - MAIN_DEPENDENCY ${BUN_HASH_LUT_GENERATOR} - DEPENDS ${_input} - COMMAND ${BUN_EXECUTABLE} ${BUN_HASH_LUT_GENERATOR} ${_input} ${_output} - VERBATIM - COMMENT "Generating ${_display_name}" - ) - endif() - - list(APPEND BUN_OBJECT_LUT_OUTPUTS "${_output}") - - # list(APPEND Bun_HEADERS ${_output}) - WEBKIT_ADD_SOURCE_DEPENDENCIES(${_input} ${_output}) - endmacro() - - foreach(_file ${BUN_OBJECT_LUT_SOURCES}) - if(NOT EXISTS "${BUN_SRC}/${_file}") - message(FATAL_ERROR "Could not find ${_file} needed for LUT generation") - endif() - - get_filename_component(_name ${_file} NAME_WE) - - # workaround for ZigGlobalObject - if(_name MATCHES "ZigGlobalObject") - set(_name "ZigGlobalObject") - endif() - - GENERATE_HASH_LUT(${BUN_SRC}/${_file} ${BUN_WORKDIR}/codegen/${_name}.lut.h ${_name}.lut.h) - endforeach() - - WEBKIT_ADD_SOURCE_DEPENDENCIES(${BUN_SRC}/bun.js/bindings/ZigGlobalObject.cpp ${BUN_WORKDIR}/codegen/ZigGlobalObject.lut.h) -endif() - -# --- Identifier Cache --- -if(NOT NO_CODEGEN) - set(BUN_IDENTIFIER_CACHE_OUT - "${BUN_SRC}/js_lexer/id_continue_bitset.blob" - "${BUN_SRC}/js_lexer/id_continue_bitset.meta.blob" - "${BUN_SRC}/js_lexer/id_start_bitset.blob" - "${BUN_SRC}/js_lexer/id_start_bitset.meta.blob") - add_custom_command( - OUTPUT ${BUN_IDENTIFIER_CACHE_OUT} - MAIN_DEPENDENCY "${BUN_SRC}/js_lexer/identifier_data.zig" - DEPENDS "${BUN_SRC}/js_lexer/identifier_cache.zig" - COMMAND ${ZIG_COMPILER} run "${BUN_SRC}/js_lexer/identifier_data.zig" - VERBATIM - COMMENT "Building Identifier Cache" - ) -endif() - -# --- Bundled TS/JS --- -# Note: It's not worth doing this in parallel at the CMake/Ninja level, because this bundling -# requires all the JS files to be known, but also Bun will use all cores during bundling anyways. -if(NOT NO_CODEGEN) - file(GLOB BUN_TS_MODULES ${CONFIGURE_DEPENDS} - "${BUN_SRC}/js/node/*.ts" - "${BUN_SRC}/js/node/*.js" - "${BUN_SRC}/js/bun/*.js" - "${BUN_SRC}/js/bun/*.ts" - "${BUN_SRC}/js/thirdparty/*.js" - "${BUN_SRC}/js/thirdparty/*.ts" - "${BUN_SRC}/js/internal/*.js" - "${BUN_SRC}/js/internal/*.ts" - ) - file(GLOB BUN_TS_FUNCTIONS ${CONFIGURE_DEPENDS} "${BUN_SRC}/js/builtins/*.ts") - - file(GLOB CODEGEN_FILES ${CONFIGURE_DEPENDS} "${BUN_CODEGEN_SRC}/*.ts") - - add_custom_command( - OUTPUT - "${BUN_WORKDIR}/codegen/InternalModuleRegistryConstants.h" - "${BUN_WORKDIR}/codegen/InternalModuleRegistry+createInternalModuleById.h" - "${BUN_WORKDIR}/codegen/InternalModuleRegistry+enum.h" - "${BUN_WORKDIR}/codegen/InternalModuleRegistry+numberOfModules.h" - "${BUN_WORKDIR}/codegen/NativeModuleImpl.h" - "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" - "${BUN_WORKDIR}/codegen/SyntheticModuleType.h" - COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-modules.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" - DEPENDS ${BUN_TS_MODULES} ${CODEGEN_FILES} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Bundling JS modules" - ) -endif() - -WEBKIT_ADD_SOURCE_DEPENDENCIES( - "${BUN_SRC}/bun.js/bindings/InternalModuleRegistry.cpp" - "${BUN_WORKDIR}/codegen/InternalModuleRegistryConstants.h" -) - -add_custom_command( - OUTPUT "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp" - "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.h" - COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-functions.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" - DEPENDS ${BUN_TS_FUNCTIONS} ${CODEGEN_FILES} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Bundling JS builtin functions" -) -list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp") - -# --- Peechy API --- -# if(NOT NO_CODEGEN) -# add_custom_command( -# OUTPUT "${BUN_SRC}/api/schema.js" -# "${BUN_SRC}/api/schema.d.ts" -# "${BUN_SRC}/api/schema.zig" -# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" -# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/.bin/peechy" -# "--schema" "${BUN_SRC}/api/schema.peechy" -# "--esm" "${BUN_SRC}/api/schema.js" -# "--ts" "${BUN_SRC}/api/schema.d.ts" -# "--zig" "${BUN_SRC}/api/schema.zig" -# COMMAND "${ZIG_COMPILER}" "fmt" "src/api/schema.zig" -# COMMAND "${PRETTIER}" "--config=.prettierrc.cjs" "--write" "src/api/schema.js" "src/api/schema.d.ts" -# DEPENDS "${BUN_SRC}/api/schema.peechy" -# COMMENT "Building schema" -# ) -# add_custom_command( -# OUTPUT "${BUN_SRC}/analytics/analytics_schema.zig" -# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" -# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/.bin/peechy" -# "--schema" "${BUN_SRC}/analytics/schema.peechy" -# "--zig" "${BUN_SRC}/analytics/analytics_schema.zig" -# COMMAND "${ZIG_COMPILER}" "fmt" "${BUN_SRC}/analytics/analytics_schema.zig" -# DEPENDS "${BUN_SRC}/api/schema.peechy" -# COMMENT "Building analytics_schema.zig" -# ) -# endif() - -# --- Runtime.js --- -if(NOT NO_CODEGEN) - add_custom_command( - OUTPUT "src/fallback.out.js" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMAND "${ESBUILD}" "--target=esnext" "--bundle" "src/fallback.ts" "--format=iife" "--platform=browser" "--minify" "--outfile=src/fallback.out.js" - DEPENDS "src/fallback.ts" - ) -endif() - -# --- Zig Object --- -file(GLOB ZIG_FILES - "${BUN_SRC}/*.zig" - "${BUN_SRC}/*/*.zig" - "${BUN_SRC}/*/*/*.zig" - "${BUN_SRC}/*/*/*/*.zig" - "${BUN_SRC}/*/*/*/*/*.zig" -) - -if(NOT BUN_ZIG_OBJ) - set(BUN_ZIG_OBJ "${BUN_WORKDIR}/CMakeFiles/bun-zig.o") -endif() - -get_filename_component(BUN_ZIG_OBJ "${BUN_ZIG_OBJ}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") - -set(USES_TERMINAL_NOT_IN_CI "") - -if(NOT CI) - set(USES_TERMINAL_NOT_IN_CI "USES_TERMINAL") -endif() - -if(NOT BUN_LINK_ONLY AND NOT BUN_CPP_ONLY) - add_custom_command( - OUTPUT "${BUN_ZIG_OBJ}" - COMMAND - "${ZIG_COMPILER}" "build" "obj" - "-Doutput-file=${BUN_ZIG_OBJ}" - "-Dgenerated-code=${BUN_WORKDIR}/codegen" - "-Dversion=${Bun_VERSION}" - "-Dcanary=${CANARY}" - "-Doptimize=${ZIG_OPTIMIZE}" - "-Dcpu=${CPU_TARGET}" - "-Dtarget=${ZIG_TARGET}" - DEPENDS - "${CMAKE_CURRENT_SOURCE_DIR}/build.zig" - "${ZIG_FILES}" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" - "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" - "${BUN_IDENTIFIER_CACHE_OUT}" - "${BUN_SRC}/api/schema.zig" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Building zig code" - VERBATIM - - # This is here to show Zig's progress indicator - ${USES_TERMINAL_NOT_IN_CI} - ) -endif() - -if(WIN32) - list(APPEND BUN_RAW_SOURCES "${BUN_SRC}/bun.js/bindings/windows/musl-memmem.c") - include_directories("${BUN_SRC}/bun.js/bindings/windows") -endif() - -if(NOT BUN_CPP_ARCHIVE) - # TODO: unified sources - set(BUN_SOURCES ${BUN_RAW_SOURCES}) -else() - # used by ci - set(BUN_SOURCES "") - add_link_options("${BUN_CPP_ARCHIVE}") -endif() - -# -- Windows resources (app icon) -- -if(CANARY GREATER 0) - set(Bun_VERSION_WITH_TAG "${Bun_VERSION}-canary.${CANARY}") -else() - set(Bun_VERSION_WITH_TAG "${Bun_VERSION}") -endif() - -if(WIN32) - set(BUN_ICO_PATH "${BUN_SRC}/bun.ico") - configure_file("${BUN_SRC}/windows-app-info.rc" "${BUN_WORKDIR}/CMakeFiles/windows-app-info.rc") - list(APPEND BUN_SOURCES "${BUN_WORKDIR}/CMakeFiles/windows-app-info.rc") -endif() - -# -- The Buntime™️ --- -if(NOT BUN_CPP_ONLY) - add_executable(${bun} "${BUN_SOURCES}" "${BUN_ZIG_OBJ}") -else() - add_executable(${bun} "${BUN_SOURCES}") -endif() - -set_target_properties(${bun} PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS YES - CXX_VISIBILITY_PRESET hidden - C_STANDARD 17 - C_STANDARD_REQUIRED YES - VISIBILITY_INLINES_HIDDEN YES -) - -add_compile_definitions( - - # TODO: are all of these variables strictly necessary? - "_HAS_EXCEPTIONS=0" - "LIBUS_USE_OPENSSL=1" - "UWS_HTTPRESPONSE_NO_WRITEMARK=1" - "LIBUS_USE_BORINGSSL=1" - "WITH_BORINGSSL=1" - "STATICALLY_LINKED_WITH_JavaScriptCore=1" - "STATICALLY_LINKED_WITH_WTF=1" - "STATICALLY_LINKED_WITH_BMALLOC=1" - "BUILDING_WITH_CMAKE=1" - "JSC_OBJC_API_ENABLED=0" - "BUN_SINGLE_THREADED_PER_VM_ENTRY_SCOPE=1" - "NAPI_EXPERIMENTAL=ON" - "NOMINMAX" - "IS_BUILD" - "BUILDING_JSCONLY__" - "BUN_DYNAMIC_JS_LOAD_PATH=\"${BUN_WORKDIR}/js\"" -) - -if(NOT ASSERT_ENABLED) - add_compile_definitions("NDEBUG=1") -else() - add_compile_definitions("ASSERT_ENABLED=1") -endif() - -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/packages/ - ${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets - ${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/webcore - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/webcrypto - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/sqlite - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/modules - ${CMAKE_CURRENT_SOURCE_DIR}/src/js/builtins - ${CMAKE_CURRENT_SOURCE_DIR}/src/napi - ${CMAKE_CURRENT_SOURCE_DIR}/src/deps - ${CMAKE_CURRENT_SOURCE_DIR}/src/deps/picohttpparser - ${WEBKIT_INCLUDE_DIR} - "${BUN_WORKDIR}/codegen" -) - -# -- BUN_CPP_ONLY Target -if(NOT BUN_CPP_ARCHIVE) - if(BUN_CPP_ONLY) - if(NOT WIN32) - string(REPLACE ";" ".o\n " BUN_OBJECT_LIST "${BUN_SOURCES}.o") - string(REPLACE "${BUN_WORKDIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - write_file("${BUN_WORKDIR}/compile-cpp-only.sh" - "#!/usr/bin/env bash\n" - "# this file is generated in CMakeLists.txt\n" - "set -ex\n" - "OBJ_LIST=(\n ${BUN_OBJECT_LIST}\n)\n" - "ninja \${OBJ_LIST[@]} $@\n" - "\"${AR}\" rcvs bun-cpp-objects.a \${OBJ_LIST[@]}\n" - "echo '-> bun-cpp-objects.a'\n" - ) - else() - string(REPLACE ";" ".obj\",\n \"" BUN_OBJECT_LIST "\"${BUN_SOURCES}.obj\"") - string(REPLACE "rc.obj" "rc.res" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - string(REPLACE "${BUN_WORKDIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - write_file("${BUN_WORKDIR}/compile-cpp-only.ps1" - "# this file is generated in CMakeLists.txt\n" - "$ErrorActionPreference = \"Stop\"\n" - "$ObjectFiles=@(\n ${BUN_OBJECT_LIST}\n)\n" - "ninja @ObjectFiles @args\n" - "& \"${AR}\" rcvs bun-cpp-objects.a @ObjectFiles\n" - "Write-Host '-> bun-cpp-objects.a'\n" - ) - endif() - endif() -else() - set_target_properties(${bun} PROPERTIES LINKER_LANGUAGE CXX) -endif() - -# --- clang and linker flags --- -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - if(NOT WIN32) - target_compile_options(${bun} PUBLIC -g3 -O0 -gdwarf-4 - -Werror=return-type - -Werror=return-stack-address - -Werror=implicit-function-declaration - ) - else() - target_compile_options(${bun} PUBLIC /Od /Z7) - endif() - - add_compile_definitions("BUN_DEBUG=1") -elseif(CMAKE_BUILD_TYPE STREQUAL "Release") - if(NOT WIN32) - target_compile_options(${bun} PUBLIC -O3 -flto=full -emit-llvm -g1 - -Werror=return-type - -Werror=return-stack-address - -Werror=implicit-function-declaration - ) - else() - target_compile_options(${bun} PUBLIC /O2 -flto=full /DEBUG /Z7) - target_link_options(${bun} PUBLIC /LTCG /DEBUG) - endif() -endif() - -if(NOT CI AND NOT WIN32) - target_compile_options(${bun} PRIVATE -fdiagnostics-color=always) -endif() - -if(NOT CPU_TARGET STREQUAL "native") - # passing -march=native to clang will break older systems - # by default on x64, CPU_TARGET is set to "haswell" or "nehalem" depending on baseline - # on arm, this argument will not be passed. - target_compile_options(${bun} PUBLIC "-march=${CPU_TARGET}") -else() - if(APPLE AND ARCH STREQUAL "aarch64") - # On arm macOS, we can set it to a minimum of the M1 cpu set. this might be the default already. - target_compile_options(${bun} PUBLIC "-mcpu=apple-m1") - endif() -endif() - -target_compile_options(${bun} PUBLIC -ferror-limit=${ERROR_LIMIT}) - -if(WIN32) - add_compile_definitions( - "WIN32" - "_WINDOWS" - "WIN32_LEAN_AND_MEAN=1" - "_CRT_SECURE_NO_WARNINGS" - "BORINGSSL_NO_CXX=1" # lol - ) - - # set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") - set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") - - target_compile_options(${bun} PUBLIC "/EHsc" "/GR-") - target_link_options(${bun} PUBLIC "/STACK:0x1200000,0x100000") -else() - target_compile_options(${bun} PUBLIC - -fPIC - -mtune=${CPU_TARGET} - -fconstexpr-steps=1271242 - -fconstexpr-depth=27 - -fno-exceptions - -fvisibility=hidden - -fvisibility-inlines-hidden - -fno-rtti - -fno-omit-frame-pointer - ) - string(APPEND CMAKE_CXX_FLAGS " -std=c++2a") -endif() - -if(APPLE) - if(ARCH STREQUAL "x86_64") - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") - else() - set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") - endif() - - target_link_options(${bun} PUBLIC "-dead_strip") - target_link_options(${bun} PUBLIC "-dead_strip_dylibs") - target_link_options(${bun} PUBLIC "-Wl,-stack_size,0x1200000") - target_link_options(${bun} PUBLIC "-exported_symbols_list" "${BUN_SRC}/symbols.txt") - set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.txt") - - target_link_options(${bun} PUBLIC "-fno-keep-static-consts") - target_link_libraries(${bun} PRIVATE "resolv") -endif() - -if(UNIX AND NOT APPLE) - target_link_options(${bun} PUBLIC - "-fuse-ld=lld" - "-static-libstdc++" - "-static-libgcc" - "-fuse-ld=lld" - "-Wl,-z,now" - "-Wl,--as-needed" - "-Wl,--gc-sections" - "-Wl,-z,stack-size=12800000" - "-Wl,--wrap=fcntl" - "-Wl,--wrap=fcntl64" - "-Wl,--wrap=stat64" - "-Wl,--wrap=pow" - "-Wl,--wrap=exp" - "-Wl,--wrap=log" - "-Wl,--wrap=log2" - "-Wl,--wrap=lstat" - "-Wl,--wrap=stat" - "-Wl,--wrap=fstat" - "-Wl,--wrap=fstatat" - "-Wl,--wrap=lstat64" - "-Wl,--wrap=stat64" - "-Wl,--wrap=fstat64" - "-Wl,--wrap=fstatat64" - "-Wl,--wrap=mknod" - "-Wl,--wrap=mknodat" - "-Wl,--wrap=statx" - "-Wl,--compress-debug-sections=zlib" - "-Bsymbolics-functions" - "-rdynamic" - "-Wl,--dynamic-list=${BUN_SRC}/symbols.dyn" - "-Wl,--version-script=${BUN_SRC}/linker.lds" - ) - - target_link_libraries(${bun} PRIVATE "c") - target_link_libraries(${bun} PRIVATE "pthread") - target_link_libraries(${bun} PRIVATE "dl") - - if(NOT USE_STATIC_LIBATOMIC) - target_link_libraries(${bun} PUBLIC "libatomic.so") - else() - target_link_libraries(${bun} PRIVATE "libatomic.a") - endif() - - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicudata.a") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicui18n.a") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicuuc.a") - - set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/linker.lds") - set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.dyn") -endif() - -# --- ICU --- -if(APPLE) - # TODO: a much better check can be done to find this path - find_path( - ICU4C_DIR NAMES lib/libicudata.a - PATHS ENV PATH /usr/local/opt/icu4c /opt/homebrew/opt/icu4c - ) - find_path( - ICONV_DIR NAMES lib/libiconv.a - PATHS ENV PATH /usr/local/opt/libiconv /opt/homebrew/opt/libiconv - ) - - target_link_libraries(${bun} PRIVATE "icucore") - target_link_libraries(${bun} PRIVATE "${ICONV_DIR}/lib/libiconv.a") - target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicudata.a") - target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicui18n.a") - target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicuuc.a") -endif() - -# --- Stripped Binary "bun" -if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32 AND NOT ASSERT_ENABLED) - # add_custom_command( - # TARGET ${bun} - # POST_BUILD - # COMMAND ${DSYMUTIL} -o ${BUN_WORKDIR}/bun.dSYM ${BUN_WORKDIR}/${bun} - # COMMENT "Stripping Symbols" - # ) - add_custom_command( - TARGET ${bun} - POST_BUILD - COMMAND ${STRIP} -s -x -S -o ${BUN_WORKDIR}/bun ${BUN_WORKDIR}/${bun} - COMMENT "Stripping Symbols" - ) -endif() - -if(WIN32) - # Kill all instances of bun before linking. - add_custom_command( - TARGET ${bun} - PRE_BUILD - COMMAND - "powershell" - "/C" - "Stop-Process -Name '${bun}' -Force -ErrorAction SilentlyContinue; exit 0" - ) -endif() - -# --- Dependencies --- -if(USE_CUSTOM_ZLIB) - include_directories(${BUN_DEPS_DIR}/zlib) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/zlib.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libz.a") - endif() -else() - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_DIR}/zlib_maybethisworks.lib") - else() - find_package(ZLIB REQUIRED) - target_link_libraries(${bun} PRIVATE ZLIB::ZLIB) - endif() -endif() - -if(USE_CUSTOM_BORINGSSL) - include_directories(${BUN_DEPS_DIR}/boringssl/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/crypto.lib") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/ssl.lib") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/decrepit.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libcrypto.a") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libssl.a") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libdecrepit.a") - endif() -else() - include(FindBoringSSL) - FindBoringSSL(${bun}) -endif() - -if(USE_CUSTOM_LIBARCHIVE) - include_directories(${BUN_DEPS_DIR}/libarchive/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/archive.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libarchive.a") - endif() -else() - find_package(LibArchive REQUIRED) - target_link_libraries(${bun} PRIVATE LibArchive::LibArchive) -endif() - -if(USE_CUSTOM_MIMALLOC) - include_directories(${BUN_DEPS_DIR}/mimalloc/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/mimalloc.lib") - elseif(APPLE) - if(USE_DEBUG_JSC OR CMAKE_BUILD_TYPE STREQUAL "Debug") - message(STATUS "Using debug mimalloc") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc-debug.a") - else() - # https://github.com/microsoft/mimalloc/issues/512 - # Linking mimalloc via object file on macOS x64 can cause heap corruption - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc.a") - endif() - else() - if(USE_DEBUG_JSC OR CMAKE_BUILD_TYPE STREQUAL "Debug") - message(STATUS "Using debug mimalloc") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc-debug.a") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc.o") - endif() - endif() -else() - find_package(mimalloc REQUIRED) - target_link_libraries(${bun} PRIVATE mimalloc) -endif() - -if(USE_CUSTOM_ZSTD) - include_directories(${BUN_DEPS_DIR}/zstd/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/zstd.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libzstd.a") - endif() -else() - find_package(zstd CONFIG REQUIRED) - target_link_libraries(${bun} PRIVATE zstd::libzstd) -endif() - -if(USE_CUSTOM_CARES) - include_directories(${BUN_DEPS_DIR}/c-ares/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/cares.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libcares.a") - endif() -else() - find_package(c-ares CONFIG REQUIRED) - target_link_libraries(${bun} PRIVATE c-ares::cares) -endif() - -if(USE_CUSTOM_BASE64) - include_directories(${BUN_DEPS_DIR}/base64/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/base64.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libbase64.a") - endif() -else() - find_package(base64 REQUIRED) - target_link_libraries(${bun} PRIVATE base64::base64) -endif() - -if(USE_CUSTOM_TINYCC) - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/tcc.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libtcc.a") - endif() -else() - find_package(tinycc REQUIRED) - target_link_libraries(${bun} PRIVATE tinycc::tinycc) -endif() - -if(USE_CUSTOM_LOLHTML) - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/lolhtml.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/liblolhtml.a") - endif() -else() - find_package(lolhtml REQUIRED) - target_link_libraries(${bun} PRIVATE lolhtml::lolhtml) -endif() - -if(WIN32) - if(USE_CUSTOM_LIBUV) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libuv.lib") - include_directories(${bun} PRIVATE "${BUN_DEPS_DIR}/libuv/include") - else() - find_package(libuv CONFIG REQUIRED) - target_link_libraries(${bun} PRIVATE $,libuv::uv_a,libuv::uv>) - endif() -endif() - -if(USE_STATIC_SQLITE) - add_library(sqlite3 STATIC src/bun.js/bindings/sqlite/sqlite3.c) - target_include_directories(sqlite3 PUBLIC src/bun.js/bindings/sqlite) - target_compile_definitions(sqlite3 PRIVATE - "SQLITE_ENABLE_COLUMN_METADATA=" - "SQLITE_MAX_VARIABLE_NUMBER=250000" - "SQLITE_ENABLE_RTREE=1" - "SQLITE_ENABLE_FTS3=1" - "SQLITE_ENABLE_FTS3_PARENTHESIS=1" - "SQLITE_ENABLE_FTS5=1" - "SQLITE_ENABLE_JSON1=1" - ) - target_link_libraries(${bun} PRIVATE sqlite3) - message(STATUS "Using static sqlite3") - target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=0") -else() - message(STATUS "Using dynamicly linked sqlite3") - target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=1") -endif() - -if(USE_CUSTOM_LSHPACK) - include_directories(${BUN_DEPS_DIR}/ls-hpack) - if(WIN32) - include_directories(${BUN_DEPS_DIR}/ls-hpack/compat/queue) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/lshpack.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/liblshpack.a") - endif() -else() - find_package(lshpack REQUIRED) - target_link_libraries(${bun} PRIVATE lshpack) -endif() - -if(NOT WIN32) - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libWTF.a") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libJavaScriptCore.a") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libbmalloc.a") -else() - target_link_options(${bun} PRIVATE "-static") - target_link_libraries(${bun} PRIVATE - "${WEBKIT_LIB_DIR}/WTF.lib" - "${WEBKIT_LIB_DIR}/JavaScriptCore.lib" - "${WEBKIT_LIB_DIR}/sicudt.lib" - "${WEBKIT_LIB_DIR}/sicuin.lib" - "${WEBKIT_LIB_DIR}/sicuuc.lib" - winmm - bcrypt - ntdll - ucrt - userenv - dbghelp - wsock32 # ws2_32 required by TransmitFile aka sendfile on windows - ) -endif() - -if(WIN32) - # delayimp -delayload:shell32.dll -delayload:ole32.dll -endif() - -if(BUN_LINK_ONLY) - message(STATUS "NOTE: BUN_LINK_ONLY is ON, this build config will only link the Bun executable") -endif() - -if(BUN_CPP_ONLY) - message(STATUS "NOTE: BUN_CPP_ONLY is ON, this build will only work with 'compile-cpp-only.${SCRIPT_EXTENSION}'") -endif() - -if(NO_CODEGEN) - message(STATUS "NOTE: NO_CODEGEN is ON, this build expects ./codegen to exist") +cmake_minimum_required(VERSION 3.22) +cmake_policy(SET CMP0091 NEW) +cmake_policy(SET CMP0067 NEW) + +set(Bun_VERSION "1.0.26") +set(WEBKIT_TAG c3712c13dcdc091cfe4c7cb8f2c1fd16472e6f92) + +set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}") +message(STATUS "Configuring Bun ${Bun_VERSION} in ${BUN_WORKDIR}") + +# --- Build Type --- +if(NOT CMAKE_BUILD_TYPE) + message(WARNING "No CMAKE_BUILD_TYPE value specified, defaulting to Debug.\nSet a build type with -DCMAKE_BUILD_TYPE=") + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build (Debug, Release)" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release)$") + message(FATAL_ERROR + "Invalid CMAKE_BUILD_TYPE value specified: ${CMAKE_BUILD_TYPE}\n" + "CMAKE_BUILD_TYPE must be Debug or Release.") + endif() + + message(STATUS "The CMake build type is: ${CMAKE_BUILD_TYPE}") +endif() + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(DEBUG ON) + set(DEFAULT_ZIG_OPTIMIZE "Debug") + set(bun "bun-debug") + + # COMPILE_COMMANDS + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +elseif(CMAKE_BUILD_TYPE STREQUAL "Release") + set(DEBUG OFF) + set(DEFAULT_ZIG_OPTIMIZE "ReleaseFast") + + if(WIN32) + # lld-link will strip it for you, so we can build directly to bun.exe + set(bun "bun") + + # TODO(@paperdave): Remove this + # it is enabled for the time being to make sure to catch more bugs in the experimental windows builds + set(DEFAULT_ZIG_OPTIMIZE "ReleaseSafe") + else() + set(bun "bun-profile") + endif() +endif() + +# --- LLVM --- +# This detection is a little overkill, but it ensures that the set LLVM_VERSION matches under +# any case possible. Sorry for the complexity... +# +# Bun and WebKit must be compiled with the same compiler, so we do as much as we can to ensure that +# the compiler used for the prebuilt WebKit, LLVM 16, is the one that we detect in this process. +# +# It has to be done before project() is called, so that CMake doesnt pick a compiler for us, but even then +# we do some extra work afterwards to double-check, and we will rerun BUN_FIND_LLVM if the compiler did not match. +# +# If the user passes -DLLVM_PREFIX, most of this logic is skipped, but we still warn if invalid. +set(LLVM_VERSION 16) + +macro(BUN_FIND_LLVM) + find_program( + _LLVM_CXX_PATH + NAMES clang++-${LLVM_VERSION} clang++ + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s clang++ binary. Please pass -DLLVM_PREFIX with the path to LLVM" + ) + + if(NOT _LLVM_CXX_PATH) + message(FATAL_ERROR "Could not find LLVM ${LLVM_VERSION}, search paths: ${PLATFORM_LLVM_SEARCH_PATHS}") + endif() + + set(CMAKE_CXX_COMPILER "${_LLVM_CXX_PATH}") + find_program( + _LLVM_C_PATH + NAMES clang-${LLVM_VERSION} clang + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s clang binary. Please pass -DLLVM_PREFIX with the path to LLVM" + ) + + if(NOT _LLVM_C_PATH) + message(FATAL_ERROR "Could not find LLVM ${LLVM_VERSION}, search paths: ${PLATFORM_LLVM_SEARCH_PATHS}") + endif() + + set(CMAKE_C_COMPILER "${_LLVM_C_PATH}") + + find_program( + STRIP + NAMES llvm-strip + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" + ) + find_program( + STRIP + NAMES strip + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" + ) + find_program( + DSYMUTIL + NAMES dsymutil + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s dsymutil binary" + ) + find_program( + AR + NAMES llvm-ar + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" + ) + find_program( + AR + NAMES ar + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" + ) + find_program( + RANLIB + NAMES llvm-ranlib + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" + ) + + execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE _tmp) + string(REGEX MATCH "version ([0-9]+)\\.([0-9]+)\\.([0-9]+)" CMAKE_CXX_COMPILER_VERSION "${_tmp}") + set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") +endmacro() + +if(UNIX) + if(LLVM_PREFIX) + set(PLATFORM_LLVM_SEARCH_PATHS ${LLVM_PREFIX}/bin) + else() + set(PLATFORM_LLVM_SEARCH_PATHS /usr/lib/llvm-${LLVM_VERSION}/bin /usr/lib/llvm${LLVM_VERSION}/bin /usr/bin /usr/local/bin) + + if(APPLE) + set(PLATFORM_LLVM_SEARCH_PATHS /opt/homebrew/opt/llvm@${LLVM_VERSION}/bin /opt/homebrew/bin ${PLATFORM_LLVM_SEARCH_PATHS}) + endif() + endif() + + if(CMAKE_CXX_COMPILER) + set(_LLVM_CXX_PATH "${CMAKE_CXX_COMPILER}") + endif() + + if(CMAKE_C_COMPILER) + set(_LLVM_C_PATH "${CMAKE_C_COMPILER}") + endif() + + BUN_FIND_LLVM() +else() + # Windows uses Clang-CL + # TODO: good configuration in this regard. -G Ninja will pick clang-cl if possible, which should be fine for most users. + if(NOT CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "clang-cl") + endif() + + if(NOT CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "clang-cl") + endif() + + find_program( + STRIP + NAMES llvm-strip + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" + ) + find_program( + AR + NAMES llvm-ar + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" + ) +endif() + +set(CMAKE_COLOR_DIAGNOSTICS ON) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_C_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD_REQUIRED ON) + +project(Bun VERSION "${Bun_VERSION}") + +# if(MSVC) +# message(FATAL_ERROR "Bun does not support building with MSVC. Please use `cmake -G Ninja` with LLVM ${LLVM_VERSION} and Ninja.") +# endif() + +# More effort to prevent using the wrong C++ compiler +if(UNIX) + if((NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR(NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${LLVM_VERSION}\.")) + # Attempt to auto-correct the compiler + message(STATUS "Compiler mismatch, attempting to auto-correct") + unset(_LLVM_CXX_PATH) + BUN_FIND_LLVM() + + if((NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR(NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${LLVM_VERSION}\.")) + message(WARNING "Expected LLVM ${LLVM_VERSION} as the C++ compiler, build may fail or break at runtime.") + endif() + endif() +endif() + +message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} at ${CMAKE_CXX_COMPILER}") + +# --- End LLVM --- +if(NOT WIN32) + set(SHELL "bash") + set(SCRIPT_EXTENSION "sh") +else() + set(SCRIPT_EXTENSION "ps1") + + # pwsh is the new powershell, powershell is the old one. + find_program(SHELL NAMES pwsh powershell) +endif() + +set(DEFAULT_ON_UNLESS_APPLE ON) + +if(APPLE) + set(DEFAULT_ON_UNLESS_APPLE OFF) +endif() + +set(CI OFF) + +if(DEFINED ENV{CI} OR DEFINED ENV{GITHUB_ACTIONS}) + set(CI ON) +endif() + +set(DEFAULT_USE_STATIC_LIBATOMIC ON) +set(DEFAULT_USE_DEBUG_JSC, OFF) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(DEFAULT_USE_DEBUG_JSC ON) +endif() + +if(WIN32) + set(DEFAULT_USE_DEBUG_JSC OFF) +endif() + +if(UNIX AND NOT APPLE) + execute_process(COMMAND cat /etc/os-release COMMAND head -n1 OUTPUT_VARIABLE LINUX_DISTRO) + + if(${LINUX_DISTRO} MATCHES "NAME=\"(Arch|Manjaro|Artix) Linux\"\n") + set(DEFAULT_USE_STATIC_LIBATOMIC OFF) + endif() +endif() + +# -- Build Flags -- +option(USE_STATIC_SQLITE "Statically link SQLite?" ${DEFAULT_ON_UNLESS_APPLE}) +option(USE_CUSTOM_ZLIB "Use Bun's recommended version of zlib" ON) +option(USE_CUSTOM_BORINGSSL "Use Bun's recommended version of BoringSSL" ON) +option(USE_CUSTOM_LIBARCHIVE "Use Bun's recommended version of libarchive" ON) +option(USE_CUSTOM_MIMALLOC "Use Bun's recommended version of Mimalloc" ON) +option(USE_CUSTOM_ZSTD "Use Bun's recommended version of zstd" ON) +option(USE_CUSTOM_CARES "Use Bun's recommended version of c-ares" ON) +option(USE_CUSTOM_BASE64 "Use Bun's recommended version of libbase64" ON) +option(USE_CUSTOM_LOLHTML "Use Bun's recommended version of lolhtml" ON) +option(USE_CUSTOM_TINYCC "Use Bun's recommended version of tinycc" ON) +option(USE_CUSTOM_LIBUV "Use Bun's recommended version of libuv (Windows only)" ON) +option(USE_CUSTOM_LSHPACK "Use Bun's recommended version of ls-hpack" ON) +option(USE_BASELINE_BUILD "Build Bun for baseline (older) CPUs" OFF) + +option(USE_VALGRIND "Build Bun with Valgrind support (Linux only)" OFF) + +option(ZIG_OPTIMIZE "Optimization level for Zig" ${DEFAULT_ZIG_OPTIMIZE}) +option(USE_DEBUG_JSC "Enable assertions and use a debug build of JavaScriptCore" ${DEFAULT_USE_DEBUG_JSC}) +option(USE_UNIFIED_SOURCES "Use unified sources to speed up the build" OFF) +option(USE_STATIC_LIBATOMIC "Statically link libatomic, requires the presence of libatomic.a" ${DEFAULT_USE_STATIC_LIBATOMIC}) + +if(USE_VALGRIND) + # Disable SIMD + set(USE_BASELINE_BUILD ON) + + if(ARCH STREQUAL "x86_64") + # This is for picohttpparser + # Valgrind cannot handle SSE4.2 instructions + add_compile_definitions("__SSE4_2__=0") + endif() +endif() + +if(NOT CANARY) + set(CANARY 0) +endif() + +if(NOT ZIG_OPTIMIZE) + set(ZIG_OPTIMIZE ${DEFAULT_ZIG_OPTIMIZE}) +endif() + +set(ERROR_LIMIT 100 CACHE STRING "Maximum number of errors to show when compiling C++ code") + +set(ARCH x86_64) + +if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|arm") + set(ARCH aarch64) +endif() + +if(NOT CPU_TARGET) + if(DEFINED ENV{CPU_TARGET}) + set(CPU_TARGET $ENV{CPU_TARGET}) + else() + set(CPU_TARGET "native" CACHE STRING "CPU target for the compiler" FORCE) + + if(ARCH STREQUAL "x86_64") + if(USE_BASELINE_BUILD) + set(CPU_TARGET "nehalem") + else() + set(CPU_TARGET "haswell") + endif() + endif() + endif() +endif() + +message(STATUS "Building for CPU Target: ${CPU_TARGET}") + +if(NOT ZIG_TARGET) + set(ZIG_TARGET "native") + + if(WIN32) + set(ZIG_TARGET "${ARCH}-windows-msvc") + endif() +endif() + +set(CONFIGURE_DEPENDS "CONFIGURE_DEPENDS") + +if(NO_CONFIGURE_DEPENDS) + set(CONFIGURE_DEPENDS "") +endif() + +# --- CLI Paths --- +set(REQUIRED_IF_NOT_ONLY_CPP_OR_LINK "") + +if(NOT BUN_CPP_ONLY AND NOT BUN_LINK_ONLY) + set(REQUIRED_IF_NOT_ONLY_CPP_OR_LINK "REQUIRED") +endif() + +# Zig Compiler +function(validate_zig validator_result_var item) + set(${validator_result_var} FALSE PARENT_SCOPE) + + # We will allow any valid zig compiler, as long as it contains some text from `zig zen` + # Ideally we would do a version or feature check, but that would be quite slow + execute_process(COMMAND ${item} zen OUTPUT_VARIABLE ZIG_ZEN_OUTPUT) + + if(ZIG_ZEN_OUTPUT MATCHES "Together we serve the users") + set(${validator_result_var} TRUE PARENT_SCOPE) + else() + set(${validator_result_var} FALSE PARENT_SCOPE) + endif() +endfunction() + +if(ZIG_COMPILER) + if(ZIG_COMPILER STREQUAL "system") + message(STATUS "Using system Zig compiler") + unset(ZIG_COMPILER_) + endif() + + find_program(ZIG_COMPILER_ zig ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to the Zig compiler" VALIDATOR validate_zig) + set(ZIG_COMPILER "${ZIG_COMPILER_}") + message(STATUS "Found Zig Compiler: ${ZIG_COMPILER}") +elseif(NOT BUN_CPP_ONLY AND NOT BUN_LINK_ONLY) + execute_process( + COMMAND "${SHELL}" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/download-zig.${SCRIPT_EXTENSION}" + ) + set(ZIG_COMPILER "${CMAKE_CURRENT_SOURCE_DIR}/.cache/zig/zig") + + if(WIN32) + set(ZIG_COMPILER "${ZIG_COMPILER}.exe") + endif() + + if(NOT EXISTS "${ZIG_COMPILER}") + unset(ZIG_COMPILER) + message(FATAL_ERROR "Auto-installation of Zig failed. Please pass -DZIG_COMPILER=system or a path to the Zig") + endif() + + message(STATUS "Installed Zig Compiler: ${ZIG_COMPILER}") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "build.zig") +endif() + +# Bun +if(NOT WIN32) + find_program(BUN_EXECUTABLE bun ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to an already built release of Bun") + message(STATUS "Found Bun: ${BUN_EXECUTABLE}") +else() + set(BUN_EXECUTABLE "echo") +endif() + +# Prettier +find_program(PRETTIER prettier DOC "Path to prettier" PATHS ./node_modules/.bin ENV PATH) + +# Esbuild (TODO: switch these to "bun build") +find_program(ESBUILD esbuild DOC "Path to esbuild" PATHS ./node_modules/.bin ENV PATH) + +# Ruby (only needed for unified sources) +if(USE_UNIFIED_SOURCES) + # ruby 'WebKit/Source/WTF/Scripts/generate-unified-source-bundles.rb' source_list.txt --source-tree-path . --derived-sources-path build/unified-sources + find_program(RUBY ruby DOC "Path to ruby") +endif() + +# CCache +find_program(CCACHE_PROGRAM sccache) +find_program(CCACHE_PROGRAM ccache) + +if(CCACHE_PROGRAM) + set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") + set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") + message(STATUS "Using ccache: ${CCACHE_PROGRAM}") +endif() + +# --- WebKit --- +# WebKit is either prebuilt and distributed via NPM, or you can pass WEBKIT_DIR to use a local build. +# We cannot include their CMake build files (TODO: explain why, for now ask @paperdave why) +# +# On Unix, this will pull from NPM the single package that is needed and use that +if(WIN32) + set(STATIC_LIB_EXT "lib") + set(libJavaScriptCore "JavaScriptCore") + set(libWTF "WTF") +else() + set(STATIC_LIB_EXT "a") + set(libJavaScriptCore "libJavaScriptCore") + set(libWTF "libWTF") +endif() + +if(NOT WEBKIT_DIR) + set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "") + set(ASSERT_ENABLED "0") + + if(USE_DEBUG_JSC) + add_compile_definitions("BUN_DEBUG=1") + set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "-debug") + set(ASSERT_ENABLED "1") + elseif(NOT DEBUG AND NOT WIN32) + set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "-lto") + set(ASSERT_ENABLED "0") + endif() + + if(WIN32) + set(BUN_WEBKIT_PACKAGE_PLATFORM "windows") + elseif(APPLE) + set(BUN_WEBKIT_PACKAGE_PLATFORM "macos") + else() + set(BUN_WEBKIT_PACKAGE_PLATFORM "linux") + endif() + + if(ARCH STREQUAL "x86_64") + set(BUN_WEBKIT_PACKAGE_ARCH "amd64") + elseif(ARCH MATCHES "aarch64|arm64|arm") + set(BUN_WEBKIT_PACKAGE_ARCH "arm64") + endif() + + set(BUN_WEBKIT_PACKAGE_NAME "bun-webkit-${BUN_WEBKIT_PACKAGE_PLATFORM}-${BUN_WEBKIT_PACKAGE_ARCH}${BUN_WEBKIT_PACKAGE_NAME_SUFFIX}") + + message(STATUS "Using Pre-built WebKit: ${BUN_WEBKIT_PACKAGE_NAME}") + execute_process( + COMMAND "${SHELL}" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/download-webkit.${SCRIPT_EXTENSION}" + "${BUN_WORKDIR}/bun-webkit" + "${WEBKIT_TAG}" + "${BUN_WEBKIT_PACKAGE_NAME}" + WORKING_DIRECTORY ${BUN_WORKDIR} + ) + + if(NOT EXISTS "${BUN_WORKDIR}/bun-webkit") + message(FATAL_ERROR "Prebuilt WebKit package ${BUN_WEBKIT_PACKAGE_NAME} failed to install") + endif() + + set(WEBKIT_INCLUDE_DIR "${BUN_WORKDIR}/bun-webkit/include") + set(WEBKIT_LIB_DIR "${BUN_WORKDIR}/bun-webkit/lib") +elseif(WEBKIT_DIR STREQUAL "omit") + message(STATUS "Not using WebKit. This is only valid if you are only trying to build Zig code") +else() + # Expected to be WebKit/WebKitBuild/${CMAKE_BUILD_TYPE} + if(EXISTS "${WEBKIT_DIR}/cmakeconfig.h") + # You may need to run: + # make jsc-compile-debug jsc-copy-headers + include_directories( + "${WEBKIT_DIR}/" + "${WEBKIT_DIR}/JavaScriptCore/Headers/JavaScriptCore" + "${WEBKIT_DIR}/JavaScriptCore/PrivateHeaders" + "${WEBKIT_DIR}/bmalloc/Headers" + "${WEBKIT_DIR}/WTF/Headers" + ) + set(WEBKIT_LIB_DIR "${WEBKIT_DIR}/lib") + + if(USE_DEBUG_JSC) + add_compile_definitions("BUN_DEBUG=1") + set(ASSERT_ENABLED "1") + endif() + else() + if(NOT EXISTS "${WEBKIT_DIR}/lib/${libWTF}.${STATIC_LIB_EXT}" OR NOT EXISTS "${WEBKIT_DIR}/lib/${libJavaScriptCore}.${STATIC_LIB_EXT}") + if(WEBKIT_DIR MATCHES "src/bun.js/WebKit$") + message(FATAL_ERROR "WebKit directory ${WEBKIT_DIR} does not contain all the required files for Bun. Did you forget to init submodules?") + endif() + + message(FATAL_ERROR "WebKit directory ${WEBKIT_DIR} does not contain all the required files for Bun. Expected a path to the oven-sh/WebKit repository, or a path to a folder containing `include` and `lib`.") + endif() + + set(WEBKIT_INCLUDE_DIR "${WEBKIT_DIR}/include") + set(WEBKIT_LIB_DIR "${WEBKIT_DIR}/lib") + + message(STATUS "Using specified WebKit directory: ${WEBKIT_DIR}") + + set(ASSERT_ENABLED "0") + message(STATUS "WebKit assertions: OFF") + endif() +endif() + +# --- CMake Macros --- + +# Append the given dependencies to the source file +macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps) + set(_tmp) + get_source_file_property(_tmp ${_source} OBJECT_DEPENDS) + + if(NOT _tmp) + set(_tmp "") + endif() + + foreach(f ${_deps}) + list(APPEND _tmp "${f}") + endforeach() + + set_source_files_properties(${_source} PROPERTIES OBJECT_DEPENDS "${_tmp}") + unset(_tmp) +endmacro() + +# --- BUILD --- +set(BUN_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src") +set(BUN_DEPS_DIR "${BUN_SRC}/deps") +set(BUN_CODEGEN_SRC "${BUN_SRC}/codegen") + +if(NOT BUN_DEPS_OUT_DIR) + set(BUN_DEPS_OUT_DIR "${BUN_DEPS_DIR}") +endif() + +set(BUN_RAW_SOURCES, "") + +file(GLOB BUN_CPP ${CONFIGURE_DEPENDS} + "${BUN_SRC}/deps/*.cpp" + "${BUN_SRC}/io/*.cpp" + "${BUN_SRC}/bun.js/modules/*.cpp" + "${BUN_SRC}/bun.js/bindings/*.cpp" + "${BUN_SRC}/bun.js/bindings/webcore/*.cpp" + "${BUN_SRC}/bun.js/bindings/sqlite/*.cpp" + "${BUN_SRC}/bun.js/bindings/webcrypto/*.cpp" + "${BUN_SRC}/bun.js/bindings/webcrypto/*/*.cpp" + "${BUN_SRC}/deps/picohttpparser/picohttpparser.c" +) +list(APPEND BUN_RAW_SOURCES ${BUN_CPP}) + +# -- Brotli -- +set(BROTLI_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/deps/brotli") +file(GLOB BROTLI_FILES ${CONFIGURE_DEPENDS} + "${BROTLI_SRC}/common/*.c" + "${BROTLI_SRC}/enc/*.c" + "${BROTLI_SRC}/dec/*.c" +) +list(APPEND BUN_RAW_SOURCES ${BROTLI_FILES}) +include_directories("${BUN_DEPS_DIR}/brotli/include") + +# -- uSockets -- +set(USOCKETS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src") +file(GLOB USOCKETS_FILES ${CONFIGURE_DEPENDS} + "${USOCKETS_SRC}/*.c" + "${USOCKETS_SRC}/eventing/*.c" + "${USOCKETS_SRC}/internal/*.c" + "${USOCKETS_SRC}/crypto/*.c" + "${USOCKETS_SRC}/crypto/*.cpp" +) +list(APPEND BUN_RAW_SOURCES ${USOCKETS_FILES}) + +# --- Classes Generator --- +file(GLOB BUN_CLASSES_TS ${CONFIGURE_DEPENDS} + "${BUN_SRC}/bun.js/*.classes.ts" + "${BUN_SRC}/bun.js/api/*.classes.ts" + "${BUN_SRC}/bun.js/test/*.classes.ts" + "${BUN_SRC}/bun.js/webcore/*.classes.ts" + "${BUN_SRC}/bun.js/node/*.classes.ts" +) +add_custom_command( + OUTPUT "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureHeader.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMClientIsoSubspaces.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMIsoSubspaces.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureImpl.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" + COMMAND ${BUN_EXECUTABLE} "${BUN_CODEGEN_SRC}/generate-classes.ts" ${BUN_CLASSES_TS} "${BUN_WORKDIR}/codegen" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + MAIN_DEPENDENCY "${BUN_CODEGEN_SRC}/generate-classes.ts" + DEPENDS ${BUN_CLASSES_TS} + VERBATIM + COMMENT "Generating *.classes.ts bindings" +) +list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp") + +# --- JSSink Generator --- +add_custom_command( + OUTPUT "${BUN_WORKDIR}/codegen/JSSink.cpp" + "${BUN_WORKDIR}/codegen/JSSink.h" + COMMAND ${BUN_EXECUTABLE} "src/codegen/generate-jssink.ts" "${BUN_WORKDIR}/codegen" + VERBATIM + MAIN_DEPENDENCY "src/codegen/generate-jssink.ts" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generating JSSink" +) +list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/JSSink.cpp") + +# --- .lut.h Generator --- +set(BUN_OBJECT_LUT_SOURCES + bun.js/bindings/BunObject.cpp + bun.js/bindings/ZigGlobalObject.lut.txt + bun.js/bindings/JSBuffer.cpp + bun.js/bindings/BunProcess.cpp + bun.js/bindings/ProcessBindingConstants.cpp + bun.js/bindings/ProcessBindingNatives.cpp +) +set(BUN_OBJECT_LUT_OUTPUTS "") +set(BUN_HASH_LUT_GENERATOR "${BUN_CODEGEN_SRC}/create-hash-table.ts") + +if(NOT BUN_LINK_ONLY) + macro(GENERATE_HASH_LUT _input _output _display_name) + if(NOT NO_CODEGEN) + add_custom_command( + OUTPUT ${_output} + MAIN_DEPENDENCY ${BUN_HASH_LUT_GENERATOR} + DEPENDS ${_input} + COMMAND ${BUN_EXECUTABLE} ${BUN_HASH_LUT_GENERATOR} ${_input} ${_output} + VERBATIM + COMMENT "Generating ${_display_name}" + ) + endif() + + list(APPEND BUN_OBJECT_LUT_OUTPUTS "${_output}") + + # list(APPEND Bun_HEADERS ${_output}) + WEBKIT_ADD_SOURCE_DEPENDENCIES(${_input} ${_output}) + endmacro() + + foreach(_file ${BUN_OBJECT_LUT_SOURCES}) + if(NOT EXISTS "${BUN_SRC}/${_file}") + message(FATAL_ERROR "Could not find ${_file} needed for LUT generation") + endif() + + get_filename_component(_name ${_file} NAME_WE) + + # workaround for ZigGlobalObject + if(_name MATCHES "ZigGlobalObject") + set(_name "ZigGlobalObject") + endif() + + GENERATE_HASH_LUT(${BUN_SRC}/${_file} ${BUN_WORKDIR}/codegen/${_name}.lut.h ${_name}.lut.h) + endforeach() + + WEBKIT_ADD_SOURCE_DEPENDENCIES(${BUN_SRC}/bun.js/bindings/ZigGlobalObject.cpp ${BUN_WORKDIR}/codegen/ZigGlobalObject.lut.h) +endif() + +# --- Identifier Cache --- +if(NOT NO_CODEGEN) + set(BUN_IDENTIFIER_CACHE_OUT + "${BUN_SRC}/js_lexer/id_continue_bitset.blob" + "${BUN_SRC}/js_lexer/id_continue_bitset.meta.blob" + "${BUN_SRC}/js_lexer/id_start_bitset.blob" + "${BUN_SRC}/js_lexer/id_start_bitset.meta.blob") + add_custom_command( + OUTPUT ${BUN_IDENTIFIER_CACHE_OUT} + MAIN_DEPENDENCY "${BUN_SRC}/js_lexer/identifier_data.zig" + DEPENDS "${BUN_SRC}/js_lexer/identifier_cache.zig" + COMMAND ${ZIG_COMPILER} run "${BUN_SRC}/js_lexer/identifier_data.zig" + VERBATIM + COMMENT "Building Identifier Cache" + ) +endif() + +# --- Bundled TS/JS --- +# Note: It's not worth doing this in parallel at the CMake/Ninja level, because this bundling +# requires all the JS files to be known, but also Bun will use all cores during bundling anyways. +if(NOT NO_CODEGEN) + file(GLOB BUN_TS_MODULES ${CONFIGURE_DEPENDS} + "${BUN_SRC}/js/node/*.ts" + "${BUN_SRC}/js/node/*.js" + "${BUN_SRC}/js/bun/*.js" + "${BUN_SRC}/js/bun/*.ts" + "${BUN_SRC}/js/thirdparty/*.js" + "${BUN_SRC}/js/thirdparty/*.ts" + "${BUN_SRC}/js/internal/*.js" + "${BUN_SRC}/js/internal/*.ts" + ) + file(GLOB BUN_TS_FUNCTIONS ${CONFIGURE_DEPENDS} "${BUN_SRC}/js/builtins/*.ts") + + file(GLOB CODEGEN_FILES ${CONFIGURE_DEPENDS} "${BUN_CODEGEN_SRC}/*.ts") + + add_custom_command( + OUTPUT + "${BUN_WORKDIR}/codegen/InternalModuleRegistryConstants.h" + "${BUN_WORKDIR}/codegen/InternalModuleRegistry+createInternalModuleById.h" + "${BUN_WORKDIR}/codegen/InternalModuleRegistry+enum.h" + "${BUN_WORKDIR}/codegen/InternalModuleRegistry+numberOfModules.h" + "${BUN_WORKDIR}/codegen/NativeModuleImpl.h" + "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" + "${BUN_WORKDIR}/codegen/SyntheticModuleType.h" + COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-modules.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" + DEPENDS ${BUN_TS_MODULES} ${CODEGEN_FILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Bundling JS modules" + ) +endif() + +WEBKIT_ADD_SOURCE_DEPENDENCIES( + "${BUN_SRC}/bun.js/bindings/InternalModuleRegistry.cpp" + "${BUN_WORKDIR}/codegen/InternalModuleRegistryConstants.h" +) + +add_custom_command( + OUTPUT "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp" + "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.h" + COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-functions.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" + DEPENDS ${BUN_TS_FUNCTIONS} ${CODEGEN_FILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Bundling JS builtin functions" +) +list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp") + +# --- Peechy API --- +# if(NOT NO_CODEGEN) +# add_custom_command( +# OUTPUT "${BUN_SRC}/api/schema.js" +# "${BUN_SRC}/api/schema.d.ts" +# "${BUN_SRC}/api/schema.zig" +# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/.bin/peechy" +# "--schema" "${BUN_SRC}/api/schema.peechy" +# "--esm" "${BUN_SRC}/api/schema.js" +# "--ts" "${BUN_SRC}/api/schema.d.ts" +# "--zig" "${BUN_SRC}/api/schema.zig" +# COMMAND "${ZIG_COMPILER}" "fmt" "src/api/schema.zig" +# COMMAND "${PRETTIER}" "--config=.prettierrc.cjs" "--write" "src/api/schema.js" "src/api/schema.d.ts" +# DEPENDS "${BUN_SRC}/api/schema.peechy" +# COMMENT "Building schema" +# ) +# add_custom_command( +# OUTPUT "${BUN_SRC}/analytics/analytics_schema.zig" +# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/.bin/peechy" +# "--schema" "${BUN_SRC}/analytics/schema.peechy" +# "--zig" "${BUN_SRC}/analytics/analytics_schema.zig" +# COMMAND "${ZIG_COMPILER}" "fmt" "${BUN_SRC}/analytics/analytics_schema.zig" +# DEPENDS "${BUN_SRC}/api/schema.peechy" +# COMMENT "Building analytics_schema.zig" +# ) +# endif() + +# --- Runtime.js --- +if(NOT NO_CODEGEN) + add_custom_command( + OUTPUT "src/fallback.out.js" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMAND "${ESBUILD}" "--target=esnext" "--bundle" "src/fallback.ts" "--format=iife" "--platform=browser" "--minify" "--outfile=src/fallback.out.js" + DEPENDS "src/fallback.ts" + ) +endif() + +# --- Zig Object --- +file(GLOB ZIG_FILES + "${BUN_SRC}/*.zig" + "${BUN_SRC}/*/*.zig" + "${BUN_SRC}/*/*/*.zig" + "${BUN_SRC}/*/*/*/*.zig" + "${BUN_SRC}/*/*/*/*/*.zig" +) + +if(NOT BUN_ZIG_OBJ) + set(BUN_ZIG_OBJ "${BUN_WORKDIR}/CMakeFiles/bun-zig.o") +endif() + +get_filename_component(BUN_ZIG_OBJ "${BUN_ZIG_OBJ}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") + +set(USES_TERMINAL_NOT_IN_CI "") + +if(NOT CI) + set(USES_TERMINAL_NOT_IN_CI "USES_TERMINAL") +endif() + +if(NOT BUN_LINK_ONLY AND NOT BUN_CPP_ONLY) + add_custom_command( + OUTPUT "${BUN_ZIG_OBJ}" + COMMAND + "${ZIG_COMPILER}" "build" "obj" + "-Doutput-file=${BUN_ZIG_OBJ}" + "-Dgenerated-code=${BUN_WORKDIR}/codegen" + "-Dversion=${Bun_VERSION}" + "-Dcanary=${CANARY}" + "-Doptimize=${ZIG_OPTIMIZE}" + "-Dcpu=${CPU_TARGET}" + "-Dtarget=${ZIG_TARGET}" + DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/build.zig" + "${ZIG_FILES}" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" + "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" + "${BUN_IDENTIFIER_CACHE_OUT}" + "${BUN_SRC}/api/schema.zig" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Building zig code" + VERBATIM + + # This is here to show Zig's progress indicator + ${USES_TERMINAL_NOT_IN_CI} + ) +endif() + +if(WIN32) + list(APPEND BUN_RAW_SOURCES "${BUN_SRC}/bun.js/bindings/windows/musl-memmem.c") + include_directories("${BUN_SRC}/bun.js/bindings/windows") +endif() + +if(NOT BUN_CPP_ARCHIVE) + # TODO: unified sources + set(BUN_SOURCES ${BUN_RAW_SOURCES}) +else() + # used by ci + set(BUN_SOURCES "") + add_link_options("${BUN_CPP_ARCHIVE}") +endif() + +# -- Windows resources (app icon) -- +if(CANARY GREATER 0) + set(Bun_VERSION_WITH_TAG "${Bun_VERSION}-canary.${CANARY}") +else() + set(Bun_VERSION_WITH_TAG "${Bun_VERSION}") +endif() + +if(WIN32) + set(BUN_ICO_PATH "${BUN_SRC}/bun.ico") + configure_file("${BUN_SRC}/windows-app-info.rc" "${BUN_WORKDIR}/CMakeFiles/windows-app-info.rc") + list(APPEND BUN_SOURCES "${BUN_WORKDIR}/CMakeFiles/windows-app-info.rc") +endif() + +# -- The Buntime™️ --- +if(NOT BUN_CPP_ONLY) + add_executable(${bun} "${BUN_SOURCES}" "${BUN_ZIG_OBJ}") +else() + add_executable(${bun} "${BUN_SOURCES}") +endif() + +set_target_properties(${bun} PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS YES + CXX_VISIBILITY_PRESET hidden + C_STANDARD 17 + C_STANDARD_REQUIRED YES + VISIBILITY_INLINES_HIDDEN YES +) + +add_compile_definitions( + + # TODO: are all of these variables strictly necessary? + "_HAS_EXCEPTIONS=0" + "LIBUS_USE_OPENSSL=1" + "UWS_HTTPRESPONSE_NO_WRITEMARK=1" + "LIBUS_USE_BORINGSSL=1" + "WITH_BORINGSSL=1" + "STATICALLY_LINKED_WITH_JavaScriptCore=1" + "STATICALLY_LINKED_WITH_WTF=1" + "STATICALLY_LINKED_WITH_BMALLOC=1" + "BUILDING_WITH_CMAKE=1" + "JSC_OBJC_API_ENABLED=0" + "BUN_SINGLE_THREADED_PER_VM_ENTRY_SCOPE=1" + "NAPI_EXPERIMENTAL=ON" + "NOMINMAX" + "IS_BUILD" + "BUILDING_JSCONLY__" + "BUN_DYNAMIC_JS_LOAD_PATH=\"${BUN_WORKDIR}/js\"" +) + +if(NOT ASSERT_ENABLED) + add_compile_definitions("NDEBUG=1") +else() + add_compile_definitions("ASSERT_ENABLED=1") +endif() + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/packages/ + ${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets + ${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/webcore + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/webcrypto + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/sqlite + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/modules + ${CMAKE_CURRENT_SOURCE_DIR}/src/js/builtins + ${CMAKE_CURRENT_SOURCE_DIR}/src/napi + ${CMAKE_CURRENT_SOURCE_DIR}/src/deps + ${CMAKE_CURRENT_SOURCE_DIR}/src/deps/picohttpparser + ${WEBKIT_INCLUDE_DIR} + "${BUN_WORKDIR}/codegen" +) + +# -- BUN_CPP_ONLY Target +if(NOT BUN_CPP_ARCHIVE) + if(BUN_CPP_ONLY) + if(NOT WIN32) + string(REPLACE ";" ".o\n " BUN_OBJECT_LIST "${BUN_SOURCES}.o") + string(REPLACE "${BUN_WORKDIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + write_file("${BUN_WORKDIR}/compile-cpp-only.sh" + "#!/usr/bin/env bash\n" + "# this file is generated in CMakeLists.txt\n" + "set -ex\n" + "OBJ_LIST=(\n ${BUN_OBJECT_LIST}\n)\n" + "ninja \${OBJ_LIST[@]} $@\n" + "\"${AR}\" rcvs bun-cpp-objects.a \${OBJ_LIST[@]}\n" + "echo '-> bun-cpp-objects.a'\n" + ) + else() + string(REPLACE ";" ".obj\",\n \"" BUN_OBJECT_LIST "\"${BUN_SOURCES}.obj\"") + string(REPLACE "rc.obj" "rc.res" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + string(REPLACE "${BUN_WORKDIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + write_file("${BUN_WORKDIR}/compile-cpp-only.ps1" + "# this file is generated in CMakeLists.txt\n" + "$ErrorActionPreference = \"Stop\"\n" + "$ObjectFiles=@(\n ${BUN_OBJECT_LIST}\n)\n" + "ninja @ObjectFiles @args\n" + "& \"${AR}\" rcvs bun-cpp-objects.a @ObjectFiles\n" + "Write-Host '-> bun-cpp-objects.a'\n" + ) + endif() + endif() +else() + set_target_properties(${bun} PROPERTIES LINKER_LANGUAGE CXX) +endif() + +# --- clang and linker flags --- +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if(NOT WIN32) + target_compile_options(${bun} PUBLIC -g3 -O0 -gdwarf-4 + -Werror=return-type + -Werror=return-stack-address + -Werror=implicit-function-declaration + ) + else() + target_compile_options(${bun} PUBLIC /Od /Z7) + endif() + + add_compile_definitions("BUN_DEBUG=1") +elseif(CMAKE_BUILD_TYPE STREQUAL "Release") + if(NOT WIN32) + target_compile_options(${bun} PUBLIC -O3 -flto=full -emit-llvm -g1 + -Werror=return-type + -Werror=return-stack-address + -Werror=implicit-function-declaration + ) + else() + target_compile_options(${bun} PUBLIC /O2 -flto=full /DEBUG /Z7) + target_link_options(${bun} PUBLIC /LTCG /DEBUG) + endif() +endif() + +if(NOT CI AND NOT WIN32) + target_compile_options(${bun} PRIVATE -fdiagnostics-color=always) +endif() + +if(NOT CPU_TARGET STREQUAL "native") + # passing -march=native to clang will break older systems + # by default on x64, CPU_TARGET is set to "haswell" or "nehalem" depending on baseline + # on arm, this argument will not be passed. + target_compile_options(${bun} PUBLIC "-march=${CPU_TARGET}") +else() + if(APPLE AND ARCH STREQUAL "aarch64") + # On arm macOS, we can set it to a minimum of the M1 cpu set. this might be the default already. + target_compile_options(${bun} PUBLIC "-mcpu=apple-m1") + endif() +endif() + +target_compile_options(${bun} PUBLIC -ferror-limit=${ERROR_LIMIT}) + +if(WIN32) + add_compile_definitions( + "WIN32" + "_WINDOWS" + "WIN32_LEAN_AND_MEAN=1" + "_CRT_SECURE_NO_WARNINGS" + "BORINGSSL_NO_CXX=1" # lol + ) + + # set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") + set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") + + target_compile_options(${bun} PUBLIC "/EHsc" "/GR-") + target_link_options(${bun} PUBLIC "/STACK:0x1200000,0x100000") +else() + target_compile_options(${bun} PUBLIC + -fPIC + -mtune=${CPU_TARGET} + -fconstexpr-steps=1271242 + -fconstexpr-depth=27 + -fno-exceptions + -fvisibility=hidden + -fvisibility-inlines-hidden + -fno-rtti + -fno-omit-frame-pointer + ) + string(APPEND CMAKE_CXX_FLAGS " -std=c++2a") +endif() + +if(APPLE) + if(ARCH STREQUAL "x86_64") + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") + else() + set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") + endif() + + target_link_options(${bun} PUBLIC "-dead_strip") + target_link_options(${bun} PUBLIC "-dead_strip_dylibs") + target_link_options(${bun} PUBLIC "-Wl,-stack_size,0x1200000") + target_link_options(${bun} PUBLIC "-exported_symbols_list" "${BUN_SRC}/symbols.txt") + set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.txt") + + target_link_options(${bun} PUBLIC "-fno-keep-static-consts") + target_link_libraries(${bun} PRIVATE "resolv") +endif() + +if(UNIX AND NOT APPLE) + target_link_options(${bun} PUBLIC + "-fuse-ld=lld" + "-static-libstdc++" + "-static-libgcc" + "-fuse-ld=lld" + "-Wl,-z,now" + "-Wl,--as-needed" + "-Wl,--gc-sections" + "-Wl,-z,stack-size=12800000" + "-Wl,--wrap=fcntl" + "-Wl,--wrap=fcntl64" + "-Wl,--wrap=stat64" + "-Wl,--wrap=pow" + "-Wl,--wrap=exp" + "-Wl,--wrap=log" + "-Wl,--wrap=log2" + "-Wl,--wrap=lstat" + "-Wl,--wrap=stat" + "-Wl,--wrap=fstat" + "-Wl,--wrap=fstatat" + "-Wl,--wrap=lstat64" + "-Wl,--wrap=stat64" + "-Wl,--wrap=fstat64" + "-Wl,--wrap=fstatat64" + "-Wl,--wrap=mknod" + "-Wl,--wrap=mknodat" + "-Wl,--wrap=statx" + "-Wl,--compress-debug-sections=zlib" + "-Bsymbolics-functions" + "-rdynamic" + "-Wl,--dynamic-list=${BUN_SRC}/symbols.dyn" + "-Wl,--version-script=${BUN_SRC}/linker.lds" + ) + + target_link_libraries(${bun} PRIVATE "c") + target_link_libraries(${bun} PRIVATE "pthread") + target_link_libraries(${bun} PRIVATE "dl") + + if(NOT USE_STATIC_LIBATOMIC) + target_link_libraries(${bun} PUBLIC "libatomic.so") + else() + target_link_libraries(${bun} PRIVATE "libatomic.a") + endif() + + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicudata.a") + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicui18n.a") + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicuuc.a") + + set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/linker.lds") + set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.dyn") +endif() + +# --- ICU --- +if(APPLE) + # TODO: a much better check can be done to find this path + find_path( + ICU4C_DIR NAMES lib/libicudata.a + PATHS ENV PATH /usr/local/opt/icu4c /opt/homebrew/opt/icu4c + ) + find_path( + ICONV_DIR NAMES lib/libiconv.a + PATHS ENV PATH /usr/local/opt/libiconv /opt/homebrew/opt/libiconv + ) + + target_link_libraries(${bun} PRIVATE "icucore") + target_link_libraries(${bun} PRIVATE "${ICONV_DIR}/lib/libiconv.a") + target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicudata.a") + target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicui18n.a") + target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicuuc.a") +endif() + +# --- Stripped Binary "bun" +if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32 AND NOT ASSERT_ENABLED) + # add_custom_command( + # TARGET ${bun} + # POST_BUILD + # COMMAND ${DSYMUTIL} -o ${BUN_WORKDIR}/bun.dSYM ${BUN_WORKDIR}/${bun} + # COMMENT "Stripping Symbols" + # ) + add_custom_command( + TARGET ${bun} + POST_BUILD + COMMAND ${STRIP} -s -x -S -o ${BUN_WORKDIR}/bun ${BUN_WORKDIR}/${bun} + COMMENT "Stripping Symbols" + ) +endif() + +if(WIN32) + # Kill all instances of bun before linking. + add_custom_command( + TARGET ${bun} + PRE_BUILD + COMMAND + "powershell" + "/C" + "Stop-Process -Name '${bun}' -Force -ErrorAction SilentlyContinue; exit 0" + ) +endif() + +# --- Dependencies --- +if(USE_CUSTOM_ZLIB) + include_directories(${BUN_DEPS_DIR}/zlib) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/zlib.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libz.a") + endif() +else() + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_DIR}/zlib_maybethisworks.lib") + else() + find_package(ZLIB REQUIRED) + target_link_libraries(${bun} PRIVATE ZLIB::ZLIB) + endif() +endif() + +if(USE_CUSTOM_BORINGSSL) + include_directories(${BUN_DEPS_DIR}/boringssl/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/crypto.lib") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/ssl.lib") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/decrepit.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libcrypto.a") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libssl.a") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libdecrepit.a") + endif() +else() + include(FindBoringSSL) + FindBoringSSL(${bun}) +endif() + +if(USE_CUSTOM_LIBARCHIVE) + include_directories(${BUN_DEPS_DIR}/libarchive/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/archive.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libarchive.a") + endif() +else() + find_package(LibArchive REQUIRED) + target_link_libraries(${bun} PRIVATE LibArchive::LibArchive) +endif() + +if(USE_CUSTOM_MIMALLOC) + include_directories(${BUN_DEPS_DIR}/mimalloc/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/mimalloc.lib") + elseif(APPLE) + if(USE_DEBUG_JSC OR CMAKE_BUILD_TYPE STREQUAL "Debug") + message(STATUS "Using debug mimalloc") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc-debug.a") + else() + # https://github.com/microsoft/mimalloc/issues/512 + # Linking mimalloc via object file on macOS x64 can cause heap corruption + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc.a") + endif() + else() + if(USE_DEBUG_JSC OR CMAKE_BUILD_TYPE STREQUAL "Debug") + message(STATUS "Using debug mimalloc") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc-debug.a") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc.o") + endif() + endif() +else() + find_package(mimalloc REQUIRED) + target_link_libraries(${bun} PRIVATE mimalloc) +endif() + +if(USE_CUSTOM_ZSTD) + include_directories(${BUN_DEPS_DIR}/zstd/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/zstd.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libzstd.a") + endif() +else() + find_package(zstd CONFIG REQUIRED) + target_link_libraries(${bun} PRIVATE zstd::libzstd) +endif() + +if(USE_CUSTOM_CARES) + include_directories(${BUN_DEPS_DIR}/c-ares/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/cares.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libcares.a") + endif() +else() + find_package(c-ares CONFIG REQUIRED) + target_link_libraries(${bun} PRIVATE c-ares::cares) +endif() + +if(USE_CUSTOM_BASE64) + include_directories(${BUN_DEPS_DIR}/base64/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/base64.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libbase64.a") + endif() +else() + find_package(base64 REQUIRED) + target_link_libraries(${bun} PRIVATE base64::base64) +endif() + +if(USE_CUSTOM_TINYCC) + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/tcc.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libtcc.a") + endif() +else() + find_package(tinycc REQUIRED) + target_link_libraries(${bun} PRIVATE tinycc::tinycc) +endif() + +if(USE_CUSTOM_LOLHTML) + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/lolhtml.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/liblolhtml.a") + endif() +else() + find_package(lolhtml REQUIRED) + target_link_libraries(${bun} PRIVATE lolhtml::lolhtml) +endif() + +if(WIN32) + if(USE_CUSTOM_LIBUV) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libuv.lib") + include_directories(${bun} PRIVATE "${BUN_DEPS_DIR}/libuv/include") + else() + find_package(libuv CONFIG REQUIRED) + target_link_libraries(${bun} PRIVATE $,libuv::uv_a,libuv::uv>) + endif() +endif() + +if(USE_STATIC_SQLITE) + add_library(sqlite3 STATIC src/bun.js/bindings/sqlite/sqlite3.c) + target_include_directories(sqlite3 PUBLIC src/bun.js/bindings/sqlite) + target_compile_definitions(sqlite3 PRIVATE + "SQLITE_ENABLE_COLUMN_METADATA=" + "SQLITE_MAX_VARIABLE_NUMBER=250000" + "SQLITE_ENABLE_RTREE=1" + "SQLITE_ENABLE_FTS3=1" + "SQLITE_ENABLE_FTS3_PARENTHESIS=1" + "SQLITE_ENABLE_FTS5=1" + "SQLITE_ENABLE_JSON1=1" + ) + target_link_libraries(${bun} PRIVATE sqlite3) + message(STATUS "Using static sqlite3") + target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=0") +else() + message(STATUS "Using dynamicly linked sqlite3") + target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=1") +endif() + +if(USE_CUSTOM_LSHPACK) + include_directories(${BUN_DEPS_DIR}/ls-hpack) + if(WIN32) + include_directories(${BUN_DEPS_DIR}/ls-hpack/compat/queue) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/lshpack.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/liblshpack.a") + endif() +else() + find_package(lshpack REQUIRED) + target_link_libraries(${bun} PRIVATE lshpack) +endif() + +if(NOT WIN32) + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libWTF.a") + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libJavaScriptCore.a") + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libbmalloc.a") +else() + target_link_options(${bun} PRIVATE "-static") + target_link_libraries(${bun} PRIVATE + "${WEBKIT_LIB_DIR}/WTF.lib" + "${WEBKIT_LIB_DIR}/JavaScriptCore.lib" + "${WEBKIT_LIB_DIR}/sicudt.lib" + "${WEBKIT_LIB_DIR}/sicuin.lib" + "${WEBKIT_LIB_DIR}/sicuuc.lib" + winmm + bcrypt + ntdll + ucrt + userenv + dbghelp + wsock32 # ws2_32 required by TransmitFile aka sendfile on windows + ) +endif() + +if(WIN32) + # delayimp -delayload:shell32.dll -delayload:ole32.dll +endif() + +if(BUN_LINK_ONLY) + message(STATUS "NOTE: BUN_LINK_ONLY is ON, this build config will only link the Bun executable") +endif() + +if(BUN_CPP_ONLY) + message(STATUS "NOTE: BUN_CPP_ONLY is ON, this build will only work with 'compile-cpp-only.${SCRIPT_EXTENSION}'") +endif() + +if(NO_CODEGEN) + message(STATUS "NOTE: NO_CODEGEN is ON, this build expects ./codegen to exist") endif() \ No newline at end of file diff --git a/src/StandaloneModuleGraph.zig b/src/StandaloneModuleGraph.zig index 75ea62add9..1b4949bbb4 100644 --- a/src/StandaloneModuleGraph.zig +++ b/src/StandaloneModuleGraph.zig @@ -17,15 +17,44 @@ pub const StandaloneModuleGraph = struct { files: bun.StringArrayHashMap(File), entry_point_id: u32 = 0, + // We never want to hit the filesystem for these files + // We use the `/$bunfs/` prefix to indicate that it's a virtual path + // It is `/$bunfs/` because: + // + // - `$` makes it unlikely to collide with a real path + // - `/$bunfs/` is 8 characters which is fast to compare for 64-bit CPUs + pub const base_path = switch (Environment.os) { + else => "/$bunfs/", + // Special case for windows because of file URLs being invalid + // if they do not have a drive letter. B drive because 'bun' but + // also because it's more unlikely to collide with a real path. + .windows => "B:\\~BUN\\", + }; + + pub const base_public_path = switch (Environment.os) { + else => "/$bunfs/", + .windows => "B:/~BUN/", + }; + + pub fn isBunStandaloneFilePath(str: []const u8) bool { + return bun.strings.hasPrefixComptime(str, base_path) or + (Environment.isWindows and bun.strings.hasPrefixComptime(str, base_public_path)); + } + pub fn entryPoint(this: *const StandaloneModuleGraph) *File { return &this.files.values()[this.entry_point_id]; } + // by normalized file path pub fn find(this: *const StandaloneModuleGraph, name: []const u8) ?*File { - if (!bun.strings.isBunStandaloneFilePath(name)) { + if (!bun.strings.hasPrefixComptime(name, base_path)) { return null; } - + if (Environment.isWindows) { + var normalized_buf: [bun.MAX_PATH_BYTES]u8 = undefined; + const normalized = bun.path.platformToPosixBuf(u8, name, &normalized_buf); + return this.files.getPtr(normalized); + } return this.files.getPtr(name); } diff --git a/src/allocators.zig b/src/allocators.zig index 39f290bb08..291677d0de 100644 --- a/src/allocators.zig +++ b/src/allocators.zig @@ -4,8 +4,11 @@ const FeatureFlags = @import("./feature_flags.zig"); const Environment = @import("./env.zig"); const FixedBufferAllocator = std.heap.FixedBufferAllocator; const bun = @import("root").bun; -pub fn isSliceInBuffer(slice: anytype, buffer: anytype) bool { - return (@intFromPtr(&buffer) <= @intFromPtr(slice.ptr) and (@intFromPtr(slice.ptr) + slice.len) <= (@intFromPtr(buffer) + buffer.len)); + +/// Checks if a slice's pointer is contained within another slice. +pub inline fn isSliceInBuffer(comptime T: type, slice: []const T, buffer: []const T) bool { + return (@intFromPtr(buffer.ptr) <= @intFromPtr(slice.ptr) and + (@intFromPtr(slice.ptr) + slice.len) <= (@intFromPtr(buffer.ptr) + buffer.len)); } pub fn sliceRange(slice: []const u8, buffer: []const u8) ?[2]u32 { @@ -305,8 +308,8 @@ pub fn BSSStringList(comptime _count: usize, comptime _item_length: usize) type return instance.slice_buf_used >= @as(u16, count); } - pub fn exists(_: *const Self, value: ValueType) bool { - return isSliceInBuffer(value, &instance.backing_buf); + pub fn exists(self: *const Self, value: ValueType) bool { + return isSliceInBuffer(u8, value, &self.backing_buf); } pub fn editableSlice(slice: []const u8) []u8 { diff --git a/src/async/windows_event_loop.zig b/src/async/windows_event_loop.zig index cd2d038204..0dc855f8d7 100644 --- a/src/async/windows_event_loop.zig +++ b/src/async/windows_event_loop.zig @@ -33,7 +33,7 @@ pub const KeepAlive = struct { return; this.status = .inactive; - loop.inc(); + loop.dec(); } /// Only intended to be used from EventLoop.Pollable diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index bb8ce7321d..f17e4576c4 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -2277,7 +2277,8 @@ pub const Subprocess = struct { .flags = if (windows_hide == 1) uv.UV_PROCESS_WINDOWS_HIDE else 0, }; - if (uv.uv_spawn(jsc_vm.uvLoop(), &subprocess.pid, &options).errEnum()) |errno| { + const loop = jsc_vm.uvLoop(); + if (uv.uv_spawn(loop, &subprocess.pid, &options).errEnum()) |errno| { alloc.destroy(subprocess); globalThis.throwValue(bun.sys.Error.fromCode(errno, .uv_spawn).toJSC(globalThis)); return .zero; @@ -2339,7 +2340,7 @@ pub const Subprocess = struct { // sync while (!subprocess.hasExited()) { - uv.Loop.get().tickWithTimeout(0); + loop.tickWithTimeout(0); if (subprocess.stderr == .pipe and subprocess.stderr.pipe == .buffer) { subprocess.stderr.pipe.buffer.readAll(); @@ -2348,9 +2349,6 @@ pub const Subprocess = struct { if (subprocess.stdout == .pipe and subprocess.stdout.pipe == .buffer) { subprocess.stdout.pipe.buffer.readAll(); } - - jsc_vm.tick(); - jsc_vm.eventLoop().autoTick(); } const exitCode = subprocess.exit_code orelse 1; diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index ef7c202a75..b6dc6d4e96 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -276,7 +276,13 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, WTF::String filename = callFrame->uncheckedArgument(1).toWTFString(globalObject); // Support embedded .node files - if (filename.startsWith("/$bunfs/"_s)) { + // See StandaloneModuleGraph.zig for what this "$bunfs" thing is +#if OS(WINDOWS) +#define StandaloneModuleGraph__base_path "B:/~BUN/"_s +#else +#define StandaloneModuleGraph__base_path "/$bunfs/"_s +#endif + if (filename.startsWith(StandaloneModuleGraph__base_path)) { BunString bunStr = Bun::toString(filename); if (Bun__resolveEmbeddedNodeFile(globalObject->bunVM(), &bunStr)) { filename = bunStr.toWTFString(BunString::ZeroCopy); diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index 38939aef03..221642c2e8 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -5275,8 +5275,13 @@ pub const NodeFS = struct { // On Windows, we potentially mutate the path in posixToPlatformInPlace // We cannot mutate JavaScript strings in-place. That will break many things. // So we must always copy the path string on Windows. - path = args.file.path.sliceZWithForceCopy(pathbuf, Environment.isWindows); - bun.path.posixToPlatformInPlace(u8, @constCast(path)); + path = path: { + const temp_path = args.file.path.sliceZWithForceCopy(pathbuf, Environment.isWindows); + if (Environment.isWindows) { + bun.path.posixToPlatformInPlace(u8, temp_path); + } + break :path temp_path; + }; var is_dirfd_different = false; var dirfd = args.dirfd; diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index f11efabc0a..8d95575d9a 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -3769,7 +3769,7 @@ pub const Blob = struct { if (this.store) |store| { if (store.data == .bytes) { const allocated_slice = store.data.bytes.allocatedSlice(); - if (bun.isSliceInBuffer(buf, allocated_slice)) { + if (bun.isSliceInBuffer(u8, buf, allocated_slice)) { if (bun.linux.memfd_allocator.from(store.data.bytes.allocator)) |allocator| { allocator.ref(); defer allocator.deref(); diff --git a/src/bun.js/webcore/blob/ReadFile.zig b/src/bun.js/webcore/blob/ReadFile.zig index eb838bb11d..c847f97444 100644 --- a/src/bun.js/webcore/blob/ReadFile.zig +++ b/src/bun.js/webcore/blob/ReadFile.zig @@ -16,6 +16,8 @@ const JSGlobalObject = JSC.JSGlobalObject; const ZigString = JSC.ZigString; const libuv = bun.windows.libuv; +const log = bun.Output.scoped(.ReadFile, true); + pub fn NewReadFileHandler(comptime Function: anytype) type { return struct { context: Blob, @@ -569,6 +571,7 @@ pub const ReadFileUV = struct { req: libuv.fs_t = libuv.fs_t.uninitialized, pub fn start(loop: *libuv.Loop, store: *Store, off: SizeType, max_len: SizeType, comptime Handler: type, handler: *anyopaque) void { + log("ReadFileUV.start", .{}); var this = bun.new(ReadFileUV, .{ .loop = loop, .file_store = store.data.file, @@ -583,10 +586,12 @@ pub const ReadFileUV = struct { } pub fn finalize(this: *ReadFileUV) void { + log("ReadFileUV.finalize", .{}); defer { this.store.deref(); this.req.deinit(); bun.destroy(this); + log("ReadFileUV.finalize destroy", .{}); } const cb = this.on_complete_fn; @@ -607,6 +612,7 @@ pub const ReadFileUV = struct { } fn onFinish(this: *ReadFileUV) void { + log("ReadFileUV.onFinish", .{}); const fd = this.opened_fd; const needs_close = fd != bun.invalid_fd; @@ -623,6 +629,7 @@ pub const ReadFileUV = struct { } pub fn onFileOpen(this: *ReadFileUV, opened_fd: bun.FileDescriptor) void { + log("ReadFileUV.onFileOpen", .{}); if (this.errno != null) { this.onFinish(); return; @@ -639,6 +646,7 @@ pub const ReadFileUV = struct { } fn onFileInitialStat(req: *libuv.fs_t) callconv(.C) void { + log("ReadFileUV.onFileInitialStat", .{}); var this: *ReadFileUV = @alignCast(@ptrCast(req.data)); if (req.result.errEnum()) |errno| { @@ -725,7 +733,8 @@ pub const ReadFileUV = struct { pub fn queueRead(this: *ReadFileUV) void { if (this.remainingBuffer().len > 0 and this.errno == null and !this.read_eof) { - // bun.sys.read(this.opened_fd, this.remainingBuffer()) + log("ReadFileUV.queueRead - this.remainingBuffer().len = {d}", .{this.remainingBuffer().len}); + const buf = this.remainingBuffer(); var bufs: [1]libuv.uv_buf_t = .{ libuv.uv_buf_t.init(buf), @@ -745,6 +754,8 @@ pub const ReadFileUV = struct { this.onFinish(); } } else { + log("ReadFileUV.queueRead done", .{}); + // We are done reading. _ = bun.default_allocator.resize(this.buffer, this.read_off); this.buffer = this.buffer[0..this.read_off]; diff --git a/src/bun.zig b/src/bun.zig index ce212f1691..cabd345001 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -549,9 +549,7 @@ pub fn isHeapMemory(memory: anytype) bool { pub const Mimalloc = @import("./allocators/mimalloc.zig"); -pub inline fn isSliceInBuffer(slice: []const u8, buffer: []const u8) bool { - return slice.len > 0 and @intFromPtr(buffer.ptr) <= @intFromPtr(slice.ptr) and ((@intFromPtr(slice.ptr) + slice.len) <= (@intFromPtr(buffer.ptr) + buffer.len)); -} +pub const isSliceInBuffer = allocators.isSliceInBuffer; pub inline fn sliceInBuffer(stable: string, value: string) string { if (allocators.sliceRange(stable, value)) |_| { @@ -564,7 +562,7 @@ pub inline fn sliceInBuffer(stable: string, value: string) string { } pub fn rangeOfSliceInBuffer(slice: []const u8, buffer: []const u8) ?[2]u32 { - if (!isSliceInBuffer(slice, buffer)) return null; + if (!isSliceInBuffer(u8, slice, buffer)) return null; const r = [_]u32{ @as(u32, @truncate(@intFromPtr(slice.ptr) -| @intFromPtr(buffer.ptr))), @as(u32, @truncate(slice.len)), diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index 6263661982..ccbccab4ad 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -570,11 +570,10 @@ pub const BundleV2 = struct { if (path.pretty.ptr == path.text.ptr) { // TODO: outbase - const rel = bun.path.relative(this.bundler.fs.top_level_dir, path.text); - if (rel.len > 0 and rel[0] != '.') { - path.pretty = rel; - } + const rel = bun.path.relativePlatform(this.bundler.fs.top_level_dir, path.text, .loose, false); + path.pretty = this.graph.allocator.dupe(u8, rel) catch @panic("Ran out of memory"); } + path.assertPrettyIsValid(); var secondary_path_to_copy: ?Fs.Path = null; if (resolve_result.path_pair.secondary) |*secondary| { @@ -669,14 +668,10 @@ pub const BundleV2 = struct { if (path.pretty.ptr == path.text.ptr) { // TODO: outbase - const rel = bun.path.relative(this.bundler.fs.top_level_dir, path.text); - if (rel.len > 0 and rel[0] != '.') { - path.pretty = rel; - } + const rel = bun.path.relativePlatform(this.bundler.fs.top_level_dir, path.text, .loose, false); + path.pretty = this.graph.allocator.dupe(u8, rel) catch @panic("Ran out of memory"); } path.* = try path.dupeAlloc(this.graph.allocator); - // TODO: this shouldn't be necessary - path.pretty = bun.sliceInBuffer(path.text, path.pretty); entry.value_ptr.* = source_index.get(); this.graph.ast.append(bun.default_allocator, JSAst.empty) catch unreachable; @@ -1092,9 +1087,8 @@ pub const BundleV2 = struct { const source = &sources[index]; var pathname = source.path.name; - const rel = bun.path.relative(this.bundler.options.root_dir, source.path.text); - if (rel.len > 0 and rel[0] != '.') - pathname = Fs.PathName.init(rel); + // TODO: outbase + pathname = Fs.PathName.init(bun.path.relativePlatform(this.bundler.options.root_dir, source.path.text, .loose, false)); template.placeholder.name = pathname.base; template.placeholder.dir = pathname.dir; @@ -1118,8 +1112,8 @@ pub const BundleV2 = struct { }, }, .size = source.contents.len, - .output_path = std.fmt.allocPrint(bun.default_allocator, "{}", .{template}) catch unreachable, - .input_path = bun.default_allocator.dupe(u8, source.path.text) catch unreachable, + .output_path = std.fmt.allocPrint(bun.default_allocator, "{}", .{template}) catch bun.outOfMemory(), + .input_path = bun.default_allocator.dupe(u8, source.path.text) catch bun.outOfMemory(), .input_loader = .file, .output_kind = .asset, .loader = loader, @@ -1164,20 +1158,18 @@ pub const BundleV2 = struct { // conditions from creating two _ = JSC.WorkPool.get(); - if (!BundleThread.created) { - BundleThread.created = true; - + if (BundleThread.instance) |existing| { + existing.queue.push(completion); + existing.waker.?.wake(); + } else { var instance = bun.default_allocator.create(BundleThread) catch unreachable; instance.queue = .{}; - instance.waker = bun.Async.Waker.init(bun.default_allocator) catch @panic("Failed to create waker"); + instance.waker = null; instance.queue.push(completion); BundleThread.instance = instance; var thread = try std.Thread.spawn(.{}, generateInNewThreadWrap, .{instance}); thread.detach(); - } else { - BundleThread.instance.queue.push(completion); - BundleThread.instance.waker.wake(); } completion.poll_ref.ref(globalThis.bunVM()); @@ -1555,17 +1547,17 @@ pub const BundleV2 = struct { } } - pub fn generateInNewThreadWrap( - instance: *BundleThread, - ) void { + pub fn generateInNewThreadWrap(instance: *BundleThread) void { Output.Source.configureNamedThread("Bundler"); - var any = false; + instance.waker = bun.Async.Waker.init(bun.default_allocator) catch @panic("Failed to create waker"); + + var has_bundled = false; while (true) { while (instance.queue.pop()) |completion| { generateInNewThread(completion, instance.generation) catch |err| { completion.result = .{ .err = err }; - const concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch unreachable; + const concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch bun.outOfMemory(); concurrent_task.* = JSC.ConcurrentTask{ .auto_delete = true, .task = completion.task.task(), @@ -1573,23 +1565,25 @@ pub const BundleV2 = struct { }; completion.jsc_event_loop.enqueueTaskConcurrent(concurrent_task); }; - any = true; + has_bundled = true; } instance.generation +|= 1; - if (any) { + if (has_bundled) { bun.Mimalloc.mi_collect(false); + has_bundled = false; } - _ = instance.waker.wait(); + + _ = instance.waker.?.wait(); } } pub const BundleThread = struct { - waker: bun.Async.Waker, + waker: ?bun.Async.Waker, queue: bun.UnboundedQueue(JSBundleCompletionTask, .next) = .{}, generation: bun.Generation = 0, - pub var created = false; - pub var instance: *BundleThread = undefined; + + pub var instance: ?*BundleThread = undefined; }; fn generateInNewThread( @@ -2013,11 +2007,11 @@ pub const BundleV2 = struct { if (path.pretty.ptr == path.text.ptr) { // TODO: outbase - const rel = bun.path.relative(this.bundler.fs.top_level_dir, path.text); - if (rel.len > 0 and rel[0] != '.') { - path.pretty = rel; - } + const rel = bun.path.relativePlatform(this.bundler.fs.top_level_dir, path.text, .loose, false); + path.pretty = this.graph.allocator.dupe(u8, rel) catch bun.outOfMemory(); } + path.assertPrettyIsValid(); + path.* = path.dupeAlloc(this.graph.allocator) catch @panic("Ran out of memory"); var secondary_path_to_copy: ?Fs.Path = null; if (resolve_result.path_pair.secondary) |*secondary| { @@ -2029,9 +2023,6 @@ pub const BundleV2 = struct { } } - path.* = path.dupeAlloc(this.graph.allocator) catch @panic("Ran out of memory"); - // TODO: this shouldn't be necessary - path.pretty = bun.sliceInBuffer(path.text, path.pretty); import_record.path = path.*; debug("created ParseTask: {s}", .{path.text}); @@ -7121,6 +7112,7 @@ const LinkerContext = struct { if (source.path.isFile()) { // Use the pretty path as the file name since it should be platform- // independent (relative paths and the "/" path separator) + source.path.assertPrettyIsValid(); break :brk source.path.pretty; } else { // If this isn't in the "file" namespace, just use the full path text @@ -11260,8 +11252,6 @@ pub const Chunk = struct { switch (this) { .pieces => |*pieces| { var count: usize = 0; - const file_path_buf: [4096]u8 = undefined; - _ = file_path_buf; var from_chunk_dir = std.fs.path.dirnamePosix(chunk.final_rel_path) orelse ""; if (strings.eqlComptime(from_chunk_dir, ".")) from_chunk_dir = ""; @@ -11269,6 +11259,10 @@ pub const Chunk = struct { for (pieces.slice()) |piece| { count += piece.data_len; + if (Environment.allow_assert) { + std.debug.assert(piece.data().len == piece.data_len); + } + switch (piece.index.kind) { .chunk, .asset => { const index = piece.index.index; @@ -11293,7 +11287,7 @@ pub const Chunk = struct { if (from_chunk_dir.len == 0) file_path else - bun.path.relative(from_chunk_dir, file_path), + bun.path.relativePlatform(from_chunk_dir, file_path, .posix, false), ); count += cheap_normalizer[0].len + cheap_normalizer[1].len; }, @@ -11308,10 +11302,10 @@ pub const Chunk = struct { for (pieces.slice()) |piece| { const data = piece.data(); - if (data.len > 0) + if (data.len > 0) { @memcpy(remain[0..data.len], data); - - remain = remain[data.len..]; + remain = remain[data.len..]; + } switch (piece.index.kind) { .asset, .chunk => { @@ -11328,8 +11322,7 @@ pub const Chunk = struct { .chunk => chunks[index].final_rel_path, else => unreachable, }; - // normalize windows paths to '/' - bun.path.platformToPosixInPlace(u8, @constCast(file_path)); + const cheap_normalizer = cheapPrefixNormalizer( import_prefix, if (from_chunk_dir.len == 0) @@ -11551,7 +11544,10 @@ const ContentHasher = struct { // xxhash64 outperforms Wyhash if the file is > 1KB or so hasher: std.hash.XxHash64 = std.hash.XxHash64.init(0), + const log = bun.Output.scoped(.ContentHasher, true); + pub fn write(self: *ContentHasher, bytes: []const u8) void { + log("HASH_UPDATE {d}:\n{s}\n----------\n", .{ bytes.len, std.mem.sliceAsBytes(bytes) }); self.hasher.update(std.mem.asBytes(&bytes.len)); self.hasher.update(bytes); } @@ -11563,6 +11559,7 @@ const ContentHasher = struct { } pub fn writeInts(self: *ContentHasher, i: []const u32) void { + log("HASH_UPDATE: {any}\n", .{i}); self.hasher.update(std.mem.sliceAsBytes(i)); } diff --git a/src/cli/build_command.zig b/src/cli/build_command.zig index 27d1be6d61..f8af12d66b 100644 --- a/src/cli/build_command.zig +++ b/src/cli/build_command.zig @@ -107,15 +107,8 @@ pub const BuildCommand = struct { return; } - // We never want to hit the filesystem for these files - // We use the `/$bunfs/` prefix to indicate that it's a virtual path - // It is `/$bunfs/` because: - // - // - `$` makes it unlikely to collide with a real path - // - `/$bunfs/` is 8 characters which is fast to compare for 64-bit CPUs - // - this_bundler.options.public_path = "/$bunfs/root/"; - this_bundler.resolver.opts.public_path = "/$bunfs/root/"; + this_bundler.options.public_path = bun.StandaloneModuleGraph.base_public_path ++ "root/"; + this_bundler.resolver.opts.public_path = bun.StandaloneModuleGraph.base_public_path ++ "root/"; if (outfile.len == 0) { outfile = std.fs.path.basename(this_bundler.options.entry_points[0]); diff --git a/src/cli/install.ps1 b/src/cli/install.ps1 index 1567dc7b75..22a907a4f7 100644 --- a/src/cli/install.ps1 +++ b/src/cli/install.ps1 @@ -97,6 +97,7 @@ function Install-Bun { Write-Error $_ exit 1 } + Remove-Item "${BunBin}\bun.exe" -ErrorAction SilentlyContinue Move-Item "${BunBin}\$Target\bun.exe" "${BunBin}\bun.exe" -Force Remove-Item "${BunBin}\$Target" -Recurse -Force @@ -116,8 +117,13 @@ function Install-Bun { Install-Bun -Version $Version -ForceBaseline $True exit 1 } - if ($LASTEXITCODE -eq 3221225781) { # STATUS_DLL_NOT_FOUND + if (($LASTEXITCODE -eq 3221225781) # STATUS_DLL_NOT_FOUND + # https://discord.com/channels/876711213126520882/1149339379446325248/1205194965383250081 + # http://community.sqlbackupandftp.com/t/error-1073741515-solved/1305 + || ($LASTEXITCODE -eq 1073741515)) + { Write-Output "Install Failed - You are missing a DLL required to run bun.exe" + Write-Output "This can be solved by installing the Visual C++ Redistributable from Microsoft:`nSee https://learn.microsoft.com/cpp/windows/latest-supported-vc-redist`nDirect Download -> https://aka.ms/vs/17/release/vc_redist.x64.exe`n`n" Write-Output "The command '${BunBin}\bun.exe --revision' exited with code ${LASTEXITCODE}`n" exit 1 } @@ -135,6 +141,11 @@ function Install-Bun { $C_RESET = [char]27 + "[0m" $C_GREEN = [char]27 + "[1;32m" + # delete bunx if it exists already. this happens if you re-install + # we don't want to hit an "already exists" error. + Remove-Item "${BunBin}\bunx.exe" -ErrorAction SilentlyContinue + Remove-Item "${BunBin}\bunx.cmd" -ErrorAction SilentlyContinue + try { $null = New-Item -ItemType HardLink -Path "${BunBin}\bunx.exe" -Target "${BunBin}\bun.exe" -Force } catch { @@ -167,10 +178,6 @@ function Install-Bun { } if(!$hasExistingOther) { - if((Get-Command -ErrorAction SilentlyContinue bun) -eq $null) { - Write-Output "To get started, restart your terminal session, then type `"bun`"`n" - } else { - Write-Output "Type `"bun`" in your terminal to get started`n" - } + Write-Output "To get started, restart your terminal/editor, then type `"bun`"`n" } } \ No newline at end of file diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index dca5a1fef4..3a1e45854f 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -212,7 +212,7 @@ pub const CommandLineReporter = struct { if (this.jest.bail == this.summary.fail) { this.printSummary(); - Output.prettyError("\nBailed out after {d} failures\n", .{this.jest.bail}); + Output.prettyError("\nBailed out after {d} failure{s}\n", .{ this.jest.bail, if (this.jest.bail == 1) "" else "s" }); Global.exit(1); } } @@ -719,11 +719,28 @@ pub const TestCommand = struct { // Treat arguments as filters and scan the codebase const filter_names = if (ctx.positionals.len == 0) &[0][]const u8{} else ctx.positionals[1..]; + const filter_names_normalized = if (!Environment.isWindows) + filter_names + else brk: { + const normalized = try ctx.allocator.alloc([]const u8, filter_names.len); + for (filter_names, normalized) |in, *out| { + const to_normalize = try ctx.allocator.dupe(u8, in); + bun.path.posixToPlatformInPlace(u8, to_normalize); + out.* = to_normalize; + } + break :brk normalized; + }; + defer if (Environment.isWindows) { + for (filter_names_normalized) |i| + ctx.allocator.free(i); + ctx.allocator.free(filter_names_normalized); + }; + var scanner = Scanner{ .dirs_to_scan = Scanner.Fifo.init(ctx.allocator), .options = &vm.bundler.options, .fs = vm.bundler.fs, - .filter_names = filter_names, + .filter_names = filter_names_normalized, .results = &results, }; const dir_to_scan = brk: { @@ -1030,7 +1047,7 @@ pub const TestCommand = struct { if (reporter.jest.bail == reporter.summary.fail) { reporter.printSummary(); - Output.prettyError("\nBailed out after {d} failures\n", .{reporter.jest.bail}); + Output.prettyError("\nBailed out after {d} failure{s}\n", .{ reporter.jest.bail, if (reporter.jest.bail == 1) "" else "s" }); Global.exit(1); } diff --git a/src/fs.zig b/src/fs.zig index e3b8343d5e..1c338186cf 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -1664,6 +1664,16 @@ pub const Path = struct { return this.name.dirWithTrailingSlash(); } + /// The bundler will hash path.pretty, so it needs to be consistent across platforms. + /// This assertion might be a bit too forceful though. + pub fn assertPrettyIsValid(path: *const Path) void { + if (Environment.isWindows and Environment.allow_assert) { + if (std.mem.indexOfScalar(u8, path.pretty, '\\') != null) { + std.debug.panic("Expected pretty file path to have only forward slashes, got '{s}'", .{path.pretty}); + } + } + } + // This duplicates but only when strictly necessary // This will skip allocating if it's already in FilenameStore or DirnameStore pub fn dupeAlloc(this: *const Path, allocator: std.mem.Allocator) !Fs.Path { diff --git a/src/install/semver.zig b/src/install/semver.zig index 2942c384ca..ad2778c71f 100644 --- a/src/install/semver.zig +++ b/src/install/semver.zig @@ -249,7 +249,9 @@ pub const String = extern struct { buf: string, in: string, ) Pointer { - std.debug.assert(bun.isSliceInBuffer(in, buf)); + if (Environment.allow_assert) { + std.debug.assert(bun.isSliceInBuffer(u8, in, buf)); + } return Pointer{ .off = @as(u32, @truncate(@intFromPtr(in.ptr) - @intFromPtr(buf.ptr))), diff --git a/src/js_lexer.zig b/src/js_lexer.zig index a7ac8f8bdc..c7adf811f1 100644 --- a/src/js_lexer.zig +++ b/src/js_lexer.zig @@ -2001,7 +2001,7 @@ fn NewLexer_( } if (comptime Environment.allow_assert) - std.debug.assert(rest.len == 0 or bun.isSliceInBuffer(rest, text)); + std.debug.assert(rest.len == 0 or bun.isSliceInBuffer(u8, rest, text)); while (rest.len > 0) { const c = rest[0]; diff --git a/src/options.zig b/src/options.zig index 99d727c5fc..309cf858fa 100644 --- a/src/options.zig +++ b/src/options.zig @@ -2587,11 +2587,24 @@ pub const PathTemplate = struct { return strings.contains(this.data, comptime "[" ++ @tagName(field) ++ "]"); } + inline fn writeReplacingSlashesOnWindows(w: anytype, slice: []const u8) !void { + if (Environment.isWindows) { + var remain = slice; + while (strings.indexOfChar(remain, '/')) |i| { + try w.writeAll(remain[0..i]); + try w.writeByte('\\'); + remain = remain[i + 1 ..]; + } + try w.writeAll(remain); + } else { + try w.writeAll(slice); + } + } + pub fn format(self: PathTemplate, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { var remain = self.data; - bun.path.posixToPlatformInPlace(u8, @constCast(remain)); while (strings.indexOfChar(remain, '[')) |j| { - try writer.writeAll(remain[0..j]); + try writeReplacingSlashesOnWindows(writer, remain[0..j]); remain = remain[j + 1 ..]; if (remain.len == 0) { // TODO: throw error @@ -2618,15 +2631,15 @@ pub const PathTemplate = struct { const placeholder = remain[0..end_len]; const field = PathTemplate.Placeholder.map.get(placeholder) orelse { - try writer.writeAll(placeholder); + try writeReplacingSlashesOnWindows(writer, placeholder); remain = remain[end_len..]; continue; }; switch (field) { - .dir => try writer.writeAll(if (self.placeholder.dir.len > 0) self.placeholder.dir else "."), - .name => try writer.writeAll(self.placeholder.name), - .ext => try writer.writeAll(self.placeholder.ext), + .dir => try writeReplacingSlashesOnWindows(writer, if (self.placeholder.dir.len > 0) self.placeholder.dir else "."), + .name => try writeReplacingSlashesOnWindows(writer, self.placeholder.name), + .ext => try writeReplacingSlashesOnWindows(writer, self.placeholder.ext), .hash => { if (self.placeholder.hash) |hash| { try writer.print("{any}", .{(hashFormatter(hash))}); @@ -2636,7 +2649,7 @@ pub const PathTemplate = struct { remain = remain[end_len + 1 ..]; } - try writer.writeAll(remain); + try writeReplacingSlashesOnWindows(writer, remain); } pub const hashFormatter = bun.fmt.hexIntLower; diff --git a/src/resolver/resolve_path.zig b/src/resolver/resolve_path.zig index 130d6cf466..38493afcdd 100644 --- a/src/resolver/resolve_path.zig +++ b/src/resolver/resolve_path.zig @@ -477,8 +477,9 @@ pub fn dirname(str: []const u8, comptime platform: Platform) []const u8 { } } -threadlocal var relative_from_buf: [4096]u8 = undefined; -threadlocal var relative_to_buf: [4096]u8 = undefined; +threadlocal var relative_from_buf: bun.PathBuffer = undefined; +threadlocal var relative_to_buf: bun.PathBuffer = undefined; + pub fn relative(from: []const u8, to: []const u8) []const u8 { return relativePlatform(from, to, .auto, false); } @@ -736,7 +737,10 @@ pub fn normalizeStringGenericTZ( } } else { // drive letter - buf[buf_i] = path_[0]; + buf[buf_i] = switch (path_[0]) { + 'a'...'z' => path_[0] & (std.math.maxInt(T) ^ (1 << 5)), + else => path_[0], + }; buf[buf_i + 1] = ':'; buf_i += 2; dotdot = buf_i; @@ -1180,7 +1184,7 @@ pub fn joinZ(_parts: anytype, comptime _platform: Platform) [:0]const u8 { pub fn joinZBuf(buf: []u8, _parts: anytype, comptime _platform: Platform) [:0]const u8 { const joined = joinStringBuf(buf[0 .. buf.len - 1], _parts, _platform); - std.debug.assert(bun.isSliceInBuffer(joined, buf)); + std.debug.assert(bun.isSliceInBuffer(u8, joined, buf)); const start_offset = @intFromPtr(joined.ptr) - @intFromPtr(buf.ptr); buf[joined.len + start_offset] = 0; return buf[start_offset..][0..joined.len :0]; diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 33d0118659..caeaf66101 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -876,14 +876,13 @@ pub const Resolver = struct { }; } - // When using `bun build --compile`, module resolution is never relative - // to our special /$bunfs/ directory. + // When using `bun build --compile`, module resolution is never + // relative to our special /$bunfs/ directory. // - // It's always relative to the current working directory of the project - // root. + // It's always relative to the current working directory of the project root. const source_dir = brk: { if (r.standalone_module_graph) |graph| { - if (strings.isBunStandaloneFilePath(import_path)) { + if (bun.StandaloneModuleGraph.isBunStandaloneFilePath(import_path)) { if (graph.files.contains(import_path)) { return .{ .success = Result{ @@ -898,7 +897,7 @@ pub const Resolver = struct { } return .{ .not_found = {} }; - } else if (strings.isBunStandaloneFilePath(source_dir_)) { + } else if (bun.StandaloneModuleGraph.isBunStandaloneFilePath(source_dir_)) { break :brk Fs.FileSystem.instance.top_level_dir; } } diff --git a/src/string_immutable.zig b/src/string_immutable.zig index bf000a66e2..f59c365f63 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -735,7 +735,7 @@ pub fn withoutTrailingSlashWindowsPath(this: string) []const u8 { } pub fn withTrailingSlash(dir: string, in: string) []const u8 { - if (comptime Environment.allow_assert) std.debug.assert(bun.isSliceInBuffer(dir, in)); + if (comptime Environment.allow_assert) std.debug.assert(bun.isSliceInBuffer(u8, dir, in)); return in[0..@min(strings.withoutTrailingSlash(in[0..@min(dir.len + 1, in.len)]).len + 1, in.len)]; } @@ -869,10 +869,6 @@ pub fn hasPrefixComptime(self: string, comptime alt: anytype) bool { return self.len >= alt.len and eqlComptimeCheckLenWithType(u8, self[0..alt.len], alt, false); } -pub fn isBunStandaloneFilePath(self: string) bool { - return hasPrefixComptime(self, "/$bunfs/"); -} - pub fn hasPrefixComptimeUTF16(self: []const u16, comptime alt: []const u8) bool { return self.len >= alt.len and eqlComptimeCheckLenWithType(u16, self[0..alt.len], comptime toUTF16Literal(alt), false); } diff --git a/src/string_mutable.zig b/src/string_mutable.zig index b485e5defa..cdf89173ca 100644 --- a/src/string_mutable.zig +++ b/src/string_mutable.zig @@ -37,7 +37,7 @@ pub const MutableString = struct { } pub fn owns(this: *const MutableString, slice: []const u8) bool { - return @import("root").bun.isSliceInBuffer(slice, this.list.items.ptr[0..this.list.capacity]); + return bun.isSliceInBuffer(u8, slice, this.list.items.ptr[0..this.list.capacity]); } pub fn growIfNeeded(self: *MutableString, amount: usize) !void { diff --git a/test/bundler/bun-build-api.test.ts b/test/bundler/bun-build-api.test.ts index 14a657ceba..f61e94a267 100644 --- a/test/bundler/bun-build-api.test.ts +++ b/test/bundler/bun-build-api.test.ts @@ -1,9 +1,11 @@ -// @known-failing-on-windows: 1 failing import { test, expect, describe } from "bun:test"; import { readFileSync } from "fs"; import { bunEnv, bunExe } from "harness"; import { join } from "path"; +// TODO(@paperdave) +const todoOnWindows = process.platform === "win32" ? test.todo : test; + describe("Bun.build", () => { test("passing undefined doesnt segfault", () => { try { @@ -77,7 +79,7 @@ describe("Bun.build", () => { Bun.gc(true); }); - test("rebuilding busts the directory entries cache", () => { + todoOnWindows("rebuilding busts the directory entries cache", () => { Bun.gc(true); const { exitCode, stderr } = Bun.spawnSync({ cmd: [bunExe(), join(import.meta.dir, "bundler-reloader-script.ts")], diff --git a/test/bundler/bundler_compile.test.ts b/test/bundler/bundler_compile.test.ts index 11370f213e..70c2827656 100644 --- a/test/bundler/bundler_compile.test.ts +++ b/test/bundler/bundler_compile.test.ts @@ -1,4 +1,3 @@ -// @known-failing-on-windows: panic "TODO on Windows" import assert from "assert"; import dedent from "dedent"; import { ESBUILD, itBundled, testForFile } from "./expectBundled"; @@ -25,9 +24,16 @@ describe("bundler", () => { if (pathToFileURL(import.meta.path).href !== import.meta.url) throw "fail"; `, }, - run: { stdout: `file:///$bunfs/root/out /$bunfs/root/out`, setCwd: true }, + run: { + stdout: + process.platform !== "win32" + ? `file:///$bunfs/root/out /$bunfs/root/out` + : `file:///B:/~BUN/root/out B:\\~BUN\\root\\out`, + setCwd: true, + }, }); itBundled("compile/VariousBunAPIs", { + todo: process.platform === "win32", // TODO(@paperdave) compile: true, files: { "/entry.ts": ` @@ -180,7 +186,7 @@ describe("bundler", () => { }, compile: true, }); - itBundled("compile/embedded-sqlite-file", { + itBundled("compile/EmbeddedSqlite", { compile: true, files: { "/entry.ts": /* js */ ` diff --git a/test/bundler/bundler_npm.test.ts b/test/bundler/bundler_npm.test.ts index 581b2442fc..30ffc333a2 100644 --- a/test/bundler/bundler_npm.test.ts +++ b/test/bundler/bundler_npm.test.ts @@ -1,4 +1,3 @@ -// @known-failing-on-windows: panic "TODO on Windows" import assert from "assert"; import dedent from "dedent"; import { ESBUILD, itBundled, testForFile } from "./expectBundled"; @@ -6,6 +5,7 @@ var { describe, test, expect } = testForFile(import.meta.path); describe("bundler", () => { itBundled("npm/ReactSSR", { + todo: process.platform === "win32", // TODO(@paperdave) install: ["react@next", "react-dom@next"], files: { "/entry.tsx": /* tsx */ ` diff --git a/test/bundler/bundler_plugin.test.ts b/test/bundler/bundler_plugin.test.ts index f461bba077..35313dbff1 100644 --- a/test/bundler/bundler_plugin.test.ts +++ b/test/bundler/bundler_plugin.test.ts @@ -514,7 +514,7 @@ describe("bundler", () => { }; }); itBundled("plugin/ManyFiles", ({ root }) => { - const FILES = 200; + const FILES = process.platform === "win32" ? 50 : 200; // windows is slower at this const create = (fn: (i: number) => string) => new Array(FILES).fill(0).map((_, i) => fn(i)); let onResolveCount = 0; @@ -818,7 +818,7 @@ describe("bundler", () => { plugins(build) { const opts = (build as any).initialOptions; expect(opts.bundle).toEqual(true); - expect(opts.entryPoints).toEqual([root + "/index.ts"]); + expect(opts.entryPoints).toEqual([root + path.sep + "index.ts"]); expect(opts.external).toEqual(["esbuild"]); expect(opts.format).toEqual(undefined); expect(opts.minify).toEqual(false); diff --git a/test/bundler/esbuild/default.test.ts b/test/bundler/esbuild/default.test.ts index feda2a00f1..dc9ccf695a 100644 --- a/test/bundler/esbuild/default.test.ts +++ b/test/bundler/esbuild/default.test.ts @@ -1,8 +1,8 @@ -// @known-failing-on-windows: 1 failing import assert from "assert"; import dedent from "dedent"; import { ESBUILD_PATH, RUN_UNCHECKED_TESTS, itBundled, testForFile } from "../expectBundled"; +import { osSlashes } from "harness"; var { describe, test, expect } = testForFile(import.meta.path); // Tests ported from: // https://github.com/evanw/esbuild/blob/main/internal/bundler_tests/bundler_default_test.go @@ -5176,6 +5176,7 @@ describe("bundler", () => { run: { runtime: "node", file: "/test.mjs", + // using os slashes here is correct because we run the bundle in bun. stdout: ` function undefined string "function" @@ -5185,8 +5186,8 @@ describe("bundler", () => { object {"works":true} object {"works":true} number 567 - string "/node_modules/some-path/index.js" - string "/node_modules/second-path/index.js" + string ${JSON.stringify(osSlashes("/node_modules/some-path/index.js"))} + string ${JSON.stringify(osSlashes("/node_modules/second-path/index.js"))} object {"default":123} object {"default":567} `, @@ -5211,8 +5212,8 @@ describe("bundler", () => { object {"works":true} object {"works":true} number 567 - string "/node_modules/some-path/index.js" - string "/node_modules/second-path/index.js" + string ${JSON.stringify(osSlashes("/node_modules/some-path/index.js"))} + string ${JSON.stringify(osSlashes("/node_modules/second-path/index.js"))} object {"default":123} object {"default":567} `, diff --git a/test/bundler/esbuild/loader.test.ts b/test/bundler/esbuild/loader.test.ts index c76fdd18ac..ec4e29535b 100644 --- a/test/bundler/esbuild/loader.test.ts +++ b/test/bundler/esbuild/loader.test.ts @@ -64,6 +64,7 @@ describe("bundler", () => { ], }); itBundled("loader/File", { + todo: process.platform === "win32", // TODO(@paperdave) files: { "/entry.js": ` import path from 'path'; @@ -84,6 +85,7 @@ describe("bundler", () => { }, }); itBundled("loader/FileMultipleNoCollision", { + todo: process.platform === "win32", // TODO(@paperdave) files: { "/entry.js": /* js */ ` import path from 'path'; @@ -109,6 +111,7 @@ describe("bundler", () => { }, }); itBundled("loader/FileMultipleNoCollisionAssetNames", { + todo: process.platform === "win32", // TODO(@paperdave) files: { "/entry.js": /* js */ ` import path from 'path'; diff --git a/test/bundler/expectBundled.ts b/test/bundler/expectBundled.ts index 2cf4dff3ce..22768a2e70 100644 --- a/test/bundler/expectBundled.ts +++ b/test/bundler/expectBundled.ts @@ -3,7 +3,6 @@ */ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs"; import path from "path"; -import dedent from "dedent"; import { bunEnv, bunExe } from "harness"; import { tmpdir } from "os"; import { callerSourceOrigin } from "bun:jsc"; @@ -12,6 +11,38 @@ import type { Expect } from "bun:test"; import { PluginBuilder } from "bun"; import * as esbuild from "esbuild"; +/** Dedent module does a bit too much with their stuff. we will be much simpler */ +function dedent(str: string | TemplateStringsArray, ...args: any[]) { + // https://github.com/tc39/proposal-string-cooked#motivation + let single_string = String.raw({ raw: str }, ...args); + single_string = single_string.trim(); + + let lines = single_string.split("\n"); + let first_line = lines[0]; + let smallest_indent = Infinity; + for (let line of lines.slice(1)) { + let match = line.match(/^\s+/); + if (match) { + smallest_indent = Math.min(smallest_indent, match[0].length); + } else { + return single_string; + } + } + + if (smallest_indent === Infinity) { + return single_string; + } + + return ( + first_line + + "\n" + + lines + .slice(1) + .map(x => x.slice(smallest_indent)) + .join("\n") + ); +} + let currentFile: string | undefined; function errorOrWarnParser(isError = true) { @@ -621,11 +652,18 @@ function expectBundled( .map(x => String(x)) as [string, ...string[]]; if (DEBUG) { - writeFileSync( - path.join(root, "run.sh"), - "#!/bin/sh\n" + + if (process.platform !== "win32") { + writeFileSync( + path.join(root, "run.sh"), + "#!/bin/sh\n" + + cmd.map(x => (x.match(/^[a-z0-9_:=\./\\-]+$/i) ? x : `"${x.replace(/"/g, '\\"')}"`)).join(" "), + ); + } else { + writeFileSync( + path.join(root, "run.ps1"), cmd.map(x => (x.match(/^[a-z0-9_:=\./\\-]+$/i) ? x : `"${x.replace(/"/g, '\\"')}"`)).join(" "), - ); + ); + } try { mkdirSync(path.join(root, ".vscode"), { recursive: true }); } catch (e) {} @@ -639,30 +677,22 @@ function expectBundled( ...(compile ? [ { - "type": "lldb", + "type": process.platform !== "win32" ? "lldb" : "cppvsdbg", "request": "launch", "name": "run compiled exe", "program": outfile, "args": [], "cwd": root, - "env": { - "FORCE_COLOR": "1", - }, - "console": "internalConsole", }, ] : []), { - "type": "lldb", + "type": process.platform !== "win32" ? "lldb" : "cppvsdbg", "request": "launch", "name": "bun test", "program": cmd[0], "args": cmd.slice(1), "cwd": root, - "env": { - "FORCE_COLOR": "1", - }, - "console": "internalConsole", }, ], }, @@ -1291,6 +1321,9 @@ for (const [key, blob] of build.outputs) { console.log(`reference stdout:`); console.log(result); console.log(`---`); + console.log(`expected stdout:`); + console.log(expected); + console.log(`---`); } expect(result).toBe(expected); } else { diff --git a/test/cli/test/bun-test.test.ts b/test/cli/test/bun-test.test.ts index f835d1ee00..0c0e6fc61d 100644 --- a/test/cli/test/bun-test.test.ts +++ b/test/cli/test/bun-test.test.ts @@ -293,7 +293,7 @@ describe("bun test", () => { }); `, }); - expect(stderr).toContain("Bailed out after 1 failures"); + expect(stderr).toContain("Bailed out after 1 failure"); expect(stderr).not.toContain("test #2"); }); diff --git a/test/harness.ts b/test/harness.ts index e80d82c480..fd17a31d4e 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -434,3 +434,7 @@ export async function describeWithContainer( fn(port); }); } + +export function osSlashes(path: string) { + return isWindows ? path.replace(/\//g, "\\") : path; +} diff --git a/test/js/node/v8/v8-date-parser.test.js b/test/js/node/v8/v8-date-parser.test.js index 6b92536059..73fc6786f6 100644 --- a/test/js/node/v8/v8-date-parser.test.js +++ b/test/js/node/v8/v8-date-parser.test.js @@ -1,4 +1,3 @@ -// @known-failing-on-windows: 1 failing // Copyright 2013 the V8 project authors. All rights reserved. // Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. // @@ -21,6 +20,7 @@ // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +const todoOnWindows = process.platform === "win32" ? test.todo : test; describe("v8 date parser", () => { // https://github.com/v8/v8/blob/c45b7804109ece574f71fd45417b4ad498a99e6f/test/webkit/date-parse-comments-test.js#L27 @@ -438,7 +438,8 @@ describe("v8 date parser", () => { }); // https://github.com/v8/v8/blob/c45b7804109ece574f71fd45417b4ad498a99e6f/test/intl/regress-1451943.js#L5 - test("test/intl/regress-1451943.js", () => { + // TODO: fix this on windows, see https://github.com/v8/v8/commit/8cf4ef33389eb4f47b37ffede388dbdcce16e1ee#diff-9adde1d14b1ec0068b077d06b5dadf0aae9717f63c809263604f9853d27d11db + todoOnWindows("test/intl/regress-1451943.js", () => { let beforeOct1582GregorianTransition = new Date("1582-01-01T00:00Z"); let afterOct1582GregorianTransition = new Date("1583-01-01T00:00Z");