From a08cc7d2ae3bd6e90f8d26ac13f2e0652687dc30 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 15 Jun 2023 17:10:42 -0700 Subject: compiler: resolve library paths in the frontend search_strategy is no longer passed to Compilation at all; instead it is used in the CLI code only. When using Zig CLI mode, `-l` no longer has the ability to link statically; use positional arguments for this. The CLI has a small abstraction around library resolution handling which is used to remove some code duplication regarding static libraries, as well as handle the difference between zig cc CLI mode and zig CLI mode. Thanks to this, system libraries are now included in the cache hash, and thus changes to them will correctly cause cache misses. In the future, lib_dirs should no longer be passed to Compilation at all, because it is a frontend-only concept. Previously, -search_paths_first and -search_dylibs_first were Darwin-only arguments; they now work the same for all targets. Same thing with --sysroot. Improved the error reporting for failure to find a system library. An example error now looks like this: ``` $ zig build-exe test.zig -lfoo -L. -L/a -target x86_64-macos --sysroot /home/andy/local error: unable to find Dynamic system library 'foo' using strategy 'no_fallback'. search paths: ./libfoo.tbd ./libfoo.dylib ./libfoo.so /home/andy/local/a/libfoo.tbd /home/andy/local/a/libfoo.dylib /home/andy/local/a/libfoo.so /a/libfoo.tbd /a/libfoo.dylib /a/libfoo.so ``` closes #14963 --- src/Compilation.zig | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 2e269a7e80..f966f1e17f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -448,6 +448,7 @@ pub const ClangPreprocessorMode = enum { stdout, }; +pub const Framework = link.Framework; pub const SystemLib = link.SystemLib; pub const CacheMode = link.CacheMode; @@ -505,7 +506,7 @@ pub const InitOptions = struct { c_source_files: []const CSourceFile = &[0]CSourceFile{}, link_objects: []LinkObject = &[0]LinkObject{}, framework_dirs: []const []const u8 = &[0][]const u8{}, - frameworks: std.StringArrayHashMapUnmanaged(SystemLib) = .{}, + frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{}, system_lib_names: []const []const u8 = &.{}, system_lib_infos: []const SystemLib = &.{}, /// These correspond to the WASI libc emulated subcomponents including: @@ -644,8 +645,6 @@ pub const InitOptions = struct { entitlements: ?[]const u8 = null, /// (Darwin) size of the __PAGEZERO segment pagezero_size: ?u64 = null, - /// (Darwin) search strategy for system libraries - search_strategy: ?link.File.MachO.SearchStrategy = null, /// (Darwin) set minimum space for future expansion of the load commands headerpad_size: ?u32 = null, /// (Darwin) set enough space as if all paths were MATPATHLEN @@ -1567,7 +1566,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .install_name = options.install_name, .entitlements = options.entitlements, .pagezero_size = options.pagezero_size, - .search_strategy = options.search_strategy, .headerpad_size = options.headerpad_size, .headerpad_max_install_names = options.headerpad_max_install_names, .dead_strip_dylibs = options.dead_strip_dylibs, @@ -1727,15 +1725,18 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // When linking mingw-w64 there are some import libs we always need. for (mingw.always_link_libs) |name| { - try comp.bin_file.options.system_libs.put(comp.gpa, name, .{}); + try comp.bin_file.options.system_libs.put(comp.gpa, name, .{ + .needed = false, + .weak = false, + .path = name, + }); } } // Generate Windows import libs. if (target.os.tag == .windows) { const count = comp.bin_file.options.system_libs.count(); try comp.work_queue.ensureUnusedCapacity(count); - var i: usize = 0; - while (i < count) : (i += 1) { + for (0..count) |i| { comp.work_queue.writeItemAssumeCapacity(.{ .windows_import_lib = i }); } } @@ -2377,7 +2378,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes } man.hash.addOptionalBytes(comp.bin_file.options.soname); man.hash.addOptional(comp.bin_file.options.version); - link.hashAddSystemLibs(&man.hash, comp.bin_file.options.system_libs); + try link.hashAddSystemLibs(man, comp.bin_file.options.system_libs); man.hash.addListOfBytes(comp.bin_file.options.force_undefined_symbols.keys()); man.hash.addOptional(comp.bin_file.options.allow_shlib_undefined); man.hash.add(comp.bin_file.options.bind_global_refs_locally); @@ -2395,10 +2396,9 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes // Mach-O specific stuff man.hash.addListOfBytes(comp.bin_file.options.framework_dirs); - link.hashAddSystemLibs(&man.hash, comp.bin_file.options.frameworks); + link.hashAddFrameworks(&man.hash, comp.bin_file.options.frameworks); try man.addOptionalFile(comp.bin_file.options.entitlements); man.hash.addOptional(comp.bin_file.options.pagezero_size); - man.hash.addOptional(comp.bin_file.options.search_strategy); man.hash.addOptional(comp.bin_file.options.headerpad_size); man.hash.add(comp.bin_file.options.headerpad_max_install_names); man.hash.add(comp.bin_file.options.dead_strip_dylibs); -- cgit v1.2.3 From a1e21ceec8ecb475f96c5e83ee9f8d59ceecc82d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 1 Aug 2023 17:43:09 -0700 Subject: frontend: fix linking to Windows DLLs as system libs --- src/Compilation.zig | 5 +++ src/main.zig | 87 +++++++++++++++++++++++++++++++++-------------------- src/mingw.zig | 32 +++++++++++++++----- 3 files changed, 85 insertions(+), 39 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index f966f1e17f..0c8b3c5248 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5618,6 +5618,11 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { // to queue up a work item to produce the DLL import library for this. const gop = try comp.bin_file.options.system_libs.getOrPut(comp.gpa, lib_name); if (!gop.found_existing and comp.getTarget().os.tag == .windows) { + gop.value_ptr.* = .{ + .needed = true, + .weak = false, + .path = undefined, + }; try comp.work_queue.writeItem(.{ .windows_import_lib = comp.bin_file.options.system_libs.count() - 1, }); diff --git a/src/main.zig b/src/main.zig index 83e1e2bc38..797a33a20b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -28,6 +28,7 @@ const target_util = @import("target.zig"); const crash_report = @import("crash_report.zig"); const Module = @import("Module.zig"); const AstGen = @import("AstGen.zig"); +const mingw = @import("mingw.zig"); const Server = std.zig.Server; pub const std_options = struct { @@ -477,6 +478,8 @@ const usage_build_generic = \\ -needed-l[lib], Link against system library (even if unused) \\ --needed-library [lib] \\ -L[d], --library-directory [d] Add a directory to the library search path + \\ -search_paths_first Search each library search path for dynamic libs then static libs + \\ -search_dylibs_first Search for dynamic libs in each library search path, then static libs. \\ -T[script], --script [script] Use a custom linker script \\ --version-script [path] Provide a version .map file \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) @@ -537,8 +540,6 @@ const usage_build_generic = \\ -install_name=[value] (Darwin) add dylib's install name \\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature \\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment in hexadecimal notation - \\ -search_paths_first (Darwin) search each dir in library search paths for `libx.dylib` then `libx.a` - \\ -search_dylibs_first (Darwin) search `libx.dylib` in each dir in library search paths, then `libx.a` \\ -headerpad [value] (Darwin) set minimum space for future expansion of the load commands in hexadecimal notation \\ -headerpad_max_install_names (Darwin) set enough space as if all paths were MAXPATHLEN \\ -dead_strip (Darwin) remove functions and data that are unreachable by the entry point or exported symbols @@ -2567,6 +2568,34 @@ fn buildOutputType( } lib_dir_args = undefined; // From here we use lib_dirs instead. + const self_exe_path: ?[]const u8 = if (!process.can_spawn) + null + else + introspect.findZigExePath(arena) catch |err| { + fatal("unable to find zig self exe path: {s}", .{@errorName(err)}); + }; + + var zig_lib_directory: Compilation.Directory = d: { + if (override_lib_dir) |unresolved_lib_dir| { + const lib_dir = try introspect.resolvePath(arena, unresolved_lib_dir); + break :d .{ + .path = lib_dir, + .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { + fatal("unable to open zig lib directory '{s}': {s}", .{ lib_dir, @errorName(err) }); + }, + }; + } else if (builtin.os.tag == .wasi) { + break :d getWasiPreopen("/lib"); + } else if (self_exe_path) |p| { + break :d introspect.findZigLibDirFromSelfExe(arena, p) catch |err| { + fatal("unable to find zig installation directory: {s}", .{@errorName(err)}); + }; + } else { + unreachable; + } + }; + defer zig_lib_directory.handle.close(); + // Now that we have target info, we can find out if any of the system libraries // are part of libc or libc++. We remove them from the list and communicate their // existence via flags instead. @@ -2612,6 +2641,25 @@ fn buildOutputType( }, } + if (target_info.target.os.tag == .windows) { + const exists = mingw.libExists(arena, target_info.target, zig_lib_directory, lib_name) catch |err| { + fatal("failed to check zig installation for DLL import libs: {s}", .{ + @errorName(err), + }); + }; + if (exists) { + try resolved_system_libs.append(arena, .{ + .name = lib_name, + .lib = .{ + .needed = true, + .weak = false, + .path = undefined, + }, + }); + continue; + } + } + if (fs.path.isAbsolute(lib_name)) { fatal("cannot use absolute path as a system library: {s}", .{lib_name}); } @@ -2758,9 +2806,13 @@ fn buildOutputType( if (failed_libs.items.len > 0) { for (failed_libs.items) |f| { + const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths; std.log.err("unable to find {s} system library '{s}' using strategy '{s}'. searched paths:{s}", .{ - @tagName(f.preferred_mode), f.name, @tagName(f.strategy), f.checked_paths, + @tagName(f.preferred_mode), f.name, @tagName(f.strategy), searched_paths, }); + if (f.preferred_mode == .Dynamic and f.strategy == .no_fallback) { + std.log.info("to link statically, pass the library as a positional argument", .{}); + } } process.exit(1); } @@ -3079,35 +3131,6 @@ fn buildOutputType( } } - const self_exe_path: ?[]const u8 = if (!process.can_spawn) - null - else - introspect.findZigExePath(arena) catch |err| { - fatal("unable to find zig self exe path: {s}", .{@errorName(err)}); - }; - - var zig_lib_directory: Compilation.Directory = d: { - if (override_lib_dir) |unresolved_lib_dir| { - const lib_dir = try introspect.resolvePath(arena, unresolved_lib_dir); - break :d .{ - .path = lib_dir, - .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { - fatal("unable to open zig lib directory '{s}': {s}", .{ lib_dir, @errorName(err) }); - }, - }; - } else if (builtin.os.tag == .wasi) { - break :d getWasiPreopen("/lib"); - } else if (self_exe_path) |p| { - break :d introspect.findZigLibDirFromSelfExe(arena, p) catch |err| { - fatal("unable to find zig installation directory: {s}", .{@errorName(err)}); - }; - } else { - unreachable; - } - }; - - defer zig_lib_directory.handle.close(); - var thread_pool: ThreadPool = undefined; try thread_pool.init(.{ .allocator = gpa }); defer thread_pool.deinit(); diff --git a/src/mingw.zig b/src/mingw.zig index 39059f804a..f4d5ae23e2 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -283,7 +283,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const def_file_path = findDef(comp, arena, lib_name) catch |err| switch (err) { + const def_file_path = findDef(arena, comp.getTarget(), comp.zig_lib_directory, lib_name) catch |err| switch (err) { error.FileNotFound => { log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name }); // In this case we will end up putting foo.lib onto the linker line and letting the linker @@ -431,10 +431,28 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { }); } -/// This function body is verbose but all it does is test 3 different paths and see if a .def file exists. -fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8 { - const target = comp.getTarget(); +pub fn libExists( + allocator: Allocator, + target: std.Target, + zig_lib_directory: Cache.Directory, + lib_name: []const u8, +) !bool { + const s = findDef(allocator, target, zig_lib_directory, lib_name) catch |err| switch (err) { + error.FileNotFound => return false, + else => |e| return e, + }; + defer allocator.free(s); + return true; +} +/// This function body is verbose but all it does is test 3 different paths and +/// see if a .def file exists. +fn findDef( + allocator: Allocator, + target: std.Target, + zig_lib_directory: Cache.Directory, + lib_name: []const u8, +) ![]u8 { const lib_path = switch (target.cpu.arch) { .x86 => "lib32", .x86_64 => "lib64", @@ -451,7 +469,7 @@ fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8 { // Try the archtecture-specific path first. const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def"; - if (comp.zig_lib_directory.path) |p| { + if (zig_lib_directory.path) |p| { try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name }); } else { try override_path.writer().print(fmt_path, .{ lib_path, lib_name }); @@ -468,7 +486,7 @@ fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8 // Try the generic version. override_path.shrinkRetainingCapacity(0); const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def"; - if (comp.zig_lib_directory.path) |p| { + if (zig_lib_directory.path) |p| { try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name }); } else { try override_path.writer().print(fmt_path, .{lib_name}); @@ -485,7 +503,7 @@ fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8 // Try the generic version and preprocess it. override_path.shrinkRetainingCapacity(0); const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in"; - if (comp.zig_lib_directory.path) |p| { + if (zig_lib_directory.path) |p| { try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name }); } else { try override_path.writer().print(fmt_path, .{lib_name}); -- cgit v1.2.3 From 986a3d23abcbdb61fd733d2340d4872b6ee55dca Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 1 Aug 2023 23:48:14 -0700 Subject: frontend: make SystemLib.path optional This can be null in two cases right now: 1. Windows DLLs that zig ships such as advapi32. 2. extern "foo" fn declarations where we find out about libraries too late TODO: make this non-optional and resolve those two cases somehow. --- src/Compilation.zig | 4 ++-- src/link.zig | 8 ++++++-- src/link/Elf.zig | 2 +- src/link/MachO/zld.zig | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 0c8b3c5248..91b31c6004 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1728,7 +1728,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { try comp.bin_file.options.system_libs.put(comp.gpa, name, .{ .needed = false, .weak = false, - .path = name, + .path = null, }); } } @@ -5621,7 +5621,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { gop.value_ptr.* = .{ .needed = true, .weak = false, - .path = undefined, + .path = null, }; try comp.work_queue.writeItem(.{ .windows_import_lib = comp.bin_file.options.system_libs.count() - 1, diff --git a/src/link.zig b/src/link.zig index 9edba50123..6e5921d815 100644 --- a/src/link.zig +++ b/src/link.zig @@ -26,7 +26,11 @@ const TypedValue = @import("TypedValue.zig"); pub const SystemLib = struct { needed: bool, weak: bool, - path: []const u8, + /// This can be null in two cases right now: + /// 1. Windows DLLs that zig ships such as advapi32. + /// 2. extern "foo" fn declarations where we find out about libraries too late + /// TODO: make this non-optional and resolve those two cases somehow. + path: ?[]const u8, }; /// When adding a new field, remember to update `hashAddFrameworks`. @@ -48,7 +52,7 @@ pub fn hashAddSystemLibs( for (hm.values()) |value| { man.hash.add(value.needed); man.hash.add(value.weak); - _ = try man.addFile(value.path, null); + if (value.path) |p| _ = try man.addFile(p, null); } } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 3292168bce..dd88d47fab 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1842,7 +1842,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // libraries and not static libraries (the check for that needs to be earlier), // but they could be full paths to .so files, in which case we // want to avoid prepending "-l". - argv.appendAssumeCapacity(lib_info.path); + argv.appendAssumeCapacity(lib_info.path.?); } if (!as_needed) { diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 40cf9b217a..56eee2b546 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -3554,7 +3554,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr { const vals = options.system_libs.values(); try libs.ensureUnusedCapacity(vals.len); - for (vals) |v| libs.putAssumeCapacity(v.path, v); + for (vals) |v| libs.putAssumeCapacity(v.path.?, v); } try MachO.resolveLibSystem(arena, comp, options.sysroot, target, options.lib_dirs, &libs); -- cgit v1.2.3 From c94bbebb9150f68ce179caa4f6beeab0622696a6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 2 Aug 2023 18:35:18 -0700 Subject: std.zig.system.NativePaths: simplify and integrate with Darwin SDK --- lib/std/zig/system/NativePaths.zig | 108 ++++++++++++------------------------- src/Compilation.zig | 6 ++- src/main.zig | 25 +-------- 3 files changed, 40 insertions(+), 99 deletions(-) (limited to 'src/Compilation.zig') diff --git a/lib/std/zig/system/NativePaths.zig b/lib/std/zig/system/NativePaths.zig index f9798695ad..61f71144ca 100644 --- a/lib/std/zig/system/NativePaths.zig +++ b/lib/std/zig/system/NativePaths.zig @@ -1,6 +1,5 @@ const std = @import("../../std.zig"); const builtin = @import("builtin"); -const ArrayList = std.ArrayList; const Allocator = std.mem.Allocator; const process = std.process; const mem = std.mem; @@ -8,28 +7,18 @@ const mem = std.mem; const NativePaths = @This(); const NativeTargetInfo = std.zig.system.NativeTargetInfo; -include_dirs: ArrayList([:0]u8), -lib_dirs: ArrayList([:0]u8), -framework_dirs: ArrayList([:0]u8), -rpaths: ArrayList([:0]u8), -warnings: ArrayList([:0]u8), +arena: Allocator, +include_dirs: std.ArrayListUnmanaged([]const u8) = .{}, +lib_dirs: std.ArrayListUnmanaged([]const u8) = .{}, +framework_dirs: std.ArrayListUnmanaged([]const u8) = .{}, +rpaths: std.ArrayListUnmanaged([]const u8) = .{}, +warnings: std.ArrayListUnmanaged([]const u8) = .{}, -pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths { +pub fn detect(arena: Allocator, native_info: NativeTargetInfo) !NativePaths { const native_target = native_info.target; - - var self: NativePaths = .{ - .include_dirs = ArrayList([:0]u8).init(allocator), - .lib_dirs = ArrayList([:0]u8).init(allocator), - .framework_dirs = ArrayList([:0]u8).init(allocator), - .rpaths = ArrayList([:0]u8).init(allocator), - .warnings = ArrayList([:0]u8).init(allocator), - }; - errdefer self.deinit(); - + var self: NativePaths = .{ .arena = arena }; var is_nix = false; - if (process.getEnvVarOwned(allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { - defer allocator.free(nix_cflags_compile); - + if (process.getEnvVarOwned(arena, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { is_nix = true; var it = mem.tokenizeScalar(u8, nix_cflags_compile, ' '); while (true) { @@ -58,9 +47,7 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths error.EnvironmentVariableNotFound => {}, error.OutOfMemory => |e| return e, } - if (process.getEnvVarOwned(allocator, "NIX_LDFLAGS")) |nix_ldflags| { - defer allocator.free(nix_ldflags); - + if (process.getEnvVarOwned(arena, "NIX_LDFLAGS")) |nix_ldflags| { is_nix = true; var it = mem.tokenizeScalar(u8, nix_ldflags, ' '); while (true) { @@ -89,17 +76,18 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths return self; } + // TODO: consider also adding homebrew paths + // TODO: consider also adding macports paths if (comptime builtin.target.isDarwin()) { - try self.addIncludeDir("/usr/include"); - try self.addLibDir("/usr/lib"); - try self.addFrameworkDir("/System/Library/Frameworks"); - - if (builtin.target.os.version_range.semver.min.major < 11) { - try self.addIncludeDir("/usr/local/include"); - try self.addLibDir("/usr/local/lib"); - try self.addFrameworkDir("/Library/Frameworks"); + if (std.zig.system.darwin.isDarwinSDKInstalled(arena)) sdk: { + const sdk = std.zig.system.darwin.getDarwinSDK(arena, native_target) orelse break :sdk; + try self.addLibDir(try std.fs.path.join(arena, &.{ sdk.path, "usr/lib" })); + try self.addFrameworkDir(try std.fs.path.join(arena, &.{ sdk.path, "System/Library/Frameworks" })); + try self.addIncludeDir(try std.fs.path.join(arena, &.{ sdk.path, "usr/include" })); + return self; } - + // These do not include headers, so the ones that come with the SDK are preferred. + try self.addFrameworkDir("/System/Library/Frameworks"); return self; } @@ -115,8 +103,7 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths } if (builtin.os.tag != .windows) { - const triple = try native_target.linuxTriple(allocator); - defer allocator.free(triple); + const triple = try native_target.linuxTriple(arena); const qual = native_target.ptrBitWidth(); @@ -172,69 +159,42 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths return self; } -pub fn deinit(self: *NativePaths) void { - deinitArray(&self.include_dirs); - deinitArray(&self.lib_dirs); - deinitArray(&self.framework_dirs); - deinitArray(&self.rpaths); - deinitArray(&self.warnings); - self.* = undefined; -} - -fn deinitArray(array: *ArrayList([:0]u8)) void { - for (array.items) |item| { - array.allocator.free(item); - } - array.deinit(); -} - pub fn addIncludeDir(self: *NativePaths, s: []const u8) !void { - return self.appendArray(&self.include_dirs, s); + return self.include_dirs.append(self.arena, s); } pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { - const item = try std.fmt.allocPrintZ(self.include_dirs.allocator, fmt, args); - errdefer self.include_dirs.allocator.free(item); - try self.include_dirs.append(item); + const item = try std.fmt.allocPrint(self.arena, fmt, args); + try self.include_dirs.append(self.arena, item); } pub fn addLibDir(self: *NativePaths, s: []const u8) !void { - return self.appendArray(&self.lib_dirs, s); + try self.lib_dirs.append(self.arena, s); } pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { - const item = try std.fmt.allocPrintZ(self.lib_dirs.allocator, fmt, args); - errdefer self.lib_dirs.allocator.free(item); - try self.lib_dirs.append(item); + const item = try std.fmt.allocPrint(self.arena, fmt, args); + try self.lib_dirs.append(self.arena, item); } pub fn addWarning(self: *NativePaths, s: []const u8) !void { - return self.appendArray(&self.warnings, s); + return self.warnings.append(self.arena, s); } pub fn addFrameworkDir(self: *NativePaths, s: []const u8) !void { - return self.appendArray(&self.framework_dirs, s); + return self.framework_dirs.append(self.arena, s); } pub fn addFrameworkDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { - const item = try std.fmt.allocPrintZ(self.framework_dirs.allocator, fmt, args); - errdefer self.framework_dirs.allocator.free(item); - try self.framework_dirs.append(item); + const item = try std.fmt.allocPrint(self.arena, fmt, args); + try self.framework_dirs.append(self.arena, item); } pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { - const item = try std.fmt.allocPrintZ(self.warnings.allocator, fmt, args); - errdefer self.warnings.allocator.free(item); - try self.warnings.append(item); + const item = try std.fmt.allocPrint(self.arena, fmt, args); + try self.warnings.append(self.arena, item); } pub fn addRPath(self: *NativePaths, s: []const u8) !void { - return self.appendArray(&self.rpaths, s); -} - -fn appendArray(self: *NativePaths, array: *ArrayList([:0]u8), s: []const u8) !void { - _ = self; - const item = try array.allocator.dupeZ(u8, s); - errdefer array.allocator.free(item); - try array.append(item); + try self.rpaths.append(self.arena, s); } diff --git a/src/Compilation.zig b/src/Compilation.zig index 91b31c6004..094275f749 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -857,8 +857,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const sysroot = blk: { if (options.sysroot) |sysroot| { break :blk sysroot; - } else if (options.native_darwin_sdk) |sdk| { - break :blk sdk.path; } else { break :blk null; } @@ -4341,6 +4339,10 @@ pub fn addCCArgs( try argv.append("-ObjC++"); } + for (comp.bin_file.options.framework_dirs) |framework_dir| { + try argv.appendSlice(&.{ "-isystem", framework_dir }); + } + // According to Rich Felker libc headers are supposed to go before C language headers. // However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics // and other compiler specific items. diff --git a/src/main.zig b/src/main.zig index 87db5c80ea..3bdcf0d2ce 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2685,34 +2685,13 @@ fn buildOutputType( warn("{s}", .{warning}); } - const has_sysroot = if (comptime builtin.target.isDarwin()) outer: { - if (std.zig.system.darwin.isDarwinSDKInstalled(arena)) { - const sdk = std.zig.system.darwin.getDarwinSDK(arena, target_info.target) orelse - break :outer false; - native_darwin_sdk = sdk; - try clang_argv.ensureUnusedCapacity(2); - clang_argv.appendAssumeCapacity("-isysroot"); - clang_argv.appendAssumeCapacity(sdk.path); - break :outer true; - } else break :outer false; - } else false; - try clang_argv.ensureUnusedCapacity(paths.include_dirs.items.len * 2); - const isystem_flag = if (has_sysroot) "-iwithsysroot" else "-isystem"; for (paths.include_dirs.items) |include_dir| { - clang_argv.appendAssumeCapacity(isystem_flag); + clang_argv.appendAssumeCapacity("-isystem"); clang_argv.appendAssumeCapacity(include_dir); } - try clang_argv.ensureUnusedCapacity(paths.framework_dirs.items.len * 2); - try framework_dirs.ensureUnusedCapacity(paths.framework_dirs.items.len); - const iframework_flag = if (has_sysroot) "-iframeworkwithsysroot" else "-iframework"; - for (paths.framework_dirs.items) |framework_dir| { - clang_argv.appendAssumeCapacity(iframework_flag); - clang_argv.appendAssumeCapacity(framework_dir); - framework_dirs.appendAssumeCapacity(framework_dir); - } - + try framework_dirs.appendSlice(paths.framework_dirs.items); try lib_dirs.appendSlice(paths.lib_dirs.items); try rpath_list.appendSlice(paths.rpaths.items); } -- cgit v1.2.3 From da91ef5c28bd11823bd84b6f54df9ca601f03e21 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 2 Aug 2023 19:17:07 -0700 Subject: zig libc: restore functionality on macOS Regressed in 2006add8496c47804ee3b6c562f420871cb4ea0a. References to native_darwin_sdk are no longer kept in the frontend. Instead the darwin SDK is detected as part of NativePaths and as part of LibCInstallation. --- src/Compilation.zig | 134 ++++++++++++++++----------------------- src/libc_installation.zig | 16 ++++- src/link.zig | 4 +- src/link/MachO/load_commands.zig | 9 ++- src/main.zig | 4 +- 5 files changed, 77 insertions(+), 90 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 094275f749..8b071cff0e 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -637,8 +637,6 @@ pub const InitOptions = struct { wasi_exec_model: ?std.builtin.WasiExecModel = null, /// (Zig compiler development) Enable dumping linker's state as JSON. enable_link_snapshots: bool = false, - /// (Darwin) Path and version of the native SDK if detected. - native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null, /// (Darwin) Install name of the dylib install_name: ?[]const u8 = null, /// (Darwin) Path to entitlements file @@ -945,7 +943,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { options.is_native_abi, link_libc, options.libc_installation, - options.native_darwin_sdk != null, ); const must_pie = target_util.requiresPIE(options.target); @@ -1560,7 +1557,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .wasi_exec_model = wasi_exec_model, .hash_style = options.hash_style, .enable_link_snapshots = options.enable_link_snapshots, - .native_darwin_sdk = options.native_darwin_sdk, .install_name = options.install_name, .entitlements = options.entitlements, .pagezero_size = options.pagezero_size, @@ -4865,7 +4861,6 @@ fn detectLibCIncludeDirs( is_native_abi: bool, link_libc: bool, libc_installation: ?*const LibCInstallation, - has_macos_sdk: bool, ) !LibCDirs { if (!link_libc) { return LibCDirs{ @@ -4881,28 +4876,19 @@ fn detectLibCIncludeDirs( // If linking system libraries and targeting the native abi, default to // using the system libc installation. if (is_native_abi and !target.isMinGW()) { - if (target.isDarwin()) { - return if (has_macos_sdk) - // For Darwin/macOS, we are all set with getDarwinSDK found earlier. - LibCDirs{ - .libc_include_dir_list = &[0][]u8{}, - .libc_installation = null, - } - else - getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target); - } const libc = try arena.create(LibCInstallation); - libc.* = LibCInstallation.findNative(.{ .allocator = arena }) catch |err| switch (err) { + libc.* = LibCInstallation.findNative(.{ .allocator = arena, .target = target }) catch |err| switch (err) { error.CCompilerExitCode, error.CCompilerCrashed, error.CCompilerCannotFindHeaders, error.UnableToSpawnCCompiler, + error.DarwinSdkNotFound, => |e| { // We tried to integrate with the native system C compiler, // however, it is not installed. So we must rely on our bundled // libc files. if (target_util.canBuildLibC(target)) { - return detectLibCFromBuilding(arena, zig_lib_dir, target, has_macos_sdk); + return detectLibCFromBuilding(arena, zig_lib_dir, target); } return e; }, @@ -4914,7 +4900,7 @@ fn detectLibCIncludeDirs( // If not linking system libraries, build and provide our own libc by // default if possible. if (target_util.canBuildLibC(target)) { - return detectLibCFromBuilding(arena, zig_lib_dir, target, has_macos_sdk); + return detectLibCFromBuilding(arena, zig_lib_dir, target); } // If zig can't build the libc for the target and we are targeting the @@ -4928,7 +4914,7 @@ fn detectLibCIncludeDirs( if (use_system_abi) { const libc = try arena.create(LibCInstallation); - libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true }); + libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true, .target = target }); return detectLibCFromLibCInstallation(arena, target, libc); } @@ -4977,69 +4963,59 @@ fn detectLibCFromBuilding( arena: Allocator, zig_lib_dir: []const u8, target: std.Target, - has_macos_sdk: bool, ) !LibCDirs { - switch (target.os.tag) { - .macos => return if (has_macos_sdk) - // For Darwin/macOS, we are all set with getDarwinSDK found earlier. - LibCDirs{ - .libc_include_dir_list = &[0][]u8{}, - .libc_installation = null, - } - else - getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target), - else => { - const generic_name = target_util.libCGenericName(target); - // Some architectures are handled by the same set of headers. - const arch_name = if (target.abi.isMusl()) - musl.archNameHeaders(target.cpu.arch) - else if (target.cpu.arch.isThumb()) - // ARM headers are valid for Thumb too. - switch (target.cpu.arch) { - .thumb => "arm", - .thumbeb => "armeb", - else => unreachable, - } - else - @tagName(target.cpu.arch); - const os_name = @tagName(target.os.tag); - // Musl's headers are ABI-agnostic and so they all have the "musl" ABI name. - const abi_name = if (target.abi.isMusl()) "musl" else @tagName(target.abi); - const s = std.fs.path.sep_str; - const arch_include_dir = try std.fmt.allocPrint( - arena, - "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}", - .{ zig_lib_dir, arch_name, os_name, abi_name }, - ); - const generic_include_dir = try std.fmt.allocPrint( - arena, - "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}", - .{ zig_lib_dir, generic_name }, - ); - const generic_arch_name = target_util.osArchName(target); - const arch_os_include_dir = try std.fmt.allocPrint( - arena, - "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any", - .{ zig_lib_dir, generic_arch_name, os_name }, - ); - const generic_os_include_dir = try std.fmt.allocPrint( - arena, - "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any", - .{ zig_lib_dir, os_name }, - ); + if (target.isDarwin()) + return getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target); + + const generic_name = target_util.libCGenericName(target); + // Some architectures are handled by the same set of headers. + const arch_name = if (target.abi.isMusl()) + musl.archNameHeaders(target.cpu.arch) + else if (target.cpu.arch.isThumb()) + // ARM headers are valid for Thumb too. + switch (target.cpu.arch) { + .thumb => "arm", + .thumbeb => "armeb", + else => unreachable, + } + else + @tagName(target.cpu.arch); + const os_name = @tagName(target.os.tag); + // Musl's headers are ABI-agnostic and so they all have the "musl" ABI name. + const abi_name = if (target.abi.isMusl()) "musl" else @tagName(target.abi); + const s = std.fs.path.sep_str; + const arch_include_dir = try std.fmt.allocPrint( + arena, + "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}", + .{ zig_lib_dir, arch_name, os_name, abi_name }, + ); + const generic_include_dir = try std.fmt.allocPrint( + arena, + "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}", + .{ zig_lib_dir, generic_name }, + ); + const generic_arch_name = target_util.osArchName(target); + const arch_os_include_dir = try std.fmt.allocPrint( + arena, + "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any", + .{ zig_lib_dir, generic_arch_name, os_name }, + ); + const generic_os_include_dir = try std.fmt.allocPrint( + arena, + "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any", + .{ zig_lib_dir, os_name }, + ); - const list = try arena.alloc([]const u8, 4); - list[0] = arch_include_dir; - list[1] = generic_include_dir; - list[2] = arch_os_include_dir; - list[3] = generic_os_include_dir; + const list = try arena.alloc([]const u8, 4); + list[0] = arch_include_dir; + list[1] = generic_include_dir; + list[2] = arch_os_include_dir; + list[3] = generic_os_include_dir; - return LibCDirs{ - .libc_include_dir_list = list, - .libc_installation = null, - }; - }, - } + return LibCDirs{ + .libc_include_dir_list = list, + .libc_installation = null, + }; } pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8) ![]const u8 { diff --git a/src/libc_installation.zig b/src/libc_installation.zig index bdfe83b71a..4dbe9d9c57 100644 --- a/src/libc_installation.zig +++ b/src/libc_installation.zig @@ -33,6 +33,7 @@ pub const LibCInstallation = struct { LibCKernel32LibNotFound, UnsupportedArchitecture, WindowsSdkNotFound, + DarwinSdkNotFound, ZigIsTheCCompiler, }; @@ -171,6 +172,7 @@ pub const LibCInstallation = struct { pub const FindNativeOptions = struct { allocator: Allocator, + target: std.Target, /// If enabled, will print human-friendly errors to stderr. verbose: bool = false, @@ -181,7 +183,19 @@ pub const LibCInstallation = struct { var self: LibCInstallation = .{}; if (is_darwin) { - @panic("Darwin is handled separately via std.zig.system.darwin module"); + if (!std.zig.system.darwin.isDarwinSDKInstalled(args.allocator)) + return error.DarwinSdkNotFound; + const sdk = std.zig.system.darwin.getDarwinSDK(args.allocator, args.target) orelse + return error.DarwinSdkNotFound; + defer args.allocator.free(sdk.path); + + self.include_dir = try fs.path.join(args.allocator, &.{ + sdk.path, "usr/include", + }); + self.sys_include_dir = try fs.path.join(args.allocator, &.{ + sdk.path, "usr/include", + }); + return self; } else if (is_windows) { var sdk: ZigWindowsSDK = ZigWindowsSDK.find(args.allocator) catch |err| switch (err) { error.NotFound => return error.WindowsSdkNotFound, diff --git a/src/link.zig b/src/link.zig index 6e5921d815..2fea01ff89 100644 --- a/src/link.zig +++ b/src/link.zig @@ -231,6 +231,7 @@ pub const Options = struct { version: ?std.SemanticVersion, compatibility_version: ?std.SemanticVersion, + darwin_sdk_version: ?std.SemanticVersion = null, libc_installation: ?*const LibCInstallation, dwarf_format: ?std.dwarf.Format, @@ -241,9 +242,6 @@ pub const Options = struct { /// (Zig compiler development) Enable dumping of linker's state as JSON. enable_link_snapshots: bool = false, - /// (Darwin) Path and version of the native SDK if detected. - native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null, - /// (Darwin) Install name for the dylib install_name: ?[]const u8 = null, diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 10f446f191..8f803d98cb 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -278,11 +278,10 @@ pub fn writeBuildVersionLC(options: *const link.Options, lc_writer: anytype) !vo const platform_version = @as(u32, @intCast(ver.major << 16 | ver.minor << 8)); break :blk platform_version; }; - const sdk_version = if (options.native_darwin_sdk) |sdk| blk: { - const ver = sdk.version; - const sdk_version = @as(u32, @intCast(ver.major << 16 | ver.minor << 8)); - break :blk sdk_version; - } else platform_version; + const sdk_version: u32 = if (options.darwin_sdk_version) |ver| + @intCast(ver.major << 16 | ver.minor << 8) + else + platform_version; const is_simulator_abi = options.target.abi == .simulator; try lc_writer.writeStruct(macho.build_version_command{ .cmdsize = cmdsize, diff --git a/src/main.zig b/src/main.zig index 3bdcf0d2ce..3f06469a75 100644 --- a/src/main.zig +++ b/src/main.zig @@ -891,7 +891,6 @@ fn buildOutputType( var minor_subsystem_version: ?u32 = null; var wasi_exec_model: ?std.builtin.WasiExecModel = null; var enable_link_snapshots: bool = false; - var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null; var install_name: ?[]const u8 = null; var hash_style: link.HashStyle = .both; var entitlements: ?[]const u8 = null; @@ -3367,7 +3366,6 @@ fn buildOutputType( .wasi_exec_model = wasi_exec_model, .debug_compile_errors = debug_compile_errors, .enable_link_snapshots = enable_link_snapshots, - .native_darwin_sdk = native_darwin_sdk, .install_name = install_name, .entitlements = entitlements, .pagezero_size = pagezero_size, @@ -4243,10 +4241,12 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { if (!cross_target.isNative()) { fatal("unable to detect libc for non-native target", .{}); } + const target_info = try detectNativeTargetInfo(cross_target); var libc = LibCInstallation.findNative(.{ .allocator = gpa, .verbose = true, + .target = target_info.target, }) catch |err| { fatal("unable to detect native libc: {s}", .{@errorName(err)}); }; -- cgit v1.2.3 From 9dd9aa49a59cf8534aaf9b44ee20d526ba8da1c6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 2 Aug 2023 20:40:56 -0700 Subject: Compilation: fix incorrect non-optional assumption --- src/Compilation.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 8b071cff0e..ece6fa77cb 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2362,10 +2362,10 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes if (comp.bin_file.options.link_libc) { man.hash.add(comp.bin_file.options.libc_installation != null); if (comp.bin_file.options.libc_installation) |libc_installation| { - man.hash.addBytes(libc_installation.crt_dir.?); + man.hash.addOptionalBytes(libc_installation.crt_dir); if (target.abi == .msvc) { - man.hash.addBytes(libc_installation.msvc_lib_dir.?); - man.hash.addBytes(libc_installation.kernel32_lib_dir.?); + man.hash.addOptionalBytes(libc_installation.msvc_lib_dir); + man.hash.addOptionalBytes(libc_installation.kernel32_lib_dir); } } man.hash.addOptionalBytes(comp.bin_file.options.dynamic_linker); -- cgit v1.2.3 From 4089f96defa7dae169e2b6cdba5e545293e57cb8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 2 Aug 2023 21:49:26 -0700 Subject: darwin: pass -iframework to clang for system frameworks --- src/Compilation.zig | 21 ++++++++++++++++++++- src/main.zig | 7 ++----- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index ece6fa77cb..79110d3bc4 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -124,6 +124,7 @@ zig_lib_directory: Directory, local_cache_directory: Directory, global_cache_directory: Directory, libc_include_dir_list: []const []const u8, +libc_framework_dir_list: []const []const u8, thread_pool: *ThreadPool, /// Populated when we build the libc++ static library. A Job to build this is placed in the queue @@ -1593,6 +1594,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .cache_parent = cache, .self_exe_path = options.self_exe_path, .libc_include_dir_list = libc_dirs.libc_include_dir_list, + .libc_framework_dir_list = libc_dirs.libc_framework_dir_list, .sanitize_c = sanitize_c, .thread_pool = options.thread_pool, .clang_passthrough_mode = options.clang_passthrough_mode, @@ -4335,8 +4337,12 @@ pub fn addCCArgs( try argv.append("-ObjC++"); } + for (comp.libc_framework_dir_list) |framework_dir| { + try argv.appendSlice(&.{ "-iframework", framework_dir }); + } + for (comp.bin_file.options.framework_dirs) |framework_dir| { - try argv.appendSlice(&.{ "-isystem", framework_dir }); + try argv.appendSlice(&.{ "-F", framework_dir }); } // According to Rich Felker libc headers are supposed to go before C language headers. @@ -4821,6 +4827,7 @@ test "classifyFileExt" { const LibCDirs = struct { libc_include_dir_list: []const []const u8, libc_installation: ?*const LibCInstallation, + libc_framework_dir_list: []const []const u8, }; fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8, target: Target) !LibCDirs { @@ -4851,6 +4858,7 @@ fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8, return LibCDirs{ .libc_include_dir_list = list, .libc_installation = null, + .libc_framework_dir_list = &.{}, }; } @@ -4866,6 +4874,7 @@ fn detectLibCIncludeDirs( return LibCDirs{ .libc_include_dir_list = &[0][]u8{}, .libc_installation = null, + .libc_framework_dir_list = &.{}, }; } @@ -4921,11 +4930,13 @@ fn detectLibCIncludeDirs( return LibCDirs{ .libc_include_dir_list = &[0][]u8{}, .libc_installation = null, + .libc_framework_dir_list = &.{}, }; } fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const LibCInstallation) !LibCDirs { var list = try std.ArrayList([]const u8).initCapacity(arena, 5); + var framework_list = std.ArrayList([]const u8).init(arena); list.appendAssumeCapacity(lci.include_dir.?); @@ -4953,9 +4964,16 @@ fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const list.appendAssumeCapacity(config_dir); } + if (target.isDarwin()) d: { + const down1 = std.fs.path.dirname(lci.sys_include_dir.?) orelse break :d; + const down2 = std.fs.path.dirname(down1) orelse break :d; + try framework_list.append(try std.fs.path.join(arena, &.{ down2, "System", "Library", "Frameworks" })); + } + return LibCDirs{ .libc_include_dir_list = list.items, .libc_installation = lci, + .libc_framework_dir_list = framework_list.items, }; } @@ -5015,6 +5033,7 @@ fn detectLibCFromBuilding( return LibCDirs{ .libc_include_dir_list = list, .libc_installation = null, + .libc_framework_dir_list = &.{}, }; } diff --git a/src/main.zig b/src/main.zig index e3720cf903..a1b0216a70 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2695,11 +2695,8 @@ fn buildOutputType( try rpath_list.appendSlice(paths.rpaths.items); } - // Now that we have target info, we can find out if any of the system libraries - // are part of libc or libc++. We remove them from the list and communicate their - // existence via flags instead. - // Similarly, if any libs in this list are statically provided, we omit - // them from the resolved list and populate the link_objects array instead. + // If any libs in this list are statically provided, we omit them from the + // resolved list and populate the link_objects array instead. { var test_path = std.ArrayList(u8).init(gpa); defer test_path.deinit(); -- cgit v1.2.3 From 4923e64199d8a16f7e0f376a1839daa70a9dfdf2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 2 Aug 2023 22:08:56 -0700 Subject: Compilation: detect sysroot from libc installation --- src/Compilation.zig | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 79110d3bc4..a08c3e09f4 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -853,14 +853,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { break :blk false; }; - const sysroot = blk: { - if (options.sysroot) |sysroot| { - break :blk sysroot; - } else { - break :blk null; - } - }; - const lto = blk: { if (options.want_lto) |explicit| { if (!use_lld and !options.target.isDarwin()) @@ -946,6 +938,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { options.libc_installation, ); + const sysroot = options.sysroot orelse libc_dirs.sysroot; + const must_pie = target_util.requiresPIE(options.target); const pie: bool = if (options.want_pie) |explicit| pie: { if (!explicit and must_pie) { @@ -4828,6 +4822,7 @@ const LibCDirs = struct { libc_include_dir_list: []const []const u8, libc_installation: ?*const LibCInstallation, libc_framework_dir_list: []const []const u8, + sysroot: ?[]const u8, }; fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8, target: Target) !LibCDirs { @@ -4859,6 +4854,7 @@ fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8, .libc_include_dir_list = list, .libc_installation = null, .libc_framework_dir_list = &.{}, + .sysroot = null, }; } @@ -4875,6 +4871,7 @@ fn detectLibCIncludeDirs( .libc_include_dir_list = &[0][]u8{}, .libc_installation = null, .libc_framework_dir_list = &.{}, + .sysroot = null, }; } @@ -4931,6 +4928,7 @@ fn detectLibCIncludeDirs( .libc_include_dir_list = &[0][]u8{}, .libc_installation = null, .libc_framework_dir_list = &.{}, + .sysroot = null, }; } @@ -4964,16 +4962,20 @@ fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const list.appendAssumeCapacity(config_dir); } + var sysroot: ?[]const u8 = null; + if (target.isDarwin()) d: { const down1 = std.fs.path.dirname(lci.sys_include_dir.?) orelse break :d; const down2 = std.fs.path.dirname(down1) orelse break :d; try framework_list.append(try std.fs.path.join(arena, &.{ down2, "System", "Library", "Frameworks" })); + sysroot = down2; } return LibCDirs{ .libc_include_dir_list = list.items, .libc_installation = lci, .libc_framework_dir_list = framework_list.items, + .sysroot = sysroot, }; } @@ -5034,6 +5036,7 @@ fn detectLibCFromBuilding( .libc_include_dir_list = list, .libc_installation = null, .libc_framework_dir_list = &.{}, + .sysroot = null, }; } -- cgit v1.2.3