authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-24 14:30:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-24 14:30:28-07:00
log0cfa39304b18c6a04689bd789f5dc4d035ec43b0
tree9dc20b8bbf29909fc7f093618cccd42845aa4e41
parentb56e916fa1d3508a01a6fc0b62f3f64dd3843b85

zig cc: recognize more coff linker options

Related: #7874

4 files changed, 120 insertions(+), 8 deletions(-)

src/Compilation.zig+10
......@@ -468,6 +468,11 @@ pub const InitOptions = struct {
468468 disable_c_depfile: bool = false,
469469 linker_z_nodelete: bool = false,
470470 linker_z_defs: bool = false,
471 linker_tsaware: bool = false,
472 linker_nxcompat: bool = false,
473 linker_dynamicbase: bool = false,
474 major_subsystem_version: ?u32 = null,
475 minor_subsystem_version: ?u32 = null,
471476 clang_passthrough_mode: bool = false,
472477 verbose_cc: bool = false,
473478 verbose_link: bool = false,
......@@ -1035,6 +1040,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
10351040 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
10361041 .z_nodelete = options.linker_z_nodelete,
10371042 .z_defs = options.linker_z_defs,
1043 .tsaware = options.linker_tsaware,
1044 .nxcompat = options.linker_nxcompat,
1045 .dynamicbase = options.linker_dynamicbase,
1046 .major_subsystem_version = options.major_subsystem_version,
1047 .minor_subsystem_version = options.minor_subsystem_version,
10381048 .stack_size_override = options.stack_size_override,
10391049 .image_base_override = options.image_base_override,
10401050 .include_compiler_rt = include_compiler_rt,
src/link.zig+5
......@@ -69,6 +69,9 @@ pub const Options = struct {
6969 rdynamic: bool,
7070 z_nodelete: bool,
7171 z_defs: bool,
72 tsaware: bool,
73 nxcompat: bool,
74 dynamicbase: bool,
7275 bind_global_refs_locally: bool,
7376 is_native_os: bool,
7477 is_native_abi: bool,
......@@ -88,6 +91,8 @@ pub const Options = struct {
8891 each_lib_rpath: bool,
8992 disable_lld_caching: bool,
9093 is_test: bool,
94 major_subsystem_version: ?u32,
95 minor_subsystem_version: ?u32,
9196 gc_sections: ?bool = null,
9297 allow_shlib_undefined: ?bool,
9398 subsystem: ?std.Target.SubSystem,
src/link/Coff.zig+49-8
......@@ -877,6 +877,11 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
877877 man.hash.addStringSet(self.base.options.system_libs);
878878 man.hash.addOptional(self.base.options.subsystem);
879879 man.hash.add(self.base.options.is_test);
880 man.hash.add(self.base.options.tsaware);
881 man.hash.add(self.base.options.nxcompat);
882 man.hash.add(self.base.options.dynamicbase);
883 man.hash.addOptional(self.base.options.major_subsystem_version);
884 man.hash.addOptional(self.base.options.minor_subsystem_version);
880885
881886 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
882887 _ = try man.hit();
......@@ -976,6 +981,26 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
976981 try argv.append("-DLL");
977982 }
978983
984 if (self.base.options.tsaware) {
985 try argv.append("-tsaware");
986 }
987 if (self.base.options.nxcompat) {
988 try argv.append("-nxcompat");
989 }
990 if (self.base.options.dynamicbase) {
991 try argv.append("-dynamicbase");
992 }
993 const subsystem_suffix = ss: {
994 if (self.base.options.major_subsystem_version) |major| {
995 if (self.base.options.minor_subsystem_version) |minor| {
996 break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor });
997 } else {
998 break :ss try allocPrint(arena, ",{d}", .{major});
999 }
1000 }
1001 break :ss "";
1002 };
1003
9791004 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
9801005
9811006 if (self.base.options.link_libc) {
......@@ -1029,35 +1054,51 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
10291054 const mode: Mode = mode: {
10301055 if (resolved_subsystem) |subsystem| switch (subsystem) {
10311056 .Console => {
1032 try argv.append("-SUBSYSTEM:console");
1057 try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
1058 subsystem_suffix,
1059 }));
10331060 break :mode .win32;
10341061 },
10351062 .EfiApplication => {
1036 try argv.append("-SUBSYSTEM:efi_application");
1063 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
1064 subsystem_suffix,
1065 }));
10371066 break :mode .uefi;
10381067 },
10391068 .EfiBootServiceDriver => {
1040 try argv.append("-SUBSYSTEM:efi_boot_service_driver");
1069 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
1070 subsystem_suffix,
1071 }));
10411072 break :mode .uefi;
10421073 },
10431074 .EfiRom => {
1044 try argv.append("-SUBSYSTEM:efi_rom");
1075 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
1076 subsystem_suffix,
1077 }));
10451078 break :mode .uefi;
10461079 },
10471080 .EfiRuntimeDriver => {
1048 try argv.append("-SUBSYSTEM:efi_runtime_driver");
1081 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
1082 subsystem_suffix,
1083 }));
10491084 break :mode .uefi;
10501085 },
10511086 .Native => {
1052 try argv.append("-SUBSYSTEM:native");
1087 try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
1088 subsystem_suffix,
1089 }));
10531090 break :mode .win32;
10541091 },
10551092 .Posix => {
1056 try argv.append("-SUBSYSTEM:posix");
1093 try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{
1094 subsystem_suffix,
1095 }));
10571096 break :mode .win32;
10581097 },
10591098 .Windows => {
1060 try argv.append("-SUBSYSTEM:windows");
1099 try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{
1100 subsystem_suffix,
1101 }));
10611102 break :mode .win32;
10621103 },
10631104 } else if (target.os.tag == .uefi) {
src/main.zig+56
......@@ -529,6 +529,9 @@ fn buildOutputType(
529529 var linker_bind_global_refs_locally: ?bool = null;
530530 var linker_z_nodelete = false;
531531 var linker_z_defs = false;
532 var linker_tsaware = false;
533 var linker_nxcompat = false;
534 var linker_dynamicbase = false;
532535 var test_evented_io = false;
533536 var stack_size_override: ?u64 = null;
534537 var image_base_override: ?u64 = null;
......@@ -549,6 +552,8 @@ fn buildOutputType(
549552 var main_pkg_path: ?[]const u8 = null;
550553 var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no;
551554 var subsystem: ?std.Target.SubSystem = null;
555 var major_subsystem_version: ?u32 = null;
556 var minor_subsystem_version: ?u32 = null;
552557
553558 var system_libs = std.ArrayList([]const u8).init(gpa);
554559 defer system_libs.deinit();
......@@ -1307,10 +1312,56 @@ fn buildOutputType(
13071312 image_base_override = std.fmt.parseUnsigned(u64, linker_args.items[i], 0) catch |err| {
13081313 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
13091314 };
1315 } else if (mem.eql(u8, arg, "-T")) {
1316 i += 1;
1317 if (i >= linker_args.items.len) {
1318 fatal("expected linker arg after '{s}'", .{arg});
1319 }
1320 linker_script = linker_args.items[i];
13101321 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) {
13111322 link_eh_frame_hdr = true;
13121323 } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) {
13131324 link_eh_frame_hdr = false;
1325 } else if (mem.eql(u8, arg, "--tsaware")) {
1326 linker_tsaware = true;
1327 } else if (mem.eql(u8, arg, "--nxcompat")) {
1328 linker_nxcompat = true;
1329 } else if (mem.eql(u8, arg, "--dynamicbase")) {
1330 linker_dynamicbase = true;
1331 } else if (mem.eql(u8, arg, "--high-entropy-va")) {
1332 // This option does not do anything.
1333 } else if (mem.eql(u8, arg, "--export-all-symbols")) {
1334 rdynamic = true;
1335 } else if (mem.eql(u8, arg, "--start-group") or
1336 mem.eql(u8, arg, "--end-group"))
1337 {
1338 // We don't need to care about these because these args are
1339 // for resolving circular dependencies but our linker takes
1340 // care of this without explicit args.
1341 } else if (mem.startsWith(u8, arg, "--major-os-version") or
1342 mem.startsWith(u8, arg, "--minor-os-version"))
1343 {
1344 // This option does not do anything.
1345 } else if (mem.startsWith(u8, arg, "--major-subsystem-version=")) {
1346 major_subsystem_version = std.fmt.parseUnsigned(
1347 u32,
1348 arg["--major-subsystem-version=".len..],
1349 10,
1350 ) catch |err| {
1351 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1352 };
1353 } else if (mem.startsWith(u8, arg, "--minor-subsystem-version=")) {
1354 minor_subsystem_version = std.fmt.parseUnsigned(
1355 u32,
1356 arg["--minor-subsystem-version=".len..],
1357 10,
1358 ) catch |err| {
1359 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1360 };
1361 } else if (mem.startsWith(u8, arg, "--major-os-version=") or
1362 mem.startsWith(u8, arg, "--minor-os-version="))
1363 {
1364 // These args do nothing.
13141365 } else {
13151366 warn("unsupported linker arg: {s}", .{arg});
13161367 }
......@@ -1800,6 +1851,11 @@ fn buildOutputType(
18001851 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,
18011852 .linker_z_nodelete = linker_z_nodelete,
18021853 .linker_z_defs = linker_z_defs,
1854 .linker_tsaware = linker_tsaware,
1855 .linker_nxcompat = linker_nxcompat,
1856 .linker_dynamicbase = linker_dynamicbase,
1857 .major_subsystem_version = major_subsystem_version,
1858 .minor_subsystem_version = minor_subsystem_version,
18031859 .link_eh_frame_hdr = link_eh_frame_hdr,
18041860 .link_emit_relocs = link_emit_relocs,
18051861 .stack_size_override = stack_size_override,