#Can we detect availability of module/package at comptime?

1 messages · Page 1 of 1 (latest)

forest lagoon
#

I have a package praxis that doesnt use SDL, but in one small place, one parent project needs praxis to have SDL.

Can I put SDL into the praxis package, and have some kind of comptime check that adds a function if SDL exists?

i.e. something like:

if (builtin.haspackage("SDL")) {
    const sdl = @import("SDL");
    pub fn load_game_asset_via_sdl(...) {
       // Load using SDL cross platform read/write helpers
    }
}
pub fn load_game_asset_local(...) {
    // Load with normal std file read/write
}

But I am also wondering if this even makes sense, because perhaps you could say this special function would simply not be compiled if its never used by the parent package. Does that make sense?

#

Thinking about it more, you would need a comptime check if you wanted to do this yes?

if (builtin.haspackage("SDL")) {
    const sdl = @import("SDL");
    pub fn load_game_asset(...) {
       // Load using SDL abstraction
    }
}
pub fn load_game_asset(...) {
    // Load with normal zig file read/write
}
keen jackal
#

something I do in my project is I do is export some things from my root file

pub const imgui = @import("imgui");

and then any dependency can use it by checking if the root module has imgui, ie

if(@hasDecl(@import("root"), "imgui") {
    imgui.abcd();
}

in your case, it would be

pub fn load_game_asset_sdl(...) {
   if (!@hasDecl(@import("root"), "SDL")) @compileError("requires sdl");
   // Load using SDL cross platform read/write helpers
}
pub fn load_game_asset(...) {
    // Load with normal std file read/write
}
#

an alternative to consider if load_game_asset only needs to read one file is to have the caller read the file and pass the contents to load_game_asset

forest lagoon
#

So conceptually, you are saying you set a "variable" in the build.zig for some cases?

#

I need to look up hasDecl

keen jackal
#

it's not in the build.zig, it's in the root file of your root module

forest lagoon
#

Oh, so you use hasDecl to check if something exists that SDL would provide, to know if SDL is in there

#

Because thinking about it, I probably actually want:

pub fn load_game_asset(...) {
    if (@hasDecl("SDL ??? TBC")) {
        const sdl = @import("SDL");
           // Load using SDL abstraction
        }
    } else {
    // Load with normal zig file read/write
    }
}
keen jackal
forest lagoon
#

I probably want something weird like @hasDecl(@import("sdl")) to see if the project can even see SDL in the first place.... But I'm still a noob at this so I don't know what I want.

keen jackal
#

hasDecl checks if a struct has a declaration

const MyStruct = struct {
    pub const one = 1;
};

comptime {
    @compileLog(@hasDecl(MyStruct, "one")); // true
    @compileLog(@hasDecl(MyStruct, "two")); // false
}
#

@import("root") returns the root file of the root module in your project (except in a test)

// main.zig
pub fn main() !void {

}
pub const something = 25;

// some_other_file.zig
const root = @import("root");
root.main; // the main function
root.something; // 25
forest lagoon
#

Yea, but I guess I am saying I don't even want SDL in my mega/general shared praxis library and force every single other project ot need SDL indirectly becasue praxis needs it.

#

So I was imagining that my shared library could be optinally told to use it (by the parent project that sucks it in)

#

So I guess I wanted the parent project to some how tell the child library if it should include it or not.

keen jackal
#

yeah, with the method I'm describing it would be like that

#

but it's not the parent project, it's the supermost parent project

forest lagoon
#

ok, neat!! I`ll create a little test project and muck aorund with it. much appreciated.

faint plume
#

alternatively, you could use build options

keen jackal
#

^ that plus a lazy dependency would work too

forest lagoon
#

Yea I get I could use build options, but I was hoping for a more "magic" way like this, if one exists

faint plume
#

build options lets you do this neat trick as well
const sdl = if (build_options.use_sdl) @import("sdl") else unreachable;

keen jackal
#

imo my method is pretty magic

forest lagoon
#

Yep, understood, I just need to try it out for real in a test project to work it out.

faint plume
keen jackal
#

zig will ban @import() with a module specifier that isn't imported

forest lagoon
#

Thanks, y'all always have helpful pointers that make learning zig easier.

faint plume
keen jackal
#

same way @import("doesnt_exist.zig") isn't allowed even if it's not referenced

faint plume
#

well rip

#

that makes some things pretty annoying

keen jackal
#

you would have to conditionally define the module to be an empty module in build.zig