diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ce6d8bc83986..6e272523d1fe8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,6 @@ set(CMAKE_C_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON) -# Should not start with v # Used in process.version, process.versions.node, napi, and elsewhere set(REPORTED_NODEJS_VERSION "22.3.0") @@ -58,11 +57,8 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release") set(DEFAULT_ZIG_OPTIMIZE "ReleaseFast") if(WIN32) - # lld-link will strip it for you, so we can build directly to bun.exe + # Debug symbols are in a separate file: bun.pdb 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() if(ZIG_OPTIMIZE STREQUAL "Debug") @@ -874,13 +870,24 @@ file(GLOB ZIG_FILES "${BUN_SRC}/*/*/*/*/*.zig" ) +if(NOT BUN_ZIG_OBJ_FORMAT) + # To use LLVM bitcode from Zig, more work needs to be done. Currently, an install of + # LLVM 18.1.7 does not compatible with what bitcode Zig 0.13 outputs (has LLVM 18.1.7) + # Change to "bc" to experiment, "Invalid record" means it is not valid output. + set(BUN_ZIG_OBJ_FORMAT "obj") +endif() + if(NOT BUN_ZIG_OBJ_DIR) set(BUN_ZIG_OBJ_DIR "${BUN_WORKDIR}/CMakeFiles") endif() get_filename_component(BUN_ZIG_OBJ_DIR "${BUN_ZIG_OBJ_DIR}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") -set(BUN_ZIG_OBJ "${BUN_ZIG_OBJ_DIR}/bun-zig.o") +if(WIN32) + set(BUN_ZIG_OBJ "${BUN_ZIG_OBJ_DIR}/bun-zig.o") +else() + set(BUN_ZIG_OBJ "${BUN_ZIG_OBJ_DIR}/bun-zig.o") +endif() set(USES_TERMINAL_NOT_IN_CI "") @@ -904,6 +911,7 @@ if(NOT BUN_LINK_ONLY AND NOT BUN_CPP_ONLY) "-Dtarget=${ZIG_TARGET}" "-Denable_logs=${ENABLE_LOGS}" "-Dreported_nodejs_version=${REPORTED_NODEJS_VERSION}" + "-Dobj_format=${BUN_ZIG_OBJ_FORMAT}" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/build.zig" "${ZIG_FILES}" @@ -1101,13 +1109,36 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release") if(USE_LTO) target_compile_options(${bun} PUBLIC -Xclang -emit-llvm-bc) - # -emit-llvm seems to not be supported or under a different name on Windows. list(APPEND LTO_FLAG "-flto=full") + list(APPEND LTO_LINK_FLAG "-flto=full") list(APPEND LTO_LINK_FLAG "/LTCG") + list(APPEND LTO_LINK_FLAG "/OPT:REF") + list(APPEND LTO_LINK_FLAG "/OPT:NOICF") endif() - target_compile_options(${bun} PUBLIC /O2 ${LTO_FLAG}) - target_link_options(${bun} PUBLIC ${LTO_LINK_FLAG} /DEBUG:FULL) + target_compile_options(${bun} PUBLIC + /O2 + ${LTO_FLAG} + /Gy + /Gw + /GF + /GA + ) + target_link_options(${bun} PUBLIC + ${LTO_LINK_FLAG} + /DEBUG:FULL + + /delayload:ole32.dll + /delayload:WINMM.dll + /delayload:dbghelp.dll + /delayload:VCRUNTIME140_1.dll + + # libuv loads these two immediately, but for some reason it seems to still be slightly faster to delayload them + /delayload:WS2_32.dll + /delayload:WSOCK32.dll + /delayload:ADVAPI32.dll + /delayload:IPHLPAPI.dll + ) endif() endif() @@ -1451,7 +1482,6 @@ if(NOT WIN32) 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" @@ -1464,6 +1494,7 @@ else() userenv dbghelp wsock32 # ws2_32 required by TransmitFile aka sendfile on windows + delayimp.lib ) endif() diff --git a/build.zig b/build.zig index 1c0e8b10ef599..d6cae3fc038b0 100644 --- a/build.zig +++ b/build.zig @@ -33,8 +33,6 @@ comptime { } } -const default_reported_nodejs_version = "22.3.0"; - const zero_sha = "0000000000000000000000000000000000000000"; const BunBuildOptions = struct { @@ -48,7 +46,7 @@ const BunBuildOptions = struct { sha: []const u8, enable_logs: bool = false, tracy_callstack_depth: u16, - reported_nodejs_version: []const u8 = default_reported_nodejs_version, + reported_nodejs_version: Version, generated_code_dir: []const u8, @@ -73,14 +71,7 @@ const BunBuildOptions = struct { opts.addOption([:0]const u8, "sha", b.allocator.dupeZ(u8, this.sha) catch @panic("OOM")); opts.addOption(bool, "baseline", this.isBaseline()); opts.addOption(bool, "enable_logs", this.enable_logs); - opts.addOption([:0]const u8, "reported_nodejs_version", b.allocator.dupeZ(u8, this.reported_nodejs_version) catch @panic("OOM")); - if (this.reported_nodejs_version.len > 0 and this.reported_nodejs_version[0] == 'v') { - @panic("Node.js version should not start with 'v'"); - } - - if (this.reported_nodejs_version.len == 0) { - @panic("Node.js version should not be empty"); - } + opts.addOption([]const u8, "reported_nodejs_version", b.fmt("{}", .{this.reported_nodejs_version})); const mod = opts.createModule(); this.cached_options_module = mod; @@ -122,6 +113,23 @@ pub fn getOSGlibCVersion(os: OperatingSystem) ?Version { }; } +pub fn getCpuModel(os: OperatingSystem, arch: Arch) ?Target.Query.CpuModel { + // https://github.com/oven-sh/bun/issues/12076 + if (os == .linux and arch == .aarch64) { + return .{ .explicit = &Target.aarch64.cpu.cortex_a35 }; + } + + // Be explicit and ensure we do not accidentally target a newer M-series chip + if (os == .mac and arch == .aarch64) { + return .{ .explicit = &Target.aarch64.cpu.apple_m1 }; + } + + // note: x86_64 is dealt with in the CMake config and passed in. + // the reason for the explicit handling on aarch64 is due to troubles + // passing the exact target in via flags. + return null; +} + pub fn build(b: *Build) !void { std.log.info("zig compiler v{s}", .{builtin.zig_version_string}); @@ -147,9 +155,12 @@ pub fn build(b: *Build) !void { break :brk .{ os, arch }; }; - if (os == .linux and arch == .aarch64) { - // #12076 - target_query.cpu_model = .{ .explicit = &std.Target.aarch64.cpu.cortex_a35 }; + // target must be refined to support older but very popular devices on + // aarch64, this means moving the minimum supported CPU to support certain + // raspberry PIs. there are also a number of cloud hosts that use virtual + // machines with surprisingly out of date versions of glibc. + if (getCpuModel(os, arch)) |cpu_model| { + target_query.cpu_model = cpu_model; } target_query.os_version_min = getOSVersionMin(os); @@ -168,6 +179,8 @@ pub fn build(b: *Build) !void { break :ref_trace if (trace == 0) null else trace; }; + const obj_format = b.option(ObjectFormat, "obj_format", "Output file for object files") orelse .obj; + var build_options = BunBuildOptions{ .target = target, .optimize = optimize, @@ -183,7 +196,10 @@ pub fn build(b: *Build) !void { break :canary if (rev == 0) null else rev; }, - .reported_nodejs_version = b.option([]const u8, "reported_nodejs_version", "Reported Node.js version") orelse default_reported_nodejs_version, + .reported_nodejs_version = try Version.parse( + b.option([]const u8, "reported_nodejs_version", "Reported Node.js version") orelse + "0.0.0-unset", + ), .sha = sha: { const sha = b.option([]const u8, "sha", "Force the git sha") orelse @@ -229,7 +245,7 @@ pub fn build(b: *Build) !void { var step = b.step("obj", "Build Bun's Zig code as a .o file"); var bun_obj = addBunObject(b, &build_options); step.dependOn(&bun_obj.step); - step.dependOn(&b.addInstallFile(bun_obj.getEmittedBin(), "bun-zig.o").step); + step.dependOn(addInstallObjectFile(b, bun_obj, "bun-zig", obj_format)); } // zig build windows-shim @@ -257,95 +273,59 @@ pub fn build(b: *Build) !void { // zig build check-all { - var step = b.step("check-all", "Check for semantic analysis errors on all supported platforms"); - inline for (.{ + const step = b.step("check-all", "Check for semantic analysis errors on all supported platforms"); + addMultiCheck(b, step, build_options, &.{ .{ .os = .windows, .arch = .x86_64 }, .{ .os = .mac, .arch = .x86_64 }, .{ .os = .mac, .arch = .aarch64 }, .{ .os = .linux, .arch = .x86_64 }, .{ .os = .linux, .arch = .aarch64 }, - }) |check| { - inline for (.{ .Debug, .ReleaseFast }) |mode| { - const check_target = b.resolveTargetQuery(.{ - .os_tag = OperatingSystem.stdOSTag(check.os), - .cpu_arch = check.arch, - .cpu_model = if (check.os == .linux and check.arch == .aarch64) .{ .explicit = &std.Target.aarch64.cpu.cortex_a35 } else .{ .determined_by_cpu_arch = {} }, - .os_version_min = getOSVersionMin(check.os), - .glibc_version = getOSGlibCVersion(check.os), - }); - - var options = BunBuildOptions{ - .target = check_target, - .os = check.os, - .arch = check_target.result.cpu.arch, - .optimize = mode, - - .canary_revision = build_options.canary_revision, - .sha = build_options.sha, - .tracy_callstack_depth = build_options.tracy_callstack_depth, - .version = build_options.version, - .reported_nodejs_version = build_options.reported_nodejs_version, - .generated_code_dir = build_options.generated_code_dir, - }; - var obj = addBunObject(b, &options); - obj.generated_bin = null; - step.dependOn(&obj.step); - } - } + }); } // zig build check-windows { - var step = b.step("check-windows", "Check for semantic analysis errors on Windows x64"); - inline for (.{ + const step = b.step("check-windows", "Check for semantic analysis errors on Windows"); + addMultiCheck(b, step, build_options, &.{ .{ .os = .windows, .arch = .x86_64 }, - }) |check| { - inline for (.{ .Debug, .ReleaseFast }) |mode| { - const check_target = b.resolveTargetQuery(.{ - .os_tag = OperatingSystem.stdOSTag(check.os), - .cpu_arch = check.arch, - .os_version_min = getOSVersionMin(check.os), - .glibc_version = getOSGlibCVersion(check.os), - }); - - var options = BunBuildOptions{ - .target = check_target, - .os = check.os, - .arch = check_target.result.cpu.arch, - .optimize = mode, - .canary_revision = build_options.canary_revision, - .sha = build_options.sha, - .tracy_callstack_depth = build_options.tracy_callstack_depth, - .version = build_options.version, - .reported_nodejs_version = build_options.reported_nodejs_version, - .generated_code_dir = build_options.generated_code_dir, - }; - var obj = addBunObject(b, &options); - obj.generated_bin = null; - step.dependOn(&obj.step); - } - } + }); } +} - // Running `zig build` with no arguments is almost always a mistake. - // TODO: revive this error. cannot right now since ZLS runs zig build without arguments - { - // const mistake_message = b.addSystemCommand(&.{ - // "echo", - // \\ - // \\To build Bun from source, please use `bun run setup` instead of `zig build`" - // \\For more info, see https://bun.sh/docs/project/contributing - // \\ - // \\If you want to build the zig code in isolation, run: - // \\ 'zig build obj -Dgenerated-code=./build/codegen [...opts]' - // \\ - // \\If you want to test a compile without emitting an object: - // \\ 'zig build check' - // \\ 'zig build check-all' (run linux+mac+windows) - // \\ - // }); - - // b.default_step.dependOn(&mistake_message.step); +pub inline fn addMultiCheck( + b: *Build, + parent_step: *Step, + root_build_options: BunBuildOptions, + to_check: []const struct { os: OperatingSystem, arch: Arch }, +) void { + inline for (to_check) |check| { + inline for (.{ .Debug, .ReleaseFast }) |mode| { + const check_target = b.resolveTargetQuery(.{ + .os_tag = OperatingSystem.stdOSTag(check.os), + .cpu_arch = check.arch, + .cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_cpu_arch, + .os_version_min = getOSVersionMin(check.os), + .glibc_version = getOSGlibCVersion(check.os), + }); + + var options: BunBuildOptions = .{ + .target = check_target, + .os = check.os, + .arch = check_target.result.cpu.arch, + .optimize = mode, + + .canary_revision = root_build_options.canary_revision, + .sha = root_build_options.sha, + .tracy_callstack_depth = root_build_options.tracy_callstack_depth, + .version = root_build_options.version, + .reported_nodejs_version = root_build_options.reported_nodejs_version, + .generated_code_dir = root_build_options.generated_code_dir, + }; + + var obj = addBunObject(b, &options); + obj.generated_bin = null; + parent_step.dependOn(&obj.step); + } } } @@ -392,6 +372,25 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile { return obj; } +const ObjectFormat = enum { + bc, + obj, +}; + +pub fn addInstallObjectFile( + b: *Build, + compile: *Compile, + name: []const u8, + out_mode: ObjectFormat, +) *Step { + // bin always needed to be computed or else the compilation will do nothing. zig build system bug? + const bin = compile.getEmittedBin(); + return &b.addInstallFile(switch (out_mode) { + .obj => bin, + .bc => compile.getEmittedLlvmBc(), + }, b.fmt("{s}.o", .{name})).step; +} + fn exists(path: []const u8) bool { const file = std.fs.openFileAbsolute(path, .{ .mode = .read_only }) catch return false; file.close(); @@ -452,7 +451,11 @@ fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void { fn validateGeneratedPath(path: []const u8) void { if (!exists(path)) { - std.debug.panic("{s} does not exist in generated code directory!", .{std.fs.path.basename(path)}); + std.debug.panic( + \\Generated file '{s}' is missing! + \\ + \\Make sure to use CMake and Ninja, or pass a manual codegen folder with '-Dgenerated-code=...' + , .{path}); } } diff --git a/packages/bun-usockets/src/bsd.c b/packages/bun-usockets/src/bsd.c index b736a340a0a6b..c04b27fb0eaab 100644 --- a/packages/bun-usockets/src/bsd.c +++ b/packages/bun-usockets/src/bsd.c @@ -882,7 +882,7 @@ int bsd_connect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd, const char *host, int por } freeaddrinfo(result); - return LIBUS_SOCKET_ERROR; + return (int)LIBUS_SOCKET_ERROR; } int bsd_disconnect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd) { diff --git a/src/bun.js/bindings/wtf-bindings.cpp b/src/bun.js/bindings/wtf-bindings.cpp index 5bb26fbe55162..5e4ebcf1e3b0c 100644 --- a/src/bun.js/bindings/wtf-bindings.cpp +++ b/src/bun.js/bindings/wtf-bindings.cpp @@ -217,9 +217,9 @@ size_t toISOString(JSC::VM& vm, double date, char in[64]) GregorianDateTime gregorianDateTime; vm.dateCache.msToGregorianDateTime(date, WTF::TimeType::UTCTime, gregorianDateTime); - // Maximum amount of space we need in buffer: 7 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds) - // 6 for formatting and one for null termination = 28. We add one extra character to allow us to force null termination. - char buffer[28]; + // Maximum amount of space we need in buffer: 8 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds) + // 6 for formatting and one for null termination = 29. + char buffer[29]; // If the year is outside the bounds of 0 and 9999 inclusive we want to use the extended year format (ES 15.9.1.15.1). int ms = static_cast(fmod(date, msPerSecond)); if (ms < 0) diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js index beb5777282a5e..cb8b466fb593f 100644 --- a/test/js/node/process/process.test.js +++ b/test/js/node/process/process.test.js @@ -148,6 +148,12 @@ it("process.version starts with v", () => { expect(process.version.startsWith("v")).toBeTruthy(); }); +it("process.version is set", () => { + // This implies you forgot -Dreported_nodejs_version in zig build configuration + expect(process.version).not.toInclude("0.0.0"); + expect(process.version).not.toInclude("unset"); +}); + it.todo("process.argv0", () => { expect(basename(process.argv0)).toBe(basename(process.argv[0])); });