美文网首页
Makefile简介

Makefile简介

作者: jrglinux | 来源:发表于2021-04-01 14:19 被阅读0次

Makefile基础

一、Makefile是什么

(1)目标文件依赖哪些文件?
(2)依赖的文件是否更新?
make 和makefile 并不是用来编译程序的,它只负责找出哪些文件有变化,并且根据依赖关系找出受影响的文件,然后执行事先在makefile 中定义好的命令规则。
因为make 就是在shell 下执行的,所以在makefile 中,位于命令规则里的那些命令,都是shell 命令。

二、Makefile基本语法

目标文件:依赖文件
[Tab键]命令
(1)目标文件是指此规则中想要生成的文件,可以是.o 结尾的目标文件,也可以是可执行文件,也可以是个伪目标,后面会介绍伪目标。
(2)依赖文件是指要生成此规则中的目标文件,需要哪些文件。通常依赖文件不是1 个,所以此处是个依赖文件的列表。
(3)命令是指此规则中要执行的动作,这些动作是指各种shell 命令。命令可以有多个,但一个命令要单独占用一行,在行首必须以Tab 开头。这是make 规定的用法,这样make 在解析到以Tab 开头的行时便知道这是要执行的命令

2.1 make 程序是怎样判断文件有过更新呢?

Linux 中,文件分为属性和数据两部分,每个文件有三种时间,分别用于记录与文件属性和文件数据相关的时间,这三个时间分别是atime、ctime、mtime。

时间 含义
atime access time 访问文件的时间,是读取就会改变,比如cat/less等命令访问文件就会更新atime,但ls查看文件不会更新atime
ctime change time 文件属性或数据修改时,就会被更新
mtime modify time 文件数据部分修改时,会被更新。如果mtime被更新,则ctime肯定也被更新了

make就是判断依赖文件和目标文件的mtime是否一致,如果依赖文件的mtime比目标文件的mtime新,则需要执行命令(命令不一定是编译命令,可以是任何shell命令)。比如如下这个makefile例子:

1:2
        @echo "2 is newer than 1"

然后新建两个文件1和2

# 首先touch 两个文件1和2,可以看到起mtime是一致的
[root@localhost test]# touch 1 2
[root@localhost test]# stat -c %y 1 2           #mtime一致
2021-03-31 23:11:32.926225333 -0400
2021-03-31 23:11:32.926225333 -0400
[root@localhost test]# make
make: '1' is up to date.                        #make命令并没有做什么
[root@localhost test]# vi 2                     #修改文件2的内容
[root@localhost test]# stat -c %y 1 2           #2的mtime要比1新了
2021-03-31 23:11:32.926225333 -0400
2021-03-31 23:11:56.588623644 -0400
[root@localhost test]# make                     #make执行了echo命令
2 is newer than 1

如果目标文件1的mtime新于依赖文件2会什么结果?

[root@localhost test]# vi 1                     #修改目标文件1的内容
[root@localhost test]# stat -c %y 1 2           #目标文件1的mtime新于依赖文件2
2021-03-31 23:13:56.341639459 -0400
2021-03-31 23:11:56.588623644 -0400
[root@localhost test]# make
make: '1' is up to date.

2.2 跳到目标处执行

如下makefile例子,当执行make时,执行完第一个目标后就退出了。

[root@localhost test]# cat Makefile
t1:1
        @echo "make t1"

t2:1
        @echo "make t2"

[root@localhost test]# make                 #执行完第一个目标就退出了
make t1

[root@localhost test]# make t2              #指定目标t2
make t2

[root@localhost test]# make t1              #指定目标t1
make t1

2.3 伪目标

通过上面的例子您看到了,规则中的命令并不总是被执行,有时候我们并不关心是否产生真实的目标文件,我们只希望make 不要考虑mtime,而是总能去执行一些命令。
对于这个需求还是有办法的,make 规定,当规则中不存在依赖文件时,这个目标文件名就称为—伪目标。

[root@localhost test]# cat Makefile
test:
        @echo "test ok"

[root@localhost test]# make
test ok

伪目标不能和真实目标文件同名,否则就失去伪目标的意义了,为了避免伪目标和真实目标文件同名的情况,可以用关键字“.PHONY”来修饰伪目标,格式为“.PHONY:伪目标名”,这样不管与伪目标同名的文件是否存在,make 照样执行伪目标处的命令。

通常需要显式用.PHONY 修饰伪目标的场合是删除编译过程中的.o 文件,这是为了避免因旧的.o 文件已存在而影响编译。如果您在Linux 下有过编译源码的经验,就会了解make clean 的作用了,通常clean就是伪目标,用来删除编译过程中的.o 文件。

怪不得clean和all同时存在也可以,因为执行完all就退出了,再执行make clean就只是clean清除

2.4 变量

makefile可以自定义变量,其也要一些系统定义好的变量。

[root@localhost test]# cat Makefile
all:
        @echo AR        :       $(AR)
        @echo AS        :       $(AS)
        @echo CC        :       $(CC)
        @echo CXX       :       $(CXX)
        @echo CPP       :       $(AR)
        @echo FC        :       $(FC)
        @echo GET       :       $(GET)
        @echo PC        :       $(PC)
        @echo MAKEINFO  :       $(MAKEINFO)
        @echo RM        :       $(RM)
        @echo TEX       :       $(TEX)
        @echo WEAVE     :       $(WEAVE)
        @echo YACC      :       $(YACC)
        @echo YACCR     :       $(YACCR)

        @echo ARFLAGS   :       $(ARFLGAS)
        @echo ASFLAGS   :       $(ASFLAGS)
        @echo CFLAGS    :       $(CFLAGS)
        @echo CXXFLAGS  :       $(CXXFLAGS)
        @echo CPPFLAGS  :       $(CPPFLAGS)
        @echo FFLAGS    :       $(FFLAGS)
        @echo LDFLAGS   :       $(LDFLAGS)
        @echo PFLAGS    :       $(PFLAGS)
        @echo YFLAGS    :       $(YFLAGS)
        
[root@localhost test]# make
AR : ar
AS : as
CC : cc
CXX : g++
CPP : ar
FC : f77
GET : get
PC : pc
MAKEINFO : makeinfo
RM : rm -f
TEX : tex
WEAVE : weave
YACC : yacc
YACCR :
ARFLAGS :
ASFLAGS :
CFLAGS :
CXXFLAGS :
CPPFLAGS :
FFLAGS :
LDFLAGS :
PFLAGS :
YFLAGS :
命令相关的变量名 含义 默认
AR 打包程序 ar
AS 汇编语言编译器 as
CC C语言编译器 cc
CXX C++语言编译器 g++
CPP C预处理器,默认是$(CC) -E gcc -E
FC Fortan的编译器和预处理器 f77
GET 从SCCS文件中提取文件程序 get
PC Pascal语言编译器 pc
MAKEINFO 将texinfo文件转换为info文件 makeinfo
RM 删除命令 rm -f
TEX 从TeX源文件中创建TexDVI文件的程序 tex
WEAVE 将Web转换为TeX的程序 weave
YACC 处理C程序的Yacc词法分析器 yacc
YACCR 处理Ratfor程序的Yacc词法分析器 yacc -r

参数相关的系统变量(列举部分),几乎都没有默认值

变量名 含义 默认
ARFLAGS 打包程序$(AR)的参数 rv
ASFLAGS 汇编语言编译器参数
CFLAGS C语言编译器参数
CXXFLAGS C++编译器参数
CPPFLAGS C预处理器参数
FFLAGS Fortan语言编译器参数
LDFLAGS 链接器参数
PFLAGS Pascal语言编译器参数
YFLAGS Yacc词法分析器参数

2.5 隐含规则

一行写不下,用 \进行换行。

注释,用#进行注释。

什么是隐含规则?对于一些使用频率非常高的规则,make 把它们当成是默认的,不需要显式地写出来,当用户未在makefile 中显式定义规则时,将默认使用隐含规则进行推导。

隐含规则只限于那些编译过程中基本固定的依赖关系,比如C 语言代码文件扩展名为.c,编译生成的目标文件扩展名是.o,这一般是一对一的。而一个可执行程序可能是由多个.o 文件共同链接生成的,所以,从可执行程序到.o 文件的关系有可能是一对多,这种不确定性无法使之成为隐含的规则。所以,对于C语言的依赖关系是:文件名.o 依赖于文件名.c,仅限于源文件生成.o 目标文件,不存在.o 文件生成可执行程序的隐含规则。

2.6 自动化变量

变量名 含义
$@ 规则中的目标文件名集合
$< 规则中依赖文件中的第一个文件
$^ 规则中所有依赖文件的集合
$? 规则中,所有比目标文件mtime更新的依赖文件集合

2.7 将每个.c文件生成对应的二进制

# File paths
SRC_DIR := .
BUILD_DIR := .
OBJ_DIR := $(BUILD_DIR)

# Compilation flags
CC := gcc
LD := gcc
CFLAGS := -Wall

# Files to be compiled
SRCS := $(wildcard $(SRC_DIR)/*.c)
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
BUILD := $(OBJS:$(OBJ_DIR)/%.o=$(BUILD_DIR)/%)

# Don't remove *.o files automatically
.SECONDARY: $(OBJS)

all: $(BUILD)

# Compile each *.c file as *.o files
# @mkdir -p $(OBJ_DIR)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
    @echo + CC $<
    @$(CC) $(CFLAGS) -c -o $@ $<

# Link each *.o file as executable files
# @mkdir -p $(BUILD_DIR)
$(BUILD_DIR)/%: $(OBJ_DIR)/%.o
    @echo + LD $@
    @$(LD) $(CFLAGS) -o $@ $<

.PHONY: all clean
clean:
    rm -rvf $(OBJS) $(BUILD)

参考:《操作系统真相还原》一书,网络博客

相关文章

  • Makefile简介

    Makefile是干嘛的? 就像dockerfile之于docker,makefile之于make.....mak...

  • Makefile简介

    Makefile基础 一、Makefile是什么 (1)目标文件依赖哪些文件?(2)依赖的文件是否更新?make ...

  • 要学好 C 语言 / C++ ,Makefile 可少不了

    一、Makefile 简介 1. Makefile 是什么? Makefile 通常指的是一个含有一系列命令(d...

  • Makefile

    1. Makefile 简介 Makefile 是和 make 命令一起配合使用的. 很多大型项目的编译都是通过 ...

  • 实践5 . Makefile文件编写

    1 简介 Makefile是用来完成构建,编译整个工程文件的工具。所以,Makefile定义了一系列的规则,按照这...

  • C++ Makefile简介

    //联系人:石虎QQ:1224614774昵称:嗡嘛呢叭咪哄 一、Makefile概述: 1.对很多Winodw...

  • 【转】GNU autotools(五)编写Makefile.am

    1. 简介 Makefile.am是比Makefile更高层次的规则,只需指定要生成什么目标,它由什么源文件生成,...

  • Makefile笔记

    Makefile 简介 makefile用来制定编译的规则及其其它更复杂的操作.并且能实现整个工程的自动化编译,提...

  • Makefile简易教程

    本文部分内容引用: 中文维基百科。 一个简单的Makefile教程。 Makefile简介 在软件开发中,make...

  • Makefile使用

    Makefile 简介 一个工程中的源文件不计其数,按其类型、功能、模块分别放在若干个目录中。makefile定义...

网友评论

      本文标题:Makefile简介

      本文链接:https://www.haomeiwen.com/subject/qunzhltx.html