2010-07-10 122 views
2

我用GCC创建了一个静态库。图书馆的大楼还行。链接到静态库时获取未定义的引用

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

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

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

如果我移动这些功能在A或B它的作品。但如果他们在D模块中则不行。

我完全没有想法正在发生什么,或者我被忽略了什么。

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

+1

请为更多信息哪些功能是在C文件中,哪些得到了一个未定义的引用(以及您是否从另一个对象美其名曰该库或其他对象中的文件)。 – paxdiablo 2010-07-10 11:18:05

回答

1

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

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

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

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

0

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

2

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

即,在生成文件(或者你正在使用什么),提出:

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

无论如何,我希望你的想法。

1

在为了简化我的应用程序/库构建而写的master 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 /正则表达式技巧不好(我急着写这个东西),我最终得到了未定义。含有TXT:

-uSomeSym' 
-uSomeOtherSym' 

即具有尾随'

我然后使用这个补充语法来剥离的,并删除重复

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

的‘关注’过滤器是因为,如果一个未定义的符号被多次引用,输出中会出现“更多引用XXX跟随”的消息,这会导致undefined.txt文件中出现假“跟随”,例如

-Wl, uXXXX' follow 

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

$(application): $(library_dependencies) $(objects) undefined.txt 
    $(CC) -o [email protected] $(LDFLAGS) $(undefined_references) $(objects) $(LDLIBS) 

我最好的方式完全推荐下面的书,因为我能够从头开始写简单的构建系统在几天内。

管理与GNU项目制作,第三版 人:罗伯特·梅克伦堡

相关问题