| author | |
| committer | |
| log | 693b12f8e1c1d99d33c01961c1fdc972a5255eb6 |
| tree | da0106bbc81d8830be509ffda0d7c0107a7400db |
| parent | 4009e0d2b1ac5b0a9a0caff676d5c73ae18c6e9e |
New API introduced: std.Build.addModule
This function exposes a zig module with the given name, which can be
used by packages that depend on this one via std.Build.Dependency.module.
std.Build.Pkg and related functionality is deleted. Every use case has a
straightforward upgrade path using the new Module struct.
std.Build.OptionsStep.getPackage is replaced by
std.Build.OptionsStep.createModule.
std.Build.CompileStep.addPackagePath is replaced by
std.Build.CompileStep.addAnonymousModule.
This partially addresses #14307 by renaming some of the instances of
"package" to "module".
Closes #142784 files changed, 106 insertions(+), 144 deletions(-)
lib/std/Build.zig+60-70| ... | ... | @@ -109,6 +109,8 @@ host: NativeTargetInfo, |
| 109 | 109 | |
| 110 | 110 | dep_prefix: []const u8 = "", |
| 111 | 111 | |
| 112 | modules: std.StringArrayHashMap(*Module), | |
| 113 | ||
| 112 | 114 | pub const ExecError = error{ |
| 113 | 115 | ReadFailure, |
| 114 | 116 | ExitCodeFailure, |
| ... | ... | @@ -232,6 +234,7 @@ pub fn create( |
| 232 | 234 | .install_path = undefined, |
| 233 | 235 | .args = null, |
| 234 | 236 | .host = host, |
| 237 | .modules = std.StringArrayHashMap(*Module).init(allocator), | |
| 235 | 238 | }; |
| 236 | 239 | try self.top_level_steps.append(&self.install_tls); |
| 237 | 240 | try self.top_level_steps.append(&self.uninstall_tls); |
| ... | ... | @@ -305,6 +308,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: []const u8) |
| 305 | 308 | .glibc_runtimes_dir = parent.glibc_runtimes_dir, |
| 306 | 309 | .host = parent.host, |
| 307 | 310 | .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }), |
| 311 | .modules = std.StringArrayHashMap(*Module).init(allocator), | |
| 308 | 312 | }; |
| 309 | 313 | try child.top_level_steps.append(&child.install_tls); |
| 310 | 314 | try child.top_level_steps.append(&child.uninstall_tls); |
| ... | ... | @@ -539,6 +543,49 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *CompileStep { |
| 539 | 543 | return obj_step; |
| 540 | 544 | } |
| 541 | 545 | |
| 546 | pub const AddModuleOptions = struct { | |
| 547 | name: []const u8, | |
| 548 | source_file: FileSource, | |
| 549 | dependencies: []const ModuleDependency = &.{}, | |
| 550 | }; | |
| 551 | ||
| 552 | pub fn addModule(b: *Build, options: AddModuleOptions) void { | |
| 553 | b.modules.put(b.dupe(options.name), b.createModule(.{ | |
| 554 | .source_file = options.source_file, | |
| 555 | .dependencies = options.dependencies, | |
| 556 | })) catch @panic("OOM"); | |
| 557 | } | |
| 558 | ||
| 559 | pub const ModuleDependency = struct { | |
| 560 | name: []const u8, | |
| 561 | module: *Module, | |
| 562 | }; | |
| 563 | ||
| 564 | pub const CreateModuleOptions = struct { | |
| 565 | source_file: FileSource, | |
| 566 | dependencies: []const ModuleDependency = &.{}, | |
| 567 | }; | |
| 568 | ||
| 569 | /// Prefer to use `addModule` which will make the module available to other | |
| 570 | /// packages which depend on this package. | |
| 571 | pub fn createModule(b: *Build, options: CreateModuleOptions) *Module { | |
| 572 | const module = b.allocator.create(Module) catch @panic("OOM"); | |
| 573 | module.* = .{ | |
| 574 | .builder = b, | |
| 575 | .source_file = options.source_file, | |
| 576 | .dependencies = moduleDependenciesToArrayHashMap(b.allocator, options.dependencies), | |
| 577 | }; | |
| 578 | return module; | |
| 579 | } | |
| 580 | ||
| 581 | fn moduleDependenciesToArrayHashMap(arena: Allocator, deps: []const ModuleDependency) std.StringArrayHashMap(*Module) { | |
| 582 | var result = std.StringArrayHashMap(*Module).init(arena); | |
| 583 | for (deps) |dep| { | |
| 584 | result.put(dep.name, dep.module) catch @panic("OOM"); | |
| 585 | } | |
| 586 | return result; | |
| 587 | } | |
| 588 | ||
| 542 | 589 | /// Initializes a RunStep with argv, which must at least have the path to the |
| 543 | 590 | /// executable. More command line arguments can be added with `addArg`, |
| 544 | 591 | /// `addArgs`, and `addArtifactArg`. |
| ... | ... | @@ -588,24 +635,6 @@ pub fn dupePath(self: *Build, bytes: []const u8) []u8 { |
| 588 | 635 | return the_copy; |
| 589 | 636 | } |
| 590 | 637 | |
| 591 | /// Duplicates a package recursively. | |
| 592 | pub fn dupePkg(self: *Build, package: Pkg) Pkg { | |
| 593 | var the_copy = Pkg{ | |
| 594 | .name = self.dupe(package.name), | |
| 595 | .source = package.source.dupe(self), | |
| 596 | }; | |
| 597 | ||
| 598 | if (package.dependencies) |dependencies| { | |
| 599 | const new_dependencies = self.allocator.alloc(Pkg, dependencies.len) catch @panic("OOM"); | |
| 600 | the_copy.dependencies = new_dependencies; | |
| 601 | ||
| 602 | for (dependencies) |dep_package, i| { | |
| 603 | new_dependencies[i] = self.dupePkg(dep_package); | |
| 604 | } | |
| 605 | } | |
| 606 | return the_copy; | |
| 607 | } | |
| 608 | ||
| 609 | 638 | pub fn addWriteFile(self: *Build, file_path: []const u8, data: []const u8) *WriteFileStep { |
| 610 | 639 | const write_file_step = self.addWriteFiles(); |
| 611 | 640 | write_file_step.add(file_path, data); |
| ... | ... | @@ -1479,6 +1508,12 @@ pub const Dependency = struct { |
| 1479 | 1508 | panic("unable to find artifact '{s}'", .{name}); |
| 1480 | 1509 | }; |
| 1481 | 1510 | } |
| 1511 | ||
| 1512 | pub fn module(d: *Dependency, name: []const u8) *Module { | |
| 1513 | return d.builder.modules.get(name) orelse { | |
| 1514 | panic("unable to find module '{s}'", .{name}); | |
| 1515 | }; | |
| 1516 | } | |
| 1482 | 1517 | }; |
| 1483 | 1518 | |
| 1484 | 1519 | pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency { |
| ... | ... | @@ -1548,10 +1583,13 @@ test "builder.findProgram compiles" { |
| 1548 | 1583 | _ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null; |
| 1549 | 1584 | } |
| 1550 | 1585 | |
| 1551 | pub const Pkg = struct { | |
| 1552 | name: []const u8, | |
| 1553 | source: FileSource, | |
| 1554 | dependencies: ?[]const Pkg = null, | |
| 1586 | pub const Module = struct { | |
| 1587 | builder: *Build, | |
| 1588 | /// This could either be a generated file, in which case the module | |
| 1589 | /// contains exactly one file, or it could be a path to the root source | |
| 1590 | /// file of directory of files which constitute the module. | |
| 1591 | source_file: FileSource, | |
| 1592 | dependencies: std.StringArrayHashMap(*Module), | |
| 1555 | 1593 | }; |
| 1556 | 1594 | |
| 1557 | 1595 | /// A file that is generated by a build step. |
| ... | ... | @@ -1713,54 +1751,6 @@ pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 { |
| 1713 | 1751 | } |
| 1714 | 1752 | } |
| 1715 | 1753 | |
| 1716 | test "dupePkg()" { | |
| 1717 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 1718 | ||
| 1719 | var arena = std.heap.ArenaAllocator.init(std.testing.allocator); | |
| 1720 | defer arena.deinit(); | |
| 1721 | ||
| 1722 | const host = try NativeTargetInfo.detect(.{}); | |
| 1723 | ||
| 1724 | var builder = try Build.create( | |
| 1725 | arena.allocator(), | |
| 1726 | "test", | |
| 1727 | "test", | |
| 1728 | "test", | |
| 1729 | "test", | |
| 1730 | host, | |
| 1731 | ); | |
| 1732 | defer builder.destroy(); | |
| 1733 | ||
| 1734 | var pkg_dep = Pkg{ | |
| 1735 | .name = "pkg_dep", | |
| 1736 | .source = .{ .path = "/not/a/pkg_dep.zig" }, | |
| 1737 | }; | |
| 1738 | var pkg_top = Pkg{ | |
| 1739 | .name = "pkg_top", | |
| 1740 | .source = .{ .path = "/not/a/pkg_top.zig" }, | |
| 1741 | .dependencies = &[_]Pkg{pkg_dep}, | |
| 1742 | }; | |
| 1743 | const duped = builder.dupePkg(pkg_top); | |
| 1744 | ||
| 1745 | const original_deps = pkg_top.dependencies.?; | |
| 1746 | const dupe_deps = duped.dependencies.?; | |
| 1747 | ||
| 1748 | // probably the same top level package details | |
| 1749 | try std.testing.expectEqualStrings(pkg_top.name, duped.name); | |
| 1750 | ||
| 1751 | // probably the same dependencies | |
| 1752 | try std.testing.expectEqual(original_deps.len, dupe_deps.len); | |
| 1753 | try std.testing.expectEqual(original_deps[0].name, pkg_dep.name); | |
| 1754 | ||
| 1755 | // could segfault otherwise if pointers in duplicated package's fields are | |
| 1756 | // the same as those in stack allocated package's fields | |
| 1757 | try std.testing.expect(dupe_deps.ptr != original_deps.ptr); | |
| 1758 | try std.testing.expect(duped.name.ptr != pkg_top.name.ptr); | |
| 1759 | try std.testing.expect(duped.source.path.ptr != pkg_top.source.path.ptr); | |
| 1760 | try std.testing.expect(dupe_deps[0].name.ptr != pkg_dep.name.ptr); | |
| 1761 | try std.testing.expect(dupe_deps[0].source.path.ptr != pkg_dep.source.path.ptr); | |
| 1762 | } | |
| 1763 | ||
| 1764 | 1754 | test { |
| 1765 | 1755 | _ = CheckFileStep; |
| 1766 | 1756 | _ = CheckObjectStep; |
lib/std/Build/CompileStep.zig+40-71| ... | ... | @@ -16,7 +16,7 @@ const FileSource = std.Build.FileSource; |
| 16 | 16 | const PkgConfigPkg = std.Build.PkgConfigPkg; |
| 17 | 17 | const PkgConfigError = std.Build.PkgConfigError; |
| 18 | 18 | const ExecError = std.Build.ExecError; |
| 19 | const Pkg = std.Build.Pkg; | |
| 19 | const Module = std.Build.Module; | |
| 20 | 20 | const VcpkgRoot = std.Build.VcpkgRoot; |
| 21 | 21 | const InstallDir = std.Build.InstallDir; |
| 22 | 22 | const InstallArtifactStep = std.Build.InstallArtifactStep; |
| ... | ... | @@ -99,7 +99,7 @@ root_src: ?FileSource, |
| 99 | 99 | out_h_filename: []const u8, |
| 100 | 100 | out_lib_filename: []const u8, |
| 101 | 101 | out_pdb_filename: []const u8, |
| 102 | packages: ArrayList(Pkg), | |
| 102 | modules: std.StringArrayHashMap(*Module), | |
| 103 | 103 | |
| 104 | 104 | object_src: []const u8, |
| 105 | 105 | |
| ... | ... | @@ -334,7 +334,7 @@ pub fn create(builder: *std.Build, options: Options) *CompileStep { |
| 334 | 334 | .out_pdb_filename = builder.fmt("{s}.pdb", .{name}), |
| 335 | 335 | .major_only_filename = null, |
| 336 | 336 | .name_only_filename = null, |
| 337 | .packages = ArrayList(Pkg).init(builder.allocator), | |
| 337 | .modules = std.StringArrayHashMap(*Module).init(builder.allocator), | |
| 338 | 338 | .include_dirs = ArrayList(IncludeDir).init(builder.allocator), |
| 339 | 339 | .link_objects = ArrayList(LinkObject).init(builder.allocator), |
| 340 | 340 | .c_macros = ArrayList([]const u8).init(builder.allocator), |
| ... | ... | @@ -946,29 +946,29 @@ pub fn addFrameworkPath(self: *CompileStep, dir_path: []const u8) void { |
| 946 | 946 | self.framework_dirs.append(self.builder.dupe(dir_path)) catch @panic("OOM"); |
| 947 | 947 | } |
| 948 | 948 | |
| 949 | pub fn addPackage(self: *CompileStep, package: Pkg) void { | |
| 950 | self.packages.append(self.builder.dupePkg(package)) catch @panic("OOM"); | |
| 951 | self.addRecursiveBuildDeps(package); | |
| 949 | /// Adds a module to be used with `@import` and exposing it in the current | |
| 950 | /// package's module table using `name`. | |
| 951 | pub fn addModule(cs: *CompileStep, name: []const u8, module: *Module) void { | |
| 952 | cs.modules.put(cs.builder.dupe(name), module) catch @panic("OOM"); | |
| 953 | cs.addRecursiveBuildDeps(module); | |
| 952 | 954 | } |
| 953 | 955 | |
| 954 | pub fn addOptions(self: *CompileStep, package_name: []const u8, options: *OptionsStep) void { | |
| 955 | self.addPackage(options.getPackage(package_name)); | |
| 956 | /// Adds a module to be used with `@import` without exposing it in the current | |
| 957 | /// package's module table. | |
| 958 | pub fn addAnonymousModule(cs: *CompileStep, name: []const u8, options: std.Build.CreateModuleOptions) void { | |
| 959 | const module = cs.builder.createModule(options); | |
| 960 | return addModule(cs, name, module); | |
| 956 | 961 | } |
| 957 | 962 | |
| 958 | fn addRecursiveBuildDeps(self: *CompileStep, package: Pkg) void { | |
| 959 | package.source.addStepDependencies(&self.step); | |
| 960 | if (package.dependencies) |deps| { | |
| 961 | for (deps) |dep| { | |
| 962 | self.addRecursiveBuildDeps(dep); | |
| 963 | } | |
| 964 | } | |
| 963 | pub fn addOptions(cs: *CompileStep, module_name: []const u8, options: *OptionsStep) void { | |
| 964 | addModule(cs, module_name, options.createModule()); | |
| 965 | 965 | } |
| 966 | 966 | |
| 967 | pub fn addPackagePath(self: *CompileStep, name: []const u8, pkg_index_path: []const u8) void { | |
| 968 | self.addPackage(Pkg{ | |
| 969 | .name = self.builder.dupe(name), | |
| 970 | .source = .{ .path = self.builder.dupe(pkg_index_path) }, | |
| 971 | }); | |
| 967 | fn addRecursiveBuildDeps(cs: *CompileStep, module: *Module) void { | |
| 968 | module.source_file.addStepDependencies(&cs.step); | |
| 969 | for (module.dependencies.values()) |dep| { | |
| 970 | cs.addRecursiveBuildDeps(dep); | |
| 971 | } | |
| 972 | 972 | } |
| 973 | 973 | |
| 974 | 974 | /// If Vcpkg was found on the system, it will be added to include and lib |
| ... | ... | @@ -1023,16 +1023,21 @@ fn linkLibraryOrObject(self: *CompileStep, other: *CompileStep) void { |
| 1023 | 1023 | self.include_dirs.append(.{ .other_step = other }) catch @panic("OOM"); |
| 1024 | 1024 | } |
| 1025 | 1025 | |
| 1026 | fn makePackageCmd(self: *CompileStep, pkg: Pkg, zig_args: *ArrayList([]const u8)) error{OutOfMemory}!void { | |
| 1027 | const builder = self.builder; | |
| 1028 | ||
| 1026 | fn appendModuleArgs( | |
| 1027 | cs: *CompileStep, | |
| 1028 | zig_args: *ArrayList([]const u8), | |
| 1029 | name: []const u8, | |
| 1030 | module: *Module, | |
| 1031 | ) error{OutOfMemory}!void { | |
| 1029 | 1032 | try zig_args.append("--pkg-begin"); |
| 1030 | try zig_args.append(pkg.name); | |
| 1031 | try zig_args.append(builder.pathFromRoot(pkg.source.getPath(self.builder))); | |
| 1032 | ||
| 1033 | if (pkg.dependencies) |dependencies| { | |
| 1034 | for (dependencies) |sub_pkg| { | |
| 1035 | try self.makePackageCmd(sub_pkg, zig_args); | |
| 1033 | try zig_args.append(name); | |
| 1034 | try zig_args.append(module.builder.pathFromRoot(module.source_file.getPath(module.builder))); | |
| 1035 | ||
| 1036 | { | |
| 1037 | const keys = module.dependencies.keys(); | |
| 1038 | for (module.dependencies.values()) |sub_module, i| { | |
| 1039 | const sub_name = keys[i]; | |
| 1040 | try cs.appendModuleArgs(zig_args, sub_name, sub_module); | |
| 1036 | 1041 | } |
| 1037 | 1042 | } |
| 1038 | 1043 | |
| ... | ... | @@ -1563,8 +1568,12 @@ fn make(step: *Step) !void { |
| 1563 | 1568 | try zig_args.append("--test-no-exec"); |
| 1564 | 1569 | } |
| 1565 | 1570 | |
| 1566 | for (self.packages.items) |pkg| { | |
| 1567 | try self.makePackageCmd(pkg, &zig_args); | |
| 1571 | { | |
| 1572 | const keys = self.modules.keys(); | |
| 1573 | for (self.modules.values()) |module, i| { | |
| 1574 | const name = keys[i]; | |
| 1575 | try self.appendModuleArgs(&zig_args, name, module); | |
| 1576 | } | |
| 1568 | 1577 | } |
| 1569 | 1578 | |
| 1570 | 1579 | for (self.include_dirs.items) |include_dir| { |
| ... | ... | @@ -1942,46 +1951,6 @@ fn getPkgConfigList(self: *std.Build) ![]const PkgConfigPkg { |
| 1942 | 1951 | } |
| 1943 | 1952 | } |
| 1944 | 1953 | |
| 1945 | test "addPackage" { | |
| 1946 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 1947 | ||
| 1948 | var arena = std.heap.ArenaAllocator.init(std.testing.allocator); | |
| 1949 | defer arena.deinit(); | |
| 1950 | ||
| 1951 | const host = try NativeTargetInfo.detect(.{}); | |
| 1952 | ||
| 1953 | var builder = try std.Build.create( | |
| 1954 | arena.allocator(), | |
| 1955 | "test", | |
| 1956 | "test", | |
| 1957 | "test", | |
| 1958 | "test", | |
| 1959 | host, | |
| 1960 | ); | |
| 1961 | defer builder.destroy(); | |
| 1962 | ||
| 1963 | const pkg_dep = Pkg{ | |
| 1964 | .name = "pkg_dep", | |
| 1965 | .source = .{ .path = "/not/a/pkg_dep.zig" }, | |
| 1966 | }; | |
| 1967 | const pkg_top = Pkg{ | |
| 1968 | .name = "pkg_dep", | |
| 1969 | .source = .{ .path = "/not/a/pkg_top.zig" }, | |
| 1970 | .dependencies = &[_]Pkg{pkg_dep}, | |
| 1971 | }; | |
| 1972 | ||
| 1973 | var exe = builder.addExecutable(.{ | |
| 1974 | .name = "not_an_executable", | |
| 1975 | .root_source_file = .{ .path = "/not/an/executable.zig" }, | |
| 1976 | }); | |
| 1977 | exe.addPackage(pkg_top); | |
| 1978 | ||
| 1979 | try std.testing.expectEqual(@as(usize, 1), exe.packages.items.len); | |
| 1980 | ||
| 1981 | const dupe = exe.packages.items[0]; | |
| 1982 | try std.testing.expectEqualStrings(pkg_top.name, dupe.name); | |
| 1983 | } | |
| 1984 | ||
| 1985 | 1954 | fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) !void { |
| 1986 | 1955 | const cond = opt orelse return; |
| 1987 | 1956 | try args.ensureUnusedCapacity(1); |
lib/std/Build/OptionsStep.zig+5-2| ... | ... | @@ -204,8 +204,11 @@ pub fn addOptionArtifact(self: *OptionsStep, name: []const u8, artifact: *Compil |
| 204 | 204 | self.step.dependOn(&artifact.step); |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | pub fn getPackage(self: *OptionsStep, package_name: []const u8) std.Build.Pkg { | |
| 208 | return .{ .name = package_name, .source = self.getSource() }; | |
| 207 | pub fn createModule(self: *OptionsStep) *std.Build.Module { | |
| 208 | return self.builder.createModule(.{ | |
| 209 | .source_file = self.getSource(), | |
| 210 | .dependencies = &.{}, | |
| 211 | }); | |
| 209 | 212 | } |
| 210 | 213 | |
| 211 | 214 | pub fn getSource(self: *OptionsStep) FileSource { |
test/standalone/pkg_import/build.zig+1-1| ... | ... | @@ -8,7 +8,7 @@ pub fn build(b: *std.Build) void { |
| 8 | 8 | .root_source_file = .{ .path = "test.zig" }, |
| 9 | 9 | .optimize = optimize, |
| 10 | 10 | }); |
| 11 | exe.addPackagePath("my_pkg", "pkg.zig"); | |
| 11 | exe.addAnonymousModule("my_pkg", .{ .source_file = .{ .path = "pkg.zig" } }); | |
| 12 | 12 | |
| 13 | 13 | const run = exe.run(); |
| 14 | 14 |