authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-06-21 22:45:43+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-06-25 19:13:43+02:00
log260c5aed86d662d2e2bd03c06d123bef9455053d
tree9bbf9bcbce9447ecacb5e92b969d0565fb4cce53
parent411f9c60b1cb30aec8706ffac75992ac8cc59cba
signature Commit is signed but in an unrecognized format.

stage2: add --sysroot link option

This feature is necessary for cross-compiling code that dynamically links system libraries, at least with the current feature set of lld.

5 files changed, 48 insertions(+), 26 deletions(-)

src/Compilation.zig+25-17
...@@ -612,6 +612,7 @@ pub const InitOptions = struct {...@@ -612,6 +612,7 @@ pub const InitOptions = struct {
612 output_mode: std.builtin.OutputMode,612 output_mode: std.builtin.OutputMode,
613 thread_pool: *ThreadPool,613 thread_pool: *ThreadPool,
614 dynamic_linker: ?[]const u8 = null,614 dynamic_linker: ?[]const u8 = null,
615 sysroot: ?[]const u8 = null,
615 /// `null` means to not emit a binary file.616 /// `null` means to not emit a binary file.
616 emit_bin: ?EmitLoc,617 emit_bin: ?EmitLoc,
617 /// `null` means to not emit a C header file.618 /// `null` means to not emit a C header file.
...@@ -879,25 +880,32 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -879,25 +880,32 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
879 break :blk false;880 break :blk false;
880 };881 };
881882
882 const DarwinOptions = struct {883 const darwin_can_use_system_linker_and_sdk =
883 syslibroot: ?[]const u8 = null,884 // comptime conditions
884 system_linker_hack: bool = false,885 ((build_options.have_llvm and comptime std.Target.current.isDarwin()) and
886 // runtime conditions
887 (use_lld and std.builtin.os.tag == .macos and options.target.isDarwin()));
888
889 const darwin_system_linker_hack = blk: {
890 if (darwin_can_use_system_linker_and_sdk) {
891 break :blk std.os.getenv("ZIG_SYSTEM_LINKER_HACK") != null;
892 } else {
893 break :blk false;
894 }
885 };895 };
886896
887 const darwin_options: DarwinOptions = if (build_options.have_llvm and comptime std.Target.current.isDarwin()) outer: {897 const sysroot = blk: {
888 const opts: DarwinOptions = if (use_lld and std.builtin.os.tag == .macos and options.target.isDarwin()) inner: {898 if (options.sysroot) |sysroot| {
899 break :blk sysroot;
900 } else if (darwin_can_use_system_linker_and_sdk) {
889 // TODO Revisit this targeting versions lower than macOS 11 when LLVM 12 is out.901 // TODO Revisit this targeting versions lower than macOS 11 when LLVM 12 is out.
890 // See https://github.com/ziglang/zig/issues/6996902 // See https://github.com/ziglang/zig/issues/6996
891 const at_least_big_sur = options.target.os.getVersionRange().semver.min.major >= 11;903 const at_least_big_sur = options.target.os.getVersionRange().semver.min.major >= 11;
892 const syslibroot = if (at_least_big_sur) try std.zig.system.getSDKPath(arena) else null;904 break :blk if (at_least_big_sur) try std.zig.system.getSDKPath(arena) else null;
893 const system_linker_hack = std.os.getenv("ZIG_SYSTEM_LINKER_HACK") != null;905 } else {
894 break :inner .{906 break :blk null;
895 .syslibroot = syslibroot,907 }
896 .system_linker_hack = system_linker_hack,908 };
897 };
898 } else .{};
899 break :outer opts;
900 } else .{};
901909
902 const lto = blk: {910 const lto = blk: {
903 if (options.want_lto) |explicit| {911 if (options.want_lto) |explicit| {
...@@ -908,7 +916,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -908,7 +916,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
908 break :blk false;916 break :blk false;
909 } else if (options.c_source_files.len == 0) {917 } else if (options.c_source_files.len == 0) {
910 break :blk false;918 break :blk false;
911 } else if (darwin_options.system_linker_hack) {919 } else if (darwin_system_linker_hack) {
912 break :blk false;920 break :blk false;
913 } else switch (options.output_mode) {921 } else switch (options.output_mode) {
914 .Lib, .Obj => break :blk false,922 .Lib, .Obj => break :blk false,
...@@ -1281,13 +1289,14 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1281,13 +1289,14 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1281 .module = module,1289 .module = module,
1282 .target = options.target,1290 .target = options.target,
1283 .dynamic_linker = options.dynamic_linker,1291 .dynamic_linker = options.dynamic_linker,
1292 .sysroot = sysroot,
1284 .output_mode = options.output_mode,1293 .output_mode = options.output_mode,
1285 .link_mode = link_mode,1294 .link_mode = link_mode,
1286 .object_format = ofmt,1295 .object_format = ofmt,
1287 .optimize_mode = options.optimize_mode,1296 .optimize_mode = options.optimize_mode,
1288 .use_lld = use_lld,1297 .use_lld = use_lld,
1289 .use_llvm = use_llvm,1298 .use_llvm = use_llvm,
1290 .system_linker_hack = darwin_options.system_linker_hack,1299 .system_linker_hack = darwin_system_linker_hack,
1291 .link_libc = link_libc,1300 .link_libc = link_libc,
1292 .link_libcpp = link_libcpp,1301 .link_libcpp = link_libcpp,
1293 .link_libunwind = link_libunwind,1302 .link_libunwind = link_libunwind,
...@@ -1295,7 +1304,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1295,7 +1304,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1295 .frameworks = options.frameworks,1304 .frameworks = options.frameworks,
1296 .framework_dirs = options.framework_dirs,1305 .framework_dirs = options.framework_dirs,
1297 .system_libs = system_libs,1306 .system_libs = system_libs,
1298 .syslibroot = darwin_options.syslibroot,
1299 .wasi_emulated_libs = options.wasi_emulated_libs,1307 .wasi_emulated_libs = options.wasi_emulated_libs,
1300 .lib_dirs = options.lib_dirs,1308 .lib_dirs = options.lib_dirs,
1301 .rpath_list = options.rpath_list,1309 .rpath_list = options.rpath_list,
src/link.zig+2-2
...@@ -38,6 +38,8 @@ pub const Options = struct {...@@ -38,6 +38,8 @@ pub const Options = struct {
38 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.38 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
39 module: ?*Module,39 module: ?*Module,
40 dynamic_linker: ?[]const u8,40 dynamic_linker: ?[]const u8,
41 /// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
42 sysroot: ?[]const u8,
41 /// Used for calculating how much space to reserve for symbols in case the binary file43 /// Used for calculating how much space to reserve for symbols in case the binary file
42 /// does not already have a symbol table.44 /// does not already have a symbol table.
43 symbol_count_hint: u64 = 32,45 symbol_count_hint: u64 = 32,
...@@ -104,8 +106,6 @@ pub const Options = struct {...@@ -104,8 +106,6 @@ pub const Options = struct {
104 llvm_cpu_features: ?[*:0]const u8,106 llvm_cpu_features: ?[*:0]const u8,
105 /// Extra args passed directly to LLD. Ignored when not linking with LLD.107 /// Extra args passed directly to LLD. Ignored when not linking with LLD.
106 extra_lld_args: []const []const u8,108 extra_lld_args: []const []const u8,
107 /// Darwin-only. Set the root path to the system libraries and frameworks.
108 syslibroot: ?[]const u8,
109109
110 objects: []const []const u8,110 objects: []const []const u8,
111 framework_dirs: []const []const u8,111 framework_dirs: []const []const u8,
src/link/Elf.zig+5
...@@ -1354,6 +1354,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1354,6 +1354,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1354 man.hash.add(allow_shlib_undefined);1354 man.hash.add(allow_shlib_undefined);
1355 man.hash.add(self.base.options.bind_global_refs_locally);1355 man.hash.add(self.base.options.bind_global_refs_locally);
1356 man.hash.add(self.base.options.tsan);1356 man.hash.add(self.base.options.tsan);
1357 man.hash.addOptionalBytes(self.base.options.sysroot);
13571358
1358 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.1359 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
1359 _ = try man.hit();1360 _ = try man.hit();
...@@ -1423,6 +1424,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1423,6 +1424,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
14231424
1424 try argv.append("-error-limit=0");1425 try argv.append("-error-limit=0");
14251426
1427 if (self.base.options.sysroot) |sysroot| {
1428 try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
1429 }
1430
1426 if (self.base.options.lto) {1431 if (self.base.options.lto) {
1427 switch (self.base.options.optimize_mode) {1432 switch (self.base.options.optimize_mode) {
1428 .Debug => {},1433 .Debug => {},
src/link/MachO.zig+6-6
...@@ -704,7 +704,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -704,7 +704,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
704 man.hash.add(allow_shlib_undefined);704 man.hash.add(allow_shlib_undefined);
705 man.hash.add(self.base.options.bind_global_refs_locally);705 man.hash.add(self.base.options.bind_global_refs_locally);
706 man.hash.add(self.base.options.system_linker_hack);706 man.hash.add(self.base.options.system_linker_hack);
707 man.hash.addOptionalBytes(self.base.options.syslibroot);707 man.hash.addOptionalBytes(self.base.options.sysroot);
708708
709 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.709 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
710 _ = try man.hit();710 _ = try man.hit();
...@@ -789,7 +789,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -789,7 +789,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
789 zld.deinit();789 zld.deinit();
790 }790 }
791 zld.arch = target.cpu.arch;791 zld.arch = target.cpu.arch;
792 zld.syslibroot = self.base.options.syslibroot;792 zld.syslibroot = self.base.options.sysroot;
793 zld.stack_size = stack_size;793 zld.stack_size = stack_size;
794794
795 // Positional arguments to the linker such as object files and static archives.795 // Positional arguments to the linker such as object files and static archives.
...@@ -833,7 +833,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -833,7 +833,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
833 try resolvePaths(833 try resolvePaths(
834 arena,834 arena,
835 &libs,835 &libs,
836 self.base.options.syslibroot,836 self.base.options.sysroot,
837 self.base.options.lib_dirs,837 self.base.options.lib_dirs,
838 search_lib_names.items,838 search_lib_names.items,
839 .lib,839 .lib,
...@@ -856,7 +856,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -856,7 +856,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
856 try resolvePaths(856 try resolvePaths(
857 arena,857 arena,
858 &libs,858 &libs,
859 self.base.options.syslibroot,859 self.base.options.sysroot,
860 self.base.options.framework_dirs,860 self.base.options.framework_dirs,
861 self.base.options.frameworks,861 self.base.options.frameworks,
862 .framework,862 .framework,
...@@ -868,7 +868,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -868,7 +868,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
868 try argv.append("zig");868 try argv.append("zig");
869 try argv.append("ld");869 try argv.append("ld");
870870
871 if (self.base.options.syslibroot) |syslibroot| {871 if (self.base.options.sysroot) |syslibroot| {
872 try argv.append("-syslibroot");872 try argv.append("-syslibroot");
873 try argv.append(syslibroot);873 try argv.append(syslibroot);
874 }874 }
...@@ -1017,7 +1017,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -1017,7 +1017,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
1017 }1017 }
1018 }1018 }
10191019
1020 if (self.base.options.syslibroot) |dir| {1020 if (self.base.options.sysroot) |dir| {
1021 try argv.append("-syslibroot");1021 try argv.append("-syslibroot");
1022 try argv.append(dir);1022 try argv.append(dir);
1023 }1023 }
src/main.zig+10-1
...@@ -379,6 +379,7 @@ const usage_build_generic =...@@ -379,6 +379,7 @@ const usage_build_generic =
379 \\ -T[script], --script [script] Use a custom linker script379 \\ -T[script], --script [script] Use a custom linker script
380 \\ --version-script [path] Provide a version .map file380 \\ --version-script [path] Provide a version .map file
381 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)381 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
382 \\ --sysroot [path] Set the system root directory (usually /)
382 \\ --version [ver] Dynamic library semver383 \\ --version [ver] Dynamic library semver
383 \\ -fsoname[=name] (Linux) Override the default SONAME value384 \\ -fsoname[=name] (Linux) Override the default SONAME value
384 \\ -fno-soname (Linux) Disable emitting a SONAME385 \\ -fno-soname (Linux) Disable emitting a SONAME
...@@ -604,6 +605,7 @@ fn buildOutputType(...@@ -604,6 +605,7 @@ fn buildOutputType(
604 var link_eh_frame_hdr = false;605 var link_eh_frame_hdr = false;
605 var link_emit_relocs = false;606 var link_emit_relocs = false;
606 var each_lib_rpath: ?bool = null;607 var each_lib_rpath: ?bool = null;
608 var sysroot: ?[]const u8 = null;
607 var libc_paths_file: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIBC");609 var libc_paths_file: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIBC");
608 var machine_code_model: std.builtin.CodeModel = .default;610 var machine_code_model: std.builtin.CodeModel = .default;
609 var runtime_args_start: ?usize = null;611 var runtime_args_start: ?usize = null;
...@@ -865,6 +867,10 @@ fn buildOutputType(...@@ -865,6 +867,10 @@ fn buildOutputType(
865 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});867 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
866 i += 1;868 i += 1;
867 target_dynamic_linker = args[i];869 target_dynamic_linker = args[i];
870 } else if (mem.eql(u8, arg, "--sysroot")) {
871 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
872 i += 1;
873 sysroot = args[i];
868 } else if (mem.eql(u8, arg, "--libc")) {874 } else if (mem.eql(u8, arg, "--libc")) {
869 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});875 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
870 i += 1;876 i += 1;
...@@ -1641,7 +1647,9 @@ fn buildOutputType(...@@ -1641,7 +1647,9 @@ fn buildOutputType(
1641 want_native_include_dirs = true;1647 want_native_include_dirs = true;
1642 }1648 }
16431649
1644 if (cross_target.isNativeOs() and (system_libs.items.len != 0 or want_native_include_dirs)) {1650 if (sysroot == null and cross_target.isNativeOs() and
1651 (system_libs.items.len != 0 or want_native_include_dirs))
1652 {
1645 const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| {1653 const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| {
1646 fatal("unable to detect native system paths: {s}", .{@errorName(err)});1654 fatal("unable to detect native system paths: {s}", .{@errorName(err)});
1647 };1655 };
...@@ -1918,6 +1926,7 @@ fn buildOutputType(...@@ -1918,6 +1926,7 @@ fn buildOutputType(
1918 .is_native_os = cross_target.isNativeOs(),1926 .is_native_os = cross_target.isNativeOs(),
1919 .is_native_abi = cross_target.isNativeAbi(),1927 .is_native_abi = cross_target.isNativeAbi(),
1920 .dynamic_linker = target_info.dynamic_linker.get(),1928 .dynamic_linker = target_info.dynamic_linker.get(),
1929 .sysroot = sysroot,
1921 .output_mode = output_mode,1930 .output_mode = output_mode,
1922 .root_pkg = root_pkg,1931 .root_pkg = root_pkg,
1923 .emit_bin = emit_bin_loc,1932 .emit_bin = emit_bin_loc,