Make

pkg-config 輸出不適用於makefile?

  • February 10, 2020

我正在嘗試執行makefile,顯示在這個 repo中,它是一個簡單的 Wayland 客戶端。但是當我執行make時,它的輸出似乎$(WAYLAND)是空白的,並且由於無法找到必要的wayland-client.h標頭檔而無法編譯。bash 中 Fedora 23 上的 cc (GCC) 版本 5.3.1。

下面是一些細節。我的問題是,我在環境中犯了什麼錯誤,導致這個makefile無法按預期為我工作?

makefile的內容:

WAYLAND=`pkg-config wayland-client --cflags --libs`
CFLAGS?=-std=c11 -Wall -Werror -O3 -fvisibility=hidden

hello_wayland: hello_wayland.o helpers.o helpers.h images.bin
   $(CC) -o hello_wayland *.o $(WAYLAND) -lrt

images.bin: images/convert.py images/window.png images/fish.png
   images/convert.py
   cat window.bin fish.bin > images.bin

clean:
   $(RM) *.o fish.bin window.bin hello_wayland

make的輸出:

cc -std=c11 -Wall -Werror -O3 -fvisibility=hidden -c -o hello_wayland.o hello_wayland.c hello_wayland.c:6:28:致命錯誤:wayland-client.h:沒有這樣的文件或目錄

請注意,上面cc的選項似乎缺少makefile$(WAYLAND)中指定的輸出。如果我像這樣手動執行cc

cc -std=c11 -Wall -Werror -O3 -fvisibility=hidden -c -o hello_wayland.o hello_wayland.c \
-I/home/me/install/include -L/home/me/install/lib -lwayland-client

編譯成功。

pkg-config wayland-client –cflags –libs 的輸出:

-I/home/me/install/include -L/home/me/install/lib -lwayland-client

~/.bash_profile的內容:

source ~/.profile
source ~/.bashrc

~/.bashrc的相關內容:

export WLD=$HOME/install
export LD_LIBRARY_PATH=$WLD/lib
export PKG_CONFIG_PATH=$WLD/lib/pkgconfig/:$WLD/share/pkgconfig/
export PATH=$WLD/bin:$PATH
export ACLOCAL_PATH=$WLD/share/aclocal
export ACLOCAL="aclocal -I $ACLOCAL_PATH"

感謝您指出對我來說可能完全顯而易見的事情。

發布的 makefile 缺少一些細節

注意:(幾乎)總是最好將編譯步驟與連結步驟分開

以下 makefile 更正了這些細節

注意:<tab>表示在實際makefile中使用tab鍵

RM             := /usr/bin/rm

LFLAGS         += `pkg-config wayland-client --libs`

CFLAGS         := -std=c11 -Wall -Werror -O3 -fvisibility=hidden
CFLAGS         += `pkg-config wayland-client --cflags`

OBJS           := hello_wayland.o helpers.o
HDRS           := helpers.h

TARGET         := hello_wayland

.PHONY: all
all: $(TARGET)

$(TARGET): $(OBJS) images.bin
<tab>$(CC) -o hello_wayland *.o $(LFLAGS) -lrt

%.o:%.c $(HDRS)
<tab>$(CC) $(CFLAGS)-c $< -o $@ -I.

images.bin: images/convert.py images/window.png images/fish.png
<tab>images/convert.py
<tab>cat window.bin fish.bin > images.bin

.PHONY: clean
clean:
<tab>$(RM) *.o fish.bin window.bin hello_wayland

你問原始makefile有什麼問題:

以下是一些觀察:

make 文件中的宏有兩種類型:

  • 那些只使用一次評估的:=
  • 每次被引用時評估的那些=

在規則

WAYLAND =`pkg-config wayland-client --cflags --libs`

WAYLAND每次引用都會重新評估

CFLAGS ?= -std=c11 -Wall -Werror -O3 -fvisibility=hidden

宏的格式無效。 ?=應該:=

在 aMakefile中,典型用法是,make all 但是此 makefile 缺少連結步驟的目標(應該是第一個目標,因此make 它本身將執行第一個目標)targets不應該是實際文件名,而是該宏包含的宏名目標名稱

宏的這種用法還使得在呼叫時設置生成的執行檔名變得容易,make而任何一種方式都可以工作,為了靈活性,最好創建一個宏。

在編寫遞歸 makefile 或多個不同的執行檔時尤其如此

hello_wayland: hello_wayland.o helpers.o helpers.h images.bin

這是一個連結步驟,帶有隱藏編譯,使用預設配方,它對任何特定的標頭檔一無所知,因此如果標頭檔更改並且標頭檔helpers.h不應該在連結步驟中,則不會進行隱藏編譯。

   $(CC) -o hello_wayland *.o $(WAYLAND) -lrt

*.o是一個glob操作,不應該在 makefile 中使用,而是使用 make 工具:

SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)

’target’ 被正確引用,$@如果使用 ’target’ 則不會出現按鍵錯誤$@

images.bin: images/convert.py images/window.png images/fish.png
   images/convert.py
   cat window.bin fish.bin > images.bin

當 atarget不是生成文件的名稱時,尤其是在較舊版本的 中make,則目標需要以a 開頭.PHONY:

.PHONY: <list of target names that produce no actual output file>

clean:
   $(RM) *.o fish.bin window.bin hello_wayland

在 makefile 中使用glob操作(例如*.o)是個壞主意。而是使用適當的宏,如$(OBJS)上面列出的宏

那麼,為什麼原來的 makefile 不起作用呢?累積成失敗的事物的組合。以下是更明顯的原因:

1) the incorrect setting of the CFLAGS macro
2) the combining of the link operation with the compile operations
3) the missing .PHONY: statement
4) the use of the `glob` statements

引用自:https://unix.stackexchange.com/questions/271087