Commit b42442f5b4
Changed files (6)
src/link/Coff/lld.zig
@@ -166,12 +166,16 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
try argv.append("-DEBUG");
const out_ext = std.fs.path.extension(full_out_path);
- const out_pdb = try allocPrint(arena, "{s}.pdb", .{
+ const out_pdb = self.base.options.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{
full_out_path[0 .. full_out_path.len - out_ext.len],
});
+
try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb}));
}
+ if (self.base.options.version) |version| {
+ try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
+ }
if (self.base.options.lto) {
switch (self.base.options.optimize_mode) {
.Debug => {},
@@ -427,7 +431,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
}
} else {
try argv.append("-NODEFAULTLIB");
- if (!is_lib) {
+ if (!is_lib and self.base.options.entry == null) {
if (self.base.options.module) |module| {
if (module.stage1_flags.have_winmain_crt_startup) {
try argv.append("-ENTRY:WinMainCRTStartup");
@@ -435,7 +439,32 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
try argv.append("-ENTRY:wWinMainCRTStartup");
}
} else {
- try argv.append("-ENTRY:wWinMainCRTStartup");
+ // If the crt isn't being linked, it won't provide the CRT startup methods that
+ // call through to the user-provided entrypoint. Instead, choose the entry point
+ // that the CRT methods would have called. Note that this differs from the behaviour
+ // of link.exe (which still tries to use the CRT methods in this case), but this
+ // fixes CMake compiler checks when using zig cc on Windows, as Windows-Clang.cmake
+ // does not specify /entry:main
+
+ // TODO: I think the correct thing to do in this case would be to inspect the object
+ // being linked (like link.exe / lld-link does) and detect which symbols are available.
+ // This would allow detection of the w variants, as well as the crt methods.
+ if (resolved_subsystem) |subsystem| {
+ switch (subsystem) {
+ .Console => {
+ // The default is to call mainCRTStartup/wmainCRTStartup, which calls main/wmain
+ try argv.append("-ENTRY:main");
+ },
+ .Windows => {
+ // The default is to call WinMainCRTStartup/wWinMainCRTStartup, which calls WinMain/wWinMain
+ try argv.append("-ENTRY:WinMain");
+ },
+ else => {}
+ }
+ }
+
+ // when no /entry is specified, lld-link will infer it based on which functions
+ // are present in the object being linked - see lld/COFF/Driver.cpp#LinkerDriver::findDefaultEntry
}
}
}
src/Compilation.zig
@@ -1042,6 +1042,11 @@ pub const InitOptions = struct {
/// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
dead_strip_dylibs: bool = false,
libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default,
+ /// (Windows) PDB source path prefix to instruct the linker how to resolve relative
+ /// paths when consolidating CodeView streams into a single PDB file.
+ pdb_source_path: ?[]const u8 = null,
+ /// (Windows) PDB output path
+ pdb_out_path: ?[]const u8 = null,
};
fn addPackageTableToCacheHash(
@@ -1892,6 +1897,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.headerpad_max_install_names = options.headerpad_max_install_names,
.dead_strip_dylibs = options.dead_strip_dylibs,
.force_undefined_symbols = .{},
+ .pdb_source_path = pdb_source_path,
+ .pdb_out_path = options.pdb_out_path,
});
errdefer bin_file.destroy();
comp.* = .{
src/link.zig
@@ -223,6 +223,9 @@ pub const Options = struct {
/// paths when consolidating CodeView streams into a single PDB file.
pdb_source_path: ?[]const u8 = null,
+ /// (Windows) PDB output path
+ pdb_out_path: ?[]const u8 = null,
+
/// (Windows) .def file to specify when linking
module_definition_file: ?[]const u8 = null,
src/main.zig
@@ -782,6 +782,7 @@ fn buildOutputType(
var headerpad_max_install_names: bool = false;
var dead_strip_dylibs: bool = false;
var reference_trace: ?u32 = null;
+ var pdb_out_path: ?[]const u8 = null;
// e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
// This array is populated by zig cc frontend and then has to be converted to zig-style
@@ -1541,7 +1542,10 @@ fn buildOutputType(
.no_stack_protector => want_stack_protector = 0,
.unwind_tables => want_unwind_tables = true,
.no_unwind_tables => want_unwind_tables = false,
- .nostdlib => ensure_libc_on_non_freestanding = false,
+ .nostdlib => {
+ ensure_libc_on_non_freestanding = false;
+ ensure_libcpp_on_non_freestanding = false;
+ },
.nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,
.shared => {
link_mode = .Dynamic;
@@ -2120,6 +2124,24 @@ fn buildOutputType(
next_arg,
});
};
+ } else if (mem.startsWith(u8, arg, "/subsystem:")) {
+ var split_it = mem.splitBackwards(u8, arg, ":");
+ subsystem = try parseSubSystem(split_it.first());
+ } else if (mem.startsWith(u8, arg, "/implib:")) {
+ var split_it = mem.splitBackwards(u8, arg, ":");
+ emit_implib = .{ .yes = split_it.first() };
+ emit_implib_arg_provided = true;
+ } else if (mem.startsWith(u8, arg, "/pdb:")) {
+ var split_it = mem.splitBackwards(u8, arg, ":");
+ pdb_out_path = split_it.first();
+ } else if (mem.startsWith(u8, arg, "/version:")) {
+ var split_it = mem.splitBackwards(u8, arg, ":");
+ const version_arg = split_it.first();
+ version = std.builtin.Version.parse(version_arg) catch |err| {
+ fatal("unable to parse /version '{s}': {s}", .{ arg, @errorName(err) });
+ };
+
+ have_version = true;
} else {
warn("unsupported linker arg: {s}", .{arg});
}
@@ -3069,6 +3091,7 @@ fn buildOutputType(
.headerpad_max_install_names = headerpad_max_install_names,
.dead_strip_dylibs = dead_strip_dylibs,
.reference_trace = reference_trace,
+ .pdb_out_path = pdb_out_path,
}) catch |err| switch (err) {
error.LibCUnavailable => {
const target = target_info.target;
build.zig
@@ -99,7 +99,7 @@ pub fn build(b: *Builder) !void {
const enable_macos_sdk = b.option(bool, "enable-macos-sdk", "Run tests requiring presence of macOS SDK and frameworks") orelse false;
const enable_symlinks_windows = b.option(bool, "enable-symlinks-windows", "Run tests requiring presence of symlinks on Windows") orelse false;
const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h");
- const disable_zstd = b.option(bool, "disable-zstd", "Skip linking zstd") orelse false;
+ const disable_libcpp = b.option(bool, "disable-libcpp", "Skip building/linking libcpp") orelse false;
if (!skip_install_lib_files) {
b.installDirectory(InstallDirectoryOptions{
@@ -278,8 +278,8 @@ pub fn build(b: *Builder) !void {
try addCmakeCfgOptionsToExe(b, cfg, test_cases, use_zig_libcxx);
} else {
// Here we are -Denable-llvm but no cmake integration.
- try addStaticLlvmOptionsToExe(exe, !disable_zstd);
- try addStaticLlvmOptionsToExe(test_cases, !disable_zstd);
+ try addStaticLlvmOptionsToExe(exe);
+ try addStaticLlvmOptionsToExe(test_cases);
}
if (target.isWindows()) {
inline for (.{ exe, test_cases }) |artifact| {
@@ -607,7 +607,7 @@ fn addCmakeCfgOptionsToExe(
}
}
-fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep, link_zstd: bool) !void {
+fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void {
// Adds the Zig C++ sources which both stage1 and stage2 need.
//
// We need this because otherwise zig_clang_cc1_main.cpp ends up pulling
@@ -629,10 +629,7 @@ fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep, link_zstd: bool) !vo
}
exe.linkSystemLibrary("z");
-
- if (link_zstd) {
- exe.linkSystemLibrary("zstd");
- }
+ exe.linkSystemLibrary("zstd");
if (exe.target.getOs().tag != .windows or exe.target.getAbi() != .msvc) {
// This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries.
CMakeLists.txt
@@ -92,6 +92,7 @@ set(ZIG_SHARED_LLVM off CACHE BOOL "Prefer linking against shared LLVM libraries
set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")
set(ZIG_STATIC_ZLIB off CACHE BOOL "Prefer linking against static zlib")
set(ZIG_ENABLE_ZSTD on CACHE BOOL "Enable linking zstd")
+set(ZIG_ENABLE_LIBCPP on CACHE BOOL "Enable linking libcpp")
set(ZIG_STATIC_ZSTD off CACHE BOOL "Prefer linking against static zstd")
set(ZIG_USE_CCACHE off CACHE BOOL "Use ccache")