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