我跟随Zed Shaw的教程"Learn C the Hard Way"并尝试自学c编程语言。
在我的ubuntu桌面上,我遇到了他在this post的说明中提到的链接问题。
也就是说,当使用如下命令链接静态库和gcc时:
gcc -Wall -g -DNDEBUG -lmylib ex29.c -o ex29
链接器无法在lib中找到这些函数。要正确链接,我必须将源文件和lib的顺序更改为:
gcc -Wall -g -DNDEBUG ex29.c -lmylib -o ex29
我尝试使用Zed提供的makefile来自动化单元测试。 makefile如下所示:
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libYOUR_LIBRARY.a
tests: CFLAGS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
这里没有列出的makefile的其余部分可以完美地构建$(TARGET)lib。
问题是Zed将lib附加到$(CFLAGS)并使用隐式规则来编译测试文件,从而产生如下命令:
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG tests/hashmap_tests.c build/mylib.a -o tests/list_tests
由于前面提到的链接问题,该命令失败了。
我想出的解决方案是明确地编写编译命令,这样我就可以改变顺序了:
$(TESTS): $(TARGET)
$(CC) $(CFLAGS) $^ $(TARGET) -o $@
如果只有一个主源文件,这可以正常工作。不幸的是,我在./tests目录下有几个,而像这样的命令是完全灾难。
我的问题是,我应该如何更改我的makefile以使其正常工作?还是有其他任何方式我可以像预期的那样做同样优雅的工作?
答案 0 :(得分:2)
CFLAGS
包含编译器标志,如-g -O2
。您不应该向其添加链接器标志。 CPPFLAGS
保存预处理程序标志,如-Isrc -DNDEBUG
。 LDFLAGS
保存链接器标志,如果需要它来查找库,可以包含-L
(大写字母L)等内容,以及-rdynamic
。 LDLIBS
变量保存库,因此您应该这样做:
CPPFLAGS = -Isrc -DNDEBUG
CFLAGS = -g -O2 -Wall -Wextra
LDFLAGS = -rdynamic
LDLIBS = -lmylib
现在,您可以使用GNU make的内置规则来构建程序。您可以通过运行make -p -f/dev/null
来查看内置规则列表。
当然,上面只是默认变量make define和use with its default rules。你不必使用它们,但总的来说,遵循惯例而不是炫耀它们会更好。