【问题标题】:Link static library using gcc with gnu make使用 gcc 和 gnu make 链接静态库
【发布时间】:2014-12-13 06:11:39
【问题描述】:

我正在关注 Zed Shaw 的教程 "Learn C the Hard Way" 并尝试自学 c 编程语言。

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

也就是说,当用 gcc 链接静态库时,使用这样的命令:

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

链接器无法在库中找到函数。要正确链接,我必须将源文件和库的顺序更改为:

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

我正在尝试使用 Zed 提供的 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) 库。

问题是 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 以使其正常工作,或者有没有其他方法可以像预期的那样优雅地完成相同的工作?

【问题讨论】:

    标签: gcc makefile linker


    【解决方案1】:

    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定义的默认变量,并使用其默认规则。您不必使用它们,但总的来说,最好遵循惯例而不是炫耀它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      • 2012-10-25
      • 2010-10-23
      相关资源
      最近更新 更多