Zig NEWS

Fuzhou Chen
Fuzhou Chen

Posted on

Use git submodule + local path to manage dependencies

I started knowing build.zig.zon from the great post from @edyu on package management in Zig. Unfortunately, my work environment requires a http proxy to access network. And by the time the post is written, zig build does not properly honor http_proxy environment variables. Thus, I have to manually download all dependencies since August 2023. (I also created a post to talk about it.)

Previously I can live with it. I just write some small executable in Zig without external dependencies. However, when I started my hobby project zamgba, it becomes a problem that must be solved.

It was painful to repeat the manual download + hash generation approach. The problem is, the hash required by build.zig.zon needs to be fetched when the first time I download the package. Unfortunately, I have to add a new library that does not have hash generated by other projects. It appears to be a chick-and-egg problem. Fortunately I found a good approach. that we can combine the git submodule + build.zig.zon.

The idea is to use .dependencies.<package_name>.path instead of .dependencies.<package_name>.url to define the project. My example project, cosumezamgba, shows how I use it:

.{
    .name = "consumezamgba",
    .version = "0.0.0",
    .minimum_zig_version = "0.12.0",

    .dependencies = .{
        .zamgba = . {
            .path = "./deps/zamgba",
        },
    },
    .paths = .{
        "",
    },
}
Enter fullscreen mode Exit fullscreen mode

We can see the project depends on ./deps/zamgba. This refers to my main project, https://github.com/fuzhouch/zamgba, referenced by git submodule. When building the example project, consumezamgba, just run one more command, git submodule update --init --recursive. It will do the trick.

An extra benefit is, when using .path, we don't need the .hash field at all. Thus it completely weave the needs of generating hash.

This is not a new idea. Actually it's borrowed from the C/C++ world. Many existing C/C++ projects still use git submodule to manage dependencies. It works pretty well in any environment, with or without HTTP proxy.

Besides, this is also a good approach to reference to a project that haven't got any stable version released, especially when we need local test or hack my dependencies. I can pin to a specific commit of my dependency with git, without the needs of looking for "Download a Zip" link on Github.

Hope it helps.

Oldest comments (3)

Collapse
 
rite2hamed profile image
Mohammed Hamed • Edited

@fuzhouch this doesn't work.

  • I created a top level solution
  • Created libs folder and a util lib project
  • tried referring into top level application, it's consistently failing with unable to find module error. This is how my top level project build.zig.zon looks like Note: I'm not using git sub module
.{
    .name = "zigawesome",
    .version = "0.0.0",

    .dependencies = .{
        .utils = .{
            .path = "./deps/utils",
        },
    },

    .paths = .{
        "",
    },
}
Enter fullscreen mode Exit fullscreen mode

This is how build.zig looks like

const utils = b.dependency("utils", .{
        .target = target,
        .optimize = optimize,
    });

    const exe = b.addExecutable(.{
        .name = "zigawesome",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    exe.root_module.addImport("utils", utils.module("utils"));
Enter fullscreen mode Exit fullscreen mode

Image description
Any help in debugging this is appreciated!

Collapse
 
xreaper95 profile image
Luis Ernesto Del Toro Peña • Edited

Make sure you have:

pub fn build(b: *std.Build) void {
    const utils_module = b.addModule("utils", .{ ... });
    .........
}
Enter fullscreen mode Exit fullscreen mode

In your deps\utils\build.zig file.

Collapse
 
fuzhouch profile image
Fuzhou Chen • Edited

Sorry for late response! (Was so busy in the past a few months). Yes, @xreaper95 is right.

I have an example project consumezamgba, building an executable to consume my ZamGBA project. Check the build.zig. We need to import dependency as below.

    const zamgba_module = b.dependency("zamgba", .{}).module("zamgba");
    rom.root_module.addImport("gba", zamgba_module);
Enter fullscreen mode Exit fullscreen mode

My code is a bit different with Luis as I use 0.14.0 daily build.

Hope it helps.