Having some trouble linking pre-built c++ libs on windows msvc platform

this is the build.zig

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

pub fn build(b: *std.Build) !void {
    _ = b.allocator;
    const target = b.standardTargetOptions(.{});

    const optimize = b.standardOptimizeOption(.{});

    var exe = if (builtin.os.tag == .windows) b.addExecutable(.{
        .name = "zig-axmol-test1",
        .root_source_file = b.path("src/win_main.zig"),
        .target = target,
        .optimize = optimize,
    }) else {
        std.log.err("Only support windows for now.\n", .{});
        return;
    };
    const axmol_libs_path = b.path("axmol_libs");
    exe.addLibraryPath(axmol_libs_path);

    exe.linkLibC();
    // exe.linkLibCpp(); //don't need when the target is msvc

    var axmol_libs_files = (try axmol_libs_path.getPath3(b, &exe.step).openDir("", .{ .iterate = true })).iterate();
    while (try axmol_libs_files.next()) |entry| {
        const LIB_SUFFIX = ".lib";
        if (!std.mem.endsWith(u8, entry.name, LIB_SUFFIX)) {
            continue;
        }
        exe.linkSystemLibrary(entry.name[0..(entry.name.len - LIB_SUFFIX.len)]);
    }
    exe.linkSystemLibrary("Winmm");
    exe.linkSystemLibrary("user32");
    exe.linkSystemLibrary("advapi32");
    exe.linkSystemLibrary("ws2_32");
    exe.linkSystemLibrary("uuid");

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);

    run_cmd.step.dependOn(b.getInstallStep());

    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

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

inside axmol_libs some pre-compiled c++ libraries(.lib) are placed, those were compiled uinsg typical windows MSVC visual studio project.

so after running normal zig build I get:

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

tried to run zig build -Dtarget=x86_64-windows-msvc
returns the following logs:

error: sub-compilation of libcxxabi failed
    :1:1: note: argument unused during compilation: '-nostdinc++'
    :1:1: note: argument unused during compilation: '-nostdinc++'
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:78:8: note: use of undeclared identifier '__libcpp_refstring'
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:10: note: in file included from Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:
#include "include/refstring.h" // from libc++
         ^
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:89:8: note: use of undeclared identifier '__libcpp_refstring'
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:10: note: in file included from Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:
#include "include/refstring.h" // from libc++
         ^
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:89:53: note: unknown type name '__libcpp_refstring'
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:10: note: in file included from Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:
#include "include/refstring.h" // from libc++
         ^
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:94:8: note: unknown type name '__libcpp_refstring'
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:10: note: in file included from Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:
#include "include/refstring.h" // from libc++
         ^
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:94:28: note: use of undeclared identifier '__libcpp_refstring'
    Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:10: note: in file included from Z:\Home\.zig\lib\libcxxabi\src/stdlib_stdexcept.cpp:15:
#include "include/refstring.h" // from libc++
<redacted>

running zig version: 0.14.0-dev.622+a84951465

just want some trouble shooting suggestions, what should I try at this point kind of lost.

update:
so when specifying the target to be x86_64-windows-msvc (eg.zig build -Dtarget=x86_64-windows-msvc) you don’t need to call exe.linkLibCpp();, probably because zig tries to link it’s own version of libc++? but now an new issue is the linker can’t seem to find standard function

lld-link: undefined symbol: __declspec(dllimport) strtoul
lld-link: undefined symbol: __declspec(dllimport) ungetc
error: lld-link: undefined symbol: __declspec(dllimport) fopen_s

anything what i am dealing with? feels like my original msvc compiled libs are wrongly compiled?

You might need to specifically link against oldnames when targeting MSVC:

    exe.linkSystemLibrary("oldnames");

actually that wasn’t required i needed to link bunch of these libs:

    exe.linkSystemLibrary("c");
    exe.linkSystemLibrary("msvcrtd");
    exe.linkSystemLibrary("Winmm");
    exe.linkSystemLibrary("Version");
    exe.linkSystemLibrary("kernel32");
    exe.linkSystemLibrary("user32");
    exe.linkSystemLibrary("gdi32");
    exe.linkSystemLibrary("winspool");
    exe.linkSystemLibrary("shell32");
    exe.linkSystemLibrary("ole32");
    exe.linkSystemLibrary("oleaut32");
    exe.linkSystemLibrary("uuid");
    exe.linkSystemLibrary("comdlg32");
    exe.linkSystemLibrary("advapi32");

but now the issue is i get duplicate symbol errors, eg:

error: lld-link: duplicate symbol: wcscmp
    note: defined at minkernel\crts\ucrt\src\appcrt\string\wcscmp.cpp:30
    note:            libucrtd.lib(wcscmp.obj)
    note: defined at ucrtbased.dll
error: lld-link: duplicate symbol: wcscpy_s
    note: defined at minkernel\crts\ucrt\src\appcrt\string\wcscpy_s.cpp:16
    note:            libucrtd.lib(wcscpy_s.obj)
    note: defined at ucrtbased.dll
error: lld-link: duplicate symbol: wcslen
    note: defined at minkernel\crts\ucrt\src\appcrt\string\strnlen.cpp:219
    note:            libucrtd.lib(strnlen.obj)
    note: defined at ucrtbased.dll

after running the build with --verbose-link flag, i get the following lld-link command:

lld-link -ERRORLIMIT:0 -NOLOGO -DEBUG 
-PDB:<redacted>\zig-axmol-test1.pdb 
-PDBALTPATH:zig-axmol-test1.pdb 
-STACK:16777216 -BASE:4194304 -MACHINE:X64 
-OUT:<redacted>\zig-axmol-test1.exe 
-IMPLIB:<redacted>\zig-axmol-test1.lib 
<redacted-verbose-lib-paths>
-SUBSYSTEM:console,6.0 libcmtd.lib libvcruntimed.lib libucrtd.lib
legacy_stdio_definitions.lib kernel32.lib ntdll.lib
C:\Users\User\AppData\Local\zig\o\e0ead63b6dc858d4b4784734ac3d1e9d\compiler_rt.lib
C:\Users\User\AppData\Local\zig\o\0844874da679c426060ac11264d2012f\kernel32.lib
C:\Users\User\AppData\Local\zig\o\13814724a30913af15e0109688c049c4\ntdll.lib

so the culpirt is libucrtd.lib is there a way to tell zig not to try to link that? or wait may be i need to pass a lld-link flag instead

libucrtd.lib is universal C runtime debug library.
Try to remove this line:

i had to specify .linkage = .dynamic of step.Compile, not sure why this worked.

if anybody ever finds troubling linking with msvc pre-built libs this is the configuration that worked for me:

    const target = b.standardTargetOptions(.{});

    const optimize = b.standardOptimizeOption(.{});

    var exe = if (builtin.os.tag == .windows) b.addExecutable(.{
        .name = "zig-axmol-test1",
        .root_source_file = b.path("src/win_main.zig"),
        .target = target,
        .optimize = optimize,
        .win32_manifest = b.path("src/win_main.manifest"),
        .linkage = .dynamic,
        .link_libc = true,
    }) else {
        std.log.err("Only support windows for now.\n", .{});
        return;
    };

    exe.linkSystemLibrary("Winmm");
    exe.linkSystemLibrary("Version");
    exe.linkSystemLibrary("kernel32");
    exe.linkSystemLibrary("user32");
    exe.linkSystemLibrary("gdi32");
    exe.linkSystemLibrary("winspool");
    exe.linkSystemLibrary("shell32");
    exe.linkSystemLibrary("ole32");
    exe.linkSystemLibrary("oleaut32");
    exe.linkSystemLibrary("uuid");
    exe.linkSystemLibrary("comdlg32");
    exe.linkSystemLibrary("advapi32");
3 Likes