【Make编译控制 02】Makefile语法基础

目录

一、Makefile概述

二、Makefile变量

三、Makefile符号


一、Makefile格式

1. 基本格式:

targets : prerequisties
[tab键]command
  • target:目标文件,可以是 OjectFile,也可以是执行文件,还可以是一个标签(Label)。
  • prerequisite:要生成那个 target 所需要的文件或是目标。
  • command:是 make 需要执行的命令。
# 可以自定义make命令,在系统命令前加 @ 会隐藏系统命令的打印

(base) [root@localhost 03_test]# vim makefile
(base) [root@localhost 03_test]# cat makefile 
debug:
        echo hello
(base) [root@localhost 03_test]# make debug
echo hello
hello
(base) [root@localhost 03_test]# vim makefile
(base) [root@localhost 03_test]# cat makefile 
debug:
        @echo hello
(base) [root@localhost 03_test]# make debug
hello
(base) [root@localhost 03_test]# vim makefile 
(base) [root@localhost 03_test]# cat makefile 
debug:
        @echo hello

test:
        @echo this is a test
(base) [root@localhost 03_test]# make test
this is a test
(base) [root@localhost 03_test]# 

2. Makefile规则:

  • make 会在当前目录下找到一个名字叫 Makefile 或 makefile 的文件
  • 如果找到,它会找文件中第一个目标文件(target),并把这个文件作为最终的目标文件
  • 如果 target 文件不存在,或是 target 文件依赖的 .o 文件(prerequities)的文件修改时间要比 target 这个文件新,就会执行后面所定义的命令 command 来生成 target 这个文件
  • 如果 target 依赖的 .o 文件(prerequisties)也存在,make 会在当前文件中找到 target 为 .o 文件的依赖性,如果找到,再根据那个规则生成 .o 文件

3. 伪目标

伪目标不是一个文件,只是一个标签。我们要显示地指明这个“目标”才能让其生效。

伪目标取名不能和文件名重名,否则不会执行命令。

为了避免 target 和 Makefile 同级目录下 文件/文件夹 重名的这种情况,我们可以使用一个特殊的标记 .PHONY 来显式地指明一个目标是 "伪目标",向 make 说明,不管是否有这个文件/文件夹,这个目标就是 "伪目标"。

.PHONY : clean

只要有这个声明,不管是否有 "clean" 文件/文件夹,要运行 "clean" 这个目标,只有"make clean" 这个命令。

二、Makefile变量

# 变量的定义,需要给初值

cpp := src/main.cpp
obj := objs/main.o
# 变量的引用,用()或{}

$(obj) : ${cpp}
    @g++ -c $(cpp) -o ${obj}

compile: $(obj)
# 预定义变量

$@ :目标(targe)的完整名称
$< :第一个依赖项(prerequisties)的名称
@^ :所有依赖项(prerequisties)的名称
(base) [root@localhost 04_test]# ls
makefile  objs  src
(base) [root@localhost 04_test]# ls src/
main.cpp
(base) [root@localhost 04_test]# ls objs/
(base) [root@localhost 04_test]# vim makefile 
(base) [root@localhost 04_test]# cat makefile 
cpp := src/main.cpp
obj := objs/main.o

$(obj) : $(cpp)
        g++ -c $(cpp) -o $(obj)

compile: $(obj)

debug:
        @echo $(cpp)
        @echo $(obj)

clean:
        rm -rf objs

.PHONY: debug clean
(base) [root@localhost 04_test]# make compile
g++ -c src/main.cpp -o objs/main.o
(base) [root@localhost 04_test]# ls objs/
main.o
(base) [root@localhost 04_test]# make debug
src/main.cpp
objs/main.o
(base) [root@localhost 04_test]# make clean
rm -rf objs
(base) [root@localhost 04_test]# ls
makefile  src
(base) [root@localhost 04_test]# 

三、Makefile符号

# 可变赋值符 =

(base) [root@localhost 05_test]# vim makefile 
(base) [root@localhost 05_test]# cat makefile 
HOST_ARCH   = aarch64
TARGET_ARCH = $(HOST_ARCH)

# ...
#
# ...

HOST_ARCH = amd64

debug:
        @echo ${TARGET_ARCH}
(base) [root@localhost 05_test]# make debug
amd64
(base) [root@localhost 05_test]#
# 立即赋值符 :=

(base) [root@localhost 05_test]# vim makefile 
(base) [root@localhost 05_test]# cat makefile 
HOST_ARCH   := aarch64
TARGET_ARCH := $(HOST_ARCH)

# ...
#
# ...

HOST_ARCH := amd64

debug:
        @echo ${TARGET_ARCH}
(base) [root@localhost 05_test]# make debug
aarch64
(base) [root@localhost 05_test]#
# 默认赋值符 ?=
# 若该变量已定义,则不做任何操作
# 若该变量未定义,则求值并分配

(base) [root@localhost 05_test]# vim makefile 
(base) [root@localhost 05_test]# cat makefile 
HOST_ARCH  = aarch64
HOST_ARCH ?= amd64
TARGET_ARCH ?= amd64

debug:
        @echo ${HOST_ARCH}
        @echo ${TARGET_ARCH}
(base) [root@localhost 05_test]# make debug
aarch64
amd64
(base) [root@localhost 05_test]#
# 累加 +=

(base) [root@localhost 05_test]# vim makefile 
(base) [root@localhost 05_test]# cat makefile 
include_path = /usr/include
CXXFLAGS := -m64 -fPIC -g -00 -std=c++11 -w -fopenmp
CXXFLAGS += $(include_path)

debug:
        @echo ${CXXFLAGS} 
(base) [root@localhost 05_test]# make debug
-m64 -fPIC -g -00 -std=c++11 -w -fopenmp /usr/include
(base) [root@localhost 05_test]#
# 续行符 /

(base) [root@localhost 05_test]# vim makefile 
(base) [root@localhost 05_test]# cat makefile 
LDLIBS := cudart opencv_core \
          gomp nvinfer protobuf cudnn pthread \
          cublas nvcaffe_parser nvinfer_plugin 

debug:
        @echo ${LDLIBS}
(base) [root@localhost 05_test]# make debug
cudart opencv_core gomp nvinfer protobuf cudnn pthread cublas nvcaffe_parser nvinfer_plugin
(base) [root@localhost 05_test]#
# 通配符 * %

# *: 通配符表示匹配任意字符串,可以用在目录名或文件名中
# %: 通配符表示匹配任意字符串,并将匹配到的字符串作为变量使用

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Makefile 是用于自动化编译程序的工具,它使用一种名为“规则”的方式来描述源文件和目标文件之间的依赖关系,然后根据这些规则自动编译程序。 Makefile 通常包括以下几个部分: 1. 变量定义:定义需要的变量,如编译器、编译选项等。 2. 目标文件:定义需要编译的目标文件、依赖文件和编译规则。 3. 伪目标:定义一些伪目标,如 clean、install 等。 下面是 Makefile语法: 1. 变量定义: 变量定义的语法格式为: ``` 变量名 = 变量值 ``` 例如: ``` CC = gcc CFLAGS = -Wall -O2 ``` 2. 目标文件: 目标文件的格式为: ``` 目标文件: 依赖文件 编译规则 ``` 例如: ``` main.o: main.c $(CC) $(CFLAGS) -c main.c -o main.o ``` 其中: - 目标文件是 main.o。 - 依赖文件是 main.c。 - 编译规则是 $(CC) $(CFLAGS) -c main.c -o main.o,表示使用 gcc 编译器和编译选项将 main.c 编译成 main.o。 3. 伪目标: 伪目标的格式为: ``` 伪目标: 命令 ``` 例如: ``` clean: rm -rf *.o ``` 其中: - 伪目标是 clean。 - 命令是 rm -rf *.o,表示删除所有的 .o 文件。 这些是 Makefile 的基本语法,你可以根据需要添加更多的规则来实现自动化编译。 ### 回答2: Makefile是用于自动化构建和管理软件项目的一种脚本语言,它描述了软件项目中的文件依赖关系和构建规则。Makefile文件通常包含一系列规则和命令。 Makefile的基本语法包括: 1.目标(Target):由一组规则组成,表示一个或多个文件的生成或操作。目标的命名可以是任意合法的文件名。 2.依赖(Prerequisites):目标所依赖的文件或目标。依赖可以是文件、目录或其他目标。当依赖发生变化时,相应的目标将重新生成。 3.命令(Command):规则中执行的命令。命令必须以Tab键开头,并且可以有多条。 4.规则(Rule):目标、依赖和命令的组合。规则表示了如何生成目标文件或执行一系列操作。 5.变量(Variables):用于存储常用的值或字符串,以便在Makefile中重复使用。变量以$符号开头,并用括号括起来。 6.条件判断(Conditionals):用于根据特定条件选择不同的规则或命令执行路径。条件判断以ifeq、ifneq等关键字开头。 7.循环(Loops):可以在Makefile中使用循环语句,例如foreach、while等,用于重复执行特定的操作。 Makefile的执行过程是根据文件的依赖关系来决定哪些目标需要重新生成。当执行make命令时,Makefile会被解析,并根据依赖关系构建目标文件,如果目标文件已经存在且依赖没有发生变化,则不会重新生成。 Makefile的优点是可以自动化构建过程、减少重复操作、提高项目的可维护性和可靠性。它可以根据项目的需要灵活定义构建规则,并自动处理文件间的依赖关系,大大简化了项目的管理工作和构建过程。 ### 回答3: makefile是一种用于构建和管理软件项目的工具,它使用明确的规则来指导编译和链接操作。它通常用于编译C/C++等编程语言的项目。 makefile的基本语法包含了规则、变量和命令。 规则是makefile的核心,它由目标、依赖和命令组成。目标是需要生成的文件,依赖是生成目标所依赖的文件或其他目标,命令是生成目标的具体操作。规则的格式如下: ``` 目标: 依赖 [tab] 命令 ``` 变量在makefile中用于保存常用的路径、编译选项等信息。可以通过变量的引用来简化makefile的书写和维护。变量的定义使用等号(=)来完成,如: ``` 变量名 = 值 ``` 命令是makefile中的具体操作步骤,用于生成目标。每条命令都必须以一个制表符(tab)开头,否则会被当作普通文本处理。 makefile还有一些常用的指令,如clean、all等。clean指令用于清理编译生成的目标文件和可执行文件,all指令用于编译所有文件。 makefile的优势在于可以自动判断哪些文件需要重新编译,从而提高了构建效率。它可以根据文件的修改时间和依赖关系来确定需要重新编译的文件,并只编译这些文件,避免了不必要的重复操作。 总之,makefile是一种强大的构建工具,它以简洁的语法和智能的依赖关系判断,能够实现高效的软件构建和管理。但需要注意的是,makefile语法在不同的平台和编译器上可能会有一些差异,需要根据具体情况进行调整和学习。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AllinTome

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

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

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

打赏作者

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

抵扣说明:

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

余额充值