1. 程式人生 > 實用技巧 >《精通Linux C程式設計》Ch5教學視訊--make的使用和Makefile的編寫

《精通Linux C程式設計》Ch5教學視訊--make的使用和Makefile的編寫

讀string

刪除string中部分內容

列印處理後的string

all : main.c foo1.c foo2.c foo3.c

gcc main.c foo1.c foo2.c foo3.c -o all

打勾命令常用

Makefile選項CFLAGS,LDFLAGS,LIBS

CFLAGS 表示用於 C 編譯器的選項,
CXXFLAGS 表示用於 C++ 編譯器的選項。
這兩個變數實際上涵蓋了編譯和彙編兩個步驟。

CFLAGS: 指定標頭檔案(.h檔案)的路徑,如:CFLAGS=-I/usr/include -I/path/include。同樣地,安裝一個包時會在安裝路徑下建立一個include目錄,當安裝過程中出現問題時,試著把以前安裝的包的include目錄加入到該變數中來。

LDFLAGS:gcc 等編譯器會用到的一些優化引數,也可以在裡面指定庫檔案的位置。用法:LDFLAGS=-L/usr/lib -L/path/to/your/lib。每安裝一個包都幾乎一定的會在安裝目錄裡建立一個lib目錄。如果明明安裝了某個包,而安裝另一個包時,它愣是說找不到,可以抒那個包的lib路徑加入的LDFALGS中試一下。

LIBS

:告訴連結器要連結哪些庫檔案,如LIBS = -lpthread -liconv

簡單地說,LDFLAGS是告訴連結器從哪裡尋找庫檔案,而LIBS是告訴連結器要連結哪些庫檔案。不過使用時連結階段這兩個引數都會加上,所以你即使將這兩個的值互換,也沒有問題。

有時候LDFLAGS指定-L雖然能讓連結器找到庫進行連結,但是執行時連結器卻找不到這個庫,如果要讓軟體執行時庫檔案的路徑也得到擴充套件,那麼我們需要增加這兩個庫給"-Wl,R":

LDFLAGS = -L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib

如果在執行./configure以前設定環境變數export LDFLAGS="-L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib" ,注意設定環境變數等號兩邊不可以有空格,而且要加上引號(shell的用法)。那麼執行configure以後,Makefile將會設定這個選項,連結時會有這個引數,編譯出來的可執行程式的庫檔案搜尋路徑就得到擴充套件了。

% 定義對檔名的匹配

https://www.ruanyifeng.com/blog/2015/02/make.html

有時,變數的值可能指向另一個變數。


v1 = $(v2)

上面程式碼中,變數 v1 的值是另一個變數 v2。這時會產生一個問題,v1 的值到底在定義時擴充套件(靜態擴充套件),還是在執行時擴充套件(動態擴充套件)?如果 v2 的值是動態的,這兩種擴充套件方式的結果可能會差異很大。

為了解決類似問題,Makefile一共提供了四個賦值運算子 (=、:=、?=、+=),它們的區別請看StackOverflow


VARIABLE = value
# 在執行時擴充套件,允許遞迴擴充套件。

VARIABLE := value
# 在定義時擴充套件。

VARIABLE ?= value
# 只有在該變數為空時才設定值。

VARIABLE += value
# 將值追加到變數的尾端。

3.6 內建變數(Implicit Variables)

Make命令提供一系列內建變數,比如,$(CC) 指向當前使用的編譯器,$(MAKE) 指向當前使用的Make工具。這主要是為了跨平臺的相容性,詳細的內建變數清單見手冊


output:
    $(CC) -o output input.c

3.7 自動變數(Automatic Variables)

Make命令還提供一些自動變數,它們的值與當前規則有關。主要有以下幾個。

(1)$@

$@指代當前目標,就是Make命令當前構建的那個目標。比如,make foo的 $@ 就指代foo。


a.txt b.txt: 
    touch $@

等同於下面的寫法。


a.txt:
    touch a.txt
b.txt:
    touch b.txt

(2)$<

$< 指代第一個前置條件。比如,規則為 t: p1 p2,那麼$< 就指代p1。


a.txt: b.txt c.txt
    cp $< $@ 

等同於下面的寫法。


a.txt: b.txt c.txt
    cp b.txt a.txt 

(3)$?

$? 指代比目標更新的所有前置條件,之間以空格分隔。比如,規則為 t: p1 p2,其中 p2 的時間戳比 t 新,$?就指代p2。

(4)$^

$^ 指代所有前置條件,之間以空格分隔。比如,規則為 t: p1 p2,那麼 $^ 就指代 p1 p2 。

(5)$*

$* 指代匹配符 % 匹配的部分, 比如% 匹配 f1.txt 中的f1 ,$* 就表示 f1。

(6)$(@D) 和 $(@F)

$(@D) 和 $(@F) 分別指向 $@ 的目錄名和檔名。比如,$@是 src/input.c,那麼$(@D) 的值為 src ,$(@F) 的值為 input.c。

(7)$(<D) 和 $(<F)

$(<D) 和 $(<F) 分別指向 $< 的目錄名和檔名。

所有的自動變數清單,請看手冊。下面是自動變數的一個例子。


dest/%.txt: src/%.txt
    @[ -d dest ] || mkdir dest
    cp $< $@

上面程式碼將 src 目錄下的 txt 檔案,拷貝到 dest 目錄下。首先判斷 dest 目錄是否存在,如果不存在就新建,然後,$< 指代前置檔案(src/%.txt), $@ 指代目標檔案(dest/%.txt)。