[MAC] How to resolve VOSM(ASM/AAM) circular dependency issue under Mac Xcode

来源:互联网 发布:指纹机可以恢复数据么 编辑:程序博客网 时间:2024/05/21 12:49

1. 起因

心血来潮,想要编一个人脸库VOSM,感觉应该很容易,最近的版本还算新,有linux和windows版本。想在mac上跑一下,顺便把Xcode,CMake,LLVM都理一下

2. 麻烦

过程不细说了。回头看看,断断续续两天时间,头一天把LLVM和gcc,clang的关系搞懂了,cmake复习一下(其实从来没认真学过)。主要问题是昨天,先是link opencv和boost始终有undefined reference的错误,尽管这两个库都是通过MacPorts安装的。boost是因为MacPorts是多线程版本,库名多了个-mt,比如libboost_filesystem-mt,libboost_system-mt等。

另外很多建议改用libstdc++而不是libc++(clang)

Linking libraries OpenCV 2.4.2 on xcode 4.5.1

Under Build Settings>Apple LLVM compiler 4.1 - Language>C++ Standard Library: Change from libc++ (LLVM ...) to libstdc++ (GNU C++ ...).

Undefined symbols for architecture x86_64 error when linking OpenCV in Xcode


不过在最终解决的环境下好像并没用到。而且有人的解释也没看懂---跟标准库有什么关系???

@BRabbit27 "nm" command revealed that libc++ has a different symbol naming convention compared to libstdc++. So, we must choose the same C++ library that OpenCV was compiled with, otherwise the linker will fail to resolve symbols. Here is a screenshot showing different naming between libc++ & libstdc++


3. 大麻烦

真正的麻烦是在整个过程中慢慢发现(慢慢还是把整个库的结构理出来了,本来开始懒得看,只想编译成功就好)module之间有循环依赖(circular dependency)。主要是cvcommon和smbuilding。在*nix下没有问题,但好像mac就不行。

On Unix, it's possible to link a shared library that contains an unresolved symbol that the linker has never seen; in this situation, any other code that pulls in this shared library must provide that symbol, or the program will fail to load. Windows doesn't allow this sort of laxity.


最接近的问题是 Ignoring an undefined symbol in a dynamic library from Xcode,从答案中又查到各种ld的option可以做lazy symbol binding,

--allow-shlib-undefined
--no-allow-shlib-undefined

Allows or disallows undefined symbols in shared libraries. This switch is similar to --no-undefined except that it determines the behaviour when the undefined symbols are in a shared library rather than a regular object file. It does not affect how undefined symbols in regular object files are handled.

The default behaviour is to report errors for any undefined symbols referenced in shared libraries if the linker is being used to create an executable, but to allow them if the linker is being used to create a shared library.

The reasons for allowing undefined symbol references in shared libraries specified at link time are that:

• A shared library specified at link time may not be the same as the one that is available at load time, so the symbol might actually be resolvable at load time.

• There are some operating systems, eg BeOS and HPPA , where undefined symbols in shared libraries are normal.

The BeOS kernel for example patches shared libraries at load time to select whichever function is most appropriate for the current architecture. This is used, for example, to dynamically select an appropriate memset function.


--no-undefined
-z defs
Report unresolved symbol references from regular object files. This is done even if the linker is creating a non-symbolic shared library. The switch --[no-]allow-shlib-undefined controls the behaviour for reporting unresolved references found in shared libraries being linked in.

--unresolved-symbols=method
Determine how to handle unresolved symbols. There are four possible values for method:
ignore-all
Do not report any unresolved symbols.
report-all
Report all unresolved symbols. This is the default.
ignore-in-object-files
Report unresolved symbols that are contained in shared libraries, but ignore them if they come from regular object files.
ignore-in-shared-libs
Report unresolved symbols that come from regular object files, but ignore them if they come from shared libraries. This can be useful when creating a dynamic binary and it is known that all the shared libraries that it should be referencing are included on the linker's command line.
The behaviour for shared libraries on their own can also be controlled by the --[no-]allow-shlib-undefined option.

Normally the linker will generate an error message for each reported unresolved symbol but the option --warn-unresolved-symbols can change this to a warning.


不过怎么试都不好使,折腾到凌晨4点还是“暂时”放弃了~~~~~


4. 解决

睡了4个小时,本以为会难受的很,反而一点感觉都没有---跑步真是有用处,有大用处!

早上起来还是不服气,到office继续战斗--虽然已经下了决心“放下”,本不是必须要做的事情,通过这个过程也理解了不少东西。。。。

原来应该是linker的option不同吧。Mac肯定用的是dyld,上面那些options都是gcc ld的。。。其实上面已经提到-undefined dynamic_lookup,不过我用时提示unrecognized link option,没有往ld和dyld上想---当时人都木了,再次下决心绝不在一个问题上纠缠超过2小时!!


Easy check for unresolved symbols in shared libraries?

dyld: lazy symbol binding failed: Symbol not found


5. 小结

一度以为是Xcode里某些未知的设置改变了CMakeLists.txt里设定的行为。看起来不是,尽管也看到很多确实属于这种情况的---或者说某个Xcode版本的bug。

无论怎样,现在觉得*nix的东西确实还是少用GUI的好,再长的编译命令也只是个命令行,要添加什么选项都很容易。

unix make版本的调通了,xcode马上也build succeeded。想想今天凌晨不停的在GUI里变换测试各种选项,真是折磨


gcc -shared -fPIC ... -Wl,-z,defsnm -C -U

otool -L build/Release/puzzle.node

otool -l build/Release/puzzle.node

-static-libstdc++
When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically. 


-Wl,option
Pass option as an option to the linker. If option contains commas, it is split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example, -Wl,-Map,output.map passes -Map output.map to the linker. When using the GNU linker, you can also get the same effect with -Wl,-Map=output.map


再次下决心绝不在一个问题上纠缠超过2小时!!