Makefile 文件编写
1、什么是Makefile文件?
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,也可以执行操作系统的命令。(来自百度百科的解释)
我举个例子就很容易理解了,比如在你写完一份代码之后,需要执行如下指令:
gcc test.c -o main
其实,Makefile文件就是将你需要执行的指令放入其中。如果你的项目比较庞大,有很多的文件需要编译,那么每次执行上面的命令会非常的耗时且容易出错,编写Makefile文件才是最好的选择。
2、Makefile文件编写基础
文件的创建可以使用命令:touch,vi、vim
首先编写一个test.c的文件
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("new test\n");
return 0;
}
下面编写Makefile文件
test:test.c #目标文件名:依赖文件名
gcc test.c -o test #这里就是要执行的命令
使用vim编写结束,按Esc,:wq退出,运行命令make,Makefile文件的名字也可以是其他的,不过运行就不只是make命令了,而要加上-f。
make -f filename
3、Makefile多文件编写
main.c
#include <stdio.h>
#include <stdlib.h>
#include "add.h"
int main()
{
int num = add(10,10);
printf("num:%d\n",num);
return 0;
}
add.h
int add(int a,int b);
add.c
#include "add.h"
int add(int a,int b)
{
return a+b;
}
Makefile文件编写如下
main:main.c add.o #编写需要从最终成果物写起
gcc main.c add.o -o main
add.o:add.c
gcc -c add.c
clean:
rm *.o main
执行make命令,先运行第一个gcc,但是依赖add.o,所以有会递归运行下一个gcc;
执行make clean,会调用 rm *.o main,则会删除生成的.o和main文件。
4、Makefile多文件编写优化
CC=gcc $(CFLAGS) #c++这里也可以使用g++,$()是使用这个变量的意思
CFLAGS = -Wall -g #-Wall会生成警告信息,-g成果包含gdb调试信息
TARGET = main #这里是最终产物名
SOURCES = $(wildcard *.c) #wildcard可以用来获取目录下所有.c文件列表
OBJS = $(patsubst %.c, %.o, $(SOURCES)) #这里使用patsubst是将所有的.c文件替换成.o
$(TARGET):$(OBJS) #目标:依赖
$(CC) $(CFLAGS) $(OBJS) -o $(TARGET) #等同于gcc -Wall -g add.o -o main
.c.o: #等同于%.o:%.c,%是一个通配符,可以认为是任何文件名
$(CC) -c $(CFLAGS) -o $@ #这个的$@就是获取执行当前命令的目标值,也就是add.o
.PHONY:clean #.PHONY是伪目标,为了防止当前目录存在名为clean的文件存在,还能解决make并行问题
clean:
rm -f $(OBJS) $(TARGET) #执行make clean删除.o文件和目标文件
5、Makefile依赖.so文件编写
CC=g++ $(CFLAGS)
CPPFLAGS = -Wl,-Bsymbolic -shared -fPIC -Wall -g #前面添加部分标识生成动态链接库
HOST=$(shell uname -m | sed -e 's/i.86/i686/' -e 's/^armv.*/arm/') #这里是执行uname -m命令打印设备系统架构,后面是匹配打印信息,'s/i.86/i686/',其中.可以看做通配符,然后将i.86替换成i686
ifeq ($(HOST),x86_64) #ifeq是判断语句,匹配字符是否相同
CPPFLAGS += -m64
SDK_LIB = m64x86
else ifeq ($(HOST),i686)
CPPFLAGS += -32
SDK_LIB = m32x86
else
endif
TARGET = SDK.so #这里生成动态链接库
INCLUDES = -I./include #这里是获取所有头文件
SOURCES = $(wildcard src/*.cpp) #获取所有cpp文件
SOURCES += $(wildcard src/common/*.cpp) #源文件可以累加获取
LINKLIBS = -L./depends/$(SDK_LIB) -lsdk -lpthread #这里是导入编译依赖的动态库,libsdk.so文件就写成-lsdk,-lpthread需要用到线程库建议加上
OBJS = $(patsubst %.cpp, %.o, $(SOURCES))
$(TARGET):$(OBJS)
$(CC) $(INCLUDES) $(CPPFLAGS) $(OBJS) $(LINKLIBS) -o $(TARGET)
.cPP.o:
$(CC) $(INCLUDES) -c $(CFLAGS) $< -o $@ # $<表示依赖文件集合
.PHONY:clean
clean:
rm -f $(OBJS) $(TARGET)
6、总结
以上则是我最近学习到的从最基础开始编写Makefile全部过程,大致涵盖了整个编写Makefile遇到的所有问题,希望对大家能有用!!!