基于CMake+CLion创建OpenGL开发环境总结

作为一名iOS开发工程师,平时使用的开发工具都是Xcode偏多,以往链接开发文件、第三方库、图片字体资源等等都只需要交给Xcode来处理即可,我只需要做一个简单的创建或导入操作,还有就是借助方便快捷的CocoaPods强大管理库工具十分简单完成。最近打算写一个文本渲染的项目,最终选择的技术方案是C++、OpenGL和FreeType,并且希望是可以跨平台编译和运行的,经过一番咨询和查找,了解CMake作为首选的工具之一,本着大众原则因此选择CMake构建项目。没想到CMake的使用程度难倒我不少时间,经过一番的学习和研究,从未接触过CMake到了解CMake实现基本的项目构建,因此想通过输出的方式,总结所学的知识,那么就开始吧。 项目链接 如果能帮到你,希望你能给我点个赞或评论吧~

开发项目需要借助一个好的工具,因此我的开发环境是

objectivec 复制代码
macOS Ventura 13.2.x
CLion 

CLion 创建项目后会自动生成一个CMakeLists.text的文件,主要构建项目的编译逻辑就在这个文件中,CLion生成一个新的项目后,在CMakeLists.text会生成一些基础代码,如下:

js 复制代码
cmake_minimum_required(VERSION 3.25)  
project(CmakeDemo)  
  
set(CMAKE_CXX_STANDARD 17)  
  
add_executable(CmakeDemo main.cpp)
  • cmake_minimum_required(VERSION 3.25) 表示CMake最小版本号, 运行的CMake版本要大于或等于该版本号
  • project(CmakeDemo) CmakeDemo表示项目名称,
  • project(CmakeDemo VERSION 1.0.0)该语句还可以定义项目的版本号
  • set(CMAKE_CXX_STANDARD 17) 表示项目编译语言和版本,这里表示支持 C++ 17语言标准
  • add_executable(CmakeDemo main.cpp) 添加执行文件,比如 main.cpp

简单的项目构建就完成了,不过十分简单还不满足用于项目。 因此我们需要一个大致完整的项目结构,一个项目主要分为src源文件、deps第三方依赖库、resource图片字体等资源,因此如下文件结构:

css 复制代码
├── deps
├── resources
└── src
    ├── CMakeLists.txt
    ├── hello.hpp
    ├── test1.hpp
    ├── test3.cpp
    └── test3.hpp

src

首先从src源文件开始,分为两种情况:

  • 如果src只有头文件,那么在主目录中的CMakeLists.text如下设置:

    js 复制代码
    file(GLOB SRC_FILE src/*.hpp) # GLOB 表示将所有.hpp结尾的文件都存入`SRC_FILE`这个变量中
    add_executable(CmakeDemo main.cpp ${SRC_FILE})
    target_include_directories(${PROJECT_NAME} PRIVATE src) # src 为路径名称

    那么就可以通过#include "hello.hpp"进行调用

  • 如果src包含头文件和源文件cpp的话,那么可以在目录中创建CMakeLists.text来管理该文件的构建,在src/CMakeLists.text可以这样写

js 复制代码
set(SRC_FILES  
       hello.hpp  
       test3.cpp  
       test3.hpp  
       test1.hpp  
       )  
 
add_library(src_lib ${SRC_FILES})  #
target_include_directories(src_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
  • add_library: 将路径中文件创建一个名为src_lib的库
  • target_include_directories:这个设置会将src目录的路径添加到src_library(这是在目录中创建的可执行文件或其他目标)的头文件搜索路径中。这样,在项目中的任何源文件中,都可以使用#include包含src目录中的头文件,例如:#include "hello.hpp".
  • 然后在主目录的CMakeLists.text 设置以下语句即可:
js 复制代码
add_subdirectory(src)  
  
add_executable(CmakeDemo main.cpp)  
// 该语句需要在add_executable 下面
target_link_libraries(${PROJECT_NAME} PRIVATE src_lib)
  • add_subdirectory: 添加子目录src
  • target_link_libraries: 将生成的库src_lib连接到项目中 最后简单的子目录构建编译就完成了

deps 第三方库的添加

第三方库添加入项目主要分为源码git submodelfind_package等等,这里只总结源码和find_package两种情况

源码

项目创建一个名为deps的文件主要存放第三方库的源码,因为我是创建OpenGL的相关的项目,需要用到gladglm库,以这两个库为例子。

点击构建按钮创建所需版本的glad项目,最后下载下来得到一份glad的源码。 我们直接拖进项目中的deps目录中即可。 CMakeLists.text新增glad和glm库的设置

js 复制代码
# glad  
## 添加源文件生成一个库  
add_library(glad deps/glad/src/glad.c)  
# 定义目标索引位置  
target_include_directories(glad PUBLIC deps/glad/include)

#glm  
add_subdirectory(deps/glm)  
## 创建一个库并生成别名  
add_library(glm:glm ALIAS glm)

# 链接库到主项目中
target_link_libraries(${PROJECT_NAME} PRIVATE glad glm:glm)
  • glad:根据源文件glad.c生成一个名为glad的库,并定义目标索引位置供项目方便调用,并最终链接到主项目中
  • glm:首先添加子目录文件,最后target_link_libraries链接到主项目中, 至此源码导入工程就完成了.
  • 总结:
    • 一般第三方库没有CMakeLists.text 文件的话,那么就要我们自己添加源文件(.cpp)生成一个库,并且定义目标索引位置方便查找。一般是src和include两个文件的处理。
    • 第三方库提供CMakeLists.text处理文件构建的话,那么我们只需要构建子目录add_subdirectory并根据子目录CMakeLists.text中生成库的名称例如glm,链接到主项目中。

源码的方式适用于无法通过find_package语句搜索到的第三方库或者自定义的库中使用,而一般比较出名的第三方都可以通过find_package进行依赖使用。

find_package

find_package 的作用是引入外部依赖包,通过CMake内置模块导入依赖库,这些库可以在/usr/local/Cellar/cmake/3.22.3/share/cmake/Modules CMake的安装路径中可以查找到,/usr/local/Cellar是我的路径,你可以根据你自己的路径查找出来。在Modules的文件下,每个以Find<LibaryName>.cmake命名的文件都可以帮我们找到一个包,例如`FindOpenGL.cmake就是OpenGL的库。使用方式也很简单:

js 复制代码
# OpenGL  
find_package(OpenGL REQUIRED) # REQUIRED:必须的意思  
# FreeType  
find_package(Freetype REQUIRED)  
# glfw3  
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)  
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)  
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)  
find_package(glfw3 3.3 REQUIRED)

### 部分省略,可以看源码

target_link_libraries(${PROJECT_NAME} PRIVATE src_lib glad glfw glm OpenGL::GL Freetype::Freetype )

glfw3 3.3Freetype这些名称都是由库自身的官方提供,或者CMake 官方内置提供。

这种方式就比较方便,不需要自己去链接文件和生成库处理,find_package还可以查找你的系统文件夹或者系统库。如果在CMakeModule文件中没有找到需要的库,也可以自行安装(只对支持CMake编译安装的库有效),具体方式这里就不展开了,详情可以网上搜索find_package引入非官方的库

如何导入资源

在开发过程中,经常会用到图片、字体、或者着色器等资源文件,那么我们也需要在CMake构建中处理这些资源文件。当前资源目录如下:

js 复制代码
├── resources
│   └── fonts
│       ├── Songti.ttc
│       ├── antoniolight.ttf
│       └── jianti.ttf

图片、字体、着色器资源都可以向上述目录路径放置,在CMakeLists.text的处理也是十分简单:

js 复制代码
add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD  
COMMAND ${CMAKE_COMMAND} -E copy_directory  
${CMAKE_SOURCE_DIR}/resources  
$<TARGET_FILE_DIR:${PROJECT_NAME}>/resources  
)

add_custom_command 这种方式有一个好处就是,每次添加文件的时候不需要执行一次CMake,而是放在编译的时候去执行,因此可以直接添加所需文件执行程序即可。

主文件中的CMakeLists.text文件内容如下:

js 复制代码
cmake_minimum_required(VERSION 3.25)  
project(CmakeDemo VERSION 1.0.0)  
  
set(CMAKE_CXX_STANDARD 17)  
  
# OpenGL  
find_package(OpenGL REQUIRED) # REQUIRED:必须的意思  
# FreeType  
find_package(Freetype REQUIRED)  
# glfw3  
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)  
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)  
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)  
find_package(glfw3 3.3 REQUIRED)  
# glad  
## 添加源文件生成一个库  
add_library(glad deps/glad/src/glad.c)  
# 定义目标索引位置  
target_include_directories(glad PUBLIC deps/glad/include)  
#glm  
add_subdirectory(deps/glm)   
  
add_subdirectory(src)  
  
add_executable(CmakeDemo main.cpp)  
  
add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD  
COMMAND ${CMAKE_COMMAND} -E copy_directory  
${CMAKE_SOURCE_DIR}/resources  
$<TARGET_FILE_DIR:${PROJECT_NAME}>/resources  
)  
  
target_link_libraries(${PROJECT_NAME} PRIVATE src_lib glad glfw glm OpenGL::GL Freetype::Freetype )

总结

经过srcdepsresource三个模块的构建之后就得出一个基础开发的环境,同时根据自己的需求在里面添砖加瓦。

CMake这个构建项目工具我也是第一次使用,还有很多知识点的缺少,想要深入理解还需要查看CMake的文档,不过这篇文章我相信足够一般基础的使用,最后希望能帮你吧!

项目链接: 如果能帮到你,希望你能给我点个赞或评论吧~

相关推荐
代码小将3 分钟前
PTA数据结构编程题7-1最大子列和问题
数据结构·c++·笔记·学习·算法
HackKong8 分钟前
高校网络安全_网络安全之道
java·网络·c++·python·学习·web安全·黑客技术
BUG制造机.23 分钟前
修炼之道 ---其四
linux·c++
神经网络的应用1 小时前
C++程序设计例题——第三章程序控制结构
c++·学习·算法
zfenggo2 小时前
c/c++ 无法跳转定义
c语言·开发语言·c++
图灵猿2 小时前
【Lua之·Lua与C/C++交互·Lua CAPI访问栈操作】
c语言·c++·lua
A懿轩A2 小时前
C/C++ 数据结构与算法【树和二叉树】 树和二叉树,二叉树先中后序遍历详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·二叉树·
hjxxlsx2 小时前
探索 C++ 自定义函数的深度与广度
开发语言·c++
lijiachang0307184 小时前
设计模式(一):单例模式
c++·笔记·学习·程序人生·单例模式·设计模式·大学生
<但凡.4 小时前
题海拾贝:蓝桥杯 2020 省AB 乘法表
c++·算法·蓝桥杯