build.zig: automatically patchelf the rpath when in a nix shell

This commit is contained in:
Mitchell Hashimoto
2023-03-13 10:58:00 -07:00
parent d114f95165
commit d99cc0aec1

View File

@ -3,6 +3,7 @@ const builtin = @import("builtin");
const fs = std.fs;
const Builder = std.build.Builder;
const LibExeObjStep = std.build.LibExeObjStep;
const RunStep = std.build.RunStep;
const apprt = @import("src/apprt.zig");
const glfw = @import("vendor/mach/libs/glfw/build.zig");
const fontconfig = @import("pkg/fontconfig/build.zig");
@ -116,6 +117,26 @@ pub fn build(b: *std.build.Builder) !void {
"Build and install the benchmark executables.",
) orelse false;
// On NixOS, the built binary from `zig build` needs to patch the rpath
// into the built binary for it to be portable across the NixOS system
// it was built for. We default this to true if we can detect we're in
// a Nix shell and have LD_LIBRARY_PATH set.
const patch_rpath: ?[]const u8 = b.option(
[]const u8,
"patch-rpath",
"Inject the LD_LIBRARY_PATH as the rpath in the built binary. " ++
"This defaults to LD_LIBRARY_PATH if we're in a Nix shell environment on NixOS.",
) orelse patch_rpath: {
// We only do the patching if we're targeting our own CPU and its Linux.
if (!target.isLinux() or !target.isNativeCpu()) break :patch_rpath null;
// If we're in a nix shell we default to doing this.
// Note: we purposely never deinit envmap because we leak the strings
const env = try std.process.getEnvMap(b.allocator);
if (env.get("IN_NIX_SHELL") == null) break :patch_rpath null;
break :patch_rpath env.get("LD_LIBRARY_PATH");
};
var version_string = b.option(
[]const u8,
"version-string",
@ -179,16 +200,36 @@ pub fn build(b: *std.build.Builder) !void {
// Exe
{
exe.addOptions("build_options", exe_options);
if (target.isDarwin()) {
// See the comment in this file
exe.addCSourceFile("src/renderer/metal_workaround.c", &.{});
}
exe.addOptions("build_options", exe_options);
if (app_runtime != .none) exe.install();
// Add the shared dependencies
_ = try addDeps(b, exe, static);
// If we're installing, we get the install step so we can add
// additional dependencies to it.
const install_step = if (app_runtime != .none) step: {
const step = b.addInstallArtifact(exe);
b.getInstallStep().dependOn(&step.step);
break :step step;
} else null;
// Patch our rpath if that option is specified.
if (patch_rpath) |rpath| {
if (rpath.len > 0) {
const run = RunStep.create(b, "patchelf rpath");
run.addArgs(&.{ "patchelf", "--set-rpath", rpath });
run.addArtifactArg(exe);
if (install_step) |step| {
step.step.dependOn(&run.step);
}
}
}
}
// App (Linux)