使用gcc和gnu make链接静态库

时间:2014-12-13 06:11:39

标签: gcc makefile linker

我跟随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以使其正常工作?还是有其他任何方式我可以像预期的那样做同样优雅的工作?

1 个答案:

答案 0 :(得分:2)

CFLAGS包含编译器标志,如-g -O2。您不应该向其添加链接器标志。 CPPFLAGS保存预处理程序标志,如-Isrc -DNDEBUGLDFLAGS保存链接器标志,如果需要它来查找库,可以包含-L(大写字母L)等内容,以及-rdynamicLDLIBS变量保存库,因此您应该这样做:

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。你不必使用它们,但总的来说,遵循惯例而不是炫耀它们会更好。