1、嵌套的CMake

如果项目很大或者项目中有很多的源码目录,在通过CMake管理项目的时候如果只使用一个CMakeLists.txt,那么这个文件会相对比较复杂,有一种化繁为简的方式就是给每个源代码目录都添加一个CMakeLists.txt文件(头文件不需要),这样每个文件都不会太复杂,而且更灵活,更容易维护。

.
├── calc
│   ├── add.cpp
│   ├── CMakeLists.txt
│   ├── dived.cpp
│   ├── mul.cpp
│   └── sub.cpp
├── inc
│   ├── calc.h
│   └── sort.h
├── sort
│   ├── CMakeLists.txt
│   ├── insert.cpp
│   └── select.cpp
├── test1
│   ├── calc.cpp
│   └── CMakeLists.txt
└── test2
│   ├── CMakeLists.txt
│   └── sort.cpp
├── CMakeLists.txt
  • calc目录:目录中的四个源文件对应加、减、乘、除算法
    • 对应的头文件是inc中的calc.h
  • inc目录:所有头文件存放目录
  • sort目录:目录中的两个源文件分别是插入和选择排序算法
    • 对应的头文件inc中的sort.h
  • test1目录:测试目录,对加减乘除算法进行测试
  • test2目录:测试目录,对排序算法进行测试

可以看到各个源文件目录所需要的CMakeLists.txt文件现在已经添加完毕了。接下来可以依次分析一下各个文件中需要添加的内容

2、具体流程
2.1、节点关系

Linux中的目录是一个梳妆结构,所以嵌套的CMake也是一个梳妆结构,最顶层的CMakeLists.txt是根节点,其次都是子节点。对于父子CMakeLists.txt文件变量作用域存在一些关系

  • 根节点CMakeLists.txt中的变量全局有效
  • 根节点CMakeLists.txt中的变量可以在子节点中使用
  • 子节点CMakeLists.txt中的变量只能在当前节点中使用

对于多级子目录的项目需要再根节点CMakeLists.txt中使用CMake的命令

# 添加子节点目录
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
  • source_dir:指定了CMakeLists.txt源代码和代码文件的位置,其实就是指定子目录
  • binary_dir:指定了输出文件的路径,一般不需要指定,忽略即可。
  • EXCLUDE_FROM_ALL:在子路径下的目录默认不会被包含到父路径ALL目标里,并且也会被排除在IDE工程文件之外。用户必须显示构建在子路径下的目标
2.2、具体实现
2.2.1、根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.10.2)
set(CMAKE_CXX_STANDARD 14)

# 主项目名称
project(main_project)
# 静态库生成的路径
set(LIBPATH ${PROJECT_SOURCE_DIR}/lib)
# 可执行程序的存储目录
set(EXECPATH ${PROJECT_SOURCE_DIR}/bin)
# 头文件目录
set(HEADPATH ${PROJECT_SOURCE_DIR}/inc)

# 库文件的名字
set(CALCLIB calc)
set(SORTLIB sort)

# 可执行程序的名字
set(EXECNAME1 main1)
set(EXECNAME2 main2)

# 添加子节点目录
# add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
add_subdirectory(calc)
add_subdirectory(sort)
add_subdirectory(test1)
add_subdirectory(test2)
  • 根节点下的CMakeLists.txt文件中定义了一系列的可能用到的全局变量的值
  • 添加子节点目录进行引用
2.2.2、calc目录CMakeLists.txt

calc目录下的源代码打包生成一个静态库文件,并且存放到指定的目录下

cmake_minimum_required(VERSION 3.10.2)
project(calc)

# 搜索源文件
aux_source_directory(./ src_list)
# 添加头文件
include_directories(${HEADPATH})
# 设置库文件存储的位置
set(LIBRARY_OUTPUT_PATH ${LIBPATH})
# 制作静态库文件
add_library(${CALCLIB} STATIC ${src_list})
  • aux_source_directory:搜索当前目录下的所有.cpp源代码
  • include_directories:指定头文件,具体的值从父节点的全局变量中获取
  • set(LIBRARY_OUTPUT_PATH ${LIBPATH}):指定静态库存储的位置
  • add_library(${CALCLIB} STATIC ${src_list}):制作一个静态库,并且指定名称和源文件列表
2.2.3、sort目录CMakeLists.txt

sort目录下的源代码打包生成一个动态库文件,并且存放到指定的目录下

cmake_minimum_required(VERSION 3.10.2)
project(sort)

# 搜索源文件
file(GLOB src_list ./*.cpp)
# 添加头文件
include_directories(${HEADPATH})
# 设置库文件存储的位置
set(LIBRARY_OUTPUT_PATH ${LIBPATH})
# 制作动态库文件
add_library(${SORTLIB} SHARED ${src_list})
2.2.4、test1目录CMakeLists.txt

用于生成测试静态库calc的可执行程序

cmake_minimum_required(VERSION 3.10.2)
project(test1)

# 搜索源代码
file(GLOB main ./*.cpp)
# 指定头文件
include_directories(${HEADPATH})
# 链接静态库
link_libraries(${CALCLIB})
# 指定静态库的路径
link_directories(${LIBPATH})

# 指定可执行程序存放的位置
set(EXECUTABLE_OUTPUT_PATH ${EXECPATH})

# 生成可执行程序
add_executable(${EXECNAME1} ${main})
  • include_directories(${HEADPATH}):指定头文件的目录,对应Makefile中的-I(大写i)
  • link_libraries(${CALCLIB}):指定需要链接静态库的名称,对应Makefile中的-l(小写L)
  • link_directories(${LIBPATH}):指定需要链接静态库的路径,对应Makefile中的-L(大写L)
2.2.5、test2目录CMakeLists.txt

用于生成测试动态库sort的可执行程序

cmake_minimum_required(VERSION 3.10.2)
project(test2)

# 搜索源文件
aux_source_directory(./ main)
# 设置可执行程序输出位置
set(EXECUTABLE_OUTPUT_PATH ${EXECPATH})

# 包含头文件
include_directories(${HEADPATH})
# 生成可执行程序
add_executable(${EXECNAME2} ${main})

# 链接动态库
link_directories(${LIBPATH})
target_link_libraries(${EXECNAME2} ${SORTLIB})
  • include_directories(${HEADPATH}):指定头文件的目录,对应Makefile中的-I(大写i)
  • link_directories(${LIBPATH}):指定需要链接动态库的路径,对应Makefile中的-L(大写L)
  • target_link_libraries(${EXECNAME2} ${SORTLIB}):可执行程序链接动态库libsort.so

在这里插入图片描述

Logo

2万人民币佣金等你来拿,中德社区发起者X.Lab,联合德国优秀企业对接开发项目,领取项目得佣金!!!

更多推荐