Linking in _mm_setzero_si128 when building with MSVC abi

Hi,

We are trying to build The-Forge, a graphics/rendering library, using Zig instead of via invoking cl.exe. We are targeting the MSVC ABI and am reaching the final linking issues (I hope!).

The problem I have now is that it’s not finding some sse intrinsics:

error: lld-link: undefined symbol: _mm_setzero_si128
    note: referenced by C:\Projects\elvengroin-legacy\external\ze-forge\external\The-Forge\Common_3\Graphics\ThirdParty\OpenSource\winpixeventruntime\Include\WinPixEventRuntime\PIXEventsCommon.h:357
    note:               ze_forge_c_cpp.lib(Direct3D12_cxx.obj):(void __cdecl PIXCopyEventArgument<char const *>(unsigned __int64 *&, unsigned __int64 const *, char const *))

I’ve tried adding #include <emmintrin.h> to no avail. I added “-msse2” to my cflags like so:


    const cflags = &.{
        "-DTIDES",
        "-DD3D12_AGILITY_SDK=1",
        "-DD3D12_AGILITY_SDK_VERSION=715",
        "-msse2",
    };

    ze_forge_c_cpp.addIncludePath(b.path("../../tools/external/msvc/Windows Kits/10/Include/10.0.22621.0/shared"));
    ze_forge_c_cpp.addIncludePath(b.path("../../tools/external/msvc/Windows Kits/10/Include/10.0.22621.0/ucrt"));
    ze_forge_c_cpp.addIncludePath(b.path("../../tools/external/msvc/Windows Kits/10/Include/10.0.22621.0/um"));
    ze_forge_c_cpp.addIncludePath(b.path("../../tools/external/msvc_BuildTools/VC/Tools/MSVC/14.39.33519/include"));

    ze_forge_c_cpp.addCSourceFiles(.{
        .files = &.{
            // Single header libraries
            "src/single_header_wrapper.cpp",

            // The-forge graphics
            "external/The-Forge/Common_3/Graphics/GraphicsConfig.cpp",
            "external/The-Forge/Common_3/Graphics/Direct3D12/Direct3D12_cxx.cpp",
            "external/The-Forge/Common_3/Graphics/Direct3D12/Direct3D12.c",
            "external/The-Forge/Common_3/Graphics/Direct3D12/Direct3D12Hooks.c",
            "external/The-Forge/Common_3/Graphics/Direct3D12/Direct3D12Raytracing.c",
            "external/The-Forge/Common_3/Utilities/ThirdParty/OpenSource/bstrlib/bstrlib.c",
            // Glue
            "external/The-Forge/Common_3/Graphics/Interfaces/IGraphics_glue.cpp",
            "external/The-Forge/Common_3/Graphics/Interfaces/IRay_glue.cpp",

            // TIDES Graphics
            "external/The-Forge/Common_3/Graphics/GraphicsTides.c",
            "external/The-Forge/Common_3/Graphics/Interfaces/IGraphicsTides_glue.cpp",

            // TIDES
            "external/The-Forge/Common_3/Tides/WindowsFileSystem.c",
            "external/The-Forge/Common_3/Tides/WindowsLog.c",
            "external/The-Forge/Common_3/Tides/WindowsMemory.c",
            "external/The-Forge/Common_3/Tides/WindowsThread.c",
        },
        .flags = cflags,
    });

Building with this command line:

        "command": "zig build -Dtarget=native-native-msvc --verbose",

Would appreciate any help! :slight_smile:

Virtually every x86_64 CPU ever made supports SSE2, so I don’t think the -msse2 flag is needed. (Besides, the “Zig” way to enable or disable CPU features would be by using -Dcpu= when invoking zig build.)

I took a look at your repo and my working theory that the problem is that MSVC/14.39.33519/include/emmintrin.h is taking priority over Zig’s zig/lib/include/emmintrin.h. The MSVC one defines the intrinsics as a bunch of extern functions (that your project is unable to find at link time), while the Zig one defines them as inline functions. You almost definitely want the Zig ones.

When you build for MSVC, Zig normally detects and adds all the necessary system header include paths using -isystem, first zig/lib/include and then the MSVC header directories. Your b.addIncludePath() lines in your build script then adds those same paths as regular include paths using -I. -I paths are searched before -isystem paths, so the MSVC emmintrin.h is found first.

I believe you will be able to fix the problem simply by removing these lines:

If that doesn’t work, you could try changing them to b.addSystemIncludePath().

2 Likes

Why do you need to include the SDK and MSVC paths?
Do you also add as a link path "../../tools/external/msvc_BuildTools/VC/Tools/MSVC/14.39.33519/lib/x64"
What is you zig libc output?

1 Like

Thank you, addSystemIncludePath made it work! (this was a reply to castholm)

Now it compiles and links, hopefully it links too :crossed_fingers:

Just removing the addIncludePaths didn’t work as then it would not find for example new.h. I’m not sure if this is a bug in Zig’s MSVC setup or not.

To get further in compilation :sweat_smile:

I got it to work, see my reply to @castholm’s post.

But to answer your question:

C:\Projects\elvengroin-legacy\external\ze-forge\test>zig libc
# The directory that contains `stdlib.h`.
# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`
include_dir=C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt

# The system-specific include directory. May be the same as `include_dir`.
# On Windows it's the directory that includes `vcruntime.h`.
# On POSIX it's the directory that includes `sys/errno.h`.
sys_include_dir=C:\Projects\elvengroin-legacy\tools\external\msvc_BuildTools\VC\Tools\MSVC\14.39.33519\include

# The directory that contains `crt1.o` or `crt2.o`.
# On POSIX, can be found with `cc -print-file-name=crt1.o`.
# Not needed when targeting MacOS.
crt_dir=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\ucrt\x64

# The directory that contains `vcruntime.lib`.
# Only needed when targeting MSVC on Windows.
msvc_lib_dir=C:\Projects\elvengroin-legacy\tools\external\msvc_BuildTools\VC\Tools\MSVC\14.39.33519\Lib\x64

# The directory that contains `kernel32.lib`.
# Only needed when targeting MSVC on Windows.
kernel32_lib_dir=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\um\x64

# The directory that contains `crtbeginS.o` and `crtendS.o`
# Only needed when targeting Haiku.
gcc_dir=