Ever wanted to run GNU make from within your zig build?

I put together a build.zig package to compile GNU’s make program and published it here:

My current use case for it is to build the linux kernel from within zig’s build system. I’m exploring techniques to incrementally port the linux kernel build system to Zig and this tool might help with that.

Here’s a snippet of the build.zig that will build the linux kernel:

    const config = blk: {
        const run_config = b.addRunArtifact(make_exe);
        run_config.addArg("-C");
        run_config.addDirectoryArg(linux_dep.path("."));
        const out_dir = run_config.addPrefixedOutputDirectoryArg("O=", ".");
        run_config.addArg("ARCH=x86_64");
        run_config.addArg("x86_64_defconfig");
        // TODO: side effects?
        b.step("defconfig", "").dependOn(&run_config.step);
        break :blk out_dir.path(b, ".config");
    };

    {
        const run_make = blk: {
            // NOTE: the custom make doesn't suppor the -j flag at the moment
            //       so it takes a while to build the kernel with it
            const use_custom_make = false;
            if (use_custom_make) break :blk b.addRunArtifact(make_exe);
            break :blk b.addSystemCommand(&.{ "make" });
        };
        run_make.addArg("-C");
        run_make.addDirectoryArg(linux_dep.path("."));
        const out_dir = run_make.addPrefixedOutputDirectoryArg("O=", ".");
        run_make.addArg("ARCH=x86_64");
        run_make.addPrefixedFileArg("KCONFIG_CONFIG=", config);
        run_make.addArg(b.fmt("-j{}", .{std.Thread.getCpuCount() catch 1}));
        const install = b.addInstallDirectory(.{
            .source_dir = out_dir,
            .install_dir = .prefix,
            .install_subdir = "linux",
        });
        b.getInstallStep().dependOn(&install.step);
    }
6 Likes