链接到静态库时获取未定义的引用

时间:2010-07-10 10:57:50

标签: c gcc static-libraries linker-errors undefined-reference

我用GCC创建了一个静态库。图书馆的建设还行。

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

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

当我使用A和B中的函数时没问题,但是当我尝试使用D中的任何函数时,我会得到未定义的引用错误。

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

我完全没有想法发生了什么或者我被忽视了什么。

我正在使用Code :: Blocks并使用普通的C文件。

4 个答案:

答案 0 :(得分:2)

多次使用的旧技巧:在链接阶段列出每个静态库两次。

即,在你的makefile(或你正在使用的任何东西)中,输入:

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

无论如何,我希望你明白这一点。

答案 1 :(得分:1)

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

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

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

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

答案 2 :(得分: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'过滤器是因为如果多次引用未定义的符号,则输出中会出现“更多引用XXX follow”的消息,这会导致undefined.txt文件中出现虚假的“跟随”,例如

-Wl, uXXXX' follow

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

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

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

使用GNU Make管理项目,第三版 作者:罗伯特梅克伦堡

答案 3 :(得分:0)

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