Linux 中 make 命令的使用心得

2023-08-17 22:51:59 阅读:1015 评论:0 点赞:0
所属分类: Linux

make

make 是一个根据指定 Shell 命令进行构建的工具。

将代码变成可执行文件的操作叫做编译;先编译这个,还是先编译那个的顺序被称为构建。Make 是最常用的构建工具,诞生于 1977 年,主要用于C语言项目的构建,但只要某个文件由变化,需要重新构建,我们都可以用 Make 进行构建。

makefile

目标(Target)

makefilemake 构建时要执行的 shell 命令的集合,即构建规则写在这里面,每条规则形式如下:

<target>: <prerequisites>
[tab] <commands>

: 前面的 target 叫做目标,后面部分是由前置依赖项和命令部分构成;依赖项和命令部分都是可选项,但是必须存在一个。

注意

命令部分前面必须由 tab 建起首,然后后面紧跟着要执行的命令。

例如:

clean:
	rm *.txt

简而言之 target 就是 make 要执行的操作名称,是一个 “伪目标”,而上面的示例的作用就是删除当前目录下的所有 txt 文件。执行命令为:

make clean

注意

当我们执行构建命令时,若此时当前目录中存在构建目标同名的文件,例如 clean,那么 make 不会执行该目标后面的构建命令。

定义伪目标

为了避免上述情况我们可以声明对于的目标为 “伪目标”,声明语法如下:

.PHONY: clean
# 多个目标
.PHONY: cleanall cleanobj cleandiff

提示

我们执行 make 命令时,后面没有执行构建的目标,默认会构建第一个目标,所以通常我们将必须的放在第一个构建目标。

例如:

make && make install
# 第一个目标用来初始化,比如依赖项检查等前置操作
# install 目标则执行实际安装

前置依赖项

前置依赖项就是目标紧跟着的部分,通常是一组文件名,之间通过空格分隔。

构建触发条件

① 目标依赖项必须都存在,否则将无法构建
② 目标依赖项修改时间比目标新,则目标需要重新构建
③ 构建的目标已存在将不会重复构建(伪目标除外)

构建命令

构建命令用来表示如何构建目标,可以是一行或者多行,它是构建目标的具体指令。每一行命令必须是由 tab 符开头,可以通过内置变量 .RECIPREPREFIX 声明为其他符号作为起始符,例如:

.RECIPEPREFIX = >

all:
> echo Hello world

警告

每行指令相互独立,之间没有前后继承关系,即无法使用上一行指令的结果。

解决办法:
① 将多条命令写在同一行,用逗号分隔。
② 在命令行末尾换行符前加上 \ 转义。
③ 指定 .ONESHELL: 命令。

提示

#Makefile 中表示注释。

构建时 make 会打印每条构建的指令,然后再执行,即回声(echoing);若想要避免这种情况,可以在每条命令前面加上 @,就可以关闭回声。

test:
	# 这是测试
	@echo Hello

通配符

* 匹配所有
? 匹配当个字符
[...] 匹配所有以括号中某个字符开头的
% 模式匹配

变量

自定义变量

name = Stan
msg = Hello $(name)

test:
	@echo $(msg)

= 在执行时扩展,允许递归扩展
:= 在定义时扩展
?= 变量值为空时才赋值
+= 将值追加到变量的尾端

内置变量
Make命令提供一系列内置变量,比如,$(CC) 指向当前使用的编译器,$(MAKE) 指向当前使用的Make工具。

自动变量

变量 说明
$@ 当前目标
$< 第一个依赖项
$? 比当前目标新的依赖项
$^ 当前目标依赖项
$* 通配符 % 所匹配的内容
$(@D) 当前目标目录名
$(@F) 当前目标文件名
$(<D) 依赖项的目录名
$(<F) 依赖项的文件名

条件和循环

条件判断

ifeq ($(CC),gcc)
	libs=$(libs_for_gcc)
else
  libs=$(normal_libs)
endif

循环

LIST = one two three
all:
  for i in $(LIST); do \
    echo  $$i; \
  done
# 等同于
all:
  for i in one two three; do \
    echo $i; \
   done```

使用函数

用语法如下:

$(function arguments)
# 或者
${function arguments}

makefile 示例

SHELL := /bin/bash
BASEDIR = $(shell pwd)

.PHONY: help
help:
		@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: install
install: ## Install dependencies
		@go mod download
		@go mod vendor

.PHONY: dev
dev: ## Run with Dev
		@test -f conf/config.local.yml || cp conf/config.local.yml.example conf/config.local.yml
		@go run cmd/todomvc/todomvc.go

.PHONY: build
build: ## Build todomvc
		@go build -o build/todomvc cmd/todomvc/todomvc.go

clean: ### Remove build dir
		@rm -fr build
标签: make makefile

永不言弃

职业:后端开发工程师
学校:重庆师范大学
城市:重庆
文章:169
好吧,不知道说点什么...

登录逐梦笔记

注册逐梦笔记

已有账号?