I want to create a complex lib

I have a build that works perfectly, but I would like not to have to redefine the design build for each project.

const std = @import("std");
// zi=g 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(.{});

	// zig-src			source projet
	// zig-src/deps		curs/ form / outils ....
	// src_c			source c/c++
	// zig-src/lib		source .h 


	// Definition of module
	const match = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/match.zig" },
	});
	match.addIncludePath(.{.path = "./lib/"});

	const modul = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/modul.zig" },
	});

	const cursed = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/cursed.zig" },
	});
	
	const utils = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/utils.zig" },
	});

	const forms = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/forms.zig" },
		.imports= &.{
		.{ .name = "cursed", .module = cursed },
		.{ .name = "utils",  .module = utils },
		.{ .name = "match",  .module = match },
		},

	});


	const grid = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/grid.zig" },
		.imports= &.{
		.{ .name = "cursed", .module = cursed },
		.{ .name = "utils",  .module = utils },
		},
	});

	
	
	const menu = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/menu.zig" },
		.imports= &.{
		.{ .name = "cursed", .module = cursed },
		.{ .name = "utils",  .module = utils },
		},
	});

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

	Prog.linkLibC();
	Prog.addObjectFile(.{.cwd_relative = "/usr/lib/libpcre2-posix.so"});

	Prog.root_module.addImport("cursed", cursed);

	Prog.root_module.addImport("utils", utils);

	Prog.root_module.addImport("match", match);
	
	Prog.root_module.addImport("forms", forms);
	
	Prog.root_module.addImport("grid" , grid);
	
	Prog.root_module.addImport("menu" , menu);
	
	Prog.root_module.addImport("modul" , modul);

	const install_exe = b.addInstallArtifact(Prog, .{});
	b.getInstallStep().dependOn(&install_exe.step); 



}

The part I would like to make into a library.

	// Definition of module
	const match = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/match.zig" },
	});
	match.addIncludePath(.{.path = "./lib/"});

	const modul = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/modul.zig" },
	});

	const cursed = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/cursed.zig" },
	});
	
	const utils = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/utils.zig" },
	});

	const forms = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/forms.zig" },
		.imports= &.{
		.{ .name = "cursed", .module = cursed },
		.{ .name = "utils",  .module = utils },
		.{ .name = "match",  .module = match },
		},

	});


	const grid = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/grid.zig" },
		.imports= &.{
		.{ .name = "cursed", .module = cursed },
		.{ .name = "utils",  .module = utils },
		},
	});

	
	
	const menu = b.createModule(.{
		.root_source_file = .{ .path = "./deps/curse/menu.zig" },
		.imports= &.{
		.{ .name = "cursed", .module = cursed },
		.{ .name = "utils",  .module = utils },
		},
	});
1 Like

Try to check this:
https://ziglang.org/documentation/master/std/#A;std:Build.dependency

My suggestion would be to just create one library with one module that combines your 7 modules. If you are always going to use these together, than I see no point to separate it into super tiny modules, that always depend on each other anyway.

If you want to keep the separate modules, your library could still expose one unified module of all the things in those 7 as one module, that depends on all of them.

5 Likes

Exactly what I want to do, but I can’t see how. I would have liked to find an example.

Here’s a quick example of a project setup that you could reference to get started:

If we assume the following directory structure:

  • .
    • library/
      • add.zig
      • multiply.zig
      • library.zig
      • build.zig
      • build.zig.zon
    • program/
      • program.zig
      • build.zig
      • build.zig.zon

We want the package named library to export two modules named add and multiply, as well as a convenience module library that re-exports both add and multiply.

// library/add.zig
pub fn addInt(a: i32, b: i32) i32 {
    return a + b;
}
pub fn addFloat(a: f32, b: f32) f32 {
    return a + b;
}
// library/multiply.zig
pub fn multiplyInt(a: i32, b: i32) i32 {
    return a * b;
}
pub fn multiplyFloat(a: f32, b: f32) f32 {
    return a * b;
}
// library/library.zig
pub const add = @import("add");
pub const multiply = @import("multiply");

To export these modules, we need to set up the library package’s build scripts as follows:

// library/build.zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    //  Note:
    // 'b.createModule()' creates a private module.
    // 'b.addModule()' creates a public module that can be imported by other build scripts.

    // Smaller modules that can be imported individually:
    const add_mod = b.addModule("add", .{
        .root_source_file = .{ .path = "add.zig" },
    });
    const multiply_mod = b.addModule("multiply", .{
        .root_source_file = .{ .path = "multiply.zig" },
    });

    // One big module that imports and re-exports the smaller modules:
    const library_mod = b.addModule("library", .{
        .root_source_file = .{ .path = "library.zig" },
        .imports = &.{
            .{ .name = "add", .module = add_mod },
            .{ .name = "multiply", .module = multiply_mod },
        },
    });
    _ = library_mod;
}
// library/build.zig.zon
.{
    .name = "library",
    .version = "0.0.0",
    .dependencies = .{},
    .paths = .{
        "",
    },
}

Now we have everything we need to be able to add library as a dependency.

For our program package which builds an executable, we would like to use the modules exported by the library package like this:

// program/program.zig
const std = @import("std");
const add = @import("add");
const multiply = @import("multiply");

pub fn main() void {
    std.debug.print("{d}\n", .{add.addInt(1, 2)});
    std.debug.print("{d}\n", .{multiply.multiplyFloat(3.3, 4.4)});
}

To add the library package as a dependency, we first add it to program/build.zig.zon:

// program/build.zig.zon
.{
    .name = "program",
    .version = "0.0.0",
    .dependencies = .{
        .library = .{
            .path = "../library",
        },
    },
    .paths = .{
        "",
    },
}

(Side note: .path here is used for relative packages on disk. If you want to fetch a package over the net (for example, from a public git repo), you use the .url and .hash fields. You can run the zig fetch command like zig fetch https://example.com/library.tar.gz --save=library to add these fields automatically. And for more general documentation on build.zig.zon, refer to the output from running zig init or check out the docs in the ziglang repo.)

Finally, update program/build.zig to resolve the dependency and import the modules:

// program/build.zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "program",
        .root_source_file = .{ .path = "program.zig" },
        .target = target,
        .optimize = optimize,
    });

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

    // Import the smaller 'add' and 'multiply' modules exported by the library.
    exe.root_module.addImport("add", library_dep.module("add"));
    exe.root_module.addImport("multiply", library_dep.module("multiply"));

    // But we could also import the larger module if we prefer.
    // In this case we would need to update the imports in 'program.zig'
    // to '@import("library")' directly.
    //exe.root_module.addImport("library", library_dep.module("library"));

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

I hope this is enough as an example to get you started converting some of your source files into a reusable library :smiley:

17 Likes

This is awesome information. May I kindly suggest you spruce it up (if at all necessary) and convert it into a post in the new Docs section?

2 Likes

I will put all of this into action. Thank you for the answers.

I will publish the result

hello, # gonzo
zig version
0.12.0-dev.2586+3c7970dc4

I did as you told me,
here is the message I get.

+ zig build --build-file /home/soleil/exemple/src-zig/buildExemple.zig
error: unable to load package manifest '/home/soleil/exemple/src-zig/libCurse.so/build.zig.zon/': NotDir

build.zig.zon (222 Bytes)

buildExemple.zig (1.3 KB)

Just for your information, the build is done without any library in version 11.
idem message error

@JPL can you please link to a repository instead?

Probably almost nobody, wants to go through the trouble of re-assembling your local state from a whole bunch of separate files.
If you want help, please make it easy for others to help you!

2 Likes

The goal was to work with a library of these objects that can be used or not in an application.
For example, concerning the issue, there are the two builds."

the buildExemple being the program wanting to use the library as specified in a response, but it doesn’t work.

I cleared it, it was to understand the context.

Often, we complain about not having enough substance."

Please create a github repository that contains your example, so that others can help you.

Hopefully google translate is correct on this:
“Veuillez créer un dépôt github qui contient votre exemple, afin que d’autres puissent vous aider.”

When depending on other packages using build.zig.zon, Zig expects the dependency package directories to follow a standard format with a build.zig file and a build.zig.zon file that have those exact names. So you might need to move/rename files like buildCurse.zig so that you end up with a project structure like the following:

  • deps/
    • curse/
      • build.zig (renamed from buildCurse.zig)
      • build.zig.zon
  • exemple/
    • build.zig (renamed from buildExemple.zig)
    • build.zig.zon

Then, you need to change the value of .path in exemple/build.zig.zon to ../deps/curse. The .path field should point to a directory, not a file like build.zig.zon or the name of a compiled output like libCurse.so.

1 Like

hello
this very good thank you #castholm

I reproduced exactly what you did because I didn’t understand why it wasn’t working. Eureka, I found my mistake, and I thank you. Huge relief… lolllll

result :grinning:

build

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 = match_mod },
		},
	});

	const grid_mod = b.addModule("grid", .{
		.root_source_file = .{ .path = "grid.zig" },
		.imports = &.{
		.{ .name = "cursed", .module = cursed_mod},
		.{ .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 = "cllpgm",	.module = callpgm_mod },
		.{ .name = "forms",		.module = forms_mod },
		.{ .name = "grid",		.module = grid_mod },
		.{ .name = "menu",		.module = menu_mod },

			
		},
	});


// include  and lib "C"
	match_mod.addIncludePath(.{.path = "./lib/"});  // regPcre2.h
	match_prod.link_libc =true;
	match_mod.addObjectFile(.{.cwd_relative = "/usr/lib/libpcre2-posix.so"});
	
	_ = library_mod;


}

// my program build

const std = @import("std");
// zi=g 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(.{});

	// library			libary motor
	// zig-src			source projet
	// src_c			source c/c++
	// zig-src/lib		source .h 



	// 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);


}

https://github.com/AS400JPLPC/zig_TermCurs/tree/master/exemple

1 Like