Skip to content

What if Conan could provide Zig with library information - #20225

Open
AbrilRBS wants to merge 1 commit into
develop2from
ar/zigdeps-2
Open

What if Conan could provide Zig with library information#20225
AbrilRBS wants to merge 1 commit into
develop2from
ar/zigdeps-2

Conversation

@AbrilRBS

@AbrilRBS AbrilRBS commented Jul 28, 2026

Copy link
Copy Markdown
Member

Changelog: Feature: Add experiemntal ZigDeps support to allow zig code to compile using C/C++ libraries
Docs: TODO

Superset of #19626, using it as a base and Calude as insight for of Zig expertise

$runslowtests

Comment thread test/conftest.py
@AbrilRBS
AbrilRBS marked this pull request as ready for review July 29, 2026 14:41
New generator to consume Conan C/C++ dependencies from a Zig `build.zig`.

Zig's build system has no format for describing a prebuilt C/C++ library, and
does not propagate include or library paths to consumers through
linkLibrary(), so there is nothing to emit into. The generator emits Zig
source instead: `conan_deps.zig`, a comptime map of every dependency, and
`conan_setup.zig`, helpers that a `build.zig` calls.

Modelled on CMakeConfigDeps: one target per component keyed "pkg::component",
each carrying only its own unmerged information, with explicit `requires`
edges that the generated code walks - doing by hand what CMake's target system
does natively. Requirement resolution reuses get_transitive_requires(), so
requirement traits are honoured from the consumer's perspective rather than
read off the dependency.

The public API takes a *std.Build.Module rather than a *Step.Compile: in Zig
0.16 every call it makes exists only on Module, and a module is not
necessarily an artifact's root, so the same call works for a test module.

The C++ runtime is requested for any dependency not declaring `languages = "C"`,
since assuming C++ for a C package costs nothing measurable while the reverse
fails the link with undefined std:: symbols. It is skipped on the MSVC ABI,
where the runtime comes from MSVC itself, and both `link_libc` and
`link_libcpp` are only set when the consumer has not decided, so they can be
overridden either side of the call.

Covers build time only: making shared dependencies loadable at run time is
left to Conan's `conanrun` environment or a deployer.

Marked experimental - the generated Zig API is expected to change.

Tests: 30 integration tests asserting on generated content with no Zig
required, and 10 functional tests running a real `zig build` against
ConanCenter packages, including variants where the dependencies are built by
CMake rather than by `zig cc`. Zig 0.16.0 is registered in test/conftest.py
and installed on Linux, macOS and Windows CI.
@AbrilRBS

AbrilRBS commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

ZigDeps by example

Written with the help of an LLM for wording

Four worked examples of a Zig project consuming Conan packages, using the experimental
ZigDeps generator. In each one the application is written in Zig; the C and C++ libraries
come from ConanCenter. Every example here was built and run end to end — see Verification.

ZigDeps is experimental. The shape of the generated Zig API is expected to change.

Contents

  1. Zig using a C library — OpenSSL — components, transitive dependencies, static and shared
  2. Zig using a C++ library — snappy — the C++ runtime, via a library's own C API
  3. Zig using a build tool — flextool_requires, generated code
  4. Testing a C library from Zig — zlib + cmockatest_requires

How it works

conan install . -g ZigDeps writes two files into a conan_zig_deps/ folder:

File What it is
conan_deps.zig Data. A comptime map of every dependency: include dirs, library paths, defines, system libs, frameworks, and each target's own requires list.
conan_setup.zig Behaviour. Helpers your build.zig calls to push that data into a module.

Zig has no native format for describing a prebuilt C library, and does not propagate include
or library paths through linkLibrary(), so there is nothing to emit into — the generator
emits Zig source that your build imports instead.

Everything is keyed "package::target", the same vocabulary CMake users know:
openssl::ssl is a component, openssl::openssl is the package root.

const conan = @import("conan_zig_deps/conan_setup.zig");

conan.linkDependencies(mod);                  // every direct dependency
conan.linkDependency(mod, "openssl::crypto"); // …or one specific target
conan.toolPath(b, "flex", "flex");            // a tool_requires executable

The helpers take a *std.Build.Module, not a *std.Build.Step.Compile. In Zig 0.16 every
call they make exists only on Module, and a module is not necessarily an artifact's root —
so the same call works for a test module.

Once a module has been set up this way, @cImport resolves the dependency's headers with no
paths written by hand.


1. Zig using a C library — OpenSSL

A Zig program that hashes a string with OpenSSL. No C sources of our own.

Shows component-level linking and transitive resolution: OpenSSL's crypto
component depends on zlib, and ssl depends on crypto, so naming one target pulls the
rest in automatically.

conanfile.txt

[requires]
openssl/3.5.4

[generators]
ZigDeps

main.zig

const std = @import("std");

// Zig imports the C headers directly. ZigDeps put OpenSSL's include directories on this
// module, so @cInclude resolves without any path being written here.
const ssl = @cImport({
    @cInclude("openssl/evp.h");
    @cInclude("openssl/crypto.h");
});

pub fn main() !void {
    const msg = "conan + zig";

    var digest: [ssl.EVP_MAX_MD_SIZE]u8 = undefined;
    var len: c_uint = 0;

    const ctx = ssl.EVP_MD_CTX_new() orelse return error.OpenSslFailed;
    defer ssl.EVP_MD_CTX_free(ctx);

    if (ssl.EVP_DigestInit_ex(ctx, ssl.EVP_sha256(), null) != 1) return error.OpenSslFailed;
    if (ssl.EVP_DigestUpdate(ctx, msg, msg.len) != 1) return error.OpenSslFailed;
    if (ssl.EVP_DigestFinal_ex(ctx, &digest, &len) != 1) return error.OpenSslFailed;

    std.debug.print("{s}\n", .{std.mem.span(ssl.OpenSSL_version(ssl.OPENSSL_VERSION))});
    std.debug.print("sha256(\"{s}\") = ", .{msg});
    for (digest[0..len]) |b| std.debug.print("{x:0>2}", .{b});
    std.debug.print("\n", .{});
}

build.zig

const std = @import("std");
const conan = @import("conan_zig_deps/conan_setup.zig");

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

    // A plain Zig module - no C or C++ sources of our own.
    const mod = b.createModule(.{
        .root_source_file = b.path("main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Only the "crypto" component is needed. Its own requires - openssl::crypto ->
    // zlib::zlib - are followed automatically, so zlib is linked without naming it.
    conan.linkDependency(mod, "openssl::crypto");

    const exe = b.addExecutable(.{ .name = "digest", .root_module = mod });
    b.installArtifact(exe);

    const run = b.addRunArtifact(exe);
    b.step("run", "Run the Zig program").dependOn(&run.step);
}
conan install . -of . --build=missing
zig build run
OpenSSL 3.5.4 30 Sep 2025
sha256("conan + zig") = c69d96afb1f7a8ea85d27a29245f1a31bb3e0026de72f0e4f762ad93fac142e6

The graph that gets walked, with nothing in build.zig describing it:

openssl::ssl ──> openssl::crypto ──> zlib::zlib

The same thing, shared

conan install . -of . -o "openssl/*:shared=True" -o "zlib/*:shared=True" --build=missing
source ./conanrun.sh          # <- required
zig build run

ZigDeps covers build time only. It deliberately emits no rpaths and copies no
libraries, because Conan already solves runtime discovery with conanrun (which sets PATH
on Windows and (DY)LD_LIBRARY_PATH elsewhere). Skipping the activation gives:

dyld[49473]: Library not loaded: @rpath/libcrypto.3.dylib

which is the expected, documented behaviour — not a bug. From a recipe, the equivalent is
self.run("zig build run", env="conanrun").

Watch out: VirtualRunEnv decides whether to export the library-path variables at all
by looking at settings.os. A consumer recipe that declares no settings gets a silently
empty conanrun environment, and shared dependencies stay unfindable with no warning.

Letting Zig compile your own C sources

Zig ships a C compiler, so a project that still has C of its own needs no separate toolchain
— and ZigDeps is used identically either way. Alongside main.zig, this example carries
digest.c (the same hashing logic written in C) and builds it as a second target from the
same build.zig:

// --- The same thing in C, compiled by Zig itself ---------------------------------
// Zig ships a C compiler, so a project with its own C sources needs no separate
// toolchain. ZigDeps is used identically either way.
const c_mod = b.createModule(.{ .target = target, .optimize = optimize });
c_mod.addCSourceFile(.{ .file = b.path("digest.c"), .flags = &.{"-std=c11"} });
conan.linkDependency(c_mod, "openssl::crypto");

const c_exe = b.addExecutable(.{ .name = "digest-c", .root_module = c_mod });
b.installArtifact(c_exe);

const run_c = b.addRunArtifact(c_exe);
b.step("run-c", "Build the C version with Zig and run it").dependOn(&run_c.step);
zig build run-c
OpenSSL 3.5.4 30 Sep 2025 (from C)
sha256("conan + zig") = c69d96afb1f7a8ea85d27a29245f1a31bb3e0026de72f0e4f762ad93fac142e6

Note the difference from the Zig module: a C module needs no @cImport, since digest.c
includes the OpenSSL headers itself — ZigDeps supplies the include paths to both.


2. Zig using a C++ library — snappy

Zig can only @cImport C, never C++. The clean case is a C++ library that ships a C API
of its own: snappy is written in C++ but maintains snappy-c.h alongside it, so it is
usable from Zig directly, with no shim and no C++ in the project at all.

This is also the sharpest demonstration of what ZigDeps contributes. Nothing on the Zig
side looks like C++ — a C header, a C API — yet the implementation behind that API is C++,
so the C++ standard library is still required at link time. A Zig binary does not link it by
default. Building without it fails with 9 undefined std:: symbols:

error: undefined symbol: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5eraseEmm

ZigDeps detects that snappy is a C++ package and asks for the runtime, so this never
surfaces.

Note also the two targets snappy produces: snappy::snappy is an .interface target — a
package root with nothing to link — which requires snappy::snappylib, the .static (or
.shared) library that carries the actual archive.

conanfile.txt

[requires]
snappy/1.1.10

[generators]
ZigDeps

main.zig

const std = @import("std");

// snappy is written in C++, but ships snappy-c.h - a real C API maintained by the project
// itself. That is what makes it usable from Zig directly: Zig can @cImport C headers, but
// never C++ ones, so a C++ library is only reachable when it exposes a C surface like this.
//
// Nothing below is C++, yet the C++ standard library is still required at link time,
// because the *implementation* behind this C API is C++. ZigDeps detects that and asks for
// the runtime; without it the link fails with undefined std:: symbols.
const snappy = @cImport({
    @cInclude("snappy-c.h");
});

pub fn main() !void {
    const input = "conan conan conan zig zig zig zig";

    var compressed: [256]u8 = undefined;
    var compressed_len: usize = compressed.len;
    if (snappy.snappy_compress(input, input.len, &compressed, &compressed_len) != snappy.SNAPPY_OK)
        return error.CompressFailed;

    var restored: [256]u8 = undefined;
    var restored_len: usize = restored.len;
    if (snappy.snappy_uncompress(&compressed, compressed_len, &restored, &restored_len) != snappy.SNAPPY_OK)
        return error.UncompressFailed;

    std.debug.print("compressed {d} -> {d} bytes\n", .{ input.len, compressed_len });
    std.debug.print("round trip ok: {}\n", .{std.mem.eql(u8, input, restored[0..restored_len])});
}

build.zig

const std = @import("std");
const conan = @import("conan_zig_deps/conan_setup.zig");

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

    // A plain Zig module. No C++ sources, and no shim: snappy provides the C API itself.
    const mod = b.createModule(.{
        .root_source_file = b.path("main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // link_libcpp is never set here. ZigDeps knows snappy is a C++ package and asks for the
    // C++ runtime itself - a Zig binary would otherwise not link it at all.
    conan.linkDependencies(mod);

    const exe = b.addExecutable(.{ .name = "roundtrip", .root_module = mod });
    b.installArtifact(exe);

    const run = b.addRunArtifact(exe);
    b.step("run", "Run the example").dependOn(&run.step);
}
conan install . -of . --build=missing
zig build run
compressed 33 -> 27 bytes
round trip ok: true

Add -o "snappy/*:shared=True" for the shared build, and source ./conanrun.sh to run it.

When the library has no C API

Most C++ libraries do not ship one. pugixml and nlohmann_json, for example, are
C++-only, so a Zig consumer has to add a small extern "C" shim — one .cpp file exposing
the operations it needs — and @cImport that shim's header instead. The build.zig is
otherwise unchanged: linkDependencies() still supplies the include paths and the C++
runtime for the shim to compile and link against.

Prefer a library with an official C API where one exists; a hand-written shim is code you
then own and have to keep in step with the library.

How C++ is detected

A dependency's languages attribute is authoritative when the recipe sets it — a package
declaring languages = "C" never gets the C++ runtime. Most recipes still leave it unset
(it is declared by well under a tenth of ConanCenter), and those are assumed to be C++.

That default is deliberate, because the two mistakes are not equally bad. Assuming C++ for a
package that turns out to be C costs nothing measurable: the linker drops the unused runtime,
so the binary is byte-identical, and Zig builds its libc++ once per machine. Assuming C for a
package that turns out to be C++ fails the link with undefined std:: symbols — and Zig's
C-only interop actively hides which case you are in, since a C++ library behind a C API (like
snappy above) looks exactly like a C one from the Zig side.

On the MSVC ABI the runtime is never requested: there it comes from MSVC itself, pulled in by
the /DEFAULTLIB directives in its own objects.

Overriding the runtime linkage

link_libc and link_libcpp are ?bool in Zig, where null means "not decided". ZigDeps
only fills them in when you have not, so either of these wins — the order relative to
linkDependencies() does not matter:

mod.link_libcpp = false;   // never link the C++ runtime for this module
mod.link_libcpp = true;    // always link it, e.g. for a header-only C++ package
conan.linkDependencies(mod);

This is an escape hatch rather than something you normally need. A package whose languages
is unset is assumed to be C++, so header-only C++ libraries and C++ implementations behind a
C API are both already covered with no opt-in. Assuming C++ costs nothing measurable — the
linker drops an unused libc++, so the binary comes out byte-identical — but the override is
there if you would rather it were not linked at all.

Troubleshooting: headers that rely on transitive includes

Zig bundles its own libc++, whose headers include slightly less than Apple's or GNU's. A
library that leans on an include it never asked for can therefore compile everywhere else
and fail here. This is a property of the library version, not of ZigDeps, and is usually
already fixed upstream — check for a newer version before working around it.

fmt is a worked example. In fmt/11.2.0, format.h calls malloc and free without
including <cstdlib>, so it fails under Zig with:

error: use of undeclared identifier 'malloc'

fmt added the include after that release (<cstdlib> in 12.0.0, <stdlib.h> on master),
so the fix is simply to move up — fmt/12.0.0 compiles and runs with Zig unchanged:

[requires]
fmt/12.0.0

If you are pinned to a version that still has the problem, force the include from the
consumer rather than patching the package:

mod.addCSourceFile(.{ .file = b.path("shim.cpp"),
                      .flags = &.{ "-std=c++17", "-include", "cstdlib" } });

3. Zig using a build tool — flex

Shows tool_requires: a dependency in the build context, where there is nothing to link
and the only thing you want is the path to a program. flex generates a C lexer during the
build; the Zig program drives it. The generated .c never exists in the repository.

conanfile.txt

[tool_requires]
flex/2.6.4

[generators]
ZigDeps

counter.l — note there is no main(); the lexer is a library Zig calls

%option noyywrap nounput noinput
%{
int words = 0, numbers = 0;
%}
%%
[0-9]+      { numbers++; }
[a-zA-Z]+   { words++; }
.|\n        { /* skip */ }
%%
int count_words(void)   { return words; }
int count_numbers(void) { return numbers; }

main.zig

const std = @import("std");

// The lexer C source does not exist in the repository: flex generates it during the build,
// and Zig compiles it into this binary. Only the hand-written header is imported.
const lexer = @cImport({
    @cInclude("lexer.h");
});

pub fn main() !void {
    _ = lexer.yylex(); // reads stdin
    std.debug.print("words={d} numbers={d}\n",
        .{ lexer.count_words(), lexer.count_numbers() });
}

build.zig

const std = @import("std");
const conan = @import("conan_zig_deps/conan_setup.zig");

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

    // flex comes from [tool_requires], so it lives in the *build* context: there is nothing
    // to link, only a program to run.
    const flex = b.addSystemCommand(&.{ conan.toolPath(b, "flex", "flex"), "-o" });
    const lexer_c = flex.addOutputFileArg("counter.c");
    flex.addFileArg(b.path("counter.l"));

    const mod = b.createModule(.{
        .root_source_file = b.path("main.zig"),
        .target = target,
        .optimize = optimize,
    });
    mod.addCSourceFile(.{ .file = lexer_c, .flags = &.{} });
    mod.addIncludePath(b.path("."));
    mod.link_libc = true;

    const exe = b.addExecutable(.{ .name = "counter", .root_module = mod });
    b.installArtifact(exe);

    const run = b.addRunArtifact(exe);
    run.setStdIn(.{ .bytes = "conan 2 zig 16 rules 42\n" });
    b.step("run", "Generate the lexer with flex, then build and run it").dependOn(&run.step);
}
conan install . -of . --build=missing
zig build run
words=3 numbers=3

toolPath() versus PATH

Conan's normal way of exposing a tool is the build environment: VirtualBuildEnv puts
every tool_requires bindir on PATH, so this also works —

source ./conanbuild.sh    # flex's bindir is now first on PATH
zig build run             # with b.addSystemCommand(&.{"flex", ...})

Both are valid. The difference is what happens when the environment is not active, which is
the common case when someone just runs zig build in a shell. On a machine with a system
flex — macOS ships /usr/bin/flex — a bare "flex" silently resolves to that one instead,
with no error and a near-identical version string.

toolPath() resolves inside the package's own bindir, so the build does not depend on
whether the environment happens to be active. Use "flex" plus conanbuild if you prefer
the environment-driven route; use toolPath() if you want the build to be self-contained.

Note that conan_tool_dirs includes the tool's own transitive tools, so this example also
exposes m4, which flex requires.


4. Testing a C library from Zig — zlib + cmocka

Zig's own test runner links a Conan dependency like any other module, so tests for a C
library can be written in Zig
. b.addTest takes a module, and linkDependencies() accepts
it directly.

A C test framework is shown second, for the case where the tests themselves are C. cmocka
is declared under [test_requires]: it becomes a real target in conan_deps.zig, but is
deliberately excluded from direct_targets, so linkDependencies() never drags a test
framework into the application. You name it explicitly, only in the test binary.

conanfile.txt

[requires]
zlib/1.3.1

[test_requires]
cmocka/1.1.7

[generators]
ZigDeps

test_zlib.zig — the primary suite

const std = @import("std");
const c = @cImport({
    @cInclude("zlib.h");
});

test "crc32 of a known string" {
    const data = "conan + zig";
    const crc = c.crc32(0, data.ptr, @intCast(data.len));
    try std.testing.expect(crc != 0);
    try std.testing.expectEqual(crc, c.crc32(0, data.ptr, @intCast(data.len)));
}

test "compressBound grows with input size" {
    try std.testing.expect(c.compressBound(1000) > c.compressBound(10));
}

test "zlib version is the one Conan resolved" {
    const v = std.mem.span(c.zlibVersion());
    try std.testing.expect(std.mem.startsWith(u8, v, "1.3"));
}

@cImport works because linkDependencies() puts zlib's include directories on the test
module before the import is translated.

test_zlib_cmocka.c — the secondary, C-based suite

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include <zlib.h>
#include <string.h>

static void test_crc32_is_stable(void **state) {
    (void)state;
    const char *msg = "conan + zig";
    uLong a = crc32(0L, (const Bytef *)msg, (uInt)strlen(msg));
    uLong b = crc32(0L, (const Bytef *)msg, (uInt)strlen(msg));
    assert_int_equal(a, b);
}

int main(void) {
    const struct CMUnitTest tests[] = { cmocka_unit_test(test_crc32_is_stable) };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

build.zig

const std = @import("std");
const conan = @import("conan_zig_deps/conan_setup.zig");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const test_step = b.step("test", "Run both test suites");

    // 1. Native Zig tests using the C dependency through @cImport.
    const zig_test_mod = b.createModule(.{
        .root_source_file = b.path("test_zlib.zig"),
        .target = target,
        .optimize = optimize,
    });
    conan.linkDependencies(zig_test_mod);
    const zig_tests = b.addTest(.{ .root_module = zig_test_mod });
    test_step.dependOn(&b.addRunArtifact(zig_tests).step);

    // 2. A C suite driven by cmocka, a [test_requires]: a real target, but not in
    //    direct_targets, so it never reaches the application. Name it explicitly.
    const c_test_mod = b.createModule(.{ .target = target, .optimize = optimize });
    c_test_mod.addCSourceFile(.{ .file = b.path("test_zlib_cmocka.c"), .flags = &.{} });
    conan.linkDependency(c_test_mod, "zlib::zlib");
    conan.linkDependency(c_test_mod, "cmocka::cmocka");
    const c_tests = b.addExecutable(.{ .name = "cmocka_tests", .root_module = c_test_mod });
    test_step.dependOn(&b.addRunArtifact(c_tests).step);
}
conan install . -of . --build=missing
zig build test --summary all
[==========] tests: Running 2 test(s).
[ RUN      ] test_crc32_is_stable
[       OK ] test_crc32_is_stable
[==========] tests: 2 test(s) run.
[  PASSED  ] 2 test(s).
Build Summary: 5/5 steps succeeded; 3/3 tests passed

Zig's own test runner prints nothing on success, which is why --summary all is used above
to show the 3 Zig tests alongside cmocka's output.


Windows: match the dependency's ABI

Conan's Windows binaries are normally built with MSVC, but Zig defaults to the MinGW
(gnu) ABI
on Windows — and only ships libc for that ABI. Linking an MSVC-produced object
in gnu mode fails on the /DEFAULTLIB: directives it carries, which lld then looks for under
MinGW names:

error: lld-link: could not open 'libMSVCRT.a': No such file or directory
error: lld-link: could not open 'libOLDNAMES.a': No such file or directory

That is an ABI mismatch, not a missing dependency. Ask for the ABI the packages were built
with:

const std = @import("std");
const builtin = @import("builtin");

pub fn build(b: *std.Build) void {
    // Match the ABI of the Conan binaries: MSVC on Windows, native elsewhere.
    var query: std.Target.Query = .{};
    if (builtin.os.tag == .windows) query.abi = .msvc;
    const target = b.standardTargetOptions(.{ .default_target = query });
    // …
}

Targeting the msvc ABI needs a real MSVC installation, since Zig does not bundle a libc for
it — zig cc -target x86_64-windows-msvc reports "unable to provide libc" without one.

The rule is simply that both sides must agree. If instead you build the dependencies
themselves with zig cc (a Conan profile using Zig as the compiler), they are gnu on both
sides and no override is needed.


Known limitations

Limitation Why
Zig cannot @cImport C++ headers A Zig-only property. C++ dependencies need a C surface: the library's own, or a shim — see example 2.
On Windows the consumer must target the msvc ABI Conan's Windows binaries are MSVC; Zig defaults to MinGW. See above.
A dependency's cflags / cxxflags / link flags are not applied Zig has no module-level flag injection — Module.addCSourceFile only applies flags to files added through it. They are emitted in conan_deps.zig and Conan warns when a dependency declares any, so pass them yourself.
No runtime discovery (no rpaths, no copied DLLs) Deliberate: conanrun and deployers already solve this. See example 1.
No set_property / target-name customisation Target names are fixed as pkg::component.
Paths are absolute Output is not relocatable after a deployer.
Header-only C++ packages that clear settings look like C Set link_libcpp yourself. See example 2.

Verification

Every example above was built and run before publishing. Nothing here is illustrative-only,
and the code shown is the code that was compiled.

Toolchain
Platform macOS 26, arm64 (Apple Silicon)
Zig 0.16.0
Packages openssl/3.5.4, zlib/1.3.1, snappy/1.1.10, flex/2.6.4 (+ m4/1.4.19), cmocka/1.1.7

Examples 1, 2 and 4 were each built and run in both static and shared configurations.
Example 3 has no link variant, being a build tool

if dep.package_type is not PackageType.APP]
direct_targets = [t for t in direct_targets if t in targets]

if flag_deps:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we warn when the profile uses compiler=gcc or libcxx!=libc++ and deps get built against libstdc++, but Zig links its own bundled libc++?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants