DEV Community

Cover image for You have been zigged (series) : Linking a library statically and dynamically
Black Tornado
Black Tornado

Posted on

You have been zigged (series) : Linking a library statically and dynamically

Static linking

In this blog, we will explore how to link a zig library statically and dynamically.

First lets create a library that contains a function my_add that adds two numbers. Note that instead of pub keyword which we used in previous blog, we will be using export keyword to decorate the my_add function. This tells the zig compiler to expose the my_add function through C ABI.

// libraries__add.zig
export fn my_add(num1: i32, num2: i32) i32 {
    return num1 + num2;
}
Enter fullscreen mode Exit fullscreen mode

Build the libraries__add.zig file as a static library using the command zig build-lib -O ReleaseSafe libraries__add.zig. This will output a liblibraries__add.a file on current folder if you are using linux or libraries__add.dll file if you are on windows.

To use this my_add function in our main code to add numbers, we will declare the my_add function's signature in main code using extern keyword. Then at compile time, we will tell the zig compiler to link the liblibraries__add.a/libraries__add.dll with our main output.

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

extern fn my_add(num1: i32, num2: i32) i32;

pub fn main(init: std.process.Init) !void {
    // setting up stdout writer
    var buffer: [1024]u8 = undefined;
    var file_writer = std.Io.File.Writer.init(.stdout(), init.io, &buffer);
    var stdout_writer = &file_writer.interface;

    try stdout_writer.print("{}+{}={}\n", .{ 5, 6, my_add(5, 6) });
    try stdout_writer.flush();
}
Enter fullscreen mode Exit fullscreen mode

Let's build our main code and link liblibraries__add.a/libraries__add.dll with the output using zig build-exe libraries__main1.zig liblibraries__add.a or zig build-exe libraries__main1.zig libraries__add.dll.

The above command will produce a libraries__main1 which when executed will print 5+6=11.

Once libraries__main1 is created, we can delete the liblibraries__add.a/libraries__add.dll file and the libraries__main1 executable will still work. This is because the library was linked statically - the entire library was copied to the final executable. Advantage of doing static linking is creation of a final binary that has no runtime dependency. Disadvantage is duplication across binaries and increased file size. Hence dynamic linking.

Dynamic linking

To dynamically link liblibraries__add.a/libraries__add.dll with libraries__main1, we pass -dynamic flag to the zig compiler when building libraries__add.zig. The build command will look like zig build-lib -O ReleaseSafe -dynamic libraries__add.zig. This will produce a liblibraries__add.so in linux and libraries__add.dll in windows. Even though the file extension is same as earlier in windows, the DLL will be position independent code. The build command for libraries__main1.zig is same. But the difference is that the liblibraries_add.so/libraries__add.dll will be dynamically linked. This means the final executable libraries__main1 will work only if it can find liblibraries_add.so/libraries__add.dll. If not, it will fail.

Thanks for reading. To be continued.

Top comments (0)