在学习make以前,咱们要知道为何要使用make。在一个项目中,当咱们改变某一个源程序时,若源文件较少,咱们对其进行编译连接并生成新的目标文件并不复杂;然而,若咱们的源文件不少,在一个大型的项目中时,若从新对这个项目进行编译连接无疑是耗时耗力,且其中不少的程序已经编译,无需再从新编译。make能够根据makefile文件提供的文件依赖,决定哪些须要从新编译,即利用其中的一个时间戳(在后面会讲到),从而节省时间。linux
例如,咱们有一个test.h头文件,一个test.cpp源文件,还有一个main.cpp源文件,咱们下面就讲解如何用make和makefile 生成一个可执行的目标文件;ios
首先,tesh.h头文件中声明了一个func函数:git
#ifndef TEST_H #define TEST_H void func(char a); #endif
test.cpp源文件中对func函数进行定义:github
#include <iostream> #include "test.h" using namespace std; void func(char a) { cout<<a<<endl; }
再定义一个main文件:vim
#include "test.h" #include<iostream> using namespace std; int main() { cout<<"please enter a char "<<endl; char ch; cin>>ch; cout<<"func(char)="<<func(ch)<<endl; return 0; }
上面定义了test.h头文件,及test.cpp和main.cpp的.cpp文件,下面首先经过g++命令编译看其结果:浏览器
若单纯的用g++,咱们能够首先使用命令函数
g++ test.cpp -fPIC -shared -o test.so
生成test.so的动态连接库,而后连接这个库生成可执行目标文件:学习
g++ main.cpp -L. -ltest -I. -o test
这样咱们就能够生成一个test的可执行文件。其中的一些参数你们能够去google或man g++查看其中的意义。google
下面讲解如何经过make和makefile的搭配来实现:spa
咱们要在源文件所在的目录中建立一个Makefile的文件,能够经过vim Makefile 命令实现。针对上面的例子咱们能够写出Makefile以下:
CPP = g++ OBJS = main.cpp test.cpp test :$(OBJS) $(CPP) $(OBJS) -o $@
而后执行
make
./test
就能够生成了如同上面同样的结果。你们能够看出,Makefile的本质其实仍是使用g++完成了编译过程。其中的CPP和OBJS至关于变量,方便咱们添加文件。而$@表明的是第一个目标文件即test目标文件。而test :$(OBJS)表示test依赖于OBJS里的源文件。当make时,发现(OBJS)中的文件比test中更新,则更新test。这里面就涉及了linux的时间戳文件,你们能够去看CSDN中一篇博文<linux Makefile时间戳>.楼主浏览器貌似不能插入网址,不知道缘由。。里面对linux的时间戳进行了详细的说明。关于Makefile时间戳的一个函数能够以下:
time_t GetModifiedTimestamp(char *path) { struct stat attr; if(stat(path,&attr) == -1) return 0; return attr.st_mtime; }
上面的代码是参考Cyberspace_TechNode的博文中的关于时间戳的函数。相应的咱们也能够写个Makefile用于生成test.so的动态连接库。在此楼主就不写了。
关于Makefile模板,你们能够参考github上的一个个人师兄徐陈峰写的Makefile 模板。经过简单修改其中的一点参数便可简单的生成对应的如lib,bin等。其中的readme.txt有详细说明。
还有个师兄提议是否是能够考虑选择Cmake替代,由于Cmake是跨平台的,目前对Cmake的了解不是太多,但愿你们可以给予意见及帮助!