将Linux编译程序移植到MAC OS X时获取未定义的符号

时间:2012-11-02 21:35:20

标签: linux macos porting undefined-symbol

我正在尝试在MAC OSX上编译程序,最初是在Linux OS上编写的。这是一个包含多个makefile的大程序。我已经工作了几个星期,现在似乎无法弄清楚为什么导致未定义的符号错误。有一个总体Makefile调用其他makefile,以便编译顺序正确。

编译时,它会创建静态库以及多个应用程序。因为这些人非常庞大,程序首先会创建这些静态库(.a文件)。然后,当它专门为应用程序编译源代码时,它链接静态库。 (希望这不是太混乱)。

我可以很好地完成静态库的构建,但是一旦我到达构建应用程序的时间点,我会收到大量未定义的符号错误,例如

未定义的符号:   “_bagUpdateOptSurface”,引自:       libdbdbv6.a中的_dbv_bag(dbv_bag.o)

当我用nm检查dbv_bag.o时,我得到了很多未使用标题U定义的函数。

我可以用nm跟踪这个函数并找到...

bagUpdateOptSurface.c - > bagUpdateOptSurface.o - > libbag.a ---> dbv_bag.c ---> dbv_bag.o ---> libdbdv6.a --->应用程序

该函数是通过带有标题T的静态库libbag.a定义的,但是对象文件dbb_bag.o将其定义为U.在某处信息丢失,我似乎无法理解为什么。

如果那里有更多将Mac程序移植到mac的经验可以帮助我们了解正在发生的事情,我将非常感激。欢迎任何想法是对还是错。

提前致谢

1 个答案:

答案 0 :(得分:0)

出于好奇,您是否尝试使用 gcc g ++ 进行链接而不是 ld ?通常这些大型项目使用带有已定义变量的makefile,你可以说使LD = gcc target 或其他一些东西。

只要有“T”版本,很多“U”标志都无关紧要。

您可能会尝试制作一个简单的例子。只需几个简短的1或2行源文件,编译为.o(带-c标志),放入库(ar -rv),看看是否可以重现问题。一旦简化,答案通常更容易找到。

如果它不是链接器标志问题,它可能是链接行上的排序问题(依赖地狱)。或者你可能只是错过某个地方的图书馆。

我想我也应该查询你正在使用的gcc / g ++版本,以及OSX的版本......

另一种可能性是使用g ++意外重载函数,可能还有来自实现的不同标题签名。

您可以尝试删除所有.o和库文件并重新编译世界(所有内容)。有时.o文件(或库)从源文件/头文件中过时,导致非常多的痛苦和痛苦......



回应评论:

如上所述,虽然埋没了,但上面:这类问题经常引用依赖地狱和命令行上的链接排序。至少他们习惯了。我不确定是否仍然如此。

你可以复制目录,删除尽可能多的代码(二进制搜索调试),做一个简单的例子,问题通常变得更容易识别。

使用gcc / g ++进行链接:您可以通过 gcc -c file.c 编译为 file.o ,然后链接 file.o 通过 ld 输入可执行文件。或者您可以执行 gcc file.o -o file 调用 gcc ,然后使用适当的参数调用 ld 。如果你不太确定你需要的库,或者你需要传递给 ld 的标志,它会很有用。

Gcc 4.2.1和OSX 10.6.8应该不是问题。我只是好奇你是否使用了过时的东西,因为旧的编译器有一些有趣的缺点/问题。

虽然现在我考虑过,你在Linux下使用什么编译器进行编译?您可能在OSX下使用更新/更旧的gcc / g ++编译器,而您的问题源于编译器的“改进”。

重载函数:Gcc / g ++通常根据文件名后缀确定C vs C ++编译。 OSX通常具有不区分大小写的文件系统。因此,无论文件名为 file.c 还是文件, gcc file.c g ++ file.C 都能正常工作。 ç的。但是,C和C ++语言的差异可能会让你感到困惑。例如,如果您定义了 foo(signed int),则类型信息将被合并(修改)到C ++编译下的已编译函数名称中。随后从C代码调用它不一定有效(正确链接)。

同样,如果头文件说 foo(short int),源代码说 foo(long int),你可能会遇到有趣的问题。