2014-12-13 101 views
1

我遵循Zed Shaw的教程"Learn C the Hard Way"并试图教自己c编程语言。使用gcc链接静态库与gnu使

在我的ubuntu桌面上,我遇到了他在this post的注释中提到的链接问题。

也就是说,连接用gcc静态库时,使用如下命令:

gcc -Wall -g -DNDEBUG -lmylib ex29.c -o ex29 

链接器无法找到在lib的功能。要正确链接,我要的源文件和lib的顺序改成这样:

gcc -Wall -g -DNDEBUG ex29.c -lmylib -o ex29 

我试图使用由捷思锐提供的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 

这里没有列出可以完美打造$(TARGET)lib中的Makefile文件的剩余部分。

问题是捷思锐追加的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 [email protected] 

此工作正常,如果只有一个主源文件。不幸的是,我在./tests目录下有几个这样的命令,并且像这样的命令完全是一场灾难。

我的问题是,我应该如何更改我的makefile以使其工作,或者是否有其他方式可以像预期的那样执行相同的工作?

回答

2

CFLAGS保存编译器标志,如-g -O2。你不应该添加链接器标志。 CPPFLAGS包含预处理器标志,如-Isrc -DNDEBUGLDFLAGS包含链接器标志,其中包括如-L(大写L),如果您需要它来查找库,以及-rdynamic。而LDLIBS变量保存库,所以你应该这样做:

CPPFLAGS = -Isrc -DNDEBUG 
CFLAGS = -g -O2 -Wall -Wextra 
LDFLAGS = -rdynamic 
LDLIBS = -lmylib 

现在你可以使用GNU内置规则使建立你的程序。您可以通过运行make -p -f/dev/null来查看内置规则的列表。

当然,以上只是默认的变量make定义和使用其默认规则。你不必使用它们,但总的来说,最好遵循约定而不是炫耀它们。

+0

谢谢你的回答! – 2014-12-15 11:59:17