Commit b97a68c529

kcbanner <kcbanner@gmail.com>
2022-11-09 06:50:29
windows: supporting changes for boostrapping via msvc
- add support for passing through .def files to the linker, required for building libLTO.dll in LLVM - fixup libcpp linking conditionals - add option to skip linking zstd for use in bootstrapping (when building against an LLVM with LLVM_ENABLE_ZSTD=OFF)
1 parent 0471eea
src/link/Coff/lld.zig
@@ -260,6 +260,10 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
             try argv.append(p);
         }
 
+        if (self.base.options.module_definition_file) |def| {
+            try argv.append(try allocPrint(arena, "-DEF:{s}", .{ def }));
+        }
+
         const resolved_subsystem: ?std.Target.SubSystem = blk: {
             if (self.base.options.subsystem) |explicit| break :blk explicit;
             switch (target.os.tag) {
src/Compilation.zig
@@ -984,6 +984,7 @@ pub const InitOptions = struct {
     linker_dynamicbase: bool = false,
     linker_optimization: ?u8 = null,
     linker_compress_debug_sections: ?link.CompressDebugSections = null,
+    linker_module_definition_file: ?[]const u8 = null,
     major_subsystem_version: ?u32 = null,
     minor_subsystem_version: ?u32 = null,
     clang_passthrough_mode: bool = false,
@@ -1815,6 +1816,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .allow_shlib_undefined = options.linker_allow_shlib_undefined,
             .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
             .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
+            .module_definition_file = options.linker_module_definition_file,
             .import_memory = options.linker_import_memory orelse false,
             .import_symbols = options.linker_import_symbols,
             .import_table = options.linker_import_table,
@@ -4379,7 +4381,7 @@ pub fn addCCArgs(
                 try argv.append("-fno-unwind-tables");
             }
         },
-        .shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},
+        .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig => {},
         .assembly => {
             // The Clang assembler does not accept the list of CPU features like the
             // compiler frontend does. Therefore we must hard-code the -m flags for
@@ -4524,6 +4526,7 @@ pub const FileExt = enum {
     object,
     static_library,
     zig,
+    def,
     unknown,
 
     pub fn clangSupportsDepFile(ext: FileExt) bool {
@@ -4537,6 +4540,7 @@ pub const FileExt = enum {
             .object,
             .static_library,
             .zig,
+            .def,
             .unknown,
             => false,
         };
@@ -4629,6 +4633,8 @@ pub fn classifyFileExt(filename: []const u8) FileExt {
         return .object;
     } else if (mem.endsWith(u8, filename, ".cu")) {
         return .cu;
+    } else if (mem.endsWith(u8, filename, ".def")) {
+        return .def;
     } else {
         return .unknown;
     }
src/link.zig
@@ -219,6 +219,13 @@ pub const Options = struct {
     /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
     dead_strip_dylibs: bool = false,
 
+    /// (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) .def file to specify when linking
+    module_definition_file: ?[] const u8 = null,
+
     pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
         return if (options.use_lld) .Obj else options.output_mode;
     }
src/main.zig
@@ -742,6 +742,7 @@ fn buildOutputType(
     var linker_nxcompat = false;
     var linker_dynamicbase = false;
     var linker_optimization: ?u8 = null;
+    var linker_module_definition_file: ?[]const u8 = null;
     var test_evented_io = false;
     var test_no_exec = false;
     var entry: ?[]const u8 = null;
@@ -1404,7 +1405,7 @@ fn buildOutputType(
                             root_src_file = arg;
                         }
                     },
-                    .unknown => {
+                    .def, .unknown => {
                         fatal("unrecognized file extension of parameter '{s}'", .{arg});
                     },
                 }
@@ -1478,6 +1479,9 @@ fn buildOutputType(
                                     .must_link = must_link,
                                 });
                             },
+                            .def => {
+                                linker_module_definition_file = it.only_arg;
+                            },
                             .zig => {
                                 if (root_src_file) |other| {
                                     fatal("found another zig file '{s}' after root source file '{s}'", .{ it.only_arg, other });
@@ -3015,6 +3019,7 @@ fn buildOutputType(
         .linker_dynamicbase = linker_dynamicbase,
         .linker_optimization = linker_optimization,
         .linker_compress_debug_sections = linker_compress_debug_sections,
+        .linker_module_definition_file = linker_module_definition_file,
         .major_subsystem_version = major_subsystem_version,
         .minor_subsystem_version = minor_subsystem_version,
         .link_eh_frame_hdr = link_eh_frame_hdr,
build.zig
@@ -99,6 +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;
 
     if (!skip_install_lib_files) {
         b.installDirectory(InstallDirectoryOptions{
@@ -277,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);
-            try addStaticLlvmOptionsToExe(test_cases);
+            try addStaticLlvmOptionsToExe(exe, !disable_zstd);
+            try addStaticLlvmOptionsToExe(test_cases, !disable_zstd);
         }
         if (target.isWindows()) {
             inline for (.{ exe, test_cases }) |artifact| {
@@ -606,7 +607,7 @@ fn addCmakeCfgOptionsToExe(
     }
 }
 
-fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void {
+fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep, link_zstd: bool) !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 +630,11 @@ fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void {
 
     exe.linkSystemLibrary("z");
 
-    if (exe.target.getOs().tag != .windows and exe.target.getAbi() != .msvc) {
-        // TODO: Support this on msvc
+    if (link_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.
         exe.linkSystemLibrary("c++");
     }
@@ -704,7 +706,7 @@ fn addCMakeSystemLibraryList(exe: *std.build.LibExeObjStep, list: []const u8) vo
             end_offset = ".lib".len;
         }
 
-        exe.linkSystemLibrary(lib[start_offset..lib.len - end_offset]);
+        exe.linkSystemLibrary(lib[start_offset .. lib.len - end_offset]);
     }
 }