Zig NEWS

Jean-Pierre
Jean-Pierre

Posted on • Updated on

creat library for application

my first publication:

I wrote this article because I encountered a major obstacle and truly needed to make the library code independent and accessible for multiple executables. I couldn't have achieved this on my own; version 0.12 represents a significant advancement. The "MAKE" alias build code, on the other hand, is much more coherent and easier to read.

thank you : castholm [](https://ziggit.dev/u/castholm/summary

zig 0.12.0 dev 2024-02

POJECT
        library/
            cursed.zig
            .....x.zig
            library.zig
            build.zig
            build.zig.zon
        src-zig/
            Exemple.zig
            exCallpgm.zig
            buildExemple.zig
            buildexCallpgm.zig
            build.zig.zon
Enter fullscreen mode Exit fullscreen mode

"library": is a directory that contains all the zig files and functions as the underlying engine. It includes a function named "build", along with "build.zig.zon" and "library.zig" files.

Particularities:

"build",This name is mandatory, a prerequisite for the compiler in your project to execute it.
(Do not do as I did and I was going around in circles ;))

    const std = @import("std");
// zi=g 0.12.0 dev

pub fn build(b: *std.Build) void {


    const cursed_mod = b.addModule("cursed", .{
        .root_source_file = .{ .path = "cursed.zig" },
    });

    const utils_mod = b.addModule("utils", .{
        .root_source_file = .{ .path = "utils.zig" },
    });

    const match_mod = b.addModule("match", .{
        .root_source_file = .{ .path = "match.zig" },
    });

    const callpgm_mod = b.addModule("callpgm", .{
        .root_source_file = .{ .path = "callpgm.zig" },
    });

    const forms_mod = b.addModule("forms", .{
        .root_source_file = .{ .path = "forms.zig" },
        .imports= &.{
        .{ .name = "cursed", .module = cursed_mod },
        .{ .name = "utils",  .module = utils_mod},
        .{ .name = "match",  .module = mThis name is mandatory, a prerequisite for the compiler in your project to execute it.
(Do not do as I did and I was going around in circles ;))atch_mod },
        },
    });

    const grid_mod = b.addModule("grid", .{
        .root_source_file = .{ .path = "grid.zig" },
        .imports = &.{
        .{ .name = "cursed", .module = cursed_mod},
    This name is mandatory, a prerequisite for the compiler in your project to execute it.
(Do not do as I did and I was going around in circles ;))   .{ .name = "utils",  .module = utils_mod},
        },
    });

    const menu_mod= b.addModule("menu", .{
        .root_source_file = .{ .path = "menu.zig" },
        .imports= &.{
        .{ .name = "cursed", .module = cursed_mod},
        .{ .name = "utils",  .module = utils_mod},
        },
    });


    const library_mod = b.addModule("library", .{
        .root_source_file = .{ .path = "library.zig" },
        .imports = &.{
        .{ .name = "cursed",    .module = cursed_mod },
        .{ .name = "utils",     .module = utils_mod },
        .{ .name = "match",     .module = match_mod },
        .{ .name = "callpgm",   .module = callpgm_mod },
        .{ .name = "forms",     .module = forms_mod },
        .{ .name = "grid",      .module = grid_mod },
        .{ .name = "menu",      .module = menu_mod },


        },
    });

    match_mod.addIncludePath(.{.path = "./lib/"});
    match_mod.link_libc = true;
    match_mod.addObjectFile(.{.cwd_relative = "/usr/lib/libpcre2-posix.so"});

    _ = library_mod;


}

Enter fullscreen mode Exit fullscreen mode

addModule (do not use CreateModule)
=>import (do not use dependency)

If you have libraries written in "C"

    match_mod.addIncludePath(.{.path = "./lib/"});
    match_mod.link_libc = true;
    match_mod.addObjectFile(.{.cwd_relative = "/usr/lib/libpcre2-posix.so"});
Enter fullscreen mode Exit fullscreen mode

The file "build.zig.zon" is required, it remains in its most basic form.< /br>
< /br>

.{
    .name = "library",
    .version = "0.0.0",
    .dependencies = .{},
    .paths = .{
        "",
    },
}
Enter fullscreen mode Exit fullscreen mode

The file "library.zig" contains all the modules that form your library. Its particularity is to make the constant linked to the import "pub".

pub const cursed    = @import("cursed");
pub const utils     = @import("utils");
pub const match     = @import("match");
pub const forms     = @import("forms");
pub const grid      = @import("grid");
pub const menu      = @import("menu");
pub const callpgm   = @import("callpgm");
Enter fullscreen mode Exit fullscreen mode

Now, the program part:

In the "src-zig" directory:

The "build.zig.zon" file is mandatory,

.{
    .name = "program",
    .version = "0.0.0",
    .dependencies = .{
        .library = .{
            .path = "../library",
        },
    },
    .paths = .{
        "",
    },
}
Enter fullscreen mode Exit fullscreen mode

The "buildExample" file:

const std = @import("std");
// zig 0.12.0 dev

pub fn build(b: *std.Build) void {
    // Standard release options allow the person running `zig build` to select
    // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
    const target   = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // Building the executable

    const Prog = b.addExecutable(.{
    .name = "Exemple",
    .root_source_file = .{ .path = "./Exemple.zig" },
    .target = target,
    .optimize = optimize,
    });

    // Resolve the 'library' dependency.
    const library_dep = b.dependency("library", .{});

    // Import the smaller 'cursed' and 'utils'... modules exported by the library. etc...
    Prog.root_module.addImport("cursed", library_dep.module("cursed"));
    Prog.root_module.addImport("utils", library_dep.module("utils"));
    Prog.root_module.addImport("match", library_dep.module("match"));
    Prog.root_module.addImport("forms", library_dep.module("forms"));
    Prog.root_module.addImport("grid",  library_dep.module("grid"));
    Prog.root_module.addImport("menu", library_dep.module("menu"));
    Prog.root_module.addImport("callpgm", library_dep.module("callpgm"));

    b.installArtifact(Prog);
}
Enter fullscreen mode Exit fullscreen mode

The peculiarity:

To resolve the dependencies, we need to indicate how:

const library_dep = b.dependency("library", .{});
Enter fullscreen mode Exit fullscreen mode

"library" with its "path" it will fetch and build the object it needs to be linked to your program.
Then, you can declare and connect your modules:

Prog.root_module.addImport("cursed", library_dep.module("cursed"))
...
Enter fullscreen mode Exit fullscreen mode

Your program will work as if it were compiled with the sources, for exemple:

const term = @import(cursed);
const kbd = @import("cursed").kbd;
...
Enter fullscreen mode Exit fullscreen mode

To compile source files within your "src-zig" directory, which may contain multiple sources such as client, invoice, delivery note, etc., it is simpler to use "--build-file" instead of "build".

Here's the command you can use:

zig build --build-file /home/soleil/exemple/src-zig/buildExemple.zig
Enter fullscreen mode Exit fullscreen mode

"code"

Go take a look at a small project, it will help you understand better, nothing beats concrete code.

Top comments (2)

Collapse
 
jefferyhus profile image
Jeffery ThaGintoki

I am so lost on how everyone does have this working except me the compiler screams about error: no field named 'root_module' in struct 'Build.Step.Compile'

Collapse
 
jpl profile image
Jean-Pierre

sorry a typing error

I corrected it, thanks for pointing it out.