Makefile之清晰认知

Makefile之清晰认知

关于Makefile,之前我在初学makefile依旧没有清晰认知。所以这次,我将着重探究一下Makefile文件的编写。

0.Makefile是什么

Makefile可以理解为一个脚本的执行器,也可以理解为一种简单语言

很多人觉得很神奇,包括我也是,第一次接触makefile,觉得这个东西非常神奇,为什么可以自动编译多文件?

我们可以简单理解为这个文件可以自动帮你执行一些命令,例如Python也可以帮你做运维,这个就类似于运维中的脚本文件

1.一般使用

# This is a standard makefile
main:main.o module1.o module2.o
    gcc main.o module1.o module2.o -o main
main.o:main.c head1.h head2.h common_head.h
    gcc -c main.c
module1.o:module1.c head1.h
    gcc -c module1.c
module2.o:module2.c head2.h
    gcc -c module2.c

结构为

[目标文件列表] [分隔符] [依赖文件列表]
    [命令]

这个Makefile的HelloWorld其实已经困扰了很多人。困扰的点如下:

1.为什么gcc编译的时候不需要加头文件?

答:gcc在编译的时候,只需要进行编译C文件。

h文件的作用仅起到替换的作用。我们在引入#include <stdlib.h>之后,在预编译的过程中,会将stdlib.h中的声明完全替换到本文件中。

误解:很多人会将#include以为是引入库,但实际不是,这个命令的作用是在预编译过程中将.h文件进行替换,真正要编译的是C文件。

证明:我们使用gcc -E main.c试一下,查看预编译后的文件,发现,头文件已经替换到了预编译后的文件中

编写一个max.h文件

int max(int a, int b);

编写一个main.c文件

#include <max.h>
int main() {
    return 0;
}

编写一个max.c文件

int max(int a, int b) {
    return a > b ? a : b;
}

在Linux下进行gcc -E main.c max.c,输出

# 1 "t.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 362 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "t.c" 2
# 1 "./max.h" 1
int max(int a, int b);
# 2 "t.c" 2
int main() {
    return 0;
}
# 1 "max.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 362 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "max.c" 2
int max(int a, int b) {
    return a > b ? a : b;
}

在预编译过程中,进行了文件替换,在#include语句完全替换成了h文件中的语句,而在文件末也附加了新的max.c,由此我们可以深刻理解这个过程

2.gcc -c是什么?

gcc -c 执行了3步操作

gcc -E进行预处理,gcc -S进行翻译汇编操作,gcc -c进行编译成链接文件(.o文件)

3.我们为什么需要倒着写?

问这个问题的人应该已经发现了,我们是需要倒着进行运行命令的,这个是makefile的规范。

如果熟悉如何用gcc在命令行进行编译多文件,那么直接进行倒着书写makefile即可。

makefile在进行寻找的过程中,首先执行第一行,发现需要下面模块,再执行下面的,所以看起来倒着,假设a依赖b,c,d三个独立模块,我们测试进行输出,答案是b,c,d,a,案例:

# This is a Makefile

main:main.o printXX.o printXXX.o
        gcc main.o printXX.o printXXX.o
        echo "a"
main.o:main.c printXX.h printXXX.h
        gcc -c main.c
        echo "b"
printXX.o:printXX.c printXX.h
        gcc -c printXX.c
        echo "c"
printXXX.o:printXXX.c printXXX.h
        gcc -c printXXX.c
        echo "d"
4.第二行报错?

实际上gcc前面那个空格是一个tab键,如果你按了2下空格,会使其报错。

如果你想简单实用makefile,了解到这边,其实已经能够清晰的编写makefile文件了。下面是附加性知识。

2.语法

1.变量的定义

我们在使用过程中,会使用到大量的gcc命令,而实际生产中,我们不一定会用gcc进行编译,常见的有cc,g++,都可以进行编译,如果要进行替换,整篇Makefile都得进行替换,那样会极其不便,所以,我们进行了一个变量替换操作。

我们来看一个例子:

CC = gcc
all:
    echo $(CC)

我们在头部进行了替换操作。

2.预定义变量

all:
        echo $(CC) $(CFLAGS) $(MAKE)

我们的cc含有很多预定义变量,如CC、CFLAGS等,我们可以编写一个这样的文件进行打印

预定义变量如下:

  • CC 默认的cc命令
  • CFLAGS -o执行
  • MAKE make命令的地址
  • MAKEFLAGS make的选项
  • SHELL 默认shell类型
  • PWD 当前makefile的目录
  • AR 库管理
  • ARFLAGS 库管理选项
  • LIBSUFFIXE 库后缀
  • A 库拓展名
3.动态改变的变量

我们在查看Makefile的时候,常常看到[email protected] $% $< $> $? $^ $+ $*

  • [email protected] 表示目标文件名,Linux中,一般称.a文件为文档文件,或者静态库文件。
main: a.c b.h
    gcc a.c

上述makefile的main就是目标文件名,如果我们在makefile中echo [email protected],则打印的是main

所以我们可以进行

main: a.c b.h
    gcc a.c -o %@
  • $% 静态库的第一个成员名,如果链接的第一个静态库是foo.a,则会打印出来,这边不加演示,都可进行echo打印
  • $< 第一个依赖库名
  • $> 值是库名(适用库文件)
  • $? 所有比目标新的依赖文件列表
  • $^ 规则的所有依赖列表,去除重复文件
  • $+ 可素$^ 保留重复文件
  • $* 目标去除后缀,例如 main.o 这个后缀去掉
4.条件语句
ifeq(gcc,$(CC))
    # 执行编译
else
    echo "error"
endif

条件语句可以根据条件进行编译

5.定义条件
ifdef foo
    echo "YES"
ifndef foo
    foo = foo

定义条件,判定是否定义

原文地址:https://www.cnblogs.com/littlepage/p/12325651.html

时间: 2024-08-15 12:53:56

Makefile之清晰认知的相关文章

清晰认知事物概念

李笑来在文章<快速学习的几个基本原则>中提到:“我们脑子里每个概念都需要清楚的定义,一切的 “聪明” 都源自于清楚.准确.必要的概念(及其定义).”第一次看到这句话时,我有一种醍醐灌顶的感觉,发现之前自己刻意对事物概念思考的动因被一语道破. 从小到大我们对周遭事物的认识每时每刻都在一层一层地扩大.小时候对基本事物的认知开始于各个不同的名词,比如玻璃球.橙子.自行车,后来加入形容词,则赋予了名词形象的不同,比如:圆圆的球,黄色的香蕉.彪悍的老虎等等,基于对基本图像的识别,如果加入情感体系,则可以

Makefile书写注意事项,个人择记

1 #sample Makefile 2 edit : main.o kbd.o command.o display.o 3 insert.o search.o files.o utils.o 4 cc -o edit main.o kbd.o command.o display.o 5 insert.o search.o files.o utils.o 6 main.o : main.c defs.h 7 cc -c main.c 8 kbd.o : kbd.c defs.h command.

从撞车看自动驾驶的人性底线

距离最近一起特斯拉自动驾驶出现事故事,已经过去一段时间,但关于自动驾驶汽车碰撞的话题却愈发引发人们思考.当两辆自动驾驶车即将相撞,各自系统该如何躲闪?若依照优先设定原则,优先保护乘客更多的A车?那么B车的人又何等无辜.人类的公平和不公平原则,在机器的二进制世界里变得那么"无情". 从实验室走向道路:自动驾驶已磨刀霍霍 人类创造新事物的出发点,往往是为了让生活变得更轻松,进而积沙成塔,彻底改变社会.历史发展进程.如果说汽车的出现让出行更为惬意,自动驾驶则是为了进一步解放车主的双手.在道路

在失败的滴滴出行LOGO上谈APP设计

有使用过打车APP的朋友都会清楚知道对滴滴出行新一轮的LOGO第一反应,最突出的特点就是山寨,除了这个就没有一点其他的味道了.12年起家的滴滴打车,LOGO换了三次脸,每一次换脸到现在,基本都不知道成啥样了?之前的滴滴LOGO起码是一个“TAXT”的实像图,还可以让人有一个比较实体的理解,起码知道是做出租车类的产品:而经过最新一轮的改变,虽然可以很好的体现“微笑出行”的效果,更大程度化发挥企业的文化,但是这也要必须建立在别人知道这是一个代表什么产品的APP上吧! 一个好的APP图标有多重要? 作

学习的节奏-知识点回归性学习

定位到点.点.点线面. 手不要懒惰,留下痕迹.用痕迹结点.(结: 动词 打节) 每天只进步一点点. 记录简洁. 两个不同阶段的学习: 学习阶段: 从细节到整体的人是 梳理: 从整体到细节回顾  难度系数取决于学习阶段 练习要清晰的会这个知识!.. .. .. 练习的效果 如果对知识不清晰认知,不能有练习效果. 作用: 依靠练习是不够的!练习是为了清晰基础上的灵活.  知识补遗,反映了哪些不足?错题的归因归到知识点上 哪里的问题. 定位到知识点! 反省. 一年的差不多就是差很多.稀里糊涂的.只有反

男人的狼性

早上地铁上看到一篇鸡汤文,男人的狼性你有多少,读着挺有道理,就放到园子里,不时警醒下自己. 1. 男人可以虚怀若谷,可以低调行事,可以沉默寡言,但绝对不可没有自信. 前面二个都是褒义词,不知鸡汤主为何要放在转折前面,自信是男人面对人生难题的支撑,相信自己,不断的从小的成功中累积自信心.鸡汤中一点,我并不认同,“女人要懂得保护男人的自信”,自信不是靠谁给予或者保护的,自信,自信是自己的信任,是内心散发出来他人可感知的一种霸气. 2. 男人可以不辉煌,可以不成功,但绝对不可没有事业心. 事业成不成,

禅修笔记——硅谷最受欢迎的情商课

禅修笔记--硅谷最受欢迎的情商课 作者 宁秋风 关注 2016.01.25 21:48* 字数 4921 阅读 1008评论 7喜欢 23 Search Inside Yourself 如何发展情商? 1 什么是情商? 情商是一种能够觉知自己和他人的情绪和情感,能够辨识出这些情绪和情感并使用这些信息来指导一个人的想法和行为的能力. 情商的五个方面 自我觉知:对个人内在的状态.喜好.资源和直觉的认识 自我调节:对个人内在的状态.冲动和资源的管理. 自我激励:引导或者促进达到目标的情感倾向. 同理心

抽屉式导航可能减少产品一半的用户參与度

设想你须要设计一个含有很多页面和模块,不能在一屏内显示全然的应用.你一定会首先想到去设计一个底部或顶部的Tab导航. 等一下.多出来的一排导航看上去有点碍眼? 我们尝试下把他们收到側边栏里.或者叫安卓团队给它的名字"側边抽屉导航". 假设你们的应用的也是多视图的,在你们的团队里,下面话题一定经常引发激烈讨论: 是把导航选项都显示在屏幕上,让你们的用户能够清晰认知app结构,并避免多余操作才干发现;还是使用側导航让主屏的显示区域更大些. 眼下,側导航在安卓设备上比較流行,而iOS平台上使

抽屉式导航可能降低产品一半的用户参与度

设想你需要设计一个含有许多页面和模块,不能在一屏内显示完全的应用.你一定会首先想到去设计一个底部或顶部的Tab导航.等一下,多出来的一排导航看上去有点碍眼?我们尝试下把他们收到侧边栏里,或者叫安卓团队给它的名字"侧边抽屉导航". 如果你们的应用的也是多视图的,在你们的团队里,以下话题一定常常引发激烈讨论: 是把导航选项都显示在屏幕上,让你们的用户可以清晰认知app结构,并避免多余操作才能发现;还是使用侧导航让主屏的显示区域更大些. 目前,侧导航在安卓设备上比较流行,而iOS平台上使用的