authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-20 03:22:02-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-01-20 03:22:02-08:00
log5c4cb60f4fab0f3c0fde43e04bbc4a03c92bef8e
tree642441862f41281202980b4c34ec32afbc9bd80d
parentb729a3f008304d464b431f8ac34ad16cde08ba7b
parent2dea37545046e1a7e472e52c8c110ee6f32842d7
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18622 from ziglang/zig-mod-edge-case

build system: better handle modules that do not have a zig root source file

3 files changed, 125 insertions(+), 63 deletions(-)

lib/std/Build/Step/Compile.zig+17-7
...@@ -1220,15 +1220,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1220,15 +1220,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1220 }1220 }
1221 }1221 }
12221222
1223 // The CLI assumes if it sees a --mod argument that it is a zig1223 // When the CLI sees a -M argument, it determines whether it
1224 // compilation unit. If there is no root source file, then this1224 // implies the existence of a Zig compilation unit based on
1225 // is not a zig compilation unit - it is perhaps a set of1225 // whether there is a root source file. If there is no root
1226 // linker objects, or C source files instead.1226 // source file, then this is not a zig compilation unit - it is
1227 // In such case, there will be only one module, so we can leave1227 // perhaps a set of linker objects, or C source files instead.
1228 // off the naming here.1228 // Linker objects are added to the CLI globally, while C source
1229 // files must have a module parent.
1229 if (module.root_source_file) |lp| {1230 if (module.root_source_file) |lp| {
1230 const src = lp.getPath2(module.owner, step);1231 const src = lp.getPath2(module.owner, step);
1231 try zig_args.appendSlice(&.{ "--mod", module_cli_name, src });1232 try zig_args.append(b.fmt("-M{s}={s}", .{ module_cli_name, src }));
1233 } else if (moduleNeedsCliArg(module)) {
1234 try zig_args.append(b.fmt("-M{s}", .{module_cli_name}));
1232 }1235 }
1233 }1236 }
1234 }1237 }
...@@ -1850,3 +1853,10 @@ pub fn rootModuleTarget(c: *Compile) std.Target {...@@ -1850,3 +1853,10 @@ pub fn rootModuleTarget(c: *Compile) std.Target {
1850 // The root module is always given a target, so we know this to be non-null.1853 // The root module is always given a target, so we know this to be non-null.
1851 return c.root_module.resolved_target.?.result;1854 return c.root_module.resolved_target.?.result;
1852}1855}
1856
1857fn moduleNeedsCliArg(mod: *const Module) bool {
1858 return for (mod.link_objects.items) |o| switch (o) {
1859 .c_source_file, .c_source_files, .assembly_file, .win32_resource_file => break true,
1860 else => continue,
1861 } else false;
1862}
src/Compilation.zig+1-3
...@@ -1172,7 +1172,7 @@ fn addModuleTableToCacheHash(...@@ -1172,7 +1172,7 @@ fn addModuleTableToCacheHash(
1172 hash.addOptionalBytes(mod.root.root_dir.path);1172 hash.addOptionalBytes(mod.root.root_dir.path);
1173 hash.addBytes(mod.root.sub_path);1173 hash.addBytes(mod.root.sub_path);
1174 },1174 },
1175 .files => |man| {1175 .files => |man| if (mod.root_src_path.len != 0) {
1176 const pkg_zig_file = try mod.root.joinString(arena, mod.root_src_path);1176 const pkg_zig_file = try mod.root.joinString(arena, mod.root_src_path);
1177 _ = try man.addFile(pkg_zig_file, null);1177 _ = try man.addFile(pkg_zig_file, null);
1178 },1178 },
...@@ -2469,8 +2469,6 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -2469,8 +2469,6 @@ fn addNonIncrementalStuffToCacheManifest(
2469 comptime assert(link_hash_implementation_version == 11);2469 comptime assert(link_hash_implementation_version == 11);
24702470
2471 if (comp.module) |mod| {2471 if (comp.module) |mod| {
2472 const main_zig_file = try mod.main_mod.root.joinString(arena, mod.main_mod.root_src_path);
2473 _ = try man.addFile(main_zig_file, null);
2474 try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.root_mod, mod.main_mod, .{ .files = man });2472 try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.root_mod, mod.main_mod, .{ .files = man });
24752473
2476 // Synchronize with other matching comments: ZigOnlyHashStuff2474 // Synchronize with other matching comments: ZigOnlyHashStuff
src/main.zig+107-53
...@@ -409,10 +409,10 @@ const usage_build_generic =...@@ -409,10 +409,10 @@ const usage_build_generic =
409 \\ --libc [file] Provide a file which specifies libc paths409 \\ --libc [file] Provide a file which specifies libc paths
410 \\ -x language Treat subsequent input files as having type <language>410 \\ -x language Treat subsequent input files as having type <language>
411 \\ --dep [[import=]name] Add an entry to the next module's import table411 \\ --dep [[import=]name] Add an entry to the next module's import table
412 \\ --mod [name] [src] Create a module based on the current per-module settings.412 \\ -M[name][=src] Create a module based on the current per-module settings.
413 \\ The first module is the main module.413 \\ The first module is the main module.
414 \\ "std" can be configured by leaving src blank.414 \\ "std" can be configured by omitting src
415 \\ After a --mod argument, per-module settings are reset.415 \\ After a -M argument, per-module settings are reset.
416 \\ --error-limit [num] Set the maximum amount of distinct error values416 \\ --error-limit [num] Set the maximum amount of distinct error values
417 \\ -fllvm Force using LLVM as the codegen backend417 \\ -fllvm Force using LLVM as the codegen backend
418 \\ -fno-llvm Prevent using LLVM as the codegen backend418 \\ -fno-llvm Prevent using LLVM as the codegen backend
...@@ -1040,56 +1040,39 @@ fn buildOutputType(...@@ -1040,56 +1040,39 @@ fn buildOutputType(
1040 .value = value,1040 .value = value,
1041 });1041 });
1042 } else if (mem.eql(u8, arg, "--mod")) {1042 } else if (mem.eql(u8, arg, "--mod")) {
1043 const mod_name = args_iter.nextOrFatal();1043 // deprecated, kept around until the next zig1.wasm update
1044 const root_src_orig = args_iter.nextOrFatal();1044 try handleModArg(
10451045 arena,
1046 const gop = try create_module.modules.getOrPut(arena, mod_name);1046 args_iter.nextOrFatal(),
10471047 args_iter.nextOrFatal(),
1048 if (gop.found_existing) {1048 &create_module,
1049 fatal("unable to add module '{s}': already exists as '{s}'", .{1049 &mod_opts,
1050 mod_name, gop.value_ptr.paths.root_src_path,1050 &cc_argv,
1051 });1051 &target_arch_os_abi,
1052 }1052 &target_mcpu,
10531053 &deps,
1054 // See duplicate logic: ModCreationGlobalFlags1054 &c_source_files_owner_index,
1055 create_module.opts.have_zcu = true;1055 &rc_source_files_owner_index,
1056 if (mod_opts.single_threaded == false)1056 &cssan,
1057 create_module.opts.any_non_single_threaded = true;1057 );
1058 if (mod_opts.sanitize_thread == true)1058 } else if (mem.startsWith(u8, arg, "-M")) {
1059 create_module.opts.any_sanitize_thread = true;1059 var it = mem.splitScalar(u8, arg["-M".len..], '=');
1060 if (mod_opts.unwind_tables == true)1060 const mod_name = it.next().?;
1061 create_module.opts.any_unwind_tables = true;1061 const root_src_orig = it.next();
1062 if (mod_opts.strip == false)1062 try handleModArg(
1063 create_module.opts.any_non_stripped = true;1063 arena,
1064 if (mod_opts.error_tracing == true)1064 mod_name,
1065 create_module.opts.any_error_tracing = true;1065 root_src_orig,
10661066 &create_module,
1067 const root_src = try introspect.resolvePath(arena, root_src_orig);1067 &mod_opts,
1068 gop.value_ptr.* = .{1068 &cc_argv,
1069 .paths = .{1069 &target_arch_os_abi,
1070 .root = .{1070 &target_mcpu,
1071 .root_dir = Cache.Directory.cwd(),1071 &deps,
1072 .sub_path = fs.path.dirname(root_src) orelse "",1072 &c_source_files_owner_index,
1073 },1073 &rc_source_files_owner_index,
1074 .root_src_path = fs.path.basename(root_src),1074 &cssan,
1075 },1075 );
1076 .cc_argv = try cc_argv.toOwnedSlice(arena),
1077 .inherited = mod_opts,
1078 .target_arch_os_abi = target_arch_os_abi,
1079 .target_mcpu = target_mcpu,
1080 .deps = try deps.toOwnedSlice(arena),
1081 .resolved = null,
1082 .c_source_files_start = c_source_files_owner_index,
1083 .c_source_files_end = create_module.c_source_files.items.len,
1084 .rc_source_files_start = rc_source_files_owner_index,
1085 .rc_source_files_end = create_module.rc_source_files.items.len,
1086 };
1087 cssan.reset();
1088 mod_opts = .{};
1089 target_arch_os_abi = null;
1090 target_mcpu = null;
1091 c_source_files_owner_index = create_module.c_source_files.items.len;
1092 rc_source_files_owner_index = create_module.rc_source_files.items.len;
1093 } else if (mem.eql(u8, arg, "--error-limit")) {1076 } else if (mem.eql(u8, arg, "--error-limit")) {
1094 const next_arg = args_iter.nextOrFatal();1077 const next_arg = args_iter.nextOrFatal();
1095 error_limit = std.fmt.parseUnsigned(Module.ErrorInt, next_arg, 0) catch |err| {1078 error_limit = std.fmt.parseUnsigned(Module.ErrorInt, next_arg, 0) catch |err| {
...@@ -7810,3 +7793,74 @@ fn parseImageBase(s: []const u8) u64 {...@@ -7810,3 +7793,74 @@ fn parseImageBase(s: []const u8) u64 {
7810 return std.fmt.parseUnsigned(u64, s, 0) catch |err|7793 return std.fmt.parseUnsigned(u64, s, 0) catch |err|
7811 fatal("unable to parse image base '{s}': {s}", .{ s, @errorName(err) });7794 fatal("unable to parse image base '{s}': {s}", .{ s, @errorName(err) });
7812}7795}
7796
7797fn handleModArg(
7798 arena: Allocator,
7799 mod_name: []const u8,
7800 opt_root_src_orig: ?[]const u8,
7801 create_module: *CreateModule,
7802 mod_opts: *Package.Module.CreateOptions.Inherited,
7803 cc_argv: *std.ArrayListUnmanaged([]const u8),
7804 target_arch_os_abi: *?[]const u8,
7805 target_mcpu: *?[]const u8,
7806 deps: *std.ArrayListUnmanaged(CliModule.Dep),
7807 c_source_files_owner_index: *usize,
7808 rc_source_files_owner_index: *usize,
7809 cssan: *ClangSearchSanitizer,
7810) !void {
7811 const gop = try create_module.modules.getOrPut(arena, mod_name);
7812
7813 if (gop.found_existing) {
7814 fatal("unable to add module '{s}': already exists as '{s}'", .{
7815 mod_name, gop.value_ptr.paths.root_src_path,
7816 });
7817 }
7818
7819 // See duplicate logic: ModCreationGlobalFlags
7820 if (mod_opts.single_threaded == false)
7821 create_module.opts.any_non_single_threaded = true;
7822 if (mod_opts.sanitize_thread == true)
7823 create_module.opts.any_sanitize_thread = true;
7824 if (mod_opts.unwind_tables == true)
7825 create_module.opts.any_unwind_tables = true;
7826 if (mod_opts.strip == false)
7827 create_module.opts.any_non_stripped = true;
7828 if (mod_opts.error_tracing == true)
7829 create_module.opts.any_error_tracing = true;
7830
7831 gop.value_ptr.* = .{
7832 .paths = p: {
7833 if (opt_root_src_orig) |root_src_orig| {
7834 create_module.opts.have_zcu = true;
7835 const root_src = try introspect.resolvePath(arena, root_src_orig);
7836 break :p .{
7837 .root = .{
7838 .root_dir = Cache.Directory.cwd(),
7839 .sub_path = fs.path.dirname(root_src) orelse "",
7840 },
7841 .root_src_path = fs.path.basename(root_src),
7842 };
7843 }
7844 break :p .{
7845 .root = .{ .root_dir = Cache.Directory.cwd() },
7846 .root_src_path = "",
7847 };
7848 },
7849 .cc_argv = try cc_argv.toOwnedSlice(arena),
7850 .inherited = mod_opts.*,
7851 .target_arch_os_abi = target_arch_os_abi.*,
7852 .target_mcpu = target_mcpu.*,
7853 .deps = try deps.toOwnedSlice(arena),
7854 .resolved = null,
7855 .c_source_files_start = c_source_files_owner_index.*,
7856 .c_source_files_end = create_module.c_source_files.items.len,
7857 .rc_source_files_start = rc_source_files_owner_index.*,
7858 .rc_source_files_end = create_module.rc_source_files.items.len,
7859 };
7860 cssan.reset();
7861 mod_opts.* = .{};
7862 target_arch_os_abi.* = null;
7863 target_mcpu.* = null;
7864 c_source_files_owner_index.* = create_module.c_source_files.items.len;
7865 rc_source_files_owner_index.* = create_module.rc_source_files.items.len;
7866}