0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CMake的实战教程-2

汽车电子技术 来源:物联网IoT开发 作者: 杰杰mcu 2023-02-14 10:43 次阅读

前言

从上一篇的文章中,相信大家也了解了CMake这个东西,但是呢它不是只是看一下就能会的,这种东西还是要实践才能学会,那么如果你已经实践过了,就会体会到上一篇文章在实际中使用到底是多么的难搞,比如:

  • 生成很多垃圾文件,这是我的第一个体会….
  • 需要手动去指定编译的文件
  • 无法指定编译器,编译选项等等很多东西….
  • 如果有子目录也不能完全适用….
  • 以及一些其他的问题….

总的来说就是在真正项目中压根就没法适用的工程,那为什么我要写呢,因为那是我学习的过程,总不能一口吞下一个大胖子是不是,接下来的一系列文章我就会让CMake变得能在实际中使用,越来越自动化,更方便构建。。。

外部构建

第一个问题,在运行cmake .后会产生很多垃圾文件,那么我们可以让它在一个build目录下去编译,生成的垃圾文件放在这个目录下就好了,不需要的时候直接清除即可。

可能有人会问,它不能像Makefile一样直接make clean 或者make distclean清除编译的垃圾文件吗,我当时学的时候也谷歌过,但是,很遗憾没有,使用我才让它产生的垃圾文件放在build目录下,其实不能说是垃圾文件,只不过是一些中间文件,记录某些东西的,我用不上它,所以认为是垃圾…仅此而已。

对此官方的解释是:

CMakeLists.txt 可以执行脚本并通过脚本生成一些临时文件,但是却没有办法来跟踪这些临时文件到底是哪些,因此,没有办法提供一个可靠的 clean 方案。

那怎么办呢?很简单,从CMake的语法我们就知道,它在构建的时候指定了PATH,也就是顶层CMakeLists.txt 入口的路径。

cmake PATH

那么很显然,它可以是相对路径而不是绝对路径,毕竟‘.’ 表示当前路径, 点点‘..’ 表示上一级路径,那么我们可以新建一个build目录,然后在build目录下去运行:

cmake ..

这在CMake中称之为外部构建(out-of-source build),而 CMake 强烈推荐的就是外部构建!

我自己也写了个build的脚本,内容非常简单,主要做两件事:

  1. 创建一个build目录(存在就不会重新创建的)
  2. 进入build目录
  3. 然后外部构建cmake
  4. 生成Makefile文件后运行make命令编译
#!/bin/bash

mkdir -p build
cd build
cmake ..
make

因此在编译的时候直接运行这个脚本即可,生成的内容全部都在build目录下。

  • 这是原始目录
.
├── build.sh
├── CMakeLists.txt
└── main.c

0 directories, 3 files

编译后在build目录下生成很多文件,包括 Makefile、section2(可执行程序)

CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile  section2

补充一点,如果你想看到cmake生成的垃圾文件比你源码还多的时候,你就会爱死外部构建这种骚操作了~

自动查找源码

不得不说,cmake是个很好的自动化构建工具,既然是自动化,那么很的东西都是自动的,比如查找源码,cmake就提供查找源码的命令:

aux_source_directory(<dir> <variable>)

它的主要作用就是: 查找在某个路径下的所有源文件 ,注意,是所有源码文件,当你的目录下有很多个源码文件的时候,他就主动去查找了,哦,当然,它也只会查找源码文件,比如*.c 、 *.cpp 、*.cc啦,反正只要是源码就可以了,但是什么txt 、 *.h文件这些它是不会记录下来的。

  • dir :指定的目录(可以是绝对路径也可以是相对路径)
  • variable:将输出结果列表储存在指定的变量中。

反正这个命令就很方便,我在某个目录下有啥源码文件,我都会被记录到变量,然后在CMake直接使用即可。当然后续也有其他的命令去找源码文件,一口吃不了一个大胖子,先了解这个先,后续慢慢学习~

变量

CMake中,变量是十分常见的,我正在就简单讲解下基本的语法吧:

定义变量常用的函数是:

set(VARIABLE_NAME VARIABLE)

取消定义变量是

unset(VARIABLE_NAME )
  • VARIABLE_NAME :变量名字
  • VARIABLE:变量的值

变量的的值始终是string(字符串)类型,变量名字是区分大小写的,一般变量命名还是正常点比较好,别搞太多乱七八糟的特殊符号,只要数字、字母,下划线"_" 、横线"-"就差不多了,变量的作用域也是有全局与局部之分,与C语言Java都差不多,我也不多说了。我的例程中全局变量是全部大写,局部变量是全小写的,也是比较好区分。

变量引用的形式为${variable_name},变量引用被变量的值替换,或者如果变量没有被设置,则由空字符串替换。变量引用可以嵌套,例如${outer_${inner_variable}veriable};环境变量引用的形式为$ENV{VARIABLE},并在相同的上下文中作为正常变量引用。

打印日志

在CMake构建的时候,你可能不知道某些变量是啥内容,那么就在终端打印出来看看就好了,这根我们写代码中的printf函数差不多,给直接打一串字符串出来瞧瞧….

message([] "message to display" ...)

首先呢,是指定消息的类型:

  • (无) = 重要消息;
  • STATUS = 非重要消息;
  • WARNING = CMake 警告, 会继续执行;
  • AUTHOR_WARNING = CMake 警告 (dev), 会继续执行;
  • SEND_ERROR = CMake 错误, 继续执行,但是会跳过生成的步骤;
  • FATAL_ERROR = CMake 错误, 终止所有处理过程;

正常情况下我都是输出一些状态信息——STATUS,打印个变量啦,打印下代码的执行顺序啦等等….

后面就是有些字符串信息了,变量在这里直接引用就好,毕竟变量本身就是字符串….

section3

给出个实例代码:

当前目录存在2个c文件,分别是main.cpower.c就是简单计算x的y次方,纯粹是个demo,我自己也懒得写,并不是因为代码有多高深,所以这代码我是从网上找的,来自@潘伟洲大神的cmake测试代码:https://github.com/wzpan/cmake-demo。

  • main.c
#include 
#include 
#include "power.h"

int main(int argc, char *argv[])
{
    if (argc < 3){
        printf("Usage: %s base exponent \\n", argv[0]);
        return 1;
    }
    double base = atof(argv[1]);
    int exponent = atoi(argv[2]);
    double result = power(base, exponent);
    printf("%g ^ %d is %g\\n", base, exponent, result);
    return 0;
}
  • power.c
double power(double base, int exponent)
{
    int result = base;
    int i;

    if (exponent == 0) {
        return 1;
    }

    for(i = 1; i < exponent; ++i){
        result = result * base;
    }

    return result;
}

然后就是CMakeLists.txt文件:

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目信息
project (section3)

# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)

# 指定生成目标
add_executable(section3 ${DIR_SRCS})

相比于上一篇文章,我这个CMakeLists.txt文件只是添加了aux_source_directory命令去自动扫描当前目录下的源码文件,并且保存到DIR_SRCS 变量中,仅此而已!!

然后在add_executable命令中,用${DIR_SRCS}变量代替指定的源码文件source1 source2 ... sourceN,当然你也可以打印一下${DIR_SRCS}变量到底保存了什么,如果不出意外的话,它保存的就是./main.c; ./power.c,表示的是当前目录下的main.cpower.c这两个文件,而分号代表它是一个list,后续会讲解怎么去提取list的内容….

message(STATUS "${DIR_SRCS}")

然后用外部构建的方式去编译代码:

jie@pc:~/github/cmake/section3$ ./build.sh 
-- The C compiler identification is GNU 7.4.0
-- The CXX compiler identification is GNU 7.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jie/github/cmake/section3/build
Scanning dependencies of target section3
[ 33%] Building C object CMakeFiles/section3.dir/main.c.o
[ 66%] Building C object CMakeFiles/section3.dir/power.c.o
[100%] Linking C executable section3
[100%] Built target section3

很明显生成了正确可执行文件~

代码下载

https://github.com/jiejieTop/cmake

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 文件
    +关注

    关注

    1

    文章

    566

    浏览量

    24744
  • Build
    +关注

    关注

    0

    文章

    26

    浏览量

    12056
  • CMake
    +关注

    关注

    0

    文章

    28

    浏览量

    1275
收藏 人收藏

    评论

    相关推荐

    Linux中CMake的使用3-不同目录多个源文件

    上篇(Linux中CMake的使用2-同目录下多个源文件)介绍了在同一目录下有多个源文件时如何编写CMakeLists.txt。
    的头像 发表于 09-21 08:49 4061次阅读
    Linux中<b class='flag-5'>CMake</b>的使用3-不同目录多个源文件

    cmake是什么?cmake的特性和编译原理(cmake原理和cmake编译过程)

    CMake是一个开源、跨平台的工具系列,是用来构建、测试和打包软件。
    的头像 发表于 07-18 10:53 4668次阅读
    <b class='flag-5'>cmake</b>是什么?<b class='flag-5'>cmake</b>的特性和编译原理(<b class='flag-5'>cmake</b>原理和<b class='flag-5'>cmake</b>编译过程)

    Windows下编译工具CMake的安装和最简使用

    MCU的开发环境一般在Windows操作系统上,简单的工程一般直接编写Makefile文件后使用make工具构建程序,复杂的工程一般借助CMake来生成Makefile文件后使用make工程构建程序
    的头像 发表于 11-14 10:18 8256次阅读
    Windows下编译工具<b class='flag-5'>CMake</b>的安装和最简使用

    CMake 入门实战

    CMake 入门实战,,
    发表于 09-28 12:38

    交叉平台开源编译系统_cmake入门

    交叉平台开源编译系统_cmake入门
    发表于 01-22 13:59 9次下载

    Cmake学习的总结(二)

    大家好,上次给大家分享了第一篇 cmake 文章:cmake学习总结(一),今天继续给大家分享cmake。那么废话就不多说,开始内容分享。
    的头像 发表于 12-24 17:54 640次阅读

    cmake管理配置ROOT项目的方法

    配置文件组成。   序号 文件名 文件说明 1 CMakeLists.txt  Cmake配置文件,用于组织项目的编译需要的库、编译的过程、编译结果 2 CMakeLists.txt.user
    的头像 发表于 01-18 17:45 4622次阅读
    <b class='flag-5'>cmake</b>管理配置ROOT项目的方法

    如何使用CMake工具套件构建CUDA应用程序

    我希望这篇文章向您展示了 CMake 如何自然地支持构建 CUDA 应用程序。如果您是 CMake 的现有用户,请试用 CMake 3 . 9 并利用改进的 CUDA 支持。如果您不是 CMa
    的头像 发表于 04-01 17:42 4559次阅读
    如何使用<b class='flag-5'>CMake</b>工具套件构建CUDA应用程序

    RT-Thread V4.1.0新特性CMake介绍与构建CMake工程

        CMake 支持 在 RT-Thread 4.1.0 正式发布版中,添加了对 CMake 的支持。开发者可以使用 SCons 工具来生成 CMakeLists.txt 文件。 为何要支持
    的头像 发表于 05-24 19:20 3013次阅读

    RT-Thread 4.1.0的CMake构建教程

    CMake 支持 在 RT-Thread 4.1.0 正式发布版中,添加了对 CMake 的支持。开发者可以使用 SCons 工具来生成 CMakeLists.txt 文件。 为何要支持 CMake
    的头像 发表于 05-25 11:06 3360次阅读

    CMake用法详解

    CMake用法详解
    发表于 10-25 16:28 2次下载

    CMake实战教程-1

    CMake 是一个跨平台的构建系统生成工具。它使用平台无关的 CMake 清单文件CMakeLists.txt,指定工程的构建过程;源码树的每个路径下都有这个文件。CMake 产生一个适用于具体平台的构建系统,用户使用这个系统构
    的头像 发表于 02-14 10:42 714次阅读
    <b class='flag-5'>CMake</b>的<b class='flag-5'>实战</b>教程-1

    CMake实战教程-2

    第一个问题,在运行`cmake .`后会产生很多垃圾文件,那么我们可以让它在一个build目录下去编译,生成的垃圾文件放在这个目录下就好了,不需要的时候直接清除即可。
    的头像 发表于 02-28 16:18 755次阅读

    在Linux下如何使用CMake编译程序

    CMake是开源、跨平台的构建工具,可以让我们通过编写简单的配置文件去生成本地的Makefile,这个配置文件是独立于运行平台和编译器的,这样就不用亲自去编写Makefile了,而且配置文件可以直接
    的头像 发表于 11-08 16:15 6439次阅读
    在Linux下如何使用<b class='flag-5'>CMake</b>编译程序

    CMake构建后的项目结构解析

    一、 CMake构建后的项目结构解析(Analysis of the Project Structure After CMake Build) 1.1 CMake构建后的目录结构(Directory
    的头像 发表于 11-10 10:27 2076次阅读
    <b class='flag-5'>CMake</b>构建后的项目结构解析