如何使用CMake构建c++项目

1. c++项目构建与CMake简介

在Windows系统上我们通常使用 Visual Studio(VS)来生成我们的c++项目。我们只需在VS相应的层次目录中添加相应的文件即可,而不需要手动指定各个文件的具体路径及依赖包含关系。

如何使用CMake构建c++项目

图1. 微软开源的Calculator源码

Linux系统上我们通常使用 CMake来构建c++项目。cmake是一个跨平台的编译工具,CMake 的组态档取名为 CMakeLists.txt。换一个通俗点的意思就是我只需要写一个CMakeLists.txt文件来指明与我的项目有关的文件、依赖等,便可将这个项目正常编译及生成可执行文件。

注:CMake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。即当我们使用 cmake命令后,我们还要使用 make命令生成可执行文件。

2.使用g++编译cpp文件

g++是GNU开发的C++编译器,是GCC(GNU Compiler Collection)GNU编译器套件的组成部分。对应一个简单的c++程序,我们一般可以使用g++命令进行直接编译。

/*文件名为main.cpp*/
#include
int main(){
        std::cout<

我们可以使用以下命令进行编译:

[En]

We can compile with the following command:

g++ -o hello main.cpp

我们可以看到程序编译和执行正常:

[En]

We can see that the program compiles and executes normally:

如何使用CMake构建c++项目

图2. Ubuntu下执行g++命令

当然g++以及gcc有较多的命令与功能,这里不再详细展开说明。

3. Cmake入门

3.1 一个简单的CMakeLists.txt:

cmake_minimum_required(VERSION 3.9) #最低版本

project(helloworld VERSION 1.0) #项目名称及自定义版本号
add_executable(hello_cmake main.cpp) #添加生成可执行文件

接下来我们使用 cmake . && make&& ./hello_cmake便可编译、生成与运行我们所编译的文件了。

  • cmake .:在当前目录下生成标准建构档(可以理解为中间文件),这里的 ” .” 指代的是当前目录。
  • make:编译中间文件,生成可执行文件。

如何使用CMake构建c++项目

图3. 执行make命令

  • ./hello_cmake:运行可执行文件。

这样,我们便使用CMake编译与生成了第一个c++文件。到目前为止它与上文中使用到的 g++的作用是一样的。而当一个c++项目越复杂时,使用CMake的优势也将越来越明显。

3.2 创建build文件夹,不同文件分离与有序化

如果你运行了 cmake . && make这两个命令,你就会发现在你的源文件所在的目录下多出了很多其他的文件。这些文件是项目编译中很重要的文件,但其实你可以完全不用去管他。我们只需要关注 CMakeLists.txt源文件

上述问题的解决方法是在项目文件夹中创建一个 build文件用于保存这些”无关紧要的编译文件”——mkdir build

如何使用CMake构建c++项目

图4. 创建build文件夹

这样你只需要进入 build目录使用 cmake .. && make便可以生成二进制文件了(可执行文件)。

注: cmake ..中 ” ..” 指代上一级目录。所以在build目录中使用 cmake ..指代的是:调用上一级目录中的CMakeLists.txt文件,并将生成的中间文件保存在当前目录。

附:对于较大型的c++项目,合理利用文件夹分类文件可以帮到我们很多。例如创建 src文件夹存放源文件(源代码),创建 bin(binary)存放可执行文件,创建 include存放头文件。

3.3 CMake使项目中包含头文件

我们创建一个include目录并在目录下编写一个较为简单的header:

#pragma once
#include
class Blah{
    public:
    inline void boo(){
        std::cout<

然后再在源文件中添加一个 #include "header.h"来引用头文件。这时如果不改变CMakeLists.txt文件,显然源文件并不知道这个header.h的具体位置。

所以,我们需要修改CMakeLists.txt文件(事实上只需要添加一行语句)

cmake_minimum_required(VERSION 3.9)

project(helloworld VERSION 1.0)
add_executable(hello_cmake main.cpp)
target_include_directories(hello_cmake PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

target_include_directories:指定编译给定目标时要使用的include目录。这里即在编译生成hello_make可执行文件时,使用CMakeLists.txt所在的目录下的include目录。 INTERFACE、PUBLIC和PRIVATE关键字用于指定target_include_directories的影响范围 。在引用库路径时使用这个命令更多,这里不在展开。

当然在CMake中 include_directories也可以指定头文件目录。其作用是:将给定的目录添加到编译器用来搜索头文件的目录中。它的范围相较于 target_include_directories更大。不需要针对于某一个给定的目标。所有生成的可执行文件都可以在 include_directories指定的目录下搜索查找头文件。

3.4 CMake处理多个源文件的编译

  1. 修改 add_executable,添加多个源文件,例如:
add_executable(hello_cmake main.cpp src/Blah.cpp)
  1. 通过修改CMakeLists.txt文件指定源文件的路径。

​ 在CMakeLists.txt中添加如下代码即可:

file(GOLB_RECURSE SRC_FILES src/*.cpp)
add_executable(hello ${SRC_FILES})

这里的 ${},相当于一个变量。在CMake中经常使用!

我们可以使用以下语句设置相应路径变量,则MYLIB_INCLUDE_DIRS为设置的路径。

set(MYLIB_INCLUDE_DIRS /tmp/customPATH/include)

3.5 CMake中引用相关文件(library\package)

我们首先需要理解以下概念。

[En]

We first need to understand the following concepts.

linux下有两种库: 动态库(.so)静态库(.a)(共享库)。二者的不同点在于代码被载入的时刻不同。

  • 静态库的代码在编译时已经加载到可执行程序中,所以比较大。
    [En]

    the code of the static library has been loaded into the executable program during compilation, so it is relatively large.*

  • 动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。

  • My own lib:

add_library(mylib STATIC lib/blah.cpp) #STATIC 静态 #添加lib
add_executable(hello_cmake main.cpp) #生成可执行文件
target_link_libraries(hello_cmake PUBLIC mylib) #链接库文件
  1. external lib with find_package:

这里以sfml作为外部依赖包为例,它需要首先从软件仓库下载,再在CMakeLists.txt文件中编写如下语句。

find_package(SFML 2 REQUIRED network audio graphics window system)
target_include_directories(hello_cmake PUBLIC ${SFML_INCLUDE_DIR})
target_link_libraries(hello_cmake PUBLIC ${SFML_LIBRARIES} ${SFML_DEPENDENCIES}) #链接库文件

这样我们就可以在源文件中加入相关include语句了。

#include
#include
  1. external lib manually (手动引用库文件)
find_library(MYLIB mylib)
find_library(MYLIB mylib PATHS /tmp/customPATH)

​ find_library可以加入 REQUIRED参数,它表示为如果未找到任何内容,则停止处理并显示错误消息。

3.6 CMake的嵌套使用

主要操作如下:

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

作用: 添加一个子目录并构建该子目录。

例如在库文件中,我们可能还需要添加头文件的路径。而将其全部写在外部的CMakeLists.txt文件中又会略显臃肿。

这时我们可以在lib文件中,编写一个新的CMakeList.txt,然后仅仅将相关代码放上去。例如

add_library(mylib STATIC blah.cpp) #STATIC 静态 #添加lib
target_include_directories(hello_cmake PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) #指定头文件

4. 案例代码

cmake_minimum_required(VERSION 3.9)
project(example_test1)
set (EXECUTABLE_OUTPUT_PATH /home/tom/文档/example_test1/bin)
aux_source_directory (/home/tom/文档/example_test1/src SRC_LIST)
include_directories (/home/tom/文档/example_test1/ltkcpp/include)

find_library(LIBLTKCPP libltkcpp_x86_64.a /home/tom/文档/example_test1/ltkcpp/lib)
find_library(LIBLTKCPP_IMPINJ libltkcppimpinj_x86_64.a /home/tom/文档/example_test1/ltkcpp/lib)
it is not recommended to statically link for ssl and crypto libraries
find_library(LIBSSL ssl REQUIRED)
find_library(LIBCRYPTO crypto REQUIRED)
The ETK does not contain a host static library for xml2.  Add the generic
name 'xml2' to link against the dynmaic library when compiling for host.

find_library(LIBXML2 NAMES libxml2.a xml2 REQUIRED)
set(LIBS
    ${LIBLTKCPP}
    ${LIBLTKCPP_IMPINJ}
    ${LIBCRYPTO}
    ${LIBSSL}
    ${LIBXML2}
)

add_executable(main ${SRC_LIST})
target_link_libraries(main PRIVATE ${LIBS})

aux_source_directory (< dir > < variable >) 搜集所有在指定路径下的源文件的文件名,将输出结果列表储存在指定的变量中。

Original: https://www.cnblogs.com/litecdows/p/cmake.html
Author: litecdows
Title: 如何使用CMake构建c++项目

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/524070/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • rabbitmq-安装部署及基础操作

    yum 安装 rabbitmq # centos7 编译安装rabbitmq 在安装RabbitMQ中需要注意:1、RabbitMQ依赖于Erlang,需要先安装Erlang2、E…

    Linux 2023年6月14日
    0101
  • SPRINGBOOT(38)整合(9)redis

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/qiu-hua/p/16552545.htmlAutho…

    Linux 2023年5月28日
    085
  • SpringBoot——自定义Redis缓存Cache

    SpringBoot自带Cache存在问题: 1.生成Key过于简单,容易冲突 默认为cacheNames + ":" + Key2.无法设置过期时间,默认时间…

    Linux 2023年5月28日
    088
  • Cisco实验:【DHCP配置】客户端跨网段通过DHCP服务器自动获取动态IP和固定IP地址

    模拟环境:R1为路由器e0/0接口和e0/1接口分别连接两个网段,e0/0连接用户区域,e0/1连接服务器区域;用户区域中SW1为接入层交换机,连接一台PC(R2模拟)和一台打印机…

    Linux 2023年6月8日
    0171
  • [极客大挑战 2019]Secret File

    0x01 寻找做题信息 打开环境,查看源代码,发现可疑链接,/Archive_room.php,action.php打开action.php会发生302跳转,查找302跳转无果,百…

    Linux 2023年6月8日
    085
  • LeetCode-210. 课程表 II

    题目来源 题目详情 现在你总共有 numCourses 门课需要选,记为 0 到 numCourses – 1。给你一个数组 prerequisites ,其中 prerequis…

    Linux 2023年6月7日
    072
  • 更新yum 源下载报错

    entos7.9 更换yum 源 为阿里云的之后,下载软件包报错 Failed connect to mirrors.aliyuncs.com:80; Connection tim…

    Linux 2023年6月14日
    077
  • 方法的深度理解

    权限修饰符 返回值类型 类名(行参列表 )throws 异常的类型{ //方法体 约定俗称:子类中叫重写的方法,父类中叫被重写的方法。 ①子类重写的方法名和行参列表和父类被重写的方…

    Linux 2023年6月14日
    087
  • CTF竞赛权威指南(PWN篇)下载地址

    博客网址:www.shicoder.top微信:18223081347欢迎加群聊天 :452380935 这里给大家提供《CTF竞赛权威指南(PWN篇)》的下载地址(不是网上的64…

    Linux 2023年6月13日
    085
  • 职场最讨厌的人,没有之一

    人物背景: 姓名:春绿,性别:未知,年龄:不详,工龄:菜鸟,人物特点:爱管闲事,管不住自己的嘴,情商约等于0.000001 人物故事: 1、领导给小明安排了一个工作,被春绿听到了,…

    Linux 2023年6月13日
    090
  • 阅读习惯2(选做)

    任务详情 参考https://www.cnblogs.com/rocedu/p/6528920.html 提交微信读书(或其他平台)目前的读书数据(总时长,册数,笔记数等)的截图,…

    Linux 2023年6月8日
    091
  • 理清计算机中的数据表示方法–2’s complement

    Bits bits是信息的基本单元,计算机通过电压的高低来确定是0还是1;这里的电压是有一定范围的,0~a视为0, a~b视为1,具体数字不用记 Data Types 同一个数字有…

    Linux 2023年6月6日
    082
  • Linux内核中内存管理相关的数据结构

    本文简要说明几个内核和内存管理有关的结构体。其中 struct page 和 struct zone有较大幅度的删减,主要删减了和NUMA模型SPARSE模型以及内存热插拔相关的域…

    Linux 2023年6月7日
    099
  • NoteOfMySQL-07-索引

    1. 索引概述 创建索引的目的是为了优化数据库的查询速度,不添加索引的情况下需要遍历所有数据才能进行删、查、改等操作。 2. 索引存储类型 存储类型 支持的存储引擎 B型树(BTR…

    Linux 2023年6月14日
    080
  • Redis集群-主从架构

    1.为什么需要集群? 互联网思维一向讲究的是三高,即高并发,高可用,高性能。高并发:系统能够同时并行处理的请求,主要度量指标有响应延时,吞吐量,每秒查询处理,每秒事务处理,并发用户…

    Linux 2023年6月7日
    0100
  • mysql内连接查询之自连接

    连接查询:当查询数据时,通过连接操作查询出存放在多个表中的不同数据,当两个或者多个表中存在相同意义的字段时,便可以通过这些字段对不同的表进行连接查询。自连接:如果在一个连接查询中,…

    Linux 2023年6月7日
    086
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球