浅显易懂 Makefile 入门 (03)— 目标文件搜索(VPATH 和 vpath 的区别和使用)、隐含规则
1. 目標文件搜索(VPATH和vpath)
如果需要的文件是存在于不同的路徑下(即源文件與 Makefile 文件不在同一個路徑下),在編譯的時候就用到了 Makefile 中為我們提供的目錄搜索文件的功能。
常見的搜索的方法的主要有兩種:
VPATH是變量,使用時需要指定文件的路徑,是搜索路徑下所有的文件;vpath是關鍵字,按照模式搜索,也可以說成是選擇搜索。搜索的時候不僅需要加上文件的路徑,還需要加上相應限制的條件;
1.1 VPATH
在 Makefile 中可以這樣寫:
VPATH := dir
我們可以這樣理解,把 dir 的值賦值給變量 VPATH,所以在執行 make 的時候會從 dir 目錄下找我們需要的文件。
當存在多個路徑的時候我們可以這樣寫:
VPATH := dir dir2
或者是
VPATH := dir:dir2
多個路徑之間要使用空格或者是冒號隔開,表示在多個路徑下搜索文件。搜索的順序為我們書寫時的順序,應該先搜索 dir 目錄下的文件,再搜索 dir2 目錄下的文件。
注意:無論定義了多少路徑,
make執行的時候會先搜索當前路徑下的文件,當前目錄下沒有我們要找的文件,才去VPATH的路徑中去尋找。如果當前目錄下有我們要使用的文件,那么make就會使用我們當前目錄下的文件。
代碼目錄結構如下:
wohu@ubuntu:~/cpp/demo$ tree
.
├── header
│ └── name.h
├── Makefile
└── source├── main.cpp└── name.cpp2 directories, 4 files
wohu@ubuntu:~/cpp/demo$
Makefile 放在 header 和 source 目錄同級目錄。編寫 Makefile 如下:
main: main.o name.og++ main.o name.o -o main
執行 make 會報錯:
make: *** No rule to make target 'main.o', needed by 'main'. Stop.
重建最終目標文件 main 的時候我們需要 main.o 文件,但是沒有找到 main.o 文件,這是錯誤的根本原因。
加上路徑搜索
VPATH = source header
main: main.o name.og++ main.o name.o -o main
輸入 make 即可正常運行
wohu@ubuntu:~/cpp/demo$ make
g++ -c -o main.o source/main.cpp
g++ -c -o name.o source/name.cpp
g++ main.o name.o -o main
wohu@ubuntu:~/cpp/demo$
3.2 vpath
具體用法:
vpath PATTERN DIRECTORIES
vpath PATTERN
vpath
其中:
PATTERN:為要尋找的條件;DIRECTORIES:尋找的路徑;
首先是用法一,命令格式如下:
vpath main.cpp dir
可以這樣理解,在 dir 路徑下搜索文件 main.cpp。多路徑的書寫規則如下:
vpath main.cpp dir dir2 或者是 vpath main.cpp dir : dir2
多路徑的用法其實和 VPATH 差不多,都是使用空格或者是冒號分隔開,搜索路徑的順序是先 dir 目錄,然后是 dir2 目錄。
其次是用法二,命令格式如下:
vpath main.cpp
用法二的意思是清除符合文件 main.cpp 的搜索目錄。
最后是用法三,命令格式如下:
vpath
vpath 單獨使的意思是清除所有已被設置的文件搜索路徑。
另外在使用 vpath 的時候,搜索的條件中可以包含模式字符 %,這個符號的作用是匹配一個或者是多個字符,例如 %.cpp表示搜索路徑下所有的 .cpp 結尾的文件。如果搜索條件中沒有包含 % ,那么搜索的文件就是具體的文件名稱。
使用 VPATH 的情況是前路徑下的文件較少,或者是搜索的文件不能使用通配符表示,這些情況下使用 VPATH 最好。
如果存在某個路徑的文件特別的多或者是可以使用通配符表示的時候,就不建議使用 VPATH 這種方法,為什么呢?
因為 VPATH 在去搜索文件的時沒有限制條件,所以它回去檢索這個目錄下的所有文件,每一個文件都會進行對比,搜索和我們目錄名相同的文件,不僅速度會很慢,而且效率會很低。
我們在這種情況下就可以使用 vpath 搜索,它包含搜索條件的限制,搜索的時候只會從我們規定的條件中搜索目標,過濾掉不符合條件的文件,當然查找的時候也會比較的快。
使用示例:
vpath %.cpp source
main: main.o name.og++ main.o name.o -o main
2. 隱含規則
所謂的隱含規則就是系統自動完成一些動作。在某些時候其實不需要給出重建目標文件的命令,有的甚至可以不需要給出規則。
例如:
vpath %.cpp source
main: main.o name.og++ main.o name.o -o main
執行 make 后,輸出結果:
wohu@ubuntu:~/cpp/demo$ make
g++ -c -o main.o source/main.cpp
g++ -c -o name.o source/name.cpp
g++ main.o name.o -o main
wohu@ubuntu:~/cpp/demo$
系統自動執行了一下兩行語句
g++ -c -o main.o source/main.cpp
g++ -c -o name.o source/name.cpp
注意:隱含條件只能省略中間目標文件重建的命令和規則,但是最終目標的命令和規則不能省略。
下面這個 makefile 是和上面等價的。
vpath %.cpp source
main: main.o name.og++ main.o name.o -o main
main.o: main.cppg++ -c ./source/main.cpp -o main.o
name.o: name.cpp g++ -c ./source/name.cpp -o name.o
執行 make 后,輸出結果:
wohu@ubuntu:~/cpp/demo$ make
g++ -c ./source/main.cpp -o main.o
g++ -c ./source/name.cpp -o name.o
g++ main.o name.o -o main
wohu@ubuntu:~/cpp/demo$
需要注意的是:通過
VPATH/vpath告知文件搜尋路徑是告知的是make,這利于它隱式推導時的文件搜索,而不是告知的gcc,所以還是得通過-I指定gcc預編譯時頭文件搜索路徑。
2.1 命令變量隱式規則
書寫 Makefile 可以直接寫 shell 時用這些變量。下面只列出一些 C/C++ 相關的:
| 變量名 | 含義 |
|---|---|
| RM | rm -f |
| AR | ar |
| CC | cc |
| CXX | g++ |
示例:
all:@echo $(RM)@echo $(AR)@echo $(CC)@echo $(CXX)
執行 make, 顯示各個變量的值
wohu@ubuntu:~/cpp/func$ make
rm -f
ar
cc
g++
wohu@ubuntu:~/cpp/func$
2.2 命令參數變量
| 變量名 | 含義 |
|---|---|
| ARFLAGS | AR命令的參數 |
| CFLAGS | C語言編譯器的參數 |
| CXXFLAGS | C++語言編譯器的參數 |
示例: 下面以 CXXFLAGS 為例演示
#include <iostream>int main(int argc, char *argv[])
{std::cout << "hello,world" << std::endl;return 0;
}
Makefile 內容
CXXFLAGS += -Wall
main: demo.o$(CXX) demo.o -o main
執行 make
wohu@ubuntu:~/cpp/func$ make
g++ -Wall -c -o demo.o demo.cpp <-- 這個是隱式規則自動推導的
g++ demo.o -o main
wohu@ubuntu:~/cpp/func$
總結
以上是生活随笔為你收集整理的浅显易懂 Makefile 入门 (03)— 目标文件搜索(VPATH 和 vpath 的区别和使用)、隐含规则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国PGA树脂行业全
- 下一篇: 2022-2028年中国TAC薄膜行业市