将linux编译程序移植到macOS时获取未定义的符号

问题描述 投票:1回答:1

我正在尝试在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方面具有更多经验,可以帮助您了解正在发生的事情,我将非常感激。任何对与错的想法都欢迎。

预先感谢

linux macos porting undefined-symbol
1个回答
0
投票

出于好奇,您是否尝试过使用gccg ++而不是ld进行链接?通常,这些大型项目使用带有已定义变量的makefile,而您只能说make LD = gcc target或类似的东西。

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

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

如果不是链接器标志问题,则可能是链接行上的排序问题(依赖关系)。否则您可能只是在某个地方缺少图书馆。

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

另一种可能性是使用g ++意外重载函数,并且可能与实现中的标头签名不同。

您可以尝试删除所有.o和库文件,然后重新编译世界(所有内容)。有时一个.o文件(或库)从源/头文件中过时,并造成了极大的痛苦和痛苦……



回复评论:

如上所述,虽然被掩埋了,但上面这样的问题:通常,此类问题指的是命令行中的依赖地狱和链接顺序。至少他们曾经如此。我不确定情况是否仍然如此。

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

与gcc / g ++链接:您可以通过gcc -cfile.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

还是file.Cgcc file.cg ++ file.C都可以工作。但是,C和C ++语言中的差异可能会咬你。例如,如果定义了foo(signed int),则类型信息将在C ++编译下合并(混合)到已编译函数名称中。随后从C代码调用它不一定有效(正确链接)。类似地,如果头文件显示

foo(short int)

,而源代码显示foo(long int),您可能会遇到有趣的问题。
© www.soinside.com 2019 - 2024. All rights reserved.