diff --git a/CMakeLists.txt b/CMakeLists.txt index f11363a7fe..7d940561ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,9 +48,9 @@ endif() option(USE_STATIC_SQLITE "Statically link SQLite?" DEFAULT_USE_STATIC_SQLITE) option(USE_CUSTOM_ZLIB "Use Bun's recommended version of zlib" DEFAULT_CUSTOM_UNLESS_WINDOWS) option(USE_CUSTOM_BORINGSSL "Use Bun's recommended version of BoringSSL" ON) -option(USE_CUSTOM_LIBARCHIVE "Use Bun's recommended version of libarchive" OFF) -option(USE_CUSTOM_MIMALLOC "Use Bun's recommended version of Mimalloc" DEFAULT_CUSTOM_UNLESS_WINDOWS) -option(USE_CUSTOM_ZSTD "Use Bun's recommended version of zstd`" DEFAULT_CUSTOM_UNLESS_WINDOWS) +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" DEFAULT_CUSTOM_UNLESS_WINDOWS) option(USE_CUSTOM_BASE64 "Use Bun's recommended version of libbase64" ON) option(USE_CUSTOM_LOLHTML "Use Bun's recommended version of lolhtml" ON) @@ -270,7 +270,15 @@ add_custom_command( # ) -add_executable(bun ${bun_SRC} ${uSockets_FILES} ${BUN_OBJECT_FILE} ${EXTRA_SRC}) + + +add_executable(bun WIN32 ${bun_SRC} ${uSockets_FILES} ${BUN_OBJECT_FILE} ${EXTRA_SRC}) +# Set /subsystem:console on bun for windows + +if (WIN32) + set_target_properties(bun PROPERTIES LINK_FLAGS " /SUBSYSTEM:CONSOLE ") +endif() + set_target_properties(bun PROPERTIES CXX_STANDARD 20 @@ -355,7 +363,7 @@ endif() if (USE_CUSTOM_LIBARCHIVE) include_directories(src/deps/libarchive/include) if (WIN32) - target_link_libraries(bun PRIVATE "${BUN_LIB_DIR}/archive_static.lib") + target_link_libraries(bun PRIVATE "${BUN_LIB_DIR}/archive.lib") else() target_link_libraries(bun PRIVATE "${BUN_LIB_DIR}/libarchive.a") endif() @@ -379,13 +387,13 @@ endif() if (USE_CUSTOM_ZSTD) include_directories(src/deps/zstd/include) if (WIN32) - target_link_libraries(bun PRIVATE "${BUN_LIB_DIR}/zstd_static.lib") + target_link_libraries(bun PRIVATE "${BUN_LIB_DIR}/zstd.lib") else() target_link_libraries(bun PRIVATE "${BUN_LIB_DIR}/libzstd.a") endif() else () find_package(zstd CONFIG REQUIRED) - target_link_libraries(bun PRIVATE zstd::libzstd_static>) + target_link_libraries(bun PRIVATE zstd::libzstd) endif() if (USE_CUSTOM_CARES) @@ -427,9 +435,8 @@ if (NOT WIN32) endif() set_property(TARGET bun PROPERTY - MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") - set_property(TARGET bun PROPERTY - MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") + MSVC_RUNTIME_LIBRARY "MultiThreadedDLL" +) if (USE_CUSTOM_LOLHTML) if (WIN32) @@ -480,17 +487,25 @@ else() string (APPEND CMAKE_CXX_FLAGS " /external:anglebrackets " ) + set_target_properties(bun PROPERTIES LINK_FLAGS " /SUBSYSTEM:CONSOLE /STACK:4194304,4194304 ") endif() if (DEFINED ENV{VCPKG_ROOT}) include_directories($ENV{VCPKG_ROOT}/installed/x64-windows/include) endif() + # include_directories(C:/Users/windo/Build/WebKit/WebKitBuild/WTF/DerivedSources) + # include_directories(C:/Users/windo/Build/WebKit/WebKitBuild/WTF/Headers) file(COPY C:/Users/windo/Code/WebKit/WebKitBuild/cmakeconfig.h DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings) + include_directories(C:/Users/windo/Code/WebKit/WebKitLibraries/win/include) link_directories(C:/Users/windo/Code/WebKit/WebKitLibraries/win/lib64) - link_libraries(icudata.lib icui8n.lib icu8uc.lib NtosKrnl winmm.lib Bcrypt.lib ntdl NtosKrnl) + target_link_directories(bun PUBLIC ${ICU_LIBRARY}) + + + target_link_libraries(bun PUBLIC icuuc icudt icutu icuio icuin icutest) + target_link_libraries(bun PUBLIC winmm ws2_32 bcrypt ntdll kernel32 shell32 shlwapi advapi32 vcruntime ucrt legacy_stdio_definitions) endif() diff --git a/src/bun.js/bindings/workaround-missing-symbols.cpp b/src/bun.js/bindings/workaround-missing-symbols.cpp index 9881d6124a..be896a8b61 100644 --- a/src/bun.js/bindings/workaround-missing-symbols.cpp +++ b/src/bun.js/bindings/workaround-missing-symbols.cpp @@ -1,14 +1,42 @@ #if defined(WIN32) + #include #include #include #include #include - +#include #include +#include +#undef _environ +#undef environ + +// TODO: figure out why these symbols were not already defined +extern "C" char** environ = nullptr; +extern "C" char** _environ = nullptr; + +// TODO: figure out why the stack check symbols are missing +extern "C" void __stack_chk_fail() { abort(); } +extern "C" void ___chkstk_ms() {} +extern "C" size_t __stack_chk_guard = 0; + +extern "C" int windows_main(int argc, char** argv, char** envp); + +extern "C" int __main() +{ + environ = *__p__environ(); +// TODO: figure out why the stack check symbols are missing +#ifdef BUN_DEBUG + __stack_chk_guard = 0xdeadbeefd00dfeed; +#endif + _environ = environ; + +// this is a workaround for an infinite loop that happens if we call main directly + return windows_main(__argc, __argv, environ); +} extern "C" int strncasecmp(const char* s1, const char* s2, size_t n) { @@ -19,6 +47,7 @@ extern "C" int fstat64( _In_ int _FileHandle, _Out_ struct _stat64* _Stat) { + return _fstat64(_FileHandle, _Stat); } diff --git a/src/bun.zig b/src/bun.zig index f1a1c5a259..8fd6ae771b 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -716,7 +716,7 @@ pub fn rangeOfSliceInBuffer(slice: []const u8, buffer: []const u8) ?[2]u32 { pub const invalid_fd = if (Environment.isWindows) // on windows, max usize is the process handle, a very valid fd - std.math.maxInt(i32) + 1 + std.math.maxInt(usize) else std.math.maxInt(FileDescriptor); @@ -1730,11 +1730,9 @@ pub const win32 = struct { pub var STDOUT_FD: FileDescriptor = undefined; pub var STDERR_FD: FileDescriptor = undefined; pub var STDIN_FD: FileDescriptor = undefined; - var argv_: [][*:0]u8 = undefined; - var args_buf: [255][*:0]u8 = undefined; pub inline fn argv() [][*:0]u8 { - return argv_; + return std.os.argv; } pub fn stdio(i: anytype) FileDescriptor { @@ -1746,46 +1744,6 @@ pub const win32 = struct { }; } - pub fn populateArgv() void { - const kernel32 = windows; - - var wargv_all = kernel32.GetCommandLineW(); - var num_args: c_int = 0; - var start = kernel32.CommandLineToArgvW(wargv_all, &num_args); - defer _ = kernel32.LocalFree(@ptrCast(start)); - var wargv = start[0..@as(usize, @intCast(num_args))]; - var argv_list = std.ArrayList([*:0]u8).init(default_allocator); - argv_list.items = &args_buf; - argv_list.capacity = args_buf.len; - - if (wargv.len > args_buf.len) { - var ptrs = default_allocator.alloc(?[*]u8, wargv.len + 1) catch unreachable; - ptrs[ptrs.len - 1] = null; - argv_list.items = @ptrCast(ptrs[0 .. ptrs.len - 1]); - argv_list.capacity = argv_list.items.len + 1; - } - - const probably_overestimated_length = strings.elementLengthUTF16IntoUTF8([]const u16, sliceTo(wargv_all, 0)) + argv_list.items.len; - var buf = default_allocator.alloc(u8, probably_overestimated_length) catch unreachable; - var builder = StringBuilder{ - .cap = probably_overestimated_length, - .ptr = buf.ptr, - .len = 0, - }; - - for (wargv) |warg_| { - var warg = sliceTo(warg_, 0); - argv_list.appendAssumeCapacity( - (builder.append16(warg) orelse brk: { - var list = strings.convertUTF16ToUTF8(std.ArrayList(u8).init(default_allocator), []const u16, warg) catch unreachable; - list.append(0) catch unreachable; - break :brk list.items.ptr[0..list.items.len :0]; - }).ptr, - ); - } - - argv_ = argv_list.items.ptr[0..argv_list.items.len]; - } }; pub usingnamespace if (@import("builtin").target.os.tag != .windows) posix else win32; diff --git a/src/cli.zig b/src/cli.zig index c68297baa0..78e0f975a2 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -1195,29 +1195,33 @@ pub const Command = struct { // _ = BunxCommand; } - if (try bun.StandaloneModuleGraph.fromExecutable(bun.default_allocator)) |graph| { - var ctx = Command.Context{ - .args = std.mem.zeroes(Api.TransformOptions), - .log = log, - .start_time = start_time, - .allocator = bun.default_allocator, - }; + // there's a bug with openSelfExe() on Windows + if (comptime !bun.Environment.isWindows) { + // bun build --compile entry point + if (try bun.StandaloneModuleGraph.fromExecutable(bun.default_allocator)) |graph| { + var ctx = Command.Context{ + .args = std.mem.zeroes(Api.TransformOptions), + .log = log, + .start_time = start_time, + .allocator = bun.default_allocator, + }; - ctx.args.target = Api.Target.bun; - var argv = try bun.default_allocator.alloc(string, bun.argv().len -| 1); - if (bun.argv().len > 1) { - for (argv, bun.argv()[1..]) |*dest, src| { - dest.* = bun.span(src); + ctx.args.target = Api.Target.bun; + var argv = try bun.default_allocator.alloc(string, bun.argv().len -| 1); + if (bun.argv().len > 1) { + for (argv, bun.argv()[1..]) |*dest, src| { + dest.* = bun.span(src); + } } - } - ctx.passthrough = argv; + ctx.passthrough = argv; - try @import("./bun_js.zig").Run.bootStandalone( - ctx, - graph.entryPoint().name, - graph, - ); - return; + try @import("./bun_js.zig").Run.bootStandalone( + ctx, + graph.entryPoint().name, + graph, + ); + return; + } } const tag = which(); diff --git a/src/cli/create_command.zig b/src/cli/create_command.zig index 8264bf771e..3edd89d592 100644 --- a/src/cli/create_command.zig +++ b/src/cli/create_command.zig @@ -700,7 +700,12 @@ pub const CreateCommand = struct { { var parent_dir = try std.fs.openDirAbsolute(destination, .{}); defer parent_dir.close(); - std.os.linkat(parent_dir.fd, "gitignore", parent_dir.fd, ".gitignore", 0) catch {}; + if (comptime Environment.isWindows) { + try parent_dir.copyFile("gitignore", parent_dir, ".gitignore", .{}); + } else { + std.os.linkat(parent_dir.fd, "gitignore", parent_dir.fd, ".gitignore", 0) catch {}; + } + std.os.unlinkat( parent_dir.fd, "gitignore", diff --git a/src/main.zig b/src/main.zig index 52cf33d531..aca3a86307 100644 --- a/src/main.zig +++ b/src/main.zig @@ -15,9 +15,7 @@ pub fn main() void { const bun = @import("root").bun; const Output = bun.Output; const Environment = bun.Environment; - if (comptime Environment.isWindows) { - bun.win32.populateArgv(); - } + if (comptime Environment.isRelease) CrashReporter.start() catch unreachable; @@ -41,8 +39,25 @@ pub fn main() void { bun.CLI.Cli.start(bun.default_allocator, stdout, stderr, MainPanicHandler); } +pub export fn windows_main(argc: c_int, argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) callconv(.C) c_int { + var env_count: usize = 0; + while (c_envp[env_count] != null) : (env_count += 1) {} + const envp = @as([*][*:0]u8, @ptrCast(c_envp))[0..env_count]; + + std.os.argv = @ptrCast(argv[0..@intCast(argc)]); + std.os.environ = envp; + + main(); + + return 0; +} + test "panic" { panic("woah", null); } pub const build_options = @import("build_options"); + +comptime { + _ = windows_main; +} \ No newline at end of file diff --git a/src/string_immutable.zig b/src/string_immutable.zig index c62266c62b..0d8d8d6bf1 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -1494,6 +1494,8 @@ pub fn toWPath(wbuf: []u16, utf8: []const u8) [:0]const u16 { // TODO: error handling // if (result.status == .surrogate) { // } + wbuf[result.count] = 0; + return wbuf[0..result.count :0]; }