diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 92b6d0de4a..d6a016f183 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -897,44 +897,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { const arena = b.allocator; const self = @fieldParentPtr(Compile, "step", step); - // Convert search prefixes to -I and -L arguments to be added at the end of - // each module's configuration. - var search_prefix_args: std.ArrayListUnmanaged([]const u8) = .{}; - for (b.search_prefixes.items) |search_prefix| { - var prefix_dir = fs.cwd().openDir(search_prefix, .{}) catch |err| { - return step.fail("unable to open prefix directory '{s}': {s}", .{ - search_prefix, @errorName(err), - }); - }; - defer prefix_dir.close(); - - // Avoid passing -L and -I flags for nonexistent directories. - // This prevents a warning, that should probably be upgraded to an error in Zig's - // CLI parsing code, when the linker sees an -L directory that does not exist. - - if (prefix_dir.accessZ("lib", .{})) |_| { - try search_prefix_args.appendSlice(arena, &.{ - "-L", try fs.path.join(arena, &.{ search_prefix, "lib" }), - }); - } else |err| switch (err) { - error.FileNotFound => {}, - else => |e| return step.fail("unable to access '{s}/lib' directory: {s}", .{ - search_prefix, @errorName(e), - }), - } - - if (prefix_dir.accessZ("include", .{})) |_| { - try search_prefix_args.appendSlice(arena, &.{ - "-I", try fs.path.join(arena, &.{ search_prefix, "include" }), - }); - } else |err| switch (err) { - error.FileNotFound => {}, - else => |e| return step.fail("unable to access '{s}/include' directory: {s}", .{ - search_prefix, @errorName(e), - }), - } - } - var zig_args = ArrayList([]const u8).init(arena); defer zig_args.deinit(); @@ -1235,10 +1197,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (cli_named_modules.modules.getIndex(module)) |module_cli_index| { const module_cli_name = cli_named_modules.names.keys()[module_cli_index]; try module.appendZigProcessFlags(&zig_args, step); - // These go after `appendZigProcessFlags` so that - // --search-prefix directories are prioritized lower than - // per-module settings. - try zig_args.appendSlice(search_prefix_args.items); // --dep arguments try zig_args.ensureUnusedCapacity(module.import_table.count() * 2); @@ -1505,6 +1463,42 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot }); } + // -I and -L arguments that appear after the last --mod argument apply to all modules. + for (b.search_prefixes.items) |search_prefix| { + var prefix_dir = fs.cwd().openDir(search_prefix, .{}) catch |err| { + return step.fail("unable to open prefix directory '{s}': {s}", .{ + search_prefix, @errorName(err), + }); + }; + defer prefix_dir.close(); + + // Avoid passing -L and -I flags for nonexistent directories. + // This prevents a warning, that should probably be upgraded to an error in Zig's + // CLI parsing code, when the linker sees an -L directory that does not exist. + + if (prefix_dir.accessZ("lib", .{})) |_| { + try zig_args.appendSlice(&.{ + "-L", try fs.path.join(arena, &.{ search_prefix, "lib" }), + }); + } else |err| switch (err) { + error.FileNotFound => {}, + else => |e| return step.fail("unable to access '{s}/lib' directory: {s}", .{ + search_prefix, @errorName(e), + }), + } + + if (prefix_dir.accessZ("include", .{})) |_| { + try zig_args.appendSlice(&.{ + "-I", try fs.path.join(arena, &.{ search_prefix, "include" }), + }); + } else |err| switch (err) { + error.FileNotFound => {}, + else => |e| return step.fail("unable to access '{s}/include' directory: {s}", .{ + search_prefix, @errorName(e), + }), + } + } + if (self.rc_includes != .any) { try zig_args.append("-rcincludes"); try zig_args.append(@tagName(self.rc_includes)); diff --git a/src/Compilation.zig b/src/Compilation.zig index 11b3328e0e..98f4012a26 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -165,6 +165,7 @@ last_update_was_cache_hit: bool = false, c_source_files: []const CSourceFile, rc_source_files: []const RcSourceFile, +global_cc_argv: []const []const u8, cache_parent: *Cache, /// Path to own executable for invoking `zig clang`. self_exe_path: ?[]const u8, @@ -1120,6 +1121,7 @@ pub const CreateOptions = struct { /// (Windows) PDB output path pdb_out_path: ?[]const u8 = null, error_limit: ?Compilation.Module.ErrorInt = null, + global_cc_argv: []const []const u8 = &.{}, pub const Entry = link.File.OpenOptions.Entry; }; @@ -1515,6 +1517,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil .wasi_emulated_libs = options.wasi_emulated_libs, .force_undefined_symbols = options.force_undefined_symbols, .link_eh_frame_hdr = link_eh_frame_hdr, + .global_cc_argv = options.global_cc_argv, }; // Prevent some footguns by making the "any" fields of config reflect @@ -2527,6 +2530,8 @@ fn addNonIncrementalStuffToCacheManifest( cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc); + man.hash.addListOfBytes(comp.global_cc_argv); + const opts = comp.cache_use.whole.lf_open_opts; try man.addOptionalFile(opts.linker_script); @@ -3941,6 +3946,7 @@ pub fn obtainCObjectCacheManifest( // that apply both to @cImport and compiling C objects. No linking stuff here! // Also nothing that applies only to compiling .zig code. cache_helpers.addModule(&man.hash, owner_mod); + man.hash.addListOfBytes(comp.global_cc_argv); man.hash.add(comp.config.link_libcpp); // When libc_installation is null it means that Zig generated this dir list @@ -5411,6 +5417,7 @@ pub fn addCCArgs( } } + try argv.appendSlice(comp.global_cc_argv); try argv.appendSlice(mod.cc_argv); } diff --git a/src/main.zig b/src/main.zig index 091e4b2668..4442234bd2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3244,6 +3244,10 @@ fn buildOutputType( .pdb_out_path = pdb_out_path, .error_limit = error_limit, .native_system_include_paths = create_module.native_system_include_paths, + // Any leftover C compilation args (such as -I) apply globally rather + // than to any particular module. This feature can greatly reduce CLI + // noise when --search-prefix and --mod are combined. + .global_cc_argv = try cc_argv.toOwnedSlice(arena), }) catch |err| switch (err) { error.LibCUnavailable => { const triple_name = try target.zigTriple(arena); @@ -3421,9 +3425,9 @@ const CreateModule = struct { c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile), rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile), - // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. - // This array is populated by zig cc frontend and then has to be converted to zig-style - // CPU features. + /// e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. + /// This array is populated by zig cc frontend and then has to be converted to zig-style + /// CPU features. llvm_m_args: std.ArrayListUnmanaged([]const u8), sysroot: ?[]const u8, lib_dirs: std.ArrayListUnmanaged([]const u8),