一句话结论:本文归纳CMake构建c++工程的基本用法,实现多依赖、多工程、多文件格式的工程编译构建。


1.简介

CMake(cross-platform make)是一个跨平台编译工具,它不能直接生成最终可执行程序,而是构建各平台标准的构建文档(如Linux的Makefile、Windows的sln)。
使用时,用户不再需要直接编写底层Makefile文件,而是编写语法简单的CMakeLists.txt文件,CMake在执行目录下查找CMakeLists.txt来生成Makefile、构建工程,大幅降低工程构建和编译的难度。

2.简单工程

- output
- build
- tests- test0- main.cc- CMakeLists.txt
cmake_minimum_required(VERSION 3.10)# set c++11
set(CMAKE_CXX_FLAGS "$GUN_FLAGS -std=c++11")# set output dir
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../output) # based on current CMakeLists.txt
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../output) # .exe
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../output) # .a# build test0
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/test0 SRC_TEST0) # collect all cxx files in $test0
add_executabel(test0 ${SRC_TEST0})

在项目构建和编译过程中会生成大量中间文件,为保持源代码目录纯净,一般在其他目录新建一个build目

mkdir build
cd build
cmake ../tests/
make

3.生成并使用链接库

目的:在A工程下,生成动态链接库,在B工程下调用。
每个带cxx的模块下都需要有CMakeLists.txt来描述当前模块的编译配置。

- output
- build
- root - libs- B - B.h- B.cc - CMakeLists.txt- tests- testA- main.cc- CMakeLists.txt

libs/B下的CMakeLists.txt

file(GLOB_RECURSE SRC_LIBS_B${CMAKE_CURRENT_SOURCE_DIR}/B/*.h${CMAKE_CURRENT_SOURCE_DIR}/B/*.cc
)
add_library(B SHARED ${SRC_LIBS_B}) # shared->.so  static->.a  object->.o

tests下的CMakeLists

... # "简单工程"中CMakeLists.txt的常规配置
include_libraries({CMAKE_CURRENT_SOURCE_DIR}/../libs/B)aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/test0 SRC_TEST0) # collect all cxx files in $test0# link B.so
add_executabel(testA ${SRC_TESTA})
target_link_libraries(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libB.so)# link B.a
link_libraries(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libB.a)
add_executable(testA ${SRC_TESTA})# linke B/*.o
add_executable(testA ${SRC_TESTA} $<TARGET_OBJECTS:B>)

4. 超多依赖模块库

目的:
A -> B.so ->C.a->D.a
B.so->C.a B.so->D.a
C.a->D.a
A->C.a A->D.a

- output
- build
- exlibs- D - D.h- D.cc- CMakeLists.txt
- root- statics- C- C.h- C.cc- CMakeLists.txt   - libs- B - B.h- B.cc - CMakeLists.txt- tests- testA- main.cc- CMakeLists.txt
- CMakeLists.txt

项目构建时,脚本从外往里调,从里往外构。最终依赖exlibs/D/CMakeLists.txt。

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/D)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/D SRC_LIBD)
add_library(D STATIC ${SRC_LIBD}) # 最外层CMakeLists会定义libD的输出目录

statics/C/CMakeLists.txt

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../exlibs/D) # include D.header
include_libraries(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libD.a) # 使用静态链接库#include_directories(${CMAKE_CURRENT_SOURCE_DIR})
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC_LIBC)
add_library(C STATIC ${SRC_LIBD}) # 最外层CMakeLists会定义libC.a的输出目录

libs/B/CMakeLists.txt

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../exlibs/D) # include D.header
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../statics/C) # include C.header
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC_LIBB)link_libraries(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libC.a ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libD.a) # 静态链接库,左边依赖右边add_library(B SHARED ${SRC_LIBD})

tests/CMakeLists.txt

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../extlibs/D)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../statics/C)# C&D都是静态链接库的形式,这里还需要再次包含一遍
link_libraries(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libC.a ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libD.a) # 静态链接库,左边依赖右边file(GLOB_RECURSE SRC_TESTA${CMAKE_CURRENT_SOURCE_DIR/testA/*.h}${CMAKE_CURRENT_SOURCE_DIR/testA/*.cc}
)
add_executable(testA ${SRC_TESTA})
target_link_libraries(testA PUBLIC ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libB.so) # 使用动态链接库B

最外层CMakeLists.txt

cmake_minium_version(VERSION 3.10)set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJEC_SOURCE_DIR}/output)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJEC_SOURCE_DIR}/output)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJEC_SOURCE_DIR}/output)set(CMAKE_CXX_FALGS "${GUN_FLAGS} -std=c++11 -fPIC -Wl,--no-as-needed -ldl -lphread") # 使用c++11标准;-fPIC 动态库中使用静态库;-Wl,--no-as-needed 链接dlsym所需系统库;-lphread使用多线程库phreadadd_subdirectory(exlibs/D)
add_subdirectory(root/statics/C)
add_subdirectory(root/libs/B)
add_subdirectory(root/tests)

5.超多依赖库II

同样的依赖关系,不想把C构建成单独的静态库,而是直接使用C编译成的.o。此时只需要在构建B时将C/*.o链接。
1.修改statics/C/CMakeLists.txt最后一行

# add_library(staticC STATIC ${SRC_LIBD})
add_library(objC OBJECT ${SRC_LIBD}) # 将C直接编译成.o备用

2.修改libs/B/CMakeLists.txt的最后2行

# link_libraries(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libC.a ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libD.a) # 静态链接库,左边依赖右边
# add_library(staticC SHARED ${SRC_LIBD})link_libraries(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libD.a) # 只链接静态库
add_library(B SHARED ${SRC_LIBD}$<TARGET_OBJECTS:objC>
) # 直接把C编到libB.so里,后续使用时,只需要链接libB.so就可以用C里的符号

3.修改tests/CMakelists.txt,去除对libC.a的依赖

# # C&D都是静态链接库的形式,这里还需要再次包含一遍
# link_libraries(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libC.a ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libD.a) # 静态链接库,左边依赖右边# 去除对libC.a的依赖
link_libraries(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libD.a}

6.总结

除此之外,还需要指定cmake_cxx_flag编译指令以实现链接系统库等个性化需求;也可以引入xxx.cmake美化cmake的CMakelists文件。

【笔记】CMake构建C++工程相关推荐

  1. cmake构建NNIE工程

    cmake构建NNIE工程 <cmake构建NNIE工程>   利用海思芯片在摄像头端做模型推理是大势所趋,本文介绍了笔者在做 NNIE 开发的过程中使用 cmake 构建 NNIE 工程 ...

  2. C++11标准|用C++写一个矩阵(包含了如何用cmake构建一个工程)

    如何用cmake构建一个工程? 构建一个工程的时候,需要做的几件事情(如果下面几件事你知道怎么做了,多大的工程就都不是问题了): 1.源代码在什么位置? 2.头文件在哪里? 3.怎么生成静态或者动态库 ...

  3. vs2017 cmake android,CMake构建VS2017工程

    1 安装VS2017/cmake 2 工程开发 3 生成VS2017工程 4 参考资料 1 安装VS2017/cmake 软件安装: Visual Studio官网下载Visual Studio Co ...

  4. linux cmake 编译项目,使用CMake构建复杂工程

    0. 什么是CMake CMake是一个跨平台的编译.安装.测试以及打包工具:CMake不直接编译软件,而是结合原生构建系统来构建软件.CMake配置文件是CMakeList.txt文件(每个源码文件 ...

  5. CMake笔记1 构建基本的项目

    最基础的同级文件操作 首先,创建CMakeLists.txt,这是CMake处理的基本文件.首先给出只有一个文件的最简单的情况: PROJECT (HELLO) SET(SRC_LIST main.c ...

  6. 用CMake构建工程时 cmake -G“Unix Makefiles“ 的使用

    在Windows上使用CMake构建项目出现了很多错误,搜索了很多资料尝试改了很多地方始终没能找到与我类似的情况,一度让我以为是系统问题.今天发现就一句,是没用cmake -G"Unix M ...

  7. 【使用CMake组织C++工程】2:CMake 常用命令和变量

    前言 前面的文章介绍了一个最简单的CMake工程,这篇文章将介绍一个稍微复杂一些的CMake工程,结合这个工程总结一下在组织一个C/C++工程时最为常用的一些CMake命令和变量.对于涉及到的命令和变 ...

  8. CMake 构建项目Android NDK项目基础知识

    本篇文章将介绍如何使用 CMake 构建实现你的第一个 NDK 项目. ##前言 你好!欢迎来到我的的学习笔记分享系列,第一次给大家分享的是 Android NDK 开发的学习笔记,让我们先开始了解 ...

  9. Devops之Gradle SpringBoot构建打包工程jar、搭建jenkins自动发布

    本文逐渐涉及当前敏捷开发中非常火的DevOps相关的技术,也就是自动化开发运维.整体偏向于环境搭建,整体学习路线为: (1)SpringBoot+Gradle+Nexus远程仓库构建打包工程jar ( ...

最新文章

  1. oracle数据库装不成功,oracle 10.2.0.4安装 创建数据库时 em不成功需要大的补丁
  2. linux系统做bond
  3. leetcode算法题--旋转数组的最小数字
  4. 国货之光业务增长背后的技术支持 - 完美日记的云原生实践
  5. 照片行【生活随笔】井冈山之行
  6. 碧桂园博智林机器人总部大楼_碧桂园职院新规划曝光!将建机器人实训大楼、新宿舍、水幕电影等...
  7. 科研绘图工具软件_如何在Windows 10 Mail中使用绘图工具
  8. Python程序-离散和线性图形
  9. 配置Syslog输出到远程日志服务器
  10. 一套完整的网络视频监控系统设计方案
  11. 【财经期刊FM-Radio|2021年03月02日】
  12. Unity3D游戏开发从零单排(五) - 导入CS模型到Unity3D
  13. 学生用计算机隐藏功能,学生计算器怎么去掉d
  14. 4 HQL操作之 -- DDL命令
  15. API服务平台,实现多个API的编排与聚合
  16. Ubuntu 18.10 cosmic换源
  17. 逆向世界杯直播App 央视影音-iOS客户端
  18. 智慧指间丨水污染预警溯源平台,实现“污水零直排”长效监管
  19. ie浏览器上取到多个MAC地址
  20. 【九】Android Activity一

热门文章

  1. 【Python问题解决】---- ERROR: Could not install packages due to an OSError: [WinError 2] 系统找不到指定的文件。
  2. 衬线字体和非衬线字体区别
  3. 如何区分“衬线体字”和“无衬线体字”?Linux Mint中如何安装字体?
  4. 电池级碳酸氢锂除杂质钙镁离子工艺原理
  5. vrchat新手教程_VRChat简易教程3-往世界里导入模型和VRC接口初探
  6. PuTTY 下载安装教程
  7. 刚开始做软件测试,一般工资范围是多少?
  8. Python之ffmpeg:利用python编程基于ffmpeg将m4a格式音频文件转为mp3格式文件
  9. Jrebel JetBrains License Server! 免费 Jrebel 激活服务器(自建)
  10. Godaddy域名申请及设置