|
| 1 | +const std = @import("std"); |
| 2 | +const Configure = @This(); |
| 3 | +const evalChildProcess = @import("build").evalChildProcessInDirectory; |
| 4 | + |
| 5 | +pub const Options = struct { |
| 6 | + source: std.Build.LazyPath, |
| 7 | + target: std.Build.ResolvedTarget, |
| 8 | + optimize: std.builtin.OptimizeMode = .Debug, |
| 9 | + linkage: std.Build.Step.Compile.Linkage = .Static, |
| 10 | + flags: ?[]const []const u8 = null, |
| 11 | +}; |
| 12 | + |
| 13 | +step: std.Build.Step, |
| 14 | +source: std.Build.LazyPath, |
| 15 | +target: std.Build.ResolvedTarget, |
| 16 | +optimize: std.builtin.OptimizeMode, |
| 17 | +linkage: std.Build.Step.Compile.Linkage, |
| 18 | +flags: std.ArrayListUnmanaged([]const u8), |
| 19 | + |
| 20 | +pub fn create(b: *std.Build, options: Options) Configure { |
| 21 | + const arena = b.allocator; |
| 22 | + const self = arena.create(Configure) catch @panic("OOM"); |
| 23 | + self.* = .{ |
| 24 | + .step = std.Build.Step.init(.{ |
| 25 | + .id = .custom, |
| 26 | + .name = b.fmt("Configure {}", .{options.source.getDisplayName()}), |
| 27 | + .owner = b, |
| 28 | + .makeFn = make, |
| 29 | + }), |
| 30 | + .source = options.source, |
| 31 | + .target = options.target, |
| 32 | + .optimize = options.optimize, |
| 33 | + .linkage = options.linkage, |
| 34 | + .flags = .{}, |
| 35 | + }; |
| 36 | + |
| 37 | + self.source.addStepDependencies(&self.step); |
| 38 | + |
| 39 | + if (options.flags) |flags| { |
| 40 | + self.flags.ensureTotalCapacity(arena, flags.len) catch @panic("OOM"); |
| 41 | + |
| 42 | + for (flags) |flag| { |
| 43 | + self.flags.appendAssumeCapacity(arena.dupe(u8, flag) catch @panic("OOM")); |
| 44 | + } |
| 45 | + } |
| 46 | + return self; |
| 47 | +} |
| 48 | + |
| 49 | +fn make(step: *std.Build.Step, _: *std.Progress.Node) anyerror!void { |
| 50 | + const b = step.owner; |
| 51 | + const arena = b.allocator; |
| 52 | + const self = @fieldParentPtr(Configure, "step", step); |
| 53 | + |
| 54 | + var man = b.graph.cache.obtain(); |
| 55 | + defer man.deinit(); |
| 56 | + |
| 57 | + try man.addFile(b.pathJoin(&.{ self.source.getPath2(b, step), "configure" }), null); |
| 58 | + |
| 59 | + if (try step.cacheHit(&man)) return; |
| 60 | + |
| 61 | + const cmd = b.findProgram(&.{ "bash", "sh" }, &.{}) catch return step.fail("Cannot locate a shell", .{}); |
| 62 | + |
| 63 | + var args = std.ArrayList([]const u8).init(arena); |
| 64 | + defer args.deinit(); |
| 65 | + |
| 66 | + try args.appendSlice(&.{ |
| 67 | + cmd, |
| 68 | + b.pathJoin(&.{ self.source.getPath2(b, step), "configure" }), |
| 69 | + b.fmt("--build={s}", .{try self.target.query.zigTriple(arena)}), |
| 70 | + "--prefix=/usr", |
| 71 | + b.fmt("--includedir={s}", .{b.cache_root.join(b.allocator, &.{ "expidus-dev", "include" })}), |
| 72 | + b.fmt("--enable-{s}", .{@as([]const u8, switch (self.linkage) { |
| 73 | + .dynamic => "shared", |
| 74 | + else => @tagName(self.linkage), |
| 75 | + })}), |
| 76 | + }); |
| 77 | + |
| 78 | + try args.appendSlice(self.flags.items); |
| 79 | + |
| 80 | + try step.handleChildProcUnsupported(null, args.items); |
| 81 | + try std.Build.Step.handleVerbose(b, null, args.items); |
| 82 | + |
| 83 | + var env_map = std.process.EnvMap.init(arena); |
| 84 | + defer env_map.deinit(); |
| 85 | + |
| 86 | + { |
| 87 | + var iter = b.graph.env_map.iterator(); |
| 88 | + while (iter.next()) |entry| { |
| 89 | + try env_map.put(entry.key_ptr.*, entry.value_ptr.*); |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + try env_map.put("CC", b.fmt("{s} cc", .{ |
| 94 | + b.graph.zig_exe, |
| 95 | + })); |
| 96 | + |
| 97 | + try env_map.put("CXX", b.fmt("{s} c++", .{ |
| 98 | + b.graph.zig_exe, |
| 99 | + })); |
| 100 | + |
| 101 | + try env_map.put("CFLAGS", b.fmt("-target={s} -mcpu={s} -O{s}", .{ |
| 102 | + try self.target.query.zigTriple(arena), |
| 103 | + try self.target.query.serializeCpuAlloc(arena), |
| 104 | + @as([]const u8, switch (self.optimize) { |
| 105 | + .ReleaseSmall => "s", |
| 106 | + .ReleaseSafe => "3", |
| 107 | + .ReleaseFast => "fast", |
| 108 | + .Debug => "g", |
| 109 | + }), |
| 110 | + })); |
| 111 | + |
| 112 | + if (b.findProgram(&.{"pkg-config"}, &.{}) catch null) |pkgconfig| { |
| 113 | + try env_map.put("PKG_CONFIG", pkgconfig); |
| 114 | + } |
| 115 | + |
| 116 | + const result = std.ChildProcess.run(.{ |
| 117 | + .allocator = arena, |
| 118 | + .argv = args.items, |
| 119 | + .cwd = self.source.getPath2(b, step), |
| 120 | + .env_map = env_map, |
| 121 | + }) catch |err| return step.fail("unable to spawn {s}: {s}", .{ cmd, @errorName(err) }); |
| 122 | + |
| 123 | + if (result.stderr.len > 0) { |
| 124 | + try step.result_error_msgs.append(arena, result.stderr); |
| 125 | + } |
| 126 | + |
| 127 | + try step.handleChildProcessTerm(result.term, null, args.items); |
| 128 | + try step.writeManifest(&man); |
| 129 | +} |
0 commit comments