| ... | ... | @@ -345,6 +345,14 @@ pub const Builder = struct { |
| 345 | 345 | return self.allocator.dupe(u8, bytes) catch unreachable; |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | pub fn dupeStrings(self: *Builder, strings: []const []const u8) [][]u8 { |
| 349 | const array = self.allocator.alloc([]u8, strings.len) catch unreachable; |
| 350 | for (strings) |s, i| { |
| 351 | array[i] = self.dupe(s); |
| 352 | } |
| 353 | return array; |
| 354 | } |
| 355 | |
| 348 | 356 | pub fn dupePath(self: *Builder, bytes: []const u8) []u8 { |
| 349 | 357 | const the_copy = self.dupe(bytes); |
| 350 | 358 | for (the_copy) |*byte| { |
| ... | ... | @@ -490,7 +498,9 @@ pub const Builder = struct { |
| 490 | 498 | return error.InvalidStepName; |
| 491 | 499 | } |
| 492 | 500 | |
| 493 | | pub fn option(self: *Builder, comptime T: type, name: []const u8, description: []const u8) ?T { |
| 501 | pub fn option(self: *Builder, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T { |
| 502 | const name = self.dupe(name_raw); |
| 503 | const description = self.dupe(description_raw); |
| 494 | 504 | const type_id = comptime typeToEnum(T); |
| 495 | 505 | const available_option = AvailableOption{ |
| 496 | 506 | .name = name, |
| ... | ... | @@ -623,7 +633,7 @@ pub const Builder = struct { |
| 623 | 633 | const step_info = self.allocator.create(TopLevelStep) catch unreachable; |
| 624 | 634 | step_info.* = TopLevelStep{ |
| 625 | 635 | .step = Step.initNoOp(.TopLevel, name, self.allocator), |
| 626 | | .description = description, |
| 636 | .description = self.dupe(description), |
| 627 | 637 | }; |
| 628 | 638 | self.top_level_steps.append(step_info) catch unreachable; |
| 629 | 639 | return &step_info.step; |
| ... | ... | @@ -760,7 +770,9 @@ pub const Builder = struct { |
| 760 | 770 | return selected_target; |
| 761 | 771 | } |
| 762 | 772 | |
| 763 | | pub fn addUserInputOption(self: *Builder, name: []const u8, value: []const u8) !bool { |
| 773 | pub fn addUserInputOption(self: *Builder, name_raw: []const u8, value_raw: []const u8) !bool { |
| 774 | const name = self.dupe(name_raw); |
| 775 | const value = self.dupe(value_raw); |
| 764 | 776 | const gop = try self.user_input_options.getOrPut(name); |
| 765 | 777 | if (!gop.found_existing) { |
| 766 | 778 | gop.entry.value = UserInputOption{ |
| ... | ... | @@ -801,7 +813,8 @@ pub const Builder = struct { |
| 801 | 813 | return false; |
| 802 | 814 | } |
| 803 | 815 | |
| 804 | | pub fn addUserInputFlag(self: *Builder, name: []const u8) !bool { |
| 816 | pub fn addUserInputFlag(self: *Builder, name_raw: []const u8) !bool { |
| 817 | const name = self.dupe(name_raw); |
| 805 | 818 | const gop = try self.user_input_options.getOrPut(name); |
| 806 | 819 | if (!gop.found_existing) { |
| 807 | 820 | gop.entry.value = UserInputOption{ |
| ... | ... | @@ -993,10 +1006,11 @@ pub const Builder = struct { |
| 993 | 1006 | } |
| 994 | 1007 | |
| 995 | 1008 | pub fn pushInstalledFile(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) void { |
| 996 | | self.installed_files.append(InstalledFile{ |
| 1009 | const file = InstalledFile{ |
| 997 | 1010 | .dir = dir, |
| 998 | 1011 | .path = dest_rel_path, |
| 999 | | }) catch unreachable; |
| 1012 | }; |
| 1013 | self.installed_files.append(file.dupe(self)) catch unreachable; |
| 1000 | 1014 | } |
| 1001 | 1015 | |
| 1002 | 1016 | pub fn updateFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void { |
| ... | ... | @@ -1139,7 +1153,7 @@ pub const Builder = struct { |
| 1139 | 1153 | } |
| 1140 | 1154 | |
| 1141 | 1155 | pub fn addSearchPrefix(self: *Builder, search_prefix: []const u8) void { |
| 1142 | | self.search_prefixes.append(search_prefix) catch unreachable; |
| 1156 | self.search_prefixes.append(self.dupePath(search_prefix)) catch unreachable; |
| 1143 | 1157 | } |
| 1144 | 1158 | |
| 1145 | 1159 | pub fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { |
| ... | ... | @@ -1160,6 +1174,7 @@ pub const Builder = struct { |
| 1160 | 1174 | fn execPkgConfigList(self: *Builder, out_code: *u8) ![]const PkgConfigPkg { |
| 1161 | 1175 | const stdout = try self.execAllowFail(&[_][]const u8{ "pkg-config", "--list-all" }, out_code, .Ignore); |
| 1162 | 1176 | var list = ArrayList(PkgConfigPkg).init(self.allocator); |
| 1177 | errdefer list.deinit(); |
| 1163 | 1178 | var line_it = mem.tokenize(stdout, "\r\n"); |
| 1164 | 1179 | while (line_it.next()) |line| { |
| 1165 | 1180 | if (mem.trim(u8, line, " \t").len == 0) continue; |
| ... | ... | @@ -1169,7 +1184,7 @@ pub const Builder = struct { |
| 1169 | 1184 | .desc = tok_it.rest(), |
| 1170 | 1185 | }); |
| 1171 | 1186 | } |
| 1172 | | return list.items; |
| 1187 | return list.toOwnedSlice(); |
| 1173 | 1188 | } |
| 1174 | 1189 | |
| 1175 | 1190 | fn getPkgConfigList(self: *Builder) ![]const PkgConfigPkg { |
| ... | ... | @@ -1224,9 +1239,16 @@ pub const Pkg = struct { |
| 1224 | 1239 | dependencies: ?[]const Pkg = null, |
| 1225 | 1240 | }; |
| 1226 | 1241 | |
| 1227 | | const CSourceFile = struct { |
| 1242 | pub const CSourceFile = struct { |
| 1228 | 1243 | source: FileSource, |
| 1229 | 1244 | args: []const []const u8, |
| 1245 | |
| 1246 | fn dupe(self: CSourceFile, b: *Builder) CSourceFile { |
| 1247 | return .{ |
| 1248 | .source = self.source.dupe(b), |
| 1249 | .args = b.dupeStrings(self.args), |
| 1250 | }; |
| 1251 | } |
| 1230 | 1252 | }; |
| 1231 | 1253 | |
| 1232 | 1254 | const CSourceFiles = struct { |
| ... | ... | @@ -1268,6 +1290,17 @@ pub const FileSource = union(enum) { |
| 1268 | 1290 | .translate_c => |tc| tc.getOutputPath(), |
| 1269 | 1291 | }; |
| 1270 | 1292 | } |
| 1293 | |
| 1294 | pub fn dupe(self: FileSource, b: *Builder) FileSource { |
| 1295 | return switch (self) { |
| 1296 | .path => |p| .{ .path = b.dupe(p) }, |
| 1297 | .write_file => |wf| .{ .write_file = .{ |
| 1298 | .step = wf.step, |
| 1299 | .basename = b.dupe(wf.basename), |
| 1300 | } }, |
| 1301 | .translate_c => |tc| .{ .translate_c = tc }, |
| 1302 | }; |
| 1303 | } |
| 1271 | 1304 | }; |
| 1272 | 1305 | |
| 1273 | 1306 | const BuildOptionArtifactArg = struct { |
| ... | ... | @@ -1443,12 +1476,14 @@ pub const LibExeObjStep = struct { |
| 1443 | 1476 | |
| 1444 | 1477 | fn initExtraArgs( |
| 1445 | 1478 | builder: *Builder, |
| 1446 | | name: []const u8, |
| 1447 | | root_src: ?FileSource, |
| 1479 | name_raw: []const u8, |
| 1480 | root_src_raw: ?FileSource, |
| 1448 | 1481 | kind: Kind, |
| 1449 | 1482 | is_dynamic: bool, |
| 1450 | 1483 | ver: ?Version, |
| 1451 | 1484 | ) LibExeObjStep { |
| 1485 | const name = builder.dupe(name_raw); |
| 1486 | const root_src: ?FileSource = if (root_src_raw) |rsrc| rsrc.dupe(builder) else null; |
| 1452 | 1487 | if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) { |
| 1453 | 1488 | panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name}); |
| 1454 | 1489 | } |
| ... | ... | @@ -1585,12 +1620,12 @@ pub const LibExeObjStep = struct { |
| 1585 | 1620 | } |
| 1586 | 1621 | |
| 1587 | 1622 | pub fn setLinkerScriptPath(self: *LibExeObjStep, path: []const u8) void { |
| 1588 | | self.linker_script = path; |
| 1623 | self.linker_script = self.builder.dupePath(path); |
| 1589 | 1624 | } |
| 1590 | 1625 | |
| 1591 | 1626 | pub fn linkFramework(self: *LibExeObjStep, framework_name: []const u8) void { |
| 1592 | 1627 | assert(self.target.isDarwin()); |
| 1593 | | self.frameworks.put(framework_name) catch unreachable; |
| 1628 | self.frameworks.put(self.builder.dupe(framework_name)) catch unreachable; |
| 1594 | 1629 | } |
| 1595 | 1630 | |
| 1596 | 1631 | /// Returns whether the library, executable, or object depends on a particular system library. |
| ... | ... | @@ -1754,25 +1789,23 @@ pub const LibExeObjStep = struct { |
| 1754 | 1789 | |
| 1755 | 1790 | pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void { |
| 1756 | 1791 | assert(self.kind == Kind.Test); |
| 1757 | | self.name_prefix = text; |
| 1792 | self.name_prefix = self.builder.dupe(text); |
| 1758 | 1793 | } |
| 1759 | 1794 | |
| 1760 | 1795 | pub fn setFilter(self: *LibExeObjStep, text: ?[]const u8) void { |
| 1761 | 1796 | assert(self.kind == Kind.Test); |
| 1762 | | self.filter = text; |
| 1797 | self.filter = if (text) |t| self.builder.dupe(t) else null; |
| 1763 | 1798 | } |
| 1764 | 1799 | |
| 1765 | 1800 | /// Handy when you have many C/C++ source files and want them all to have the same flags. |
| 1766 | 1801 | pub fn addCSourceFiles(self: *LibExeObjStep, files: []const []const u8, flags: []const []const u8) void { |
| 1767 | 1802 | const c_source_files = self.builder.allocator.create(CSourceFiles) catch unreachable; |
| 1768 | 1803 | |
| 1769 | | const flags_copy = self.builder.allocator.alloc([]u8, flags.len) catch unreachable; |
| 1770 | | for (flags) |flag, i| { |
| 1771 | | flags_copy[i] = self.builder.dupe(flag); |
| 1772 | | } |
| 1804 | const files_copy = self.builder.dupeStrings(files); |
| 1805 | const flags_copy = self.builder.dupeStrings(flags); |
| 1773 | 1806 | |
| 1774 | 1807 | c_source_files.* = .{ |
| 1775 | | .files = files, |
| 1808 | .files = files_copy, |
| 1776 | 1809 | .flags = flags_copy, |
| 1777 | 1810 | }; |
| 1778 | 1811 | self.link_objects.append(LinkObject{ .CSourceFiles = c_source_files }) catch unreachable; |
| ... | ... | @@ -1787,14 +1820,7 @@ pub const LibExeObjStep = struct { |
| 1787 | 1820 | |
| 1788 | 1821 | pub fn addCSourceFileSource(self: *LibExeObjStep, source: CSourceFile) void { |
| 1789 | 1822 | const c_source_file = self.builder.allocator.create(CSourceFile) catch unreachable; |
| 1790 | | |
| 1791 | | const args_copy = self.builder.allocator.alloc([]u8, source.args.len) catch unreachable; |
| 1792 | | for (source.args) |arg, i| { |
| 1793 | | args_copy[i] = self.builder.dupe(arg); |
| 1794 | | } |
| 1795 | | |
| 1796 | | c_source_file.* = source; |
| 1797 | | c_source_file.args = args_copy; |
| 1823 | c_source_file.* = source.dupe(self.builder); |
| 1798 | 1824 | self.link_objects.append(LinkObject{ .CSourceFile = c_source_file }) catch unreachable; |
| 1799 | 1825 | } |
| 1800 | 1826 | |
| ... | ... | @@ -1811,15 +1837,15 @@ pub const LibExeObjStep = struct { |
| 1811 | 1837 | } |
| 1812 | 1838 | |
| 1813 | 1839 | pub fn overrideZigLibDir(self: *LibExeObjStep, dir_path: []const u8) void { |
| 1814 | | self.override_lib_dir = self.builder.dupe(dir_path); |
| 1840 | self.override_lib_dir = self.builder.dupePath(dir_path); |
| 1815 | 1841 | } |
| 1816 | 1842 | |
| 1817 | 1843 | pub fn setMainPkgPath(self: *LibExeObjStep, dir_path: []const u8) void { |
| 1818 | | self.main_pkg_path = dir_path; |
| 1844 | self.main_pkg_path = self.builder.dupePath(dir_path); |
| 1819 | 1845 | } |
| 1820 | 1846 | |
| 1821 | 1847 | pub fn setLibCFile(self: *LibExeObjStep, libc_file: ?[]const u8) void { |
| 1822 | | self.libc_file = libc_file; |
| 1848 | self.libc_file = if (libc_file) |f| self.builder.dupe(f) else null; |
| 1823 | 1849 | } |
| 1824 | 1850 | |
| 1825 | 1851 | /// Unless setOutputDir was called, this function must be called only in |
| ... | ... | @@ -1879,8 +1905,9 @@ pub const LibExeObjStep = struct { |
| 1879 | 1905 | } |
| 1880 | 1906 | |
| 1881 | 1907 | pub fn addAssemblyFileSource(self: *LibExeObjStep, source: FileSource) void { |
| 1882 | | self.link_objects.append(LinkObject{ .AssemblyFile = source }) catch unreachable; |
| 1883 | | source.addStepDependencies(&self.step); |
| 1908 | const source_duped = source.dupe(self.builder); |
| 1909 | self.link_objects.append(LinkObject{ .AssemblyFile = source_duped }) catch unreachable; |
| 1910 | source_duped.addStepDependencies(&self.step); |
| 1884 | 1911 | } |
| 1885 | 1912 | |
| 1886 | 1913 | pub fn addObjectFile(self: *LibExeObjStep, path: []const u8) void { |
| ... | ... | @@ -1977,7 +2004,7 @@ pub const LibExeObjStep = struct { |
| 1977 | 2004 | /// The value is the path in the cache dir. |
| 1978 | 2005 | /// Adds a dependency automatically. |
| 1979 | 2006 | pub fn addBuildOptionArtifact(self: *LibExeObjStep, name: []const u8, artifact: *LibExeObjStep) void { |
| 1980 | | self.build_options_artifact_args.append(.{ .name = name, .artifact = artifact }) catch unreachable; |
| 2007 | self.build_options_artifact_args.append(.{ .name = self.builder.dupe(name), .artifact = artifact }) catch unreachable; |
| 1981 | 2008 | self.step.dependOn(&artifact.step); |
| 1982 | 2009 | } |
| 1983 | 2010 | |
| ... | ... | @@ -2047,7 +2074,11 @@ pub const LibExeObjStep = struct { |
| 2047 | 2074 | |
| 2048 | 2075 | pub fn setExecCmd(self: *LibExeObjStep, args: []const ?[]const u8) void { |
| 2049 | 2076 | assert(self.kind == Kind.Test); |
| 2050 | | self.exec_cmd_args = args; |
| 2077 | const duped_args = self.builder.allocator.alloc(?[]u8, args.len) catch unreachable; |
| 2078 | for (args) |arg, i| { |
| 2079 | duped_args[i] = if (arg) |a| self.builder.dupe(a) else null; |
| 2080 | } |
| 2081 | self.exec_cmd_args = duped_args; |
| 2051 | 2082 | } |
| 2052 | 2083 | |
| 2053 | 2084 | fn linkLibraryOrObject(self: *LibExeObjStep, other: *LibExeObjStep) void { |
| ... | ... | @@ -2665,9 +2696,9 @@ pub const InstallFileStep = struct { |
| 2665 | 2696 | return InstallFileStep{ |
| 2666 | 2697 | .builder = builder, |
| 2667 | 2698 | .step = Step.init(.InstallFile, builder.fmt("install {s}", .{src_path}), builder.allocator, make), |
| 2668 | | .src_path = src_path, |
| 2669 | | .dir = dir, |
| 2670 | | .dest_rel_path = dest_rel_path, |
| 2699 | .src_path = builder.dupePath(src_path), |
| 2700 | .dir = dir.dupe(builder), |
| 2701 | .dest_rel_path = builder.dupePath(dest_rel_path), |
| 2671 | 2702 | }; |
| 2672 | 2703 | } |
| 2673 | 2704 | |
| ... | ... | @@ -2684,6 +2715,16 @@ pub const InstallDirectoryOptions = struct { |
| 2684 | 2715 | install_dir: InstallDir, |
| 2685 | 2716 | install_subdir: []const u8, |
| 2686 | 2717 | exclude_extensions: ?[]const []const u8 = null, |
| 2718 | |
| 2719 | fn dupe(self: InstallDirectoryOptions, b: *Builder) InstallDirectoryOptions { |
| 2720 | return .{ |
| 2721 | .source_dir = b.dupe(self.source_dir), |
| 2722 | .install_dir = self.install_dir.dupe(b), |
| 2723 | .install_subdir = b.dupe(self.install_subdir), |
| 2724 | .exclude_extensions = if (self.exclude_extensions) |extensions| |
| 2725 | b.dupeStrings(extensions) else null, |
| 2726 | }; |
| 2727 | } |
| 2687 | 2728 | }; |
| 2688 | 2729 | |
| 2689 | 2730 | pub const InstallDirStep = struct { |
| ... | ... | @@ -2699,7 +2740,7 @@ pub const InstallDirStep = struct { |
| 2699 | 2740 | return InstallDirStep{ |
| 2700 | 2741 | .builder = builder, |
| 2701 | 2742 | .step = Step.init(.InstallDir, builder.fmt("install {s}/", .{options.source_dir}), builder.allocator, make), |
| 2702 | | .options = options, |
| 2743 | .options = options.dupe(builder), |
| 2703 | 2744 | }; |
| 2704 | 2745 | } |
| 2705 | 2746 | |
| ... | ... | @@ -2735,7 +2776,7 @@ pub const LogStep = struct { |
| 2735 | 2776 | return LogStep{ |
| 2736 | 2777 | .builder = builder, |
| 2737 | 2778 | .step = Step.init(.Log, builder.fmt("log {s}", .{data}), builder.allocator, make), |
| 2738 | | .data = data, |
| 2779 | .data = builder.dupe(data), |
| 2739 | 2780 | }; |
| 2740 | 2781 | } |
| 2741 | 2782 | |
| ... | ... | @@ -2754,7 +2795,7 @@ pub const RemoveDirStep = struct { |
| 2754 | 2795 | return RemoveDirStep{ |
| 2755 | 2796 | .builder = builder, |
| 2756 | 2797 | .step = Step.init(.RemoveDir, builder.fmt("RemoveDir {s}", .{dir_path}), builder.allocator, make), |
| 2757 | | .dir_path = dir_path, |
| 2798 | .dir_path = builder.dupePath(dir_path), |
| 2758 | 2799 | }; |
| 2759 | 2800 | } |
| 2760 | 2801 | |
| ... | ... | @@ -2798,7 +2839,7 @@ pub const Step = struct { |
| 2798 | 2839 | pub fn init(id: Id, name: []const u8, allocator: *Allocator, makeFn: fn (*Step) anyerror!void) Step { |
| 2799 | 2840 | return Step{ |
| 2800 | 2841 | .id = id, |
| 2801 | | .name = name, |
| 2842 | .name = allocator.dupe(u8, name) catch unreachable, |
| 2802 | 2843 | .makeFn = makeFn, |
| 2803 | 2844 | .dependencies = ArrayList(*Step).init(allocator), |
| 2804 | 2845 | .loop_flag = false, |
| ... | ... | @@ -2905,11 +2946,28 @@ pub const InstallDir = union(enum) { |
| 2905 | 2946 | Header: void, |
| 2906 | 2947 | /// A path relative to the prefix |
| 2907 | 2948 | Custom: []const u8, |
| 2949 | |
| 2950 | fn dupe(self: InstallDir, builder: *Builder) InstallDir { |
| 2951 | if (self == .Custom) { |
| 2952 | // Written with this temporary to avoid RLS problems |
| 2953 | const duped_path = builder.dupe(self.Custom); |
| 2954 | return .{ .Custom = duped_path }; |
| 2955 | } else { |
| 2956 | return self; |
| 2957 | } |
| 2958 | } |
| 2908 | 2959 | }; |
| 2909 | 2960 | |
| 2910 | 2961 | pub const InstalledFile = struct { |
| 2911 | 2962 | dir: InstallDir, |
| 2912 | 2963 | path: []const u8, |
| 2964 | |
| 2965 | pub fn dupe(self: InstalledFile, builder: *Builder) InstalledFile { |
| 2966 | return .{ |
| 2967 | .dir = self.dir.dupe(builder), |
| 2968 | .path = builder.dupe(self.path), |
| 2969 | }; |
| 2970 | } |
| 2913 | 2971 | }; |
| 2914 | 2972 | |
| 2915 | 2973 | test "Builder.dupePkg()" { |