Commit b5a5260546

GalaxyShard <galaxyshard.tech@proton.me>
2024-10-09 07:27:42
std.Build: implement addEmbedPath for adding C #embed search directories
1 parent fb188c3
Changed files (8)
lib
src
test
standalone
lib/compiler/build_runner.zig
@@ -1496,6 +1496,7 @@ fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void {
             .path_after,
             .framework_path,
             .framework_path_system,
+            .embed_path,
             => |lp| lp.addStepDependencies(step),
 
             .other_step => |other| {
lib/std/Build/Step/Compile.zig
@@ -943,6 +943,10 @@ pub fn addConfigHeader(compile: *Compile, config_header: *Step.ConfigHeader) voi
     compile.root_module.addConfigHeader(config_header);
 }
 
+pub fn addEmbedPath(compile: *Compile, lazy_path: LazyPath) void {
+    compile.root_module.addEmbedPath(lazy_path);
+}
+
 pub fn addLibraryPath(compile: *Compile, directory_path: LazyPath) void {
     compile.root_module.addLibraryPath(directory_path);
 }
lib/std/Build/Module.zig
@@ -164,6 +164,7 @@ pub const IncludeDir = union(enum) {
     framework_path_system: LazyPath,
     other_step: *Step.Compile,
     config_header_step: *Step.ConfigHeader,
+    embed_path: LazyPath,
 
     pub fn appendZigProcessFlags(
         include_dir: IncludeDir,
@@ -200,6 +201,9 @@ pub const IncludeDir = union(enum) {
                 const header_dir_path = full_file_path[0 .. full_file_path.len - config_header.include_path.len];
                 try zig_args.appendSlice(&.{ "-I", header_dir_path });
             },
+            .embed_path => |embed_path| {
+                try zig_args.append(try std.mem.concat(b.allocator, u8, &.{ "--embed-dir=", embed_path.getPath2(b, asking_step) }));
+            },
         }
     }
 };
@@ -511,6 +515,11 @@ pub fn addFrameworkPath(m: *Module, directory_path: LazyPath) void {
         @panic("OOM");
 }
 
+pub fn addEmbedPath(m: *Module, lazy_path: LazyPath) void {
+    const b = m.owner;
+    m.include_dirs.append(b.allocator, .{ .embed_path = lazy_path.dupe(b) }) catch @panic("OOM");
+}
+
 pub fn addLibraryPath(m: *Module, directory_path: LazyPath) void {
     const b = m.owner;
     m.lib_paths.append(b.allocator, directory_path.dupe(b)) catch @panic("OOM");
src/main.zig
@@ -541,6 +541,7 @@ const usage_build_generic =
     \\  -idirafter [dir]          Add directory to AFTER include search path
     \\  -isystem  [dir]           Add directory to SYSTEM include search path
     \\  -I[dir]                   Add directory to include search path
+    \\  --embed-dir=[dir]         Add directory to embed search path
     \\  -D[macro]=[value]         Define C [macro] to [value] (1 if [value] omitted)
     \\  -cflags [flags] --        Set extra flags for the next positional C source files
     \\  -rcflags [flags] --       Set extra flags for the next positional .rc source files
@@ -1287,6 +1288,8 @@ fn buildOutputType(
                         try cc_argv.appendSlice(arena, &.{ arg, args_iter.nextOrFatal() });
                     } else if (mem.eql(u8, arg, "-I")) {
                         try cssan.addIncludePath(arena, &cc_argv, .I, arg, args_iter.nextOrFatal(), false);
+                    } else if (mem.startsWith(u8, arg, "--embed-dir=")) {
+                        try cssan.addIncludePath(arena, &cc_argv, .embed_dir, arg, arg["--embed-dir=".len..], true);
                     } else if (mem.eql(u8, arg, "-isystem")) {
                         try cssan.addIncludePath(arena, &cc_argv, .isystem, arg, args_iter.nextOrFatal(), false);
                     } else if (mem.eql(u8, arg, "-iwithsysroot")) {
@@ -6974,13 +6977,17 @@ const ClangSearchSanitizer = struct {
                 m.iframeworkwithsysroot = true;
                 if (m.iwithsysroot) warn(wtxt, .{ dir, "iframeworkwithsysroot", "iwithsysroot" });
             },
+            .embed_dir => {
+                if (m.embed_dir) return;
+                m.embed_dir = true;
+            },
         }
         try argv.ensureUnusedCapacity(ally, 2);
         argv.appendAssumeCapacity(arg);
         if (!joined) argv.appendAssumeCapacity(dir);
     }
 
-    const Group = enum { I, isystem, iwithsysroot, idirafter, iframework, iframeworkwithsysroot };
+    const Group = enum { I, isystem, iwithsysroot, idirafter, iframework, iframeworkwithsysroot, embed_dir };
 
     const Membership = packed struct {
         I: bool = false,
@@ -6989,6 +6996,7 @@ const ClangSearchSanitizer = struct {
         idirafter: bool = false,
         iframework: bool = false,
         iframeworkwithsysroot: bool = false,
+        embed_dir: bool = false,
     };
 };
 
test/standalone/c_embed_path/data/foo.data
@@ -0,0 +1,1 @@
+This text is the contents of foo.data
\ No newline at end of file
test/standalone/c_embed_path/build.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+
+pub fn build(b: *std.Build) void {
+    const test_step = b.step("test", "Test it");
+    b.default_step = test_step;
+
+    const optimize: std.builtin.OptimizeMode = .Debug;
+
+    const exe = b.addExecutable(.{
+        .name = "test",
+        .target = b.graph.host,
+        .optimize = optimize,
+    });
+    exe.addCSourceFile(.{
+        .file = b.path("test.c"),
+        .flags = &.{"-std=c23"},
+    });
+    exe.linkLibC();
+    exe.addEmbedPath(b.path("data"));
+
+    const run_c_cmd = b.addRunArtifact(exe);
+    run_c_cmd.expectExitCode(0);
+    run_c_cmd.skip_foreign_checks = true;
+    test_step.dependOn(&run_c_cmd.step);
+}
test/standalone/c_embed_path/test.c
@@ -0,0 +1,15 @@
+
+#include <stdlib.h>
+#include <string.h>
+int main(void) {
+    // Raw bytes; not a C string
+    const char data[] = {
+#embed <foo.data>
+    };
+    const char *expected = "This text is the contents of foo.data";
+    if (sizeof data == strlen(expected) && memcmp(data, expected, sizeof data) == 0) {
+        return EXIT_SUCCESS;
+    } else {
+        return EXIT_FAILURE;
+    }
+}
test/standalone/build.zig.zon
@@ -126,6 +126,9 @@
         .c_compiler = .{
             .path = "c_compiler",
         },
+        .c_embed_path = .{
+            .path = "c_embed_path",
+        },
         .pie = .{
             .path = "pie",
         },