How to compile project that uses external .so library using build.zig in version 0.16 dev?

Hello, I was trying to compile my project that uses external shared library .so but still no luck. I have tried to ask LLM, no one can give correct answer. I have tried to read the doc but I can not find tutorial about external .so lib, I only found tutorial for linking C file. How to do it?

A .so is a shared object/library which is loaded at runtime. In Zig, you can use std.Dynlib for this.

You probably want to add linkSystemLibrary in your build.zig: Zig Build System ⚔ Zig Programming Language

Or load it at runtime with std.DynLib.

1 Like

Is there a reason to use 0.16 dev now that 0.16.0 stable has been out for a few months?

1 Like

My bad, my goal is to link them at compile time. That means static library .a right? How to do it?

Can it be used for linking at compile time static library?

It is just me lazy to manually update and not ready for breaking change. I think there should easy way to update, like

zig update stable to update to latest stable

zig update unstable to update to latest unstable

zig update latest repo to update to latest one that is in the repository

And to switch between them easily

zig switch stable

zig switch unstable

zig switch latest repo

I think there should easy way to update, like

Just use a version manager like zvm or anyzig:

A builtin feature might be useful (e.g. rewrite the top-level Zig exe to just be a very small shim which knows how to install and update the actual Zig toolchain into a global package cache), but OTH those external version managers also work just fine.

PS edited, apparently zigup has been replaced by anyzig

That doesn’t seem to cover getting an unstable version of an alread released/stable version. I could understand if you used 0.17 dev (unstable) and 0.16 non-dev (ie. stable), but not that you are still using a 0.16 dev version.

Using an old dev-version sounds like an extremely esoteric edge case though, why would anybody do that? :smiley:

In general the version managers use map files like this to find versions, and those don’t list dev-versions for older stable versions:

https://ziglang.org/download/index.json

At least ZVM lets you point to different JSONs though, so you can basically maintain your own mappings which pin specific older dev-versions:

Did you read my reply above or just directly typing?

Already said I’m lazy to update it manually. In the past, when I installed that, it was the newest dev version, no stable 0.16 was even around, it was the newest version. Then I stopped using the language for months. Then I just started using it for simple test, got error, tried to fix the error. Not interested to update the language because I was just lazy

Did you read my reply above or just directly typing??

Already said I’m lazy to update it manually. In the past, when I installed that, it was the newest dev version, no stable 0.16 was even around, it was the newest version. Then I stopped using the language for months. Then I just started using it for simple test, got error, tried to fix the error. Not interested to update the language because I was just lazy

why do you spam the same comment twice?

I don’t think @floooh was talking to you, the reply is to @Anthon.

Even if it was the case, you could just write one reply and mention more than one person.

2 Likes

Yes, I did read your reply, but was probably distracted too much by the non-relevant (to my question) information about how you think zig should be self-updating.

With the additional information you provided, I now realise what you meant that you haven’t updated zig from 0.16 dev because you have been a to lazy. As a non-native speaker of English I had problems processing ā€œIt is just me lazy to manually updateā€ as conveying that information. Apologies.

I don’t think you can statically link to a .so file (even with C). They are shared objects for dynamic linking only.

As @cancername said, you can use linkSystemLibrary as described in the docs. You can then request static linking using

  foo.linkSystemLibrary("barlib", .{ preferred_link_mode = .static });

to get static linking if there’s a static library available (a .a file).

It depends on platform and what one exactly means with static vs dynamic linkage :wink:

Both on Windows (with MSVC) and on Linux (with GCC/Clang) you can link a dynamic library with the same linker option as a static library, but what happens underneath is radically different between Windows and Linux (on Windows, MSVC links against a static library stub which at runtime does a LoadLibrary and one GetProcAddress per public function, while on Linux both static and dynamic libraries are linked with -lfoo but the linking is a two-step process, the first half happens at link time, the second half is done by a dedidcated ā€˜dynamic linker’ at runtime when the executable is loaded.

The other option is of course to do the DLL loading manually via LoadLibrary or dlopen (this is often the better option when you don’t know at build time whether the DLL is installed on the system, or if you want to dynamically decide which DLL to load (for instance D3D11 vs OpenGL vs Vulkan DLLs).

As for the Zig build system, I’m pretty sure that the regular exe.linkLibrary() also works for DLLs, the difference to linkSystemLibrary() is that one expects a build system compile step as arg, and the other a name string.

I don’t think any of that qualifies as static linking. It’s all just dynamic linking with different trampolines.

  • ld.so (or the windows equivalent) loads the .so/.dll and links at runtime – automatic dynamic linking
  • Program statically links libdl (or the windows equivalent) and uses it to load a shared library. Then looks up function pointers – manual dynamic linking
  • Program statically links a stub library which loads the shared library at runtime and jumps to function pointers – semi-automatic dynamic linking.

They all execute library code found at runtime on the users machine.

Static linking means (to me) that the library code ships inside the executable, and not in a system library. It executes the library code that was found at build time on the developer’s machine.

To statically link a shared object would mean the code contained within the shared object on the developers machine became part of the shipped binary. No loading of shared objects at runtime.

My bad, I saw his reply referenced my post, I thought he replied to me :[

I just realized you two talked about the tool wouldn’t need to support installing older version of Zig :v

But I think that is neccerery feature, because it allows to rollback version easily, like you want to test the newest version, then after knowing it has breaking changes you can rollback to the older version if neccerery