使用 CMake 和 MinGW 查找 DirectX12 库

Finding DirectX12 libraries with CMake and MinGW

我正在尝试使用 CMake 查找 DirectX 12 并 link 它针对可执行文件。到目前为止,我在用 MSVC 编译时有效,但在用 GCC 编译时失败了: Could NOT find D3D12 (missing: D3D12_LIBRARIES).

我使用的是 FindD3D12.cmake:

的稍作改动的版本
# Find the win10 SDK path.
if ("$ENV{WIN10_SDK_PATH}$ENV{WIN10_SDK_VERSION}" STREQUAL "" )
        get_filename_component(WIN10_SDK_PATH "[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0;InstallationFolder]" ABSOLUTE CACHE)
        get_filename_component(TEMP_WIN10_SDK_VERSION "[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0;ProductVersion]" ABSOLUTE CACHE)
        get_filename_component(WIN10_SDK_VERSION ${TEMP_WIN10_SDK_VERSION} NAME)
elseif(TRUE)
        set (WIN10_SDK_PATH $ENV{WIN10_SDK_PATH})
        set (WIN10_SDK_VERSION $ENV{WIN10_SDK_VERSION})
endif ("$ENV{WIN10_SDK_PATH}$ENV{WIN10_SDK_VERSION}" STREQUAL "" )

# WIN10_SDK_PATH will be something like C:\Program Files (x86)\Windows Kits
# WIN10_SDK_VERSION will be something like 10.0.14393 or 10.0.14393.0; we need the
# one that matches the directory name.

if (IS_DIRECTORY "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}.0")
        set(WIN10_SDK_VERSION "${WIN10_SDK_VERSION}.0")
endif (IS_DIRECTORY "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}.0")


# Find the d3d12 and dxgi include path, it will typically look something like this.
# C:\Program Files (x86)\Windows Kits\Include.0.10586.0\um\d3d12.h
# C:\Program Files (x86)\Windows Kits\Include.0.10586.0\shared\dxgi1_4.h
find_path(
        D3D12_INCLUDE_DIR    # Set variable D3D12_INCLUDE_DIR
        d3d12.h              # Find a path with d3d12.h
        HINTS "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}/um"
        DOC "path to WIN10 SDK header files"
        HINTS
)

find_path(
        DXGI_INCLUDE_DIR    # Set variable DXGI_INCLUDE_DIR
        dxgi1_4.h           # Find a path with dxgi1_4.h
        HINTS "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}/shared"
        DOC "path to WIN10 SDK header files"
        HINTS
)
set(D3D12_INCLUDE_DIRS ${D3D12_INCLUDE_DIR} ${DXGI_INCLUDE_DIR})

# Find D3D libraries
set(D3D12_LIB_NAMES d3d12.lib dxgi.lib d3dcompiler.lib dxguid.lib)

set(D3D12_LIBRARIES)
foreach (D3D12_LIB_NAME ${D3D12_LIB_NAMES})
        find_library(${D3D12_LIB_NAME}_LOC NAMES ${D3D12_LIB_NAME} HINTS ${D3D12_HINTS_PATH})
        set(D3D12_LIBRARIES ${D3D12_LIBRARIES} ${${D3D12_LIB_NAME}_LOC})
endforeach(D3D12_LIB_NAME)

include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set D3D12_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(
        D3D12  DEFAULT_MSG
        D3D12_INCLUDE_DIRS D3D12_LIBRARIES
)

mark_as_advanced(D3D12_INCLUDE_DIRS D3D12_LIBRARIES)

然后 link 使用:target_link_libraries(<name> ${D3D12_LIBRARIES}).

D3D12_INCLUDE_DIRS 变量设置为正确的值,问题仅出在库上。

DirectX 12 库是否与 GCC 不兼容并且 CMake 足够聪明来解决这个问题,还是我在尝试查找它们时做错了什么?

编辑:

如回答所述,不需要 FindD3D12.cmake 模块。在 Windows 上编译时,DirectX 库是系统库,因此 target_link_libraries(<name> PRIVATE d3d12.lib dxgi.lib d3dcompiler.lib dxguid.lib) 有效。

Are the DirectX 12 libraries not compatible with GCC

每个编译器都有自己的库格式,cl 使用 .lib 库,gcc 使用 .a.so 库。您不能只使用 cl 的库(存储在 Windows SDK 中的库)并将它们提供给 gcc。

============================================= =========

Windows:

DirectX 是 Windows SDK 的一部分。

如果您在 Windows 上进行编译,那么您不可能不使用 SDK 进行编译。因此不用担心处理包含目录和诸如此类的东西。

因此您可以将 Directx 库视为常规系统库,以下命令将起作用。这就是cmake的魔力。

所以你的大部分 cmake 并不是真正必要的。至少如果您使用 visual studio。 如果您不使用 visual studio,您可能需要编写一个工具链 (https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html?highlight=cmake_cxx_compiler_id#cmake-toolchains-7)

# DX12 libraries
target_link_libraries(foobar PRIVATE
    d3d12.lib
    dxgi.lib
    dxguid.lib
)

============================================= =========

Linux:

其次 DirectX12 将有 linux 支持: https://devblogs.microsoft.com/directx/directx-heart-linux/

但是我认为它不允许使用图形功能,只允许使用计算功能。但是不管假设微软没有让它变得非常痛苦,cmake 应该大致相似。

============================================= =========

最后,如果您想知道您正在构建的 SDK 版本,请查看 CMAKE_SYSTEM_VERSION

On windows 在第一个项目调用设置 SDK 版本之前设置此项。因为这就是 SDK 版本所代表的意义。 windows 个版本。

还要格外小心,在您的代码库中添加额外的 static_asserts 以确保您使用的是您希望包含的“Windows.h”版本的 SDK反正有。然后检查编译器定义,告诉您正在编译的 Windows OS 版本。

"当您使用 Windows SDK 时,您可以指定您的代码可以 运行 的 Windows 版本。预处理器宏 WINVER 和 _WIN32_WINNT 指定您的代码支持的最低操作系统版本。Visual Studio 和 Microsoft C++ 编译器支持目标 Windows 7 SP1 及更高版本。较旧的工具集包括对 Windows XP SP2、Windows Server 2003 的支持SP1、Vista 和 Windows Server 2008。不支持 Windows 95、Windows 98、Windows ME、Windows NT 和 Windows 2000 ” - Microsoft 文档 (https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-160)