您的位置:首页 > 运维架构 > Linux

Linux 下的Makefile(一)

2015-12-15 17:34 232 查看

一、入门级

入门级其实就和直接用命令在终端下编译基本上没有任何区别。只是把在终端中键入的命令全部放入到Makefile文件中。

举例:

//hello.cpp
#include<iostream>
using namespace std;
int main()
{
cout<<"Hello world!"<<endl;
return 0;
}


1.打开终端,进入当前test目录。新建一个名为Makefile的文件,注意其中M要大小。

2.输入以下命令然后保存退出:

TARGET:hello.o
g++ -o Hello hello.o
hello.o:hello.cpp
g++ -c hello.cpp


打开终端,进入test目录,即Makefile所在的目录,运行make命令,最终会生成名为Hello的可执行文件。

其中:

TARGET:hello.o表示要生成的目标文件为hello.o,得到目标文件之后再用g++ -o Hello hello.o命令生成可执行文件。

hello.o:hello.cpp表示要想得到目标文件hello.o,得依赖于g++ -c hello.cpp生成。即整个执行过程是从下到上的。

二、进阶级

进阶级就是在入门级的基础之上运用递推实现。

先假设当前所在的目录为test,里面有两个文件test/min和test/max,一个源文件main.cpp。其中min中有源文件min.cpp和min.h;max中有源文件max.cpp和max.h。即以下五个源文件:

举例:

//  test/max/max.h
#ifndef MAX_H
#define MAX_H
int Max(int a,int b);
#endif

// test/max/max.cpp
#include "max.h"
int Max(int a, int b)
{
return a > b ? a : b;
}

// test/min/min.h
#ifndef MIN_H
#define MIN_H
int Min(int a,int b);
#endif

// test/min/min.cpp
#include "min.h"
int Min(int a, int b)
{
return a > b ? b : a;
}

// test/main.cpp
#include"max/max.h"
#include"min/min.h"
#include<iostream>
using namespace std;
int main()
{
int a,b;
cin>>a>>b;
cout<<" max = "<<Max(a,b)<<
" min = "<<Min(a,b)<<endl;
return 0;
}


1.打开终端,进入当前test目录。新建一个名为Makefile的文件,注意其中M要大小。

2.输入以下命令然后保存退出:

TARGET:main.o max.o min.o
g++ -o Main main.o max.o min.o
main.o:main.cpp max/max.h min/min.h
g++ -c main.cpp
max.o:max/max.cpp
g++ -c max/max.cpp
min.o:min/min.cpp
g++ -c min/min.cpp


注意:每一编译命令也就是g++前面是一个tab的间隔,一定不要用8个空格来代替。

不然会有以下错误提示:Makefile:6: * missing separator。

打开终端,进入test目录,即Makefile所在的目录,运行make命令,最终会生成名为Main的可执行文件。其中的各种依赖关系同之前的道理。

这和之前的入门级的写法有区别? 当然没区别,唯一的区别就是多了几行,而且是重复的。试想一下,要是这个工程有上千个源文件,难道要依次写进去?当然不是。这儿只是想从侧面说明为什么要使用递推的方法来写Makefile。

递推:

CXX = g++
OBJS = main.o max/max.o min/min.o
TARGET = Main
RM = rm -f
$(TARGET):$(OBJS)
$(CXX) -o $(TARGET) $(OBJS)
$(OBJS):%.o : %.cpp
$(CXX) -c $< -o $@
clean:
-$(RM) $(TARGET) $(OBJS)


依次大致解释一下:

CXX = g++ 表示把g++ 用变量CXX来表示,在后面如果再须要用到g++只需用(CXX)引用即可。至于为什么是CXX而不是其它,这是一种默认的规则,也可以说是先入为主,你高兴随便用什么都行,因为它只是一个变量OBJS=main.omax/max.omin/min.oOBJS是objects的缩写,表示目标文件TARGET=Main表示最后生成的可执行文件(binary)的名称(CXX)引用即可。至于为什么是CXX而不是其它,这是一种默认的规则,也可以说是先入为主,你高兴随便用什么都行,因为它只是一个变量
OBJS = main.o max/max.o min/min.o OBJS是objects的缩写,表示目标文件
TARGET = Main 表示最后生成的可执行文件(binary)的名称
(TARGET):(OBJS)“(OBJS) “”这个符号的作用是引用变量,其中括号里面的就是变量名。表示Main 依赖于OBJS即所有的.o文件。

(CXX)−o(CXX) -o (TARGET) (OBJS)等价于g++−oMainmain.omax/max.omin/min.o(OBJS) 等价于 g++ -o Main main.o max/max.o min/min.o
(OBJS):%.o : %.cpp 表示把OBJS中,所有.o的目标文件,换成.cpp源文件

(CXX)−c(CXX) -c < -o @等价于g++−cmain.cpp−omain.o,其中@ 等价于 g++ -c main.cpp -o main.o,其中< 表示 .cpp文件, $@ 表示.o文件

到这儿,就已经能完成编译工程。后面的两行表示删除目标文件和可执行文件。命令为make clean,其中最后一行前面的 “-“作用是在没有要删除的文件时,执行这条命令不会报错,提示说没有该文件。

源文件链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: