原文地址:thatonegamedev.com/cpp/cmake-t…
原文作者:thatonegamedev.com/
发布时间:2021年01月08日
当使用任何一种编程语言时,你通常可以选择创建某种可执行文件或库。可执行文件是最终产品--你运行的东西,然后它执行逻辑并返回一个结果--创建一个窗口,运行一个游戏,输出计算,显示东西,等等。库是可重复使用的编译代码,可以编译到其他应用程序中。
在你开始之前
本文要求你有一定的基础知识。
- 如何编写C/C++应用程序。你可以从我的C++入门文章开始学习。
- 关于如何使用CMake的基本知识。我在这个网站上有一个很好的关于如何用CMake管理项目的教程。
程式库
对于你的C/C++项目来说,主要有两种类型的目标。让我们从库开始,因为它是可执行文件的构建模块。库包含了你写的代码,你想在多个项目之间共享。在互联网上,你可以找到许多由其他人维护的项目库。使用库可以为你节省大量的时间和精力来学习如何制作某些东西。
你也可以自己编写库。在C/C++中,用库写代码还有其他好处。
其中一个好处是可以测试你的代码。在一个单独的库上配置单元/集成测试比在一个可执行文件上配置单元/集成测试要容易得多。
另一个主要的好处是,你可以将你的代码分割成有意义的块。以后如果你在另一个项目中工作,你可以把这些块分开,然后把你需要的和可重用的分开。
静态与动态
在创建一个库时,你有两个选择--使其成为静态或动态。我知道动态链接的选择只有在Windows上才有,但这对每个人来说都是有用的。
静态库产生一个单一的文件,你可以在以后将其链接到可执行文件中(阅读更多关于编译和链接的内容)。静态链接意味着lib文件的内容将被编译到最终的可执行文件中。这在构建可执行文件的过程中需要更多的时间,并且产生一个更大的可执行文件,但从长远来看,应用程序将运行得更快。
动态库会产生两个文件--一个是空心的、只有引用的静态库,另一个是应该沿着可执行文件复制的动态库。静态库将在链接过程中使用,并将产生一个较小的可执行文件,并将有一个更快的构建时间。动态库将在运行时被评估,并且需要沿着可执行文件(通常在同一个文件夹中)。
通常这些库的扩展名会是。( .lib, .bc, .a)代表静态库,( .dll)代表动态库。
对于游戏开发,我的建议是在调试过程中使用动态链接(调试构建),因为你会想要更快的构建时间,而在创建发布构建时使用静态链接。
如何在CMake中创建一个库目标
其实真的很简单。让我们从我常用的库的项目strcuture开始。
libfolder
├── include/
│ └── A.h
├── src/
│ └── A.cpp
└── CMakeLists.txt
你会发现头文件和源文件是分开的。这是为了方便以后复制头文件目录,因为要使用一个库,你通常需要在另一个项目中指定相同的函数签名。最好将函数的定义写在include文件中,并且在另一个项目中可以很容易地使用它们。
project(libfolder LANGUAGES C CXX)
# Creating a static library
# libfolder_static is called a target name and can be used later
add_library(libfolder_static STATIC include/A.h src/A.cpp)
# Creating a dynamic lybrary
# add_library(libfolder_dynamic SHARED include/A.h src/A.cpp)
# This will set include directories for this target
# This means that A.cpp can include A.h by writing
# #include "A.h"
# instead of using relative path like
# #include "../include/A.h"
#
# Also because we set that to public any other target that links to
# libfolder_static would also have those includes
target_include_directories(libfolder_static
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
创建库很简单吧?你也可以针对其他创建的库进行链接。如果其他库是你的整个CMake项目结构的一部分,你可以使用目标名称进行链接(例如,如果你想创建一个名为libfolder2的新库,你可以将libfolder_static链接到其中。另一种方法是直接链接libfolder.lib文件。
project(libfolder2 LANGUAGES C CXX)
add_library(libfolder2_static STATIC include/B.h src/B.cpp)
# Linking against our first target
target_link_libraries(libfolder2_static PUBLIC libfolder_static )
# Or
# target_link_libraries(libfolder2_static PUBLIC libfolder_static.lib)
# if we consider that the lib file is in the current directory.
# You would still need the include files also...
可执行文件
可执行目标的作用仅仅是创建一个可以被操作系统运行的文件,并执行一组命令然后完成。它们要求有一个可以运行的主函数,否则构建会失败。你可以把库链接到可执行文件中,就像把库链接到其他库一样。
如何在CMake中创建一个可执行文件目标
可执行文件比库更容易创建。你不需要考虑你的代码会被其他目标使用,所以你可以自由地将你的代码只放在一个源目录中(或者为了保持一致性,保持与include目录的结构)。创建一个可执行文件的代码和创建一个库的代码几乎是一样的。
project(exefolder LANGUAGES C CXX)
add_executable(exefolder src/C.cpp src/C.h)
# The libfolder include directories would automatically be included here also
target_link_libraries(exefolder PRIVATE libfolder)
target_include_directories(exefolder PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
空/自定义目标
CMake也提供了创建其他类型的空目标的选项。它们不会在最后提供一个可执行的库文件,但是它们可以用来运行命令行脚本。它们被称为自定义目标,通常可以直接在其中运行命令。它们也可以被设置为依赖于其他目标。
add_custom_target(mytarget ALL
COMMENT "Just something to print out when this is run"
COMMAND <... command line to be run ...>
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_dependencies(mytarget exefolder)
其实要运行命令,你也可以直接使用add_custom_command,必须附加到一个现有的目标上。你也可以这样做来为你的自定义目标添加命令。
结束语
这篇文章涵盖了CMake中项目管理的核心概念之一。有了这些知识,你现在可以正确地使用更现代的方法创建自己的项目。
通过www.DeepL.com/Translator(免费版)翻译