Open floooh opened 1 year ago
Hey, quick update on the current state:
wasm32-emscripten
which is convenient for sokol-zig users to add to their build scripts, but is sort of hacky implemented when it comes to integrating the Emscripten SDK with the Zig build system (I hope to vastly improve the Emscripten linker integration at some later point, also, PRs are always welcome) ;)Here are some example build.zig scripts how it looks now (there are still 2 separate code paths for 'native vs web':
...and this is what the sokol-zig build.zig currently looks like, which also currently contains a lot of Emscripten SDK specific code (this is the one point which could be vastly improved in the future -> move out into a separate emsdk-zig
package, and turn the Emscripten linker step into a proper custom build step, instead of a cobbled together run-step:
Overall, the amount of hacks and workarounds for the wasm32-emscripten
build could be drastically reduced (for instance it's no longer necessary to provide a separate entry.c
file with a C main() function).
Right now I'm happy :)
...ok, apart from a few minor cosmetical/style issues in the "new" build system API, like this:
pacman.root_module.addImport("sokol", dep_sokol.module("sokol"));
...could at least be shorted to this:
pacman.addImport("sokol", dep_sokol.module("sokol"));
It feels a bit less like poking around in the guts of the build system ;)
I wanted to ask how did you solve this problem?
First, I was confused that the CrossTarget and OptimizeMode are not communicated automatically to the dependency builder object, instead I need to pass those in the args: anytype parameter of the std.Build.dependency() function. I think it would be better if all -D options are "inherited" automatically, and the parameter would only be used for overriding or adding build options.
It seems like to me that if one package generates a build flag there's no way to effectively use that build flag in a nested system without leaking that flag to all future potential dependencies.
On @andrewrk's suggestion, I'm opening a similar ticket like https://github.com/ziglang/zig/issues/16672 to document and track the hickups I encountered when bringing https://github.com/floooh/sokol-zig as package into https://github.com/floooh/pacman.zig.
(NOTE: the package manager support is currently in branches:
It might make sense to split this issue into more detailed issues later.
Some background info:
Currently (without package manager integration) sokol-zig can be integrated in two ways:
With the package manager integration it now works like this (but this was quite a bit of trial and error):
std.Build.dependency().module()
std.Build.dependency().artifact()
(writing this I guess it would be nice if I could add a linker dependency to a module, so that I only need to expose the Zig module, which would have a dependency on the C library, so that a project would only need to get the Zig module from the dependency, and this would automatically add a library dependency to the top-level project - but this would currently not work with the way I'm handling the web build).
Communicating build parameters to package manager dependencies
I stumbled over two problems:
First, I was confused that the CrossTarget and OptimizeMode are not communicated automatically to the dependency builder object, instead I need to pass those in the
args: anytype
parameter of thestd.Build.dependency()
function. I think it would be better if all-D
options are "inherited" automatically, and the parameter would only be used for overriding or adding build options.The
--sysroot
arg is passed as-is to the dependency builder object, if the sysroot path is relative to the root poject, everything works fine in the root project, but breaks down in the dependencies. I would suggest either to reject relative paths in--sysroot
, or better, automatically convert relative paths into absolute paths. I currently use this workaround which also works: https://github.com/floooh/pacman.zig/blob/ff3b259f9905f1d16e4fe430552b33c46160d9ab/build.zig#L11-L15Some confusion about using dependency build.zig as import
I had a little detour when I thought that I'm stuck, and imported the dependency's build zig as module (great feature!).
But calling functions in the import also caused some confusion, but I think this just needs to be documented.
std.Build.dependency()
. This caused some problems with relative file paths in the dependency build scripts which disappeared after calling the function with the dependency's builder object.wasm32-freestanding vs wasm32-emscripten
This is a known issue: currently I can't compile the Zig part of pacman.zig with the wasm32-emscripten target because of a problem in the Zig stdlib (see here: https://github.com/ziglang/zig/issues/10836#issuecomment-1666488896), this means I need to "patch" the platform
.emscripten
into the CrossTarget when building the sokol-zig C library (because the C code depends on Emscripten SDK featurs). This means that the Zig parts of the project need to be built withwasm32-freestanding
and the C parts aswasm32-emscripten
(which works, but feels kinda weird).Need to provide C include directory on top of Emscripten sysroot
This might be a simple bug, but I noticed that in order for the C compilation to work, I need to provide a separate header search path derived from the sysroot so that the C stdlib headers are found:
https://github.com/floooh/sokol-zig/blob/24a47f10231e45875452a110aacb78aa1a8e9648/build.zig#L110-L112
Without this, common headers like stdlib.h, string.h etc are not found in the C compile step.
Suggestion: given a sysroot path, the header and library search paths should be setup automatically for C compilation.
Suggestion: better integration of external linkers (like the Emscripten linker)
As I described above, the C code of sokol-zig depends on Emscripten platform features (embedding Javascript code into C source files, and using Emscripten specific headers). For the compilation part this works fine with the Zig compiler by using the
wasm32-emscripten
target, and providing a sysroot which points into the Emscripten SDK, but in the end I need to use the Emscripten linker to get a runnable web build (.html + .js + .wasm files).Currently I create a system command build step to invoke the Emscripten linker like this: https://github.com/floooh/pacman.zig/blob/b26f4f258ee0aa9889098973edc40df04471d9fc/build.zig#L106-L130
It took a while to figure this out, and it's a bit awkward mainly because I need to make all build outputs available as installed artifacts before the Emscripten linker is called, and I need to make sure that all dependencies are setup correctly.
Maybe it makes sense to provide a
ExternalLinkerStep
wrapper for "gcc toolchain compatible linkers" which at least takes care of the dependency setup, and adds the build outputs as-l...
.Emscripten Integration Wishlist
The following are some ideas for the future, and with the package manager infrastructure I think this doesn't need to be part of the Zig core project:
emsdk install [version]
andemsdk activate --embedded [version]
, which would basically make the Emscripten SDK available to Zig projects without "polluting" the user's environment...ideally this would be coordinated with other "SDK/toolchain packages", like:
build.zig.zon wishlist
It would be nice if I could directly use a git-url and git-ref to provide the package content (.tar.gz for any git commit works via "github magic", but it looks a bit messy):
https://github.com/floooh/pacman.zig/blob/sokol-package/build.zig.zon
This is because sokol-zig doesn't have "semver release tags" so far, they are updated automatically on each commit to the main sokol repository, and a single semver version number also doesn't really make sense, because it's actually a collection of libraries (and technically each library would need its own semver version number).
This is also why I hope that the version number in the build.zig.zon file is just "decorative" and won't be used to check if any caches are uptodate.