作为一名iOS开发工程师,平时使用的开发工具都是Xcode偏多,以往链接开发文件、第三方库、图片字体资源等等都只需要交给Xcode来处理即可,我只需要做一个简单的创建或导入操作,还有就是借助方便快捷的CocoaPods强大管理库工具十分简单完成。最近打算写一个文本渲染的项目,最终选择的技术方案是C++、OpenGL和FreeType,并且希望是可以跨平台编译和运行的,经过一番咨询和查找,了解CMake作为首选的工具之一,本着大众原则因此选择CMake构建项目。没想到CMake的使用程度难倒我不少时间,经过一番的学习和研究,从未接触过CMake到了解CMake实现基本的项目构建,因此想通过输出的方式,总结所学的知识,那么就开始吧。 项目链接 如果能帮到你,希望你能给我点个赞或评论吧~
开发项目需要借助一个好的工具,因此我的开发环境是
objectivecmacOS 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
如下设置:jsfile(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 submodel
、find_package
等等,这里只总结源码和find_package两种情况
源码
项目创建一个名为deps
的文件主要存放第三方库的源码,因为我是创建OpenGL的相关的项目,需要用到glad
、glm
库,以这两个库为例子。
- glad 源码路径
- 可以通过链接去下载源码
点击构建按钮创建所需版本的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.3
、Freetype
这些名称都是由库自身的官方提供,或者CMake
官方内置提供。
这种方式就比较方便,不需要自己去链接文件和生成库处理,find_package
还可以查找你的系统文件夹或者系统库。如果在CMake
的Module
文件中没有找到需要的库,也可以自行安装(只对支持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 )
总结
经过src
、deps
、resource
三个模块的构建之后就得出一个基础开发的环境,同时根据自己的需求在里面添砖加瓦。
CMake
这个构建项目工具我也是第一次使用,还有很多知识点的缺少,想要深入理解还需要查看CMake
的文档,不过这篇文章我相信足够一般基础的使用,最后希望能帮你吧!
项目链接: 如果能帮到你,希望你能给我点个赞或评论吧~