【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小時哩。

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