Makefile 基础知识(一)

什么是Makefile

工程编译规则,用于描述如何将代码变为可执行文件的过程

  1. 哪些文件需要编译,如何编译
  2. 需要那些类库,怎么获取这些类库
  3. 如何将上面的东西变成可执行文件
常用基本格式
<标签 target>:	<依赖项>
	<command shell 命令>

待编译的main.go文件

package main

import "fmt"

func main() {
	fmt.Println("Makefile")
}

Makefile 文件

build: main.go
  # 如果不想在命令行显示该命令,在其前面加@即可
  # @go build main.go
	go build main.go

编译

# make 也行 会默认执行第一个标签
make build

image.png

伪目标
  1. 伪目标即说明其command不会生成任何文件
  2. 使用.PHONY标记伪目标
  3. 伪目标每次都会执行

下面是一个正常的目标,其目的是生成main 可执行文件,在执行make build 时会验证 依赖项 main.go 是否是target,如果是target 则执行,是外部文件,则检查外部文件是否存在,存在则执行 command

build: main.go
# 如果不想在命令行显示该命令,在其前面加@即可
# @go build main.go
go build main.go

依赖不仅仅可以是外部文件,也可以是Makefile中的其它 target

build: net 
	go build main.go
net:
	go build net.go

main.go

package main

import "fmt"

func main() {
	fmt.Println("Makefile")
}

net.go

package main

import "fmt"

func main() {
	fmt.Println("net")
}

编译,发现没有,执行两次make build, go build net.go 就执行了一次。先明确一点,依赖项是先从内部target找起的,内部没有才找外部的。
第一次执行make build, 找到 net target,发现外部没有 net可执行文件,执行 net command (go build net.go) 构建 net可执行文件
第二次执行 make build, 找到 net target, 发现外部有net可执行文件,对比外部 net可执行文件 和 net target 的关系(由于net target 没有依赖项,就会认为外部 net 可执行文件 就是由 net target 生成的),所以认为可以复用,就不会执行 go build net.go

image.png

如果 net target 也有外部依赖 net.go,那么会变为根据 net.go是否修改来决定是否执行 command
image.png
修改 net.gomake build
image.png

下面我们违背伪目标的含义,将 net target设置成 伪目标,由于设置成伪目标所以每次都执行 go build net.go 因为和外部对比时,发现比对的目标是伪目标, 伪目标的含义是什么: 不会生成任何文件,那么就一定不会复用,故此,一定会执行 go build net.go

build: net
	go build main.go
.PHONY: net # 其实违背了伪目标的含义,其实生成了net
net:  net.go
	go build net.go

image.png

指定文件名

执行make,会在当前目录下去找 makefile 或 Makefile 文件,如果是别的文件需要通过-f 指定
将Makefile 改为 abc

build: main.go
	go build main.go

image.png

忽略command错误

通常运行command出错会终止后续 target 运行,但可以使用 - 忽略错误,保证运行完毕

由于没有abc,所以 make build 不会执行 go build main.go
Makefile

build: clean
	go build main.go
.PHONY: clean
clean:
	rm abc

image.png

使用 -忽略错误可以继续执行
Makefile

build: clean
	go build main.go
.PHONY: clean
clean:
	- rm abc

image.png

多command

多个command分行写,每一行前加一个tab
Makefile

build: 
	go build main.go
	go build net.go

image.png
如果有关联关系,可以写在一行中,通过 ; 来分割
Makefile

build:
	- set -e; rm abc; mkdir c
	- rm abc; mkdir d

由于 abc 不存在,rm abc 一定会报错,由于 第一行 有 set -e 遇到错误后不再执行后续的,所以 mkdir c 不会执行,而 写在第二行,就和第一行的 set -e 没有关联,所以遇到错误,还是会执行后面的语句 mkdir d
image.png

order-only 依赖

格式: 依赖 | order-only
下面的Makefile第一次构建完后,再 执行 make net,是不会重新构建的,除非 net.go 或者 work.go 修改

build: net
	go build main.go
net: net.go work.go
	go build net.go
	go build work.go

如果想只有 net.go 改变时才重新构建,那么可以使用 order-only 依赖
将 work.go 作为 order-only 依赖,修改 work.go 并不会重新构建

build: net
	go build main.go
net: net.go | work.go
	go build net.go
	go build work.go

image.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值