From 416717d04e182841d87783960e12068100b5b1fb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 10 Jan 2023 21:59:43 -0700 Subject: [PATCH] zig build: support libraries aware of installed headers --- lib/std/build.zig | 11 ++++++++-- lib/std/build/LibExeObjStep.zig | 38 +++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 43ec1eea20..7980bde418 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -311,12 +311,15 @@ pub const Builder = struct { return child; } - pub fn applyArgs(b: *Builder, args: anytype) !void { + fn applyArgs(b: *Builder, args: anytype) !void { // TODO this function is the way that a build.zig file communicates // options to its dependencies. It is the programmatic way to give // command line arguments to a build.zig script. - _ = b; _ = args; + // TODO create a hash based on the args and the package hash, use this + // to compute the install prefix. + const install_prefix = b.pathJoin(&.{ b.cache_root, "pkg" }); + b.resolveInstallPrefix(install_prefix, .{}); } pub fn destroy(self: *Builder) void { @@ -1154,6 +1157,10 @@ pub const Builder = struct { return self.addInstallFileWithDir(source.dupe(self), .lib, dest_rel_path); } + pub fn addInstallHeaderFile(b: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { + return b.addInstallFileWithDir(.{ .path = src_path }, .header, dest_rel_path); + } + pub fn addInstallRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8, options: InstallRawStep.CreateOptions) *InstallRawStep { return InstallRawStep.create(self, artifact, dest_filename, options); } diff --git a/lib/std/build/LibExeObjStep.zig b/lib/std/build/LibExeObjStep.zig index 4795ec6222..2a2207636a 100644 --- a/lib/std/build/LibExeObjStep.zig +++ b/lib/std/build/LibExeObjStep.zig @@ -108,6 +108,7 @@ object_src: []const u8, link_objects: ArrayList(LinkObject), include_dirs: ArrayList(IncludeDir), c_macros: ArrayList([]const u8), +installed_headers: ArrayList(*std.build.InstallFileStep), output_dir: ?[]const u8, is_linking_libc: bool = false, is_linking_libcpp: bool = false, @@ -370,6 +371,7 @@ fn initExtraArgs( .lib_paths = ArrayList([]const u8).init(builder.allocator), .rpaths = ArrayList([]const u8).init(builder.allocator), .framework_dirs = ArrayList([]const u8).init(builder.allocator), + .installed_headers = ArrayList(*std.build.InstallFileStep).init(builder.allocator), .object_src = undefined, .c_std = Builder.CStd.C99, .override_lib_dir = null, @@ -472,6 +474,13 @@ pub fn installRaw(self: *LibExeObjStep, dest_filename: []const u8, options: Inst return self.builder.installRaw(self, dest_filename, options); } +pub fn installHeader(a: *LibExeObjStep, src_path: []const u8) void { + const basename = fs.path.basename(src_path); + const install_file = a.builder.addInstallHeaderFile(src_path, basename); + a.builder.getInstallStep().dependOn(&install_file.step); + a.installed_headers.append(install_file) catch unreachable; +} + /// Creates a `RunStep` with an executable built with `addExecutable`. /// Add command line arguments with `addArg`. pub fn run(exe: *LibExeObjStep) *RunStep { @@ -1362,7 +1371,7 @@ fn make(step: *Step) !void { if (self.libc_file) |libc_file| { try zig_args.append("--libc"); - try zig_args.append(libc_file.getPath(self.builder)); + try zig_args.append(libc_file.getPath(builder)); } else if (builder.libc_file) |libc_file| { try zig_args.append("--libc"); try zig_args.append(libc_file); @@ -1577,7 +1586,7 @@ fn make(step: *Step) !void { } else { const need_cross_glibc = self.target.isGnuLibC() and self.is_linking_libc; - switch (self.builder.host.getExternalExecutor(self.target_info, .{ + switch (builder.host.getExternalExecutor(self.target_info, .{ .qemu_fixes_dl = need_cross_glibc and builder.glibc_runtimes_dir != null, .link_libc = self.is_linking_libc, })) { @@ -1661,7 +1670,7 @@ fn make(step: *Step) !void { switch (include_dir) { .raw_path => |include_path| { try zig_args.append("-I"); - try zig_args.append(self.builder.pathFromRoot(include_path)); + try zig_args.append(builder.pathFromRoot(include_path)); }, .raw_path_system => |include_path| { if (builder.sysroot != null) { @@ -1670,7 +1679,7 @@ fn make(step: *Step) !void { try zig_args.append("-isystem"); } - const resolved_include_path = self.builder.pathFromRoot(include_path); + const resolved_include_path = builder.pathFromRoot(include_path); const common_include_path = if (builtin.os.tag == .windows and builder.sysroot != null and fs.path.isAbsolute(resolved_include_path)) blk: { // We need to check for disk designator and strip it out from dir path so @@ -1686,10 +1695,21 @@ fn make(step: *Step) !void { try zig_args.append(common_include_path); }, - .other_step => |other| if (other.emit_h) { - const h_path = other.getOutputHSource().getPath(self.builder); - try zig_args.append("-isystem"); - try zig_args.append(fs.path.dirname(h_path).?); + .other_step => |other| { + if (other.emit_h) { + const h_path = other.getOutputHSource().getPath(builder); + try zig_args.append("-isystem"); + try zig_args.append(fs.path.dirname(h_path).?); + } + if (other.installed_headers.items.len != 0) { + for (other.installed_headers.items) |install_file| { + try install_file.step.make(); + } + try zig_args.append("-I"); + try zig_args.append(builder.pathJoin(&.{ + other.builder.install_prefix, "include", + })); + } }, .config_header_step => |config_header| { try zig_args.append("-I"); @@ -1790,7 +1810,7 @@ fn make(step: *Step) !void { if (self.override_lib_dir) |dir| { try zig_args.append("--zig-lib-dir"); try zig_args.append(builder.pathFromRoot(dir)); - } else if (self.builder.override_lib_dir) |dir| { + } else if (builder.override_lib_dir) |dir| { try zig_args.append("--zig-lib-dir"); try zig_args.append(builder.pathFromRoot(dir)); }