Makefile CMake
Linux项目自动化构建工具-make/Makefile
Makefile由来
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make
是一个命令工具,是一个解释makefile中指令的命令工具。两个搭配使用,完成项目自动化构建。
使用
在默认的方式下,我们只需要当前目录下输入make
命令。 make会在当前目录下找名字 为makefile
或makefile
的文件:
1 |
|
可以使用$@
$^
来分别表示:
的左右。
生成多个可执行文件
1 |
|
用伪目标all
来搭建依赖链。
项目清理
像上述中的clean,它没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以通过make
执行。即命令——make clean
,以此来清除所有的目标文件,以便于重新编译。
伪目标
- 总是被执行。
- 定义一些常用命令或管理任务,例如清理构建文件、生成文档、运行测试等。这些命令不会生成对应名字的文件,只是执行一些动作。
指定库和头文件,并且添加变量
1 |
|
CFLAGS
:指定了编译器的标志选项。其中,-std=c++11
是设置使用 C++11 标准,-I../../build/release-install-cpp11/include
是添加头文件搜索路径。LDFLAGS
:指定了链接器的标志选项。其中,-L../../build/release-install-cpp11/lib
是设置库文件的搜索路径,-lmuduo_base
和-lmuduo_net
是需要链接的库。
目标规则
server: server.cpp
:定义了目标server
,它依赖于server.cpp
文件。这意味着当server.cpp
发生变化时,server
目标需要重新构建。g++ $(CFLAGS) -o $@ $^ $(LDFLAGS)
:这是构建server
目标的命令。$(CFLAGS)
插入了编译标志。-o $@
指定了输出文件名,$@
表示目标文件,即server
。$^
表示所有的依赖文件,在这里是server.cpp
。$(LDFLAGS)
插入了链接标志。
原理:
- 在上述例子中,Makefile文件会
自顶向下
扫描。 - 如果
当前文件
的依赖文件
文件不存在,那么make会在当前文件中找目标为依赖文件
的文件。如果找不到则再根据依赖方法来生成,直到自顶向下
的依赖链结束。
如果依赖文件比目标文件新,则目标需要重新生成。——make的依赖性:会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
CMake
CMake
是一个跨平台的构建系统生成器,广泛用于管理 C/C++ 项目的构建过程。可以生成Makefile
。
1. 安装 CMake
在大多数操作系统中,CMake 可以通过包管理器安装。
- Ubuntu:
1
sudo apt-get install cmake
2. 创建 CMakeLists.txt
在你的项目根目录中创建一个 CMakeLists.txt
文件,这个文件包含构建项目所需的配置信息。
基本结构
1 |
|
添加多个源文件
1 |
|
添加库
1 |
|
包含目录
1 |
|
3. 生成构建系统
1 |
|
4. 常用指令和变量
设置变量:
1
set(VAR_NAME value)
选项开关:
1
option(USE_FEATURE "Use special feature" ON)
检查库/文件/函数的存在:
1
2
3find_package(OpenCV REQUIRED)
find_library(MY_LIB mylib)
find_file(MY_HEADER myheader.h)条件语句:
1
2
3if(USE_FEATURE)
add_definitions(-DENABLE_FEATURE)
endif()
5. 添加第三方库
如果需要使用第三方库,可以使用 find_package
或手动指定库的路径:
1 |
|
6. CMake 编译类型
通过 CMAKE_BUILD_TYPE
设置编译类型:
1 |
|
常用的编译类型有:
Debug
: 包含调试信息Release
: 优化代码RelWithDebInfo
: 优化代码并包含调试信息
7. 其他功能
安装目标:
1
install(TARGETS MyExecutable DESTINATION bin)
测试:
1
2enable_testing()
add_test(NAME MyTest COMMAND MyExecutable)
8. 使用外部项目
如果你需要从外部下载并构建一个项目,可以使用 ExternalProject
模块:
1 |
|