1. 项目概述:为什么图形学环境搭建是第一个“拦路虎”?
如果你刚拿到《计算机图形学编程(使用OpenGL和C++)》这本书,或者任何一本类似的经典教材,翻到第一章,大概率会看到“环境搭建”这几个字。很多新手朋友会想,不就是装个软件、配个路径吗,网上教程一抓一大把,赶紧跳过,直奔后面炫酷的三角形和3D模型。但以我十多年的图形开发经验来看,这个想法恰恰是后续一系列“诡异”问题的根源。图形学编程的环境搭建,远不止是“安装”,它更像是在你的电脑上,为OpenGL、C++编译器和图形驱动这三方势力,搭建一个能和平共处、高效协作的“谈判桌”。任何一方的配置有细微偏差,都可能让最简单的“Hello Window”程序都跑不起来,更别提后面的光照、纹理和着色器了。
这个学习笔记系列,就从这最基础、也最关键的“01.环境搭建”开始。我们的目标不是简单地罗列安装步骤,而是深入理解每一步背后的“为什么”。为什么选择这个编译器?为什么需要GLFW和GLAD?CMake在这里扮演什么角色?我们会使用 Visual Studio 2022 作为主力IDE,搭配 vcpkg 这个现代C++包管理工具来管理依赖,这比手动下载、配置库文件要优雅和可靠得多。整个流程会覆盖Windows平台,确保你能从一个干净的开发环境开始,建立起一个稳固、可复用的图形学项目模板。这个模板将成为你后续所有实验和学习的基石,避免每次开新项目都要重新折腾环境的窘境。
2. 核心工具链选型与原理剖析
在动手敲命令之前,我们必须搞清楚要请哪些“演员”上台,以及他们各自的角色。图形学编程是一个典型的“系统级”编程领域,它紧密依赖于操作系统、硬件驱动和底层API。
2.1 为什么是Visual Studio 2022 + vcpkg?
首先,编译器。在Windows上, Microsoft Visual C++ (MSVC) 是事实上的标准。很多底层的Windows API和驱动交互优化都是围绕MSVC进行的。选择 Visual Studio 2022 Community版 (免费且功能完整)而非其他编辑器或MinGW,能最大程度避免因编译器差异导致的链接错误和运行时异常。尤其是涉及到OpenGL的扩展加载和某些平台特定代码时,MSVC的兼容性是最好的。
其次,包管理。传统方式是从官网下载GLFW、GLAD等库的源码或预编译包,然后手动设置包含目录、库目录和附加依赖项。这种方式繁琐、易出错,且难以管理版本。 vcpkg 是微软推出的C++库管理工具,它像Python的pip或Node.js的npm一样,可以一键安装、编译并集成库到你的项目中。它会自动处理头文件路径、库文件链接以及Debug/Release版本的切换,让依赖管理变得清晰可控。
2.2 OpenGL、GLFW与GLAD:三位一体的分工
这是核心中的核心,必须理解它们的关系。
-
OpenGL本身 :它只是一个 规范 (Specification),一套由Khronos Group定义的函数API标准。它并不是一个你可以直接链接的.dll或.lib文件。你的显卡制造商(如NVIDIA、AMD、Intel)负责根据这个规范,编写具体的 驱动程序 (Driver)。真正的OpenGL实现就在这个驱动里。
-
GLFW :它的角色是 窗口和输入管理器 。原生OpenGL API并不关心如何创建窗口、处理鼠标键盘事件或读取时间。这些是操作系统(如Windows的Win32 API)负责的。GLFW为我们封装了这些跨平台的、繁琐的底层操作,提供了统一的接口来创建OpenGL渲染上下文、管理窗口和接收输入。没有它,你就要写一大堆平台特定的代码,分散学习图形学本身的精力。
-
GLAD :这是最容易被误解,也最关键的一环。OpenGL有多个版本(如3.3, 4.6),并且显卡厂商会通过 扩展 (Extensions)来提供新功能。这些函数在编译时对你的程序来说是“未知”的。 GLAD是一个扩展加载库 。它的核心工作是:在运行时,向你的显卡驱动“查询”当前环境支持的OpenGL版本和扩展,并获取这些新函数的实际内存地址,然后为你生成对应的函数指针。这样,你才能在代码里安全地调用像
glGenBuffers这样的现代OpenGL函数。如果不使用GLAD或类似的库(如GLEW),你只能使用非常古老的、固定的OpenGL 1.x函数。
注意 :很多新手会混淆GLAD和GLFW。记住一个简单的比喻:GLFW是“舞台经理”,负责搭台子(窗口)和接待观众(输入);而GLAD是“翻译官”,负责让导演(你的C++程序)能指挥来自世界各地(不同显卡驱动)的演员(OpenGL函数)。
3. 详细环境搭建实操步骤
下面我们一步步搭建环境。请严格按照顺序操作,并理解每一步的目的。
3.1 安装Visual Studio 2022
- 访问Visual Studio官网,下载Community 2022安装程序。
- 运行安装程序,在工作负载选择页面, 必须勾选“使用C++的桌面开发” 。这个工作负载包含了MSVC编译器、CMake、Windows SDK等所有必要组件。
- 在右侧的“安装详细信息”中,建议确保“Windows 10/11 SDK”和“C++ CMake工具”被选中。
- 点击安装,等待完成。这个过程可能会比较长,取决于网速。
3.2 安装与配置vcpkg
vcpkg是环境自动化的核心,我们需要先安装它,然后用它来安装我们需要的库。
-
克隆vcpkg仓库 :打开PowerShell或CMD,选择一个你喜欢的目录(例如
C:\Dev),执行以下命令。这会把vcpkg的源码克隆到本地。git clone https://github.com/Microsoft/vcpkg.git cd vcpkg -
引导vcpkg :执行引导脚本,这会编译vcpkg自身的可执行文件。
.\bootstrap-vcpkg.bat执行成功后,当前目录下会生成一个
vcpkg.exe文件。 -
集成到系统(全局) (可选但强烈推荐):为了让Visual Studio能自动发现vcpkg安装的库,运行集成命令。这只需要做一次。
.\vcpkg integrate install你会看到提示“Applied user-wide integration for this vcpkg root.”,表示成功。
-
安装所需库 :现在,用vcpkg安装GLFW和GLAD。注意,GLAD在vcpkg中的端口名是
glad,GLFW是glfw3。.\vcpkg install glfw3 glad --triplet x64-windows这里
--triplet x64-windows指定我们安装64位Windows版本的库。vcpkg会自动从源码编译这些库,并处理所有依赖。第一次安装会下载编译工具链(如CMake),需要耐心等待。实操心得 :
vcpkg install命令可能会因为网络问题失败。如果遇到下载超时,可以尝试设置命令行代理(set HTTP_PROXY=...)或使用镜像源。另一个常见问题是,如果你的系统缺少Windows SDK,编译可能会报错。此时回头检查Visual Studio安装,确保SDK组件已勾选。
3.3 创建并配置第一个CMake项目
我们不直接使用Visual Studio的.sln方案,而是采用更通用、更灵活的 CMake 来管理项目。这是现代C++项目的标准做法。
-
创建项目目录结构 :新建一个文件夹作为你的项目根目录,例如
LearnOpenGL。在里面创建以下子文件夹和文件:LearnOpenGL/ ├── CMakeLists.txt # CMake构建脚本 ├── src/ # 存放源代码 │ └── main.cpp # 主程序入口 └── include/ # 存放自定义头文件(暂时为空) -
编写CMakeLists.txt :这是项目的“总蓝图”,告诉CMake如何构建你的程序。用文本编辑器打开
CMakeLists.txt,写入以下内容:cmake_minimum_required(VERSION 3.15) # 指定CMake最低版本 project(LearnOpenGL LANGUAGES CXX) # 定义项目名和语言(C++) # 设置C++标准为C++17(或更高,现代OpenGL教程常要求C++11以上) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 重要:告诉CMake去查找vcpkg安装的库。 # 将下面的路径替换为你自己的vcpkg安装目录。 set(CMAKE_TOOLCHAIN_FILE "C:/Dev/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") # 查找所需的库包。find_package命令会借助vcpkg.cmake自动定位头文件和库文件。 find_package(glfw3 CONFIG REQUIRED) find_package(glad CONFIG REQUIRED) # 添加可执行目标,并链接库 add_executable(${PROJECT_NAME} src/main.cpp) # 将找到的库链接到我们的可执行文件上 target_link_libraries(${PROJECT_NAME} PRIVATE glfw glad) # 对于GLFW,有时还需要链接Windows的系统库 if (WIN32) target_link_libraries(${PROJECT_NAME} PRIVATE opengl32) endif()关键解释 :
-
CMAKE_TOOLCHAIN_FILE:这是连接CMake和vcpkg的桥梁。必须正确指向你的vcpkg.cmake文件路径。 -
find_package:CMake通过这个命令来查找库。CONFIG模式表示寻找库提供的CMake配置文件(vcpkg为每个库都生成了这个文件)。 -
target_link_libraries:将库的接口(头文件路径)和实现(库文件)关联到你的目标程序。
-
-
编写第一个OpenGL程序(src/main.cpp) :我们先创建一个能打开一个窗口的程序,验证环境是否成功。
#include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> // 窗口大小变化时的回调函数 void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } // 处理输入 void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } int main() { // 初始化GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // 设置OpenGL主版本号 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // 设置OpenGL次版本号 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用核心模式 // 创建窗口对象 GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // 初始化GLAD,加载OpenGL函数指针 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } // 设置视口大小,并注册回调函数 glViewport(0, 0, 800, 600); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // 渲染循环 while (!glfwWindowShouldClose(window)) { // 输入处理 processInput(window); // 渲染指令(这里用清空颜色缓冲来替代) glClearColor(0.2f, 0.3f, 0.3f, 1.0f); // 设置清空屏幕所用的颜色 glClear(GL_COLOR_BUFFER_BIT); // 清空颜色缓冲 // 检查并调用事件,交换缓冲 glfwSwapBuffers(window); // 交换颜色缓冲(双缓冲机制) glfwPollEvents(); // 触发键盘鼠标等事件 } // 清理资源,退出 glfwTerminate(); return 0; }
3.4 使用Visual Studio的CMake模式进行构建与调试
这是最便捷的方式,VS2022对CMake项目的支持已经非常完善。
-
打开项目文件夹
:启动Visual Studio 2022,选择“打开本地文件夹”,然后导航到你创建的
LearnOpenGL文件夹并打开。 -
选择构建套件
:VS会自动识别CMakeLists.txt。在底部状态栏,点击“解决方案配置”,确保选择的是
x64-Debug(或x64-Release)。第一次打开时,VS会运行CMake配置(Configure)和生成(Generate),这会在项目根目录下生成一个out/build文件夹存放构建中间文件。 -
构建与运行
:按
F5或点击顶部菜单的“调试 -> 开始调试”。VS会编译项目并运行。如果一切顺利,你将看到一个大小为800x600、背景色为蓝绿色的窗口。按下ESC键,窗口会关闭。
4. 环境验证与深度问题排查
即使按照步骤操作,也可能会遇到问题。下面是一些常见错误及其根因和解决方案。
4.1 常见编译与链接错误速查表
| 错误信息或现象 | 可能原因 | 解决方案 |
|---|---|---|
fatal error C1083: Cannot open include file: ‘glad/glad.h’
|
1. vcpkg未正确安装glad。
2. CMake未正确找到vcpkg的包。 3.
CMAKE_TOOLCHAIN_FILE
路径设置错误。
|
1. 在vcpkg目录下运行
.\vcpkg list
,确认
glad
和
glfw3
已安装。
2. 检查
CMakeLists.txt
中
CMAKE_TOOLCHAIN_FILE
的路径,必须使用
正斜杠(/)或双反斜杠(\\)
,且路径正确。
3. 在VS中,尝试删除项目下的
out
和
CMakeCache.txt
文件,然后重新打开文件夹,触发CMake重新配置。
|
LNK2019: 无法解析的外部符号 __imp_glfwInit...
| 库文件链接失败。GLFW库没有正确链接到可执行文件。 |
1. 确保
target_link_libraries
中包含了
glfw
。
2. 确保
find_package(glfw3 ...)
成功。可以在CMake配置后,查看VS的输出窗口,看是否有找到包的提示。
3. 确认安装的是
x64-windows
版本,且VS中构建目标也是
x64
。
|
| 窗口打开后立即崩溃或黑屏 |
1. OpenGL上下文创建失败(驱动不支持要求的版本)。
2. GLAD初始化失败。 |
1. 检查
glfwWindowHint
设置的OpenGL版本(如3.3)是否高于你显卡支持的最低版本。可以尝试降低到
3.0
。
2. 在
gladLoadGLLoader
之后添加检查:
std::cout << "OpenGL " << glGetString(GL_VERSION) << std::endl;
查看驱动实际提供的版本。
3. 最重要 :确保你的显卡驱动是最新的。去NVIDIA/AMD/Intel官网下载并安装最新驱动。 |
CMake Error at ... : Could not find a package configuration file ...
| vcpkg的包没有被CMake找到。 |
1. 确认
CMAKE_TOOLCHAIN_FILE
路径绝对正确。
2. 尝试在CMake配置时显式指定工具链文件:在VS中,项目 -> CMake设置 -> CMake工具链文件,手动选择
vcpkg.cmake
文件。
|
| 程序运行正常,但控制台输出乱码 | VS控制台默认编码与程序输出不匹配。 |
在
main
函数开头添加:
system(“chcp 65001”);
将控制台代码页设置为UTF-8。或者直接在VS中修改执行环境的编码设置。
|
4.2 驱动与OpenGL版本兼容性深度解析
这是图形学环境中最隐晦的坑。你的代码请求OpenGL 3.3,但为什么有时能用,有时不行?关键在于 驱动创建的上下文(Context) 。
当你调用
glfwCreateWindow
时,GLFW会向操作系统请求一个符合你要求的OpenGL渲染上下文。操作系统和显卡驱动会协商,返回一个它们
实际能提供
的、最匹配的上下文。如果你的显卡比较老,或者驱动太旧,可能只支持到OpenGL 3.1,那么你请求3.3就会失败,GLFW会返回
NULL
。
如何排查?
- 使用工具:下载GPU-Z或OpenGL Extensions Viewer这类工具,查看你的显卡 最大支持的OpenGL版本 。
-
代码检查:在初始化GLAD成功后,立即用
glGetString(GL_VERSION)和glGetString(GL_RENDERER)打印出版本和渲染器信息,确认实际获得的上下文版本。 -
降级请求:如果显卡只支持到3.1,请将
glfwWindowHint中的版本号改为3.1,并使用对应版本的GLAD(需要在GLAD网站上重新生成加载器)。现代OpenGL的核心功能从3.0/3.1开始就已基本定型,学习初期用3.1也完全足够。
4.3 vcpkg集成模式下的“神奇”与“陷阱”
使用
vcpkg integrate install
全局集成后,在Visual Studio中创建
非CMake
的传统
.sln
项目时,也能自动包含vcpkg安装的库,非常方便。但这也可能带来混淆。
“神奇”之处 :你不需要在项目属性里手动添加包含目录和库目录,VS会自动帮你搞定。
“陷阱”之处 :
- 版本冲突 :如果你之前手动配置过库路径,可能会和vcpkg的集成产生冲突,导致链接到错误的库版本。
-
清理困难
:如果想卸载vcpkg或切换版本,需要运行
.\vcpkg integrate remove来移除集成。 -
CMake项目优先
:对于我们的CMake项目,
CMAKE_TOOLCHAIN_FILE的优先级高于全局集成。CMake会严格使用它在vcpkg_installed目录下找到的库。
我的建议是: 对于新项目,尤其是学习项目,坚持使用CMake + vcpkg工具链的方式 。它清晰、可移植(你的项目目录可以拷贝到任何配置好vcpkg的机器上直接构建)、且易于管理依赖版本。
5. 构建脚本优化与项目结构规划
一个良好的开端是成功的一半。现在环境通了,我们来优化一下项目结构,让它更适合长期学习和代码管理。
5.1 优化CMakeLists.txt以提高可维护性
之前的CMakeLists.txt是功能性的,但可以写得更好。下面是一个增强版:
cmake_minimum_required(VERSION 3.15)
project(LearnOpenGL LANGUAGES CXX)
# 1. 定义项目版本(可选,但好习惯)
set(LearnOpenGL_VERSION_MAJOR 0)
set(LearnOpenGL_VERSION_MINOR 1)
# 2. 设置输出目录,让生成的可执行文件放在项目根目录的bin文件夹下
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
# 3. 设置C++标准与编译警告
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # 禁用编译器特定扩展,保证跨编译器兼容性
if (MSVC)
# MSVC编译器警告设置
add_compile_options(/W4 /WX) # 开启大部分警告,并将警告视为错误(严格要求)
else()
# GCC/Clang编译器警告设置
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
endif()
# 4. 指定vcpkg工具链(重要!路径根据实际修改)
set(CMAKE_TOOLCHAIN_FILE "C:/Dev/vcpkg/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "Vcpkg toolchain file")
# 5. 查找依赖包
find_package(glfw3 CONFIG REQUIRED)
find_package(glad CONFIG REQUIRED)
# 6. 添加可执行文件目标
add_executable(${PROJECT_NAME} src/main.cpp)
# 7. 指定头文件包含目录
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
# 8. 链接库
target_link_libraries(${PROJECT_NAME} PRIVATE glfw glad)
# 9. 平台特定的链接库
if (WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE opengl32)
endif()
优化点解析 :
-
输出目录管理
:将生成的可执行文件(.exe)统一输出到
/bin目录,库文件到/lib,保持源码目录的整洁。 -
编译警告即错误
:
/WX或-Werror标志能强制你以更高的代码质量要求自己,在学习初期就养成良好的编程习惯,避免隐藏的bug。 -
清晰的包含目录
:使用
target_include_directories明确指定自定义头文件路径,比全局设置include_directories更规范。
5.2 规划可持续学习的项目结构
随着学习深入,你会有多个章节的代码(画三角形、着色器、纹理、模型加载)。我推荐按以下方式组织,而不是把所有代码都堆在
main.cpp
里。
LearnOpenGL/
├── CMakeLists.txt
├── bin/ # 生成的可执行文件
├── lib/ # 生成的库文件(如有)
├── assets/ # 资源文件:着色器、纹理、模型
│ ├── shaders/
│ ├── textures/
│ └── models/
├── include/ # 项目公共头文件
│ └── utils/ # 工具类,如Shader加载器、Camera类
├── src/ # 源代码
│ ├── chapter1/ # 第1章:窗口与环境
│ │ └── main_window.cpp
│ ├── chapter2/ # 第2章:第一个三角形
│ │ ├── main_triangle.cpp
│ │ └── shader.cpp # 着色器类实现
│ ├── utils/ # 工具类实现
│ │ ├── shader.cpp
│ │ └── camera.cpp
│ └── main.cpp # 主入口(未来可能用于切换不同章节的演示)
└── build/ # CMake构建目录(可由VS自动生成,也可手动创建)
对应的CMakeLists.txt调整思路 : 你可以为每个章节创建一个单独的可执行文件目标。
# 在find_package之后...
add_executable(Chapter1_Window src/chapter1/main_window.cpp src/utils/shader.cpp)
target_link_libraries(Chapter1_Window PRIVATE glfw glad opengl32)
target_include_directories(Chapter1_Window PRIVATE include)
add_executable(Chapter2_Triangle src/chapter2/main_triangle.cpp src/utils/shader.cpp)
target_link_libraries(Chapter2_Triangle PRIVATE glfw glad opengl32)
target_include_directories(Chapter2_Triangle PRIVATE include)
这样,在VS里你会看到多个启动项,可以分别编译和运行不同章节的示例,互不干扰。
6. 进阶准备:着色器与资源文件管理
环境搭建的最后一步,是准备好如何管理那些非代码的“资源”,最主要的就是 着色器(Shader) 。着色器是文本文件(.vs, .fs),但我们需要在C++程序中读取它们的内容,然后编译链接成GPU程序。
6.1 实现一个简单的着色器类
在
include/utils/shader.h
和
src/utils/shader.cpp
中创建一个
Shader
类。这个类封装了从文件读取、编译、链接和使用的过程。这是几乎所有OpenGL教程都会教你的第一个工具类,它能极大简化后续操作。
shader.h 示例框架:
#pragma once
#include <glad/glad.h>
#include <string>
#include <glm/glm.hpp> // 后续用于传递矩阵等uniform变量
class Shader {
public:
unsigned int ID; // 着色器程序ID
Shader(const char* vertexPath, const char* fragmentPath);
void use();
void setBool(const std::string &name, bool value) const;
void setInt(const std::string &name, int value) const;
void setFloat(const std::string &name, float value) const;
void setMat4(const std::string &name, const glm::mat4 &mat) const;
// ... 其他set方法
private:
void checkCompileErrors(unsigned int shader, std::string type);
};
关键点
:构造函数接受顶点和片段着色器文件的路径,在内部完成
glCreateShader
,
glShaderSource
,
glCompileShader
,
glAttachShader
,
glLinkProgram
这一系列操作,并检查编译和链接错误。
6.2 在CMake中处理资源文件路径
一个常见问题是,你的可执行文件在
/bin
目录下运行,但着色器文件在
/assets/shaders
目录里。直接使用相对路径
”../assets/shaders/xxx.vs”
可能不可靠。
解决方案有两种:
-
工作目录设置
:在Visual Studio中,右键可执行文件目标 -> “属性” -> “调试”,将“工作目录”设置为
${ProjectDir}(即项目根目录)。这样程序运行时,其当前目录就是项目根目录,可以直接使用”assets/shaders/xxx.vs”路径。 -
将资源文件复制到输出目录
:在CMakeLists.txt中添加后构建命令,将
assets文件夹复制到bin目录下。这样无论从哪里运行,资源都在可执行文件旁边。
我个人更推荐第一种方法,因为它更干净,且便于在IDE中直接编辑资源文件。# 在add_executable之后 add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/assets $<TARGET_FILE_DIR:${PROJECT_NAME}>/assets )
至此,一个功能完整、结构清晰、便于调试和扩展的OpenGL学习环境就彻底搭建完毕了。这个环境不仅能运行《计算机图形学编程》书中的示例,也完全有能力作为你未来进行更复杂图形学项目或实验的起点。记住,环境搭建不是一劳永逸的,随着项目复杂度的提升,你可能需要引入像
glm
(数学库)、
stb_image
(图像加载库)等更多依赖,但有了vcpkg和CMake这个坚实基础,添加新库将变得非常简单——只需
vcpkg install glm
,然后在CMakeLists.txt中
find_package(glm)
并
target_link_libraries
即可。


被折叠的 条评论
为什么被折叠?



