| ... | ... | @@ -93,6 +93,8 @@ named_writefiles: std.StringArrayHashMap(*Step.WriteFile), |
| 93 | 93 | /// A map from build root dirs to the corresponding `*Dependency`. This is shared with all child |
| 94 | 94 | /// `Build`s. |
| 95 | 95 | initialized_deps: *InitializedDepMap, |
| 96 | /// The hash of this instance's package. `""` means that this is the root package. |
| 97 | pkg_hash: []const u8, |
| 96 | 98 | /// A mapping from dependency names to package hashes. |
| 97 | 99 | available_deps: AvailableDeps, |
| 98 | 100 | |
| ... | ... | @@ -305,6 +307,7 @@ pub fn create( |
| 305 | 307 | .modules = std.StringArrayHashMap(*Module).init(arena), |
| 306 | 308 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(arena), |
| 307 | 309 | .initialized_deps = initialized_deps, |
| 310 | .pkg_hash = "", |
| 308 | 311 | .available_deps = available_deps, |
| 309 | 312 | .release_mode = .off, |
| 310 | 313 | }; |
| ... | ... | @@ -318,10 +321,11 @@ fn createChild( |
| 318 | 321 | parent: *Build, |
| 319 | 322 | dep_name: []const u8, |
| 320 | 323 | build_root: Cache.Directory, |
| 324 | pkg_hash: []const u8, |
| 321 | 325 | pkg_deps: AvailableDeps, |
| 322 | 326 | user_input_options: UserInputOptionsMap, |
| 323 | 327 | ) !*Build { |
| 324 | | const child = try createChildOnly(parent, dep_name, build_root, pkg_deps, user_input_options); |
| 328 | const child = try createChildOnly(parent, dep_name, build_root, pkg_hash, pkg_deps, user_input_options); |
| 325 | 329 | try determineAndApplyInstallPrefix(child); |
| 326 | 330 | return child; |
| 327 | 331 | } |
| ... | ... | @@ -330,6 +334,7 @@ fn createChildOnly( |
| 330 | 334 | parent: *Build, |
| 331 | 335 | dep_name: []const u8, |
| 332 | 336 | build_root: Cache.Directory, |
| 337 | pkg_hash: []const u8, |
| 333 | 338 | pkg_deps: AvailableDeps, |
| 334 | 339 | user_input_options: UserInputOptionsMap, |
| 335 | 340 | ) !*Build { |
| ... | ... | @@ -397,6 +402,7 @@ fn createChildOnly( |
| 397 | 402 | .modules = std.StringArrayHashMap(*Module).init(allocator), |
| 398 | 403 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator), |
| 399 | 404 | .initialized_deps = parent.initialized_deps, |
| 405 | .pkg_hash = pkg_hash, |
| 400 | 406 | .available_deps = pkg_deps, |
| 401 | 407 | .release_mode = parent.release_mode, |
| 402 | 408 | }; |
| ... | ... | @@ -1830,6 +1836,26 @@ fn findPkgHashOrFatal(b: *Build, name: []const u8) []const u8 { |
| 1830 | 1836 | std.debug.panic("no dependency named '{s}' in '{s}'. All packages used in build.zig must be declared in this file", .{ name, full_path }); |
| 1831 | 1837 | } |
| 1832 | 1838 | |
| 1839 | inline fn findImportPkgHashOrFatal(b: *Build, comptime asking_build_zig: type, comptime dep_name: []const u8) []const u8 { |
| 1840 | const build_runner = @import("root"); |
| 1841 | const deps = build_runner.dependencies; |
| 1842 | |
| 1843 | const b_pkg_hash, const b_pkg_deps = comptime for (@typeInfo(deps.packages).Struct.decls) |decl| { |
| 1844 | const pkg_hash = decl.name; |
| 1845 | const pkg = @field(deps.packages, pkg_hash); |
| 1846 | if (@hasDecl(pkg, "build_zig") and pkg.build_zig == asking_build_zig) break .{ pkg_hash, pkg.deps }; |
| 1847 | } else .{ "", deps.root_deps }; |
| 1848 | if (!std.mem.eql(u8, b_pkg_hash, b.pkg_hash)) { |
| 1849 | std.debug.panic("'{}' is not the struct that corresponds to '{s}'", .{ asking_build_zig, b.pathFromRoot("build.zig") }); |
| 1850 | } |
| 1851 | comptime for (b_pkg_deps) |dep| { |
| 1852 | if (std.mem.eql(u8, dep[0], dep_name)) return dep[1]; |
| 1853 | }; |
| 1854 | |
| 1855 | const full_path = b.pathFromRoot("build.zig.zon"); |
| 1856 | std.debug.panic("no dependency named '{s}' in '{s}'. All packages used in build.zig must be declared in this file", .{ dep_name, full_path }); |
| 1857 | } |
| 1858 | |
| 1833 | 1859 | fn markNeededLazyDep(b: *Build, pkg_hash: []const u8) void { |
| 1834 | 1860 | b.graph.needed_lazy_dependencies.put(b.graph.arena, pkg_hash, {}) catch @panic("OOM"); |
| 1835 | 1861 | } |
| ... | ... | @@ -1860,7 +1886,7 @@ pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { |
| 1860 | 1886 | markNeededLazyDep(b, pkg_hash); |
| 1861 | 1887 | return null; |
| 1862 | 1888 | } |
| 1863 | | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg.deps, args); |
| 1889 | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg_hash, pkg.deps, args); |
| 1864 | 1890 | } |
| 1865 | 1891 | } |
| 1866 | 1892 | |
| ... | ... | @@ -1878,13 +1904,48 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency { |
| 1878 | 1904 | if (@hasDecl(pkg, "available")) { |
| 1879 | 1905 | std.debug.panic("dependency '{s}{s}' is marked as lazy in build.zig.zon which means it must use the lazyDependency function instead", .{ b.dep_prefix, name }); |
| 1880 | 1906 | } |
| 1881 | | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg.deps, args); |
| 1907 | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg_hash, pkg.deps, args); |
| 1882 | 1908 | } |
| 1883 | 1909 | } |
| 1884 | 1910 | |
| 1885 | 1911 | unreachable; // Bad @dependencies source |
| 1886 | 1912 | } |
| 1887 | 1913 | |
| 1914 | /// In a build.zig file, this function is to `@import` what `lazyDependency` is to `dependency`. |
| 1915 | /// If the dependency is lazy and has not yet been fetched, it instructs the parent process to fetch |
| 1916 | /// that dependency after the build script has finished running, then returns `null`. |
| 1917 | /// If the dependency is lazy but has already been fetched, or if it is eager, it returns |
| 1918 | /// the build.zig struct of that dependency, just like a regular `@import`. |
| 1919 | pub inline fn lazyImport( |
| 1920 | b: *Build, |
| 1921 | /// The build.zig struct of the package importing the dependency. |
| 1922 | /// When calling this function from the `build` function of a build.zig file's, you normally |
| 1923 | /// pass `@This()`. |
| 1924 | comptime asking_build_zig: type, |
| 1925 | comptime dep_name: []const u8, |
| 1926 | ) ?type { |
| 1927 | const build_runner = @import("root"); |
| 1928 | const deps = build_runner.dependencies; |
| 1929 | const pkg_hash = findImportPkgHashOrFatal(b, asking_build_zig, dep_name); |
| 1930 | |
| 1931 | inline for (@typeInfo(deps.packages).Struct.decls) |decl| { |
| 1932 | if (comptime mem.eql(u8, decl.name, pkg_hash)) { |
| 1933 | const pkg = @field(deps.packages, decl.name); |
| 1934 | const available = !@hasDecl(pkg, "available") or pkg.available; |
| 1935 | if (!available) { |
| 1936 | markNeededLazyDep(b, pkg_hash); |
| 1937 | return null; |
| 1938 | } |
| 1939 | return if (@hasDecl(pkg, "build_zig")) |
| 1940 | pkg.build_zig |
| 1941 | else |
| 1942 | @compileError("dependency '" ++ dep_name ++ "' does not have a build.zig"); |
| 1943 | } |
| 1944 | } |
| 1945 | |
| 1946 | comptime unreachable; // Bad @dependencies source |
| 1947 | } |
| 1948 | |
| 1888 | 1949 | pub fn anonymousDependency( |
| 1889 | 1950 | b: *Build, |
| 1890 | 1951 | /// The path to the directory containing the dependency's build.zig file, |
| ... | ... | @@ -1901,7 +1962,7 @@ pub fn anonymousDependency( |
| 1901 | 1962 | '/', '\\' => byte.* = '.', |
| 1902 | 1963 | else => continue, |
| 1903 | 1964 | }; |
| 1904 | | return dependencyInner(b, name, build_root, build_zig, &.{}, args); |
| 1965 | return dependencyInner(b, name, build_root, build_zig, "anonymous", &.{}, args); |
| 1905 | 1966 | } |
| 1906 | 1967 | |
| 1907 | 1968 | fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool { |
| ... | ... | @@ -1956,6 +2017,7 @@ pub fn dependencyInner( |
| 1956 | 2017 | name: []const u8, |
| 1957 | 2018 | build_root_string: []const u8, |
| 1958 | 2019 | comptime build_zig: ?type, |
| 2020 | pkg_hash: []const u8, |
| 1959 | 2021 | pkg_deps: AvailableDeps, |
| 1960 | 2022 | args: anytype, |
| 1961 | 2023 | ) *Dependency { |
| ... | ... | @@ -1976,7 +2038,7 @@ pub fn dependencyInner( |
| 1976 | 2038 | }, |
| 1977 | 2039 | }; |
| 1978 | 2040 | |
| 1979 | | const sub_builder = b.createChild(name, build_root, pkg_deps, user_input_options) catch @panic("unhandled error"); |
| 2041 | const sub_builder = b.createChild(name, build_root, pkg_hash, pkg_deps, user_input_options) catch @panic("unhandled error"); |
| 1980 | 2042 | if (build_zig) |bz| { |
| 1981 | 2043 | sub_builder.runBuild(bz) catch @panic("unhandled error"); |
| 1982 | 2044 | |