authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-19 15:03:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:20-07:00
log8944dea23fb554290a4b54ca40b0594f6e3f77a9
tree9ce6e53249296cac235346f7e26fbc0f6a87fc11
parentdb2ca2ca0005b73e1a7df42de77a06c5506f3aaf

CLI: fix regressed logic for any_dyn_libs

This value needs access to the fully resolved set of system libraries, which required restructuring a bunch of CLI logic.

2 files changed, 329 insertions(+), 303 deletions(-)

src/Compilation.zig+11
......@@ -86,6 +86,7 @@ skip_linker_dependencies: bool,
8686no_builtin: bool,
8787function_sections: bool,
8888data_sections: bool,
89native_system_include_paths: []const []const u8,
8990
9091c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
9192win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =
......@@ -1065,6 +1066,7 @@ pub const InitOptions = struct {
10651066 version: ?std.SemanticVersion = null,
10661067 compatibility_version: ?std.SemanticVersion = null,
10671068 libc_installation: ?*const LibCInstallation = null,
1069 native_system_include_paths: []const []const u8 = &.{},
10681070 clang_preprocessor_mode: ClangPreprocessorMode = .no,
10691071 /// This is for stage1 and should be deleted upon completion of self-hosting.
10701072 color: Color = .auto,
......@@ -1508,6 +1510,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15081510 .job_queued_update_builtin_zig = have_zcu,
15091511 .function_sections = options.function_sections,
15101512 .data_sections = options.data_sections,
1513 .native_system_include_paths = options.native_system_include_paths,
15111514 };
15121515
15131516 const lf_open_opts: link.File.OpenOptions = .{
......@@ -5296,6 +5299,14 @@ pub fn addCCArgs(
52965299 try argv.append("-ffreestanding");
52975300 }
52985301
5302 if (mod.resolved_target.is_native_os and mod.resolved_target.is_native_abi) {
5303 try argv.ensureUnusedCapacity(comp.native_system_include_paths.len * 2);
5304 for (comp.native_system_include_paths) |include_path| {
5305 argv.appendAssumeCapacity("-isystem");
5306 argv.appendAssumeCapacity(include_path);
5307 }
5308 }
5309
52995310 try argv.appendSlice(mod.cc_argv);
53005311}
53015312
src/main.zig+318-303
......@@ -821,7 +821,6 @@ fn buildOutputType(
821821 var target_mcpu: ?[]const u8 = null;
822822 var emit_h: Emit = .no;
823823 var soname: SOName = undefined;
824 var want_native_include_dirs = false;
825824 var want_compiler_rt: ?bool = null;
826825 var linker_script: ?[]const u8 = null;
827826 var version_script: ?[]const u8 = null;
......@@ -863,8 +862,6 @@ fn buildOutputType(
863862 var link_emit_relocs = false;
864863 var each_lib_rpath: ?bool = null;
865864 var build_id: ?std.zig.BuildId = null;
866 var sysroot: ?[]const u8 = null;
867 var libc_paths_file: ?[]const u8 = try EnvVar.ZIG_LIBC.get(arena);
868865 var runtime_args_start: ?usize = null;
869866 var test_filter: ?[]const u8 = null;
870867 var test_name_prefix: ?[]const u8 = null;
......@@ -892,16 +889,11 @@ fn buildOutputType(
892889 var pdb_out_path: ?[]const u8 = null;
893890 var error_limit: ?Module.ErrorInt = null;
894891 // These are before resolving sysroot.
895 var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{};
896892 var extra_cflags: std.ArrayListUnmanaged([]const u8) = .{};
897893 var extra_rcflags: std.ArrayListUnmanaged([]const u8) = .{};
898894 var symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{};
899 var rpath_list: std.ArrayListUnmanaged([]const u8) = .{};
900895 var rc_includes: Compilation.RcIncludes = .any;
901896 var manifest_file: ?[]const u8 = null;
902 var link_objects: std.ArrayListUnmanaged(Compilation.LinkObject) = .{};
903 var framework_dirs: std.ArrayListUnmanaged([]const u8) = .{};
904 var frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{};
905897 var linker_export_symbol_names: std.ArrayListUnmanaged([]const u8) = .{};
906898
907899 // Tracks the position in c_source_files which have already their owner populated.
......@@ -951,7 +943,6 @@ fn buildOutputType(
951943 .resolved_options = undefined,
952944
953945 .system_libs = .{},
954 .external_system_libs = .{},
955946 .resolved_system_libs = .{},
956947 .wasi_emulated_libs = .{},
957948
......@@ -959,6 +950,17 @@ fn buildOutputType(
959950 .rc_source_files = .{},
960951
961952 .llvm_m_args = .{},
953 .sysroot = null,
954 .lib_dirs = .{}, // populated by createModule()
955 .lib_dir_args = .{}, // populated from CLI arg parsing
956 .libc_installation = null,
957 .want_native_include_dirs = false,
958 .frameworks = .{},
959 .framework_dirs = .{},
960 .rpath_list = .{},
961 .libc_paths_file = try EnvVar.ZIG_LIBC.get(arena),
962 .link_objects = .{},
963 .native_system_include_paths = &.{},
962964 };
963965
964966 // before arg parsing, check for the NO_COLOR environment variable
......@@ -1137,17 +1139,17 @@ fn buildOutputType(
11371139 if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?)))
11381140 fatal("invalid package name '{s}': cannot contain folder separators", .{provided_name.?});
11391141 } else if (mem.eql(u8, arg, "-rpath")) {
1140 try rpath_list.append(arena, args_iter.nextOrFatal());
1142 try create_module.rpath_list.append(arena, args_iter.nextOrFatal());
11411143 } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) {
1142 try lib_dir_args.append(arena, args_iter.nextOrFatal());
1144 try create_module.lib_dir_args.append(arena, args_iter.nextOrFatal());
11431145 } else if (mem.eql(u8, arg, "-F")) {
1144 try framework_dirs.append(arena, args_iter.nextOrFatal());
1146 try create_module.framework_dirs.append(arena, args_iter.nextOrFatal());
11451147 } else if (mem.eql(u8, arg, "-framework")) {
1146 try frameworks.put(arena, args_iter.nextOrFatal(), .{});
1148 try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{});
11471149 } else if (mem.eql(u8, arg, "-weak_framework")) {
1148 try frameworks.put(arena, args_iter.nextOrFatal(), .{ .weak = true });
1150 try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{ .weak = true });
11491151 } else if (mem.eql(u8, arg, "-needed_framework")) {
1150 try frameworks.put(arena, args_iter.nextOrFatal(), .{ .needed = true });
1152 try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{ .needed = true });
11511153 } else if (mem.eql(u8, arg, "-install_name")) {
11521154 install_name = args_iter.nextOrFatal();
11531155 } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {
......@@ -1236,11 +1238,11 @@ fn buildOutputType(
12361238 } else if (mem.eql(u8, arg, "-iframework")) {
12371239 const path = args_iter.nextOrFatal();
12381240 try cssan.addIncludePath(arena, &clang_argv, .iframework, arg, path, false);
1239 try framework_dirs.append(arena, path); // Forward to the backend as -F
1241 try create_module.framework_dirs.append(arena, path); // Forward to the backend as -F
12401242 } else if (mem.eql(u8, arg, "-iframeworkwithsysroot")) {
12411243 const path = args_iter.nextOrFatal();
12421244 try cssan.addIncludePath(arena, &clang_argv, .iframeworkwithsysroot, arg, path, false);
1243 try framework_dirs.append(arena, path); // Forward to the backend as -F
1245 try create_module.framework_dirs.append(arena, path); // Forward to the backend as -F
12441246 } else if (mem.eql(u8, arg, "--version")) {
12451247 const next_arg = args_iter.nextOrFatal();
12461248 version = std.SemanticVersion.parse(next_arg) catch |err| {
......@@ -1265,10 +1267,10 @@ fn buildOutputType(
12651267 create_module.dynamic_linker = args_iter.nextOrFatal();
12661268 } else if (mem.eql(u8, arg, "--sysroot")) {
12671269 const next_arg = args_iter.nextOrFatal();
1268 sysroot = next_arg;
1270 create_module.sysroot = next_arg;
12691271 try clang_argv.appendSlice(arena, &.{ "-isysroot", next_arg });
12701272 } else if (mem.eql(u8, arg, "--libc")) {
1271 libc_paths_file = args_iter.nextOrFatal();
1273 create_module.libc_paths_file = args_iter.nextOrFatal();
12721274 } else if (mem.eql(u8, arg, "--test-filter")) {
12731275 test_filter = args_iter.nextOrFatal();
12741276 } else if (mem.eql(u8, arg, "--test-name-prefix")) {
......@@ -1620,9 +1622,9 @@ fn buildOutputType(
16201622 } else if (mem.startsWith(u8, arg, "-T")) {
16211623 linker_script = arg[2..];
16221624 } else if (mem.startsWith(u8, arg, "-L")) {
1623 try lib_dir_args.append(arena, arg[2..]);
1625 try create_module.lib_dir_args.append(arena, arg[2..]);
16241626 } else if (mem.startsWith(u8, arg, "-F")) {
1625 try framework_dirs.append(arena, arg[2..]);
1627 try create_module.framework_dirs.append(arena, arg[2..]);
16261628 } else if (mem.startsWith(u8, arg, "-l")) {
16271629 // We don't know whether this library is part of libc
16281630 // or libc++ until we resolve the target, so we append
......@@ -1667,14 +1669,14 @@ fn buildOutputType(
16671669 }
16681670 } else switch (file_ext orelse Compilation.classifyFileExt(arg)) {
16691671 .shared_library => {
1670 try link_objects.append(arena, .{ .path = arg });
1672 try create_module.link_objects.append(arena, .{ .path = arg });
16711673 create_module.opts.any_dyn_libs = true;
16721674 },
16731675 .object, .static_library => {
1674 try link_objects.append(arena, .{ .path = arg });
1676 try create_module.link_objects.append(arena, .{ .path = arg });
16751677 },
16761678 .res => {
1677 try link_objects.append(arena, .{ .path = arg });
1679 try create_module.link_objects.append(arena, .{ .path = arg });
16781680 contains_res_file = true;
16791681 },
16801682 .manifest => {
......@@ -1721,7 +1723,7 @@ fn buildOutputType(
17211723 soname = .no;
17221724 create_module.opts.ensure_libc_on_non_freestanding = true;
17231725 create_module.opts.ensure_libcpp_on_non_freestanding = arg_mode == .cpp;
1724 want_native_include_dirs = true;
1726 create_module.want_native_include_dirs = true;
17251727 // Clang's driver enables this switch unconditionally.
17261728 // Disabling the emission of .eh_frame_hdr can unexpectedly break
17271729 // some functionality that depend on it, such as C++ exceptions and
......@@ -1786,20 +1788,20 @@ fn buildOutputType(
17861788 });
17871789 },
17881790 .shared_library => {
1789 try link_objects.append(arena, .{
1791 try create_module.link_objects.append(arena, .{
17901792 .path = it.only_arg,
17911793 .must_link = must_link,
17921794 });
17931795 create_module.opts.any_dyn_libs = true;
17941796 },
17951797 .unknown, .object, .static_library => {
1796 try link_objects.append(arena, .{
1798 try create_module.link_objects.append(arena, .{
17971799 .path = it.only_arg,
17981800 .must_link = must_link,
17991801 });
18001802 },
18011803 .res => {
1802 try link_objects.append(arena, .{
1804 try create_module.link_objects.append(arena, .{
18031805 .path = it.only_arg,
18041806 .must_link = must_link,
18051807 });
......@@ -1835,7 +1837,7 @@ fn buildOutputType(
18351837 // more control over what's in the resulting
18361838 // binary: no extra rpaths and DSO filename exactly
18371839 // as provided. Hello, Go.
1838 try link_objects.append(arena, .{
1840 try create_module.link_objects.append(arena, .{
18391841 .path = it.only_arg,
18401842 .must_link = must_link,
18411843 .loption = true,
......@@ -2036,7 +2038,7 @@ fn buildOutputType(
20362038 try linker_args.append("-z");
20372039 try linker_args.append(it.only_arg);
20382040 },
2039 .lib_dir => try lib_dir_args.append(arena, it.only_arg),
2041 .lib_dir => try create_module.lib_dir_args.append(arena, it.only_arg),
20402042 .mcpu => target_mcpu = it.only_arg,
20412043 .m => try create_module.llvm_m_args.append(arena, it.only_arg),
20422044 .dep_file => {
......@@ -2050,15 +2052,15 @@ fn buildOutputType(
20502052 disable_c_depfile = true;
20512053 try clang_argv.appendSlice(arena, it.other_args);
20522054 },
2053 .framework_dir => try framework_dirs.append(arena, it.only_arg),
2054 .framework => try frameworks.put(arena, it.only_arg, .{}),
2055 .nostdlibinc => want_native_include_dirs = false,
2055 .framework_dir => try create_module.framework_dirs.append(arena, it.only_arg),
2056 .framework => try create_module.frameworks.put(arena, it.only_arg, .{}),
2057 .nostdlibinc => create_module.want_native_include_dirs = false,
20562058 .strip => mod_opts.strip = true,
20572059 .exec_model => {
20582060 create_module.opts.wasi_exec_model = parseWasiExecModel(it.only_arg);
20592061 },
20602062 .sysroot => {
2061 sysroot = it.only_arg;
2063 create_module.sysroot = it.only_arg;
20622064 },
20632065 .entry => {
20642066 create_module.opts.entry = .{ .named = it.only_arg };
......@@ -2072,7 +2074,7 @@ fn buildOutputType(
20722074 .preferred_mode = lib_preferred_mode,
20732075 .search_strategy = lib_search_strategy,
20742076 }),
2075 .weak_framework => try frameworks.put(arena, it.only_arg, .{ .weak = true }),
2077 .weak_framework => try create_module.frameworks.put(arena, it.only_arg, .{ .weak = true }),
20762078 .headerpad_max_install_names => headerpad_max_install_names = true,
20772079 .compress_debug_sections => {
20782080 if (it.only_arg.len == 0) {
......@@ -2133,7 +2135,7 @@ fn buildOutputType(
21332135 }
21342136 provided_name = name[prefix..end];
21352137 } else if (mem.eql(u8, arg, "-rpath")) {
2136 try rpath_list.append(arena, linker_args_it.nextOrFatal());
2138 try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal());
21372139 } else if (mem.eql(u8, arg, "--subsystem")) {
21382140 subsystem = try parseSubSystem(linker_args_it.nextOrFatal());
21392141 } else if (mem.eql(u8, arg, "-I") or
......@@ -2345,11 +2347,11 @@ fn buildOutputType(
23452347 });
23462348 };
23472349 } else if (mem.eql(u8, arg, "-framework")) {
2348 try frameworks.put(arena, linker_args_it.nextOrFatal(), .{});
2350 try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{});
23492351 } else if (mem.eql(u8, arg, "-weak_framework")) {
2350 try frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .weak = true });
2352 try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .weak = true });
23512353 } else if (mem.eql(u8, arg, "-needed_framework")) {
2352 try frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .needed = true });
2354 try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .needed = true });
23532355 } else if (mem.eql(u8, arg, "-needed_library")) {
23542356 try create_module.system_libs.put(arena, linker_args_it.nextOrFatal(), .{
23552357 .weak = false,
......@@ -2399,7 +2401,7 @@ fn buildOutputType(
23992401 } else if (mem.eql(u8, arg, "-install_name")) {
24002402 install_name = linker_args_it.nextOrFatal();
24012403 } else if (mem.eql(u8, arg, "-force_load")) {
2402 try link_objects.append(arena, .{
2404 try create_module.link_objects.append(arena, .{
24032405 .path = linker_args_it.nextOrFatal(),
24042406 .must_link = true,
24052407 });
......@@ -2504,7 +2506,7 @@ fn buildOutputType(
25042506 },
25052507 }
25062508 if (create_module.c_source_files.items.len == 0 and
2507 link_objects.items.len == 0 and
2509 create_module.link_objects.items.len == 0 and
25082510 root_src_file == null)
25092511 {
25102512 // For example `zig cc` and no args should print the "no input files" message.
......@@ -2550,8 +2552,8 @@ fn buildOutputType(
25502552 if (create_module.c_source_files.items.len >= 1)
25512553 break :b create_module.c_source_files.items[0].src_path;
25522554
2553 if (link_objects.items.len >= 1)
2554 break :b link_objects.items[0].path;
2555 if (create_module.link_objects.items.len >= 1)
2556 break :b create_module.link_objects.items[0].path;
25552557
25562558 if (emit_bin == .yes)
25572559 break :b emit_bin.yes;
......@@ -2761,250 +2763,10 @@ fn buildOutputType(
27612763 }
27622764 }
27632765
2764 const root_name = if (provided_name) |n| n else main_mod.fully_qualified_name;
2765
2766 // Resolve the library path arguments with respect to sysroot.
2767 var lib_dirs: std.ArrayListUnmanaged([]const u8) = .{};
2768 if (sysroot) |root| {
2769 try lib_dirs.ensureUnusedCapacity(arena, lib_dir_args.items.len * 2);
2770 for (lib_dir_args.items) |dir| {
2771 if (fs.path.isAbsolute(dir)) {
2772 const stripped_dir = dir[fs.path.diskDesignator(dir).len..];
2773 const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir });
2774 lib_dirs.appendAssumeCapacity(full_path);
2775 }
2776 lib_dirs.appendAssumeCapacity(dir);
2777 }
2778 } else {
2779 lib_dirs = lib_dir_args;
2780 }
2781 lib_dir_args = undefined; // From here we use lib_dirs instead.
2782
2783 if (main_mod.resolved_target.is_native_os and target.isDarwin()) {
2784 // If we want to link against frameworks, we need system headers.
2785 if (framework_dirs.items.len > 0 or frameworks.count() > 0)
2786 want_native_include_dirs = true;
2787 }
2788
2789 // Trigger native system library path detection if necessary.
2790 if (sysroot == null and
2791 main_mod.resolved_target.is_native_os and
2792 main_mod.resolved_target.is_native_abi and
2793 (create_module.external_system_libs.len != 0 or want_native_include_dirs))
2794 {
2795 const paths = std.zig.system.NativePaths.detect(arena, target) catch |err| {
2796 fatal("unable to detect native system paths: {s}", .{@errorName(err)});
2797 };
2798 for (paths.warnings.items) |warning| {
2799 warn("{s}", .{warning});
2800 }
2801
2802 try clang_argv.ensureUnusedCapacity(arena, paths.include_dirs.items.len * 2);
2803 for (paths.include_dirs.items) |include_dir| {
2804 clang_argv.appendAssumeCapacity("-isystem");
2805 clang_argv.appendAssumeCapacity(include_dir);
2806 }
2807
2808 try framework_dirs.appendSlice(arena, paths.framework_dirs.items);
2809 try lib_dirs.appendSlice(arena, paths.lib_dirs.items);
2810 try rpath_list.appendSlice(arena, paths.rpaths.items);
2811 }
2812
2813 var libc_installation: ?LibCInstallation = null;
2814 if (libc_paths_file) |paths_file| {
2815 libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| {
2816 fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) });
2817 };
2818 }
2819
2820 if (builtin.target.os.tag == .windows and
2821 target.abi == .msvc and
2822 create_module.external_system_libs.len != 0)
2823 {
2824 if (libc_installation == null) {
2825 libc_installation = try LibCInstallation.findNative(.{
2826 .allocator = arena,
2827 .verbose = true,
2828 .target = target,
2829 });
2830
2831 try lib_dirs.appendSlice(arena, &.{
2832 libc_installation.?.msvc_lib_dir.?,
2833 libc_installation.?.kernel32_lib_dir.?,
2834 });
2835 }
2836 }
2837
2838 // If any libs in this list are statically provided, we omit them from the
2839 // resolved list and populate the link_objects array instead.
2840 {
2841 var test_path = std.ArrayList(u8).init(gpa);
2842 defer test_path.deinit();
2843
2844 var checked_paths = std.ArrayList(u8).init(gpa);
2845 defer checked_paths.deinit();
2846
2847 var failed_libs = std.ArrayList(struct {
2848 name: []const u8,
2849 strategy: SystemLib.SearchStrategy,
2850 checked_paths: []const u8,
2851 preferred_mode: std.builtin.LinkMode,
2852 }).init(arena);
2853
2854 syslib: for (create_module.external_system_libs.items(.name), create_module.external_system_libs.items(.info)) |lib_name, info| {
2855 // Checked in the first pass above while looking for libc libraries.
2856 assert(!fs.path.isAbsolute(lib_name));
2857
2858 checked_paths.clearRetainingCapacity();
2859
2860 switch (info.search_strategy) {
2861 .mode_first, .no_fallback => {
2862 // check for preferred mode
2863 for (lib_dirs.items) |lib_dir_path| {
2864 if (try accessLibPath(
2865 &test_path,
2866 &checked_paths,
2867 lib_dir_path,
2868 lib_name,
2869 target,
2870 info.preferred_mode,
2871 )) {
2872 const path = try arena.dupe(u8, test_path.items);
2873 switch (info.preferred_mode) {
2874 .Static => try link_objects.append(arena, .{ .path = path }),
2875 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
2876 .name = lib_name,
2877 .lib = .{
2878 .needed = info.needed,
2879 .weak = info.weak,
2880 .path = path,
2881 },
2882 }),
2883 }
2884 continue :syslib;
2885 }
2886 }
2887 // check for fallback mode
2888 if (info.search_strategy == .no_fallback) {
2889 try failed_libs.append(.{
2890 .name = lib_name,
2891 .strategy = info.search_strategy,
2892 .checked_paths = try arena.dupe(u8, checked_paths.items),
2893 .preferred_mode = info.preferred_mode,
2894 });
2895 continue :syslib;
2896 }
2897 for (lib_dirs.items) |lib_dir_path| {
2898 if (try accessLibPath(
2899 &test_path,
2900 &checked_paths,
2901 lib_dir_path,
2902 lib_name,
2903 target,
2904 info.fallbackMode(),
2905 )) {
2906 const path = try arena.dupe(u8, test_path.items);
2907 switch (info.fallbackMode()) {
2908 .Static => try link_objects.append(arena, .{ .path = path }),
2909 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
2910 .name = lib_name,
2911 .lib = .{
2912 .needed = info.needed,
2913 .weak = info.weak,
2914 .path = path,
2915 },
2916 }),
2917 }
2918 continue :syslib;
2919 }
2920 }
2921 try failed_libs.append(.{
2922 .name = lib_name,
2923 .strategy = info.search_strategy,
2924 .checked_paths = try arena.dupe(u8, checked_paths.items),
2925 .preferred_mode = info.preferred_mode,
2926 });
2927 continue :syslib;
2928 },
2929 .paths_first => {
2930 for (lib_dirs.items) |lib_dir_path| {
2931 // check for preferred mode
2932 if (try accessLibPath(
2933 &test_path,
2934 &checked_paths,
2935 lib_dir_path,
2936 lib_name,
2937 target,
2938 info.preferred_mode,
2939 )) {
2940 const path = try arena.dupe(u8, test_path.items);
2941 switch (info.preferred_mode) {
2942 .Static => try link_objects.append(arena, .{ .path = path }),
2943 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
2944 .name = lib_name,
2945 .lib = .{
2946 .needed = info.needed,
2947 .weak = info.weak,
2948 .path = path,
2949 },
2950 }),
2951 }
2952 continue :syslib;
2953 }
2954
2955 // check for fallback mode
2956 if (try accessLibPath(
2957 &test_path,
2958 &checked_paths,
2959 lib_dir_path,
2960 lib_name,
2961 target,
2962 info.fallbackMode(),
2963 )) {
2964 const path = try arena.dupe(u8, test_path.items);
2965 switch (info.fallbackMode()) {
2966 .Static => try link_objects.append(arena, .{ .path = path }),
2967 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
2968 .name = lib_name,
2969 .lib = .{
2970 .needed = info.needed,
2971 .weak = info.weak,
2972 .path = path,
2973 },
2974 }),
2975 }
2976 continue :syslib;
2977 }
2978 }
2979 try failed_libs.append(.{
2980 .name = lib_name,
2981 .strategy = info.search_strategy,
2982 .checked_paths = try arena.dupe(u8, checked_paths.items),
2983 .preferred_mode = info.preferred_mode,
2984 });
2985 continue :syslib;
2986 },
2987 }
2988 @compileError("unreachable");
2989 }
2990
2991 if (failed_libs.items.len > 0) {
2992 for (failed_libs.items) |f| {
2993 const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths;
2994 std.log.err("unable to find {s} system library '{s}' using strategy '{s}'. searched paths:{s}", .{
2995 @tagName(f.preferred_mode), f.name, @tagName(f.strategy), searched_paths,
2996 });
2997 }
2998 process.exit(1);
2999 }
3000 }
3001 // After this point, create_module.resolved_system_libs is used instead of
3002 // create_module.external_system_libs.
3003
30042766 // We now repeat part of the process for frameworks.
30052767 var resolved_frameworks = std.ArrayList(Compilation.Framework).init(arena);
30062768
3007 if (frameworks.keys().len > 0) {
2769 if (create_module.frameworks.keys().len > 0) {
30082770 var test_path = std.ArrayList(u8).init(gpa);
30092771 defer test_path.deinit();
30102772
......@@ -3016,10 +2778,10 @@ fn buildOutputType(
30162778 checked_paths: []const u8,
30172779 }).init(arena);
30182780
3019 framework: for (frameworks.keys(), frameworks.values()) |framework_name, info| {
2781 framework: for (create_module.frameworks.keys(), create_module.frameworks.values()) |framework_name, info| {
30202782 checked_paths.clearRetainingCapacity();
30212783
3022 for (framework_dirs.items) |framework_dir_path| {
2784 for (create_module.framework_dirs.items) |framework_dir_path| {
30232785 if (try accessFrameworkPath(
30242786 &test_path,
30252787 &checked_paths,
......@@ -3054,11 +2816,13 @@ fn buildOutputType(
30542816 }
30552817 // After this point, resolved_frameworks is used instead of frameworks.
30562818
3057 if (create_module.opts.output_mode == .Obj and (target.ofmt == .coff or target.ofmt == .macho)) {
2819 if (create_module.resolved_options.output_mode == .Obj and
2820 (target.ofmt == .coff or target.ofmt == .macho))
2821 {
30582822 const total_obj_count = create_module.c_source_files.items.len +
30592823 @intFromBool(root_src_file != null) +
30602824 create_module.rc_source_files.items.len +
3061 link_objects.items.len;
2825 create_module.link_objects.items.len;
30622826 if (total_obj_count > 1) {
30632827 fatal("{s} does not support linking multiple objects into one", .{@tagName(target.ofmt)});
30642828 }
......@@ -3070,6 +2834,8 @@ fn buildOutputType(
30702834 const output_to_cache = listen != .none;
30712835 const optional_version = if (have_version) version else null;
30722836
2837 const root_name = if (provided_name) |n| n else main_mod.fully_qualified_name;
2838
30732839 const resolved_soname: ?[]const u8 = switch (soname) {
30742840 .yes => |explicit| explicit,
30752841 .no => null,
......@@ -3105,8 +2871,8 @@ fn buildOutputType(
31052871 .basename = try std.zig.binNameAlloc(arena, .{
31062872 .root_name = root_name,
31072873 .target = target,
3108 .output_mode = create_module.opts.output_mode,
3109 .link_mode = create_module.opts.link_mode,
2874 .output_mode = create_module.resolved_options.output_mode,
2875 .link_mode = create_module.resolved_options.link_mode,
31102876 .version = optional_version,
31112877 }),
31122878 },
......@@ -3224,9 +2990,9 @@ fn buildOutputType(
32242990 };
32252991 defer emit_docs_resolved.deinit();
32262992
3227 const is_exe_or_dyn_lib = switch (create_module.opts.output_mode) {
2993 const is_exe_or_dyn_lib = switch (create_module.resolved_options.output_mode) {
32282994 .Obj => false,
3229 .Lib => (create_module.opts.link_mode orelse .Static) == .Dynamic,
2995 .Lib => create_module.resolved_options.link_mode == .Dynamic,
32302996 .Exe => true,
32312997 };
32322998 // Note that cmake when targeting Windows will try to execute
......@@ -3354,7 +3120,7 @@ fn buildOutputType(
33543120 .self_exe_path = self_exe_path,
33553121 .config = create_module.resolved_options,
33563122 .root_name = root_name,
3357 .sysroot = sysroot,
3123 .sysroot = create_module.sysroot,
33583124 .main_mod = main_mod,
33593125 .root_mod = root_mod,
33603126 .std_mod = std_mod,
......@@ -3365,15 +3131,15 @@ fn buildOutputType(
33653131 .emit_llvm_bc = emit_llvm_bc_resolved.data,
33663132 .emit_docs = emit_docs_resolved.data,
33673133 .emit_implib = emit_implib_resolved.data,
3368 .lib_dirs = lib_dirs.items,
3369 .rpath_list = rpath_list.items,
3134 .lib_dirs = create_module.lib_dirs.items,
3135 .rpath_list = create_module.rpath_list.items,
33703136 .symbol_wrap_set = symbol_wrap_set,
33713137 .c_source_files = create_module.c_source_files.items,
33723138 .rc_source_files = create_module.rc_source_files.items,
33733139 .manifest_file = manifest_file,
33743140 .rc_includes = rc_includes,
3375 .link_objects = link_objects.items,
3376 .framework_dirs = framework_dirs.items,
3141 .link_objects = create_module.link_objects.items,
3142 .framework_dirs = create_module.framework_dirs.items,
33773143 .frameworks = resolved_frameworks.items,
33783144 .system_lib_names = create_module.resolved_system_libs.items(.name),
33793145 .system_lib_infos = create_module.resolved_system_libs.items(.lib),
......@@ -3427,7 +3193,7 @@ fn buildOutputType(
34273193 .clang_passthrough_mode = clang_passthrough_mode,
34283194 .clang_preprocessor_mode = clang_preprocessor_mode,
34293195 .version = optional_version,
3430 .libc_installation = if (libc_installation) |*lci| lci else null,
3196 .libc_installation = if (create_module.libc_installation) |*lci| lci else null,
34313197 .verbose_cc = verbose_cc,
34323198 .verbose_link = verbose_link,
34333199 .verbose_air = verbose_air,
......@@ -3458,6 +3224,7 @@ fn buildOutputType(
34583224 .reference_trace = reference_trace,
34593225 .pdb_out_path = pdb_out_path,
34603226 .error_limit = error_limit,
3227 .native_system_include_paths = create_module.native_system_include_paths,
34613228 }) catch |err| switch (err) {
34623229 error.LibCUnavailable => {
34633230 const triple_name = try target.zigTriple(arena);
......@@ -3626,10 +3393,6 @@ const CreateModule = struct {
36263393 /// link_libcpp, and then the libraries are filtered into
36273394 /// `external_system_libs` and `resolved_system_libs`.
36283395 system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
3629 external_system_libs: std.MultiArrayList(struct {
3630 name: []const u8,
3631 info: SystemLib,
3632 }),
36333396 resolved_system_libs: std.MultiArrayList(struct {
36343397 name: []const u8,
36353398 lib: Compilation.SystemLib,
......@@ -3643,6 +3406,17 @@ const CreateModule = struct {
36433406 // This array is populated by zig cc frontend and then has to be converted to zig-style
36443407 // CPU features.
36453408 llvm_m_args: std.ArrayListUnmanaged([]const u8),
3409 sysroot: ?[]const u8,
3410 lib_dirs: std.ArrayListUnmanaged([]const u8),
3411 lib_dir_args: std.ArrayListUnmanaged([]const u8),
3412 libc_installation: ?LibCInstallation,
3413 want_native_include_dirs: bool,
3414 frameworks: std.StringArrayHashMapUnmanaged(Framework),
3415 native_system_include_paths: []const []const u8,
3416 framework_dirs: std.ArrayListUnmanaged([]const u8),
3417 rpath_list: std.ArrayListUnmanaged([]const u8),
3418 libc_paths_file: ?[]const u8,
3419 link_objects: std.ArrayListUnmanaged(Compilation.LinkObject),
36463420};
36473421
36483422fn createModule(
......@@ -3749,6 +3523,10 @@ fn createModule(
37493523 // First, remove libc, libc++, and compiler_rt libraries from the system libraries list.
37503524 // We need to know whether the set of system libraries contains anything besides these
37513525 // to decide whether to trigger native path detection logic.
3526 var external_system_libs: std.MultiArrayList(struct {
3527 name: []const u8,
3528 info: SystemLib,
3529 }) = .{};
37523530 for (create_module.system_libs.keys(), create_module.system_libs.values()) |lib_name, info| {
37533531 if (target.is_libc_lib_name(lib_name)) {
37543532 create_module.opts.link_libc = true;
......@@ -3800,12 +3578,249 @@ fn createModule(
38003578 }
38013579 }
38023580
3803 try create_module.external_system_libs.append(arena, .{
3581 try external_system_libs.append(arena, .{
38043582 .name = lib_name,
38053583 .info = info,
38063584 });
38073585 }
38083586 // After this point, external_system_libs is used instead of system_libs.
3587 if (external_system_libs.len != 0)
3588 create_module.want_native_include_dirs = true;
3589
3590 // Resolve the library path arguments with respect to sysroot.
3591 if (create_module.sysroot) |root| {
3592 try create_module.lib_dirs.ensureUnusedCapacity(arena, create_module.lib_dir_args.items.len * 2);
3593 for (create_module.lib_dir_args.items) |dir| {
3594 if (fs.path.isAbsolute(dir)) {
3595 const stripped_dir = dir[fs.path.diskDesignator(dir).len..];
3596 const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir });
3597 create_module.lib_dirs.appendAssumeCapacity(full_path);
3598 }
3599 create_module.lib_dirs.appendAssumeCapacity(dir);
3600 }
3601 } else {
3602 create_module.lib_dirs = create_module.lib_dir_args;
3603 }
3604 create_module.lib_dir_args = undefined; // From here we use lib_dirs instead.
3605
3606 if (resolved_target.is_native_os and target.isDarwin()) {
3607 // If we want to link against frameworks, we need system headers.
3608 if (create_module.frameworks.count() > 0)
3609 create_module.want_native_include_dirs = true;
3610 }
3611
3612 // Trigger native system library path detection if necessary.
3613 if (create_module.sysroot == null and
3614 resolved_target.is_native_os and resolved_target.is_native_abi and
3615 create_module.want_native_include_dirs)
3616 {
3617 var paths = std.zig.system.NativePaths.detect(arena, target) catch |err| {
3618 fatal("unable to detect native system paths: {s}", .{@errorName(err)});
3619 };
3620 for (paths.warnings.items) |warning| {
3621 warn("{s}", .{warning});
3622 }
3623
3624 create_module.native_system_include_paths = try paths.include_dirs.toOwnedSlice(arena);
3625
3626 try create_module.framework_dirs.appendSlice(arena, paths.framework_dirs.items);
3627 try create_module.lib_dirs.appendSlice(arena, paths.lib_dirs.items);
3628 try create_module.rpath_list.appendSlice(arena, paths.rpaths.items);
3629 }
3630
3631 if (create_module.libc_paths_file) |paths_file| {
3632 create_module.libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| {
3633 fatal("unable to parse libc paths file at path {s}: {s}", .{
3634 paths_file, @errorName(err),
3635 });
3636 };
3637 }
3638
3639 if (builtin.target.os.tag == .windows and target.abi == .msvc and
3640 external_system_libs.len != 0)
3641 {
3642 if (create_module.libc_installation == null) {
3643 create_module.libc_installation = try LibCInstallation.findNative(.{
3644 .allocator = arena,
3645 .verbose = true,
3646 .target = target,
3647 });
3648
3649 try create_module.lib_dirs.appendSlice(arena, &.{
3650 create_module.libc_installation.?.msvc_lib_dir.?,
3651 create_module.libc_installation.?.kernel32_lib_dir.?,
3652 });
3653 }
3654 }
3655
3656 // If any libs in this list are statically provided, we omit them from the
3657 // resolved list and populate the link_objects array instead.
3658 {
3659 var test_path = std.ArrayList(u8).init(gpa);
3660 defer test_path.deinit();
3661
3662 var checked_paths = std.ArrayList(u8).init(gpa);
3663 defer checked_paths.deinit();
3664
3665 var failed_libs = std.ArrayList(struct {
3666 name: []const u8,
3667 strategy: SystemLib.SearchStrategy,
3668 checked_paths: []const u8,
3669 preferred_mode: std.builtin.LinkMode,
3670 }).init(arena);
3671
3672 syslib: for (external_system_libs.items(.name), external_system_libs.items(.info)) |lib_name, info| {
3673 // Checked in the first pass above while looking for libc libraries.
3674 assert(!fs.path.isAbsolute(lib_name));
3675
3676 checked_paths.clearRetainingCapacity();
3677
3678 switch (info.search_strategy) {
3679 .mode_first, .no_fallback => {
3680 // check for preferred mode
3681 for (create_module.lib_dirs.items) |lib_dir_path| {
3682 if (try accessLibPath(
3683 &test_path,
3684 &checked_paths,
3685 lib_dir_path,
3686 lib_name,
3687 target,
3688 info.preferred_mode,
3689 )) {
3690 const path = try arena.dupe(u8, test_path.items);
3691 switch (info.preferred_mode) {
3692 .Static => try create_module.link_objects.append(arena, .{ .path = path }),
3693 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
3694 .name = lib_name,
3695 .lib = .{
3696 .needed = info.needed,
3697 .weak = info.weak,
3698 .path = path,
3699 },
3700 }),
3701 }
3702 continue :syslib;
3703 }
3704 }
3705 // check for fallback mode
3706 if (info.search_strategy == .no_fallback) {
3707 try failed_libs.append(.{
3708 .name = lib_name,
3709 .strategy = info.search_strategy,
3710 .checked_paths = try arena.dupe(u8, checked_paths.items),
3711 .preferred_mode = info.preferred_mode,
3712 });
3713 continue :syslib;
3714 }
3715 for (create_module.lib_dirs.items) |lib_dir_path| {
3716 if (try accessLibPath(
3717 &test_path,
3718 &checked_paths,
3719 lib_dir_path,
3720 lib_name,
3721 target,
3722 info.fallbackMode(),
3723 )) {
3724 const path = try arena.dupe(u8, test_path.items);
3725 switch (info.fallbackMode()) {
3726 .Static => try create_module.link_objects.append(arena, .{ .path = path }),
3727 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
3728 .name = lib_name,
3729 .lib = .{
3730 .needed = info.needed,
3731 .weak = info.weak,
3732 .path = path,
3733 },
3734 }),
3735 }
3736 continue :syslib;
3737 }
3738 }
3739 try failed_libs.append(.{
3740 .name = lib_name,
3741 .strategy = info.search_strategy,
3742 .checked_paths = try arena.dupe(u8, checked_paths.items),
3743 .preferred_mode = info.preferred_mode,
3744 });
3745 continue :syslib;
3746 },
3747 .paths_first => {
3748 for (create_module.lib_dirs.items) |lib_dir_path| {
3749 // check for preferred mode
3750 if (try accessLibPath(
3751 &test_path,
3752 &checked_paths,
3753 lib_dir_path,
3754 lib_name,
3755 target,
3756 info.preferred_mode,
3757 )) {
3758 const path = try arena.dupe(u8, test_path.items);
3759 switch (info.preferred_mode) {
3760 .Static => try create_module.link_objects.append(arena, .{ .path = path }),
3761 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
3762 .name = lib_name,
3763 .lib = .{
3764 .needed = info.needed,
3765 .weak = info.weak,
3766 .path = path,
3767 },
3768 }),
3769 }
3770 continue :syslib;
3771 }
3772
3773 // check for fallback mode
3774 if (try accessLibPath(
3775 &test_path,
3776 &checked_paths,
3777 lib_dir_path,
3778 lib_name,
3779 target,
3780 info.fallbackMode(),
3781 )) {
3782 const path = try arena.dupe(u8, test_path.items);
3783 switch (info.fallbackMode()) {
3784 .Static => try create_module.link_objects.append(arena, .{ .path = path }),
3785 .Dynamic => try create_module.resolved_system_libs.append(arena, .{
3786 .name = lib_name,
3787 .lib = .{
3788 .needed = info.needed,
3789 .weak = info.weak,
3790 .path = path,
3791 },
3792 }),
3793 }
3794 continue :syslib;
3795 }
3796 }
3797 try failed_libs.append(.{
3798 .name = lib_name,
3799 .strategy = info.search_strategy,
3800 .checked_paths = try arena.dupe(u8, checked_paths.items),
3801 .preferred_mode = info.preferred_mode,
3802 });
3803 continue :syslib;
3804 },
3805 }
3806 @compileError("unreachable");
3807 }
3808
3809 if (failed_libs.items.len > 0) {
3810 for (failed_libs.items) |f| {
3811 const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths;
3812 std.log.err("unable to find {s} system library '{s}' using strategy '{s}'. searched paths:{s}", .{
3813 @tagName(f.preferred_mode), f.name, @tagName(f.strategy), searched_paths,
3814 });
3815 }
3816 process.exit(1);
3817 }
3818 }
3819 // After this point, create_module.resolved_system_libs is used instead of
3820 // create_module.external_system_libs.
3821
3822 if (create_module.resolved_system_libs.len != 0)
3823 create_module.opts.any_dyn_libs = true;
38093824
38103825 create_module.resolved_options = Compilation.Config.resolve(create_module.opts) catch |err| switch (err) {
38113826 else => fatal("unable to resolve compilation options: {s}", .{@errorName(err)}),