CMake简明教程

本文介绍了Cmake的基本用法,包括创建CmakeList.txt文件,管理同一目录及不同目录下的多个源文件,使用aux_source_directory命令,以及include_directories和add_executable命令。此外,还涉及了工程的组织结构,预定义变量的使用,多库联编以及find_package引入外部依赖包的方法。
摘要由CSDN通过智能技术生成

CmakeList.txt

本文主要参考
Linux下Cmake简明教程
Cmake入门基础

1. 首先体验一波cmake如何操作
  1. 编写main.cc
#include <iostream>
using namespace std;
int main()
{
	cout << "Hello" << endl;
	return 0;
}
  1. 在main.cc的目录下编写CmakeList.txt
cmake_minimum_required(VERSION 2.8)
project(demo)
add_executable(main main.cpp)

在终端下切到main.cc所在的目录下,然后输入以下命令运行cmake

cmake .
2. 同一目录下的多个源文件

此类在工程代码学习过程中经常遇到。即,同一目录下的多个源文件。
举例说明,现目录如下:
├── CMakeLists.txt
├── main.cc
├── Test.h
├── Test.cc

/*Test.cc*/
#include <iostream>
#include "Test.h"
void func(int abc)
{
	std::cout << abc << std::endl;
}
/*Test.h*/
#ifndef _TEST_H_
#define _TEST_H_
void func(int abc);

#endif
/*main.cc*/
#include <iostream>
#include "Test.h"
int main(void)
{
	func(10);
	return 0;
}

此目录CmakeList.txt如下所示

cmake_minimum_required (VERSION 2.8)
project (demo)

add_executable(main main.cc Test.cc)

可以类推,在同一目录下有多个源文件,只要add_executable里把所有的源文件添加进去就可以了。但是如果这个源文件很多很多,这样做不合适,cmake提供了一个命令可以把指定目录下所有的源文件存储在一个变量中,这个命令就是aux_source_directory(dir var)
dir:指定目录 var:存放源文件列表的变量

cmake_minimum_required (VERSION 2.8)

project (demo)

aux_source_directory(. SRC_LIST)

add_executable(main ${SRC_LIST})

使用aux_source_directory把当前目录下的源文件存列表存放到变量SRC_LIST里,然后在add_executable里调用SRC_LIST(注意调用变量时的写法)

aux_source_directory()也存在弊端,它会把指定目录下的所有源文件都加进来,可能会加入一些我们不需要的文件,此时我们可以使用set命令去新建变量来存放需要的源文件。

cmake_minimum_required (VERSION 2.8)
project (demo)
set(SRC_LIST
	./main.cc
	./Test.cc)
add_executable(main ${SRC_LIST})
3. 不同目录下的多个源文件

工程中,一般程序文件比较多时,需要分类管理,把代码根据功能放在不同的目录里方便查找。

├── CMakeLists.txt
├── main.cc
├── Test1
    └── Test.cc
    └── Test.h
├── Test2
    └── Test2.cc
    └── Test2.h	

其中,CMakeLists.txt和main.c在同一目录下

cmake_minimum_required (VERSION 2.8)
project (demo)
include_directories (Test1 Test2)
aux_source_directory (Test1 SRC_LIST)
aux_source_directory (Test2 SRC_LIST1)

add_executable (main main.cc ${SRC_LIST} ${SRC_LIST1})

include_directories:该命令是用来向工程添加多个指定头文件的搜索路径,路径之间用空格分隔。
因为main.cc里include了Test.h和Test2.h,如果没有这个命令来指定头文件所在位置,就会无法编译。当然,也可以在main.cc里使用include来指定路径,如下:

#include "Test1/Test.h"
#include "Test2/Test2.h"
4. 组织结构

一般会把源文件放到src目录下,把头文件放入到include文件下,生成的对象文件放入到build目录下,最终输出的elf文件会放到bin目录下,这样整个结构更加清晰。

├── bin
├── build
├── include
    └── Test.h
    └── Test2.h
├── src
    └── main.cc
    └── Test.cc
    └── Test2.cc
    └── CMakeLists.txt
├── CMakeLists.txt

最外层CMakeLists.txt,内容如下,

cmake_minimum_required (VERSION 2.8)
project (demo)
add_subdirectory (src)

出现一个新的命令add_subdirectory(),这个命令可以向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置,具体用法可以百度。

这里指定src目录下存放了源文件,当执行cmake时,就会进入src目录下去找src目录下的CMakeLists.txt,所以在src目录下也建立一个CMakeLists.txt,内容如下,

aux_source_directory (. SRC_LIST)
include_directories (../include)
add_executable (main ${SRC_LIST})
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

这里又出现一个新的命令set,是用于定义变量的,EXECUTABLE_OUT_PATH和PROJECT_SOURCE_DIR是CMake自带的预定义变量,其意义如下,

  • EXECUTABLE_OUTPUT_PATH :目标二进制可执行文件的存放位置
  • PROJECT_SOURCE_DIR:工程的根目录

这里set的意思是把存放elf文件的位置设置为工程根目录下的bin目录。

最外面的CMakeLists.txt用于掌控全局,使用add_subdirectory来控制其它目录下的CMakeLists.txt的运行。

cmake_minimum_required (VERSION 2.8)
project (demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

aux_source_directory (src SRC_LIST)
include_directories (include)
add_executable (main ${SRC_LIST})

同时,还要把src目录下的CMakeLists.txt删除。

4.1 标准框架工程实例

在这里插入图片描述
CMakeList.txt

cmake_minimum_required (VERSION 2.8)
project (demo)
include_directories (include) #指定头文件所在目录
aux_source_directory (Func1 SRC_LIST1) 
aux_source_directory (Func2 SRC_LIST2) 
add_executable (main src/main.cpp ${SRC_LIST1} ${SRC_LIST2})

这里主要是将头文件放在include,源文件放在src。

5. 重新生成make clean
#在build文件夹下
make clean #清除生成的可执行文件
make -j6
6. Cmake自带的预定义变量

这些预定义变量可以在CMakeList.txt里可以直接使用,加上变量名取出值就可以直接使用${}

预定义变量名称作用
PROJECT_NAME通过 project() 指定项目名称
PROJECT_SOURCE_DIR工程的根目录
PROJECT_BINARY_DIR执行 cmake 命令的目录
CMAKE_CURRENT_SOURCE_DIR当前 CMakeList.txt 文件所在的目录
CMAKE_CURRENT_BINARY_DIR编译目录,可使用 add subdirectory 来修改
EXECUTABLE_OUTPUT_PATH二进制可执行文件输出位置
LIBRARY_OUTPUT_PATH库文件输出位置
BUILD_SHARED_LIBS默认的库编译方式 ( shared 或 static ) ,默认为 static
CMAKE_C_FLAGS设置 C 编译选项
CMAKE_CXX_FLAGS设置 C++ 编译选项
CMAKE_CXX_FLAGS_DEBUG设置编译类型 Debug 时的编译选项
CMAKE_CXX_FLAGS_RELEASE设置编译类型 Release 时的编译选项
CMAKE_GENERATOR设置编译类型 Release 时的编译选项
CMAKE_COMMANDCMake 可执行文件本身的全路径
CMAKE_BUILD_TYPE工程编译生成的版本, Debug / Release
7. add_subdirectory 多库联编

在构建大型工程时,涉及到多个库联编。

之前是只有demo这一个project,有时候会写一些通用库便于移植/单独测试/任务分解,然后多个库联编,就是会有多个cmakelist.txt,而且这些库/project之间可能互相依赖。
在这里插入图片描述
假设project(demo)依赖Func3这个project,demo目录结构如上图所示。

cmake_minimum_required (VERSION 2.8)
project (demo)
include_directories (include)
aux_source_directory (Func1 SRC_LIST1) 
aux_source_directory (Func2 SRC_LIST2) 
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Func3) #增加依赖库的根目录
add_executable (main src/main.cpp ${SRC_LIST1} ${SRC_LIST2})
target_link_libraries(${PROJECT_NAME} Func3) #指定demo需要依赖Func3这个库
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 

通过add_subdirectory,target_link_libraries配合使用可以实现多库联编。
被依赖的Func3,可以独立于demo这个project运行,也可以单独编译。

8. 路径下遍历全局表达式匹配 file
#作用就是将src路径下的所有.cc文件,打包取个别名叫做变量SRC_FILES
#GLOB :产生一张与全局表达式匹配的所有文件的表 并存入指定变量SRC_FILES中
file(GLOB SRC_FILES src/*.cc)
#取出变量SRC_FILES的值,也就是打包在一起的所有.cc文件
#将这些打包在一起的.cc文件生成STATIC静态库,静态库的名称就是工程名
add_library(${PROJECT_NAME} STATIC ${SRC_FILES})

上面的*.cc也可以换成*.txt,*.proto
GLOB_RECURSE :与 GLOB 类似, 但会遍历匹配路径下面的所有子路径并匹配文件

file(GLOB_RECURSE SRC_FILES src/*.cc)
9. find_package 引入外部依赖包

环境变量的名字遵循packagename_property,即包名-属性。

假设此时我们需要引入google glog库来进行日志的记录,我们需要自行安装glog库,再进行引用。
PACKAGENAME_FOUND:当库被查找到时置为true,否则为false
PACKAGENAME_INCLUDE_DIRS或PACKAGENAME_INCLUDES:软件包导出的头文件路径PACKAGENAME_LIBRARIES或_LIBS:软件包导出的库的路径
CMakeList.txt写法

find_package(GLOG)
add_executable(glogtest glogtest.cc)
if(GLOG_FOUND)
    message(STATUS ”GLOG library found”)
else()
    message(FATAL_ERROR ”GLOG library not found”)
endif()
#找到glog库后就可以链接了
target_link_libraries(${PROJECT_NAME} glog)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值