Makefile入门详解-程序员宅基地

技术标签: Linux  makefile  嵌入式  

提示:以下是本篇文章正文内容,下面案例可供参考

一、Makefile简介

makefile主要使用在没有集成开发环境时,对工程文件进行自动化编译的工具。

makefile 的本质是一个文件,需要配合make指令进行自动化编译。

make是一个命令工具,用来解释makefile文件中的代码,从而实现自动化编译。编译使用的编译器本质上还是gcc。

makefile文件中定义了一系列的规则来指定, 哪些文件需要先编译, 哪些文件需要后编译, 哪些文件需要重新编译, 甚至于进行更复杂的功能操作。

makefile文件的命名:makefile或者Makefile。(也可通过其他方式,不使用这两个名字,通常我们使用这两个即可)

二、makefile 原理

基本原理:若想生成目标, 检查规则中的所有的依赖文件是否都存在。

1、当有依赖文件不存在

  1. 如果有的依赖文件不存在, 则向下搜索规则, 看是否有生成该依赖文件的规则:
  2. 如果有规则用来生成该依赖文件,则执行规则中的命令生成依赖文件;
  3. 如果没有规则用来生成该依赖文件, 则报错

也就是如下图所示:
在这里插入图片描述

2、当所有依赖文件存在

如果所有依赖都存在, 检查规则中的目标是否需要更新, 必须先检查它的所有依赖,依赖中有任何一个被更新, 则目标必须更新.(检查的规则是哪个时间大哪个最新)

如下图所示:
在这里插入图片描述

三、makefile基本规则

1.makefile规则三要素

  1. 目标: 要生成的目标文件
  2. 依赖: 目标文件由哪些文件生成
  3. 命令: 通过执行该命令由依赖文件生成目标

2.基本规则

规则如下:

目标:依赖
	命令		#注意命令需要以tab键开始
main:main.c test.c
	gcc main.c test.c -o main

3、makfile中的变量

makefile中使用变量有点类似于C语言中的宏定义, 使用该变量相当于内容替换, 使用变量可以使makefile易于维护, 修改起来变得简单。
makefile中有三种变量:

  1. 普通变量
  2. 自动变量
  3. 自带变量(不太了解)

3.1普通变量

变量定义是用 = 号即可,例如:

OBJS = main					//定义并赋值(通常不这样使用),会配合: 进行使用,后面会详解
$(OBJS)						//使用变量

3.2自动变量

自动变量主要有,如下所示:

  1. $@: 规则中的目标集合,在模式规则中,如果有多个目标的话,“ $@”表示匹配模式中定义的目标集合。
  2. $<:依赖文件集合中的第一个文件,如果依赖文件是以模式(即“ %” )定义的,那么“ $<”就是符合模式的一系列的文件集合
  3. $^:所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个重复的文件,会去除重复的依赖文件,只保留一份。
  4. $%:当目标是函数库的时候表示规则中的目标成员名,如果目标不是函数库文件,那么其值为空。
  5. $?:所有比目标新的依赖目标集合,以空格分开。
  6. $+:和“ $^”类似,但是当依赖文件存在重复的话不会去除重复的依赖文件。

3.3例程

CC := gcc #arm-linux-gnueabihf-gcc
TARGET := main
object := main.o test.o

.PHONY : clean

$(TARGET):$(object)
	$(CC) -o $@ $^
%.o:%.c
	$(CC) -o -c $@ $<
clean:
	rm main main.o test.o #rm main %.o

上面就是一个简单的makefile文件

4、makefile中的伪目标

Makefile 有一种特殊的目标——伪目标,一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令。

注意:使用伪目标的主要是为了避免 Makefile 中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突

上面例程中使用的伪目标clean,是用来清理编译产生的文件。

四、makefile其他常用的规则

  1. := :一个变量在定义并赋值后,不会使用后面给该变量赋值的值,只能使用前面已经定义好的
  2. ?= :如果该变量在前面没有被赋值,就给该变量赋值。如果赋值过了,就使用之前赋值的值
  3. += :需要给前面已经定义好的变量添加一些字符串进去,类似x +=1;
  4. %:类似通配符,例:%.c,也就是以 .c 结尾的所有文件
  5. \:是makefile中行的分隔符。

五、makefile中的函数

注意:此处只说下面综合例程中使用的函数和常用的函数

5.1函数 subst

函数作用:完成字符串的替换操作。
调用形式如下:

$(subst <from>,<to>,<text>)
#from:字符串中被替换的字符串
#to:替换的字符串
#text:字符串

#举例
$(subst aaa,AAA,aaabbb)
#也就是将字符串aaa替换成AAA,替换后字符串为AAAbbb

5.2函数 patsubst

函数作用:用来完成模式字符串替换
调用形式如下:

$(patsubst <pattern>,<replacement>,<text>)

$(patsubst %.c,%.o,a.c b.c c.c)
#将字符串“ a.c b.c c.c”中的所有符合“ %.c”的字符串,替换为“ %.o”,替换完成以后的字符串为“ a.o b.o c.o”

5.3函数 dir

函数作用: 用来获取目录
调用形式如下:

$(dir <names…>)

$(dir </src/a.c>)
#提取文件“ /src/a.c”的目录部分,也就是“ /src”

5.4函数 notdir

函数作用:除文件中的目录部分,提取文件名
调用形式如下:

$(notdir <names…>)

$(notdir </src/a.c>)
#提取文件“ /src/a.c”中的非目录部分,也就是文件名“ a.c”。

5.5函数 foreach

函数作用:函数用来完成循环
调用形式如下:

$(foreach <var>, <list>,<text>)
#把参数<list>中的单词逐一取出来放到参数<var>中,然后再执行<text>所包含的表达式。每次<text>都会返回一个字符串,循环的过程中,
# <text>中所包含的每个字符串会以空格隔开,最后当整个循环结束时, <text>所返回的每个字符串所组成的整个字符串将会是函数 foreach
# 函数的返回值。

5.6函数 wildcard

函数作用:通配符“ %”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,通配符不会自动展开,这个时候就要用到函数 wildcard
调用形式如下:

$(wildcard PATTERN…)

$(wildcard *.c)
#上面的代码是用来获取当前目录下所有的.c 文件,类似“%”

六、综合例程

CROSS_COMPILE	:=	arm-linux-gnueabihf-
TARGET		:=	bsp

CC 			:=	$(CROSS_COMPILE)gcc
LD			:=	$(CROSS_COMPILE)ld 
OBJCOPY		:=	$(CROSS_COMPILE)objcopy 
OBJDUMP		:=	$(CROSS_COMPILE)objdump

INCDIRS		:=	imx6ul	\
				bsp/clk		\
				bsp/delay	\
				bsp/LED

SRCDIRS		:=	project		\
				bsp/clk 	\
				bsp/delay	\
				bsp/LED 	


INCLUDE		:=	$(patsubst %, -I %, $(INCDIRS))

#SFILES		:= 	$(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
SFILES		:=	$(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES		:=	$(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

SFILENDIR	:=	$(notdir $(SFILES))
CFILENDIR	:=	$(notdir $(CFILES))

SOBJS		:=	$(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS		:=	$(patsubst %, obj/%, $(CFILENDIR:.c=.o))
OBJS		:=	$(SOBJS) $(COBJS)

VPATH		:=	 $(SRCDIRS)

.PHONY: clean

$(TARGET).bin : $(OBJS)
	$(LD)	-Timx6ul.lds	-o	$(TARGET).elf	$^
	$(OBJCOPY)	-O 	binary	-S	$(TARGET).elf	$@
	$(OBJDUMP)	-D	-m	arm	$(TARGET).elf	>	$(TARGET).dis

$(SOBJS) : obj/%.o : %.S
	$(CC)	-Wall	-nostdlib	-c	-O2		$(INCLUDE)	-o		$@ $<

$(COBJS) : obj/%.o : %.c
	$(CC)	-Wall	-nostdlib	-c	-O2		$(INCLUDE)	-o		$@ $<

clean:
	rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)

print :
		@echo	INCLUDE	 =	$(INCLUDE)
		@echo 	SFILES = $(SFILES)
		@echo 	CFILES = $(CFILES)
		@echo 	SFILENDIR	=	$(SFILENDIR)
		@echo	CFILENDIR	=	$(CFILENDIR)
		@echo	SOBJS	=	$(SOBJS)
		@echo	COBJS	=	$(COBJS)
		@echo	OBJS	=	$(OBJS)

例程中的makefile适用于大型工程管理,只需要添加源文件路径和头文件路径,不需要改动太多的makefile代码,即可实现工程代码的自动化编译。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_51363326/article/details/121127034

智能推荐

别弄丢自己-程序员宅基地

文章浏览阅读473次。《千与千寻》第一次上映是在2001年,已经过去了18年。那时,很多人年纪还小,未能从荧幕上看到这部电影,只是长大后通过网络,认识了千寻、白龙、无脸男…很多人说,自己最喜欢..._程序员吴小胖

Dynatrace系列之- 标记常见问题-程序员宅基地

文章浏览阅读885次。Dynatrace系列之- 标记常见问题在大型环境中,系统的某些方面可能会持续触发不必要的警报。这些告警可能来自非关键组件或者是非关键情况下的资源不足的问题。通常这些问题不需要人员响应。为了减少此类警报并避免发出垃圾告警邮件,Dynatrace AI根因分析引擎会自动检测那些经常发生但是并非重要的问题。Dynatrace通过观察指定期内(一天和一周)那些受监控实体的问题模型来检测此类频繁出现的问题。当在这些时间段内多次检测到同一问题时,Dynatrace会根据阈值突破的实际严重程度与问题的持续时间来评_dynatrace

SAS安装后处理错误的解决方法_sas安装后处理失败-程序员宅基地

文章浏览阅读6k次。当前面的过程都没有错误但到了最后一步的“安装后处理”错误时应检查系统时间是否已经改到当前下载的版本的有效期内。最后一步的“安装后处理”出现错误:如何检查当前下载的版本的有效期:找到SAS安装文件夹里的sid_files文件夹:并查看里面唯一的.txt文件:打开之后查看文件中的此处的两个时间节点,只要保证系统时间在这两个时间节点之间即可安装成功:后续如果还想在不更改时间的情况下正常使用SAS,可以参考下方博客,最新可以更新到2022年3月(亲测有效):https://blog.csdn.n_sas安装后处理失败

B/S与C/S区别_应用服务器运行数据负荷较重-程序员宅基地

文章浏览阅读1.3k次。一、什么是C/S和B/S 要想对“C/S”和“B/S”技术发展变化有所了解,首先必须搞清楚三个问题。第一、什么是C/S结构。 C/S(Client/Server)结构,即大家熟知的客户机和服务器结构。它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到 Client端和Server端来实现,降低了系统的通讯开销。目前大多数应_应用服务器运行数据负荷较重

计算机在使用一段时间后 无法启动系统,windows出现系统故障或无法启动的时候可以使用的6种解决方法...-程序员宅基地

文章浏览阅读1.4k次。很多时候我们会发现自己的系统问题越来越多,如果 将就使用,那系统运行效率肯定不会很高,甚至还无法正 常运行,如果选择重新安装系统,那不但麻烦不说,而且 还会耗费很长的等待时间。其实,当Windows系统一旦遇到无法启动或者运行出错的故障时,我们不妨使用下面的 六项措施,来快速而有效地“急救”受损的Windows系统, 说不定能收获奇效!1、最后一次配置Windows2000以上版本的操作系统,每次...

vscode配置Linux C++开发环境_vscode配置linux c++环境-程序员宅基地

文章浏览阅读6.4k次,点赞8次,收藏64次。vscode配置Linux C++开发环境本教程的对象主要是针对会c语言的基本使用,并且想在windows平台下进行Linux C++开发的同学。全过程简单来说就是通过vscode远程连接linux进行开发,并通过cmake来管理项目。个人感觉这算是目前比较好的方案了,vscode免费,并且远程开发的体验不错,Linux下的包管理系统也大大弥补了c++的缺陷。不过vscode的自动补全有点智障,跟visual studio的没法比,调试体验也差了点。另外visual studio也可以远程连接Lin_vscode配置linux c++环境

随便推点

51寻迹小车-程序员宅基地

文章浏览阅读1.6k次,点赞2次,收藏37次。集成了红外通信,超声波停车,寻迹,斑马线,迷宫的51单片机智能小车#include"reg51.h"#include "intrins.h"typedef unsigned int u16;typedef unsigned char u8; typedef unsigned long u32; sbit QIN1=P1^0;// P1.0输出pwmsbit QIN2=P1^1;// P1.1输出pwmsbit QIN3=P1^2;// P1.2输出pwmsbit QIN4=P

保研复习——线性代数4:向量空间-程序员宅基地

文章浏览阅读2.8k次,点赞10次,收藏21次。向量空间

计算机组成原理第六版 白中英 第四章 指令系统思维导图_计算机组成原理白中英第六版第四章-程序员宅基地

文章浏览阅读1.4k次,点赞4次,收藏8次。计算机组成原理第六版 白中英 第四章 指令系统的重点内容如果有需要源文件的可以去我的资源里面下载_计算机组成原理白中英第六版第四章

[求助] rhel8.0 8.1 8.5在线yum源安装报错Error: Transaction test error: file /etc/pki/rpm-gpg/RPM-GPG-KEY-red-程序员宅基地

文章浏览阅读347次。配置本地源安装没问题,,配置阿里云yum源后podman安装报错。_error: transaction test error: file /etc/pki/rpm-gpg/rpm-gpg-key-redhat-rele

linux拼音五笔输入法下载软件,万能五笔输入法-程序员宅基地

文章浏览阅读820次。下文是自已动手制造Linux下拼音五笔输入法,下面小编和大家一起看看自已动手制造Linux下拼音五笔输入法,希望对大家学习五笔有帮助。自已动手制造Linux下拼音五笔输入法这样就获得逆转换后的五笔的码表。三、兼并码表文件正在linux下用gedit辨别打开拼音码表文件winpyx.txt 及五笔码表文件 Wubi.txt,将winpyx.txt内的方式整合到Wubi.txt文件中。将winpyx...._万能五笔 linux

WebStorm上vue模板设置_webstorm 如何设置一个默认的vue模版-程序员宅基地

文章浏览阅读1.2k次。WebStorm上vue模板设置为了方便我们编写代码,我们有必要将经常写到的代码设置成模板,以加快代码编写效率以设置vue模板为例示范:方框中是我们需要设置的模板先选中这段代码复制然后打开文件设置之后点+号选择动态模板之后设置缩写和模板文本注意勾选格式化和定义就好啦以此为例 vue + tab就可以直接出现预设代码啦..._webstorm 如何设置一个默认的vue模版

推荐文章

热门文章

相关标签