Makefile初学

128 阅读2分钟

编译简单的Makefile

从hello world开始

go文件
package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}

执行命令

➜  golang git:(master) ✗ vim main.go
➜  golang git:(master) ✗ go build main.go
➜  golang git:(master) ✗ ./main
hello world!

如果重新执行make需要对源文件进行

编写Makefile并执行make

执行命令

➜  golang git:(master) ✗ vim Makefile
➜  golang git:(master) ✗ make 
go build main.go
➜  golang git:(master) ✗ ./main
hello world!

编写Makefile

#Makefile
main:main.go
        go build main.go
Makefile三要素

image.png

  • main:代表命令指向的目标
  • main.go 命令执行依赖的文件
  • go build main.go 命令

对main.go进行简单的修改

增加bar.go

package main

import "fmt"

type Rst struct {
    Name string
}

func NewRst(name string) *Rst {
    return &Rst{Name: name}
}

func (r *Rst) Hello() {
    fmt.Println("Hello, " + r.Name)
}

修改main.go

package main

func main() {
    rst := NewRst("小明")

    rst.Hello()
}

这样的话对应的Makefile也要修改

#Makefile
main:main.go bar.go
        go build main.go bar.go

如果修改或者增加文件都要对Makefile文件修改就太麻烦,这时候可以使用Makefile的wildcard 函数(wildcard function)来达到这一目的。

wildcard函数

Makefile函数的写法是:$(function arguments), wildcard函数的写法:$(wildcard pattern…)

修改后的Makefile:通配符*可以匹配任意长度的字符

#Makefile
main : $(wildcard *.go)
        go build $(wildcard *.go) 

修改main.go重新执行make

➜  golang git:(master) ✗ make
go build main.go bar.go 

变量

还可以用变量来提高效率,使用方法和go的 var:= value 赋值一样 变量的使用方法是$(var)

#Makefile
go_file := $(wildcard *.go) 
main : $(go_file)
        go build $(go_file)

常用变量

  • =:=的区别是这个符号在赋值的时候不在意声明变量的先后顺序,会优先展开调用的参数

    fo = a
    as = $(fo) b
    fo = aa
    

    这种情况as的值是aab,= 赋值的时候会根据最后的值决定,:= 会赋当前值

  • := 等同go的:=

  • += 等同go的+=

  • ?= 等同redis的SETNX命令,如果已赋值就不赋值,没有就赋当前值

froeach函数

foreach的函数意义和for循环相似$(foreach var,list,text),具体是循环从list中取数据,然后赋值给var,并且展开text

arr := ./model
arr += ./test
INCS := $(foreach dir,$(arr),$(dir)/*.go)

dir = ./model 展开 $(dir)/.go, INCS += ./model/.go

dir = ./test 同理

patsubst函数,

$(patsubst pattern,replacement,text)

字符串替换函数,匹配text中pattern模版部分,替换成replacement

arr := main.go

tmp := $(patsubst %.go,%_bak.go,$(arr))

%通配符的作用就是匹配以.go结尾的文字,成replacement的%就是%.go的%挪过来

伪目标

在Makefile中我们需要执行某些动作,比如清理缓存,可以定一个clean目标,执行make clean

tmp := ./tmp
clean:
    rm -r $(tmp)

go中这个方法很有用,go build可以指定编译地址,而且有go module管理依赖,不用担心依赖问题

终端输出

@指令

执行Makefile会把命令打印到终端中,这样看起来会比较杂乱,命令加上@会禁止输出到终端中

tmp := ./tmp
clean:
    @rm -r $(tmp)
echo

Makefile可以使用终端的指令集,所以可以用echo来自定义输出

tmp := ./tmp
clean:
    @echo trying
    @rm -r $(tmp)
    @echo complete