Makefile 保姆级使用教程

简介: Makefile 保姆级使用教程

Makefile 规则

一个简单的 Makefile 文件包含一系列的“规则”,其样式如下:

目标(target)…: 依赖(prerequiries)…

命令(command)


目标(target)通常是要生成的文件的名称,可以是可执行文件或OBJ文件, 也可以是一个执行的动作名称,诸如‘ clean ’。


依赖是用来产生目标的材料(比如源文件),一个目标经常有几个依赖。


命令是生成目标时执行的动作,一个规则可以含有几个命令,每个命令占一 行。


注意:


每个命令行前面必须是一个 Tab 字符,即命令行第一个字符是 Tab。这是容易出错的地方。


通常,如果一个依赖发生了变化,就需要规则调用命令以更新或创建目标。 但是并非所有的目标都有依赖,例如,目标“ clean ”的作用是清除文件,它 有依赖。


规则一般是用于解释怎样和何时重建目标。make 首先调用命令处理依赖, 进而才能创建或更新目标。当然,一个规则也可以是用于解释怎样和何时执行一 个动作,即打印提示信息。


一个 Makefile 文件可以包含规则以外的其他文本,但一个简单的 Makefile 文件仅仅需要包含规则。虽然真正的规则比这里展示的例子复杂,但格式是完全一样的

Makefile的使用介绍

在 Linux 中使用 make 命令来编译程序,特别是大程序

make 命令所执行的动作依赖于 Makefile 文件。最简单的 Makefile 文件如下:


将上述 4 行存为 Makefile 文件(注意必须以 Tab 键缩进第 2、4 行,不能以空格键缩进),放入 01_hello 目录下,然后直接执行 make 命令即可编译程序,执行 “make clean”即可清除编译出来的结果。


make 命令根据文件更新的时间戳来决定哪些文件需要重新编译,这使得可以避免编译已经编译过的、没有变化的程序,可以大大提高编译效率。


使用touch命令可以改变文件更新的时间


make 命令的使用

make 命令的使用:


执行 make 命令时,它会去当前目录下查找名为“Makefile”的文件,并根 据它的指示去执行操作,生成第一个目标。

我们可以使用“ -f ”选项指定文件,不再使用名为“Makefile”的文件,比 如:

我们可以使用“ -C ”选项指定目录,切换到其他目录里去,比如:

我们可以指定目标,不再默认生成第一个目标:

即时变量、延时变量介绍和使用

A = xxx // 延时变量


B ?= xxx // 延时变量,只有第一次定义时赋值才成功;如果曾定义过,此赋值无效


C := xxx // 立即变量


D += yyy // 如果 D 在前面是延时变量,那么现在它还是延时变量;// 如果 D 在前面是立即变量,那么现在它还是立即变量

例如:

使用make命令编译多个文件

%通配符

  • %.o:表示所用的.o文件%.
  • %.c:表示所有的.c文件

$@:表示目标

$<:表示第一个依赖文件  

$^:表示所有依赖文件

示例:

假想目标

我们的 Makefile 中有这样的目标:

clean:

       rm -f $(shell find -name "*.o")

       rm -f $(TARGET)

如果当前目录下恰好有名为“clean”的文件,那么执行“ make clean ”时它 就不会执行那些删除命令。


这时我们需要把“ clean ”这个目标,设置为“假想目标”,这样可以确保执行“ make clean ”时那些删除命令肯定可以得到执行。


使用下面的语句把“clean”设置为假想目标:

.PHONY : clean

示例:

常用函数

1.$(foreach var,list,text)

简单地说,就是 for each var in list, change it to text。对 list 中的每一个 元素,取出来赋给 var,然后把 var 改为 text 所描述的形式。

2.$(wildcard pattern)

pattern 所列出的文件是否存在,把存在的文件都列出来。


3.$(filter pattern...,text)

把 text 中符合 pattern 格式的内容,filter(过滤)出来、留下来。


4.$(filter-out pattern...,text)

把 text 中符合 pattern 格式的内容,filter-out(过滤)出来、扔掉。


5.$(patsubst pattern,replacement,text)

寻找' text '中符合格式' pattern '的字,用' replacement '替换它们。


' pattern '和' replacement '中可以使用通配符。

示例:

通用 Makefile 的设计思想

在 Makefile 文件中确定要编译的文件、目录,比如:

obj-y += main.o

“Makefile”文件总是被“Makefile.build”包含的。


在 Makefile.build 中设置编译规则,有 3 条编译规则:


1.怎么编译子目录? 进入子目录编译:

$(subdir-y):

       make -C $@ -f $(TOPDIR)/Makefile.build

2.怎么编译当前目录中的文件?

%.o : %.c

       $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -Wp,-MD,$(dep_file) -c -o $@ $<

3.当前目录下的.o 和子目录下的 built-in.o 要打包起来:

built-in.o : $(cur_objs) $(subdir_objs)

       $(LD) -r -o $@ $^

顶层 Makefile 中把顶层目录的 built-in.o 链接成 APP:

$(TARGET) : built-in.o

        $(CC) $(LDFLAGS) -o $(TARGET) built-in.o

示例:


本程序的Makefile分为3类:

1. 顶层目录的Makefile

2. 顶层目录的Makefile.build

3. 各级子目录的Makefile


一、各级子目录的Makefile:

  它最简单,形式如下:


EXTRA_CFLAGS  :=

CFLAGS_file.o :=


obj-y += file.o

obj-y += subdir/



  "obj-y += file.o"  表示把当前目录下的file.c编进程序里,

  "obj-y += subdir/" 表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。

  "EXTRA_CFLAGS",    它给当前目录下的所有文件(不含其下的子目录)设置额外的编译选项, 可以不设置

  "CFLAGS_xxx.o",    它给当前目录下的xxx.c设置它自己的编译选项, 可以不设置


注意:

1. "subdir/"中的斜杠"/"不可省略

2. 顶层Makefile中的CFLAGS在编译任意一个.c文件时都会使用

3. CFLAGS  EXTRA_CFLAGS  CFLAGS_xxx.o 三者组成xxx.c的编译选项


二、顶层目录的Makefile:

  它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外,

  主要是定义工具链前缀CROSS_COMPILE,

  定义编译参数CFLAGS,

  定义链接参数LDFLAGS,

  这些参数就是文件中用export导出的各变量。


三、顶层目录的Makefile.build:

  这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o


四、怎么使用这套Makefile:

1.把顶层Makefile, Makefile.build放入程序的顶层目录

  在各自子目录创建一个空白的Makefile


2.确定编译哪些源文件

  修改顶层目录和各自子目录Makefile的obj-y :

   obj-y += xxx.o

   obj-y += yyy/

   这表示要编译当前目录下的xxx.c, 要编译当前目录下的yyy子目录    


3. 确定编译选项、链接选项

  修改顶层目录Makefile的CFLAGS,这是编译所有.c文件时都要用的编译选项;

  修改顶层目录Makefile的LDFLAGS,这是链接最后的应用程序时的链接选项;

 

  修改各自子目录下的Makefile:

  "EXTRA_CFLAGS",    它给当前目录下的所有文件(不含其下的子目录)设置额外的编译选项, 可以不设置

  "CFLAGS_xxx.o",    它给当前目录下的xxx.c设置它自己的编译选项, 可以不设置

 

4. 使用哪个编译器?

  修改顶层目录Makefile的CROSS_COMPILE, 用来指定工具链的前缀(比如arm-linux-)

 

5. 确定应用程序的名字:

  修改顶层目录Makefile的TARGET, 这是用来指定编译出来的程序的名字


6. 执行"make"来编译,执行"make clean"来清除,执行"make distclean"来彻底清除

相关文章
|
编译器 Linux 调度
makfile的编译选项:CFLAGS、CPPFLAGS、LDFLAGS、LIBS
makfile的编译选项:CFLAGS、CPPFLAGS、LDFLAGS、LIBS
2766 0
|
存储 安全 Linux
|
算法 Linux API
【Linux系统编程】Linux下删除文件的 API方式以及文件删除机制差异
【Linux系统编程】Linux下删除文件的 API方式以及文件删除机制差异
370 0
|
前端开发 数据可视化 Java
程序员最喜欢用的 8 种代码对比工具,值得收入囊中
程序员最喜欢用的 8 种代码对比工具,值得收入囊中
1233 0
|
Ubuntu Linux C++
Ubuntu20.4配置arm交叉编译环境
我是在虚拟机中配置的,如果你的嵌入式设备足够完成自己的编译,可以不考虑虚拟机的。
1397 0
|
存储 Shell Linux
【Shell 命令集合 系统设置 】⭐ Linux 取消或删除已设置的环境变量 unset命令 使用指南
【Shell 命令集合 系统设置 】⭐ Linux 取消或删除已设置的环境变量 unset命令 使用指南
697 0
|
11月前
|
数据采集
使用 Puppeteer 绕过 Captcha:实现商家数据自动化采集
本文介绍了如何使用Puppeteer结合代理IP和用户伪装技术,轻松绕过大众点评的Captcha验证,实现商家信息的高效采集。通过配置Puppeteer、设置代理和用户伪装参数、模拟人类操作等步骤,成功提取了目标页面的数据。该方法不仅提高了爬虫的稳定性和隐蔽性,还为市场研究和商业分析提供了有力支持。注意,数据采集需遵守法律法规及网站政策。
308 1
使用 Puppeteer 绕过 Captcha:实现商家数据自动化采集
|
11月前
|
数据采集 存储 监控
实现自动化数据抓取:使用Node.js操控鼠标点击与位置坐标
本文介绍了如何使用Node.js和Puppeteer实现自动化数据抓取,特别是针对新闻网站“澎湃新闻”。通过设置代理IP、User-Agent和Cookie,提高爬虫的效率和隐蔽性,避免被网站封锁。代码示例展示了如何模拟鼠标点击、键盘输入等操作,抓取并整理新闻数据,适用于需要规避IP限制和突破频率限制的场景。
455 10
|
安全 关系型数据库 数据库
阿里云RDS PostgreSQL版支持 PG17,还不来体验?
PostgreSQL被誉为最先进的开源数据库,具有强大的扩展性和灵活架构。9月26日,社区官方正式发布了PostgreSQL 17.0版本,在性能、逻辑复制、开发者体验等方面进行了优化。阿里云RDS PostgreSQL 版已支持 PostgreSQL 17.0,并在社区17.0基础上,进行了安全、成本、可运维性等多方面提升,增加多种内核特性及插件特性。
|
安全 Linux 网络安全
【工具使用】几款优秀的SSH连接客户端软件工具推荐FinalShell、Xshell、MobaXterm、OpenSSH、PUTTY、Terminus、mRemoteNG、Terminals等
【工具使用】几款优秀的SSH连接客户端软件工具推荐FinalShell、Xshell、MobaXterm、OpenSSH、PUTTY、Terminus、mRemoteNG、Terminals等
117699 0