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

发布时间:2024年01月20日

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 函数处理后得到的。

文章来源:https://blog.csdn.net/qq_52952281/article/details/135637491
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。