使用CLion跑Direct3D 12——项目配置

2 篇文章 0 订阅

初入D3D12,一个好的教程就是红龙书(网站:https://www.d3dcoder.net,源码:https://github.com/d3dcoder/d3d12book)。按照书中所说,默认配置是VS2015。但是由于本人习惯使用PyCharm,更适应他们家的版面和配置方式,因此选择CLion。但是初入CLion,没有配置过一个成体系的C++项目的我也是一头雾水。好在这之前本人尝试过OpenGL项目的配置,因此迁移学习一下,把以前的经验用在现在。看到网上好像并没有相关的解说,将自己的经验分享到博客上,希望对大家有所帮助。

我将按照我的探索过程来讲解,一步步构建一个能使D3D运行的配置体系。

一、CLion项目结构

随便创建一个C++可执行文件项目,CLion IDE中显示的文件结构如下:

在这里插入图片描述

其中“外部库”一项指的是本项目之外的潜在头文件目录,从此处可以引一些基础头文件。

但是基础头文件肯定是不够的,玩不出太多花样。因此我们尝试添加更多的外部库使得更nb的头文件可以被引用。然而试了半天发现外部库是无法手动加入的(我之前还天真的以为右击就可以添加源)。

通过后面的试探,我们发现,CMakeLists.txt这个文件是主导这个操作的重要途径。

在这里插入图片描述

此处显示的就是一个最基本的CMakeLists结构。使用CMake编译能够高效地编译并构建整个项目,而不需要你在终端不断输入一些繁琐的命令(没错,说的就是g++),也不会生成一些讨厌的中间产物(诸如.obj,甚至.exe)。这里就四句话,我想大家应该能根据英语大概猜出这里的意思。其实分别就是检测cmake版本、构建项目并命名、设置C++标准,以及加入可执行文件。我们先展示这个,之后会慢慢拓展。

另外由于我们是新建了一个新项目,CLion贴心地自动帮我们添加了构建配置。打开“文件”>“设置”>“构建、执行、部署”>“CMake”,可以看到初始配置如图:

在这里插入图片描述

这个东西配好后,会生成一个cmake-build-debug的目录。在此基础上当你修改了你的CMakeLists文件时,CMake会被重新编译。

好,那么话说回来,到底怎么添加外部库呢?

二、引用外部库

之前尝试了用C++来实现OpenGL项目,于是随便打了个OpenGL项目。然而我们惊讶地发现,我们居然需要引两个不知名的东西:GLFW和glad(这两个东西在OpenGL的作用请自行搜查)!

在这里插入图片描述

然而可以看到我的include下面并没有报错,因为我已经解决了这个问题。那么我是怎么解决的呢?添加外部库嘛。那么又怎么添加呢?

首先,你得保证你的系统中有这么一些库的存在。常规的方法便是从比如GLFW网站上下载源码zip,然后使用CMake GUI这类工具进行构建,并在我们的CMakeLists文件中指明构建完成后的路径(感兴趣的话看看这个例子:https://zhuanlan.zhihu.com/p/375055950)。然而如你所见,这个方法极其繁琐,特别是参数和路径的配置,牵一发而动全身,一步错步步错。

因此一个更方便的方法是通过vcpkg工具去管理各种C++库。我们只需要执行两句话(注意我的vcpkg已经配置了环境变量):

vcpkg install glfw3:x64-mingw-static

vcpkg install glad:x64-mingw-static

然而虽然我们已经确认安装了这两个库,但是由于我们使用的是CLion自带的CMake,其与vcpkg并没有什么关系。所以我们需要链接CLion与vcpkg。参考这两篇文章:https://blog.csdn.net/xmcy001122/article/details/115557750https://blog.csdn.net/weixin_40448140/article/details/109111042

两个要点:

  1. 在“文件”>“设置”>“构建、执行、部署”>“CMake”中指定DCMAKE_TOOLCHAIN_FILE参数的路径;
  2. 写好CMakeLists.txt。

**另外注意:**你的项目路径中不能含有中文!(空格可以有)

因为我们是刚入手,所以CMakeLists确实是不好写。此处展示OpenGL这个项目的CMakeLists:

在这里插入图片描述

与最开始的CMakeLists只有两个差别:

  1. 第二行的set(VCPKG_TARGET_TRIPLET "x64-mingw-static" CACHE STRING "" FORCE) 是设置 vcpkgtriplet
  2. find_packagetarget_link_libraries实际上是vcpkg install完以后蹦出来的提示,要求你将其拷贝至CMakeList.txt中使用。

右击CMakeList.txt文件,重新加载CMake,如果编译通过,我们可以惊喜地发现:外部库中多了一个条目,而且头文件源码中的库不会报错了。

在这里插入图片描述

三、D3D12+CLion

**注意:**此处,我们采用红龙书中所举的例子(源码中的Chapter 6 Drawing in Direct3D\Box)。

1. 引用D3D库

我们知道,DirectX是Windows的孩子。其安装只能够通过Visual Studio Installer来进行(虽然如此,我依然选择CLion IDE)。

Direct3D 12 标头和库是 Windows 10 SDK 的一部分。 使用 Direct3D 12 时无需单独下载或安装。安装 Windows 10 SDK 软件并Visual Studio后,Direct3D 12 编程环境的设置已完成。

——Windows Direct3D 12文档

所以,理论上只要在VS Installer中安装Windows 10 SDK就行(也有可能要安装其他东西,但是我不太记得有没有了)。在你安装的对应VS版本中点击“修改”>“单个组件”>搜索“Windows 10 SDK”>选一个最新的装吧。

接着,同理,需要链接CLion与Visual Studio。如果你有注意的话,你会发现我们刚才修改了DCMAKE_TOOLCHAIN_FILE参数。再仔细一点的话,你会发现在“构建、执行、部署”>“CMake”条目的上面,有一个叫做“工具链”的东西。

在这里插入图片描述

此处展示的是我已经配置好的情况。如果没有动过的话,默认的工具链应该是MinGW。我们可以把Visual Studio设为默认(因为一般这个都拿来搞大工程嘛)。

但是!我想起来了!有可能会遇到这种状况:你明明下载了一个Visual Studio版本,可在这里的工具集却显示找不到!这是因为没有安装MSVC!(我就记得有什么东西要安装嘛)

参考https://blog.csdn.net/u011159582/article/details/109228999,同样在“修改”>“单个组件”中下载最新的MSVC,应该就能解决找不到工具集的问题。

(如果还报错的话自己查查还需要安装什么组件,因为我们保证这些组件是必须在VS Installer上安装的,比较规范,文档可查)

在“构建、执行、部署”>“CMake”中确认工具链为VS后,点击确定,我们会发现,外部库中出现了一堆前缀中包含Microsoft Visual Studio和Windows Kits 10的东西(并且以MinGW为前缀的那些库无了)。

2. CMakeLists

假设你上面的设置(安装VS Installer中的元件、配置工具链)都没错。现在我们check一下源码。当你点开一个源码时,如果你刚打开项目还没有CMakeLists文件,IDE会贴心地在顶栏问你:项目未配置,要不要自动创建一个CMakeList?此时你可以在这里创建一个CMakeLists,并将所有的C++源全部加进来。现在的CMakeLists的情况应该是这样:

cmake_minimum_required(VERSION 3.25)
project(Box)

set(CMAKE_CXX_STANDARD 14)

add_executable(Box
        BoxApp.cpp)

那我们试跑一下。

在这里插入图片描述

很遗憾,第一次报了这样一个错误。不仅是这里的MessageBox,我们发现很多其他地方,只要涉及到宽字符,都会或多或少有报错。即使是将这里的MessageBox改成MessageBoxW,或者强制类型转换,在一些地方的字符串也会变成乱码。

参考[1],我们知道这个问题是由于字符集所致。在VS IDE中,可以通过设置字符集来解决这个问题[2]。但是,找了半天,CLion没有这个选项。那怎么弄呢?

受[2]、[3]启发,我们搜索是否能在CMakeLists文件中声明编码,结果还真被我找到了,如[4]所示。

参考:

[1] https://stackoverflow.com/questions/13977388/error-cannot-convert-const-wchar-t-13-to-lpcstr-aka-const-char-in-assi

[2] https://stackoverflow.com/questions/46317752/how-to-change-project-character-set-in-jetbrains-clion

[3] https://stackoverflow.com/questions/53450841/d-unicode-string-literals-cant-print-specific-unicode-character

[4] https://blog.csdn.net/NAPO687/article/details/125754925

因此,我们在CMakeLists加上一句:

cmake_minimum_required(VERSION 3.25)
project(Box)

set(CMAKE_CXX_STANDARD 14)

add_executable(Box
        BoxApp.cpp)
add_definitions(-DUNICODE)

好,第二次构建:

====================[ 构建 | Box | Debug ]========================================
"C:\Program Files\JetBrains\CLion 2022.3.3\bin\cmake\win\x64\bin\cmake.exe" --build "D:\CityU\Collections\2023-04\d3d12book\Chapter 6 Drawing in Direct3D\Box\cmake-build-debug" --target Box -j 18
[0/1] Re-running CMake...
-- Configuring done
-- Generating done
-- Build files have been written to: D:/CityU/Collections/2023-04/d3d12book/Chapter 6 Drawing in Direct3D/Box/cmake-build-debug
[1/2] Building CXX object CMakeFiles\Box.dir\BoxApp.cpp.obj
[2/2] Linking CXX executable Box.exe
FAILED: Box.exe 
cmd.exe /C "cd . && "C:\Program Files\JetBrains\CLion 2022.3.3\bin\cmake\win\x64\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\Box.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100220~1.0\x86\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100220~1.0\x86\mt.exe --manifests  -- C:\PROGRA~1\MIB055~1\2022\COMMUN~1\VC\Tools\MSVC\1435~1.322\bin\Hostx86\x86\link.exe /nologo CMakeFiles\Box.dir\BoxApp.cpp.obj  /out:Box.exe /implib:Box.lib /pdb:Box.pdb /version:0.0 /machine:X86 /debug /INCREMENTAL /subsystem:console  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK Pass 1: command "C:\PROGRA~1\MIB055~1\2022\COMMUN~1\VC\Tools\MSVC\1435~1.322\bin\Hostx86\x86\link.exe /nologo CMakeFiles\Box.dir\BoxApp.cpp.obj /out:Box.exe /implib:Box.lib /pdb:Box.pdb /version:0.0 /machine:X86 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\Box.dir/intermediate.manifest CMakeFiles\Box.dir/manifest.res" failed (exit code 1120) with the following output:
BoxApp.cpp.obj : error LNK2019: 无法解析的外部符号 "public: static class Microsoft::WRL::ComPtr<struct ID3D12Resource> __cdecl d3dUtil::CreateDefaultBuffer(struct ID3D12Device *,struct ID3D12GraphicsCommandList *,void const *,unsigned __int64,class Microsoft::WRL::ComPtr<struct ID3D12Resource> &)" (?CreateDefaultBuffer@d3dUtil@@SA?AV?$ComPtr@UID3D12Resource@@@WRL@Microsoft@@PAUID3D12Device@@PAUID3D12GraphicsCommandList@@PBX_KAAV234@@Z),函数 __catch$_WinMain@16$0 中引用了该符号
... # 此处省略另外17个“BoxApp.cpp.obj : error LNK2019: 无法解析的外部符号”
Box.exe : fatal error LNK1120: 18 个无法解析的外部命令
ninja: build stopped: subcommand failed.

看起来一团乱麻,但是全都是“BoxApp.cpp.obj : error LNK2019: 无法解析的外部符号”。仔细一看,这些函数来源都来自../../Common中的那些函数定义。于是我们在CMakeLists中引入这些cpp文件:

cmake_minimum_required(VERSION 3.25)
project(Box)

set(CMAKE_CXX_STANDARD 14)
set(D3D_APP_SRC ../../Common/d3dApp.cpp)
set(D3D_UTIL_SRC ../../Common/d3dUtil.cpp)
set(GAME_TIMER_SRC ../../Common/GameTimer.cpp)
set(DDS_TEXTURE_LOADER_SRC ../../Common/DDSTextureLoader.cpp)
set(MATH_HELPER_SRC ../../Common/MathHelper.cpp)

add_executable(Box
        BoxApp.cpp
        ${D3D_APP_SRC}
        ${D3D_UTIL_SRC}
        ${GAME_TIMER_SRC}
        ${DDS_TEXTURE_LOADER_SRC}
        ${MATH_HELPER_SRC})
add_definitions(-DUNICODE)

第三次编译:

====================[ 构建 | Box | Debug ]========================================
"C:\Program Files\JetBrains\CLion 2022.3.3\bin\cmake\win\x64\bin\cmake.exe" --build "D:\CityU\Collections\2023-04\d3d12book\Chapter 6 Drawing in Direct3D\Box\cmake-build-debug" --target Box -j 18
[0/1] Re-running CMake...
-- Configuring done
-- Generating done
-- Build files have been written to: D:/CityU/Collections/2023-04/d3d12book/Chapter 6 Drawing in Direct3D/Box/cmake-build-debug
[1/6] Building CXX object CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\GameTimer.cpp.obj
[2/6] Building CXX object CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\MathHelper.cpp.obj
[3/6] Building CXX object CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\DDSTextureLoader.cpp.obj
[4/6] Building CXX object CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\d3dUtil.cpp.obj
[5/6] Building CXX object CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\d3dApp.cpp.obj
[6/6] Linking CXX executable Box.exe
FAILED: Box.exe 
cmd.exe /C "cd . && "C:\Program Files\JetBrains\CLion 2022.3.3\bin\cmake\win\x64\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\Box.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100220~1.0\x86\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100220~1.0\x86\mt.exe --manifests  -- C:\PROGRA~1\MIB055~1\2022\COMMUN~1\VC\Tools\MSVC\1435~1.322\bin\Hostx86\x86\link.exe /nologo CMakeFiles\Box.dir\BoxApp.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\d3dApp.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\d3dUtil.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\GameTimer.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\DDSTextureLoader.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\MathHelper.cpp.obj  /out:Box.exe /implib:Box.lib /pdb:Box.pdb /version:0.0 /machine:X86 /debug /INCREMENTAL /subsystem:console  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK Pass 1: command "C:\PROGRA~1\MIB055~1\2022\COMMUN~1\VC\Tools\MSVC\1435~1.322\bin\Hostx86\x86\link.exe /nologo CMakeFiles\Box.dir\BoxApp.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\d3dApp.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\d3dUtil.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\GameTimer.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\DDSTextureLoader.cpp.obj CMakeFiles\Box.dir\D_\CityU\Collections\2023-04\d3d12book\Common\MathHelper.cpp.obj /out:Box.exe /implib:Box.lib /pdb:Box.pdb /version:0.0 /machine:X86 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\Box.dir/intermediate.manifest CMakeFiles\Box.dir/manifest.res" failed (exit code 1120) with the following output:
MSVCRTD.lib(exe_main.obj) : error LNK2019: 无法解析的外部符号 _main,函数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) 中引用了该符号
Box.exe : fatal error LNK1120: 1 个无法解析的外部命令
ninja: build stopped: subcommand failed.

直接说。这个的解决方法是在add_executable声明其为WIN32可执行文件:

add_executable(Box WIN32
        BoxApp.cpp
        ${D3D_APP_SRC}
        ${D3D_UTIL_SRC}
        ${GAME_TIMER_SRC}
        ${DDS_TEXTURE_LOADER_SRC}
        ${MATH_HELPER_SRC})

这样以后,再次构建:

在这里插入图片描述

终于!写完啦!!(并感

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值