Makefile工具使用
Posted 别呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Makefile工具使用相关的知识,希望对你有一定的参考价值。
人们通常利用 make 工具来自动完成编译工作。这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。利用这种自动编译可大大简化开发工作,避免不必要的重新编译。
Makefile
make 工具通过一个称为 makefile 的文件来完成并自动维护编译工作。makefile 需要按照某种语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。当修改了其中某个源文件时,如果其他源文件依赖于该文件,则也要重新编译所有依赖该文件的源文件。
Makefile基本规则
target...:prerequisites...
command
...
目标(target)
:程序产生的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如“clean”。
依赖(prerequisites)
:是用来产生目标的输入文件,一个目标通常依赖于多个文件。
命令(command)
:是make执行的动作,一个可以有多个命令,每个占一行。注意:每个命令行的起始字符必须为TAB字符!
如果prerequisites中有一个或多个文件更新的话,command就要执行,这就是Makefile最核心的内容
最简单的Makefile例子
源文件有:
main.c
#include <stdio.h>
int main(){
int a1 = 10, a2 = 20;
Swap(a1, a2);
printf("swap value : %d ,%d",a1,a2);
return 0;
}
swap.h
#ifndef _SWAP_H_
#define _SWAP_H_
void Swap(int *a,int *b);
#endif
swap.c
#include "swap.h"
void Swap(int *a,int *b){
int *temp = a;
a = b;
b = temp;
}
将源文件放到同一位置后,用vi Makefile
(这里M可以不用大写)命令创建Makefile文件并添加内容如下:
main:main.o swap.o
gcc main.o swap.o -o main //注意空一个tab
main.o:main.c swap.h
gcc -c main.c -o main.o
swap.o:swap.c swap.h
gcc -c swap.c -o swap.o
clean:
rm -f main main.o swap.o
添加完并保存后,用 make
编译执行而后生成一个 main
文件,用./main
执行。
make是如何工作的
1、make会在当前目录下找名字叫“Makefile
”或“makefile
”。
2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“main”这个文件,并把这个文件作为最终的目标文件。
3、如果main文件不存在,或是main所依赖的后面的 .o 文件的文件修改时间要比main这个文件新,那么,他就会执行后面所定义的命令来生成main这个文件。
4、如果main所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。
5、当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件make的终极任务,也就是执行文件main了。
常见伪目标.PHONY
all: target1 target2
Target1:
执行make all
install
执行make install
Clean
执行make clean
Makefile使用伪目标:
main:main.o swap.o
gcc main.o swap.o -o main
main.o:main.c swap.h
gcc -c main.c -o main.o
swap.o:swap.c swap.h
gcc -c swap.c -o swap.o
.PHONY:clean
clean:
rm -f main main.o swap.o
(注意:同样是写到Makefile文件里,然后执行make,最后执行生成的可执行文件,下文操作方法都一样。)
Makefile自动化变量
选项名 | 作用 |
---|---|
$@ | 规则的目标文件名 |
$< | 规则的第一个依赖文件名 |
$^ | 规则的所有依赖文件列表 |
makefile中使用变量
objects=main.o swap.o
main:$(objects)
gcc $(objects) -o main
main.o:main.c swap.h
gcc -c main.c -o main.o
swap.o:swap.c swap.h
gcc -c swap.c -o swap.o
.PHONT:clean
clean:
rm -f main main.o swap.o
make自动推导
GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。
只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么 whatever.c,就会是whatever.o的依赖文件。并且 gcc -c whatever.c 也会被推导出来。
缺点:一旦新增加源文件就要修改
示例:
objects= main.o swap.o
main:$(objects)
gcc $(objects) -o main
$(objects):
.PHONY:clean
clean:
rm -f main *.o
Makefile中常见函数
1、wildcard函数
:当前目录下匹配模式的文件
例如:
src=$(wildcard *.c)
2、notdir函数
:去除路径
例如:
$(notdir $(src))
3、patsubst函数
:模式匹配替换
例如:
$(patsubst%.c,%.o,$(src))
等价于 $(src:.c=.o)
4、shell函数
:执行shell命令
例如:
$(shell ls –d */)
优点:不需要修改makefile就能适应
示例:
ELF=main
CC=gcc
src=$(wildcard *.c)
objects=$(src:.c=.o)
$(ELF):$(objects)
$(CC) $^ -o $@
$(objects):
clean:
rm -f $(objects) $(ELF)
多级目录Makefile
ELF=main
CC=gcc
src=$(find -name '*.c')
objects=$(src:.c=.o)
$(ELF):$(objects)
.c.o:
$(CC) –c $< -o $@
#$(objects):
clean:
rm -f $(objects) $(ELF)
在顶层目录中编写一个Makefile
CC=gcc
SUBDIR=$(shell ls -d */)
ELF = main
ROOTSRC=$(wildcard *.c)
ROOTOBJ=$(ROOTSRC:%.c=%.o)
SUBSRC=$(shell find $(SUBDIR) -name '*.c')
SUBOBJ=$(SUBSRC:%.c=%.o)
$(ELF):$(ROOTOBJ) $(SUBOBJ)
$(CC) -o $(ELF) $(ROOTOBJ) $(SUBOBJ)
.c.o:
echo $(@D) $(<F) $(@F)
$(CC) -c $(@D)/$(<F) -o $(@D)/$(@F)
clean:
rm $(ELF) $(ROOTOBJ) $(SUBOBJ)
以上是关于Makefile工具使用的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 NMake 样式 Makefile 的 clang-cl 无法回显
Android 逆向Android 进程注入工具开发 ( Visual Studio 开发 Android NDK 应用 | 使用 Makefile 构建 Android 平台 NDK 应用 )(代码