JulNadeauCA / libagar

Cross-Platform GUI Toolkit (stable)
https://libagar.org/
BSD 2-Clause "Simplified" License
401 stars 42 forks source link

Zig build fails due to undeclared identifiers #79

Closed clsource closed 7 months ago

clsource commented 7 months ago

Hello, I'm experimenting with Agar and Zig lang. For some reason I cannot compile.

It seems something undefined in AG_TAILQ_LAST, AG_TAILQ_PREV and AGOBJECT_LAST_CHILD.

These are some errors I got:

error: use of undeclared identifier 'struct_headname'
pub inline fn AG_TAILQ_LAST(head: anytype, headname: anytype) @TypeOf(@import("std").zig.c_translation.cast([*c]struct_headname, head.*.tqh_last).*.tqh_last.*) {
error: use of undeclared identifier 'struct_headname'
pub inline fn AG_TAILQ_PREV(elm: anytype, headname: anytype, field: anytype) @TypeOf(@import("std").zig.c_translation.cast([*c]struct_headname, elm.*.field.tqe_prev).*.tqh_last.*) {
error: use of undeclared identifier 'struct_t'
pub inline fn AGOBJECT_LAST_CHILD(@"var": anytype, t: anytype) [*c]struct_t {

To replicate these are the files I am using:

Makefile

PKG_CONFIG_PATH=pc/
PKG_LIBAGAR=${PKG_CONFIG_PATH}libagar.pc
AGAR_VERSION=`agar-config --version`
AGAR_CFLAGS=`agar-config --cflags`
AGAR_LIBS=`agar-config --libs`

build b:
    @make config
    PKG_CONFIG_PATH=${PKG_CONFIG_PATH} zig build

config c:
    @mkdir -p ${PKG_CONFIG_PATH}
    @echo "Name: libagar" > ${PKG_LIBAGAR}
    @echo "Description: LibAgar is a cross-platform GUI system. It provides a base framework and a standard toolkit of widgets from which high-performance, portable graphical applications can be built." >> ${PKG_LIBAGAR}
    @echo "Version: ${AGAR_VERSION}\n" >> ${PKG_LIBAGAR}
    @echo "Requires:" >> ${PKG_LIBAGAR}
    @echo "Libs: ${AGAR_LIBS}" >> ${PKG_LIBAGAR}
    @echo "Cflags: ${AGAR_CFLAGS}" >> ${PKG_LIBAGAR}
    @echo ${PKG_LIBAGAR}

build.zig

const std = @import("std");

// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) void {
    // Standard target options allows the person running `zig build` to choose
    // what target to build for. Here we do not override the defaults, which
    // means any target is allowed, and the default is native. Other options
    // for restricting supported target set are available.
    const target = b.standardTargetOptions(.{});

    // Standard optimization options allow the person running `zig build` to select
    // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
    // set a preferred release mode, allowing the user to decide how to optimize.
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "agar-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,
    });

    exe.linkLibC();

    // Add our custom libagar pkg-config libs and cflags to the zig build
    exe.linkSystemLibrary2("libagar", .{ .use_pkg_config = .force });

    // This declares intent for the executable to be installed into the
    // standard location when the user invokes the "install" step (the default
    // step when running `zig build`).
    b.installArtifact(exe);

    // This *creates* a Run step in the build graph, to be executed when another
    // step is evaluated that depends on it. The next line below will establish
    // such a dependency.
    const run_cmd = b.addRunArtifact(exe);

    // By making the run step depend on the install step, it will be run from the
    // installation directory rather than directly from within the cache directory.
    // This is not necessary, however, if the application depends on other installed
    // files, this ensures they will be present and in the expected location.
    run_cmd.step.dependOn(b.getInstallStep());

    // This allows the user to pass arguments to the application in the build
    // command itself, like this: `zig build run -- arg1 arg2 etc`
    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    // This creates a build step. It will be visible in the `zig build --help` menu,
    // and can be selected like this: `zig build run`
    // This will evaluate the `run` step rather than the default, which is "install".
    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);

    // Creates a step for unit testing. This only builds the test executable
    // but does not run it.
    const unit_tests = b.addTest(.{
        .root_source_file = .{ .path = "src/main.zig" },
        .target = target,
        .optimize = optimize,
    });

    const run_unit_tests = b.addRunArtifact(unit_tests);

    // Similar to creating the run step earlier, this exposes a `test` step to
    // the `zig build --help` menu, providing a way for the user to request
    // running the unit tests.
    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&run_unit_tests.step);
}

src/main.zig

const std = @import("std");

const c = @cImport({
    @cInclude("stdio.h");
});

const agar = @cImport({
    @cInclude("agar/core.h");
    @cInclude("agar/gui.h");
});

pub fn main() !void {
    if (agar.AG_InitCore(c.NULL, 0) == -1) {
        c.fprintf(c.stderr, "Agar Core Init failed: %s\n", agar.AG_GetError());
        return 1;
    }

    if (agar.AG_InitGraphics(0) == -1) {
        c.fprintf(c.stderr, "Agar Graphics Init failed: %s\n", agar.AG_GetError());
        return 1;
    }

    const win = agar.AG_WindowNew(0);
    agar.AG_LabelNew(win, 0, "Hello, world!");
    agar.AG_WindowShow(win);
    agar.AG_EventLoop();

    return 0;
}

How to replicate

imagen

Create the files and then execute make build.

clsource commented 7 months ago

So I asked in Zig discord about this, and this was the response.


From: tomck5836 https://discord.com/channels/605571803288698900/1036403458305163384/1229840153279725618

Normally this kind of error occurs when you're trying to import a c header which contains complex stuff like macros, or static/inline functions which zig cannot properly translate to zig

Does libagar intentionally provide zig support? If not, they can't do anything to help + you're best off deleting the issue. This is not a problem with libagar (unless they explicitly say they support zig)

your options are:

The @cImport stuff is just a shortcut that zig has to automatically try and import c headers. You can just write your own bindings with export fn (...), getting all the function signatures to match up.


So I guess for properly using libagar with zig I have to create zig bindings 💯