Hi there,
I’m doing some experiments on implenting custom allocator functions for Raylib, specifically using Not-Nik’s bindings
I have successfully managed to use them, but I have to manually modify the raylib.h in the dependancy to include the exported functions from zig.
This feels a bit clunky and not very portable, is it possible to automate this process through the build system?
std.Build.Step.Compile has a defineCMacro, was hoping there was something along the line of includeCHeader equivalent
I found (I think?) gcc and clang has -include cmd argument to specify a header.h is it perhaps possible to call that from the main build script?
Search engines, aren’t much use these days so thought I would ask here
dimdin
October 18, 2024, 11:36pm
2
Hi @Mariuspersen
welcome to ziggit
Why are you modifying raylib.h
? (e.g. what is stopping you from adding the functions in another header file?)
dimdin:
welcome to ziggit
Thanks!
I could do that too, the only thing I really care about is that raylib is using my allocator functions without manually modifiying the original dependancy
The question is how?
Ok, I managed to solve it.
There is probably already a built in way of doing this so this is probably entirely redundant
fn includeHeader(m: *std.Build.Module, sub_path: []const u8) void {
const b = m.owner;
const path = std.fs.cwd().realpathAlloc(b.allocator, sub_path) catch @panic("OOM");
const string = b.fmt("-include{s}", .{path});
for (m.link_objects.items) |lobj| {
switch (lobj) {
.c_source_file => updateFlags(
std.Build.Module.CSourceFile,
b,
lobj.c_source_file,
string,
),
.c_source_files => updateFlags(
std.Build.Module.CSourceFiles,
b,
lobj.c_source_files,
string,
),
else => {},
}
}
}
fn updateFlags(T: type, b: *std.Build, c_source_file: *T, path: []u8) void {
if (T != std.Build.Module.CSourceFile and T != std.Build.Module.CSourceFiles) {
@compileError("Needs to be CSourceFile or CSourceFiles");
}
const new_flags = b.allocator.alloc([]u8, c_source_file.flags.len + 1) catch @panic("OOM");
for (new_flags[0..c_source_file.flags.len], c_source_file.flags) |*new_flag, old_flag| {
new_flag.* = b.dupe(old_flag);
}
new_flags[new_flags.len - 1] = path;
c_source_file.flags = new_flags;
}
So the build function ends up looking something like this:
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const raylib_dep = b.dependency("raylib-zig", .{
.target = target,
.optimize = optimize,
});
const raylib = raylib_dep.module("raylib");
const raygui = raylib_dep.module("raygui");
const raylib_artifact = raylib_dep.artifact("raylib");
raylib_artifact.defineCMacro("SUPPORT_FILEFORMAT_JPG", null);
//Added this
includeHeader(&raylib_artifact.root_module, "src/memory.h");
const exe = b.addExecutable(.{
.name = "projectboat",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
exe.linkLibrary(raylib_artifact);
exe.root_module.addImport("raylib", raylib);
exe.root_module.addImport("raygui", raygui);
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}