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

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

3天内不再提示

【Makefile】Makefile与shell命令的联系

嵌入式物联网开发 来源:嵌入式物联网开发 作者:嵌入式物联网开发 2022-07-11 09:06 次阅读

【Makefile】Makefile与shell命令为何总是藕断丝连?

1 写在前面

博主最近在项目实践过程中,需要深度定制项目的Makefile,其中有些复杂的流程必须得借助shell脚本才能高效地完成,为此博主特意深入学习了在Makefile种调用shell命令的方法。

大家都知道shell命令是Linux的神器,学会灵活应用它可以大大提升执行的自动化效率。

Makefile也是GNU的另一大神器,大家要知道,大名鼎鼎的Linux内核的编译就是靠Makefile来支撑的,连这么庞大、复杂的系统编译它都可以轻松驾驭,可想而知,它也是牛逼哄哄的存在。

我们试想一下,如果把Makefile和shell命令这两大神器联合在一起,会有怎样的效果,我们一起来看下。

2 什么是Makefile?

这个问题,我在之前的博文中就有介绍过,感兴趣的可以点过去看一看:【Linux + Makefile】十分钟教你学会Makefile的FORCE。

下面我再总结下,到底什么是Makefile?

Makefile的基本形式如下所示:

TARGET : DEPENDENCES CMD

# TARGET:生成的目标,可以是一个文件,也可以是一个虚拟符号(非真实文件) # DEPENDENCES: 生成目标的所有依赖,它是一个集合,可以只有一个文件,或者很多文件;也可以是虚拟符号 # CMD:把所有依赖生成目标的执行命令,其中CMD前面是一个TAB键,而不能是空格 Makefile的基本规则,归纳起来就是一句话:【当一个TARGET (欲生成的目标)比它的任何一个DEPENDENCES(依赖的文件)旧时,这个TARGET就要重新生成】。

这段话读起来很简单,就是Makefile在执行编译的时候,会先去判断TARGET和其依赖文件的时间差,如果TARGET的时间比较旧,意味着依赖文件已经更新了,那么TARGET就要重新生成;反之,如果TARGET的时间比较新,意味着在TARGET生成后,依赖文件是没有改变过的,自然就不用重新去生成TARGET。

说白了,就是搞清楚【TARGET 和 DEPENDENCES 的时间关系】,弄明白了这个,你就可以读懂Makefile了。

3 如何调试Makefile?

以下Makefile给大家演示下如何在Makefile中写注释以及如何调试Makefile的变量。

# This is an annotation for this Makefile.

# Call shell cmd in these ways ...
CUR_PATH = `pwd`
LS_FILES = "`ls`"
LS_TEST_FILES = "$(shell ls test*)"
DEBUG_VARIABLE = "debug"

# Debug your Makefile variables ...
$(info "This is a info msg ...")
$(warning "This is a warning msg ... DEBUG_VARIABLE=$(DEBUG_VARIABLE)")
$(error "This is a error msg ... It will make this Makefile to exist beacuse of an 'error' accur.")

# Begin you targets and dependences

info:
    @echo "CUR_PATH = $(CUR_PATH)"
    @echo "LS_FILES = $(LS_FILES)"
    @echo "LS_TEST_FILES = $(LS_TEST_FILES)"

我们执行下make info可以看下,输出信息

img

分别对应info,warning,error;这三个函数是Makefile中内置的,在任意Makefile中都可以使用。但是需要注意的,这三个函数可以在Makefile的任意位置调用,但是必须符合语法规则,比如在CMD部分(见第一章节的引用内容)调用时,必须时TAB开头。

我们试下这个的效果:

imgimg

4 Makefile定义变量的时候调用shell命令

还是拿上面的Makefile来分析,我们一开始定义了几个变量:

CUR_PATH = `pwd`
LS_FILES = "`ls`"
LS_TEST_FILES = "$(shell ls test*)"

其中CURPATH是保存当前Makefile的路径,我们都知道shell命令有个pwd可以获取到当前目录的路径,所以 CURPATH 变量正是利用了这个命令来取得当前路径。其中,值得注意的是 表示的是获取pwd命令的返回值,这个,不是分号 ' ',而是键盘左上角数字1左边的那个键值,新手一般非常容易搞错这一点。

第二个变量LS_FILES的定义,使用同样的方式调用了 ls 命令,但是它在返回值的左右,加了 “ ”;这样做的主要目的是,ls的返回值通常是一个字符串,中间每个文件名用空格隔开的;如果我们想把这一系列的字符串连起来而不是分散的,我们就必须使用 " "把它们包起来,这样Makefile变量就会把它当作一个字符串整体来处理。

第三个变量LSTESTFILES,它就换了一种方式来调用shell命令,它的格式是 $(shell xxx),其中xxx就是一个可以在shell环境下执行的shell命令,比如本例子中,xxx就是 ls test*。

两者方法没有本质的区别,结合自己的实际情况来使用即可,从易读性来说,推荐使用$(shell xxx)的调用方式。

5 Makefile在执行命令的时候调用shell命令

以下面的Makefile为例子:

# This is an annotation for this Makefile.

shell_cmd:
    @ls test*
    @pwd
    @echo "shell_cmd test ..."

执行make shell_cmd,我们可以看到输出:

img

只要是shell执行的命令,都可以运行,这就方便我们做一些自动化操作,比如创建目录、删除文件、下载文件、上传文件等等。

6 Makefile以函数的形式调用shell命令

请看下面的Makefile内容

# This is an annotation for this Makefile.

DEBUG_VARIABLE = "debug"

# This is a shell function.
define function_test_shell
    param1=$1;\
    local_variable=12345678;\
    debug_variable=$(DEBUG_VARIABLE);\
    echo "param1=$$param1";\
    echo "local_variable=$$local_variable";\
    echo "debug_variable=$$debug_variable";\
    i=0;\
    cnt=10;\
    for i in `seq $$cnt`; do\
        echo "i=$$i";\
    done;\
    ls -al;\
    ls -al test*
endef

# Begin you targets and dependences

shell_function:
    @$(call function_test_shell,$(DEBUG_VARIABLE))

我们执行make shell_function可以看到输出:

pYYBAGLK8s2ACqvEAABZItmdNSQ889.png

对应就是shell函数里面的操作。

在Makefile调用shell函数的写法上,有几点特别需要注意:

1)Makefile定义函数是使用define 和 endef,务必配对使用;函数里面的实现可以调用shell命令,也可以调用Makefile内置的函数,也可以调用自定义的Makefile函数;

2)Makefile函数的调用方式是$(call function,xx,yy,zz),其中function是函数名,也就是define后面的名字,xx/yy/zz分别是函数的三个入参;当然有几个参数就填几个,每一个使用 , 隔开;

3) 在函数里面使用$1 $2 $3获取输入的参数,即$+数字的方式获取入参;

4)如果函数里面使用的是shell组合命令,请务必在每一条shell命令后面加上 ; 符号,并且每一行加上 \ 连起来;这样对于shell解析器而言,它会认为是一条长长的组合输入命令,而不报语法错误;

5)函数内部使用shell的变量,比如是变量a,正确的写法是$$a;而不是常规的shell写法$a,也不是Makefile获取变量的方法$(a)或${a};这一点特别需要注意。

6)如果函数内部访问的是Makefile定义的变量,比如示例中的访问DEBUGVARIABLE变量,还是采用$(DEBUGVARIABLE)的方式。


好了,本期分享就到这里,有疑问的话,欢迎联系我。

7 更多分享

欢迎关注我的github仓库01workstation,日常分享一些开发笔记和项目实战,欢迎指正问题。

同时也非常欢迎关注我的CSDN主页和专栏:

【CSDN主页-架构师李肯】

RT-Thread主页-架构师李肯】

【C/C++语言编程专栏】

【GCC专栏】

【信息安全专栏】

【RT-Thread开发笔记】

freeRTOS开发笔记】

【BLE蓝牙开发笔记】

ARM开发笔记】

RISC-V开发笔记】

有问题的话,可以跟我讨论,知无不答,谢谢大家。

审核编辑:汤梓红

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

    关注

    87

    文章

    10992

    浏览量

    206745
  • Makefile
    +关注

    关注

    1

    文章

    122

    浏览量

    19094
  • Shell
    +关注

    关注

    1

    文章

    358

    浏览量

    22903
收藏 人收藏

    评论

    相关推荐

    Linux中makefileshell的区别

    :*** missing separator.Stop. 5、在Makefile中执行shell命令,一行创建一个进程来执行。更多学习信息交流卢工3311615775,这也是为什么很多Make
    发表于 09-22 14:29

    无法在2015.3 sdk中运行makefile

    17-259] Unknown Tcl命令'make -f Makefile'发送命令到OS shell执行.make.EXE:没有什么可以为'all'做。以上来自于谷歌翻译以下为原
    发表于 04-17 10:04

    Makefile编写

    )shell函数 执行shell命令例如:$(shell ls -d */)当我们学会了Makefile编写就可以让其为我们所用了,有什么疑
    发表于 11-02 15:59

    教你写Makefile

    教你写Makefile 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,
    发表于 02-10 14:24 37次下载

    C语言入门教程-makefile

    makefile 重复键入上一节的gcc命令很是麻烦,尤其是当您要不断修改的代码,且使用了好几个函数库的时候。make工具解决了这个问题。您可以用下面的makefile代替前面的一串编
    发表于 07-29 11:20 819次阅读

    驾驭Makefile

    驾驭Makefile在网上你能找到很多关于Makefile的学习资料,但绝大部分给你的只是一个知识点,与将Makefile运用到项目中(尤其是大型项目)的差距非常的大。因为,将Makefile
    发表于 01-05 17:05 9次下载

    跟我一起学makefile

    关于makefile学习,深入了解嵌入式下makefile的编写
    发表于 05-23 18:21 0次下载

    makefile的基本语法

     在Makefile中,最重要的三个概念是:目标(target)、依赖关系(dependency)和命令(command)。目标是指要干什么,即运行make后生成什么;依赖是指明目标所依赖的其他目标;命令则告诉make如何生成目
    发表于 11-12 10:15 1.1w次阅读

    嵌入式系统Kconfig .config Makefile联系和区别

    2.6内核的Makefile分为5个组成部分: 1. 最顶层的Makefile :读取 .config文件的内容,并总体上负责build内核和模块。 2. 内核的.config配置文件 3.
    的头像 发表于 08-01 16:20 5394次阅读

    Makefile是什么?Makefile工作原理是怎样的?Makefile经典教程免费下载

    Makefile的重要性 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力 makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令
    发表于 09-12 17:19 0次下载
    <b class='flag-5'>Makefile</b>是什么?<b class='flag-5'>Makefile</b>工作原理是怎样的?<b class='flag-5'>Makefile</b>经典教程免费下载

    Makefile】简单实用的Makefile模板来了

    【Linux + Makefile】简单实用的Makefile模板来了
    的头像 发表于 08-31 12:46 1647次阅读
    【<b class='flag-5'>Makefile</b>】简单实用的<b class='flag-5'>Makefile</b>模板来了

    Linux开发_Makefile规则与Shell脚本语言

    介绍Linux下Makefile编程知识点,Shell脚本知识点。
    的头像 发表于 09-17 15:40 951次阅读

    什么是Makefile

    如果您有多个 c、c++ 和其他语言的文件,并且想通过终端命令编译它们,我们该如何编译他们呢?为了解决这类问题,Makefile就出现了。
    的头像 发表于 02-17 10:41 3462次阅读
    什么是<b class='flag-5'>Makefile</b>?

    和我一起写makefile

    make 命令执行时,需要一个 makefile 文件,以告诉 make 命令需要怎么样的去编译和链接程序。首先,我们用一个示例来说明 makefile 的书写规则,以便给大家一个感性
    发表于 10-07 11:23 0次下载

    Makefile可以做什么?Makefile的基本格式

    Makefile可以根据指定的依赖规则和文件是否有修改来执行命令。常用来编译软件源代码,只需要重新编译修改过的文件,使得编译速度大大加快。
    的头像 发表于 01-25 11:18 241次阅读