我正在尝试运行生成文件,如图所示这个仓库,这是一个简单的 Wayland 客户端。但当我跑步时制作,看起来输出$(WAYLAND)
是空白的,并且由于找不到必要的内容而无法编译Wayland-client.h头文件。 Fedora 23 上的 bash 中的 cc (GCC) 版本 5.3.1。
以下是一些详细信息。我的问题是,我的环境出了什么问题,导致无法实现这一点生成文件按预期为我工作?
内容生成文件:
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
输出制作:
cc -std=c11 -Wall -Werror -O3 -fvisibility=hidden -c -o hello_wayland.o hello_wayland.c hello_wayland.c:6:28:致命错误:wayland-client.h:没有这样的文件或目录
请注意选项如何抄送上面似乎缺少$(WAYLAND)
指定的输出生成文件。如果我手动执行抄送像这样:
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"
感谢您指出一些对我来说可能完全显而易见的事情。
答案1
发布的 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
宏格式无效。 ?=
应该:=
在 a 中Makefile
,典型用法是,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)
“目标”被正确引用,并且如果使用,$@
则不会出现击键错误。$@
images.bin: images/convert.py images/window.png images/fish.png
images/convert.py
cat window.bin fish.bin > images.bin
当 atarget
不是生成的文件的名称时,特别是在旧版本的 中make
,则目标前面需要带有.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