@@ -69,13 +69,15 @@ pub const Builder = struct {
6969 search_prefixes : ArrayList ([]const u8 ),
7070 libc_file : ? []const u8 = null ,
7171 installed_files : ArrayList (InstalledFile ),
72+ /// Path to the directory containing build.zig.
7273 build_root : []const u8 ,
7374 cache_root : []const u8 ,
7475 global_cache_root : []const u8 ,
7576 release_mode : ? std.builtin.Mode ,
7677 is_release : bool ,
78+ /// zig lib dir
7779 override_lib_dir : ? []const u8 ,
78- vcpkg_root : VcpkgRoot ,
80+ vcpkg_root : VcpkgRoot = .unattempted ,
7981 pkg_config_pkg_list : ? (PkgConfigError ! []const PkgConfigPkg ) = null ,
8082 args : ? [][]const u8 = null ,
8183 debug_log_scopes : []const []const u8 = &.{},
@@ -100,6 +102,8 @@ pub const Builder = struct {
100102 /// Information about the native target. Computed before build() is invoked.
101103 host : NativeTargetInfo ,
102104
105+ dep_prefix : []const u8 = "" ,
106+
103107 pub const ExecError = error {
104108 ReadFailure ,
105109 ExitCodeFailure ,
@@ -223,7 +227,6 @@ pub const Builder = struct {
223227 .is_release = false ,
224228 .override_lib_dir = null ,
225229 .install_path = undefined ,
226- .vcpkg_root = VcpkgRoot { .unattempted = {} },
227230 .args = null ,
228231 .host = host ,
229232 };
@@ -233,6 +236,92 @@ pub const Builder = struct {
233236 return self ;
234237 }
235238
239+ fn createChild (
240+ parent : * Builder ,
241+ dep_name : []const u8 ,
242+ build_root : []const u8 ,
243+ args : anytype ,
244+ ) ! * Builder {
245+ const child = try createChildOnly (parent , dep_name , build_root );
246+ try applyArgs (child , args );
247+ return child ;
248+ }
249+
250+ fn createChildOnly (parent : * Builder , dep_name : []const u8 , build_root : []const u8 ) ! * Builder {
251+ const allocator = parent .allocator ;
252+ const child = try allocator .create (Builder );
253+ child .* = .{
254+ .allocator = allocator ,
255+ .install_tls = .{
256+ .step = Step .initNoOp (.top_level , "install" , allocator ),
257+ .description = "Copy build artifacts to prefix path" ,
258+ },
259+ .uninstall_tls = .{
260+ .step = Step .init (.top_level , "uninstall" , allocator , makeUninstall ),
261+ .description = "Remove build artifacts from prefix path" ,
262+ },
263+ .user_input_options = UserInputOptionsMap .init (allocator ),
264+ .available_options_map = AvailableOptionsMap .init (allocator ),
265+ .available_options_list = ArrayList (AvailableOption ).init (allocator ),
266+ .verbose = parent .verbose ,
267+ .verbose_link = parent .verbose_link ,
268+ .verbose_cc = parent .verbose_cc ,
269+ .verbose_air = parent .verbose_air ,
270+ .verbose_llvm_ir = parent .verbose_llvm_ir ,
271+ .verbose_cimport = parent .verbose_cimport ,
272+ .verbose_llvm_cpu_features = parent .verbose_llvm_cpu_features ,
273+ .prominent_compile_errors = parent .prominent_compile_errors ,
274+ .color = parent .color ,
275+ .reference_trace = parent .reference_trace ,
276+ .invalid_user_input = false ,
277+ .zig_exe = parent .zig_exe ,
278+ .default_step = undefined ,
279+ .env_map = parent .env_map ,
280+ .top_level_steps = ArrayList (* TopLevelStep ).init (allocator ),
281+ .install_prefix = undefined ,
282+ .dest_dir = parent .dest_dir ,
283+ .lib_dir = parent .lib_dir ,
284+ .exe_dir = parent .exe_dir ,
285+ .h_dir = parent .h_dir ,
286+ .install_path = parent .install_path ,
287+ .sysroot = parent .sysroot ,
288+ .search_prefixes = ArrayList ([]const u8 ).init (allocator ),
289+ .libc_file = parent .libc_file ,
290+ .installed_files = ArrayList (InstalledFile ).init (allocator ),
291+ .build_root = build_root ,
292+ .cache_root = parent .cache_root ,
293+ .global_cache_root = parent .global_cache_root ,
294+ .release_mode = parent .release_mode ,
295+ .is_release = parent .is_release ,
296+ .override_lib_dir = parent .override_lib_dir ,
297+ .debug_log_scopes = parent .debug_log_scopes ,
298+ .debug_compile_errors = parent .debug_compile_errors ,
299+ .enable_darling = parent .enable_darling ,
300+ .enable_qemu = parent .enable_qemu ,
301+ .enable_rosetta = parent .enable_rosetta ,
302+ .enable_wasmtime = parent .enable_wasmtime ,
303+ .enable_wine = parent .enable_wine ,
304+ .glibc_runtimes_dir = parent .glibc_runtimes_dir ,
305+ .host = parent .host ,
306+ .dep_prefix = parent .fmt ("{s}{s}." , .{ parent .dep_prefix , dep_name }),
307+ };
308+ try child .top_level_steps .append (& child .install_tls );
309+ try child .top_level_steps .append (& child .uninstall_tls );
310+ child .default_step = & child .install_tls .step ;
311+ return child ;
312+ }
313+
314+ fn applyArgs (b : * Builder , args : anytype ) ! void {
315+ // TODO this function is the way that a build.zig file communicates
316+ // options to its dependencies. It is the programmatic way to give
317+ // command line arguments to a build.zig script.
318+ _ = args ;
319+ // TODO create a hash based on the args and the package hash, use this
320+ // to compute the install prefix.
321+ const install_prefix = b .pathJoin (&.{ b .cache_root , "pkg" });
322+ b .resolveInstallPrefix (install_prefix , .{});
323+ }
324+
236325 pub fn destroy (self : * Builder ) void {
237326 self .env_map .deinit ();
238327 self .top_level_steps .deinit ();
@@ -1068,6 +1157,10 @@ pub const Builder = struct {
10681157 return self .addInstallFileWithDir (source .dupe (self ), .lib , dest_rel_path );
10691158 }
10701159
1160+ pub fn addInstallHeaderFile (b : * Builder , src_path : []const u8 , dest_rel_path : []const u8 ) * InstallFileStep {
1161+ return b .addInstallFileWithDir (.{ .path = src_path }, .header , dest_rel_path );
1162+ }
1163+
10711164 pub fn addInstallRaw (self : * Builder , artifact : * LibExeObjStep , dest_filename : []const u8 , options : InstallRawStep.CreateOptions ) * InstallRawStep {
10721165 return InstallRawStep .create (self , artifact , dest_filename , options );
10731166 }
@@ -1300,6 +1393,70 @@ pub const Builder = struct {
13001393 &[_ ][]const u8 { base_dir , dest_rel_path },
13011394 ) catch unreachable ;
13021395 }
1396+
1397+ pub const Dependency = struct {
1398+ builder : * Builder ,
1399+
1400+ pub fn artifact (d : * Dependency , name : []const u8 ) * LibExeObjStep {
1401+ var found : ? * LibExeObjStep = null ;
1402+ for (d .builder .install_tls .step .dependencies .items ) | dep_step | {
1403+ const inst = dep_step .cast (InstallArtifactStep ) orelse continue ;
1404+ if (mem .eql (u8 , inst .artifact .name , name )) {
1405+ if (found != null ) panic ("artifact name '{s}' is ambiguous" , .{name });
1406+ found = inst .artifact ;
1407+ }
1408+ }
1409+ return found orelse {
1410+ for (d .builder .install_tls .step .dependencies .items ) | dep_step | {
1411+ const inst = dep_step .cast (InstallArtifactStep ) orelse continue ;
1412+ log .info ("available artifact: '{s}'" , .{inst .artifact .name });
1413+ }
1414+ panic ("unable to find artifact '{s}'" , .{name });
1415+ };
1416+ }
1417+ };
1418+
1419+ pub fn dependency (b : * Builder , name : []const u8 , args : anytype ) * Dependency {
1420+ const build_runner = @import ("root" );
1421+ const deps = build_runner .dependencies ;
1422+
1423+ inline for (@typeInfo (deps .imports ).Struct .decls ) | decl | {
1424+ if (mem .startsWith (u8 , decl .name , b .dep_prefix ) and
1425+ mem .endsWith (u8 , decl .name , name ) and
1426+ decl .name .len == b .dep_prefix .len + name .len )
1427+ {
1428+ const build_zig = @field (deps .imports , decl .name );
1429+ const build_root = @field (deps .build_root , decl .name );
1430+ return dependencyInner (b , name , build_root , build_zig , args );
1431+ }
1432+ }
1433+
1434+ const full_path = b .pathFromRoot ("build.zig.ini" );
1435+ std .debug .print ("no dependency named '{s}' in '{s}'\n " , .{ name , full_path });
1436+ std .process .exit (1 );
1437+ }
1438+
1439+ fn dependencyInner (
1440+ b : * Builder ,
1441+ name : []const u8 ,
1442+ build_root : []const u8 ,
1443+ comptime build_zig : type ,
1444+ args : anytype ,
1445+ ) * Dependency {
1446+ const sub_builder = b .createChild (name , build_root , args ) catch unreachable ;
1447+ sub_builder .runBuild (build_zig ) catch unreachable ;
1448+ const dep = b .allocator .create (Dependency ) catch unreachable ;
1449+ dep .* = .{ .builder = sub_builder };
1450+ return dep ;
1451+ }
1452+
1453+ pub fn runBuild (b : * Builder , build_zig : anytype ) anyerror ! void {
1454+ switch (@typeInfo (@typeInfo (@TypeOf (build_zig .build )).Fn .return_type .? )) {
1455+ .Void = > build_zig .build (b ),
1456+ .ErrorUnion = > try build_zig .build (b ),
1457+ else = > @compileError ("expected return type of build to be 'void' or '!void'" ),
1458+ }
1459+ }
13031460};
13041461
13051462test "builder.findProgram compiles" {
0 commit comments