试图包含一个库,但不断收到“未定义的引用”消息


72

我正在尝试使用libtommath库。我在Ubuntu linux上的项目中使用的是NetBeans IDE。我已经下载并构建了该库,我已经进行了“ make install”操作,将生成的.a文件放入/ usr / lib /,并将.h文件放入/ usr / include

它似乎正在适当地查找文件(因为我不再遇到那些错误,这是在安装到/ usr目录之前所做的)。

但是,当我创建一个简单的main来调用mp_init(位于库中)时,在尝试创建项目时出现以下错误:

mkdir -p build/Debug/GNU-Linux-x86
rm -f build/Debug/GNU-Linux-x86/main.o.d
gcc -c -g -MMD -MP -MF build/Debug/GNU-Linux-x86/main.o.d -o build/Debug/GNU-Linux-x86/main.o main.c
mkdir -p dist/Debug/GNU-Linux-x86
gcc -o dist/Debug/GNU-Linux-x86/cproj1 build/Debug/GNU-Linux-x86/main.o
build/Debug/GNU-Linux-x86/main.o: In function 'main':
/home/[[myusername]]/NetBeansProjects/CProj1/main.c:18: undefined reference to `mp_init'
collect2: ld returned 1 exit status
make[2]: *** [dist/Debug/GNU-Linux-x86/cproj1] Error 1

因此,看起来链接器无法在库中找到该函数,但是它在那里,所以我只是不知道是什么原因引起的。

如果直接键入gcc命令并跳过makefile,则会遇到相同的错误,同时还要确保静态库也已使用gcc进行了编译。

编辑添加:

如果直接进行编译并使用-l或-L添加库,则会遇到这些相同的错误:

$ gcc -l /usr/lib/libtommath.a main.c 
/usr/bin/ld: cannot find -l/usr/lib/libtommath.a
collect2: ld returned 1 exit status

$ gcc -llibtommath.a main.c 
/usr/bin/ld: cannot find -llibtommath.a
collect2: ld returned 1 exit status

$ gcc -Llibtommath.a main.c 
/tmp/ccOxzclw.o: In function `main':
main.c:(.text+0x18): undefined reference to `mp_init'
collect2: ld returned 1 exit status

$ gcc -Llibtommath.a main.c 
/tmp/ccOxzclw.o: In function `main':
main.c:(.text+0x18): undefined reference to `mp_init'
collect2: ld returned 1 exit status

我对这些东西非常生锈,所以我不确定在这里使用的命令是否正确,在-L示例中是否找到了库?如果找不到该图书馆,那么我如何才能找到该图书馆?它在/ usr / lib中,我已经用当前目录中的.a文件进行了尝试,等等。是否需要设置环境变量?如果是这样,如何等等。

我尝试了一个完全不同的库(GMP),并遇到了完全相同的问题。这一定是某种Ubuntu环境问题吗?有人知道如何解决此问题吗?

Answers:


159

这里的技巧是将库放在正在编译的模块之后。问题是参考。链接器按顺序解析引用,因此当库在编译模块之前时,链接器会感到困惑,并且认为不需要库中的任何功能。通过将库放在模块之后,链接器将解析对模块中库的引用。


10
+1哦,谢谢!我知道链接解析顺序是很合理的做法,但要记住这些事实确实有帮助!
Shalom Craimer 2011年

2
这对我有用。我以前很老的makefile曾经可以工作,但是现在看来编译器变得太聪明了:)
gak 2012年

1
我不愿重复另一个问题:stackoverflow.com/questions/12748837/…因为该答案增加了一个细节:“ GCC reuqire的最新版本中,您将目标文件和库按照它们相互依赖的顺序放置” 。
维克托·谢尔吉琴科

1
我想投票给你1000次-我花了几天的时间试图让我的项目链接起来,而你的解决方案就是解决方案!
piccy

1
2020年且仍然有意义
GottZ


6

如果.c源文件已转换为.cpp(如在parsec中一样),则extern后面必须跟“ C”,如

extern "C" void foo();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.