C++學(xué)習(xí)進(jìn)階之Makefile基礎(chǔ)用法詳解
1. Makefile基本語法與執(zhí)行
為什么要使用 Makefile?
Makefile 文件描述了整個(gè)工程的編譯、鏈接的規(guī)則。
為工程編寫 Makefile 的好處是能夠使用一行命令來完成“自動(dòng)化編譯”。只需提供一個(gè)(通常對于一個(gè)工程來說會(huì)是多個(gè))正確的 Makefile,接下來每次的編譯都只需要在終端輸入“make”命令,整個(gè)工程便會(huì)完全自動(dòng)編譯,極大提高了效率。尤其是在編譯一個(gè)僅有一小部分文件被改動(dòng)過的大項(xiàng)目的情況下。
絕大多數(shù)的 IDE 開發(fā)環(huán)境都會(huì)為用戶自動(dòng)編寫 Makefile。
Make 是怎么工作的?
Make 工作的原則就是:
一個(gè)目標(biāo)文件當(dāng)且僅當(dāng)在其依賴文件(dependencies)的更改時(shí)間戳比該目標(biāo)文件的創(chuàng)建時(shí)間戳新時(shí),這個(gè)目標(biāo)文件才需要被重新編譯。
Make 工具會(huì)遍歷所有的依賴文件,并且把它們對應(yīng)的目標(biāo)文件進(jìn)行更新。編譯的命令和這些目標(biāo)文件及它們對應(yīng)的依賴文件的關(guān)系則全部儲(chǔ)存在 Makefile 中。
Makefile 中也指定了應(yīng)該如何創(chuàng)建,創(chuàng)建出怎么樣的目標(biāo)文件和可執(zhí)行文件等信息。
除此之外,你甚至還可以在 Makefile 中儲(chǔ)存一些你想調(diào)用的系統(tǒng)終端的命令,像一個(gè) Shell 腳本一樣使用它。
作用:
Makefile 文件告訴 Make 怎樣編譯和連接成一個(gè)程序
可用命令 dnf install make 安裝make功能
格式:
按如下格式編寫 Makefile
目標(biāo)(target): 依賴(prerequiries)...
命令(command)
注意:每個(gè)命令行前面必須是一個(gè)Tab字符,即命令行第一個(gè)字符是Tab
實(shí)驗(yàn):
vim Makefile 編輯文件:
simpletest:simple.o simpletest.o g++ simple.o simpletest.o -o simpletest simple.o:simple.cpp g++ -c simple.cpp -o simple.o simpletest.o:simpletest.cpp g++ -c simpletest.cpp -o simpletest.o
結(jié)果為:
[root@foundation1 shishi]# make
g++ -c simple.cpp -o simple.o
g++ -c simpletest.cpp -o simpletest.o
g++ simple.o simpletest.o -o simpletest
命令上下是有順序的,上一行對下一行具有依賴關(guān)系
如果文件夾中已經(jīng)有.o文件,make后會(huì)提示已經(jīng)生成,需要?jiǎng)h除.o文件后再make
clean的作用: 被指定時(shí)會(huì)刪除對應(yīng).o文件,避免上述情況
simpletest:simple.o simpletest.o g++ simple.o simpletest.o -o simpletest simple.o:simple.cpp g++ -c simple.cpp -o simple.o simpletest.o:simpletest.cpp g++ -c simpletest.cpp -o simpletest.o clean: rm simpletest simple.o simpletest.o
結(jié)果為:
[root@foundation1 shishi]# make clean
rm simpletest simple.o simpletest.o
[root@foundation1 shishi]# make
g++ -c simple.cpp -o simple.o
g++ -c simpletest.cpp -o simpletest.o
g++ simple.o simpletest.o -o simpletest
2. Makefile簡化過程
使用變量: 如果調(diào)用某個(gè)文件用的次數(shù)較多,可以使用變量代替,變量可以直接替換
變量定義: 變量 = 字符串
變量使用: $(變量名)
makefile 文件可改為:
TARGET = simpletest OBJS = simple.o simpletest.o $(TARGET):$(OBJS) g++ $(OBJS) -o $(TARGET) simple.o:simple.cpp g++ -c simple.cpp -o simple.o simpletest.o:simpletest.cpp g++ -c simpletest.cpp -o simpletest.o clean: rm $(TARGET) $(OBJS)
命令自動(dòng)推導(dǎo): 我們可以發(fā)現(xiàn),由于 .cpp 文件都是生成對應(yīng)的 .o 文件,所以 makefile 文件是可以自動(dòng)識(shí)別的
makefile 文件可改為:
TARGET = simpletest OBJS = simple.o simpletest.o $(TARGET):$(OBJS) g++ $(OBJS) -o $(TARGET) simple.o:simple.cpp simpletest.o:simpletest.cpp clean: rm $(TARGET) $(OBJS)
預(yù)定義變量: 系統(tǒng)中自己也定義了一些變量
變量 | 程序 | 默認(rèn)值 |
---|---|---|
CC | C語言編譯程序 | cc |
CXX | C++編譯程序 | g++ |
AR | C++打包程序 | ar |
CPP | 帶有標(biāo)準(zhǔn)輸出的C語言預(yù)處理程序 | $(CC) -E |
RM | 刪除命令 | rm |
makefile 文件可改為:
TARGET = simpletest OBJS = simple.o simpletest.o $(TARGET):$(OBJS) $(CXX) $(OBJS) -o $(TARGET) simple.o:simple.cpp simpletest.o:simpletest.cpp clean: $(RM) $(TARGET) $(OBJS)
假想目標(biāo): 如果文件夾中有clean文件,那么make clean就不能使用,需要使用假想目標(biāo),可以在執(zhí)行命令時(shí)不查看文件夾里面的文件,直接生效
makefile 文件可改為:
TARGET = simpletest OBJS = simple.o simpletest.o .PHONY: clean $(TARGET):$(OBJS) $(CXX) $(OBJS) -o $(TARGET) simple.o:simple.cpp simpletest.o:simpletest.cpp clean: $(RM) $(TARGET) $(OBJS)
建議不生成目標(biāo)文件的命令都設(shè)為假想目標(biāo)
3. Makefile生成并使用庫
3.1 動(dòng)態(tài)庫的建立與使用
vim Makefile 編輯文件:
TARGET = simpletest OBJS = simple.o LIB = libsimple.so CXXFLAGS = -c -fPIC .PHONY: clean $(TARGET):$(LIB) simpletest.o $(CXX) simpletest.o -o $(TARGET) -L. -lsimple $(LIB):$(OBJS) $(CXX) -shared $(OBJS) -o $(LIB) simple.o:simple.cpp $(CXX) $(CXXFLAGS) simple.cpp -o $(OBJS) simpletest.o:simpletest.cpp $(CXX) $(CXXFLAGS) simpletest.cpp -o simpletest.o clean: $(RM) $(TARGET) $(OBJS) $(LIB)
結(jié)果為:
[root@foundation1 shishi]# make clean
rm -f simpletest simple.o libsimple.so
[root@foundation1 shishi]# make
g++ -c -fPIC simple.cpp -o simple.o
g++ -shared simple.o -o libsimple.so
g++ -c -fPIC simpletest.cpp -o simpletest.o
g++ simpletest.o -o simpletest -L. -lsimple
預(yù)定義變量:
還是需要在前面定義
變量 | 程序參數(shù) |
---|---|
CFLAGS | 用于C編譯器的額外標(biāo)志 |
CXXFLAGS | 用于C++編譯器的額外標(biāo)志 |
ARFLAGS | 用于C/C++打包器的額外標(biāo)志 |
LDFLAGS | 鏈接庫路徑-L |
LDLIBS | 鏈接庫-l |
makefile 文件可改為:
TARGET = simpletest OBJS = simple.o LIB = libsimple.so CXXFLAGS = -c -fPIC LDFLAGS = -L. LDLIBS = -lsimple .PHONY: clean $(TARGET):$(LIB) simpletest.o $(CXX) simpletest.o -o $(TARGET) $(LDFLAGS) $(LDLIBS) $(LIB):$(OBJS) $(CXX) -shared $(OBJS) -o $(LIB) simple.o:simple.cpp $(CXX) $(CXXFLAGS) simple.cpp -o $(OBJS) simpletest.o:simpletest.cpp $(CXX) $(CXXFLAGS) simpletest.cpp -o simpletest.o clean: $(RM) $(TARGET) $(OBJS) $(LIB)
自動(dòng)變量:
自動(dòng)變量是在規(guī)則每次執(zhí)行時(shí)都基于目標(biāo)和依賴產(chǎn)生新值的變量
自動(dòng)變量 | 含義 |
---|---|
$< | 表示第一個(gè)匹配的依賴 |
$@ | 表示目標(biāo) |
$^ | 所有依賴 |
$? | 所有依賴中更新的文件 |
$+ | 所有依賴文件不去重 |
$(@D) | 目標(biāo)文件路徑 |
$(@F) | 目標(biāo)文件名稱 |
makefile 文件可改為:
TARGET = simpletest OBJS = simple.o LIB = libsimple.so CXXFLAGS = -c -fPIC LDFLAGS = -L. LDLIBS = -lsimple .PHONY: clean $(TARGET):simpletest.o $(LIB) $(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS) $(LIB):$(OBJS) $(CXX) -shared $^ -o $@ simple.o:simple.cpp $(CXX) $(CXXFLAGS) $< -o $@ simpletest.o:simpletest.cpp $(CXX) $(CXXFLAGS) $< -o $@ clean: $(RM) $(TARGET) $(OBJS) $(LIB)
自動(dòng)匹配:
通配符主要用于匹配文件名,makefile中使用%作為通配符。從匹配目標(biāo)格式的目標(biāo)名中依據(jù)通配符抽取部分字符串,再按照抽取字符串分配到每一個(gè)依賴格式中產(chǎn)生依賴名。例如,使用%.o:%.cpp
可以讓重復(fù)的語句合為一句
makefile 文件可改為:
TARGET = simpletest OBJS = simple.o LIB = libsimple.so CXXFLAGS = -c -fPIC LDFLAGS = -L. LDLIBS = -lsimple TESTOBJ = simpletest.o .PHONY: clean $(TARGET):$(TESTOBJ) $(LIB) $(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS) $(LIB):$(OBJS) $(CXX) -shared $^ -o $@ $(TESTOBJ) $(OBJS):%.o:%.cpp $(CXX) $(CXXFLAGS) $< -o $@ clean: $(RM) $(TARGET) $(OBJS) $(LIB) $(TESTOBJ)
3.2 動(dòng)態(tài)加載庫的建立與使用
TARGET = simpletest2 OBJS = simple.o LIB = libsimple.so CXXFLAGS = -c -fPIC LDLIBS = -ldl TESTOBJ = simpletest2.o .PHONY: clean # 生成可執(zhí)行文件 $(TARGET):$(TESTOBJ) $(LIB) $(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS) # 生成庫 $(LIB):$(OBJS) $(CXX) -shared $^ -o $@ # 生成目標(biāo)文件 $(TESTOBJ) $(OBJS):%.o:%.cpp $(CXX) $(CXXFLAGS) $< -o $@ clean: $(RM) $(TARGET) $(OBJS) $(LIB) $(TESTOBJ)
結(jié)果為:
[root@foundation1 C++7.4]# make clean
rm -f simpletest2 simple.o libsimple.so simpletest2.o
[root@foundation1 C++7.4]# make
g++ -c -fPIC simpletest2.cpp -o simpletest2.o
g++ -c -fPIC simple.cpp -o simple.o
g++ -shared simple.o -o libsimple.so
g++ simpletest2.o -o simpletest2 -ldl
[root@foundation1 C++7.4]# ./simpletest2
Simple()
Test()
~Simple()
總結(jié)
到此這篇關(guān)于C++學(xué)習(xí)進(jìn)階之Makefile基礎(chǔ)用法的文章就介紹到這了,更多相關(guān)C++ Makefile基礎(chǔ)用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ Primer Plus 第四章之C++ Primer Plus復(fù)合類型學(xué)習(xí)筆記
數(shù)組(array)是一種數(shù)據(jù)格式,能夠存儲(chǔ)多個(gè)同類型的值。每個(gè)值都存儲(chǔ)在一個(gè)獨(dú)立的數(shù)組元素中,計(jì)算機(jī)在內(nèi)存中依次存儲(chǔ)數(shù)組的各個(gè)元素,今天給大家重點(diǎn)介紹C++ Primer Plus復(fù)合類型的實(shí)例詳解,感興趣的朋友一起看看吧2021-07-07C++ Cartographer源碼中關(guān)于Sensor的數(shù)據(jù)走向深扒
這篇文章主要介紹了C++ Cartographer源碼中關(guān)于Sensor的數(shù)據(jù)走向,整個(gè)Cartographer源碼閱讀是很枯燥的, 但絕對是可以學(xué)到東西的,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03簡單比較C語言中的execl()函數(shù)與execlp()函數(shù)
這篇文章主要介紹了C語言中的execl()函數(shù)與execlp()函數(shù)的簡單比較,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-08-08C/C++讀寫JSON數(shù)據(jù)的詳細(xì)過程記錄
JSON文件無論是在web開發(fā)、客戶端開發(fā)、服務(wù)端等開發(fā)中都是應(yīng)用比較廣泛的的第一種輕量級(jí)數(shù)據(jù)交換格式,非常方便閱讀和編寫,下面這篇文章主要給大家介紹了關(guān)于C/C++讀寫JSON數(shù)據(jù)的詳細(xì)過程,需要的朋友可以參考下2023-04-04C語言實(shí)現(xiàn)簡易學(xué)生成績管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡易學(xué)生成績管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12