3

我用 GCC 制作了一个静态库。图书馆的建设还可以。

当我使用它时,链接器会在某些函数上引发未定义的引用错误。但是nm说函数是在静态库中定义和导出的(用 T 标记)。我知道我需要将库放在需要它们的模块之后的链接顺序,所以这不是问题。

静态库是从 3 个 C 文件构建的。Ac Bc 和 Dc D 模块依赖于 A 和 B(包括它们的标题)。

当我使用 A 和 B 中的函数时没问题,但是当我尝试使用 DI 中的任何函数时,它们会出现未定义的引用错误。

如果我在 A 或 B 中移动这些功能,它就可以工作。但如果它们在 D 模块中,则不是。

我完全不知道发生了什么或我忽略了什么。

我正在使用 Code::Blocks 并使用纯 C 文件。

4

4 回答 4

3

一个多次有效的老技巧:在链接阶段列出每个静态库两次。

即,在您的makefile(或您正在使用的任何内容)中,输入:

gcc -o <outfile> <liba> <libb> <libc> <liba> <libb> <libc>

无论如何,我希望你能明白。

于 2010-07-10T17:09:56.457 回答
1

我发现我在我的项目中添加了一个 .cpp 文件,我只是将它重命名为 .c。我在创建项目时选择了 C 语言而不是 C++。我不认为这会导致问题

我认为文件扩展名决定了 IDE 何时在 gcc 和 g++ 之间进行选择。但不是。在 Code::Blocks 中,如果您添加扩展名为 .cpp 的文件,它将使用 g++。如果添加扩展名为 .c 的文件,它将使用 gcc。但是,如果您重命名文件,它将使用相同的编译器。您必须在项目选项中明确更改它。

该 D 模块是使用 g++ 而不是 gcc 构建的。

当我将 IDE 设置为在构建时显示整个命令行而不仅仅是“编译 foo.c”时,我意识到了这一点。

于 2010-07-12T18:14:14.987 回答
1

在我为简化应用程序/库构建而编写的主 make 文件中,我使用的解决方案是运行链接步骤两次。使用 -u 链接器选项在第二个链接上指定未定义的符号。

在我的make文件中,我有一个这样的目标:

undefined.txt:
    @$(generate-undefined-syms)

它调用这个宏......第一次尝试链接......

define generate-undefined-syms
    $(PRINTF) "$(this_makefile): Generating undefined symbols ... \n"
    $(CC) -o rubbish $(LDFLAGS) $(objects) $(LDLIBS) 2>&1 | $(GREP) 'undefined reference' > tmp.txt; \
    $(SED) 's/^.*`/-Wl,-u/g' < tmp.txt > undefined.txt; \
    rm -f tmp.txt rubbish
endef

由于我的 sed/regexp 技能不好(而且我匆忙写了这些东西),我最终得到了 undefined.txt,其中包含:

-uSomeSym'
-uSomeOtherSym'

即带有尾随'

然后我使用这个 make 语法去除's,并删除重复项

undefined_references = $(filter-out follow, $(sort $(subst ',,$(shell cat undefined.txt))))

'follow' 过滤器是因为如果多次引用一个未定义的符号,输出中会出现“more references to XXX follow”的消息,这会导致 undefined.txt 文件中出现虚假的“follow”,例如

-Wl, uXXXX' follow

最后我第二次链接(注意对undefined.txt的依赖)

$(application): $(library_dependencies) $(objects) undefined.txt
    $(CC) -o $@ $(LDFLAGS) $(undefined_references) $(objects) $(LDLIBS)

顺便说一句,我完全推荐了以下书,因为我能够在几天内从头开始编写一个简单的构建系统。

使用 GNU Make 管理项目,第三版 作者:Robert Mecklenburg

于 2012-05-18T16:16:18.820 回答
0

也许您应该使用ranlib或适当的ar选项来为您的 .a 文件提供索引。

于 2010-07-10T11:06:38.037 回答