Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows SDK is not properly added to the library path #15037

Closed
princessakokosowa opened this issue Mar 21, 2023 · 5 comments
Closed

Windows SDK is not properly added to the library path #15037

princessakokosowa opened this issue Mar 21, 2023 · 5 comments
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@princessakokosowa
Copy link

princessakokosowa commented Mar 21, 2023

Zig Version

0.11.0-dev.2196+bc0f24691

Steps to Reproduce and Observed Behavior

I have been using Zig as a build system for my C code, here goes my build.zig file.

const std = @import("std");

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

    const exe = b.addExecutable(.{
        .name     = "programme",
        .target   = target,
        .optimize = optimize,
    });
    exe.install();
    exe.linkLibC();

    switch (exe.target.getOsTag()) {
        .windows => {
            exe.linkSystemLibraryName("d3d12");
            exe.linkSystemLibraryName("dxgi");
            exe.linkSystemLibraryName("dxguid");
         // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         // This line causes the problem.
        },
        else => unreachable,
    }

    exe.addIncludePath("src");
    exe.addCSourceFiles(&.{
        "src/main.c",
    }, &.{
        // Warnings and errors.
        "-Wall",
        "-Werror",
        "-Wfatal-errors",
        "-Wmissing-field-initializers",
        "-Wno-comment",
        "-Wno-extern-c-compat",
        "-Wno-sequence-point",
        "-Wno-unknown-pragmas",
        "-Wstrict-prototypes",
        "-Wwrite-strings",

        // Code-relared things.
        "-fno-sanitize=undefined",
        "-fpack-struct=8",
        // "-fstack-protector-strong",
        "-fvisibility=hidden",
        
        // Misc.
        "-g",
        "-pedantic",
        "-std=c17",
    });

    const run_cmd = exe.run();
    run_cmd.step.dependOn(b.getInstallStep());

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

I get this error when compiling.

LLD Link... error(link): DLL import library for -ldxguid not found
error: DllImportLibraryNotFound
error: programme...
error: The following command exited with error code 1:
<path_redacted>\zig.exe build-exe -ld3d12 -ldxgi -ldxguid -cflags -Wall -Werror -Wfatal-errors -Wmissing-field-initializers -Wno-comment -Wno-extern-c-compat -Wno-sequence-point -Wno-unknown-pragmas -Wstrict-prototypes -Wwrite-strings -fno-sanitize=undefined -fpack-struct=8 -fvisibility=hidden -g -pedantic -std=c17 -- <path_redacted>\src\main.c -lc --cache-dir <path_redacted>\zig-cache --global-cache-dir <path_redacted>\zig --name programme -I <path_redacted>\src --enable-cache 
error: the following build command failed with exit code 1:
<path_redacted>\zig-cache\o\5591aa3bd80d82155b32aee6a37e7031\build.exe <path_redacted>\zig.exe <path_redacted> <path_redacted>\zig-cache C:\Users\pukk\AppData\Local\zig

This static library can be linked against the program if the path to the Windows SDK is explicitly provided to the compiler.

fn concat(a: []const u8, b: []const u8, allocator: std.mem.Allocator) ![]u8 {
    const result = try allocator.alloc(u8, a.len + b.len);

    std.mem.copy(u8, result, a);
    std.mem.copy(u8, result[a.len..], b);

    return result;
}

fn ascending(context: std.mem.Allocator, a: []const u8, b: []const u8) bool {
    _ = context;

    return std.mem.eql(u8, a, b);
}

fn findWindowsKitsAndAddLibraryPathToExe(b: *std.build.Builder, exe: *std.Build.CompileStep) !void {
    const windows_kits_path = "C:\\Program Files (x86)\\Windows Kits\\10\\Lib";
    const libs_subpath      = "\\um\\x64";

    var windows_kits_dir = try std.fs.openIterableDirAbsolute(windows_kits_path, .{
        .access_sub_paths = true,
    });

    var dirs = std.ArrayList([]const u8).init(b.allocator);
    defer dirs.deinit();

    var it = windows_kits_dir.iterate();
    while (try it.next()) |dir| {
        if (dir.kind != .Directory) continue;

        try dirs.append(b.dupe(dir.name));
    }

    if (dirs.getLastOrNull() == null) return error.NoVersionAvailable;
    std.sort.sort([]const u8, dirs.items, b.allocator, ascending);

    const version = dirs.getLast();
    const version_subpath = try concat("\\", version, b.allocator);
    defer b.allocator.free(version_subpath);

    const windows_kits_version_path = try concat(windows_kits_path,version_subpath, b.allocator);
    defer b.allocator.free(windows_kits_version_path);

    const windows_kits_version_libs_path = try concat(windows_kits_version_path, libs_subpath, b.allocator);
    defer b.allocator.free(windows_kits_version_libs_path);

    exe.addLibraryPath(windows_kits_version_libs_path);
}

// ...

    switch (exe.target.getOsTag()) {
        .windows => {
            try findWindowsKitsAndAddLibraryPathToExe(b, exe);

            exe.linkSystemLibraryName("d3d12");
            exe.linkSystemLibraryName("dxgi");
            exe.linkSystemLibraryName("dxguid");
        },
        else => unreachable,
    }

// ...

Of course, for demonstration purposes, this piece of code could be limited to hardcoding the full path to my Windows SDK, but I decided to write a slightly more interesting way of doing this and this should work on your PCs.

Here goes main.c file.

#ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN

#define NOMINMAX
#include <Windows.h>

#define COBJMACROS

#pragma warning(push)
#pragma warning(disable:4115)

#include "d3d12.h"
#include "d3d12sdklayers.h"
#include "dxgi1_6.h"

#pragma warning(pop)

typedef enum Flag {
    FLAG_ENABLE_DEBUG_LAYER        = 1 << 0,
    FLAG_ENABLE_SHADER_DEBUGGING   = 1 << 1,
    FLAG_ENABLE_STABLE_POWER_STATE = 1 << 2,
} Flag;

typedef unsigned long long Flags;

#define TRUE  1
#define FALSE 0

int main(void) {
    Flags flags = FLAG_ENABLE_DEBUG_LAYER | FLAG_ENABLE_SHADER_DEBUGGING | FLAG_ENABLE_STABLE_POWER_STATE;

    // Testing...
    {
        _Bool       succeeded                        = TRUE;
        _Bool const should_enable_debug_layer        = (_Bool)((flags & FLAG_ENABLE_DEBUG_LAYER       ) != 0);
        // _Bool const should_enable_shader_debugging   = (_Bool)((flags & FLAG_ENABLE_SHADER_DEBUGGING  ) != 0);
        // _Bool const should_enable_stable_power_state = (_Bool)((flags & FLAG_ENABLE_STABLE_POWER_STATE) != 0);

        ID3D12Debug1* debug_controller = NULL;

        if (should_enable_debug_layer == TRUE) {
            succeeded = SUCCEEDED(D3D12GetDebugInterface(&IID_ID3D12Debug1, (void**)&debug_controller));
            if (succeeded == TRUE) {
                ID3D12Debug1_EnableDebugLayer(debug_controller);
                // ID3D12Debug1_SetEnableSynchronizedCommandQueueValidation(debug_controller, TRUE);
                // ID3D12Debug1_Release(debug_controller);
            }
        }
    }

    return 0;
}

Expected Behavior

I suppose that this thing should be already handled by the compiler itself (or so it seems from browsing https://github.com/ziglang/zig/blob/master/src/windows_sdk.cpp file) or... maybe I am missing something?

@princessakokosowa princessakokosowa added the bug Observed behavior contradicts documented or intended behavior label Mar 21, 2023
@michal-z
Copy link
Contributor

michal-z commented Mar 21, 2023

By default Zig uses gnu ABI on Windows. Have you tried using msvc ABI?

zig build -Dtarget=x86_64-windows-msvc

It should then correctly find Windows SDK installed on your system.

@princessakokosowa
Copy link
Author

Thanks @michal-z! It's true that I haven't tried using msvc ABI, but to be fair, I kind of don't intend to use it. clang offers a couple of compiler extensions that I reallly like and thus, I'll stick to that. Also, it'd make my C code a mess if I tried to differentiate between compiler versions (#ifdefs etc.).

If Zig not adding Windows SDK when using gnu ABI is a defined and expected behaviour, then this issue is, sadly, not an issue.

@michal-z
Copy link
Contributor

When using gnu ABI Windows SDK is provided by Zig distribution (mingw64). It works fine but there are some missing pieces.

Also, note that clang compiler is always used (even if you use msvc ABI).

@michal-z
Copy link
Contributor

Your program should actually work fine..

@mlarouche
Copy link
Sponsor Contributor

I still have the issue even with using msvc ABI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

3 participants