From 4b02a39aa93b0043f05de0d90443051c019643ab Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 13:25:30 -0500 Subject: self-hosted libc detection * libc_installation.cpp is deleted. src-self-hosted/libc_installation.zig is now used for both stage1 and stage2 compilers. * (breaking) move `std.fs.File.access` to `std.fs.Dir.access`. The API now encourages use with an open directory handle. * Add `std.os.faccessat` and related functions. * Deprecate the "C" suffix naming convention for null-terminated parameters. "C" should be used when it is related to libc. However null-terminated parameters often have to do with the native system ABI rather than libc. "Z" suffix is the new convention. For example, `std.os.openC` is deprecated in favor of `std.os.openZ`. * Add `std.mem.dupeZ` for using an allocator to copy memory and add a null terminator. * Remove dead struct field `std.ChildProcess.llnode`. * Introduce `std.event.Batch`. This API allows expressing concurrency without forcing code to be async. It requires no Allocator and does not introduce any failure conditions. However it is not thread-safe. * There is now an ongoing experiment to transition away from `std.event.Group` in favor of `std.event.Batch`. * `std.os.execvpeC` calls `getenvZ` rather than `getenv`. This is slightly more efficient on most systems, and works around a limitation of `getenv` lack of integration with libc. * (breaking) `std.os.AccessError` gains `FileBusy`, `SymLinkLoop`, and `ReadOnlyFileSystem`. Previously these error codes were all reported as `PermissionDenied`. * Add `std.Target.isDragonFlyBSD`. * stage2: access to the windows_sdk functions is done with a manually maintained .zig binding file instead of `@cImport`. * Update src-self-hosted/libc_installation.zig with all the improvements that stage1 has seen to src/libc_installation.cpp until now. In addition, it now takes advantage of Batch so that evented I/O mode takes advantage of concurrency, but it still works in blocking I/O mode, which is how it is used in stage1. --- src/error.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/error.cpp') diff --git a/src/error.cpp b/src/error.cpp index 871b6b9e35..1e0267eb67 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -65,6 +65,20 @@ const char *err_str(Error err) { case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format"; case ErrorUnknownApplicationBinaryInterface: return "unknown application binary interface"; case ErrorASTUnitFailure: return "compiler bug: clang encountered a compile error, but the libclang API does not expose the error. See https://github.com/ziglang/zig/issues/4455 for more details"; + case ErrorBadPathName: return "bad path name"; + case ErrorSymLinkLoop: return "sym link loop"; + case ErrorProcessFdQuotaExceeded: return "process fd quota exceeded"; + case ErrorSystemFdQuotaExceeded: return "system fd quota exceeded"; + case ErrorNoDevice: return "no device"; + case ErrorDeviceBusy: return "device busy"; + case ErrorUnableToSpawnCCompiler: return "unable to spawn system C compiler"; + case ErrorCCompilerExitCode: return "system C compiler exited with failure code"; + case ErrorCCompilerCrashed: return "system C compiler crashed"; + case ErrorCCompilerCannotFindHeaders: return "system C compiler cannot find libc headers"; + case ErrorLibCRuntimeNotFound: return "libc runtime not found"; + case ErrorLibCStdLibHeaderNotFound: return "libc std lib headers not found"; + case ErrorLibCKernel32LibNotFound: return "kernel32 library not found"; + case ErrorUnsupportedArchitecture: return "unsupported architecture"; } return "(invalid error)"; } -- cgit v1.2.3 From 5c54d7bee7ca4d7d7948e2549fd67b61e2dcaf17 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 19:58:27 -0500 Subject: add missing implementations of libc installation to detect msvc paths --- lib/std/fs.zig | 1 - src-self-hosted/libc_installation.zig | 55 ++++++++++++++++++++++++++++++++--- src-self-hosted/stage2.zig | 2 ++ src/error.cpp | 1 + src/stage2.h | 1 + 5 files changed, 55 insertions(+), 5 deletions(-) (limited to 'src/error.cpp') diff --git a/lib/std/fs.zig b/lib/std/fs.zig index bc9ae6aa2d..a00ba6a63f 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -96,7 +96,6 @@ pub fn updateFile(source_path: []const u8, dest_path: []const u8) !PrevStatus { /// atime, and mode of the source file so that the next call to `updateFile` will not need a copy. /// Returns the previous status of the file before updating. /// If any of the directories do not exist for dest_path, they are created. -/// TODO https://github.com/ziglang/zig/issues/2885 pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?File.Mode) !PrevStatus { const my_cwd = cwd(); diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index d66f00c14e..85d6fc61ed 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -36,6 +36,7 @@ pub const LibCInstallation = struct { LibCStdLibHeaderNotFound, LibCKernel32LibNotFound, UnsupportedArchitecture, + WindowsSdkNotFound, }; pub fn parse( @@ -174,7 +175,7 @@ pub const LibCInstallation = struct { } /// Finds the default, native libc. - pub fn findNative(allocator: *Allocator) !LibCInstallation { + pub fn findNative(allocator: *Allocator) FindError!LibCInstallation { var self: LibCInstallation = .{}; if (is_windows) { @@ -199,8 +200,8 @@ pub const LibCInstallation = struct { try batch.wait(); }, .OutOfMemory => return error.OutOfMemory, - .NotFound => return error.NotFound, - .PathTooLong => return error.NotFound, + .NotFound => return error.WindowsSdkNotFound, + .PathTooLong => return error.WindowsSdkNotFound, } } } else { @@ -311,7 +312,11 @@ pub const LibCInstallation = struct { return error.LibCStdLibHeaderNotFound; } - fn findNativeIncludeDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) !void { + fn findNativeIncludeDirWindows( + self: *LibCInstallation, + allocator: *Allocator, + sdk: *ZigWindowsSDK, + ) FindError!void { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); @@ -432,6 +437,48 @@ pub const LibCInstallation = struct { } return error.LibCKernel32LibNotFound; } + + fn findNativeMsvcIncludeDir( + self: *LibCInstallation, + allocator: *Allocator, + sdk: *ZigWindowsSDK, + ) FindError!void { + const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCStdLibHeaderNotFound; + const msvc_lib_dir = msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]; + const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound; + const up2 = fs.path.dirname(up1) orelse return error.LibCStdLibHeaderNotFound; + + var result_buf = try std.Buffer.init(allocator, up2); + defer result_buf.deinit(); + + try result_buf.append("\\include"); + + var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { + error.FileNotFound, + error.NotDir, + error.NoDevice, + => return error.LibCStdLibHeaderNotFound, + + else => return error.FileSystem, + }; + defer dir.close(); + + dir.accessZ("vcruntime.h", .{}) catch |err| switch (err) { + error.FileNotFound => return error.LibCStdLibHeaderNotFound, + else => return error.FileSystem, + }; + + self.sys_include_dir = result_buf.toOwnedSlice(); + } + + fn findNativeMsvcLibDir( + self: *LibCInstallation, + allocator: *Allocator, + sdk: *ZigWindowsSDK, + ) FindError!void { + const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCRuntimeNotFound; + self.msvc_lib_dir = try std.mem.dupeZ(allocator, u8, msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]); + } }; const default_cc_exe = if (is_windows) "cc.exe" else "cc"; diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 95719d47a9..897f2a3ed8 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -108,6 +108,7 @@ const Error = extern enum { LibCStdLibHeaderNotFound, LibCKernel32LibNotFound, UnsupportedArchitecture, + WindowsSdkNotFound, }; const FILE = std.c.FILE; @@ -985,6 +986,7 @@ export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error { error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound, error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound, error.UnsupportedArchitecture => return .UnsupportedArchitecture, + error.WindowsSdkNotFound => return .WindowsSdkNotFound, }; stage1_libc.initFromStage2(libc); return .None; diff --git a/src/error.cpp b/src/error.cpp index 1e0267eb67..b7cc8e630a 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -79,6 +79,7 @@ const char *err_str(Error err) { case ErrorLibCStdLibHeaderNotFound: return "libc std lib headers not found"; case ErrorLibCKernel32LibNotFound: return "kernel32 library not found"; case ErrorUnsupportedArchitecture: return "unsupported architecture"; + case ErrorWindowsSdkNotFound: return "Windows SDK not found"; } return "(invalid error)"; } diff --git a/src/stage2.h b/src/stage2.h index f6bb17c884..856a5c3df8 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -99,6 +99,7 @@ enum Error { ErrorLibCStdLibHeaderNotFound, ErrorLibCKernel32LibNotFound, ErrorUnsupportedArchitecture, + ErrorWindowsSdkNotFound, }; // ABI warning -- cgit v1.2.3 From 2f9c5c0644dd516ec0d96f33333a35e6b4deea91 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 15:23:59 -0500 Subject: self-host dynamic linker detection --- lib/std/os.zig | 32 +++--- lib/std/process.zig | 56 ++++++++++ lib/std/target.zig | 137 +++++++++++++++++++++++ src-self-hosted/introspect.zig | 8 ++ src-self-hosted/libc_installation.zig | 39 ++++++- src-self-hosted/stage2.zig | 103 ++++++++++++++--- src-self-hosted/util.zig | 137 ----------------------- src/codegen.cpp | 52 ++------- src/compiler.cpp | 34 ------ src/compiler.hpp | 1 - src/error.cpp | 1 + src/os.cpp | 18 --- src/os.hpp | 4 - src/stage2.cpp | 6 +- src/stage2.h | 69 +++++++++++- src/target.cpp | 203 ---------------------------------- src/target.hpp | 62 +---------- 17 files changed, 430 insertions(+), 532 deletions(-) (limited to 'src/error.cpp') diff --git a/lib/std/os.zig b/lib/std/os.zig index c5fdc41d83..0f492a25f2 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2974,18 +2974,26 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void { } pub fn dl_iterate_phdr( - comptime T: type, - callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, - data: ?*T, -) isize { + context: var, + comptime Error: type, + comptime callback: fn (info: *dl_phdr_info, size: usize, context: @TypeOf(context)) Error!void, +) Error!void { + const Context = @TypeOf(context); + if (builtin.object_format != .elf) @compileError("dl_iterate_phdr is not available for this target"); if (builtin.link_libc) { - return system.dl_iterate_phdr( - @ptrCast(std.c.dl_iterate_phdr_callback, callback), - @ptrCast(?*c_void, data), - ); + switch (system.dl_iterate_phdr(struct { + fn callbackC(info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int { + const context_ptr = @ptrCast(*const Context, @alignCast(@alignOf(*const Context), data)); + callback(info, size, context_ptr.*) catch |err| return @errorToInt(err); + return 0; + } + }.callbackC, @intToPtr(?*c_void, @ptrToInt(&context)))) { + 0 => return, + else => |err| return @errSetCast(Error, @intToError(@intCast(u16, err))), // TODO don't hardcode u16 + } } const elf_base = std.process.getBaseAddress(); @@ -3007,11 +3015,10 @@ pub fn dl_iterate_phdr( .dlpi_phnum = ehdr.e_phnum, }; - return callback(&info, @sizeOf(dl_phdr_info), data); + return callback(&info, @sizeOf(dl_phdr_info), context); } // Last return value from the callback function - var last_r: isize = 0; while (it.next()) |entry| { var dlpi_phdr: [*]elf.Phdr = undefined; var dlpi_phnum: u16 = undefined; @@ -3033,11 +3040,8 @@ pub fn dl_iterate_phdr( .dlpi_phnum = dlpi_phnum, }; - last_r = callback(&info, @sizeOf(dl_phdr_info), data); - if (last_r != 0) break; + try callback(&info, @sizeOf(dl_phdr_info), context); } - - return last_r; } pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError; diff --git a/lib/std/process.zig b/lib/std/process.zig index 0178f6fa91..ddae0bffbb 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -613,3 +613,59 @@ pub fn getBaseAddress() usize { else => @compileError("Unsupported OS"), } } + +/// Caller owns the result value and each inner slice. +pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]u8 { + switch (builtin.link_mode) { + .Static => return &[_][:0]u8{}, + .Dynamic => {}, + } + const List = std.ArrayList([:0]u8); + switch (builtin.os) { + .linux, + .freebsd, + .netbsd, + .dragonfly, + => { + var paths = List.init(allocator); + errdefer { + const slice = paths.toOwnedSlice(); + for (slice) |item| { + allocator.free(item); + } + allocator.free(slice); + } + try os.dl_iterate_phdr(&paths, error{OutOfMemory}, struct { + fn callback(info: *os.dl_phdr_info, size: usize, list: *List) !void { + const name = info.dlpi_name orelse return; + if (name[0] == '/') { + const item = try mem.dupeZ(list.allocator, u8, mem.toSliceConst(u8, name)); + errdefer list.allocator.free(item); + try list.append(item); + } + } + }.callback); + return paths.toOwnedSlice(); + }, + .macosx, .ios, .watchos, .tvos => { + var paths = List.init(allocator); + errdefer { + const slice = paths.toOwnedSlice(); + for (slice) |item| { + allocator.free(item); + } + allocator.free(slice); + } + const img_count = std.c._dyld_image_count(); + var i: u32 = 0; + while (i < img_count) : (i += 1) { + const name = std.c._dyld_get_image_name(i); + const item = try mem.dupeZ(allocator, u8, mem.toSliceConst(u8, name)); + errdefer allocator.free(item); + try paths.append(item); + } + return paths.toOwnedSlice(); + }, + else => return error.UnimplementedSelfExeSharedPaths, + } +} diff --git a/lib/std/target.zig b/lib/std/target.zig index fb3fe96075..af8d6474ed 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1037,6 +1037,13 @@ pub const Target = union(enum) { }; } + pub fn isAndroid(self: Target) bool { + return switch (self.getAbi()) { + .android => true, + else => false, + }; + } + pub fn isDragonFlyBSD(self: Target) bool { return switch (self.getOs()) { .dragonfly => true, @@ -1196,6 +1203,136 @@ pub const Target = union(enum) { return .unavailable; } + + pub const FloatAbi = enum { + hard, + soft, + soft_fp, + }; + + pub fn getFloatAbi(self: Target) FloatAbi { + return switch (self.getAbi()) { + .gnueabihf, + .eabihf, + .musleabihf, + => .hard, + else => .soft, + }; + } + + /// Caller owns returned memory. + pub fn getStandardDynamicLinkerPath( + self: Target, + allocator: *mem.Allocator, + ) error{ + OutOfMemory, + UnknownDynamicLinkerPath, + }![:0]u8 { + const a = allocator; + if (self.isAndroid()) { + return mem.dupeZ(a, u8, if (self.getArchPtrBitWidth() == 64) + "/system/bin/linker64" + else + "/system/bin/linker"); + } + + if (self.isMusl()) { + var result = try std.Buffer.init(allocator, "/lib/ld-musl-"); + defer result.deinit(); + + var is_arm = false; + switch (self.getArch()) { + .arm, .thumb => { + try result.append("arm"); + is_arm = true; + }, + .armeb, .thumbeb => { + try result.append("armeb"); + is_arm = true; + }, + else => |arch| try result.append(@tagName(arch)), + } + if (is_arm and self.getFloatAbi() == .hard) { + try result.append("hf"); + } + try result.append(".so.1"); + return result.toOwnedSlice(); + } + + switch (self.getOs()) { + .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"), + .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"), + .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"), + .linux => switch (self.getArch()) { + .i386, + .sparc, + .sparcel, + => return mem.dupeZ(a, u8, "/lib/ld-linux.so.2"), + + .aarch64 => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64.so.1"), + .aarch64_be => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64_be.so.1"), + .aarch64_32 => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64_32.so.1"), + + .arm, + .armeb, + .thumb, + .thumbeb, + => return mem.dupeZ(a, u8, switch (self.getFloatAbi()) { + .hard => "/lib/ld-linux-armhf.so.3", + else => "/lib/ld-linux.so.3", + }), + + .mips, + .mipsel, + .mips64, + .mips64el, + => return error.UnknownDynamicLinkerPath, + + .powerpc => return mem.dupeZ(a, u8, "/lib/ld.so.1"), + .powerpc64, .powerpc64le => return mem.dupeZ(a, u8, "/lib64/ld64.so.2"), + .s390x => return mem.dupeZ(a, u8, "/lib64/ld64.so.1"), + .sparcv9 => return mem.dupeZ(a, u8, "/lib64/ld-linux.so.2"), + .x86_64 => return mem.dupeZ(a, u8, switch (self.getAbi()) { + .gnux32 => "/libx32/ld-linux-x32.so.2", + else => "/lib64/ld-linux-x86-64.so.2", + }), + + .riscv32 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv32-ilp32.so.1"), + .riscv64 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv64-lp64.so.1"), + + .arc, + .avr, + .bpfel, + .bpfeb, + .hexagon, + .msp430, + .r600, + .amdgcn, + .tce, + .tcele, + .xcore, + .nvptx, + .nvptx64, + .le32, + .le64, + .amdil, + .amdil64, + .hsail, + .hsail64, + .spir, + .spir64, + .kalimba, + .shave, + .lanai, + .wasm32, + .wasm64, + .renderscript32, + .renderscript64, + => return error.UnknownDynamicLinkerPath, + }, + else => return error.UnknownDynamicLinkerPath, + } + } }; test "parseCpuFeatureSet" { diff --git a/src-self-hosted/introspect.zig b/src-self-hosted/introspect.zig index 3cf18ab363..11838e7e63 100644 --- a/src-self-hosted/introspect.zig +++ b/src-self-hosted/introspect.zig @@ -6,6 +6,14 @@ const fs = std.fs; const warn = std.debug.warn; +pub fn detectDynamicLinker(allocator: *mem.Allocator, target: std.Target) ![:0]u8 { + if (target == .Native) { + return @import("libc_installation.zig").detectNativeDynamicLinker(allocator); + } else { + return target.getStandardDynamicLinkerPath(allocator); + } +} + /// Caller must free result pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 { const test_zig_dir = try fs.path.join(allocator, &[_][]const u8{ test_path, "lib", "zig" }); diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index f97850bb68..1fec40c516 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -492,7 +492,7 @@ pub const LibCInstallation = struct { const default_cc_exe = if (is_windows) "cc.exe" else "cc"; /// caller owns returned memory -pub fn ccPrintFileName( +fn ccPrintFileName( allocator: *Allocator, o_file: []const u8, want_dirname: enum { full_path, only_dir }, @@ -535,6 +535,43 @@ pub fn ccPrintFileName( } } +/// Caller owns returned memory. +pub fn detectNativeDynamicLinker(allocator: *Allocator) ![:0]u8 { + const standard_ld_path = try std.Target.current.getStandardDynamicLinkerPath(allocator); + var standard_ld_path_resource: ?[:0]u8 = standard_ld_path; // Set to null to avoid freeing it. + defer if (standard_ld_path_resource) |s| allocator.free(s); + + const standard_ld_basename = fs.path.basename(standard_ld_path); + + { + // Best case scenario: the current executable is dynamically linked, and we can iterate + // over our own shared objects and find a dynamic linker. + const lib_paths = try std.process.getSelfExeSharedLibPaths(allocator); + defer allocator.free(lib_paths); + + for (lib_paths) |lib_path| { + if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) { + return std.mem.dupeZ(allocator, u8, lib_path); + } + } + } + + // If Zig is statically linked, such as via distributed binary static builds, the above + // trick won't work. What are we left with? Try to run the system C compiler and get + // it to tell us the dynamic linker path. + return ccPrintFileName(allocator, standard_ld_basename, .full_path) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.LibCRuntimeNotFound, + error.CCompilerExitCode, + error.CCompilerCrashed, + error.UnableToSpawnCCompiler, + => { + standard_ld_path_resource = null; // Prevent freeing standard_ld_path. + return standard_ld_path; + }, + }; +} + const Search = struct { path: []const u8, version: []const u8, diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 897f2a3ed8..02269a8c4f 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -109,6 +109,7 @@ const Error = extern enum { LibCKernel32LibNotFound, UnsupportedArchitecture, WindowsSdkNotFound, + UnknownDynamicLinkerPath, }; const FILE = std.c.FILE; @@ -1012,24 +1013,100 @@ export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: } // ABI warning -export fn stage2_libc_cc_print_file_name( - out_ptr: *[*:0]u8, - out_len: *usize, - o_file: [*:0]const u8, - want_dirname: bool, -) Error { - const result = @import("libc_installation.zig").ccPrintFileName( +const Stage2Target = extern struct { + arch: c_int, + sub_arch: c_int, + vendor: c_int, + os: c_int, + abi: c_int, + glibc_version: ?*Stage2GLibCVersion, // null means default + cpu_features: *Stage2CpuFeatures, + is_native: bool, +}; + +// ABI warning +const Stage2GLibCVersion = extern struct { + major: u32, + minor: u32, + patch: u32, +}; + +// ABI warning +export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: *[*:0]u8, out_len: *usize) Error { + const target: Target = if (in_target.is_native) .Native else .{ + .Cross = .{ + .arch = switch (enumInt(@TagType(Target.Arch), in_target.arch)) { + .arm => .{ .arm = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + .armeb => .{ .armeb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + .thumb => .{ .thumb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + .thumbeb => .{ .thumbeb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + + .aarch64 => .{ .aarch64 = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, + .aarch64_be => .{ .aarch64_be = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, + .aarch64_32 => .{ .aarch64_32 = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, + + .kalimba => .{ .kalimba = enumInt(Target.Arch.Kalimba, in_target.sub_arch) }, + + .arc => .arc, + .avr => .avr, + .bpfel => .bpfel, + .bpfeb => .bpfeb, + .hexagon => .hexagon, + .mips => .mips, + .mipsel => .mipsel, + .mips64 => .mips64, + .mips64el => .mips64el, + .msp430 => .msp430, + .powerpc => .powerpc, + .powerpc64 => .powerpc64, + .powerpc64le => .powerpc64le, + .r600 => .r600, + .amdgcn => .amdgcn, + .riscv32 => .riscv32, + .riscv64 => .riscv64, + .sparc => .sparc, + .sparcv9 => .sparcv9, + .sparcel => .sparcel, + .s390x => .s390x, + .tce => .tce, + .tcele => .tcele, + .i386 => .i386, + .x86_64 => .x86_64, + .xcore => .xcore, + .nvptx => .nvptx, + .nvptx64 => .nvptx64, + .le32 => .le32, + .le64 => .le64, + .amdil => .amdil, + .amdil64 => .amdil64, + .hsail => .hsail, + .hsail64 => .hsail64, + .spir => .spir, + .spir64 => .spir64, + .shave => .shave, + .lanai => .lanai, + .wasm32 => .wasm32, + .wasm64 => .wasm64, + .renderscript32 => .renderscript32, + .renderscript64 => .renderscript64, + }, + .os = enumInt(Target.Os, in_target.os), + .abi = enumInt(Target.Abi, in_target.abi), + .cpu_features = in_target.cpu_features.cpu_features, + }, + }; + const result = @import("introspect.zig").detectDynamicLinker( std.heap.c_allocator, - mem.toSliceConst(u8, o_file), - if (want_dirname) .only_dir else .full_path, + target, ) catch |err| switch (err) { error.OutOfMemory => return .OutOfMemory, - error.LibCRuntimeNotFound => return .FileNotFound, - error.CCompilerExitCode => return .CCompilerExitCode, - error.CCompilerCrashed => return .CCompilerCrashed, - error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, + error.UnknownDynamicLinkerPath => return .UnknownDynamicLinkerPath, }; out_ptr.* = result.ptr; out_len.* = result.len; return .None; } + +fn enumInt(comptime Enum: type, int: c_int) Enum { + return @intToEnum(Enum, @intCast(@TagType(Enum), int)); +} diff --git a/src-self-hosted/util.zig b/src-self-hosted/util.zig index 95bc72469d..04c5420d26 100644 --- a/src-self-hosted/util.zig +++ b/src-self-hosted/util.zig @@ -2,143 +2,6 @@ const std = @import("std"); const Target = std.Target; const llvm = @import("llvm.zig"); -pub const FloatAbi = enum { - Hard, - Soft, - SoftFp, -}; - -/// TODO expose the arch and subarch separately -pub fn isArmOrThumb(self: Target) bool { - return switch (self.getArch()) { - .arm, - .armeb, - .aarch64, - .aarch64_be, - .thumb, - .thumbeb, - => true, - else => false, - }; -} - -pub fn getFloatAbi(self: Target) FloatAbi { - return switch (self.getAbi()) { - .gnueabihf, - .eabihf, - .musleabihf, - => .Hard, - else => .Soft, - }; -} - -pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { - const env = self.getAbi(); - const arch = self.getArch(); - const os = self.getOs(); - switch (os) { - .freebsd => { - return "/libexec/ld-elf.so.1"; - }, - .linux => { - switch (env) { - .android => { - if (self.getArchPtrBitWidth() == 64) { - return "/system/bin/linker64"; - } else { - return "/system/bin/linker"; - } - }, - .gnux32 => { - if (arch == .x86_64) { - return "/libx32/ld-linux-x32.so.2"; - } - }, - .musl, - .musleabi, - .musleabihf, - => { - if (arch == .x86_64) { - return "/lib/ld-musl-x86_64.so.1"; - } - }, - else => {}, - } - switch (arch) { - .i386, - .sparc, - .sparcel, - => return "/lib/ld-linux.so.2", - - .aarch64 => return "/lib/ld-linux-aarch64.so.1", - - .aarch64_be => return "/lib/ld-linux-aarch64_be.so.1", - - .arm, - .thumb, - => return switch (getFloatAbi(self)) { - .Hard => return "/lib/ld-linux-armhf.so.3", - else => return "/lib/ld-linux.so.3", - }, - - .armeb, - .thumbeb, - => return switch (getFloatAbi(self)) { - .Hard => return "/lib/ld-linux-armhf.so.3", - else => return "/lib/ld-linux.so.3", - }, - - .mips, - .mipsel, - .mips64, - .mips64el, - => return null, - - .powerpc => return "/lib/ld.so.1", - .powerpc64 => return "/lib64/ld64.so.2", - .powerpc64le => return "/lib64/ld64.so.2", - .s390x => return "/lib64/ld64.so.1", - .sparcv9 => return "/lib64/ld-linux.so.2", - .x86_64 => return "/lib64/ld-linux-x86-64.so.2", - - .arc, - .avr, - .bpfel, - .bpfeb, - .hexagon, - .msp430, - .r600, - .amdgcn, - .riscv32, - .riscv64, - .tce, - .tcele, - .xcore, - .nvptx, - .nvptx64, - .le32, - .le64, - .amdil, - .amdil64, - .hsail, - .hsail64, - .spir, - .spir64, - .kalimba, - .shave, - .lanai, - .wasm32, - .wasm64, - .renderscript32, - .renderscript64, - .aarch64_32, - => return null, - } - }, - else => return null, - } -} - pub fn getDarwinArchString(self: Target) [:0]const u8 { const arch = self.getArch(); switch (arch) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 0b5d2e82f1..f0640c871c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8624,7 +8624,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { break; } buf_appendf(contents, "pub const output_mode = OutputMode.%s;\n", out_type); - const char *link_type = g->is_dynamic ? "Dynamic" : "Static"; + const char *link_type = g->have_dynamic_link ? "Dynamic" : "Static"; buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", link_type); buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); @@ -8731,7 +8731,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { cache_int(&cache_hash, g->build_mode); cache_bool(&cache_hash, g->strip_debug_symbols); cache_int(&cache_hash, g->out_type); - cache_bool(&cache_hash, g->is_dynamic); + cache_bool(&cache_hash, detect_dynamic_link(g)); cache_bool(&cache_hash, g->is_test_build); cache_bool(&cache_hash, g->is_single_threaded); cache_bool(&cache_hash, g->test_is_evented); @@ -8957,6 +8957,8 @@ static void init(CodeGen *g) { } static void detect_dynamic_linker(CodeGen *g) { + Error err; + if (g->dynamic_linker_path != nullptr) return; if (!g->have_dynamic_link) @@ -8964,45 +8966,15 @@ static void detect_dynamic_linker(CodeGen *g) { if (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic)) return; - const char *standard_ld_path = target_dynamic_linker(g->zig_target); - if (standard_ld_path == nullptr) - return; - - if (g->zig_target->is_native) { - // target_dynamic_linker is usually correct. However on some systems, such as NixOS - // it will be incorrect. See if we can do better by looking at what zig's own - // dynamic linker path is. - g->dynamic_linker_path = get_self_dynamic_linker_path(); - if (g->dynamic_linker_path != nullptr) - return; - - // If Zig is statically linked, such as via distributed binary static builds, the above - // trick won't work. What are we left with? Try to run the system C compiler and get - // it to tell us the dynamic linker path -#if defined(ZIG_OS_LINUX) - { - Error err; - for (size_t i = 0; possible_ld_names[i] != NULL; i += 1) { - const char *lib_name = possible_ld_names[i]; - char *result_ptr; - size_t result_len; - if ((err = stage2_libc_cc_print_file_name(&result_ptr, &result_len, lib_name, false))) { - if (err != ErrorCCompilerCannotFindFile && err != ErrorNoCCompilerInstalled) { - fprintf(stderr, "Unable to detect native dynamic linker: %s\n", err_str(err)); - exit(1); - } - continue; - } - g->dynamic_linker_path = buf_create_from_mem(result_ptr, result_len); - // Skips heap::c_allocator because the memory is allocated by stage2 library. - free(result_ptr); - return; - } - } -#endif + char *dynamic_linker_ptr; + size_t dynamic_linker_len; + if ((err = stage2_detect_dynamic_linker(g->zig_target, &dynamic_linker_ptr, &dynamic_linker_len))) { + fprintf(stderr, "Unable to detect dynamic linker: %s\n", err_str(err)); + exit(1); } - - g->dynamic_linker_path = buf_create_from_str(standard_ld_path); + g->dynamic_linker_path = buf_create_from_mem(dynamic_linker_ptr, dynamic_linker_len); + // Skips heap::c_allocator because the memory is allocated by stage2 library. + free(dynamic_linker_ptr); } static void detect_libc(CodeGen *g) { diff --git a/src/compiler.cpp b/src/compiler.cpp index 484a4ca089..31bac4ee24 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -4,20 +4,6 @@ #include -static Buf saved_dynamic_linker_path = BUF_INIT; -static bool searched_for_dyn_linker = false; - -static void detect_dynamic_linker(Buf *lib_path) { -#if defined(ZIG_OS_LINUX) - for (size_t i = 0; possible_ld_names[i] != NULL; i += 1) { - if (buf_ends_with_str(lib_path, possible_ld_names[i])) { - buf_init_from_buf(&saved_dynamic_linker_path, lib_path); - break; - } - } -#endif -} - Buf *get_self_libc_path(void) { static Buf saved_libc_path = BUF_INIT; static bool searched_for_libc = false; @@ -43,25 +29,6 @@ Buf *get_self_libc_path(void) { } } -Buf *get_self_dynamic_linker_path(void) { - for (;;) { - if (saved_dynamic_linker_path.list.length != 0) { - return &saved_dynamic_linker_path; - } - if (searched_for_dyn_linker) - return nullptr; - ZigList lib_paths = {}; - Error err; - if ((err = os_self_exe_shared_libs(lib_paths))) - return nullptr; - for (size_t i = 0; i < lib_paths.length; i += 1) { - Buf *lib_path = lib_paths.at(i); - detect_dynamic_linker(lib_path); - } - searched_for_dyn_linker = true; - } -} - Error get_compiler_id(Buf **result) { static Buf saved_compiler_id = BUF_INIT; @@ -98,7 +65,6 @@ Error get_compiler_id(Buf **result) { return err; for (size_t i = 0; i < lib_paths.length; i += 1) { Buf *lib_path = lib_paths.at(i); - detect_dynamic_linker(lib_path); if ((err = cache_add_file(ch, lib_path))) return err; } diff --git a/src/compiler.hpp b/src/compiler.hpp index ee9c4ab4fc..4a1699b782 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -12,7 +12,6 @@ #include "error.hpp" Error get_compiler_id(Buf **result); -Buf *get_self_dynamic_linker_path(void); Buf *get_self_libc_path(void); Buf *get_zig_lib_dir(void); diff --git a/src/error.cpp b/src/error.cpp index b7cc8e630a..af1359f9ee 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -80,6 +80,7 @@ const char *err_str(Error err) { case ErrorLibCKernel32LibNotFound: return "kernel32 library not found"; case ErrorUnsupportedArchitecture: return "unsupported architecture"; case ErrorWindowsSdkNotFound: return "Windows SDK not found"; + case ErrorUnknownDynamicLinkerPath: return "Windows SDK not found"; } return "(invalid error)"; } diff --git a/src/os.cpp b/src/os.cpp index 5e2c986e43..268e812050 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -2129,21 +2129,3 @@ void os_file_close(OsFile *file) { *file = -1; #endif } - -#ifdef ZIG_OS_LINUX -const char *possible_ld_names[] = { -#if defined(ZIG_ARCH_X86_64) - "ld-linux-x86-64.so.2", - "ld-musl-x86_64.so.1", -#elif defined(ZIG_ARCH_ARM64) - "ld-linux-aarch64.so.1", - "ld-musl-aarch64.so.1", -#elif defined(ZIG_ARCH_ARM) - "ld-linux-armhf.so.3", - "ld-musl-armhf.so.1", - "ld-linux.so.3", - "ld-musl-arm.so.1", -#endif - NULL, -}; -#endif diff --git a/src/os.hpp b/src/os.hpp index c26d6c8df5..116861e8b5 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -43,10 +43,6 @@ #define ZIG_ARCH_UNKNOWN #endif -#ifdef ZIG_OS_LINUX -extern const char *possible_ld_names[]; -#endif - #if defined(ZIG_OS_WINDOWS) #define ZIG_PRI_usize "I64u" #define ZIG_PRI_i64 "I64d" diff --git a/src/stage2.cpp b/src/stage2.cpp index db4f529c68..7f68321752 100644 --- a/src/stage2.cpp +++ b/src/stage2.cpp @@ -171,9 +171,7 @@ enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) { stage2_panic(msg, strlen(msg)); } -enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, - const char *o_file, bool want_dirname) -{ - const char *msg = "stage0 called stage2_libc_cc_print_file_name"; +enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **out_ptr, size_t *out_len) { + const char *msg = "stage0 called stage2_detect_dynamic_linker"; stage2_panic(msg, strlen(msg)); } diff --git a/src/stage2.h b/src/stage2.h index 856a5c3df8..15a66379a7 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -12,6 +12,8 @@ #include #include +#include "zig_llvm.h" + #ifdef __cplusplus #define ZIG_EXTERN_C extern "C" #else @@ -100,6 +102,7 @@ enum Error { ErrorLibCKernel32LibNotFound, ErrorUnsupportedArchitecture, ErrorWindowsSdkNotFound, + ErrorUnknownDynamicLinkerPath, }; // ABI warning @@ -242,8 +245,70 @@ ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, c ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file); // ABI warning ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc); + +// ABI warning +// Synchronize with target.cpp::os_list +enum Os { + OsFreestanding, + OsAnanas, + OsCloudABI, + OsDragonFly, + OsFreeBSD, + OsFuchsia, + OsIOS, + OsKFreeBSD, + OsLinux, + OsLv2, // PS3 + OsMacOSX, + OsNetBSD, + OsOpenBSD, + OsSolaris, + OsWindows, + OsHaiku, + OsMinix, + OsRTEMS, + OsNaCl, // Native Client + OsCNK, // BG/P Compute-Node Kernel + OsAIX, + OsCUDA, // NVIDIA CUDA + OsNVCL, // NVIDIA OpenCL + OsAMDHSA, // AMD HSA Runtime + OsPS4, + OsELFIAMCU, + OsTvOS, // Apple tvOS + OsWatchOS, // Apple watchOS + OsMesa3D, + OsContiki, + OsAMDPAL, + OsHermitCore, + OsHurd, + OsWASI, + OsEmscripten, + OsUefi, + OsOther, +}; + +// ABI warning +struct ZigGLibCVersion { + uint32_t major; // always 2 + uint32_t minor; + uint32_t patch; +}; + +// ABI warning +struct ZigTarget { + enum ZigLLVM_ArchType arch; + enum ZigLLVM_SubArchType sub_arch; + enum ZigLLVM_VendorType vendor; + Os os; + enum ZigLLVM_EnvironmentType abi; + struct ZigGLibCVersion *glibc_version; // null means default + struct Stage2CpuFeatures *cpu_features; + bool is_native; +}; + // ABI warning -ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, - const char *o_file, bool want_dirname); +ZIG_EXTERN_C enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, + char **out_ptr, size_t *out_len); #endif diff --git a/src/target.cpp b/src/target.cpp index b8979d0214..209b42f3c9 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1204,213 +1204,10 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static, } } -enum FloatAbi { - FloatAbiHard, - FloatAbiSoft, - FloatAbiSoftFp, -}; - -static FloatAbi get_float_abi(const ZigTarget *target) { - const ZigLLVM_EnvironmentType env = target->abi; - if (env == ZigLLVM_GNUEABIHF || - env == ZigLLVM_EABIHF || - env == ZigLLVM_MuslEABIHF) - { - return FloatAbiHard; - } else { - return FloatAbiSoft; - } -} - -static bool is_64_bit(ZigLLVM_ArchType arch) { - return target_arch_pointer_bit_width(arch) == 64; -} - bool target_is_android(const ZigTarget *target) { return target->abi == ZigLLVM_Android; } -const char *target_dynamic_linker(const ZigTarget *target) { - if (target_is_android(target)) { - return is_64_bit(target->arch) ? "/system/bin/linker64" : "/system/bin/linker"; - } - - if (target_is_musl(target)) { - Buf buf = BUF_INIT; - buf_init_from_str(&buf, "/lib/ld-musl-"); - bool is_arm = false; - switch (target->arch) { - case ZigLLVM_arm: - case ZigLLVM_thumb: - buf_append_str(&buf, "arm"); - is_arm = true; - break; - case ZigLLVM_armeb: - case ZigLLVM_thumbeb: - buf_append_str(&buf, "armeb"); - is_arm = true; - break; - default: - buf_append_str(&buf, target_arch_name(target->arch)); - } - if (is_arm && get_float_abi(target) == FloatAbiHard) { - buf_append_str(&buf, "hf"); - } - buf_append_str(&buf, ".so.1"); - return buf_ptr(&buf); - } - - switch (target->os) { - case OsFreeBSD: - return "/libexec/ld-elf.so.1"; - case OsNetBSD: - return "/libexec/ld.elf_so"; - case OsDragonFly: - return "/libexec/ld-elf.so.2"; - case OsLinux: { - const ZigLLVM_EnvironmentType abi = target->abi; - switch (target->arch) { - case ZigLLVM_UnknownArch: - zig_unreachable(); - case ZigLLVM_x86: - case ZigLLVM_sparc: - case ZigLLVM_sparcel: - return "/lib/ld-linux.so.2"; - - case ZigLLVM_aarch64: - return "/lib/ld-linux-aarch64.so.1"; - - case ZigLLVM_aarch64_be: - return "/lib/ld-linux-aarch64_be.so.1"; - - case ZigLLVM_aarch64_32: - return "/lib/ld-linux-aarch64_32.so.1"; - - case ZigLLVM_arm: - case ZigLLVM_thumb: - if (get_float_abi(target) == FloatAbiHard) { - return "/lib/ld-linux-armhf.so.3"; - } else { - return "/lib/ld-linux.so.3"; - } - - case ZigLLVM_armeb: - case ZigLLVM_thumbeb: - if (get_float_abi(target) == FloatAbiHard) { - return "/lib/ld-linux-armhf.so.3"; - } else { - return "/lib/ld-linux.so.3"; - } - - case ZigLLVM_mips: - case ZigLLVM_mipsel: - case ZigLLVM_mips64: - case ZigLLVM_mips64el: - zig_panic("TODO implement target_dynamic_linker for mips"); - - case ZigLLVM_ppc: - return "/lib/ld.so.1"; - - case ZigLLVM_ppc64: - return "/lib64/ld64.so.2"; - - case ZigLLVM_ppc64le: - return "/lib64/ld64.so.2"; - - case ZigLLVM_systemz: - return "/lib64/ld64.so.1"; - - case ZigLLVM_sparcv9: - return "/lib64/ld-linux.so.2"; - - case ZigLLVM_x86_64: - if (abi == ZigLLVM_GNUX32) { - return "/libx32/ld-linux-x32.so.2"; - } - if (abi == ZigLLVM_Musl || abi == ZigLLVM_MuslEABI || abi == ZigLLVM_MuslEABIHF) { - return "/lib/ld-musl-x86_64.so.1"; - } - return "/lib64/ld-linux-x86-64.so.2"; - - case ZigLLVM_wasm32: - case ZigLLVM_wasm64: - return nullptr; - - case ZigLLVM_riscv32: - return "/lib/ld-linux-riscv32-ilp32.so.1"; - case ZigLLVM_riscv64: - return "/lib/ld-linux-riscv64-lp64.so.1"; - - case ZigLLVM_arc: - case ZigLLVM_avr: - case ZigLLVM_bpfel: - case ZigLLVM_bpfeb: - case ZigLLVM_hexagon: - case ZigLLVM_msp430: - case ZigLLVM_r600: - case ZigLLVM_amdgcn: - case ZigLLVM_tce: - case ZigLLVM_tcele: - case ZigLLVM_xcore: - case ZigLLVM_nvptx: - case ZigLLVM_nvptx64: - case ZigLLVM_le32: - case ZigLLVM_le64: - case ZigLLVM_amdil: - case ZigLLVM_amdil64: - case ZigLLVM_hsail: - case ZigLLVM_hsail64: - case ZigLLVM_spir: - case ZigLLVM_spir64: - case ZigLLVM_kalimba: - case ZigLLVM_shave: - case ZigLLVM_lanai: - case ZigLLVM_renderscript32: - case ZigLLVM_renderscript64: - zig_panic("TODO implement target_dynamic_linker for this arch"); - } - zig_unreachable(); - } - case OsFreestanding: - case OsIOS: - case OsTvOS: - case OsWatchOS: - case OsMacOSX: - case OsUefi: - case OsWindows: - case OsEmscripten: - case OsOther: - return nullptr; - - case OsAnanas: - case OsCloudABI: - case OsFuchsia: - case OsKFreeBSD: - case OsLv2: - case OsOpenBSD: - case OsSolaris: - case OsHaiku: - case OsMinix: - case OsRTEMS: - case OsNaCl: - case OsCNK: - case OsAIX: - case OsCUDA: - case OsNVCL: - case OsAMDHSA: - case OsPS4: - case OsELFIAMCU: - case OsMesa3D: - case OsContiki: - case OsAMDPAL: - case OsHermitCore: - case OsHurd: - case OsWASI: - zig_panic("TODO implement target_dynamic_linker for this OS"); - } - zig_unreachable(); -} - bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target) { assert(host_target != nullptr); diff --git a/src/target.hpp b/src/target.hpp index 3e984e1269..4344749719 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -8,51 +8,10 @@ #ifndef ZIG_TARGET_HPP #define ZIG_TARGET_HPP -#include +#include "stage2.h" struct Buf; -// Synchronize with target.cpp::os_list -enum Os { - OsFreestanding, - OsAnanas, - OsCloudABI, - OsDragonFly, - OsFreeBSD, - OsFuchsia, - OsIOS, - OsKFreeBSD, - OsLinux, - OsLv2, // PS3 - OsMacOSX, - OsNetBSD, - OsOpenBSD, - OsSolaris, - OsWindows, - OsHaiku, - OsMinix, - OsRTEMS, - OsNaCl, // Native Client - OsCNK, // BG/P Compute-Node Kernel - OsAIX, - OsCUDA, // NVIDIA CUDA - OsNVCL, // NVIDIA OpenCL - OsAMDHSA, // AMD HSA Runtime - OsPS4, - OsELFIAMCU, - OsTvOS, // Apple tvOS - OsWatchOS, // Apple watchOS - OsMesa3D, - OsContiki, - OsAMDPAL, - OsHermitCore, - OsHurd, - OsWASI, - OsEmscripten, - OsUefi, - OsOther, -}; - // Synchronize with target.cpp::subarch_list_list enum SubArchList { SubArchListNone, @@ -78,23 +37,6 @@ enum TargetSubsystem { TargetSubsystemAuto }; -struct ZigGLibCVersion { - uint32_t major; // always 2 - uint32_t minor; - uint32_t patch; -}; - -struct ZigTarget { - ZigLLVM_ArchType arch; - ZigLLVM_SubArchType sub_arch; - ZigLLVM_VendorType vendor; - Os os; - ZigLLVM_EnvironmentType abi; - ZigGLibCVersion *glibc_version; // null means default - Stage2CpuFeatures *cpu_features; - bool is_native; -}; - enum CIntType { CIntTypeShort, CIntTypeUShort, @@ -168,8 +110,6 @@ const char *target_lib_file_prefix(const ZigTarget *target); const char *target_lib_file_ext(const ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch); -const char *target_dynamic_linker(const ZigTarget *target); - bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); ZigLLVM_OSType get_llvm_os_type(Os os_type); -- cgit v1.2.3 From e26f063b22893f50dd7eb02a01585f4d52849ede Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 15:46:53 -0500 Subject: support the concept of a target not having a dynamic linker --- lib/std/target.zig | 19 +++++++++++++++++-- src-self-hosted/stage2.zig | 2 ++ src/codegen.cpp | 1 + src/error.cpp | 3 ++- src/stage2.h | 1 + 5 files changed, 23 insertions(+), 3 deletions(-) (limited to 'src/error.cpp') diff --git a/lib/std/target.zig b/lib/std/target.zig index af8d6474ed..d3f487e9ff 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1227,6 +1227,7 @@ pub const Target = union(enum) { ) error{ OutOfMemory, UnknownDynamicLinkerPath, + TargetHasNoDynamicLinker, }![:0]u8 { const a = allocator; if (self.isAndroid()) { @@ -1300,6 +1301,10 @@ pub const Target = union(enum) { .riscv32 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv32-ilp32.so.1"), .riscv64 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv64-lp64.so.1"), + .wasm32, + .wasm64, + => return error.TargetHasNoDynamicLinker, + .arc, .avr, .bpfel, @@ -1324,12 +1329,22 @@ pub const Target = union(enum) { .kalimba, .shave, .lanai, - .wasm32, - .wasm64, .renderscript32, .renderscript64, => return error.UnknownDynamicLinkerPath, }, + + .freestanding, + .ios, + .tvos, + .watchos, + .macosx, + .uefi, + .windows, + .emscripten, + .other, + => return error.TargetHasNoDynamicLinker, + else => return error.UnknownDynamicLinkerPath, } } diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 02269a8c4f..5b918f9514 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -110,6 +110,7 @@ const Error = extern enum { UnsupportedArchitecture, WindowsSdkNotFound, UnknownDynamicLinkerPath, + TargetHasNoDynamicLinker, }; const FILE = std.c.FILE; @@ -1101,6 +1102,7 @@ export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: ) catch |err| switch (err) { error.OutOfMemory => return .OutOfMemory, error.UnknownDynamicLinkerPath => return .UnknownDynamicLinkerPath, + error.TargetHasNoDynamicLinker => return .TargetHasNoDynamicLinker, }; out_ptr.* = result.ptr; out_len.* = result.len; diff --git a/src/codegen.cpp b/src/codegen.cpp index f0640c871c..225e39989c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8969,6 +8969,7 @@ static void detect_dynamic_linker(CodeGen *g) { char *dynamic_linker_ptr; size_t dynamic_linker_len; if ((err = stage2_detect_dynamic_linker(g->zig_target, &dynamic_linker_ptr, &dynamic_linker_len))) { + if (err == ErrorTargetHasNoDynamicLinker) return; fprintf(stderr, "Unable to detect dynamic linker: %s\n", err_str(err)); exit(1); } diff --git a/src/error.cpp b/src/error.cpp index af1359f9ee..c633e2fe67 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -80,7 +80,8 @@ const char *err_str(Error err) { case ErrorLibCKernel32LibNotFound: return "kernel32 library not found"; case ErrorUnsupportedArchitecture: return "unsupported architecture"; case ErrorWindowsSdkNotFound: return "Windows SDK not found"; - case ErrorUnknownDynamicLinkerPath: return "Windows SDK not found"; + case ErrorUnknownDynamicLinkerPath: return "unknown dynamic linker path"; + case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker"; } return "(invalid error)"; } diff --git a/src/stage2.h b/src/stage2.h index 15a66379a7..b6e4cebbaf 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -103,6 +103,7 @@ enum Error { ErrorUnsupportedArchitecture, ErrorWindowsSdkNotFound, ErrorUnknownDynamicLinkerPath, + ErrorTargetHasNoDynamicLinker, }; // ABI warning -- cgit v1.2.3