什么是makefile?对于Winodws程序员来说可能很陌生,因为windows的IDE已经把所有的工作都做好了,你只需要点击各个按钮就可以了。但是对于一个Unix/Windows程序员来讲makefile则是必须要懂的。结合makefile的大多应用场合我们可以说:会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
此处先对makefile的最基本的应用做介绍,以后再继续深入。参考如下
首先准备三个文件file1.cpp、file1.h、file2.cpp,程序代码如下:
//fiel1.h
#ifndef FILE1_H_
#define FILE1_H_
#ifdef __cplusplus
extern "C"{
#endif
void file1print();
#ifdef __cplusplus
}
#endif
#endif
//file1.cpp
#include<iostream>
#include "file1.h"
using namespace std;
void file1print(){
cout<<"Print file1......."<<endl;
}
//file2.cpp
#include<iostream>
#include "file1.h"
using namespace std;
int main(){
cout<<"Print file2....."<<endl;
file1print();
return 0;
}
一、基本makefile编写
helloworld: file1.o file2.o
g++ file1.o file2.o -o helloworld
file2.o:file2.cpp
g++ -c file2.cpp -o file2.o
file1.o:file1.cpp
g++ -c file1.cpp -o file1.o
clean:
rm -rf *.o helloworld
解析:makefile文件的编写规则如下。
目标:先决需要
(tab)<command>
(tab)<command>
注:每个命令行前面都必须要有tab符号。
注:“先决需要”中如果有一个以上的文件比“目标”文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。
上面makefile的目的就是要编译一个helloworld的可执行文件,接下来详细解释:
(1)helloworld依赖file1.o file2.o两个文件。
helloworld: file1.o file2.o
依赖于file.o和file2.o两个目标文件编译出helloworld可执行文件。
g++ file1.o file2.o -o helloworld
(2)file2.o依赖于file2.cpp文件。
file2.o:file2.cpp
依赖于file2.cpp源文件编译出file2.o可执行文件。
(3)file1.o依赖于file1.cpp文件。
file1.o:file1.cpp
依赖于file1.cpp源文件编译出file1.o可执行文件。
(4)最后写入一个clean。当用户输入“make clean”命令时,会删除*.o和helloworld文件。
clean:
rm -rm *.o helloworld
二、makefile中使用变量
其实在makefile文件中使用变量很简单。知道如何设定变量和如何引用变量就ok了。
设定变量:var=value
引用变量:$(var)即可
objs=file1.o file2.o
xx=g++
cflags=-Wall -O -g
helloworld: $(objs)
$(xx) $(objs) -o helloworld
file2.o:file2.cpp file1.h
$(xx) $(flags) -c file2.cpp -o file2.o
file1.o:file1.cpp file1.h
$(xx) $(flags) -c file1.cpp -o file1.o
clean:
rm -rf *.o helloworld
三、makefile中使用函数
这个略微复杂一点,看看下面这个吧!
xx=g++
cc=gcc
cflags=-Wall -O -g
target=helloworld
%.o:%.c
$(cc) $(cflags) -c $< -o $@
%.o:%.cpp
$(xx) $(cflags) -c $< -o $@
source=$(wildcard *.c *.cpp)
objs=$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(source)))
$(target):$(objs)
$(xx) $(objs) -o $(target)
clean:
rm -rf *.o helloworld
(1)wildcard函数:source = $(wildcard *.c *.cpp)
产生一个所有以.c、.cpp结尾的文件的列表,存入变量source里面。
(2)patsubst函数:用于匹配替换。$(patsubst %.cpp,%.o,$(source))
将$(source)指定的后缀为.cpp的变量符号全部替换成为.o为后缀。
至于$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(source)))的意思就是将$(source)指定的后缀为.cp或.cpp的变量符号全部替换成为.o为后缀。
(3)有用的内部变量:
1)$@:目标文件
2)$<:第一个依赖文件
3)$^:所有的依赖文件
有了这些后第一个实例的makefile文件就可以写成如下样式了:
helloworld: file1.o file2.o
g++ -o $@ $^
file2.o:file2.cpp
g++ -c $<
file1.o:file1.cpp
g++ -c $<
clean:
rm -rf *.o helloworld