authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-28 13:27:52-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-28 14:51:56-05:00
log500dde32d5cf59f5700fb3f69ae6c7a0defd8a93
tree135d6b28fdb7690a8ef117b378cec0f11392d1ee
parent07f52119de2a8bdb84389c73332e113cf12ac997
signature Commit is signed but in an unrecognized format.

dynamic_linker becomes a field of std.zig.CrossTarget


13 files changed, 137 insertions(+), 127 deletions(-)

lib/std/build.zig+5-7
...@@ -1177,8 +1177,6 @@ pub const LibExeObjStep = struct {...@@ -1177,8 +1177,6 @@ pub const LibExeObjStep = struct {
1177 /// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.1177 /// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
1178 glibc_multi_install_dir: ?[]const u8 = null,1178 glibc_multi_install_dir: ?[]const u8 = null,
11791179
1180 dynamic_linker: ?[]const u8 = null,
1181
1182 /// Position Independent Code1180 /// Position Independent Code
1183 force_pic: ?bool = null,1181 force_pic: ?bool = null,
11841182
...@@ -1978,6 +1976,11 @@ pub const LibExeObjStep = struct {...@@ -1978,6 +1976,11 @@ pub const LibExeObjStep = struct {
1978 }1976 }
1979 try zig_args.append(mcpu_buffer.toSliceConst());1977 try zig_args.append(mcpu_buffer.toSliceConst());
1980 }1978 }
1979
1980 if (self.target.dynamic_linker.get()) |dynamic_linker| {
1981 try zig_args.append("--dynamic-linker");
1982 try zig_args.append(dynamic_linker);
1983 }
1981 }1984 }
19821985
1983 if (self.linker_script) |linker_script| {1986 if (self.linker_script) |linker_script| {
...@@ -1985,11 +1988,6 @@ pub const LibExeObjStep = struct {...@@ -1985,11 +1988,6 @@ pub const LibExeObjStep = struct {
1985 zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable;1988 zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable;
1986 }1989 }
19871990
1988 if (self.dynamic_linker) |dynamic_linker| {
1989 try zig_args.append("--dynamic-linker");
1990 try zig_args.append(dynamic_linker);
1991 }
1992
1993 if (self.version_script) |version_script| {1991 if (self.version_script) |version_script| {
1994 try zig_args.append("--version-script");1992 try zig_args.append("--version-script");
1995 try zig_args.append(builder.pathFromRoot(version_script));1993 try zig_args.append(builder.pathFromRoot(version_script));
lib/std/target.zig+64-28
...@@ -1099,16 +1099,52 @@ pub const Target = struct {...@@ -1099,16 +1099,52 @@ pub const Target = struct {
1099 }1099 }
1100 }1100 }
11011101
1102 pub const DynamicLinker = struct {
1103 /// Contains the memory used to store the dynamic linker path. This field should
1104 /// not be used directly. See `get` and `set`. This field exists so that this API requires no allocator.
1105 buffer: [255]u8 = undefined,
1106
1107 /// Used to construct the dynamic linker path. This field should not be used
1108 /// directly. See `get` and `set`.
1109 max_byte: ?u8 = null,
1110
1111 /// Asserts that the length is less than or equal to 255 bytes.
1112 pub fn init(dl_or_null: ?[]const u8) DynamicLinker {
1113 var result: DynamicLinker = undefined;
1114 result.set(dl_or_null);
1115 return result;
1116 }
1117
1118 /// The returned memory has the same lifetime as the `DynamicLinker`.
1119 pub fn get(self: *const DynamicLinker) ?[]const u8 {
1120 const m: usize = self.max_byte orelse return null;
1121 return self.buffer[0 .. m + 1];
1122 }
1123
1124 /// Asserts that the length is less than or equal to 255 bytes.
1125 pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {
1126 if (dl_or_null) |dl| {
1127 mem.copy(u8, &self.buffer, dl);
1128 self.max_byte = @intCast(u8, dl.len - 1);
1129 } else {
1130 self.max_byte = null;
1131 }
1132 }
1133 };
1134
1102 /// The result will be a byte index *pointing at the final byte*. In other words, length minus one.1135 /// The result will be a byte index *pointing at the final byte*. In other words, length minus one.
1103 /// A return value of `null` means the concept of a dynamic linker is not meaningful for that target.1136 /// A return value of `null` means the concept of a dynamic linker is not meaningful for that target.
1104 pub fn standardDynamicLinkerPath(self: Target, buffer: *[255]u8) ?u8 {1137 pub fn standardDynamicLinkerPath(self: Target) DynamicLinker {
1138 var result: DynamicLinker = .{};
1105 const S = struct {1139 const S = struct {
1106 fn print(b: *[255]u8, comptime fmt: []const u8, args: var) u8 {1140 fn print(r: *DynamicLinker, comptime fmt: []const u8, args: var) DynamicLinker {
1107 return @intCast(u8, (std.fmt.bufPrint(b, fmt, args) catch unreachable).len - 1);1141 r.max_byte = @intCast(u8, (std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1);
1142 return r.*;
1108 }1143 }
1109 fn copy(b: *[255]u8, s: []const u8) u8 {1144 fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
1110 mem.copy(u8, b, s);1145 mem.copy(u8, &r.buffer, s);
1111 return @intCast(u8, s.len - 1);1146 r.max_byte = @intCast(u8, s.len - 1);
1147 return r.*;
1112 }1148 }
1113 };1149 };
1114 const print = S.print;1150 const print = S.print;
...@@ -1116,7 +1152,7 @@ pub const Target = struct {...@@ -1116,7 +1152,7 @@ pub const Target = struct {
11161152
1117 if (self.isAndroid()) {1153 if (self.isAndroid()) {
1118 const suffix = if (self.cpu.arch.ptrBitWidth() == 64) "64" else "";1154 const suffix = if (self.cpu.arch.ptrBitWidth() == 64) "64" else "";
1119 return print(buffer, "/system/bin/linker{}", .{suffix});1155 return print(&result, "/system/bin/linker{}", .{suffix});
1120 }1156 }
11211157
1122 if (self.isMusl()) {1158 if (self.isMusl()) {
...@@ -1130,28 +1166,28 @@ pub const Target = struct {...@@ -1130,28 +1166,28 @@ pub const Target = struct {
1130 else => |arch| @tagName(arch),1166 else => |arch| @tagName(arch),
1131 };1167 };
1132 const arch_suffix = if (is_arm and self.getFloatAbi() == .hard) "hf" else "";1168 const arch_suffix = if (is_arm and self.getFloatAbi() == .hard) "hf" else "";
1133 return print(buffer, "/lib/ld-musl-{}{}.so.1", .{ arch_part, arch_suffix });1169 return print(&result, "/lib/ld-musl-{}{}.so.1", .{ arch_part, arch_suffix });
1134 }1170 }
11351171
1136 switch (self.os.tag) {1172 switch (self.os.tag) {
1137 .freebsd => return copy(buffer, "/libexec/ld-elf.so.1"),1173 .freebsd => return copy(&result, "/libexec/ld-elf.so.1"),
1138 .netbsd => return copy(buffer, "/libexec/ld.elf_so"),1174 .netbsd => return copy(&result, "/libexec/ld.elf_so"),
1139 .dragonfly => return copy(buffer, "/libexec/ld-elf.so.2"),1175 .dragonfly => return copy(&result, "/libexec/ld-elf.so.2"),
1140 .linux => switch (self.cpu.arch) {1176 .linux => switch (self.cpu.arch) {
1141 .i386,1177 .i386,
1142 .sparc,1178 .sparc,
1143 .sparcel,1179 .sparcel,
1144 => return copy(buffer, "/lib/ld-linux.so.2"),1180 => return copy(&result, "/lib/ld-linux.so.2"),
11451181
1146 .aarch64 => return copy(buffer, "/lib/ld-linux-aarch64.so.1"),1182 .aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"),
1147 .aarch64_be => return copy(buffer, "/lib/ld-linux-aarch64_be.so.1"),1183 .aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"),
1148 .aarch64_32 => return copy(buffer, "/lib/ld-linux-aarch64_32.so.1"),1184 .aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"),
11491185
1150 .arm,1186 .arm,
1151 .armeb,1187 .armeb,
1152 .thumb,1188 .thumb,
1153 .thumbeb,1189 .thumbeb,
1154 => return copy(buffer, switch (self.getFloatAbi()) {1190 => return copy(&result, switch (self.getFloatAbi()) {
1155 .hard => "/lib/ld-linux-armhf.so.3",1191 .hard => "/lib/ld-linux-armhf.so.3",
1156 else => "/lib/ld-linux.so.3",1192 else => "/lib/ld-linux.so.3",
1157 }),1193 }),
...@@ -1168,20 +1204,20 @@ pub const Target = struct {...@@ -1168,20 +1204,20 @@ pub const Target = struct {
1168 };1204 };
1169 const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008);1205 const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008);
1170 const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";1206 const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";
1171 return print(buffer, "/lib{}/{}", .{ lib_suffix, loader });1207 return print(&result, "/lib{}/{}", .{ lib_suffix, loader });
1172 },1208 },
11731209
1174 .powerpc => return copy(buffer, "/lib/ld.so.1"),1210 .powerpc => return copy(&result, "/lib/ld.so.1"),
1175 .powerpc64, .powerpc64le => return copy(buffer, "/lib64/ld64.so.2"),1211 .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"),
1176 .s390x => return copy(buffer, "/lib64/ld64.so.1"),1212 .s390x => return copy(&result, "/lib64/ld64.so.1"),
1177 .sparcv9 => return copy(buffer, "/lib64/ld-linux.so.2"),1213 .sparcv9 => return copy(&result, "/lib64/ld-linux.so.2"),
1178 .x86_64 => return copy(buffer, switch (self.abi) {1214 .x86_64 => return copy(&result, switch (self.abi) {
1179 .gnux32 => "/libx32/ld-linux-x32.so.2",1215 .gnux32 => "/libx32/ld-linux-x32.so.2",
1180 else => "/lib64/ld-linux-x86-64.so.2",1216 else => "/lib64/ld-linux-x86-64.so.2",
1181 }),1217 }),
11821218
1183 .riscv32 => return copy(buffer, "/lib/ld-linux-riscv32-ilp32.so.1"),1219 .riscv32 => return copy(&result, "/lib/ld-linux-riscv32-ilp32.so.1"),
1184 .riscv64 => return copy(buffer, "/lib/ld-linux-riscv64-lp64.so.1"),1220 .riscv64 => return copy(&result, "/lib/ld-linux-riscv64-lp64.so.1"),
11851221
1186 // Architectures in this list have been verified as not having a standard1222 // Architectures in this list have been verified as not having a standard
1187 // dynamic linker path.1223 // dynamic linker path.
...@@ -1191,7 +1227,7 @@ pub const Target = struct {...@@ -1191,7 +1227,7 @@ pub const Target = struct {
1191 .bpfeb,1227 .bpfeb,
1192 .nvptx,1228 .nvptx,
1193 .nvptx64,1229 .nvptx64,
1194 => return null,1230 => return result,
11951231
1196 // TODO go over each item in this list and either move it to the above list, or1232 // TODO go over each item in this list and either move it to the above list, or
1197 // implement the standard dynamic linker path code for it.1233 // implement the standard dynamic linker path code for it.
...@@ -1217,7 +1253,7 @@ pub const Target = struct {...@@ -1217,7 +1253,7 @@ pub const Target = struct {
1217 .lanai,1253 .lanai,
1218 .renderscript32,1254 .renderscript32,
1219 .renderscript64,1255 .renderscript64,
1220 => return null,1256 => return result,
1221 },1257 },
12221258
1223 // Operating systems in this list have been verified as not having a standard1259 // Operating systems in this list have been verified as not having a standard
...@@ -1232,7 +1268,7 @@ pub const Target = struct {...@@ -1232,7 +1268,7 @@ pub const Target = struct {
1232 .emscripten,1268 .emscripten,
1233 .wasi,1269 .wasi,
1234 .other,1270 .other,
1235 => return null,1271 => return result,
12361272
1237 // TODO go over each item in this list and either move it to the above list, or1273 // TODO go over each item in this list and either move it to the above list, or
1238 // implement the standard dynamic linker path code for it.1274 // implement the standard dynamic linker path code for it.
...@@ -1259,7 +1295,7 @@ pub const Target = struct {...@@ -1259,7 +1295,7 @@ pub const Target = struct {
1259 .amdpal,1295 .amdpal,
1260 .hermit,1296 .hermit,
1261 .hurd,1297 .hurd,
1262 => return null,1298 => return result,
1263 }1299 }
1264 }1300 }
1265};1301};
lib/std/zig/cross_target.zig+14-3
...@@ -40,6 +40,10 @@ pub const CrossTarget = struct {...@@ -40,6 +40,10 @@ pub const CrossTarget = struct {
40 /// If `isGnuLibC()` is `false`, this must be `null` and is ignored.40 /// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
41 glibc_version: ?SemVer = null,41 glibc_version: ?SemVer = null,
4242
43 /// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path
44 /// based on the `os_tag`.
45 dynamic_linker: DynamicLinker = DynamicLinker{},
46
43 pub const OsVersion = union(enum) {47 pub const OsVersion = union(enum) {
44 none: void,48 none: void,
45 semver: SemVer,49 semver: SemVer,
...@@ -48,6 +52,8 @@ pub const CrossTarget = struct {...@@ -48,6 +52,8 @@ pub const CrossTarget = struct {
4852
49 pub const SemVer = std.builtin.Version;53 pub const SemVer = std.builtin.Version;
5054
55 pub const DynamicLinker = Target.DynamicLinker;
56
51 pub fn fromTarget(target: Target) CrossTarget {57 pub fn fromTarget(target: Target) CrossTarget {
52 var result: CrossTarget = .{58 var result: CrossTarget = .{
53 .cpu_arch = target.cpu.arch,59 .cpu_arch = target.cpu.arch,
...@@ -170,6 +176,10 @@ pub const CrossTarget = struct {...@@ -170,6 +176,10 @@ pub const CrossTarget = struct {
170 /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline".176 /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline".
171 cpu_features: ?[]const u8 = null,177 cpu_features: ?[]const u8 = null,
172178
179 /// Absolute path to dynamic linker, to override the default, which is either a natively
180 /// detected path, or a standard path.
181 dynamic_linker: ?[]const u8 = null,
182
173 /// If this is provided, the function will populate some information about parsing failures,183 /// If this is provided, the function will populate some information about parsing failures,
174 /// so that user-friendly error messages can be delivered.184 /// so that user-friendly error messages can be delivered.
175 diagnostics: ?*Diagnostics = null,185 diagnostics: ?*Diagnostics = null,
...@@ -199,8 +209,9 @@ pub const CrossTarget = struct {...@@ -199,8 +209,9 @@ pub const CrossTarget = struct {
199 var dummy_diags: ParseOptions.Diagnostics = undefined;209 var dummy_diags: ParseOptions.Diagnostics = undefined;
200 const diags = args.diagnostics orelse &dummy_diags;210 const diags = args.diagnostics orelse &dummy_diags;
201211
202 // Start with everything initialized to default values.212 var result: CrossTarget = .{
203 var result: CrossTarget = .{};213 .dynamic_linker = DynamicLinker.init(args.dynamic_linker),
214 };
204215
205 var it = mem.separate(args.arch_os_abi, "-");216 var it = mem.separate(args.arch_os_abi, "-");
206 const arch_name = it.next().?;217 const arch_name = it.next().?;
...@@ -446,7 +457,7 @@ pub const CrossTarget = struct {...@@ -446,7 +457,7 @@ pub const CrossTarget = struct {
446 return self.cpu_arch == null and self.cpu_model == null and457 return self.cpu_arch == null and self.cpu_model == null and
447 self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty() and458 self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty() and
448 self.os_tag == null and self.os_version_min == null and self.os_version_max == null and459 self.os_tag == null and self.os_version_min == null and self.os_version_max == null and
449 self.abi == null;460 self.abi == null and self.dynamic_linker.get() == null;
450 }461 }
451462
452 pub fn zigTriple(self: CrossTarget, allocator: *mem.Allocator) error{OutOfMemory}![:0]u8 {463 pub fn zigTriple(self: CrossTarget, allocator: *mem.Allocator) error{OutOfMemory}![:0]u8 {
lib/std/zig/system.zig+25-52
...@@ -168,14 +168,9 @@ pub const NativePaths = struct {...@@ -168,14 +168,9 @@ pub const NativePaths = struct {
168pub const NativeTargetInfo = struct {168pub const NativeTargetInfo = struct {
169 target: Target,169 target: Target,
170170
171 /// Contains the memory used to store the dynamic linker path. This field should171 dynamic_linker: DynamicLinker = DynamicLinker{},
172 /// not be used directly. See `dynamicLinker` and `setDynamicLinker`. This field
173 /// exists so that this API requires no allocator.
174 dynamic_linker_buffer: [255]u8 = undefined,
175172
176 /// Used to construct the dynamic linker path. This field should not be used173 pub const DynamicLinker = Target.DynamicLinker;
177 /// directly. See `dynamicLinker` and `setDynamicLinker`.
178 dynamic_linker_max: ?u8 = null,
179174
180 pub const DetectError = error{175 pub const DetectError = error{
181 OutOfMemory,176 OutOfMemory,
...@@ -220,21 +215,6 @@ pub const NativeTargetInfo = struct {...@@ -220,21 +215,6 @@ pub const NativeTargetInfo = struct {
220 return detectAbiAndDynamicLinker(allocator, cpu, os);215 return detectAbiAndDynamicLinker(allocator, cpu, os);
221 }216 }
222217
223 /// The returned memory has the same lifetime as the `NativeTargetInfo`.
224 pub fn dynamicLinker(self: *const NativeTargetInfo) ?[]const u8 {
225 const m: usize = self.dynamic_linker_max orelse return null;
226 return self.dynamic_linker_buffer[0 .. m + 1];
227 }
228
229 pub fn setDynamicLinker(self: *NativeTargetInfo, dl_or_null: ?[]const u8) void {
230 if (dl_or_null) |dl| {
231 mem.copy(u8, &self.dynamic_linker_buffer, dl);
232 self.dynamic_linker_max = @intCast(u8, dl.len - 1);
233 } else {
234 self.dynamic_linker_max = null;
235 }
236 }
237
238 /// First we attempt to use the executable's own binary. If it is dynamically218 /// First we attempt to use the executable's own binary. If it is dynamically
239 /// linked, then it should answer both the C ABI question and the dynamic linker question.219 /// linked, then it should answer both the C ABI question and the dynamic linker question.
240 /// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then220 /// 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 {...@@ -273,15 +253,14 @@ pub const NativeTargetInfo = struct {
273 .os = os,253 .os = os,
274 .abi = abi,254 .abi = abi,
275 };255 };
276 const ld_info = &ld_info_list_buffer[ld_info_list_len];256 const ld = target.standardDynamicLinkerPath();
277 ld_info_list_len += 1;257 if (ld.get() == null) continue;
278258
279 ld_info.* = .{259 ld_info_list_buffer[ld_info_list_len] = .{
280 .ld_path_buffer = undefined,260 .ld = ld,
281 .ld_path_max = undefined,
282 .abi = abi,261 .abi = abi,
283 };262 };
284 ld_info.ld_path_max = target.standardDynamicLinkerPath(&ld_info.ld_path_buffer) orelse continue;263 ld_info_list_len += 1;
285 }264 }
286 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];265 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];
287266
...@@ -298,7 +277,7 @@ pub const NativeTargetInfo = struct {...@@ -298,7 +277,7 @@ pub const NativeTargetInfo = struct {
298 // This is O(N^M) but typical case here is N=2 and M=10.277 // This is O(N^M) but typical case here is N=2 and M=10.
299 find_ld: for (lib_paths) |lib_path| {278 find_ld: for (lib_paths) |lib_path| {
300 for (ld_info_list) |ld_info| {279 for (ld_info_list) |ld_info| {
301 const standard_ld_basename = fs.path.basename(ld_info.ldPath());280 const standard_ld_basename = fs.path.basename(ld_info.ld.get().?);
302 if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) {281 if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) {
303 found_ld_info = ld_info;282 found_ld_info = ld_info;
304 found_ld_path = lib_path;283 found_ld_path = lib_path;
...@@ -329,8 +308,8 @@ pub const NativeTargetInfo = struct {...@@ -329,8 +308,8 @@ pub const NativeTargetInfo = struct {
329 .os = os_adjusted,308 .os = os_adjusted,
330 .abi = found_ld_info.abi,309 .abi = found_ld_info.abi,
331 },310 },
311 .dynamic_linker = DynamicLinker.init(found_ld_path),
332 };312 };
333 result.setDynamicLinker(found_ld_path);
334 return result;313 return result;
335 }314 }
336315
...@@ -472,18 +451,18 @@ pub const NativeTargetInfo = struct {...@@ -472,18 +451,18 @@ pub const NativeTargetInfo = struct {
472 elf.PT_INTERP => {451 elf.PT_INTERP => {
473 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);452 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
474 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);453 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
475 if (p_filesz > result.dynamic_linker_buffer.len) return error.NameTooLong;454 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
476 _ = try preadFull(env_file, result.dynamic_linker_buffer[0..p_filesz], p_offset, p_filesz);455 _ = try preadFull(env_file, result.dynamic_linker.buffer[0..p_filesz], p_offset, p_filesz);
477 // PT_INTERP includes a null byte in p_filesz.456 // PT_INTERP includes a null byte in p_filesz.
478 const len = p_filesz - 1;457 const len = p_filesz - 1;
479 // dynamic_linker_max is "max", not "len".458 // dynamic_linker.max_byte is "max", not "len".
480 // We know it will fit in u8 because we check against dynamic_linker_buffer.len above.459 // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
481 result.dynamic_linker_max = @intCast(u8, len - 1);460 result.dynamic_linker.max_byte = @intCast(u8, len - 1);
482461
483 // Use it to determine ABI.462 // Use it to determine ABI.
484 const full_ld_path = result.dynamic_linker_buffer[0..len];463 const full_ld_path = result.dynamic_linker.buffer[0..len];
485 for (ld_info_list) |ld_info| {464 for (ld_info_list) |ld_info| {
486 const standard_ld_basename = fs.path.basename(ld_info.ldPath());465 const standard_ld_basename = fs.path.basename(ld_info.ld.get().?);
487 if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) {466 if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) {
488 result.target.abi = ld_info.abi;467 result.target.abi = ld_info.abi;
489 break;468 break;
...@@ -679,26 +658,20 @@ pub const NativeTargetInfo = struct {...@@ -679,26 +658,20 @@ pub const NativeTargetInfo = struct {
679 }658 }
680659
681 fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {660 fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {
682 var result: NativeTargetInfo = .{661 const target: Target = .{
683 .target = .{662 .cpu = cpu,
684 .cpu = cpu,663 .os = os,
685 .os = os,664 .abi = Target.Abi.default(cpu.arch, os),
686 .abi = Target.Abi.default(cpu.arch, os),665 };
687 },666 return NativeTargetInfo{
667 .target = target,
668 .dynamic_linker = target.standardDynamicLinkerPath(),
688 };669 };
689 result.dynamic_linker_max = result.target.standardDynamicLinkerPath(&result.dynamic_linker_buffer);
690 return result;
691 }670 }
692671
693 const LdInfo = struct {672 const LdInfo = struct {
694 ld_path_buffer: [255]u8,673 ld: DynamicLinker,
695 ld_path_max: u8,
696 abi: Target.Abi,674 abi: Target.Abi,
697
698 pub fn ldPath(self: *const LdInfo) []const u8 {
699 const m: usize = self.ld_path_max;
700 return self.ld_path_buffer[0 .. m + 1];
701 }
702 };675 };
703676
704 fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {677 fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {
src-self-hosted/stage2.zig+8-7
...@@ -651,8 +651,9 @@ export fn stage2_target_parse(...@@ -651,8 +651,9 @@ export fn stage2_target_parse(
651 target: *Stage2Target,651 target: *Stage2Target,
652 zig_triple: ?[*:0]const u8,652 zig_triple: ?[*:0]const u8,
653 mcpu: ?[*:0]const u8,653 mcpu: ?[*:0]const u8,
654 dynamic_linker: ?[*:0]const u8,
654) Error {655) Error {
655 stage2TargetParse(target, zig_triple, mcpu) catch |err| switch (err) {656 stage2TargetParse(target, zig_triple, mcpu, dynamic_linker) catch |err| switch (err) {
656 error.OutOfMemory => return .OutOfMemory,657 error.OutOfMemory => return .OutOfMemory,
657 error.UnknownArchitecture => return .UnknownArchitecture,658 error.UnknownArchitecture => return .UnknownArchitecture,
658 error.UnknownOperatingSystem => return .UnknownOperatingSystem,659 error.UnknownOperatingSystem => return .UnknownOperatingSystem,
...@@ -676,14 +677,17 @@ fn stage2TargetParse(...@@ -676,14 +677,17 @@ fn stage2TargetParse(
676 stage1_target: *Stage2Target,677 stage1_target: *Stage2Target,
677 zig_triple_oz: ?[*:0]const u8,678 zig_triple_oz: ?[*:0]const u8,
678 mcpu_oz: ?[*:0]const u8,679 mcpu_oz: ?[*:0]const u8,
680 dynamic_linker_oz: ?[*:0]const u8,
679) !void {681) !void {
680 const target: CrossTarget = if (zig_triple_oz) |zig_triple_z| blk: {682 const target: CrossTarget = if (zig_triple_oz) |zig_triple_z| blk: {
681 const zig_triple = mem.toSliceConst(u8, zig_triple_z);683 const zig_triple = mem.toSliceConst(u8, zig_triple_z);
682 const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null;684 const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null;
685 const dynamic_linker = if (dynamic_linker_oz) |dl_z| mem.toSliceConst(u8, dl_z) else null;
683 var diags: CrossTarget.ParseOptions.Diagnostics = .{};686 var diags: CrossTarget.ParseOptions.Diagnostics = .{};
684 break :blk CrossTarget.parse(.{687 break :blk CrossTarget.parse(.{
685 .arch_os_abi = zig_triple,688 .arch_os_abi = zig_triple,
686 .cpu_features = mcpu,689 .cpu_features = mcpu,
690 .dynamic_linker = dynamic_linker,
687 .diagnostics = &diags,691 .diagnostics = &diags,
688 }) catch |err| switch (err) {692 }) catch |err| switch (err) {
689 error.UnknownCpuModel => {693 error.UnknownCpuModel => {
...@@ -1170,7 +1174,7 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)...@@ -1170,7 +1174,7 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)
1170 if (cross_target.os_tag == null) {1174 if (cross_target.os_tag == null) {
1171 adjusted_target.os = detected_info.target.os;1175 adjusted_target.os = detected_info.target.os;
11721176
1173 if (detected_info.dynamicLinker()) |dl| {1177 if (detected_info.dynamic_linker.get()) |dl| {
1174 have_native_dl = true;1178 have_native_dl = true;
1175 dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl);1179 dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl);
1176 }1180 }
...@@ -1182,11 +1186,8 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)...@@ -1182,11 +1186,8 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)
1182 }1186 }
1183 }1187 }
1184 if (!have_native_dl) {1188 if (!have_native_dl) {
1185 var buf: [255]u8 = undefined;1189 const dl = adjusted_target.standardDynamicLinkerPath();
1186 dynamic_linker_ptr.* = if (adjusted_target.standardDynamicLinkerPath(&buf)) |m|1190 dynamic_linker_ptr.* = if (dl.get()) |s| try mem.dupeZ(std.heap.c_allocator, u8, s) else null;
1187 try mem.dupeZ(std.heap.c_allocator, u8, buf[0 .. @as(usize, m) + 1])
1188 else
1189 null;
1190 }1191 }
1191 return adjusted_target;1192 return adjusted_target;
1192}1193}
src/all_types.hpp-1
...@@ -2255,7 +2255,6 @@ struct CodeGen {...@@ -2255,7 +2255,6 @@ struct CodeGen {
2255 Buf *test_name_prefix;2255 Buf *test_name_prefix;
2256 Buf *zig_lib_dir;2256 Buf *zig_lib_dir;
2257 Buf *zig_std_dir;2257 Buf *zig_std_dir;
2258 Buf *dynamic_linker_path;
2259 Buf *version_script_path;2258 Buf *version_script_path;
22602259
2261 const char **llvm_argv;2260 const char **llvm_argv;
src/codegen.cpp+3-16
...@@ -8832,19 +8832,6 @@ static void init(CodeGen *g) {...@@ -8832,19 +8832,6 @@ static void init(CodeGen *g) {
8832 }8832 }
8833}8833}
88348834
8835static void detect_dynamic_linker(CodeGen *g) {
8836 if (g->dynamic_linker_path != nullptr)
8837 return;
8838 if (!g->have_dynamic_link)
8839 return;
8840 if (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))
8841 return;
8842
8843 if (g->zig_target->dynamic_linker != nullptr) {
8844 g->dynamic_linker_path = buf_create_from_str(g->zig_target->dynamic_linker);
8845 }
8846}
8847
8848static void detect_libc(CodeGen *g) {8835static void detect_libc(CodeGen *g) {
8849 Error err;8836 Error err;
88508837
...@@ -10285,6 +10272,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -10285,6 +10272,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
10285 cache_int(ch, g->zig_target->glibc_or_darwin_version->minor);10272 cache_int(ch, g->zig_target->glibc_or_darwin_version->minor);
10286 cache_int(ch, g->zig_target->glibc_or_darwin_version->patch);10273 cache_int(ch, g->zig_target->glibc_or_darwin_version->patch);
10287 }10274 }
10275 if (g->zig_target->dynamic_linker != nullptr) {
10276 cache_str(ch, g->zig_target->dynamic_linker);
10277 }
10288 cache_int(ch, detect_subsystem(g));10278 cache_int(ch, detect_subsystem(g));
10289 cache_bool(ch, g->strip_debug_symbols);10279 cache_bool(ch, g->strip_debug_symbols);
10290 cache_bool(ch, g->is_test_build);10280 cache_bool(ch, g->is_test_build);
...@@ -10325,7 +10315,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -10325,7 +10315,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
10325 cache_str(ch, g->libc->msvc_lib_dir);10315 cache_str(ch, g->libc->msvc_lib_dir);
10326 cache_str(ch, g->libc->kernel32_lib_dir);10316 cache_str(ch, g->libc->kernel32_lib_dir);
10327 }10317 }
10328 cache_buf_opt(ch, g->dynamic_linker_path);
10329 cache_buf_opt(ch, g->version_script_path);10318 cache_buf_opt(ch, g->version_script_path);
1033010319
10331 // gen_c_objects appends objects to g->link_objects which we want to include in the hash10320 // 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) {...@@ -10422,7 +10411,6 @@ void codegen_build_and_link(CodeGen *g) {
10422 g->have_err_ret_tracing = detect_err_ret_tracing(g);10411 g->have_err_ret_tracing = detect_err_ret_tracing(g);
10423 g->have_sanitize_c = detect_sanitize_c(g);10412 g->have_sanitize_c = detect_sanitize_c(g);
10424 detect_libc(g);10413 detect_libc(g);
10425 detect_dynamic_linker(g);
1042610414
10427 Buf digest = BUF_INIT;10415 Buf digest = BUF_INIT;
10428 if (g->enable_cache) {10416 if (g->enable_cache) {
...@@ -10619,7 +10607,6 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o...@@ -10619,7 +10607,6 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o
10619 child_gen->verbose_cc = parent_gen->verbose_cc;10607 child_gen->verbose_cc = parent_gen->verbose_cc;
10620 child_gen->verbose_llvm_cpu_features = parent_gen->verbose_llvm_cpu_features;10608 child_gen->verbose_llvm_cpu_features = parent_gen->verbose_llvm_cpu_features;
10621 child_gen->llvm_argv = parent_gen->llvm_argv;10609 child_gen->llvm_argv = parent_gen->llvm_argv;
10622 child_gen->dynamic_linker_path = parent_gen->dynamic_linker_path;
1062310610
10624 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);10611 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
10625 child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled;10612 child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled;
src/link.cpp+2-2
...@@ -1751,9 +1751,9 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -1751,9 +1751,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
1751 }1751 }
17521752
1753 if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) {1753 if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) {
1754 assert(g->dynamic_linker_path != nullptr);1754 assert(g->zig_target->dynamic_linker != nullptr);
1755 lj->args.append("-dynamic-linker");1755 lj->args.append("-dynamic-linker");
1756 lj->args.append(buf_ptr(g->dynamic_linker_path));1756 lj->args.append(g->zig_target->dynamic_linker);
1757 }1757 }
1758 }1758 }
17591759
src/main.cpp+5-6
...@@ -401,7 +401,7 @@ static int main0(int argc, char **argv) {...@@ -401,7 +401,7 @@ static int main0(int argc, char **argv) {
401 bool link_eh_frame_hdr = false;401 bool link_eh_frame_hdr = false;
402 ErrColor color = ErrColorAuto;402 ErrColor color = ErrColorAuto;
403 CacheOpt enable_cache = CacheOptAuto;403 CacheOpt enable_cache = CacheOptAuto;
404 Buf *dynamic_linker = nullptr;404 const char *dynamic_linker = nullptr;
405 const char *libc_txt = nullptr;405 const char *libc_txt = nullptr;
406 ZigList<const char *> clang_argv = {0};406 ZigList<const char *> clang_argv = {0};
407 ZigList<const char *> lib_dirs = {0};407 ZigList<const char *> lib_dirs = {0};
...@@ -496,7 +496,7 @@ static int main0(int argc, char **argv) {...@@ -496,7 +496,7 @@ static int main0(int argc, char **argv) {
496 os_path_join(get_zig_special_dir(zig_lib_dir), buf_create_from_str("build_runner.zig"), build_runner_path);496 os_path_join(get_zig_special_dir(zig_lib_dir), buf_create_from_str("build_runner.zig"), build_runner_path);
497497
498 ZigTarget target;498 ZigTarget target;
499 if ((err = target_parse_triple(&target, "native", nullptr))) {499 if ((err = target_parse_triple(&target, "native", nullptr, nullptr))) {
500 fprintf(stderr, "Unable to get native target: %s\n", err_str(err));500 fprintf(stderr, "Unable to get native target: %s\n", err_str(err));
501 return EXIT_FAILURE;501 return EXIT_FAILURE;
502 }502 }
...@@ -766,7 +766,7 @@ static int main0(int argc, char **argv) {...@@ -766,7 +766,7 @@ static int main0(int argc, char **argv) {
766 } else if (strcmp(arg, "--name") == 0) {766 } else if (strcmp(arg, "--name") == 0) {
767 out_name = argv[i];767 out_name = argv[i];
768 } else if (strcmp(arg, "--dynamic-linker") == 0) {768 } else if (strcmp(arg, "--dynamic-linker") == 0) {
769 dynamic_linker = buf_create_from_str(argv[i]);769 dynamic_linker = argv[i];
770 } else if (strcmp(arg, "--libc") == 0) {770 } else if (strcmp(arg, "--libc") == 0) {
771 libc_txt = argv[i];771 libc_txt = argv[i];
772 } else if (strcmp(arg, "-D") == 0) {772 } else if (strcmp(arg, "-D") == 0) {
...@@ -968,7 +968,7 @@ static int main0(int argc, char **argv) {...@@ -968,7 +968,7 @@ static int main0(int argc, char **argv) {
968 init_all_targets();968 init_all_targets();
969969
970 ZigTarget target;970 ZigTarget target;
971 if ((err = target_parse_triple(&target, target_string, mcpu))) {971 if ((err = target_parse_triple(&target, target_string, mcpu, dynamic_linker))) {
972 fprintf(stderr, "invalid target: %s\n"972 fprintf(stderr, "invalid target: %s\n"
973 "See `%s targets` to display valid targets.\n", err_str(err), arg0);973 "See `%s targets` to display valid targets.\n", err_str(err), arg0);
974 return print_error_usage(arg0);974 return print_error_usage(arg0);
...@@ -1193,7 +1193,6 @@ static int main0(int argc, char **argv) {...@@ -1193,7 +1193,6 @@ static int main0(int argc, char **argv) {
11931193
1194 codegen_set_strip(g, strip);1194 codegen_set_strip(g, strip);
1195 g->is_dynamic = is_dynamic;1195 g->is_dynamic = is_dynamic;
1196 g->dynamic_linker_path = dynamic_linker;
1197 g->verbose_tokenize = verbose_tokenize;1196 g->verbose_tokenize = verbose_tokenize;
1198 g->verbose_ast = verbose_ast;1197 g->verbose_ast = verbose_ast;
1199 g->verbose_link = verbose_link;1198 g->verbose_link = verbose_link;
...@@ -1320,7 +1319,7 @@ static int main0(int argc, char **argv) {...@@ -1320,7 +1319,7 @@ static int main0(int argc, char **argv) {
1320 return main_exit(root_progress_node, EXIT_SUCCESS);1319 return main_exit(root_progress_node, EXIT_SUCCESS);
1321 } else if (cmd == CmdTest) {1320 } else if (cmd == CmdTest) {
1322 ZigTarget native;1321 ZigTarget native;
1323 if ((err = target_parse_triple(&native, "native", nullptr))) {1322 if ((err = target_parse_triple(&native, "native", nullptr, nullptr))) {
1324 fprintf(stderr, "Unable to get native target: %s\n", err_str(err));1323 fprintf(stderr, "Unable to get native target: %s\n", err_str(err));
1325 return EXIT_FAILURE;1324 return EXIT_FAILURE;
1326 }1325 }
src/stage2.cpp+6-1
...@@ -191,7 +191,9 @@ static void get_native_target(ZigTarget *target) {...@@ -191,7 +191,9 @@ static void get_native_target(ZigTarget *target) {
191 }191 }
192}192}
193193
194Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu) {194Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
195 const char *dynamic_linker)
196{
195 Error err;197 Error err;
196198
197 if (zig_triple == nullptr) {199 if (zig_triple == nullptr) {
...@@ -249,6 +251,9 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons...@@ -249,6 +251,9 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons
249 target->cache_hash = "\n\n";251 target->cache_hash = "\n\n";
250 }252 }
251253
254 if (dynamic_linker != nullptr) {
255 target->dynamic_linker = dynamic_linker;
256 }
252 return ErrorNone;257 return ErrorNone;
253}258}
254259
src/stage2.h+2-1
...@@ -298,7 +298,8 @@ struct ZigTarget {...@@ -298,7 +298,8 @@ struct ZigTarget {
298};298};
299299
300// ABI warning300// ABI warning
301ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu);301ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
302 const char *dynamic_linker);
302303
303304
304// ABI warning305// ABI warning
src/target.cpp+2-2
...@@ -410,8 +410,8 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si...@@ -410,8 +410,8 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si
410 return ErrorUnknownABI;410 return ErrorUnknownABI;
411}411}
412412
413Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu) {413Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker) {
414 return stage2_target_parse(target, triple, mcpu);414 return stage2_target_parse(target, triple, mcpu, dynamic_linker);
415}415}
416416
417const char *target_arch_name(ZigLLVM_ArchType arch) {417const char *target_arch_name(ZigLLVM_ArchType arch) {
src/target.hpp+1-1
...@@ -41,7 +41,7 @@ enum CIntType {...@@ -41,7 +41,7 @@ enum CIntType {
41 CIntTypeCount,41 CIntTypeCount,
42};42};
4343
44Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu);44Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker);
45Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len);45Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len);
46Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);46Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
47Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);47Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);