Makefile知识点备忘
1 Makefile步骤
1.edit (vi)
2.编译 (gcc)
3.项目project (make)
4.setup打包发布 (make)
例如:
1.makedemo文件夹下有3个c文件:func1.c func2.c main.c ,main.c中使用了2个函数分别位于func1.c func2.c中,
2.gcc main.c func1.c func2.c -o mainwork 。
3.执行./mainwork 2 5,则传入参数2 5,并打印结果。
2 Makefile作用(工程文件组织,编译成复杂的程序 | 安装以及卸载程序)
2.1 标题Makefile中rule格式:
targets(目标):prerequisites(依赖)
command(命令)
2.2 vi一个Makefile,最终是生成第一条rule包含的文件,递归的去调用rule下面的指令
#creat first rule
mainwork1:main.o func1.o func2.o
gcc main.o func1.o func2.o -o mainwork
main.o:main.c
gcc -c main.c
func1.o:func1.c
gcc -c func1.c
func2.o:func2.c
gcc -c func2.c
-
源文件:
main.c func1.c func2.c Makefile -
make之后目录所包含文件:
main.c main.o func1.c func1.o func2.c func2.o mainwork(可执行文件) Makefile -
若删除mainwork之后,并未修改源文件,再执行make命令,不会再次重新编译,而是直接生成可执行文件mainwork
2.2 make clean 指令
若想删除垃圾文件(伪目标文件):则在Makefile后面自己编写rule
#creat first rule
mainwork1:main.o func1.o func2.o
gcc main.o func1.o func2.o -o mainwork
main.o:main.c
gcc -c main.c
func1.o:func1.c
gcc -c func1.c
func2.o:func2.c
gcc -c func2.c
clean:
rm func1.o func2.o main.o
- 源文件:
main.c func1.c func2.c Makefile - make之后目录所包含文件:
main.c main.o func1.c func1.o func2.c func2.o mainwork(可执行文件) Makefile - make clean之后目录所包含文件:
main.c func1.c unc2.c Makefile
2.3 make install与make uninstall 指令
若想安装与卸载依旧是在Makefile文件里面自己编写rule,如果权限不够可以加上sudo。
#creat first rule
mainwork1:main.o func1.o func2.o
gcc main.o func1.o func2.o -o mainwork
main.o:main.c
gcc -c main.c
func1.o:func1.c
gcc -c func1.c
func2.o:func2.c
gcc -c func2.c
clean:
rm func1.o func2.o main.o
install:
cp mainwork /usr/local/mainwork
uninstall:
rm /usr/local/mainwork
- 执行make install之后,路径文件夹中会存在mainwork可执行文件。
- 执行make uninstall之后,路径文件夹下的mainwork会去除。
2.4 Makefile中变量
2.4.1 用户自定义变量-类似c语言宏
采用MObj = main.o func1.o func2.o,调用则$(MObj)
#creat first rule
MObj = main.o func1.o func2.o
mainwork1:$(MObj )
gcc $(MObj ) -o mainwork
main.o:main.c
gcc -c main.c
func1.o:func1.c
gcc -c func1.c
func2.o:func2.c
gcc -c func2.c
clean:
rm func1.o func2.o main.o
install:
cp mainwork /usr/local/mainwork
uninstall:
rm /usr/local/mainwork
2.4.2 预定义变量,有利于商业软件的开发使用,例如更换编译器gcc之后,只需要将CC=gcc更换即可
#creat first rule
CC= gcc
CFLAGS = -g -c
MObj = main.o func1.o func2.o
mainwork1:$(MObj)
$(CC) $(CFLAGS ) $(MObj) -o mainwork
main.o:main.c
$(CC) $(CFLAGS ) main.c
func1.o:func1.c
$(CC) $(CFLAGS ) func1.c
func2.o:func2.c
$(CC) $(CFLAGS ) func2.c
clean:
rm $(MObj) mainwork
install:
cp mainwork /usr/local/mainwork
uninstall:
rm /usr/local/mainwork
2.4.3 自动变量以及环境变量
$* | 不包含拓展名的目标文件名称 |
---|---|
$< | 第一个依赖文件名称 |
$? | 所有时间戳比目标文件晚的依赖文件 |
$@ | 目标文件完整名称(常用) |
$^ | 所有不重复的依赖文件(常用) |
#creat first rule
CC= gcc
CFLAGS = -g -c
MObj = main.o func1.o func2.o
mainwork1:$(MObj)
$(CC) $(CFLAGS ) $(MObj) -o $@
或者:
mainwork1:$(MObj) //$(^)代替了所有的依赖文件
$(CC) $(^) -o $@
main.o:main.c
$(CC) $(CFLAGS ) main.c
func1.o:func1.c
$(CC) $(CFLAGS ) func1.c
func2.o:func2.c
$(CC) $(CFLAGS ) func2.c
clean:
rm $(MObj) $@
install:
cp mainwork /usr/local/$@
uninstall:
rm /usr/local/$@
2.5 伪目标
采用伪目标可以防止文件夹下有同名的可执行文件.
#creat first rule
CC= gcc
CFLAGS = -g -c
MObj = main.o func1.o func2.o
mainwork1:$(MObj)
$(CC) $(CFLAGS ) $(MObj) -o $@
或者:
mainwork1:$(MObj) //$(^)代替了所有的依赖文件
$(CC) $(^) -o $@
main.o:main.c
$(CC) $(CFLAGS ) main.c
func1.o:func1.c
$(CC) $(CFLAGS ) func1.c
func2.o:func2.c
$(CC) $(CFLAGS ) func2.c
.PHONY: clean
clean:
rm $(MObj) $@
.PHONY: install
install:
cp mainwork /usr/local/$@
.PHONY: uninstall
uninstall:
rm /usr/local/$@
2.6 引用其它Makefile及Makefile嵌套
- 包含:如果需要包含新的make2.mk文件
声明include make2.mk
即可。 - 嵌套:文件夹为树状结构,顶级为root,内含一个make嵌套执行子文件夹下的make,生成依赖文件后,返回执行root文件夹下的make。
subsystem:
cd subdir && gcc -c main.c
等价于:
subsystem:
gcc -c main.c -Csubdir
2.7 条件判断
条件判断前不需要TAB空格,否则被认为是执行的命令,而非判断条件。
#creat first rule
CC= gcc
CFLAGS = -g -c
MObj = main.o func1.o func2.o
mainwork1:$(MObj)
ifeq($(CC),gcc) //如果$(cc) == gcc,则。。。否则。。
$(CC) $(^) -o $@
else
$(CC) $^ -o mainwork2
endif
main.o:main.c
$(CC) $(CFLAGS ) main.c
func1.o:func1.c
$(CC) $(CFLAGS ) func1.c
func2.o:func2.c
$(CC) $(CFLAGS ) func2.c
.PHONY: clean
clean:
rm $(MObj) $@
.PHONY: install
install:
cp mainwork /usr/local/$@
.PHONY: uninstall
uninstall:
rm /usr/local/$@
2.8 Makefile管理命令
-C dir | 读入指定目录下面的Makefile |
---|---|
-f file | 读入当前目录下的file文件为Makefile |
-i | 忽略所有的命令执行错误 |
-I dir | 指定被包含的Makefile所在目录(大写i dir) |
- -C dir举例
如果文件夹为MakeDemo,内含Makefile文件。目前位于makedemo文件夹的上级目录,则执行
make -C MakeDemo
- -f file举例
如果文件夹为MakeDemo,Makefile改名为tc.mk文件。则在MakeDemo文件夹内执行
make -f tc.mk
- -I dir举例
采用include的形式来包含
3 Autotools
由autoscan、aclocal、autoconf、autoheader、automake组成,作用为 扫描→展开宏→生成configure→生成head→生成makefile。
autoscan | 扫描源代码目录生成configure.scan文件 | configure.scan包含系统配置的基本选项,均为宏定义,需要将其更名为configure.in |
---|---|---|
aclocal | 是一个perl脚本程序,根据configure.in文件内容,自动生成aclocal.m4文件。定义为:aclocal - create aclocal.m4 by scanning configure.ac | 生成的aclocal.m4是宏展开文件 |
autoconf | 用来生成configure文件 | configure.in文件的内容是宏,宏经过autoconf处理后会变成检查系统特性、环境变量、软件必须参数的shell脚本 |
autoheader | 自动生成config.h.in | 在configure生成config.h时生成in文件 |
automake | 使用automake–add-missing 来生成Makefile.in | Makefile.am是用来生成Makefile.in的,需要手工书写 |
需要依赖的程序m4,prel
autotools使用流程
第一步:手工编写Makefile.am这个文件
第二步:在源代码目录树的最高层运行autoscan。然后手动修改configure.scan文件,并改名为configure.ac/configure.in
第三步:运行aclocal,它会根据configure.ac的内容生成aclocal.m4文件
第四步:运行autoconf,它根据configure.ac和aclocal.m4的内容生成configure这个配置脚本文件
第五步:运行automake –add-missing,它根据Makefile.am的内容生成Makefile.in
第六步:运行configure,它会根据Makefile.in的内容生成Makefile这个文件
操作示例:
mkdir demo_conf //新建一个文件夹 并且进入,然后vi hello.c如下
#include <stdio.h>
int main()
{
printf("hello configure\n");
return 0;
}
- 执行
autoscan
生成autoscan.log configure.scan hello.c
生成的configure.scan内的AC_XXX宏是供autoconfigure使用的。 - 将configure.scan重命名为configure.ac
mv configure.scan configure.ac
- vi configure.ac并修改如下
AC_INIT(hello,1.0,123456@qq.com)//文件名,版本号,bug发送至所写邮箱
AM_INIT_AUTOMAKE(hello,1.0)//新增一个宏在AC_CONFIG_HEADERS([config.h])下,表示需要automake工具生成目标文件。
AC_OUTPUT(Makefile)
- 执行
aclocal
生成aclocal.m4
,vi aclocal.m4可知相当于展开了AM_INIT_AUTOMAKE - 已经有了aclocal.m4与configure.ac,则可以执行autoconf,生成configure文件
- 手写一个Makefile.am文件,vi Makefile.am
bin_PROGRAMS = hello //生成的程序名
hello_SOURCES = hello.c //依赖的源代码文件名
- 已经有了Makefile.am与config.h.in 则执行
automake --add-missing
若缺少NEWS README AUTHORS ChangLog等文件可以自己添加touch NEWS README AUTHORS ChangLog
,若缺少config.h.in
可以在configure.ac中把configure.h的需求#掉,或者执行autoheader
生成config.h.in - 执行
./configure
生成config.status 与Makefile - 有了Makefile文件,可以执行
make
生成hello文件 - 执行
./hello
,屏幕输出hello congifure. - 执行
sudo make install
可安装到指定目录下,可以不用在当前文件夹下就可./hello
- 商业发布执行
make dist
可生成hello-1.0.tar.gz压缩包