Hey, I’m trying to replicate what I have in a Makefile from a past non-zig project and having trouble with defining build steps.
I think posting a minimal makefile will more quickly communicate what I’m trying to accomplish:
# cross-compilation targets
PLATFORMS = linux windows darwin
# host to which the binary will connect, without args
HOST ?= localhost
# port to which the binary will connect, without args
PORT ?= 8443
PREFIX ?= ./build
APP ?= myapp
# embeds host/port in the binary
LDFLAGS = "-s -w -X main.connectString=${HOST}:${PORT}"
# references the calling target within each block
# `make windows` makes $target equal "windows"
target = $(word 1, $@)
# just builds for the current platform/arch
.DEFAULT_GOAL = debug
debug:
go build -o ${PREFIX}/${APP} cmd/myapp/main.go
${PLATFORMS}: ## one of: windows, linux, darwin
GOOS=${target} go build \
-o ${PREFIX}/${APP}.${target} \
-buildmode pie \
-ldflags ${LDFLAGS} \
-trimpath \
cmd/myapp/main.go
all: $(PLATFORMS) ## makes all windows, linux, darwin targets
clean:
rm -rf $PREFIX/$APP*
Main points:
- Just running
make
builds thedebug
target - Running
make windows
does just that, makes an exe - Running
make all
runs each ofmake {windows,darwin,linux}
- Expose config options for embedding variable at buildtime (host/port)
What I’m currently trying to replicate is points 1 and 3. I’d like
zig build
to make a bin for the system on which I’m currently developing. This works with the generated build.zig
file.
However, I’m trying to modify fn build
to define a build step equivalent to make all
.
Re-reading this all, I’m thinking I should probably add specific os targets individually, and just make zig build all
have those as deps. Anyway…
Here’s my current build.zig
. I have a debug statement that tells me the buildFn
is being run,
but I’m not ending up with any artifacts.
const std = @import("std");
pub fn build(b: *std.Build) void {
// Allow a user to bake in server:port information to the final binary
const buildOptions = b.addOptions();
const host_option = b.option([]const u8, "host", "ip addr to which the shell connects") orelse "localhost";
const port_option = b.option(u32, "port", "port to which the shell connects") orelse 1337;
buildOptions.addOption([]const u8, "host", host_option);
buildOptions.addOption(u32, "port", port_option);
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Configure the program artifacts
const exe = b.addExecutable(.{
.name = "hello",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// make the build options accessible withing the program source code
// with @import("config") ex config.host, config.port
exe.root_module.addOptions("config", buildOptions);
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
const make_all_step = b.step("all", "Make all binaries");
make_all_step.makeFn = makeFn;
}
fn makeFn(step: *std.Build.Step, prog_node: std.Progress.Node) anyerror!void {
_ = prog_node;
std.debug.print("{s}\n", .{"Making Everything"});
const targets: []const std.Target.Query = &.{
.{ .cpu_arch = .aarch64, .os_tag = .macos },
.{ .cpu_arch = .aarch64, .os_tag = .linux },
.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .gnu },
.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .musl },
.{ .cpu_arch = .x86_64, .os_tag = .windows },
};
for (targets) |tgt| {
std.debug.print("Making {?}\n", .{tgt.os_tag});
const exe = step.owner.addExecutable(.{
.name = "hello",
.root_source_file = step.owner.path("src/main.zig"),
.target = step.owner.resolveTargetQuery(tgt),
});
const instep = step.owner.addInstallArtifact(exe, .{});
step.dependOn(&instep.step);
}
return undefined;
}
Thanks for any input. Excited to get this working and be rid of external build tools.
I realized the target options are available to me becuase of const target = b.standardTargetOptions(.{});
up near the top of the build file, but I’m just trying to make convenience methods to help out users.