Elfboard-ELF开发板 Linux学习笔记(七)—— Makefile基本语法学习

本文详细介绍了Makefile的基本结构,包括目标和依赖关系、变量定义(递归、简单和条件赋值)、系统变量(如编译器选项)、条件表达式以及不同写法的Makefile实例。对于Linux开发人员来说,掌握Makefile的这些基础知识至关重要。
摘要由CSDN通过智能技术生成

Elfboard-ELF开发板 Linux学习笔记(七)—— Makefile基本语法学习

Makefile 文件不仅存在于源码根目录下,在其他的子目录下也基本都有 Makefile 文件。在执行编译时,Make 工具会解析根目录下 Makefile 文件进行编译,而根目录的 Makefile 会调用子目录下的 Makefile,子目录下又有子目录,层层调用。Makefile 需要按照一定的格式语法规则进行书写。如果你是做 Linux 应用开发的人员,那么写 Makefile 就是必备技能,就需要深谙 Makefile 语法规则。对于我们 Linux 平台初级开发人员,很少需要我们去写一个复杂的 Makefile 文件,只是在做平台移植的时候可能需要去简单修改或者阅读 Makefile 文件,所以呢,下面我们就简单了解一下 Makefile 基本格式规则。

一、目标和依赖

目标就是我们需要生成的文件,依赖就是生成目标文件所需要的其他文件,称为依赖文件。
基本语法规则:

targets(目标):dependent_files(依赖文件)
    command(执行的命令)
#示例:
app:app.o fun1.o fun2.o
    gcc -o app app.o fun1.o fun2.o
app.o:app.c
    gcc -c app.c
fun1.o:fun1.c fun1.h
    gcc -c fun1.c
fun2.o:fun2.c fun2.h
    gcc -c fun2.c
clean:
    rm -rf *.o app

第一行:通过app.o fun1.o fun2.o依赖文件连接为目标文件
第二行:通过依赖文件app.c编译为目标文件
下面几行亦是如此
正常情况下不运行clean除非执行 make clean

二、变量定义

1.递归赋值

变量的名称 = 变量值
变量的值将会是整个 Makefile 中最后被指定的值。

2.简单赋值

变量的名称 := 变量值
变量的值决定于它在 Makefile 中的位置,而不是整个 Makefile 展开后最终的值。

3.条件赋值

变量的名称 ?= 变量值
如果变量未定义,则使用该变量值定义变量。如果该变量已经被定义赋值,则该赋值语句无效,使用原有值.

    a ?= 123
    b ?= $(a) string
    a ?= 678
    target:
        @echo "a = $(a)"
        @echo "b = $(b)"

    # a = 123
    # b = 123 string

4.追加赋值

变量的名称 += 变量值

a := 123
b := $(a) string
a += $(b)
target:
    @echo "a = $(a)"
    @echo "b = $(b)"
# a = 123 123 string
# b = 123 string

三、系统变量——环境变量及默认值

系统变量或者叫环境变量,包含了常见编译器、汇编器的名称及其编译选项,我们在编译之前使用 . /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi 主要就是设置这些系统环境变量的值。
下面列出常见的系统变量及其部分默认值

    AR:库文件维护程序的名称,默认值为 ar;
    AS:汇编程序的名称,默认值为 as;
    CC:C 编译器的名称,默认值为 cc;
    CPP:C 预编译器的名称,默认值为$(CC) –E;
    CXX:C++编译器的名称,默认值为 g++;
    FC:FORTRAN 编译器的名称,默认值为 f77;
    RM:文件删除程序的名称,默认值为 rm –f;
    ARFLAGS:库文件维护程序的选项,无默认值;
    ASFLAGS:汇编程序的选项,无默认值;
    CFLAGS:C 编译器的选项,无默认值;
    CPPFLAGS:C 预编译的选项,无默认值;
    CXXFLAGS:C++编译器的选项,无默认值;
    FFLAGS:FORTRAN 编译器的选项,无默认值;

四、条件表达式语法

1.比较两个值是否相等

比较 arg1 和 arg2 值是否相同,如果相同则执行 text-if-true,否则执行 text-if-false。

2.比较某值是否为空

判断 variable 是否为空,如果非空则为真,执行 text-if-true,否则执行 text-if-false。

五、Makefile文件写法

1.写法一

test : main.c sub.c sub.h
    gcc -o test main.c sub.c
#第一行     test目标文件依赖main.c sub.c sub.h
#第二行     编译链接main.c sub.c文件到test

2.写法二——不支持检测头文件

test : main.o sub.o
    gcc -o test main.o sub.o
main.o : main.c
    gcc -c -o main.o main.c
sub.o : sub.c
    gcc -c -o sub.o sub.c
clean:
    rm *.o test -f

3.写法三——不支持检测头文件

test : main.o sub.o
    gcc -o test main.o sub.o
%.o : %.c
    gcc -c -o $@ $<
clean:
    rm *.o test -f

4.写法四——支持检测头文件(但是需要手工添加头文件规则)

test : main.o sub.o
    gcc -o test main.o sub.o
%.o : %.c
    gcc -c -o $@ $<
sub.o : sub.h
clean:
    rm *.o test -f

5.写法五——支持自动检测头文件

objs := main.o sub.o
test : $(objs)
    gcc -o test $^

# 需要判断是否存在依赖文件
# .main.o.d .sub.o.d
dep_files := $(foreach f, $(objs), .$(f).d)
dep_files := $(wildcard $(dep_files))
# 把依赖文件包含进来
ifneq ($(dep_files),)
    include $(dep_files)
endif
%.o : %.c
    gcc -Wp,-MD,.$@.d -c -o $@ $<
clean:
    rm *.o test -f
distclean:
    rm $(dep_files) *.o test -f

五、解释Makefile文档

#   File: Makefile
src := $(shell ls *.c)
objs := $(patsubst %.c,%.o,$(src))

test: $(objs)
    gcc -o $@ $^
%.o:%.c
    gcc -c -o $@ $<
clean:
    rm -f test *.o

上述 Makefile 中 @ 、 @、 @^、 < 称为自动变量。 <称为自动变量。 <称为自动变量。@表示规则的目标文件名; 表 示所有依赖的名字,名字之间用空格隔开; ^表示所有依赖的名字,名字之间用空格隔开; 示所有依赖的名字,名字之间用空格隔开;<表示第一个依赖的文件名。‘%’是通配符,它和一个字符串中任意个数的字符相匹配。
第一行 src 变量的值为‘main.c sub.c’。
第二行 objs 变量的值为‘main.o sub.o’,是 src 变量经过 patsubst 函数处理后得到的。

  • 45
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君逸~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值