二、一个目录下有多个源文件
2.1 基础的实例
2.1.1 项目结构和实例
main.c编写
#include <stdio.h> #include "testFunc.h" int main(void) { func(100); return 0; }
testFunc.h编写
void func(int data);
testFunc.c编写
#include <stdio.h> #include "testFunc.h" void func(int data) { printf("data is %d\n", data); }
CMakeLists.txt编写(不加打印信息了)
cmake_minimum_required (VERSION 2.8) project (zxm) add_executable(hello main.c testFunc.c)
2.1.2 编译运行
进入build,运行查看
cd build/ cmake .. make ./hello
2.2 进阶优化
如果源文件很多呢,几十个,一个个加入到add_executable就很麻烦。这时候可以使用aux_source_directory,用于自动将指定目录下的源文件列表添加到变量中。
并且,这么多源文件,最好放到单独的文件夹里面。
2.2.1 项目结构和实例
创建子目录src,存放源文件。在2.1例子的基础上,增加testFun1.c,testFun1.h文件,修改main.c文件。
testFun1.c编写
#include <stdio.h> #include "testFunc1.h" void func1(int data) { printf("data is %d\n", data); }
testFun1.h编写
void func1(int data);
main.c编写
#include <stdio.h> #include "testFunc.h" #include "testFunc1.h" int main(void) { func(100); func1(200); return 0; }
src目录下的CMakeLists.txt编写
cmake_minimum_required (VERSION 2.8) project (zxm) # 把当前目录下的源文件添加到变量SRC_LIST中 aux_source_directory(. SRC_LIST) add_executable(hello ${SRC_LIST})
主目录下的CMakeLists.txt编写
cmake_minimum_required (VERSION 2.8) project (zxm) add_subdirectory(src bin)
2.2.2 编译运行
cd build/ cmake .. make cd bin/ ./hello
2.2.3 aux_source_directory
用于自动查找指定目录 dir 下的所有源文件,并将它们的完整路径(包括文件名)存储在变量 variable 中。
aux_source_directory(dir variable)
其中:
- dir 是要进行源文件搜索的目录路径。
- variable 是用于存储找到的源文件列表的变量名。
例如
假设有一个名为 src 的目录,其中包含以下源文件:main.cpp、helper.cpp 和 utils.cpp。你可以使用 aux_source_directory 命令来自动获取这些源文件:
# 搜索 src 目录下的所有源文件,并将它们的完整路径存储在变量 SOURCES 中。 aux_source_directory(src SOURCES)
然后,你可以使用 SOURCES 变量来指定要编译的源文件列表
add_executable(my_app ${SOURCES})
三、多个目录有多个源文件
3.1 基础的实例
3.1.1 项目结构和实例
. ├── build ├── CMakeLists.txt └── src ├── CMakeLists.txt ├── main.c ├── test_func │ ├── testFunc.c │ └── testFunc.h └── test_func1 ├── testFun1.c └── testFunc1.h
把testFunc.c和testFunc.h放在test_func目录下,把testFunc1.c和testFunc1.h放在test_func1目录下。
修改src目录下的CMakeLists.txt为
重点是include_directories,向工程添加多个特定的头文件搜索路径;相当于指定g++编译器的-I参数值。
cmake_minimum_required (VERSION 2.8) project (zxm) # 向工程添加多个指定头文件的搜索路径 include_directories(test_func test_func1) # 把当前目录下的源文件添加到变量SRC_LIST中 aux_source_directory(test_func SRC_LIST) aux_source_directory(test_func1 SRC_LIST1) add_executable(hello main.c ${SRC_LIST} ${SRC_LIST1})
当然,也可以在main.c里包含具体的头文件路径,这就不需要include_directories
#include "test_func/testFunc.h" #include "test_func1/testFunc1.h"
3.1.2 编译运行
cd build/ cmake .. make cd bin/ ./hello
3.1.3 include_directories
用于向 CMake 构建系统添加一个或多个包含目录,告诉 CMake 在编译源代码时搜索头文件所在的目录。
include_directories(dir1 [dir2 ...])
其中,dir1、dir2 等是要添加的包含目录的路径。
例如,假设你的项目中有一个名为 include 的目录,里面包含了一些头文件。你可以使用 include_directories 命令将该目录添加到项目中:
include_directories(include)
3.2 进阶优化
综合上面介绍的,工程项目中,一般会把源文件放在src目录,头文件放在include目录,cmake生成的对象文件放在build目录,最终输出可执行文件放在build目录下的bin目录
3.2.1 项目结构和实例
.
. ├── build ├── CMakeLists.txt ├── include │ ├── testFunc1.h │ └── testFunc.h └── src ├── CMakeLists.txt ├── main.c ├── testFunc1.c └── testFunc.c
修改src目录下的CMakeLists.txt
cmake_minimum_required (VERSION 2.8) project (zxm) # 向工程添加多个指定头文件的搜索路径 include_directories(../include) # 把当前目录下的源文件添加到变量SRC_LIST中 aux_source_directory(. SRC_LIST) add_executable(hello ${SRC_LIST})
3.2.2 编译运行
cd build/ cmake .. make cd bin/ ./hello
3.3 进阶优化2
3.3.1 项目结构和实例
进一步,如果想修改可执行文件的生成路径,比如在src目录下的bin目录
修改src目录下的CMakeLists.txt
cmake_minimum_required (VERSION 2.8) project (zxm) # 向工程添加多个指定头文件的搜索路径 include_directories(../include) # 把当前目录下的源文件添加到变量SRC_LIST中 aux_source_directory(. SRC_LIST) add_executable(hello ${SRC_LIST}) # EXECUTABLE_OUTPUT_PATH 可执行文件输出的存放路径 # 包PROJECT_SOURCE_DIR 含项目名的最近一个 CMakeLists.txt 文件所在的目录的路径 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
修改主目录下的CMakeLists.txt
cmake_minimum_required (VERSION 2.8) project (zxm) add_subdirectory(src)
3.2.2 编译运行
cd build/ cmake .. make cd ../src/bin/ ./hello
四、生成库(待更新)
在软件开发中,动态库(Dynamic Library)和静态库(Static Library)是两种常见的库文件类型。
1) 动态库:
- 动态库是一种在运行时加载的库文件。它以共享的方式被多个程序使用,可以在不同的应用程序之间共享代码和数据。
- 动态库具有独立编译和链接的优势,因此可以以相对较小的体积提供功能模块。
- 当一个程序调用动态库时,操作系统会在内存中加载该库,并将其映射到运行进程的地址空间。这种共享的方式可以节省系统资源和内存使用,并允许库的更新和升级。
- 动态库的扩展名通常为 .so(在Linux/Unix)或 .dll(在Windows)。
2)静态库:
- 静态库是一种在编译时链接到程序中的库文件。它会将库的代码和数据复制到最终生成的可执行文件中。
- 静态库使得可执行文件完全自包含,不依赖于外部的库文件。这可以提供更好的可移植性和独立性,因为所有需要的代码都包含在一个文件中。
- 静态库通常比动态库更容易部署和分发,因为不需要处理共享库的加载和依赖关系。
- 静态库的扩展名通常为 .a(在Linux/Unix)或 .lib(在Windows)。
在实际开发中,可以根据项目需求和约束来选择使用动态库还是静态库。动态库适合用于提供公共功能的共享库,而静态库则适合用于构建独立、可移植的可执行文件。
DCMAKE_INSTALL_PREFIX
指定 camke install 时的相对路径前缀
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
install
用于指定在安装时运行的规则。它可以用来安装很多内容,可以包括目标二进制、动态库、静态库以及文件、目录、脚本等。
install(TARGETS <target>... [...]) install({FILES | PROGRAMS} <file>... [...]) install(DIRECTORY <dir>... [...]) install(SCRIPT <file> [...]) install(CODE <code> [...]) install(EXPORT <export-name> [...])
目标文件的安装
install(TARGETS targets... [EXPORT <export-name>] [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE| PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE] [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [NAMELINK_COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL] [NAMELINK_ONLY|NAMELINK_SKIP] ] [...] [INCLUDES DESTINATION [<dir> ...]] )
参数中的TARGET可以是很多种目标文件,最常见的是通过ADD_EXECUTABLE或者ADD_LIBRARY定义的目标文件,即可执行二进制、动态库、静态库。
为了符合一般的默认安装路径,如果设置了DESTINATION参数,推荐配置在安装目录变量下的文件夹。
例如:
INSTALL(TARGETS myrun mylib mystaticlib # 可执行二进制myrun安装到${CMAKE_INSTALL_BINDIR}目录 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # 可执行二进制myrun安装到${CMAKE_INSTALL_BINDIR}目录 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # 可执行二进制myrun安装到${CMAKE_INSTALL_BINDIR}目录 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} )
普通文件的安装
install(<FILES|PROGRAMS> files... TYPE <type> | DESTINATION <dir> [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL])
FILES|PROGRAMS若为相对路径给出的文件名,将相对于当前源目录进行解释。其中,FILES为普通的文本文件,PROGRAMS指的是非目标文件的可执行程序(如脚本文件)。
# 将文本文件 myfile.txt 安装到目标路径的 share/myproject 目录下 install(FILES myfile.txt DESTINATION share/myproject)
目录的安装
install(DIRECTORY dirs... TYPE <type> | DESTINATION <dir> [FILE_PERMISSIONS permissions...] [DIRECTORY_PERMISSIONS permissions...] [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [EXCLUDE_FROM_ALL] [FILES_MATCHING] [[PATTERN <pattern> | REGEX <regex>] [EXCLUDE] [PERMISSIONS permissions...]] [...])
该命令将一个或多个目录的内容安装到给定的目的地,目录结构被逐个复制到目标位置。
# 将目录 mydir/ 及其内容安装到目标路径的 include/myproject 目录下 install(DIRECTORY mydir/ DESTINATION include/myproject)