【UBUNTU】makefile文件的写法

序言

linux中编译代码往往没有windows下直接使用IDE来得方便,但是既然从事了C/C++的开发就必然会涉及到linux下的C/C++编程。既然是编译C/C++代码,那就要学会怎么写makefile文件了,下面来说说怎么使用makefile文件来编译代码。

第一种情况

只有一个main.cpp文件,代码如下:

#include <iostream>
using namespace std;
int main() {
    cout<<"I was created by makefile"<<endl;
    return 0;
}

正常情况下我们使用g++ mian.cpp -o main.o来编译代码,当使用makefile的时候应该这样写:

main.o: main.cpp   
	g++ main.cpp -o main.o
clean:
	rm main.o
#===============格式如下=================#
(生成目标的文件): (生成目标文件所需要的依赖文件)
	命令

为了方便和养成良好习惯,一般再加上个clean,当更新完cpp文件后,重新make之前先输入make clean,makefile文件会执行clean中的shell命令。

第二种情况

main.cpp文件使用了其他cpp文件中的函数,比如下面代码中main.cpp使用了print.cpp的函数。
print.cpp以及其print.h头文件的代码如下

// print.h
#ifndef PRINT_H
#define PRINT_H
#include<iostream>
void printLine(std::string str);
#endif 
/*===============================*/
//print.cpp
#include"print.h"
using namespace std;
void printLine(string str){
    cout<< str <<endl;
}
//main.cpp
#include <iostream>
#include "print.h"
using namespace std;
int main() {
    string str = "I was created by makefile";
    printLine(str);
    return 0;
}	

正常情况下我们需要两步编译:

g++ -c print.cpp #生成print.o依赖文件
然后执行
g++ main.cpp print.o -o main.o

而makefile的写法如下:

main.o: main.cpp print.o (生成main.o的依赖文件有main.cpp和print.o)
	g++ main.cpp print.o -o main.o 
	
print.o: print.cpp
	g++ -c print.cpp
	
clean:
	rm main.o print.o

makefile的执行步骤是这样的
1.系统打算编译生成main.o,发现了main.o需要main.cpp和print.o。
2.main.cpp已经有了,但是发现print.o没有,于是系统继续往下看,发现了print.o的生成依赖于print.cpp。
3.发现print.cpp存在了,于是执行makefile中的g++ -c print.cpp命令,生成了print.o
4.此时,main.cpp和print.o都存在了,于是系统跳回第一行,执行下面的命令g++ main.cpp print.o -o main.o
注意:所以在修改完CPP文件后,重新编译前要执行make clean,否则makefile发现已经存在的.o依赖文件,那么是不会再次生成新的依赖文件的。

第三种情况

main.cpp中不单单使用了print.cpp和print.h,还使用了其他的cpp和h文件(假如是print_2.cpp和print_2.h),同理只需要把main.o的需要的依赖文件加上就行了,makefile如下:

main.o: main.cpp print.o print_2.o
	g++ main.cpp print.o print_2.o -o main.o

print.o: print.cpp
	g++ -c print.cpp

print_2.o: print_2.cpp
	g++ -c print_2.cpp

clean:
	rm main.o print.o print_2.o

第四种情况

需要同时编译出两个不同功能的main文件,即main1.o和main2.o.这时候要用到一个关键字all,如果不使用all的话,makefile编译的时候只会编译第一个main1.o,下面的main2.o就只当成main1.o的依赖文件看待了(如果用不上就不执行),makefile的代码如下

all: main1.o main2.o #注意这里多了一行all打头的代码,表示着我们需要编译的目标文件

main1.o: main1.cpp print.o print_2.o
	g++ main1.cpp print.o print_2.o -o main1.o

main2.o: main2.cpp print.o print_2.o
	g++ main2.cpp print.o print_2.o -o main2.o

print.o: print.cpp
	g++ -c print.cpp

print_2.o: print_2.cpp
	g++ -c print_2.cpp

clean:
	rm main1.o main2.o print.o print_2.o

第五种情况

有人问到,我想用gcc编译怎么办,但是里面都是g++,要改的话好麻烦。这时候就要对编译的方式进行命名,如下:

CC = g++ #将CC命名为g++或者gcc,as your will
main.o: main.cpp   
	$(CC) main.cpp -o main.o
clean:
	rm main.o

以上我们就使用了**$(CC)**来代替编译方式了
又有人问到,我想用c++11来编译,makefile要怎么写呢,这时候同理我们也用命名大法,将CFLAG命名为 -std=c++11,如下:

CFLAG = -std=c++11 #
main.o: main.cpp   
	g++ $(CFLAG) main.cpp -o main.o
clean:
	rm main.o

**为了方便,**通常我们还把需要生成的.o文件写成一个OBJECTS对象,后面clean的时候操作起来也方便,makefile如下

CFLAG = -std=c++11
OBJECTS = main1.o main2.o print.o print_2.o
all: main1.o main2.o

main1.o: main1.cpp print.o print_2.o
	g++ main1.cpp print.o print_2.o -o main1.o $(CFLAG)

main2.o: main2.cpp print.o print_2.o
	g++ main2.cpp print.o print_2.o -o main2.o

print.o: print.cpp
	g++ -c print.cpp

print_2.o: print_2.cpp
	g++ -c print_2.cpp

clean:
	rm $(OBJECTS)
#===================================#
clean的写法其实写成下面的形式好点:
.PHONY:clean 
clean: 
-rm $(OBJECTS)
这种形式表示clean是个伪文件,当clean途中发生错误的时候,可以跳过这个错误的文件,继续clean下面的文件

其他的我就不讲了,这只是基本的makefile写法,如果帮到你就点个赞哈,写了2小时哩。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章