diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b64bcca81..807077476a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -590,6 +590,7 @@ set(ZIG_STD_FILES "os/freebsd/x86_64.zig" "os/path.zig" "os/time.zig" + "os/uefi.zig" "os/windows/advapi32.zig" "os/windows/error.zig" "os/windows/index.zig" diff --git a/README.md b/README.md index c1eec599e5..e9756b404d 100644 --- a/README.md +++ b/README.md @@ -87,26 +87,26 @@ clarity. #### Support Table -| | freestanding | linux | macosx | windows | freebsd | other | -|--------|--------------|--------|--------|---------|---------|--------| -|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 | -|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | -|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | -|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | -|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | -|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | -|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | -|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | -|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | +| | freestanding | linux | macosx | windows | freebsd | UEFI | other | +|--------|--------------|--------|--------|---------|---------|--------|--------| +|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 | +|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | +|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | +|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | +|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | +|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | +|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | +|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | +|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | ## Community diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig index 218353c9d7..36381b820d 100644 --- a/src-self-hosted/target.zig +++ b/src-self-hosted/target.zig @@ -520,7 +520,7 @@ pub const Target = union(enum) { => return 64, }, - builtin.Os.windows => switch (id) { + builtin.Os.windows, builtin.Os.uefi => switch (id) { CInt.Id.Short, CInt.Id.UShort, => return 16, diff --git a/src/all_types.hpp b/src/all_types.hpp index 11304e536d..2b55f8ee2e 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1750,12 +1750,11 @@ struct CodeGen { BuildMode build_mode; OutType out_type; ZigTarget zig_target; + TargetSubsystem subsystem; bool is_static; bool strip_debug_symbols; bool is_test_build; bool is_native_target; - bool windows_subsystem_windows; - bool windows_subsystem_console; bool linker_rdynamic; bool no_rosegment_workaround; bool each_lib_rpath; diff --git a/src/analyze.cpp b/src/analyze.cpp index 9c24f3cc8d..04d957b626 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3203,14 +3203,12 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi if (ccc) { if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) { g->have_c_main = true; - g->windows_subsystem_windows = false; - g->windows_subsystem_console = true; + g->subsystem = TargetSubsystemConsole; } else if (buf_eql_str(symbol_name, "WinMain") && g->zig_target.os == OsWindows) { g->have_winmain = true; - g->windows_subsystem_windows = true; - g->windows_subsystem_console = false; + g->subsystem = TargetSubsystemWindows; } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && g->zig_target.os == OsWindows) { @@ -3221,6 +3219,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi g->have_dllmain_crt_startup = true; } } + FnExport *fn_export = fn_table_entry->export_list.add_one(); memset(fn_export, 0, sizeof(FnExport)); buf_init_from_buf(&fn_export->name, symbol_name); @@ -4376,8 +4375,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r if (is_pub && ok_cc) { if (buf_eql_str(proto_name, "main")) { g->have_pub_main = true; - g->windows_subsystem_windows = false; - g->windows_subsystem_console = true; + g->subsystem = TargetSubsystemConsole; } else if (buf_eql_str(proto_name, "panic")) { g->have_pub_panic = true; } diff --git a/src/codegen.cpp b/src/codegen.cpp index e37703d5f0..bbf8ffa340 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -291,11 +291,6 @@ void codegen_add_framework(CodeGen *g, const char *framework) { g->darwin_frameworks.append(buf_create_from_str(framework)); } -void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) { - g->windows_subsystem_windows = mwindows; - g->windows_subsystem_console = mconsole; -} - void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min) { g->mmacosx_version_min = mmacosx_version_min; } @@ -7236,8 +7231,7 @@ static void init(CodeGen *g) { } if (g->is_test_build) { - g->windows_subsystem_windows = false; - g->windows_subsystem_console = true; + g->subsystem = TargetSubsystemConsole; } assert(g->root_out_name); @@ -7273,7 +7267,7 @@ static void init(CodeGen *g) { // LLVM creates invalid binaries on Windows sometimes. // See https://github.com/ziglang/zig/issues/508 // As a workaround we do not use target native features on Windows. - if (g->zig_target.os == OsWindows) { + if (g->zig_target.os == OsWindows || g->zig_target.os == OsUefi) { target_specific_cpu_args = ""; target_specific_features = ""; } else { @@ -7519,6 +7513,7 @@ static void gen_root_source(CodeGen *g) { report_errors_and_maybe_exit(g); if (!g->is_test_build && g->zig_target.os != OsFreestanding && + g->zig_target.os != OsUefi && !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup && ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe)) { @@ -8075,12 +8070,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_int(ch, g->zig_target.os); cache_int(ch, g->zig_target.env_type); cache_int(ch, g->zig_target.oformat); + cache_int(ch, g->subsystem); cache_bool(ch, g->is_static); cache_bool(ch, g->strip_debug_symbols); cache_bool(ch, g->is_test_build); cache_bool(ch, g->is_native_target); - cache_bool(ch, g->windows_subsystem_windows); - cache_bool(ch, g->windows_subsystem_console); cache_bool(ch, g->linker_rdynamic); cache_bool(ch, g->no_rosegment_workaround); cache_bool(ch, g->each_lib_rpath); diff --git a/src/codegen.hpp b/src/codegen.hpp index 1d39e4bf5e..6f1cdfb677 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -33,7 +33,6 @@ void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir); void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir); void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir); void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); -void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole); void codegen_add_lib_dir(CodeGen *codegen, const char *dir); void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib); LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib); diff --git a/src/link.cpp b/src/link.cpp index 188f976a86..593f7f309f 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -444,73 +444,20 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag); } -static void construct_linker_job_coff(LinkJob *lj) { +static void add_uefi_link_args(LinkJob *lj) { + lj->args.append("/BASE:0"); + lj->args.append("/ENTRY:EfiMain"); + lj->args.append("/OPT:REF"); + lj->args.append("/SAFESEH:NO"); + lj->args.append("/MERGE:.rdata=.data"); + lj->args.append("/ALIGN:32"); + lj->args.append("/NODEFAULTLIB"); + lj->args.append("/SECTION:.xdata,D"); +} + +static void add_nt_link_args(LinkJob *lj, bool is_library) { CodeGen *g = lj->codegen; - lj->args.append("/ERRORLIMIT:0"); - - if (g->libc_link_lib != nullptr) { - find_libc_lib_path(g); - } - - lj->args.append("-NOLOGO"); - - if (!g->strip_debug_symbols) { - lj->args.append("-DEBUG"); - } - - if (g->out_type == OutTypeExe) { - // TODO compile time stack upper bound detection - lj->args.append("/STACK:16777216"); - } - - coff_append_machine_arg(g, &lj->args); - - if (g->windows_subsystem_windows) { - lj->args.append("/SUBSYSTEM:windows"); - } else if (g->windows_subsystem_console) { - lj->args.append("/SUBSYSTEM:console"); - } - // The commented out stuff is from when we linked with MinGW - // Now that we're linking with LLD it remains to be determined - // how to handle --target-environ gnu - // These comments are a clue - - bool is_library = g->out_type == OutTypeLib; - //bool dll = g->out_type == OutTypeLib; - //bool shared = !g->is_static && dll; - //if (g->is_static) { - // lj->args.append("-Bstatic"); - //} else { - // if (dll) { - // lj->args.append("--dll"); - // } else if (shared) { - // lj->args.append("--shared"); - // } - // lj->args.append("-Bdynamic"); - // if (dll || shared) { - // lj->args.append("-e"); - // if (g->zig_target.arch.arch == ZigLLVM_x86) { - // lj->args.append("_DllMainCRTStartup@12"); - // } else { - // lj->args.append("DllMainCRTStartup"); - // } - // lj->args.append("--enable-auto-image-base"); - // } - //} - - lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); - - if (g->libc_link_lib != nullptr) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir)))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir)))); - - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir)))); - if (g->libc_static_lib_dir != nullptr) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir)))); - } - } - if (lj->link_in_crt) { const char *lib_str = g->is_static ? "lib" : ""; const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : ""; @@ -533,29 +480,180 @@ static void construct_linker_job_coff(LinkJob *lj) { //https://msdn.microsoft.com/en-us/library/bb531344.aspx lj->args.append("legacy_stdio_definitions.lib"); - //if (shared || dll) { - // lj->args.append(get_libc_file(g, "dllcrt2.o")); - //} else { - // if (g->windows_linker_unicode) { - // lj->args.append(get_libc_file(g, "crt2u.o")); - // } else { - // lj->args.append(get_libc_file(g, "crt2.o")); - // } - //} - //lj->args.append(get_libc_static_file(g, "crtbegin.o")); - // msvcrt depends on kernel32 lj->args.append("kernel32.lib"); } else { - lj->args.append("-NODEFAULTLIB"); + lj->args.append("/NODEFAULTLIB"); if (!is_library) { if (g->have_winmain) { - lj->args.append("-ENTRY:WinMain"); + lj->args.append("/ENTRY:WinMain"); } else { - lj->args.append("-ENTRY:WinMainCRTStartup"); + lj->args.append("/ENTRY:WinMainCRTStartup"); } } } +} + +// These are n actual command lines from LINK.EXE UEFI builds (app & driver) to be used as guidance cleaning +// up a bit for building the COFF linker args: +// /OUT:"J:\coding\nebulae\k\x64\Release\k.efi" /LTCG:incremental /Driver /PDB:"J:\coding\nebulae\k\x64\Release\k.pdb" "UefiApplicationEntryPoint.lib" "UefiRuntimeLib.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\nebulae\k\x64\Release\k.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_APPLICATION /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D" +// /OUT:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.efi" /LTCG:incremental /Driver /PDB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.pdb" "UefiDriverEntryPoint.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D" +// This commented out stuff is from when we linked with MinGW +// Now that we're linking with LLD it remains to be determined +// how to handle --target-environ gnu +// These comments are a clue +//bool dll = g->out_type == OutTypeLib; +//bool shared = !g->is_static && dll; +//if (g->is_static) { +// lj->args.append("-Bstatic"); +//} else { +// if (dll) { +// lj->args.append("--dll"); +// } else if (shared) { +// lj->args.append("--shared"); +// } +// lj->args.append("-Bdynamic"); +// if (dll || shared) { +// lj->args.append("-e"); +// if (g->zig_target.arch.arch == ZigLLVM_x86) { +// lj->args.append("_DllMainCRTStartup@12"); +// } else { +// lj->args.append("DllMainCRTStartup"); +// } +// lj->args.append("--enable-auto-image-base"); +// } +//} +//if (shared || dll) { +// lj->args.append(get_libc_file(g, "dllcrt2.o")); +//} else { +// if (g->windows_linker_unicode) { +// lj->args.append(get_libc_file(g, "crt2u.o")); +// } else { +// lj->args.append(get_libc_file(g, "crt2.o")); +// } +//} +//lj->args.append(get_libc_static_file(g, "crtbegin.o")); +//if (g->libc_link_lib != nullptr) { +//if (g->is_static) { +// lj->args.append("--start-group"); +//} + +//lj->args.append("-lmingw32"); + +//lj->args.append("-lgcc"); +//bool is_android = (g->zig_target.env_type == ZigLLVM_Android); +//bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target); +//if (!g->is_static && !is_android) { +// if (!is_cyg_ming) { +// lj->args.append("--as-needed"); +// } +// //lj->args.append("-lgcc_s"); +// if (!is_cyg_ming) { +// lj->args.append("--no-as-needed"); +// } +//} +//if (g->is_static && !is_android) { +// //lj->args.append("-lgcc_eh"); +//} +//if (is_android && !g->is_static) { +// lj->args.append("-ldl"); +//} + +//lj->args.append("-lmoldname"); +//lj->args.append("-lmingwex"); +//lj->args.append("-lmsvcrt"); + + +//if (g->windows_subsystem_windows) { +// lj->args.append("-lgdi32"); +// lj->args.append("-lcomdlg32"); +//} +//lj->args.append("-ladvapi32"); +//lj->args.append("-lshell32"); +//lj->args.append("-luser32"); +//lj->args.append("-lkernel32"); + +//if (g->is_static) { +// lj->args.append("--end-group"); +//} + +//if (lj->link_in_crt) { +// lj->args.append(get_libc_static_file(g, "crtend.o")); +//} +//} + + +static void construct_linker_job_coff(LinkJob *lj) { + CodeGen *g = lj->codegen; + + lj->args.append("/ERRORLIMIT:0"); + + if (g->libc_link_lib != nullptr) { + find_libc_lib_path(g); + } + + lj->args.append("/NOLOGO"); + + if (!g->strip_debug_symbols) { + lj->args.append("/DEBUG"); + } + + if (g->out_type == OutTypeExe) { + // TODO compile time stack upper bound detection + lj->args.append("/STACK:16777216"); + } + + coff_append_machine_arg(g, &lj->args); + + bool is_library = g->out_type == OutTypeLib; + switch (g->subsystem) { + case TargetSubsystemAuto: + break; + case TargetSubsystemConsole: + lj->args.append("/SUBSYSTEM:console"); + add_nt_link_args(lj, is_library); + break; + case TargetSubsystemEfiApplication: + lj->args.append("/SUBSYSTEM:efi_application"); + add_uefi_link_args(lj); + break; + case TargetSubsystemEfiBootServiceDriver: + lj->args.append("/SUBSYSTEM:efi_boot_service_driver"); + add_uefi_link_args(lj); + break; + case TargetSubsystemEfiRom: + lj->args.append("/SUBSYSTEM:efi_rom"); + add_uefi_link_args(lj); + break; + case TargetSubsystemEfiRuntimeDriver: + lj->args.append("/SUBSYSTEM:efi_runtime_driver"); + add_uefi_link_args(lj); + break; + case TargetSubsystemNative: + lj->args.append("/SUBSYSTEM:native"); + add_nt_link_args(lj, is_library); + break; + case TargetSubsystemPosix: + lj->args.append("/SUBSYSTEM:posix"); + add_nt_link_args(lj, is_library); + break; + case TargetSubsystemWindows: + lj->args.append("/SUBSYSTEM:windows"); + add_nt_link_args(lj, is_library); + break; + } + + lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); + + if (g->libc_link_lib != nullptr) { + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir)))); + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir)))); + + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir)))); + if (g->libc_static_lib_dir != nullptr) { + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir)))); + } + } if (is_library && !g->is_static) { lj->args.append("-DLL"); @@ -627,54 +725,6 @@ static void construct_linker_job_coff(LinkJob *lj) { } } - //if (g->libc_link_lib != nullptr) { - //if (g->is_static) { - // lj->args.append("--start-group"); - //} - - //lj->args.append("-lmingw32"); - - //lj->args.append("-lgcc"); - //bool is_android = (g->zig_target.env_type == ZigLLVM_Android); - //bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target); - //if (!g->is_static && !is_android) { - // if (!is_cyg_ming) { - // lj->args.append("--as-needed"); - // } - // //lj->args.append("-lgcc_s"); - // if (!is_cyg_ming) { - // lj->args.append("--no-as-needed"); - // } - //} - //if (g->is_static && !is_android) { - // //lj->args.append("-lgcc_eh"); - //} - //if (is_android && !g->is_static) { - // lj->args.append("-ldl"); - //} - - //lj->args.append("-lmoldname"); - //lj->args.append("-lmingwex"); - //lj->args.append("-lmsvcrt"); - - - //if (g->windows_subsystem_windows) { - // lj->args.append("-lgdi32"); - // lj->args.append("-lcomdlg32"); - //} - //lj->args.append("-ladvapi32"); - //lj->args.append("-lshell32"); - //lj->args.append("-luser32"); - //lj->args.append("-lkernel32"); - - //if (g->is_static) { - // lj->args.append("--end-group"); - //} - - //if (lj->link_in_crt) { - // lj->args.append(get_libc_static_file(g, "crtend.o")); - //} - //} } diff --git a/src/main.cpp b/src/main.cpp index 078dfb25f9..fd8e3db2fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -90,8 +90,7 @@ static int print_full_usage(const char *arg0) { " -rdynamic add all symbols to the dynamic symbol table\n" " -rpath [path] add directory to the runtime library search path\n" " --no-rosegment compromise security to workaround valgrind bug\n" - " -mconsole (windows) --subsystem console to the linker\n" - " -mwindows (windows) --subsystem windows to the linker\n" + " --subsystem [subsystem] (windows) /SUBSYSTEM: to the linker\n" " -framework [name] (darwin) link against framework\n" " -mios-version-min [ver] (darwin) set iOS deployment target\n" " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n" @@ -371,8 +370,6 @@ int main(int argc, char **argv) { const char *target_arch = nullptr; const char *target_os = nullptr; const char *target_environ = nullptr; - bool mwindows = false; - bool mconsole = false; bool rdynamic = false; const char *mmacosx_version_min = nullptr; const char *mios_version_min = nullptr; @@ -395,6 +392,7 @@ int main(int argc, char **argv) { int runtime_args_start = -1; bool no_rosegment_workaround = false; bool system_linker_hack = false; + TargetSubsystem subsystem = TargetSubsystemAuto; if (argc >= 2 && strcmp(argv[1], "build") == 0) { Buf zig_exe_path_buf = BUF_INIT; @@ -540,10 +538,6 @@ int main(int argc, char **argv) { verbose_llvm_ir = true; } else if (strcmp(arg, "--verbose-cimport") == 0) { verbose_cimport = true; - } else if (strcmp(arg, "-mwindows") == 0) { - mwindows = true; - } else if (strcmp(arg, "-mconsole") == 0) { - mconsole = true; } else if (strcmp(arg, "-rdynamic") == 0) { rdynamic = true; } else if (strcmp(arg, "--no-rosegment") == 0) { @@ -687,6 +681,37 @@ int main(int argc, char **argv) { ver_patch = atoi(argv[i]); } else if (strcmp(arg, "--test-cmd") == 0) { test_exec_args.append(argv[i]); + } else if (strcmp(arg, "--subsystem") == 0) { + if (strcmp(argv[i], "console") == 0) { + subsystem = TargetSubsystemConsole; + } else if (strcmp(argv[i], "windows") == 0) { + subsystem = TargetSubsystemWindows; + } else if (strcmp(argv[i], "posix") == 0) { + subsystem = TargetSubsystemPosix; + } else if (strcmp(argv[i], "native") == 0) { + subsystem = TargetSubsystemNative; + } else if (strcmp(argv[i], "efi_application") == 0) { + subsystem = TargetSubsystemEfiApplication; + } else if (strcmp(argv[i], "efi_boot_service_driver") == 0) { + subsystem = TargetSubsystemEfiBootServiceDriver; + } else if (strcmp(argv[i], "efi_rom") == 0) { + subsystem = TargetSubsystemEfiRom; + } else if (strcmp(argv[i], "efi_runtime_driver") == 0) { + subsystem = TargetSubsystemEfiRuntimeDriver; + } else { + fprintf(stderr, "invalid: --subsystem %s\n" + "Options are:\n" + " console\n" + " windows\n" + " posix\n" + " native\n" + " efi_application\n" + " efi_boot_service_driver\n" + " efi_rom\n" + " efi_runtime_driver\n" + , argv[i]); + return EXIT_FAILURE; + } } else { fprintf(stderr, "Invalid argument: %s\n", arg); return print_error_usage(arg0); @@ -849,6 +874,8 @@ int main(int argc, char **argv) { buf_out_name = buf_create_from_str("run"); } CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir()); + g->subsystem = subsystem; + if (disable_pic) { if (out_type != OutTypeLib || !is_static) { fprintf(stderr, "--disable-pic only applies to static libraries"); @@ -909,7 +936,6 @@ int main(int argc, char **argv) { codegen_add_rpath(g, rpath_list.at(i)); } - codegen_set_windows_subsystem(g, mwindows, mconsole); codegen_set_rdynamic(g, rdynamic); g->no_rosegment_workaround = no_rosegment_workaround; if (mmacosx_version_min && mios_version_min) { diff --git a/src/target.cpp b/src/target.cpp index 5a4b5252f1..6fea79518c 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -174,6 +174,7 @@ static const Os os_list[] = { OsContiki, OsAMDPAL, OsZen, + OsUefi, }; // Coordinate with zig_llvm.h @@ -282,6 +283,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) { case OsSolaris: return ZigLLVM_Solaris; case OsWindows: + case OsUefi: return ZigLLVM_Win32; case OsHaiku: return ZigLLVM_Haiku; @@ -394,6 +396,8 @@ const char *get_target_os_name(Os os_type) { return "freestanding"; case OsZen: return "zen"; + case OsUefi: + return "uefi"; case OsAnanas: case OsCloudABI: case OsDragonFly: @@ -756,6 +760,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case CIntTypeCount: zig_unreachable(); } + case OsUefi: case OsWindows: switch (id) { case CIntTypeShort: @@ -803,7 +808,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { } const char *target_o_file_ext(ZigTarget *target) { - if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows) { + if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) { return ".obj"; } else { return ".o"; @@ -821,13 +826,15 @@ const char *target_llvm_ir_file_ext(ZigTarget *target) { const char *target_exe_file_ext(ZigTarget *target) { if (target->os == OsWindows) { return ".exe"; + } else if (target->os == OsUefi) { + return ".efi"; } else { return ""; } } const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) { - if (target->os == OsWindows) { + if (target->os == OsWindows || target->os == OsUefi) { if (is_static) { return ".lib"; } else { diff --git a/src/target.hpp b/src/target.hpp index 04652179d2..a87b12351a 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -51,6 +51,19 @@ enum Os { OsContiki, OsAMDPAL, OsZen, + OsUefi, +}; + +enum TargetSubsystem { + TargetSubsystemAuto, // Zig should infer the subsystem + TargetSubsystemConsole, + TargetSubsystemWindows, + TargetSubsystemPosix, + TargetSubsystemNative, + TargetSubsystemEfiApplication, + TargetSubsystemEfiBootServiceDriver, + TargetSubsystemEfiRom, + TargetSubsystemEfiRuntimeDriver, }; struct ZigTarget { diff --git a/src/translate_c.cpp b/src/translate_c.cpp index f6bc9cd683..02fa3b24be 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -4749,8 +4749,10 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const clang_argv.append("-isystem"); clang_argv.append(buf_ptr(codegen->zig_c_headers_dir)); - clang_argv.append("-isystem"); - clang_argv.append(buf_ptr(codegen->libc_include_dir)); + if (codegen->libc_include_dir != nullptr) { + clang_argv.append("-isystem"); + clang_argv.append(buf_ptr(codegen->libc_include_dir)); + } // windows c runtime requires -D_DEBUG if using debug libraries if (codegen->build_mode == BuildModeDebug) { diff --git a/std/debug/index.zig b/std/debug/index.zig index 73c6ea7b56..93d6a60a03 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -1135,7 +1135,7 @@ pub const DebugInfo = switch (builtin.os) { return self.ofiles.allocator; } }, - builtin.Os.windows => struct { + builtin.Os.uefi, builtin.Os.windows => struct { pdb: pdb.Pdb, coff: *coff.Coff, sect_contribs: []pdb.SectionContribEntry, diff --git a/std/os/index.zig b/std/os/index.zig index b19679c969..bb2eb76265 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -18,6 +18,7 @@ test "std.os" { _ = @import("test.zig"); _ = @import("time.zig"); _ = @import("windows/index.zig"); + _ = @import("uefi.zig"); _ = @import("get_app_data_dir.zig"); } @@ -26,6 +27,8 @@ pub const darwin = @import("darwin.zig"); pub const linux = @import("linux/index.zig"); pub const freebsd = @import("freebsd/index.zig"); pub const zen = @import("zen.zig"); +pub const uefi = @import("uefi.zig"); + pub const posix = switch (builtin.os) { Os.linux => linux, Os.macosx, Os.ios => darwin, @@ -33,6 +36,7 @@ pub const posix = switch (builtin.os) { Os.zen => zen, else => @compileError("Unsupported OS"), }; + pub const net = @import("net.zig"); pub const ChildProcess = @import("child_process.zig").ChildProcess; @@ -187,6 +191,10 @@ pub fn abort() noreturn { } windows.ExitProcess(3); }, + Os.uefi => { + // TODO there's gotta be a better thing to do here than loop forever + while (true) {} + }, else => @compileError("Unsupported OS"), } } diff --git a/std/os/uefi.zig b/std/os/uefi.zig new file mode 100644 index 0000000000..8ed60d9c9b --- /dev/null +++ b/std/os/uefi.zig @@ -0,0 +1,2 @@ +// TODO this is where the extern declarations go. For example, see +// inc/efilib.h in gnu-efi-code diff --git a/std/special/panic.zig b/std/special/panic.zig index ca1caea73c..bd3ad971e0 100644 --- a/std/special/panic.zig +++ b/std/special/panic.zig @@ -13,6 +13,10 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn builtin.Os.freestanding, builtin.Os.zen => { while (true) {} }, + builtin.Os.uefi => { + // TODO look into using the debug info and logging helpful messages + std.os.abort(); + }, else => { const first_trace_addr = @ptrToInt(@returnAddress()); std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);