dynamic_linker becomes a field of std.zig.CrossTarget

master
Andrew Kelley 2020-02-28 13:27:52 -05:00
parent 07f52119de
commit 500dde32d5
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
13 changed files with 137 additions and 127 deletions

View File

@ -1177,8 +1177,6 @@ pub const LibExeObjStep = struct {
/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`. /// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
glibc_multi_install_dir: ?[]const u8 = null, glibc_multi_install_dir: ?[]const u8 = null,
dynamic_linker: ?[]const u8 = null,
/// Position Independent Code /// Position Independent Code
force_pic: ?bool = null, force_pic: ?bool = null,
@ -1978,6 +1976,11 @@ pub const LibExeObjStep = struct {
} }
try zig_args.append(mcpu_buffer.toSliceConst()); try zig_args.append(mcpu_buffer.toSliceConst());
} }
if (self.target.dynamic_linker.get()) |dynamic_linker| {
try zig_args.append("--dynamic-linker");
try zig_args.append(dynamic_linker);
}
} }
if (self.linker_script) |linker_script| { if (self.linker_script) |linker_script| {
@ -1985,11 +1988,6 @@ pub const LibExeObjStep = struct {
zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable; zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable;
} }
if (self.dynamic_linker) |dynamic_linker| {
try zig_args.append("--dynamic-linker");
try zig_args.append(dynamic_linker);
}
if (self.version_script) |version_script| { if (self.version_script) |version_script| {
try zig_args.append("--version-script"); try zig_args.append("--version-script");
try zig_args.append(builder.pathFromRoot(version_script)); try zig_args.append(builder.pathFromRoot(version_script));

View File

@ -1099,16 +1099,52 @@ pub const Target = struct {
} }
} }
pub const DynamicLinker = struct {
/// Contains the memory used to store the dynamic linker path. This field should
/// not be used directly. See `get` and `set`. This field exists so that this API requires no allocator.
buffer: [255]u8 = undefined,
/// Used to construct the dynamic linker path. This field should not be used
/// directly. See `get` and `set`.
max_byte: ?u8 = null,
/// Asserts that the length is less than or equal to 255 bytes.
pub fn init(dl_or_null: ?[]const u8) DynamicLinker {
var result: DynamicLinker = undefined;
result.set(dl_or_null);
return result;
}
/// The returned memory has the same lifetime as the `DynamicLinker`.
pub fn get(self: *const DynamicLinker) ?[]const u8 {
const m: usize = self.max_byte orelse return null;
return self.buffer[0 .. m + 1];
}
/// Asserts that the length is less than or equal to 255 bytes.
pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {
if (dl_or_null) |dl| {
mem.copy(u8, &self.buffer, dl);
self.max_byte = @intCast(u8, dl.len - 1);
} else {
self.max_byte = null;
}
}
};
/// The result will be a byte index *pointing at the final byte*. In other words, length minus one. /// The result will be a byte index *pointing at the final byte*. In other words, length minus one.
/// A return value of `null` means the concept of a dynamic linker is not meaningful for that target. /// A return value of `null` means the concept of a dynamic linker is not meaningful for that target.
pub fn standardDynamicLinkerPath(self: Target, buffer: *[255]u8) ?u8 { pub fn standardDynamicLinkerPath(self: Target) DynamicLinker {
var result: DynamicLinker = .{};
const S = struct { const S = struct {
fn print(b: *[255]u8, comptime fmt: []const u8, args: var) u8 { fn print(r: *DynamicLinker, comptime fmt: []const u8, args: var) DynamicLinker {
return @intCast(u8, (std.fmt.bufPrint(b, fmt, args) catch unreachable).len - 1); r.max_byte = @intCast(u8, (std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1);
return r.*;
} }
fn copy(b: *[255]u8, s: []const u8) u8 { fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
mem.copy(u8, b, s); mem.copy(u8, &r.buffer, s);
return @intCast(u8, s.len - 1); r.max_byte = @intCast(u8, s.len - 1);
return r.*;
} }
}; };
const print = S.print; const print = S.print;
@ -1116,7 +1152,7 @@ pub const Target = struct {
if (self.isAndroid()) { if (self.isAndroid()) {
const suffix = if (self.cpu.arch.ptrBitWidth() == 64) "64" else ""; const suffix = if (self.cpu.arch.ptrBitWidth() == 64) "64" else "";
return print(buffer, "/system/bin/linker{}", .{suffix}); return print(&result, "/system/bin/linker{}", .{suffix});
} }
if (self.isMusl()) { if (self.isMusl()) {
@ -1130,28 +1166,28 @@ pub const Target = struct {
else => |arch| @tagName(arch), else => |arch| @tagName(arch),
}; };
const arch_suffix = if (is_arm and self.getFloatAbi() == .hard) "hf" else ""; const arch_suffix = if (is_arm and self.getFloatAbi() == .hard) "hf" else "";
return print(buffer, "/lib/ld-musl-{}{}.so.1", .{ arch_part, arch_suffix }); return print(&result, "/lib/ld-musl-{}{}.so.1", .{ arch_part, arch_suffix });
} }
switch (self.os.tag) { switch (self.os.tag) {
.freebsd => return copy(buffer, "/libexec/ld-elf.so.1"), .freebsd => return copy(&result, "/libexec/ld-elf.so.1"),
.netbsd => return copy(buffer, "/libexec/ld.elf_so"), .netbsd => return copy(&result, "/libexec/ld.elf_so"),
.dragonfly => return copy(buffer, "/libexec/ld-elf.so.2"), .dragonfly => return copy(&result, "/libexec/ld-elf.so.2"),
.linux => switch (self.cpu.arch) { .linux => switch (self.cpu.arch) {
.i386, .i386,
.sparc, .sparc,
.sparcel, .sparcel,
=> return copy(buffer, "/lib/ld-linux.so.2"), => return copy(&result, "/lib/ld-linux.so.2"),
.aarch64 => return copy(buffer, "/lib/ld-linux-aarch64.so.1"), .aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"),
.aarch64_be => return copy(buffer, "/lib/ld-linux-aarch64_be.so.1"), .aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"),
.aarch64_32 => return copy(buffer, "/lib/ld-linux-aarch64_32.so.1"), .aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"),
.arm, .arm,
.armeb, .armeb,
.thumb, .thumb,
.thumbeb, .thumbeb,
=> return copy(buffer, switch (self.getFloatAbi()) { => return copy(&result, switch (self.getFloatAbi()) {
.hard => "/lib/ld-linux-armhf.so.3", .hard => "/lib/ld-linux-armhf.so.3",
else => "/lib/ld-linux.so.3", else => "/lib/ld-linux.so.3",
}), }),
@ -1168,20 +1204,20 @@ pub const Target = struct {
}; };
const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008); const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008);
const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1"; const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";
return print(buffer, "/lib{}/{}", .{ lib_suffix, loader }); return print(&result, "/lib{}/{}", .{ lib_suffix, loader });
}, },
.powerpc => return copy(buffer, "/lib/ld.so.1"), .powerpc => return copy(&result, "/lib/ld.so.1"),
.powerpc64, .powerpc64le => return copy(buffer, "/lib64/ld64.so.2"), .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"),
.s390x => return copy(buffer, "/lib64/ld64.so.1"), .s390x => return copy(&result, "/lib64/ld64.so.1"),
.sparcv9 => return copy(buffer, "/lib64/ld-linux.so.2"), .sparcv9 => return copy(&result, "/lib64/ld-linux.so.2"),
.x86_64 => return copy(buffer, switch (self.abi) { .x86_64 => return copy(&result, switch (self.abi) {
.gnux32 => "/libx32/ld-linux-x32.so.2", .gnux32 => "/libx32/ld-linux-x32.so.2",
else => "/lib64/ld-linux-x86-64.so.2", else => "/lib64/ld-linux-x86-64.so.2",
}), }),
.riscv32 => return copy(buffer, "/lib/ld-linux-riscv32-ilp32.so.1"), .riscv32 => return copy(&result, "/lib/ld-linux-riscv32-ilp32.so.1"),
.riscv64 => return copy(buffer, "/lib/ld-linux-riscv64-lp64.so.1"), .riscv64 => return copy(&result, "/lib/ld-linux-riscv64-lp64.so.1"),
// Architectures in this list have been verified as not having a standard // Architectures in this list have been verified as not having a standard
// dynamic linker path. // dynamic linker path.
@ -1191,7 +1227,7 @@ pub const Target = struct {
.bpfeb, .bpfeb,
.nvptx, .nvptx,
.nvptx64, .nvptx64,
=> return null, => return result,
// TODO go over each item in this list and either move it to the above list, or // TODO go over each item in this list and either move it to the above list, or
// implement the standard dynamic linker path code for it. // implement the standard dynamic linker path code for it.
@ -1217,7 +1253,7 @@ pub const Target = struct {
.lanai, .lanai,
.renderscript32, .renderscript32,
.renderscript64, .renderscript64,
=> return null, => return result,
}, },
// Operating systems in this list have been verified as not having a standard // Operating systems in this list have been verified as not having a standard
@ -1232,7 +1268,7 @@ pub const Target = struct {
.emscripten, .emscripten,
.wasi, .wasi,
.other, .other,
=> return null, => return result,
// TODO go over each item in this list and either move it to the above list, or // TODO go over each item in this list and either move it to the above list, or
// implement the standard dynamic linker path code for it. // implement the standard dynamic linker path code for it.
@ -1259,7 +1295,7 @@ pub const Target = struct {
.amdpal, .amdpal,
.hermit, .hermit,
.hurd, .hurd,
=> return null, => return result,
} }
} }
}; };

View File

@ -40,6 +40,10 @@ pub const CrossTarget = struct {
/// If `isGnuLibC()` is `false`, this must be `null` and is ignored. /// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
glibc_version: ?SemVer = null, glibc_version: ?SemVer = null,
/// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path
/// based on the `os_tag`.
dynamic_linker: DynamicLinker = DynamicLinker{},
pub const OsVersion = union(enum) { pub const OsVersion = union(enum) {
none: void, none: void,
semver: SemVer, semver: SemVer,
@ -48,6 +52,8 @@ pub const CrossTarget = struct {
pub const SemVer = std.builtin.Version; pub const SemVer = std.builtin.Version;
pub const DynamicLinker = Target.DynamicLinker;
pub fn fromTarget(target: Target) CrossTarget { pub fn fromTarget(target: Target) CrossTarget {
var result: CrossTarget = .{ var result: CrossTarget = .{
.cpu_arch = target.cpu.arch, .cpu_arch = target.cpu.arch,
@ -170,6 +176,10 @@ pub const CrossTarget = struct {
/// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline". /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline".
cpu_features: ?[]const u8 = null, cpu_features: ?[]const u8 = null,
/// Absolute path to dynamic linker, to override the default, which is either a natively
/// detected path, or a standard path.
dynamic_linker: ?[]const u8 = null,
/// If this is provided, the function will populate some information about parsing failures, /// If this is provided, the function will populate some information about parsing failures,
/// so that user-friendly error messages can be delivered. /// so that user-friendly error messages can be delivered.
diagnostics: ?*Diagnostics = null, diagnostics: ?*Diagnostics = null,
@ -199,8 +209,9 @@ pub const CrossTarget = struct {
var dummy_diags: ParseOptions.Diagnostics = undefined; var dummy_diags: ParseOptions.Diagnostics = undefined;
const diags = args.diagnostics orelse &dummy_diags; const diags = args.diagnostics orelse &dummy_diags;
// Start with everything initialized to default values. var result: CrossTarget = .{
var result: CrossTarget = .{}; .dynamic_linker = DynamicLinker.init(args.dynamic_linker),
};
var it = mem.separate(args.arch_os_abi, "-"); var it = mem.separate(args.arch_os_abi, "-");
const arch_name = it.next().?; const arch_name = it.next().?;
@ -446,7 +457,7 @@ pub const CrossTarget = struct {
return self.cpu_arch == null and self.cpu_model == null and return self.cpu_arch == null and self.cpu_model == null and
self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty() and self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty() and
self.os_tag == null and self.os_version_min == null and self.os_version_max == null and self.os_tag == null and self.os_version_min == null and self.os_version_max == null and
self.abi == null; self.abi == null and self.dynamic_linker.get() == null;
} }
pub fn zigTriple(self: CrossTarget, allocator: *mem.Allocator) error{OutOfMemory}![:0]u8 { pub fn zigTriple(self: CrossTarget, allocator: *mem.Allocator) error{OutOfMemory}![:0]u8 {

View File

@ -168,14 +168,9 @@ pub const NativePaths = struct {
pub const NativeTargetInfo = struct { pub const NativeTargetInfo = struct {
target: Target, target: Target,
/// Contains the memory used to store the dynamic linker path. This field should dynamic_linker: DynamicLinker = DynamicLinker{},
/// not be used directly. See `dynamicLinker` and `setDynamicLinker`. This field
/// exists so that this API requires no allocator.
dynamic_linker_buffer: [255]u8 = undefined,
/// Used to construct the dynamic linker path. This field should not be used pub const DynamicLinker = Target.DynamicLinker;
/// directly. See `dynamicLinker` and `setDynamicLinker`.
dynamic_linker_max: ?u8 = null,
pub const DetectError = error{ pub const DetectError = error{
OutOfMemory, OutOfMemory,
@ -220,21 +215,6 @@ pub const NativeTargetInfo = struct {
return detectAbiAndDynamicLinker(allocator, cpu, os); return detectAbiAndDynamicLinker(allocator, cpu, os);
} }
/// The returned memory has the same lifetime as the `NativeTargetInfo`.
pub fn dynamicLinker(self: *const NativeTargetInfo) ?[]const u8 {
const m: usize = self.dynamic_linker_max orelse return null;
return self.dynamic_linker_buffer[0 .. m + 1];
}
pub fn setDynamicLinker(self: *NativeTargetInfo, dl_or_null: ?[]const u8) void {
if (dl_or_null) |dl| {
mem.copy(u8, &self.dynamic_linker_buffer, dl);
self.dynamic_linker_max = @intCast(u8, dl.len - 1);
} else {
self.dynamic_linker_max = null;
}
}
/// First we attempt to use the executable's own binary. If it is dynamically /// First we attempt to use the executable's own binary. If it is dynamically
/// linked, then it should answer both the C ABI question and the dynamic linker question. /// linked, then it should answer both the C ABI question and the dynamic linker question.
/// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then /// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then
@ -273,15 +253,14 @@ pub const NativeTargetInfo = struct {
.os = os, .os = os,
.abi = abi, .abi = abi,
}; };
const ld_info = &ld_info_list_buffer[ld_info_list_len]; const ld = target.standardDynamicLinkerPath();
ld_info_list_len += 1; if (ld.get() == null) continue;
ld_info.* = .{ ld_info_list_buffer[ld_info_list_len] = .{
.ld_path_buffer = undefined, .ld = ld,
.ld_path_max = undefined,
.abi = abi, .abi = abi,
}; };
ld_info.ld_path_max = target.standardDynamicLinkerPath(&ld_info.ld_path_buffer) orelse continue; ld_info_list_len += 1;
} }
const ld_info_list = ld_info_list_buffer[0..ld_info_list_len]; const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];
@ -298,7 +277,7 @@ pub const NativeTargetInfo = struct {
// This is O(N^M) but typical case here is N=2 and M=10. // This is O(N^M) but typical case here is N=2 and M=10.
find_ld: for (lib_paths) |lib_path| { find_ld: for (lib_paths) |lib_path| {
for (ld_info_list) |ld_info| { for (ld_info_list) |ld_info| {
const standard_ld_basename = fs.path.basename(ld_info.ldPath()); const standard_ld_basename = fs.path.basename(ld_info.ld.get().?);
if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) { if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) {
found_ld_info = ld_info; found_ld_info = ld_info;
found_ld_path = lib_path; found_ld_path = lib_path;
@ -329,8 +308,8 @@ pub const NativeTargetInfo = struct {
.os = os_adjusted, .os = os_adjusted,
.abi = found_ld_info.abi, .abi = found_ld_info.abi,
}, },
.dynamic_linker = DynamicLinker.init(found_ld_path),
}; };
result.setDynamicLinker(found_ld_path);
return result; return result;
} }
@ -472,18 +451,18 @@ pub const NativeTargetInfo = struct {
elf.PT_INTERP => { elf.PT_INTERP => {
const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset); const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz); const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
if (p_filesz > result.dynamic_linker_buffer.len) return error.NameTooLong; if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
_ = try preadFull(env_file, result.dynamic_linker_buffer[0..p_filesz], p_offset, p_filesz); _ = try preadFull(env_file, result.dynamic_linker.buffer[0..p_filesz], p_offset, p_filesz);
// PT_INTERP includes a null byte in p_filesz. // PT_INTERP includes a null byte in p_filesz.
const len = p_filesz - 1; const len = p_filesz - 1;
// dynamic_linker_max is "max", not "len". // dynamic_linker.max_byte is "max", not "len".
// We know it will fit in u8 because we check against dynamic_linker_buffer.len above. // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
result.dynamic_linker_max = @intCast(u8, len - 1); result.dynamic_linker.max_byte = @intCast(u8, len - 1);
// Use it to determine ABI. // Use it to determine ABI.
const full_ld_path = result.dynamic_linker_buffer[0..len]; const full_ld_path = result.dynamic_linker.buffer[0..len];
for (ld_info_list) |ld_info| { for (ld_info_list) |ld_info| {
const standard_ld_basename = fs.path.basename(ld_info.ldPath()); const standard_ld_basename = fs.path.basename(ld_info.ld.get().?);
if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) { if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) {
result.target.abi = ld_info.abi; result.target.abi = ld_info.abi;
break; break;
@ -679,26 +658,20 @@ pub const NativeTargetInfo = struct {
} }
fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo { fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {
var result: NativeTargetInfo = .{ const target: Target = .{
.target = .{ .cpu = cpu,
.cpu = cpu, .os = os,
.os = os, .abi = Target.Abi.default(cpu.arch, os),
.abi = Target.Abi.default(cpu.arch, os), };
}, return NativeTargetInfo{
.target = target,
.dynamic_linker = target.standardDynamicLinkerPath(),
}; };
result.dynamic_linker_max = result.target.standardDynamicLinkerPath(&result.dynamic_linker_buffer);
return result;
} }
const LdInfo = struct { const LdInfo = struct {
ld_path_buffer: [255]u8, ld: DynamicLinker,
ld_path_max: u8,
abi: Target.Abi, abi: Target.Abi,
pub fn ldPath(self: *const LdInfo) []const u8 {
const m: usize = self.ld_path_max;
return self.ld_path_buffer[0 .. m + 1];
}
}; };
fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) { fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {

View File

@ -651,8 +651,9 @@ export fn stage2_target_parse(
target: *Stage2Target, target: *Stage2Target,
zig_triple: ?[*:0]const u8, zig_triple: ?[*:0]const u8,
mcpu: ?[*:0]const u8, mcpu: ?[*:0]const u8,
dynamic_linker: ?[*:0]const u8,
) Error { ) Error {
stage2TargetParse(target, zig_triple, mcpu) catch |err| switch (err) { stage2TargetParse(target, zig_triple, mcpu, dynamic_linker) catch |err| switch (err) {
error.OutOfMemory => return .OutOfMemory, error.OutOfMemory => return .OutOfMemory,
error.UnknownArchitecture => return .UnknownArchitecture, error.UnknownArchitecture => return .UnknownArchitecture,
error.UnknownOperatingSystem => return .UnknownOperatingSystem, error.UnknownOperatingSystem => return .UnknownOperatingSystem,
@ -676,14 +677,17 @@ fn stage2TargetParse(
stage1_target: *Stage2Target, stage1_target: *Stage2Target,
zig_triple_oz: ?[*:0]const u8, zig_triple_oz: ?[*:0]const u8,
mcpu_oz: ?[*:0]const u8, mcpu_oz: ?[*:0]const u8,
dynamic_linker_oz: ?[*:0]const u8,
) !void { ) !void {
const target: CrossTarget = if (zig_triple_oz) |zig_triple_z| blk: { const target: CrossTarget = if (zig_triple_oz) |zig_triple_z| blk: {
const zig_triple = mem.toSliceConst(u8, zig_triple_z); const zig_triple = mem.toSliceConst(u8, zig_triple_z);
const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null; const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null;
const dynamic_linker = if (dynamic_linker_oz) |dl_z| mem.toSliceConst(u8, dl_z) else null;
var diags: CrossTarget.ParseOptions.Diagnostics = .{}; var diags: CrossTarget.ParseOptions.Diagnostics = .{};
break :blk CrossTarget.parse(.{ break :blk CrossTarget.parse(.{
.arch_os_abi = zig_triple, .arch_os_abi = zig_triple,
.cpu_features = mcpu, .cpu_features = mcpu,
.dynamic_linker = dynamic_linker,
.diagnostics = &diags, .diagnostics = &diags,
}) catch |err| switch (err) { }) catch |err| switch (err) {
error.UnknownCpuModel => { error.UnknownCpuModel => {
@ -1170,7 +1174,7 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)
if (cross_target.os_tag == null) { if (cross_target.os_tag == null) {
adjusted_target.os = detected_info.target.os; adjusted_target.os = detected_info.target.os;
if (detected_info.dynamicLinker()) |dl| { if (detected_info.dynamic_linker.get()) |dl| {
have_native_dl = true; have_native_dl = true;
dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl); dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl);
} }
@ -1182,11 +1186,8 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)
} }
} }
if (!have_native_dl) { if (!have_native_dl) {
var buf: [255]u8 = undefined; const dl = adjusted_target.standardDynamicLinkerPath();
dynamic_linker_ptr.* = if (adjusted_target.standardDynamicLinkerPath(&buf)) |m| dynamic_linker_ptr.* = if (dl.get()) |s| try mem.dupeZ(std.heap.c_allocator, u8, s) else null;
try mem.dupeZ(std.heap.c_allocator, u8, buf[0 .. @as(usize, m) + 1])
else
null;
} }
return adjusted_target; return adjusted_target;
} }

View File

@ -2255,7 +2255,6 @@ struct CodeGen {
Buf *test_name_prefix; Buf *test_name_prefix;
Buf *zig_lib_dir; Buf *zig_lib_dir;
Buf *zig_std_dir; Buf *zig_std_dir;
Buf *dynamic_linker_path;
Buf *version_script_path; Buf *version_script_path;
const char **llvm_argv; const char **llvm_argv;

View File

@ -8832,19 +8832,6 @@ static void init(CodeGen *g) {
} }
} }
static void detect_dynamic_linker(CodeGen *g) {
if (g->dynamic_linker_path != nullptr)
return;
if (!g->have_dynamic_link)
return;
if (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))
return;
if (g->zig_target->dynamic_linker != nullptr) {
g->dynamic_linker_path = buf_create_from_str(g->zig_target->dynamic_linker);
}
}
static void detect_libc(CodeGen *g) { static void detect_libc(CodeGen *g) {
Error err; Error err;
@ -10285,6 +10272,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_int(ch, g->zig_target->glibc_or_darwin_version->minor); cache_int(ch, g->zig_target->glibc_or_darwin_version->minor);
cache_int(ch, g->zig_target->glibc_or_darwin_version->patch); cache_int(ch, g->zig_target->glibc_or_darwin_version->patch);
} }
if (g->zig_target->dynamic_linker != nullptr) {
cache_str(ch, g->zig_target->dynamic_linker);
}
cache_int(ch, detect_subsystem(g)); cache_int(ch, detect_subsystem(g));
cache_bool(ch, g->strip_debug_symbols); cache_bool(ch, g->strip_debug_symbols);
cache_bool(ch, g->is_test_build); cache_bool(ch, g->is_test_build);
@ -10325,7 +10315,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_str(ch, g->libc->msvc_lib_dir); cache_str(ch, g->libc->msvc_lib_dir);
cache_str(ch, g->libc->kernel32_lib_dir); cache_str(ch, g->libc->kernel32_lib_dir);
} }
cache_buf_opt(ch, g->dynamic_linker_path);
cache_buf_opt(ch, g->version_script_path); cache_buf_opt(ch, g->version_script_path);
// gen_c_objects appends objects to g->link_objects which we want to include in the hash // gen_c_objects appends objects to g->link_objects which we want to include in the hash
@ -10422,7 +10411,6 @@ void codegen_build_and_link(CodeGen *g) {
g->have_err_ret_tracing = detect_err_ret_tracing(g); g->have_err_ret_tracing = detect_err_ret_tracing(g);
g->have_sanitize_c = detect_sanitize_c(g); g->have_sanitize_c = detect_sanitize_c(g);
detect_libc(g); detect_libc(g);
detect_dynamic_linker(g);
Buf digest = BUF_INIT; Buf digest = BUF_INIT;
if (g->enable_cache) { if (g->enable_cache) {
@ -10619,7 +10607,6 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o
child_gen->verbose_cc = parent_gen->verbose_cc; child_gen->verbose_cc = parent_gen->verbose_cc;
child_gen->verbose_llvm_cpu_features = parent_gen->verbose_llvm_cpu_features; child_gen->verbose_llvm_cpu_features = parent_gen->verbose_llvm_cpu_features;
child_gen->llvm_argv = parent_gen->llvm_argv; child_gen->llvm_argv = parent_gen->llvm_argv;
child_gen->dynamic_linker_path = parent_gen->dynamic_linker_path;
codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled; child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled;

View File

@ -1751,9 +1751,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
} }
if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) { if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) {
assert(g->dynamic_linker_path != nullptr); assert(g->zig_target->dynamic_linker != nullptr);
lj->args.append("-dynamic-linker"); lj->args.append("-dynamic-linker");
lj->args.append(buf_ptr(g->dynamic_linker_path)); lj->args.append(g->zig_target->dynamic_linker);
} }
} }

View File

@ -401,7 +401,7 @@ static int main0(int argc, char **argv) {
bool link_eh_frame_hdr = false; bool link_eh_frame_hdr = false;
ErrColor color = ErrColorAuto; ErrColor color = ErrColorAuto;
CacheOpt enable_cache = CacheOptAuto; CacheOpt enable_cache = CacheOptAuto;
Buf *dynamic_linker = nullptr; const char *dynamic_linker = nullptr;
const char *libc_txt = nullptr; const char *libc_txt = nullptr;
ZigList<const char *> clang_argv = {0}; ZigList<const char *> clang_argv = {0};
ZigList<const char *> lib_dirs = {0}; ZigList<const char *> lib_dirs = {0};
@ -496,7 +496,7 @@ static int main0(int argc, char **argv) {
os_path_join(get_zig_special_dir(zig_lib_dir), buf_create_from_str("build_runner.zig"), build_runner_path); os_path_join(get_zig_special_dir(zig_lib_dir), buf_create_from_str("build_runner.zig"), build_runner_path);
ZigTarget target; ZigTarget target;
if ((err = target_parse_triple(&target, "native", nullptr))) { if ((err = target_parse_triple(&target, "native", nullptr, nullptr))) {
fprintf(stderr, "Unable to get native target: %s\n", err_str(err)); fprintf(stderr, "Unable to get native target: %s\n", err_str(err));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -766,7 +766,7 @@ static int main0(int argc, char **argv) {
} else if (strcmp(arg, "--name") == 0) { } else if (strcmp(arg, "--name") == 0) {
out_name = argv[i]; out_name = argv[i];
} else if (strcmp(arg, "--dynamic-linker") == 0) { } else if (strcmp(arg, "--dynamic-linker") == 0) {
dynamic_linker = buf_create_from_str(argv[i]); dynamic_linker = argv[i];
} else if (strcmp(arg, "--libc") == 0) { } else if (strcmp(arg, "--libc") == 0) {
libc_txt = argv[i]; libc_txt = argv[i];
} else if (strcmp(arg, "-D") == 0) { } else if (strcmp(arg, "-D") == 0) {
@ -968,7 +968,7 @@ static int main0(int argc, char **argv) {
init_all_targets(); init_all_targets();
ZigTarget target; ZigTarget target;
if ((err = target_parse_triple(&target, target_string, mcpu))) { if ((err = target_parse_triple(&target, target_string, mcpu, dynamic_linker))) {
fprintf(stderr, "invalid target: %s\n" fprintf(stderr, "invalid target: %s\n"
"See `%s targets` to display valid targets.\n", err_str(err), arg0); "See `%s targets` to display valid targets.\n", err_str(err), arg0);
return print_error_usage(arg0); return print_error_usage(arg0);
@ -1193,7 +1193,6 @@ static int main0(int argc, char **argv) {
codegen_set_strip(g, strip); codegen_set_strip(g, strip);
g->is_dynamic = is_dynamic; g->is_dynamic = is_dynamic;
g->dynamic_linker_path = dynamic_linker;
g->verbose_tokenize = verbose_tokenize; g->verbose_tokenize = verbose_tokenize;
g->verbose_ast = verbose_ast; g->verbose_ast = verbose_ast;
g->verbose_link = verbose_link; g->verbose_link = verbose_link;
@ -1320,7 +1319,7 @@ static int main0(int argc, char **argv) {
return main_exit(root_progress_node, EXIT_SUCCESS); return main_exit(root_progress_node, EXIT_SUCCESS);
} else if (cmd == CmdTest) { } else if (cmd == CmdTest) {
ZigTarget native; ZigTarget native;
if ((err = target_parse_triple(&native, "native", nullptr))) { if ((err = target_parse_triple(&native, "native", nullptr, nullptr))) {
fprintf(stderr, "Unable to get native target: %s\n", err_str(err)); fprintf(stderr, "Unable to get native target: %s\n", err_str(err));
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -191,7 +191,9 @@ static void get_native_target(ZigTarget *target) {
} }
} }
Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu) { Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
const char *dynamic_linker)
{
Error err; Error err;
if (zig_triple == nullptr) { if (zig_triple == nullptr) {
@ -249,6 +251,9 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons
target->cache_hash = "\n\n"; target->cache_hash = "\n\n";
} }
if (dynamic_linker != nullptr) {
target->dynamic_linker = dynamic_linker;
}
return ErrorNone; return ErrorNone;
} }

View File

@ -298,7 +298,8 @@ struct ZigTarget {
}; };
// ABI warning // ABI warning
ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu); ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
const char *dynamic_linker);
// ABI warning // ABI warning

View File

@ -410,8 +410,8 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si
return ErrorUnknownABI; return ErrorUnknownABI;
} }
Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu) { Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker) {
return stage2_target_parse(target, triple, mcpu); return stage2_target_parse(target, triple, mcpu, dynamic_linker);
} }
const char *target_arch_name(ZigLLVM_ArchType arch) { const char *target_arch_name(ZigLLVM_ArchType arch) {

View File

@ -41,7 +41,7 @@ enum CIntType {
CIntTypeCount, CIntTypeCount,
}; };
Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu); Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker);
Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len); Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len);
Error target_parse_os(Os *os, const char *os_ptr, size_t os_len); Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len); Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);