makefile快速开始(go项目makefile编写实战)

本文详细介绍了Makefile在Go项目中的应用,包括Makefile的基础语法、如何编写高质量的Makefile以及Go项目的Makefile实战。重点讲解了如何设置Go应用程序的版本信息,选择不同的JSON解析库,并使用ldflags进行编译选项设置。此外,还涵盖了Makefile中的伪目标、变量赋值、条件语句和常用函数,以及Makefile在项目管理和调试中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、makefile快速开始

1. 什么是makefile、make

Makefile是一个名为make软件所需要的脚本文件,该脚本文件可以指导make软件控制gcc等工具链去编译工程文件最终得到可执行文件,几乎所有的Linux发行版都内置了GNU-Make软件,VScode等多种IED也内置了Make程序。

你见到的xxx.mk文件或者Makefile都统称为Makefile脚本文件。大多数的make都支持“makefile”和“Makefile”这两种默认文件名称。

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

make是一个命令工具,它解释Makefile 中的指令。Makefile用来调用各种命令做自动化构建工具非常方便。

1.1 make命令 工作流程

  1. 读入所有的Makefile。
  2. 读入被include的其它Makefile。
  3. 初始化文件中的变量。
  4. 推导隐晦规则,并分析所有规则。
  5. 为所有的目标文件创建依赖关系链。
  6. 根据依赖关系,决定哪些目标要重新生成。
  7. 执行生成命令。

当我们在执行 make 条命令的时候,make 就会去当前文件下找要执行的编译规则,也就是 Makefile 文件。我们编写 Makefile 的时可以使用的文件的名称 “GNUmakefile” 、“makefile” 、“Makefile” ,make 执行时回去寻找 Makefile 文件,推荐使用Makefile。

1.2 关于程序的编译和链接

一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。

编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。

链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(LibraryFile),也就是 .lib文件,在UNIX下,是Archive File,也就是.a文件。

总结: 源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成Object File。而在链接程序时,链接器会在所有的Object File中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error)

2. 掌握 Makefile 常用语法基础

2.1 Makefile 规则语法

规则:用于说明如何生成一个或多个目标文件
规则的格式:

targets:prerequisites
    command
目标: 依赖
[tab键]命令
  • target 目标
    可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(伪目标)。

  • prerequisites
    生成该target所依赖的文件或target。生成目标所要依赖的文件,可能不止一个。

  • command
    该target要执行的命令(任意的shell命令)。生成目标所要执行的命令,注意所有的命令必须要以tab 键开头。

总结:target这一个或多个的目标文件依赖于prerequisites中的文件, 其生成规则定义在command中。

2.2 伪目标 | Makefile中.PHONY的作用

.PHONY(伪目标)

伪目标是这样一个目标:它不代表一个真正的文件名,在执行make时可以指定这个目标来执行所在规则定义的命令,有时也可以将一个伪目标称为标签。伪目标通过PHONY来指明。

如果我们指定的目标不是创建目标文件,而是使用makefile执行一些特定的命令,例如:

clean:
        rm *.o temp

我们希望,只要输入make clean后,rm *.o temp命令就会执行。但是,当前目录中存在一个和指定目标重名的文件时,例如clean文件,结果就不是我们想要的了。输入make clean后,rm *.o temp 命令一定不会被执行。

解决的办法:将目标clean定义成伪目标就成了。 无论当前目录下是否存在clean这个文件,输入make clean后,rm *.o temp命令都会被执行。

这种做法的带来的好处还不止此,它同时提高了make的执行效率,因为将clean定义成伪目标后,make的执行程序不会试图寻找clean的隐含规则。

举例如下:

clean:
	rm -rf $(CLEAN) $(BINS)
.PHONY: clean

2.3 变量赋值

Makefile变量的定义和使用
参考URL: http://c.biancheng.net/view/7096.html

变量的使用在我们的 Makefile 编写中还是非常广泛的,可以说我们的 Makefile 中必不可少的东西。

Makefile 的变量的四种基本赋值方式:

  • 简单赋值 ( := ) 编程语言中常规理解的赋值方式,只对当前语句的变量有效。
  • 递归赋值 ( = ) 赋值语句可能影响多个变量,所有目标变量相关的其他变量都受影响。
  • 条件赋值 ( ?= ) 如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。
  • 追加赋值 ( += ) 原变量用空格隔开的方式追加一个新值。
  1. 简单赋值
x:=foo
y:=$(x)b
x:=new
test:
        @echo "y=>$(y)"
        @echo "x=>$(x)"

:=与我们实际上更符合我们平时写代码的思维,也就是顺序声明变量,使用这种赋值方式,前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。
比较常用。

  1. 递归赋值
x=foo
y=$(x)b
x=new
test:
        @echo "y=>$(y)"
        @echo "x=>$(x)"

结果:

[root@centos7 ~]# make test
y=>newb
x=>new

使用= 需要注意2点:
1)这种赋值方式是有先后顺序的,后面的赋值会覆盖掉前面的赋值。因此这种赋值方式,比较好用。不太符合我们的书写逻辑。
2) 右侧中的变量不一定非要是已定义好的值,其也可以使用后面定义的值。

x = $(y)
y = hello
  1. 条件赋值
x:=foo
y:=$(x)b
x?=new
test:
        @echo "y=>$(y)"
        @echo "x=>$(x)"
  1. 追加赋值
x:=foo
y:=$(x)b
x?=new
test:
        @echo "y=>$(y)"
        @echo "x=>$(x)"
  1. 追加赋值

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

西京刀客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值