Transitive dependency error

Zigstr build.zig.zon:

.{
    .name = "zigstr",
    .version = "0.1.0",
    .dependencies = .{
	    .cow_list = .{
		    .url = "https://github.com/jecolon/cow_list/archive/refs/heads/main.tar.gz",
		    .hash = "1220cac93f4107205f2d078df6b7f94b7e68e61634c009d3bfec68b29bee2420e347",
	    },
	    .ziglyph = .{
		    .url = "https://github.com/jecolon/ziglyph/archive/refs/heads/main.tar.gz",
		    .hash = "1220400c10661a8b8c88bed1c195b0f71fc2636a044fd312cc0d9b2b46232424b258",
	    },
    },
}

Zigstr build.zig:

    // Deps
    const ziglyph = b.dependency("ziglyph", .{
        .target = target,
        .optimize = optimize,
    });
    const ziglyph_mod = ziglyph.module("ziglyph");
    const ziglyph_lib = ziglyph.artifact("ziglyph");

    const cow_list = b.dependency("cow_list", .{
        .target = target,
        .optimize = optimize,
    });
    const cow_list_mod = cow_list.module("cow_list");
    const cow_list_lib = cow_list.artifact("cow_list");

    // Module
    _ = b.addModule("zigstr", .{
        .source_file = .{ .path = "src/Zigstr.zig" },
    });

    const lib = b.addStaticLibrary(.{
        .name = "zigstr",
        .root_source_file = .{ .path = "src/Zigstr.zig" },
        .target = target,
        .optimize = optimize,
    });
    lib.addModule("ziglyph", ziglyph_mod);
    lib.linkLibrary(ziglyph_lib);
    lib.addModule("cow_list", cow_list_mod);
    lib.linkLibrary(cow_list_lib);

    b.installArtifact(lib);

Zigstr builds and runs tests fine.


New project build.zig.zon:

.{
    .name = "sb",
    .version = "0.1.0",
    .dependencies = .{
	   .zigstr = .{
		   .url = "https://github.com/jecolon/zigstr/archive/refs/heads/main.tar.gz",
		   .hash = "12204d99247a6f40d8fc4113541817026bea26dd6297196cdfc52affbbcdd0b75d45",
	   },
    },
}

New project build.zig:

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

    const zigstr = b.dependency("zigstr", .{
        .target = target,
        .optimize = optimize,
    });
    const zigstr_mod = zigstr.module("zigstr");
    const zigstr_lib = zigstr.artifact("zigstr");
    exe.addModule("zigstr", zigstr_mod);
    exe.linkLibrary(zigstr_lib);

    b.installArtifact(exe);

New project zig build --summary all:

Build Summary: 3/6 steps succeeded; 1 failed
install transitive failure
└─ install sb transitive failure
   └─ zig build-exe sb Debug native 1 errors
      └─ zig build-lib zigstr Debug native-native success 37ms MaxRSS:88M
         ├─ zig build-lib ziglyph Debug native-native success 529ms MaxRSS:87M
         └─ zig build-lib cow_list Debug native-native success 529ms MaxRSS:153M
/Users/jecolon/.cache/zig/p/12204d99247a6f40d8fc4113541817026bea26dd6297196cdfc52affbbcdd0b75d45/src/Zigstr.zig:5:25: error: no package named 'cow_list' available within package 'root.zigstr'
const CowList = @import("cow_list").CowList;
                        ^~~~~~~~~~

So it seems the transitive dependency on cow_list that zigstr has isn’t working at the new project level?

Anybody can point me to a working Zig project that has transitive dependencies (A → B → C) ?

Might be unrelated to your problem, and I might be wrong, but it seems like you wouldn’t need both addModule and linkLibrary for each module. One or the other would make more sense to me.

Ok, you helped me troubleshoot this; many thanks! I got it working by leaving just

exe.addModule("zigstr", zigstr.module("zigstr"));

in the new project build.zig. In the dependency build.zigs I removed everything having to do with creating a static library artifact. Just leaving the b.addModule calls to create the exported modules for each. In the middle-man dependency (zigstr in this case) build.zig, what finally made it work was adding this to its module definition:

const zigstr = b.addModule("zigstr", .{
    .source_file = .{ .path = "src/Zigstr.zig" },
});
zigstr.dependencies.put("ziglyph", ziglyph.module("ziglyph")) catch unreachable;
zigstr.dependencies.put("cow_list", cow_list.module("cow_list")) catch unreachable;

I see that the module struct has a dependencies field, a std.StringArrayHashMap(*Module), and that’w where I’m adding the transitive dependencies via the put method. Is there another way of doing this or is this the Ziguanic way?

1 Like

There’s a dependencies field in CreateModuleOptions. Here’s how zls creates its module:

1 Like

Yes! Now that looks more like it. You’re a life saver @squeek502 ! :slightly_smiling_face:

2 Likes