make 学习笔记

在学习make之前,我们要知道为什么要使用make。在一个项目中,当我们改变某一个源程序时,若源文件较少,我们对其进行编译链接并生成新的目标文件并不复杂;然而,若我们的源文件很多,在一个大型的项目中时,若重新对这个项目进行编译链接无疑是耗时耗力,且其中很多的程序已经编译,无需再重新编译。make可以根据makefile文件提供的文件依赖,决定哪些需要重新编译,即利用其中的一个时间戳(在后面会讲到),从而节省时间。

例如,我们有一个test.h头文件,一个test.cpp源文件,还有一个main.cpp源文件,我们下面就讲解如何用make和makefile 生成一个可执行的目标文件;

首先,tesh.h头文件中声明了一个func函数:

#ifndef TEST_H
#define TEST_H

void func(char a);
#endif

 test.cpp源文件中对func函数进行定义:

#include <iostream>
#include "test.h"
using namespace std;

void func(char a)
{
      cout<<a<<endl;
}

 再定义一个main文件:

#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++查看其中的意义。

下面讲解如何通过make和makefile的搭配来实现:

我们要在源文件所在的目录中创建一个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的了解不是太多,希望大家能够给予意见及帮助!

 

 

posted @ 2013-12-12 15:57  Jerry-c  阅读(875)  评论(0编辑  收藏  举报