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)識別的
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語言結(jié)構(gòu)體數(shù)組常用的三種賦值方法(包含字符串)
C語言只有在定義字符數(shù)組的時(shí)候才能用“=”來初始化變量,其它情況下是不能直接用“=”來為字符數(shù)組賦值的,下面這篇文章主要給大家介紹了關(guān)于C語言結(jié)構(gòu)體數(shù)組常用的三種賦值方法,需要的朋友可以參考下2022-06-06
windows下vscode環(huán)境c++利用matplotlibcpp繪圖
本文主要介紹了windows下vscode環(huán)境c++利用matplotlibcpp繪圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
Qt5中QML自定義環(huán)形菜單/環(huán)形選擇框的實(shí)現(xiàn)
本文主要介紹了Qt5中QML自定義環(huán)形菜單/環(huán)形選擇框的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
C++基于socket編程實(shí)現(xiàn)聊天室功能
這篇文章主要介紹了C++基于socket編程實(shí)現(xiàn)聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
C++輸出上三角/下三角/菱形/楊輝三角形(實(shí)現(xiàn)代碼)
本篇文章是對C++中輸出上三角/下三角/菱形/楊輝三角形的示例代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-07-07
c++中vector<int>和vector<int*>的用法及區(qū)別
這篇文章主要介紹了c++中vector<int>和vector<int*>的用法及區(qū)別,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2013-10-10

