一.了解CMake
学习CMake之前,你一定得了解makrfile相关内容及其意义,CMake和makefile都是用于构建软件项目的工具,但它们的设计原则有很大的区别。
makefile是一种比较老的构建工具,它是基于规则的依赖关系来完成编译的。makefile将整个构建过程分为多个步骤,并且使用文件时间戳来判断是否需要重新构建目标。makefile通常需要手动编写,而且需要对底层系统的细节有一定的了解。
相比之下,CMake是一个跨平台的高级构建工具,它可以自动生成makefile或其他构建工具所需要的文件。CMake提供了一个简单的语言来描述项目的结构和依赖关系,并可根据不同平台和编译器生成相应的构建文件。CMake还支持交叉编译,可以方便地在不同的操作系统和架构上构建相同的项目。
总的来说,CMake比makefile更加高级和灵活,可以更轻松地管理复杂的项目和跨平台编译。
谈一谈我个人的理解,原本是C语言链接其他库碰到的,尤其是使用CLion编译器,其他编译器链接体积小的库还好,但是如果链接的第三方库比较大,特别容易出现卡死的情况,还是CLion比较好,但是使用这个软件你会发现它的每个项目都有一个 CMakeLists.txt文件,链接库的话需要编写这个文件,如果不知道它,链接库操作总是不顺畅。
二.CMake基础命令
1.cmake_minimum_required
在使用CMake编写项目时,必须在CMakeLists.txt文件的开头指定要求的最低版本号。这通常通过使用cmake_minimum_required命令来完成。该命令告诉CMake要求的最低版本号是多少,如果运行CMake的机器上安装的CMake版本低于指定的最低版本,则会产生错误。
因此,在CMake项目中,cmake_minimum_required(VERSION 3.10)这样的命令通常是必填的。当然,你也可以根据你的实际情况来设置更高的最小版本号。
2.project
在 CMake 中,project 命令用于定义项目名称及其基本信息。一般而言,CMakeLists.txt 文件的第一个非注释行就是 project 命令。
project 命令的基本语法如下:
project(projectname [VERSION version] [DESCRIPTION description] [HOMEPAGE_URL url] [LANGUAGES language1 [language2 ...]])
projectname:必填,表示项目名称。
VERSION:可选,表示项目的版本号。
DESCRIPTION:可选,描述项目的简短说明。
HOMEPAGE_URL:可选,表示项目主页的 URL 地址。
LANGUAGES:可选,表示项目所使用的编程语言,默认情况下为 C 和 C++。
project 命令通常会将以下变量设置为对应的值:
PROJECT_NAME:项目名称。
PROJECT_VERSION:项目版本号。
PROJECT_DESCRIPTION:项目描述。
PROJECT_HOMEPAGE_URL:项目主页的 URL 地址。
PROJECT_LANGUAGES:项目所使用的编程语言。
通过执行 project 命令,我们可以在 CMake 中定义项目名称及其基本信息,从而方便管理和构建整个项目。
3.add_executable
add_executable 的语法如下:
add_executable(target_name source1 [source2 ...])
其中,target_name 为创建的目标的名称,source1, source2, … 是源文件的列表,可以包括多个源文件。每一个源文件都应该是一个相对或绝对路径。
在 CMakeLists.txt 文件中,通常会把 add_executable 命令放在其他命令的前面,以便在生成项目时先创建可执行文件的目标。
注意:这里的target不一定非要和项目名一样,毕竟一个项目包含多个可执行文件,但是后面必须写依赖的文件。
4.message
message()
函数用于输出一条消息到CMake的生成日志中,可用于调试或显示某些信息。它的语法如下:
message([<mode>] "message to display")
其中是一个可选参数,指定输出的消息类型,可以是以下之一:
STATUS:输出为绿色。
WARNING:输出为黄色。
AUTHOR_WARNING:输出为红色。
SEND_ERROR:输出为红色,并停止 CMake 过程。
FATAL_ERROR:输出为红色,并且停止 CMake 过程并返回错误代码。
DEPRECATION:输出为带有前缀“–”,并在尝试使用过时功能时输出。
示例:
# 输出普通(默认)消息 message("This is a normal message") # 输出警告消息 message(WARNING "This is a warning message") # 输出错误消息 message(SEND_ERROR "This is an error message") # 输出致命错误消息 message(FATAL_ERROR "This is a fatal error message")
三.CMake补充命令
1.option
在CMake中,option命令用于定义一个可选的开关变量,这个变量可以通过命令行或者CMake GUI进行设置。语法如下:
option(<option_variable> "help string describing option" [initial value])
其中,是变量名,"help string describing option"是对该选项的描述文本,[initial value]是该选项的初始值(默认值为OFF)。
例如,我们可以定义一个名为 EXAMPLE_OPTION 的选项:
option(EXAMPLE_OPTION "Enable example feature" OFF)
这将定义一个名为 EXAMPLE_OPTION 的选项,它的默认值为 OFF,同时还提供了一个描述文本 "Enable example feature"。
在使用时,可以通过 if 命令根据该选项的值来控制代码的编译。
if(EXAMPLE_OPTION) add_compile_definitions(ENABLE_EXAMPLE_FEATURE) endif()
这里我们使用了 add_compile_definitions 命令来添加编译选项 -DENABLE_EXAMPLE_FEATURE,如果 EXAMPLE_OPTION 的值为 ON,则这个选项就会被启用。
2.set
set()函数用于设置变量的值。它的语法如下:
set(<variable> <value> [CACHE <type> <docstring> [FORCE]])
其中,是要设置的变量名,是要设置的变量值。如果要将变量写入缓存,请使用CACHE选项。指定缓存值的类型,是对该缓存变量的描述。如果要覆盖现有的缓存变量,请使用FORCE选项。
示例:
# 设置一个普通变量 set(my_var "Hello World") # 设置一个缓存变量 set(my_cache_var "Hello Cache" CACHE STRING "Description of my_cache_var")
3.include_directories
include_directories是CMake的一个命令,用于向编译器添加头文件搜索路径。
例如,如果你的项目在/path/to/project目录下,并且你需要使用foo.h和bar.h这两个头文件,那么你需要将它们的搜索路径添加到 CMakeLists.txt 文件中:
include_directories(/path/to/project/include)
这样,CMake就会将 /path/to/project/include 添加到编译器的搜索路径中,使得在源代码中包含foo.h和bar.h时能够正确地找到它们。
你也可以指定多个搜索路径:
include_directories( /path/to/project/include /path/to/other/include )
当然,你也可以使用相对路径。例如,在以下示例中,假定你的头文件位于./include目录下:
include_directories(include)
需要注意的是,include_directories只影响当前目录及其子目录中的源文件。如果你需要在更高级别的目录中使用头文件,请考虑使用target_include_directories命令,该命令可将头文件搜索路径添加到特定的目标或库中。
4.target_include_directories
target_include_directories命令的详细使用方法如下:
target_include_directories(target [SYSTEM | BEFORE] [INTERFACE | PUBLIC | PRIVATE] <directory> [<directory> ...] )
参数说明:
target:要添加头文件搜索路径的目标或库名称。
SYSTEM:将指定的目录作为系统路径添加,这通常用于包含操作系统提供的头文件。
BEFORE:将指定的目录添加到其他搜索路径之前。
INTERFACE、PUBLIC、PRIVATE:控制头文件搜索路径的可见性。如果使用多个关键字,则它们之间应该按照INTERFACE、PUBLIC、PRIVATE的顺序排列。
<directory>:要添加的头文件搜索目录。
举例来说,如果你要向名为mymath的库添加一个头文件搜索路径,可以使用以下命令:
target_include_directories(mymath PUBLIC include)
这将把include目录添加到mymath库的公共接口中,使得其他依赖于mymath的目标也能够访问这个头文件目录。
四.库的链接
1.add_library
add_library命令是CMake中用于创建静态库或共享库的命令。它的基本语法如下:
Copy Codeadd_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...])
其中,参数说明如下:
<name>:要创建的库的名称。
STATIC、SHARED、MODULE:指定库的类型,分别表示静态库、共享库和模块库,默认是静态库。
EXCLUDE_FROM_ALL:如果添加了这个参数,那么这个库将不会被默认构建,需要显式地使用make <target>命令来构建它。
source1、source2等:库的源文件列表。
举例来说,如果你有两个源文件foo.cpp和bar.cpp,并希望创建一个名为mylib的静态库,可以使用以下命令:
add_library(mylib STATIC foo.cpp bar.cpp)
这将创建一个名为libmylib.a(在Linux和Mac上)或mylib.lib(在Windows上)的静态库文件,包含foo.cpp和bar.cpp中定义的函数和变量。
如果你希望创建一个共享库而不是静态库,可以使用以下命令:
add_library(mylib SHARED foo.cpp bar.cpp)
这将创建一个名为libmylib.so(在Linux和Mac上)或mylib.dll(在Windows上)的共享库文件。
如果你希望创建一个模块库,可以使用以下命令:
add_library(mylib MODULE foo.cpp bar.cpp)
这将创建一个名为mylib.so(在Linux和Mac上)或mylib.dll(在Windows上)的模块库文件。
最后,如果你希望将库文件从生成的默认构建目标中排除,可以添加EXCLUDE_FROM_ALL参数,例如:
add_library(mylib STATIC EXCLUDE_FROM_ALL foo.cpp bar.cpp)
这将使得mylib库不会被默认构建,需要显式地使用make mylib命令来构建它。
2.target_link_libraries()
target_link_libraries() 是 CMake 中用于链接库的命令。该命令的语法如下:
target_link_libraries(target library1 <library2> ... <libraryN>)
其中,target 表示要链接库的目标(例如可执行文件或库文件);library1、library2、……、libraryN 表示要链接到目标中的库文件的名称。
使用 target_link_libraries 命令可以将库文件链接到目标文件中,以便在运行时能够调用其中定义的函数和数据结构。例如,在创建一个可执行文件时,如果需要使用某个库文件,则可以使用 target_link_libraries 命令将该库文件链接到可执行文件中,使得程序能够编译并运行。
此外,还可以通过 target_link_libraries 添加链接选项和链接器标志。例如,将 -lm 选项添加到链接操作中,可以告诉链接器链接数学库文件。
总之,target_link_libraries 命令是 CMake 中非常重要的一个命令,它可以方便地管理多个源文件和依赖项之间的关系,简化了项目的构建过程。
五.实例操作
1.链接sds
cmake_minimum_required(VERSION 3.25) project(untitled C) set(CMAKE_C_STANDARD 11) add_executable(untitled main.c) add_library(sds sds.c sds.h) target_link_libraries(untitled sds)
2.链接sqlite
cmake_minimum_required(VERSION 3.25) project(db_work C) set(CMAKE_C_STANDARD 11) add_compile_options(-l sqlite3) add_executable(db_work main.c sqlite3.c)
注释:
这是一个使用C语言编写的项目的CMakeLists.txt文件,用于构建生成可执行文件。
cmake_minimum_required(VERSION 3.25): 指定最低的 CMake 版本号。
project(db_work C): 定义项目名称为db_work,并指定使用C语言进行编译。
set(CMAKE_C_STANDARD 11): 设置C标准为C11。
add_compile_options(-l sqlite3): 添加编译选项,链接SQLite 3动态库。
add_executable(db_work main.c sqlite3.c): 添加要编译的源代码文件,包括主程序main.c和SQLite 3的C文件sqlite3.c,并生成可执行文件db_work。
六.总结
本篇博客,虽然知识点比较偏,但是非常有用。