#Where do dependencies in .zon files go once built? and how to reference them in your own zig files?

1 messages · Page 1 of 1 (latest)

ionic sail
#

Currently I am trying to use raylib in my zig project, by using the .zon file containing the url and hash of where its located. This seems to work and the build step seems to finish for that (and i can see some header files from it in the zig-cache folder), but in my own build.zig file I'm having trouble linking it for my code. I see examples online of people who have done this when they pull in raylib as a git submodule, and i see examples of people doing this when they are using the zig bindings for raylib, but i can't find any examples for using .zon file as a dependency.

    const raylib_optimize = b.option(
        std.builtin.OptimizeMode,
        "raylib-optimize",
        "Prioritize performance, safety, or binary size (-O flag), defaults to value of optimize option",
    ) orelse optimize;

    const strip = b.option(
        bool,
        "strip",
        "Strip debug info to reduce binary size, defaults to false",
    ) orelse false;
    exe.strip = strip;

    const raylib_dep = b.dependency("raylib", .{
        .target = target,
        .optimize = raylib_optimize,
    });
    exe.linkLibrary(raylib_dep.artifact("raylib"));

The above code in the build.zig file and adding const rl = @import("raylib"); to the top of my main.zig file doesn't work, it gives the error: src/main.zig:2:20: error: no package named 'raylib' available within package 'root'; const rl = @import("raylib");

I think i'm missing something obvious here, but I've been trying to solve this myself all day and haven't come across any examples of how to do this, so thought it was time to ask the question here. Any help would be greatly appreciated.

wraith prairie
#

You need to add the raylib module to the exe.

ionic sail
#

like this? exe.addModule("raylib", raylib.module("raylib"));

#
pav@deb12:~/git/personal/raylib-zig$ zig build run
thread 591780 panic: unable to find module 'raylib'
/usr/local/zig/lib/std/debug.zig:373:22: 0x37f8b9 in panicExtra__anon_43830 (build)
    std.builtin.panic(msg, trace, ret_addr);
                     ^
/usr/local/zig/lib/std/debug.zig:348:15: 0x353319 in panic__anon_26466 (build)
    panicExtra(null, null, format, args);
              ^
/usr/local/zig/lib/std/Build.zig:1707:18: 0x326f37 in module (build)
            panic("unable to find module '{s}'", .{name});
                 ^
/home/rexxy/git/personal/grey-cards/build.zig:34:42: 0x2de9a7 in build (build)
    exe.addModule("raylib", raylib.module("raylib"));
                                         ^
/usr/local/zig/lib/std/Build.zig:1855:33: 0x2cc873 in runBuild__anon_7113 (build)
        .Void => build_zig.build(b),
                                ^
/usr/local/zig/lib/build_runner.zig:301:29: 0x2c8595 in main (build)
        try builder.runBuild(root);
                            ^
/usr/local/zig/lib/std/start.zig:379:37: 0x2b3ad5 in posixCallMainAndExit (build)
            var i: usize = 0;
                                    ^
/usr/local/zig/lib/std/start.zig:251:5: 0x2b35c1 in _start (build)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x5 in ??? (???)
Unwind information for `???:0x5` was not available, trace may be incomplete

error: the following build command crashed

This is the error i got when trying to do that

wraith prairie
#

You would have to check in raylib's build.zig how the module is called.

#

I'm not familiar with raylib so I can't help you with the specifics.

ionic sail
#

what are we looking for in there?>

#

but also, this goes to the title of my question here. How does the .zon build actually work? and where is the build artifacts being stored?

#

because clearly its pulling down the .tar.gz and it builds it using the build.zig

wraith prairie
#

Ok I think I see. This package is just the C library not the bindings, so there's no module to consume, only the static lib.

#

If this package exported a module there would be a b.addModule() call somewhere.

ionic sail
#

right. and so i guess the build script i have is doing what its suppose to be doing, its linking the static library. but how do i import that into my main.zig ?

wraith prairie
#

You would @cImport the appropriate headers.

ionic sail
#
    .dependencies = .{
        .raylib = .{ 
            .url = "https://github.com/raysan5/raylib/archive/bc15c19518968878b68bbfe8eac3fe4297f11770.tar.gz",
            .hash = "122093954b8c911e507de32d83a2046e122c6aca64e71f5244d54f9bbb93730c3ab7"
        },

How do i turn this, into usable code?

#

right

#

but where are those headers?

wraith prairie
#

They should already be added to the include path when you link the static library.

ionic sail
#

because i have them in the zig-cache folder after my build works. but thats not useful to import from there because those folder names change?

#

thats what i assumed should happen, but it didnt work

#

let me rerun with that code to see what the error was, i had forgotten

#
const rl = @cImport({
    @cInclude("raylib.h");
    @cInclude("raymath.h");
    @cInclude("rlgl.h");
});

gives me this:

src/main.zig:14:7: error: root struct of file '.home.pav.git.personal.raylib-zig.zig-cache.o.acb02e85e3de5cec59f7601928d8dbf1.cimport' has no member named 'initWindow'
    rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - basic window");
    ~~^~~~~~~~~~~
#

which kind of indicates that its not being imported correctly. because that function is absolutely in the header file in the zig-cache folder

wraith prairie
#

Can you open up the c import file and check what's in there?

#

Zig is finding the headers, otherwise the error would be different.

#

Like header not found

inner summit
#

the function is InitWindow not initWindow

ionic sail
#

weirdddd

#

why does it change the function name capitalisation?

inner summit
#

it doesnt

#

raylib uses PascalCase

ionic sail
#

well first of all, thank you both for your help!

#

i think something is definitely still broken though, lol. i can now compile and run, but vscode is super unhappy

#

there is no auto complete either for raylib stuff

#

but anyway, thats unrelated to this thread. you've fixed my dependency issue. and i really appreciate it

wraith prairie
#

Yeah, zls sometimes doesn't work properly with c import stuff.

neat summit
#

zls: someone reported a similar issue a couple of days ago;
"... this is caused by ZLS running translate-c before the build runner was able to resolve the include directories. Building ZLS with -Dsingle-threaded should work around this issue."

worthy plinth
#

works for me (even with zls)

ionic sail
#

@worthy plinth does auto complete work for you too?

ionic sail
#

ok cool. something is broken with my zls and vscodium then. because my build file looks the same as that example now and the build does work (and i can run the my first window example)

ionic sail
ionic sail
#

I guess the next challenge for me is figuring out how to enable raygui in my project 😄 i can see that the raylib build.zig has an option struct with bools to turn on and off different parts of raylib, but i havn't had success in using that struct inside my own projects build.zig file

#

i want to see that to true in my own build.zig file

worthy plinth
ionic sail
#

right, but what does that look like in my own build.zig file? can we access that struct like that? or are we relying on the standard options?

worthy plinth
#

in the .{} when you call dependency you can pass the option as a field

ionic sail
#
    // Add raylib as a dependency. We pull this down from the url in build.zig.zon
    const raylib_module = b.dependency("raylib", .{
        .optimize = optimize,
        .target = target,
        .options = {
            "raygui" = true;
        }
    });

this clearly doesn't work 😛

worthy plinth
#

.raygui = true

#

only that

#

b.option will generate a field with an option of type T

#

will not do any kind of inside thing

ionic sail
#
    // Add raylib as a dependency. We pull this down from the url in build.zig.zon
    const raylib_module = b.dependency("raylib", .{
        .optimize = optimize,
        .target = target,
        .raygui = true,
    });

So to be clear, are you saying that is how we access the option struct from our own build script?

worthy plinth
#

yea

ionic sail
#
pav@deb12:~/git/personal/raylib-zig$ zig build run
raylib.install ../raygui/src/raygui.h to raygui.h: error: unable to update file from '/home/pav/.cache/zig/p/raygui/src/raygui.h' to '/home/pav/git/personal/raylib-zig/zig-cache/i/637755593f519be4b3613489b67dd79c/include/raygui.h': FileNotFound
#

oh, is raygui a completely seperate dependency i need to add to the .zon file too?

worthy plinth
#

looks like it

#

Funny enough, you can't since it does not have build.zig

#

lol

#

but since is just a header file

#

I think you could just copy it?

#

copy it and add the include to the exe?

ionic sail
#

ah ok yup makes sense. will do! thanks!

worthy plinth
#

Yeah, seems just a bit weird lol

#

I think is that the build.zig wasn't thought for that

#

lol

#

Oh it expects something weird

#

it expectes that raygui has an adjacent folder with raygui as a project

#

?????

#

ok, the solution is ez

#

just don't use the raylib thing from the build.zig of raylib

#

instead

ionic sail
#

oh?

worthy plinth
#

give me a sec

#

and I update my example

ionic sail
#

i will eagerly await your example then 🙂

worthy plinth
#

Done

#

@ionic sail

ionic sail
#

awesome! thanks so much!

worthy plinth
#

yeah, just a weird thing from raylib

#

lol

ionic sail
#

do you think there is a way to do this with using raygui as a dependency instead of putting the header file in the repo itself?

#

i dont fully understand how the package manager works. but when we put a dependency in the .zon file, im assuming it pulls down the source, and so we WOULD have access to the header file at build time right?

#

and so in my head, im imagining we would only need tiny little tweaks to your example to do so?

#

or does the zig package manager only work for projects that include a build.zig file?

#

i really need to learn what this package manager is doing under the hood

#

because i cant even figure out if its downloading the source from raygui

#

it doesn't complain about the hash being wrong, even though i know it is....

ionic sail
#

something like this? i feel like this is close. but as per the 2x TODO comments, i can't get the path right for the raygui.h header file

#
// Add in any project dependencies. We pull these down from the urls in build.zig.zon
    const raylib_module = b.dependency("raylib", .{
        .optimize = optimize,
        .target = target,
        // Add in optional modules in raylib
        .raudio = true,
        .rmodels = true,
        .rshapes = true,
        .rtext = true,
        .rtextures = true,
        // we need to have raygui as a seperate dependency because the current build script
        // in raylib for including raygui is broken :( Raylib raygui.c supposes that raygui 
        // is in a nearby directory, this is not true using the package manager
        .raygui = false,
        .platform_drm = false,
    });

    // We can use the header file from the raygui repo. But it doesn't 
    // have a build.zig script, so we need to manage that seperately
    const raygui_module = b.dependency("raygui", .{
        .optimize = optimize,
        .target = target,
    });
    // We won't actually use the module, but it seems to be needed to trigger the 
    // package manager to download the repo 
    _ = raygui_module;

    // We need to generate the implementation for raygui.h in raygui.c
    // see here: https://github.com/raysan5/raylib/blob/bc15c19518968878b68bbfe8eac3fe4297f11770/src/build.zig#L60  
    const generate_file_raygui_c = b.addWriteFiles();
    // TODO: This needs to be a path releative to wherever the raygui_module got downloaded to. How do I find that path??
    const generated_file = generate_file_raygui_c.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
    // Since this repo doesn't have a build.zig, it doesn't seem like we can use the raygui_module
    // Instead we will add it as a static library to link to the exe later
    const raygui_lib = b.addStaticLibrary(.{
        .name = "raygui",
        // TODO: This is the generated c file, But how do i ensure the header file is in the same directory??
        .root_source_file = generated_file,
        .link_libc = true,
        .optimize = optimize,
        .target = target,
    });
    raygui_lib.step.dependOn(&generate_file_raygui_c.step);

    // This is where we specify the main executable
    const exe = b.addExecutable(.{
        .name = "raylib-zig",
        // In this case the main source file is merely a path, however, in more
        // complicated build scripts, this could be a generated file.
        .root_source_file = .{ .path = "src/main.zig" },
        .target = target,
        .optimize = optimize,
    });

    // We need to link any of the depedencys we build
    exe.linkLibrary(raylib_module.artifact("raylib"));
    exe.linkLibrary(raygui_lib);
worthy plinth
#

eventually we will

#

but at the moment we cant

inner summit
#

we can

#

dependency.path

worthy plinth
#

PR my example away please

inner summit
ionic sail
#

@inner summit are you saying there is a field .path on our depedency modules that i can just use to add the header file in a specific place?

inner summit
#

its a function that lets you get a LazyPath from an arbitrary file/dir in a dependency

ionic sail
#

i know im super inexperienced with zig, but this seems like a problem that should be easily doable. All i need is the header file as part of the raylib module i added as a dependency, lmao

#

yeah i think i tried that

#

let me check my commit history one second

#

const generated_file = generate_file_raygui_c.add(raygui_module.path("src/raygui.c"), "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");

#

like that?

inner summit
#

sort of? youd use .path on the header file to get it added to your project somewhere

#

then creating a C source file like that would be a separate thing, no .path

#

honestly i think vendoring raygui is fine, its 1 header and the repo youd be pulling in using the package manager is unnecessary

ionic sail
#

absolutely fair, and very likely what i'll end up doing because i've already spent a full day on this problem.

I guess im mostly just trying to figure out how the package manager works. because zigs awesome feature is being able to use native c code, and now we have an easy way to pull in c repos with the package manager

#

it seems like if i understand how this system works properly, i will easily be able to pull in whatever c code i want to use

worthy plinth
#

so far depends on build.zig existing

#

unless there is a recent change I am unaware of

ionic sail
#

does it though? because we can put any repo we want in the .zon file and it WILL download the repo

#

its essentially a git clone right?

#

we have access to the source SOMEWHERE On our machine

#

actually i know where it is

#

its in the home/.cache/zig

worthy plinth
#

Not really a git clone

#

and yes we know where

ionic sail
#

and the golders are the hases

worthy plinth
#

is just that it's not expressed in the build system

ionic sail
#

the problem is accessing those files during build time, lol

worthy plinth
#

you can ofc doing it

ionic sail
#

and how to link them together

worthy plinth
#

@ionic sail is a matter of getting the file and maybe doing a copy using b.cache.global_cache

#

but it's not the most "pretty" way

inner summit
worthy plinth
#

then it is possible @ionic sail
just that I need to update zig so I would get back into making it into my repo in like 8 hours lol

ionic sail
#

I mean thats up to you. Don't feel obligated to do it just on my behalf. But For me personally like i said this is mostly a quest on learning the build system and package manager. and so any example that comes around i'm absolutely going to check out and see how others do it!

That example @inner summit seems like a great start! i do find it confusing that there is a function that hardcodes all the files though, lol. i need some time to read this further

worthy plinth
inner summit
#

yea

#

the dependency they pulled in is raw sdl, no build.zig

#

they constructed a library directly from the source tree

worthy plinth
#

Zig is only as aware as it's build system is aware of the commands needed to build it

#

So you need to provide the stuff

inner summit
#

i think there was something added recently to make that thing a bit more ergonomic, one sec

ionic sail
#

oh, i think the main thing im missing here is the call to installartifact?

#

oh wait nevermind this doesn't use the exe

#

this is a lib?

worthy plinth
#

line 70

ionic sail
#

yeah thats whati i mean, do i need to do that in my build.zig?

worthy plinth
#

yea

#

lib, executables and object files are instalables

ionic sail
#

or when using an exe we link instead?

worthy plinth
#

Oh, well, you can just link it

#

like I do

#

My raygui.h is just for linking purposes

#

Someone should update raylib build.zig

inner summit
#

save some typing

ionic sail
#

can i circle back to something real quick

#

when we put a dependency in the .zon file, what do we need to do inside the build.zig file for it to go out and actually download the .tar.gz into our cache folder?

#

i guess what im trying to explicitly ask is, do we need to have a b.dependency with a name that matches the name in the .zon file? is that how it works?

inner summit
#

atm it downloads it unconditionally as far as im aware, what you do in build.zig doesnt matter

worthy plinth
#

^

ionic sail
#

ok, thats a big assumption i was getting wrong then!

inner summit
ionic sail
#

wait a second, lol

#

if the package manager downloads dependencys regardless, then how does the build system actually know what we are trying to link in?

#

we just specify a name and some default options basically? how does that match up to actual files in the cache?

inner summit
#

like you asked earlier, its basically like a git clone
it downloads the dependency folder into zig cache then hashes the contents, if it mashes the hash in your zon file, it stays, otherwise its deleted and errors
when you run you zig build and declare your different dependencies and what modules/artifacts you want it basically calls the build.zig of the dependency
that build.zig declares things like modules and libraries and depending on how theyre declared, exposes them to your build.zig

#

then if the thing you asked for in your build.zig exists in the dependency it builds that thing and then you link it/add it however you want

worthy plinth
#

also reusing hashes will result in collisions that makes it so when calling something that expects X package to be downloaded fail

ionic sail
#

so i have 2 folders in my cache, and both contain /src folders. when i say link src/x.c will it just check both folders?

inner summit
#

no its based off of the dependency in your zon file which is linked to a hash

#

each dependency in zigs cache has the name of its hash

#

so when you do b.dependency("raylib") it returns a dependency that is linked to what is called "raylib" in your zon

ionic sail
#

right, but in the build.zig file, i dont mention a hash. so how does const raylib_module = b.dependency("raylib", .{ .optimize = optimize, .target = target} match to the correct folder in my cache?

#

oh so it does have to match the .zon name

inner summit
#

yea

ionic sail
#

right i must have misunderstood the answer before because i asked that and i thought it didnt matter, lol

#

yeah that makes much more sense

#

ok, i have much more to read about, but this thread definitly has given me a much better general understanding of the package manager and build system

#

i am hugely appreciative of all of you.

#

thanks so much

inner summit
#

np

#

its understandable to be confused, really none of this is documented at all

inner summit
ionic sail
#

early adopter pains i guess