diff --git a/test/standalone.zig b/test/standalone.zig index 495468eb24..2f1b7d1339 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -266,6 +266,10 @@ pub const build_cases = [_]BuildCase{ .build_root = "test/standalone/depend_on_main_mod", .import = @import("standalone/depend_on_main_mod/build.zig"), }, + .{ + .build_root = "test/standalone/install_headers", + .import = @import("standalone/install_headers/build.zig"), + }, }; const std = @import("std"); diff --git a/test/standalone/install_headers/build.zig b/test/standalone/install_headers/build.zig new file mode 100644 index 0000000000..20fab2aaa6 --- /dev/null +++ b/test/standalone/install_headers/build.zig @@ -0,0 +1,83 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test"); + b.default_step = test_step; + + const libfoo = b.addStaticLibrary(.{ + .name = "foo", + .target = b.resolveTargetQuery(.{}), + .optimize = .Debug, + }); + libfoo.addCSourceFile(.{ .file = b.addWriteFiles().add("empty.c", "") }); + + const exe = b.addExecutable(.{ + .name = "exe", + .target = b.resolveTargetQuery(.{}), + .optimize = .Debug, + .link_libc = true, + }); + exe.addCSourceFile(.{ .file = b.addWriteFiles().add("main.c", + \\#include + \\#include + \\#include + \\#include + \\#include + \\int main(void) { + \\ printf(FOO_A FOO_B FOO_D FOO_CONFIG_1 FOO_CONFIG_2); + \\ return 0; + \\} + ) }); + + libfoo.installHeaders(.{ .path = "include" }, "foo", .{ .exclude_extensions = &.{".ignore_me.h"} }); + libfoo.installHeader(b.addWriteFiles().add("d.h", + \\#define FOO_D "D" + \\ + ), "foo/d.h"); + + if (libfoo.installed_headers_include_tree != null) std.debug.panic("include tree step was created before linking", .{}); + + // Link before we have registered all headers for installation, + // to verify that the lazily created write files step is properly taken into account. + exe.linkLibrary(libfoo); + + if (libfoo.installed_headers_include_tree == null) std.debug.panic("include tree step was not created after linking", .{}); + + libfoo.installConfigHeader(b.addConfigHeader(.{ + .style = .blank, + .include_path = "foo/config.h", + }, .{ + .FOO_CONFIG_1 = "1", + .FOO_CONFIG_2 = "2", + })); + + const run_exe = b.addRunArtifact(exe); + run_exe.expectStdOutEqual("ABD12"); + test_step.dependOn(&run_exe.step); + + const install_exe = b.addInstallArtifact(libfoo, .{ + .dest_dir = .{ .override = .{ .custom = "custom" } }, + .h_dir = .{ .override = .{ .custom = "custom/include" } }, + .implib_dir = .disabled, + .pdb_dir = .disabled, + }); + const check_exists = b.addExecutable(.{ + .name = "check_exists", + .root_source_file = .{ .path = "check_exists.zig" }, + .target = b.resolveTargetQuery(.{}), + .optimize = .Debug, + }); + const run_check_exists = b.addRunArtifact(check_exists); + run_check_exists.addArgs(&.{ + "custom/include/foo/a.h", + "!custom/include/foo/ignore_me.txt", + "custom/include/foo/sub_dir/b.h", + "!custom/include/foo/sub_dir/c.ignore_me.h", + "custom/include/foo/d.h", + "custom/include/foo/config.h", + }); + run_check_exists.setCwd(.{ .cwd_relative = b.getInstallPath(.prefix, "") }); + run_check_exists.expectExitCode(0); + run_check_exists.step.dependOn(&install_exe.step); + test_step.dependOn(&run_check_exists.step); +} diff --git a/test/standalone/install_headers/check_exists.zig b/test/standalone/install_headers/check_exists.zig new file mode 100644 index 0000000000..da07af1028 --- /dev/null +++ b/test/standalone/install_headers/check_exists.zig @@ -0,0 +1,37 @@ +const std = @import("std"); + +/// Checks the existence of files relative to cwd. +/// A path starting with ! should not exist. +pub fn main() !void { + var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena_state.deinit(); + + const arena = arena_state.allocator(); + + var arg_it = try std.process.argsWithAllocator(arena); + _ = arg_it.next(); + + const cwd = std.fs.cwd(); + const cwd_realpath = try cwd.realpathAlloc(arena, ""); + + while (arg_it.next()) |file_path| { + if (file_path.len > 0 and file_path[0] == '!') { + errdefer std.log.err( + "excluded file check '{s}{c}{s}' failed", + .{ cwd_realpath, std.fs.path.sep, file_path[1..] }, + ); + if (std.fs.cwd().statFile(file_path[1..])) |_| { + return error.FileFound; + } else |err| switch (err) { + error.FileNotFound => {}, + else => return err, + } + } else { + errdefer std.log.err( + "included file check '{s}{c}{s}' failed", + .{ cwd_realpath, std.fs.path.sep, file_path }, + ); + _ = try std.fs.cwd().statFile(file_path); + } + } +} diff --git a/test/standalone/install_headers/include/a.h b/test/standalone/install_headers/include/a.h new file mode 100644 index 0000000000..570548abb7 --- /dev/null +++ b/test/standalone/install_headers/include/a.h @@ -0,0 +1 @@ +#define FOO_A "A" diff --git a/test/standalone/install_headers/include/ignore_me.txt b/test/standalone/install_headers/include/ignore_me.txt new file mode 100644 index 0000000000..592fd2594b --- /dev/null +++ b/test/standalone/install_headers/include/ignore_me.txt @@ -0,0 +1 @@ +ignore me diff --git a/test/standalone/install_headers/include/sub_dir/b.h b/test/standalone/install_headers/include/sub_dir/b.h new file mode 100644 index 0000000000..f16019c96f --- /dev/null +++ b/test/standalone/install_headers/include/sub_dir/b.h @@ -0,0 +1 @@ +#define FOO_B "B" diff --git a/test/standalone/install_headers/include/sub_dir/ignore_me.h b/test/standalone/install_headers/include/sub_dir/ignore_me.h new file mode 100644 index 0000000000..11e5ba752b --- /dev/null +++ b/test/standalone/install_headers/include/sub_dir/ignore_me.h @@ -0,0 +1 @@ +#error "ignore me"