| ... | @@ -831,81 +831,42 @@ pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void { | ... | @@ -831,81 +831,42 @@ pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void { |
| 831 | self.exec_cmd_args = duped_args; | 831 | self.exec_cmd_args = duped_args; |
| 832 | } | 832 | } |
| 833 | | 833 | |
| 834 | fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void { | 834 | const CliNamedModules = struct { |
| 835 | const b = cs.step.owner; | 835 | modules: std.AutoArrayHashMapUnmanaged(*Module, void), |
| 836 | // First, traverse the whole dependency graph and give every module a | 836 | names: std.StringArrayHashMapUnmanaged(void), |
| 837 | // unique name, ideally one named after what it's called somewhere in the | 837 | |
| 838 | // graph. It will help here to have both a mapping from module to name and | 838 | /// Traverse the whole dependency graph and give every module a unique |
| 839 | // a set of all the currently-used names. | 839 | /// name, ideally one named after what it's called somewhere in the graph. |
| 840 | var mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8) = .{}; | 840 | /// It will help here to have both a mapping from module to name and a set |
| 841 | var names = std.StringHashMap(void).init(b.allocator); | 841 | /// of all the currently-used names. |
| 842 | | 842 | fn init(arena: Allocator, root_module: *Module) Allocator.Error!CliNamedModules { |
| 843 | { | 843 | var self: CliNamedModules = .{ |
| 844 | var it = cs.root_module.iterateDependencies(null, false); | 844 | .modules = .{}, |
| 845 | _ = it.next(); // Skip over the root module. | 845 | .names = .{}, |
| | 846 | }; |
| | 847 | var it = root_module.iterateDependencies(null, false); |
| | 848 | { |
| | 849 | const item = it.next().?; |
| | 850 | assert(root_module == item.module); |
| | 851 | try self.modules.put(arena, root_module, {}); |
| | 852 | try self.names.put(arena, "root", {}); |
| | 853 | } |
| 846 | while (it.next()) |item| { | 854 | while (it.next()) |item| { |
| 847 | // While we're traversing the root dependencies, let's make sure that no module names | | |
| 848 | // have colons in them, since the CLI forbids it. We handle this for transitive | | |
| 849 | // dependencies further down. | | |
| 850 | if (std.mem.indexOfScalar(u8, item.name, ':') != null) { | | |
| 851 | return cs.step.fail("module '{s}' contains a colon", .{item.name}); | | |
| 852 | } | | |
| 853 | | | |
| 854 | var name = item.name; | 855 | var name = item.name; |
| 855 | var n: usize = 0; | 856 | var n: usize = 0; |
| 856 | while (names.contains(name)) { | 857 | while (true) { |
| 857 | name = b.fmt("{s}{d}", .{ item.name, n }); | 858 | const gop = try self.names.getOrPut(arena, name); |
| | 859 | if (!gop.found_existing) { |
| | 860 | try self.modules.putNoClobber(arena, item.module, {}); |
| | 861 | break; |
| | 862 | } |
| | 863 | name = try std.fmt.allocPrint(arena, "{s}{d}", .{ item.name, n }); |
| 858 | n += 1; | 864 | n += 1; |
| 859 | } | 865 | } |
| 860 | | | |
| 861 | try mod_names.put(b.allocator, item.module, name); | | |
| 862 | try names.put(name, {}); | | |
| 863 | } | 866 | } |
| | 867 | return self; |
| 864 | } | 868 | } |
| 865 | | 869 | }; |
| 866 | // Since the module names given to the CLI are based off of the exposed | | |
| 867 | // names, we already know that none of the CLI names have colons in them, | | |
| 868 | // so there's no need to check that explicitly. | | |
| 869 | | | |
| 870 | // Every module in the graph is now named; output their definitions | | |
| 871 | for (mod_names.keys(), mod_names.values()) |mod, name| { | | |
| 872 | const root_src = mod.root_source_file orelse continue; | | |
| 873 | const deps_str = try constructDepString(b.allocator, mod_names, mod.import_table); | | |
| 874 | const src = root_src.getPath2(mod.owner, &cs.step); | | |
| 875 | try zig_args.append("--mod"); | | |
| 876 | try zig_args.append(b.fmt("{s}:{s}:{s}", .{ name, deps_str, src })); | | |
| 877 | } | | |
| 878 | | | |
| 879 | // Lastly, output the root dependencies | | |
| 880 | const deps_str = try constructDepString(b.allocator, mod_names, cs.root_module.import_table); | | |
| 881 | if (deps_str.len > 0) { | | |
| 882 | try zig_args.append("--deps"); | | |
| 883 | try zig_args.append(deps_str); | | |
| 884 | } | | |
| 885 | } | | |
| 886 | | | |
| 887 | fn constructDepString( | | |
| 888 | allocator: std.mem.Allocator, | | |
| 889 | mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8), | | |
| 890 | deps: std.StringArrayHashMapUnmanaged(*Module), | | |
| 891 | ) ![]const u8 { | | |
| 892 | var deps_str = std.ArrayList(u8).init(allocator); | | |
| 893 | var it = deps.iterator(); | | |
| 894 | while (it.next()) |kv| { | | |
| 895 | const expose = kv.key_ptr.*; | | |
| 896 | const name = mod_names.get(kv.value_ptr.*).?; | | |
| 897 | if (std.mem.eql(u8, expose, name)) { | | |
| 898 | try deps_str.writer().print("{s},", .{name}); | | |
| 899 | } else { | | |
| 900 | try deps_str.writer().print("{s}={s},", .{ expose, name }); | | |
| 901 | } | | |
| 902 | } | | |
| 903 | if (deps_str.items.len > 0) { | | |
| 904 | return deps_str.items[0 .. deps_str.items.len - 1]; // omit trailing comma | | |
| 905 | } else { | | |
| 906 | return ""; | | |
| 907 | } | | |
| 908 | } | | |
| 909 | | 870 | |
| 910 | fn getGeneratedFilePath(self: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) []const u8 { | 871 | fn getGeneratedFilePath(self: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) []const u8 { |
| 911 | const maybe_path: ?*GeneratedFile = @field(self, tag_name); | 872 | const maybe_path: ?*GeneratedFile = @field(self, tag_name); |
| ... | @@ -991,14 +952,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -991,14 +952,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 991 | var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic; | 952 | var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic; |
| 992 | // Track the number of positional arguments so that a nice error can be | 953 | // Track the number of positional arguments so that a nice error can be |
| 993 | // emitted if there is nothing to link. | 954 | // emitted if there is nothing to link. |
| 994 | var total_linker_objects: usize = 0; | 955 | var total_linker_objects: usize = @intFromBool(self.root_module.root_source_file != null); |
| 995 | | | |
| 996 | if (self.root_module.root_source_file) |lp| { | | |
| 997 | try zig_args.append(lp.getPath(b)); | | |
| 998 | total_linker_objects += 1; | | |
| 999 | } | | |
| 1000 | | | |
| 1001 | try self.root_module.appendZigProcessFlags(&zig_args, step); | | |
| 1002 | | 956 | |
| 1003 | { | 957 | { |
| 1004 | // Fully recursive iteration including dynamic libraries to detect | 958 | // Fully recursive iteration including dynamic libraries to detect |
| ... | @@ -1010,6 +964,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1010,6 +964,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1010 | } | 964 | } |
| 1011 | } | 965 | } |
| 1012 | | 966 | |
| | 967 | var cli_named_modules = try CliNamedModules.init(b.allocator, &self.root_module); |
| | 968 | |
| 1013 | // For this loop, don't chase dynamic libraries because their link | 969 | // For this loop, don't chase dynamic libraries because their link |
| 1014 | // objects are already linked. | 970 | // objects are already linked. |
| 1015 | var it = self.root_module.iterateDependencies(self, false); | 971 | var it = self.root_module.iterateDependencies(self, false); |
| ... | @@ -1233,6 +1189,38 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1233,6 +1189,38 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1233 | }, | 1189 | }, |
| 1234 | } | 1190 | } |
| 1235 | } | 1191 | } |
| | 1192 | |
| | 1193 | // We need to emit the --mod argument here so that the above link objects |
| | 1194 | // have the correct parent module, but only if the module is part of |
| | 1195 | // this compilation. |
| | 1196 | if (cli_named_modules.modules.getIndex(module)) |module_cli_index| { |
| | 1197 | const module_cli_name = cli_named_modules.names.keys()[module_cli_index]; |
| | 1198 | try module.appendZigProcessFlags(&zig_args, step); |
| | 1199 | |
| | 1200 | // --dep arguments |
| | 1201 | try zig_args.ensureUnusedCapacity(module.import_table.count() * 2); |
| | 1202 | for (module.import_table.keys(), module.import_table.values()) |name, dep| { |
| | 1203 | const dep_index = cli_named_modules.modules.getIndex(dep).?; |
| | 1204 | const dep_cli_name = cli_named_modules.names.keys()[dep_index]; |
| | 1205 | zig_args.appendAssumeCapacity("--dep"); |
| | 1206 | if (std.mem.eql(u8, dep_cli_name, name)) { |
| | 1207 | zig_args.appendAssumeCapacity(dep_cli_name); |
| | 1208 | } else { |
| | 1209 | zig_args.appendAssumeCapacity(b.fmt("{s}={s}", .{ name, dep_cli_name })); |
| | 1210 | } |
| | 1211 | } |
| | 1212 | |
| | 1213 | // The CLI assumes if it sees a --mod argument that it is a zig |
| | 1214 | // compilation unit. If there is no root source file, then this |
| | 1215 | // is not a zig compilation unit - it is perhaps a set of |
| | 1216 | // linker objects, or C source files instead. |
| | 1217 | // In such case, there will be only one module, so we can leave |
| | 1218 | // off the naming here. |
| | 1219 | if (module.root_source_file) |lp| { |
| | 1220 | const src = lp.getPath2(b, step); |
| | 1221 | try zig_args.appendSlice(&.{ "--mod", module_cli_name, src }); |
| | 1222 | } |
| | 1223 | } |
| 1236 | } | 1224 | } |
| 1237 | | 1225 | |
| 1238 | if (total_linker_objects == 0) { | 1226 | if (total_linker_objects == 0) { |
| ... | @@ -1470,8 +1458,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1470,8 +1458,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1470 | } | 1458 | } |
| 1471 | } | 1459 | } |
| 1472 | | 1460 | |
| 1473 | try self.appendModuleArgs(&zig_args); | | |
| 1474 | | | |
| 1475 | if (b.sysroot) |sysroot| { | 1461 | if (b.sysroot) |sysroot| { |
| 1476 | try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot }); | 1462 | try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot }); |
| 1477 | } | 1463 | } |