嵌入式Linux (十一)

姓名:杨乔   学号:19020100280    学院:电子工程学院

转自:

https://max.book118.com/html/2016/1207/69449578.shtm

【嵌牛导读】嵌入式一般指嵌入式系统。嵌入式系统由硬件和软件组成。是能够独立进行运作的器件。Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。

【嵌牛鼻子】make 工程管理器

【嵌牛提问】make 工程管理器如何使用?

【嵌牛正文】

前面几节主要介绍如何在Linux环境下使用文本编辑器,如何使用GCC编译出可执行文件,以及如何使用GDB来调试程序。既然所有的工作都已经完成了,为什么还需要make这个工程管理器呢?

工程管理器可以用来管理较多的文件。读者可以试想一下:一个由上百个源文件构成的项目,如果其中只有一个或少数几个文件进行了修改,按照之前所学的 GCC 的用法,就不得不把所有的文件重新编译一遍。原因就在于编译器并不知道哪些文件是最近更新的,所以,程序员就不得不处理所有的文件来完成重新编译工作。

显然,开发人员需要一个能够自动识别出那些被更新的代码文件并实现整个工程自动编译的工具。

实际上,make就是一个自动编译管理器,能够根据文件时间戳自动发现更新过的文件从而减少编译的工作量。同时,它通过读入Makefile文件的内容来执行大量的编译工作,用户只需编写一次简单的编译语句即可。它大大提高了项目开发和维护的工作效率,几乎所有嵌入式Linux下的项目编程均会涉及make管理器,希望读者能够认真学习本节内容。

1.5.1 Makefile基本结构

Makefile用来告诉make如何编译和链接一个程序,它是make读入的唯一配置文件。本小节主要讲解Makefile的编写规则。在一个Makefile中通常包含如下内容。① 需要由 make 工具创建的目标体(target),目标体通常是目标文件、可执行文件或是一个标签。② 要创建的目标体所依赖的文件(dependency_file)。③ 创建每个目标体时需要运行的命令(command)。它的格式为target: dependency_filescommand例如,有两个文件分别为“hello.c”和“hello.h”,希望创建的目标体为“hello.o”,执行的命令为 GCC 编译指令“gcc –c hello.c”,那么,对应的 Makefile 就可以写为以下形式。#The simplest examplehello.o: hello.c hello.hgcc –c hello.c –o hello.o接着就可以使用make了。使用make的格式为“make target”,这样make就会自动读入Makefile (也可以是首字母小写makefile)执行对应target的command语句,并会找到相应的依赖文件,如下所示。[root@localhost makefile]# make hello.ogcc –c hello.c –o hello.o[root@localhost makefile]# lshello.c hello.h hello.o Makefile可以看到,Makefile执行了“hello.o”对应的命令语句,并生成了“hello.o”目标体。

在Makefile中的每一个command前必须有“Tab”符,否则在运行make命令时会出错。上面实例中的Makefile在实际中是几乎不存在的,因为它过于简单,仅包含两个文件和一个命令,在这种情况下完全不需要编写Makefile,只需在Shell中直接输入命令即可。在实际中使用的Makefile往往是包含很多命令的,一个项目也会包含多个Makefile。

下面就对较复杂的Makefile进行讲解。以下这个工程包含有3个头文件和8个C文件,其Makefile如下:

edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.ogcc -o edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.omain.o : main.c defs.hgcc -c main.c –o main.o

kbd.o : kbd.c defs.h command.hgcc -c kbd.c –o kbd.ocommand.o : command.c defs.h command.hgcc -c command.c –o command.odisplay.o : display.c defs.h buffer.hgcc -c display.c –o display.o

insert.o : insert.c defs.h buffer.hgcc -c insert.c –o insert.osearch.o : search.c defs.h buffer.hgcc -c search.c –o search.ofiles.o : files.c defs.h buffer.h command.hgcc -c files.c –o files.outils.o : utils.c defs.hgcc -c utils.c –o utils.oclean :rm edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.o

这里的反斜杠“\”是换行符的意思,用于增加Makefile的可读性。读者可以把这些内容保存在文件名为“Makefile”或“makefile”的文件中,然后在该目录下直接输入命令“make”就可以生成可执行文件“edit”。如果想要删除可执行文件和所有的中间目标文件,只需要简单地执行一下“make clean”即可。

在这个“makefile”中,目标文件(target)包含以下内容:可执行文件“edit”和中间目标文件“*.o”,依赖文件(dependency_file)就是冒号后面的那些“*.c”文件和“*.h”文件。

每一个“.o”文件都有一组依赖文件,而这些“.o”文件又是可执行文件“edit”的依赖文件。依赖关系表明目标文件是由哪些文件生成的。换言之,目标文件是由哪些文件更新的。在定义好依赖关系后,后面的一行命令定义了如何生成目标文件。请读者注意,这些命令都是以一个“Tab”键作为开头的。

值得注意的是,make工程管理器并不关心命令是如何工作的,它只负责执行用户事先定义好的命令。同时,make还会比较目标文件和依赖文件的最后修改日期,如果依赖文件的日期比目标文件的日期新,或者目标文件并不存在,那么,make就会执行后续定义的命令。

这里要说明一点,clean不是一个文件,它只不过是一个动作名称,也可称其为标签,不依赖于其他任何文件。若用户想要执行其后的命令,就要在 make 命令后显式地指出这个标签的名字。这个方法非常有用,通常用户可以在一个Makefile中定义一些和编译无关的命令,比如程序的打包、备份或删除等。

1.5.2 Makefile变量

为了进一步简化Makefile的编写和维护,make允许在Makefile中创建和使用变量。变量是在Makefile中定义的名字,用来代替一个文本字符串,该文本字符串称为该变量的值。变量的值可以用来代替目标体、依赖文件、命令以及Makefile文件中的其他部分。在Makefile中的变量定义有两种方式:一种是递归展开方式,另一种是简单扩展方式。

递归展开方式定义的变量是在引用该变量时进行替换的,即如果该变量包含了对其他变量的引用,则在引用该变量时一次性将内嵌的变量全部展开。虽然这种类型的变量能够很好地完成用户的指令,但是它也有严重的缺点,如不能在变量后追加内容,因为语句“CFLAGS =$(CFLAGS)–O”在变量扩展过程中可能导致无穷循环。

为了避免上述问题,简单扩展型变量的值在定义处展开,并且只展开一次,因此它不包含任何对其他变量的引用,从而消除了变量的嵌套引用。递归展开方式的定义格式为VAR=var。简单扩展方式的定义格式为VAR:=var。Make中的变量使用格式为$(VAR)。

变量名是不包括“:”,“#”,“=”、结尾空格的任何字符串。同时,变量名中包含字母、数字以及下划线以外的情况应尽量避免,因为它们可能在将来被赋予特别的含义。变量名是大小写敏感的,例如变量名“foo”、“FOO”和“Foo”代表不同的变量。推荐在Makefile内部使用小写字母作为变量名,预留大写字母作为控制隐含规则参数或用户重载命令选项参数的变量名。

在上面的例子中,先来看看edit这个规则。edit : main.o kbd.o command.o display.o \insert.o search.o files.o utils.ogcc -o edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.o

读者可以看到“.o”文件的字符串被重复了两次,如果在工程需要加入一个新的“.o”文件,那么用户需要在这两处分别加入(其实应该是有3处,另外一处在clean中)。当然,这个实例的Makefile并不复杂,所以在这两处分别添加也没有太多的工作量。但如果Makefile 变得复杂,用户就很有可能会忽略一个需要加入的地方,从而导致编译失败。所以,为了使Makefile易维护,推荐在Makefile中尽量使用变量这种形式。

这样,用户在这个实例中就可以按以下的方式来定义变量。OBJS = main.o kbd.o command.o display.o \insert.o search.o files.o utils.o这里是以递归展开的方式来进行定义的。在此之后,用户就可以很方便地在 Makefile 中以“$(objects)”的方式来使用这个变量了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容