【发布时间】:2015-11-27 01:42:33
【问题描述】:
我无法在我的 Mac 上正确链接 OpenSceneGraph 项目。我通过 macports 安装了它,我得到了 osgviewer 和其他 osg 程序的工作,这意味着它以某种方式被编译和链接。该代码是一个更大项目的一部分,但是我将 OSG 代码分解为最简单的部分以隔离我的问题。我首先认为这是一个 CMake 问题,所以我创建了一个 Makefile 来尝试在那里隔离。这没什么区别。
这里是示例代码。
// OpenSceneGraph Libraries
#include <osg/Geode>
#include <osg/Group>
#include <osg/ShapeDrawable>
#include <osgUtil/Optimizer>
#include <osgUtil/SmoothingVisitor>
#include <osgUtil/Simplifier>
#include <osg/Node>
#include <osg/Texture1D>
#include <osg/Texture2D>
#include <osg/TexGen>
#include <osg/Material>
#include <osgViewer/Viewer>
#include <osgDB/Registry>
#include <osgDB/WriteFile>
#include <osgDB/ReadFile>
#include <osgSim/Version>
#include <osgFX/Version>
#include <osgTerrain/Version>
#include <osgVolume/Version>
// C++ Libraries
#include <iostream>
#include <string>
/**
* @brief Main Application
*/
int main( int argc, char* argv[] )
{
// Define Write Options
osgDB::Options* write_options = new osgDB::Options("WriteImageHint=IncludeData Compressor=zlib");
// Create the Root Nodes
osg::ref_ptr<osg::Group> root_node(new osg::Group());
// Write the Node File
osgDB::writeNodeFile( *root_node.get(),
"output.osgb",
write_options );
// Return
return 0;
}
这是 Makefile 代码。我已经添加了超出需要的方法,但没有任何效果。
OSG_LIBS=-lOpenThreads -losgDB -losg -losgUtil -losgTerrain
LIBS=-L/opt/local/lib $(OSG_LIBS)
INCL=-I/opt/local/include
CPP=clang++
foo: foo.cpp
$(CPP) foo.cpp $(LIBS) $(INCL)
这是特定命令上 VERBOSE=1 的 make 输出。
$ make VERBOSE=1
clang++ foo.cpp -L/opt/local/lib -lOpenThreads -losgDB -losg -losgUtil -losgTerrain -I/opt/local/include
Undefined symbols for architecture x86_64:
"osgDB::writeNodeFile(osg::Node const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, osgDB::Options const*)", referenced from:
_main in foo-2c45f6.o
"osgDB::Options::parsePluginStringData(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char, char)", referenced from:
osgDB::Options::Options(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in foo-2c45f6.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [foo] Error 1
我已针对共享库运行otool 和其他应用程序,以尝试查找未定义引用的位置。我知道当我运行nm 时,这两种方法的符号都在libosgDB.dylib 中,但链接它不起作用。
我开始从源代码编译 OpenSceneGraph,但这本身也会产生编译错误。我前面还有很长的战斗。非常感谢您抽出宝贵时间。
更新:
观察
- 在编译器行重新排序库不起作用。
【问题讨论】:
-
OS X 上的 C++ 链接器错误,其中唯一缺少的符号似乎是那些包含
std::__1::basic_string的符号?这看起来很像 C++ 标准库不兼容。确保您的库和应用程序都是针对 libstdc++ 或 libc++ 构建的(这也意味着您不能使用 g++ 编译其中一个而使用 clang++ 编译另一个)。 -
好收获。我正在研究 MacPorts 上 OSG 的 portfile 规范,以找出他们使用的编译器。由于 MacPorts 在您的机器上手动构建每个包,这绝对是值得信赖的。一旦我做更多的研究,我会更新。
-
MacPorts 总是尝试使用系统默认编译器并遵循系统默认选择的 C++ 标准库。因此,除非
Portfile做了任何具体的事情(而且似乎没有),否则clang++在任何 >= 10.9 上使用libc++。 -
每当发现使用的字符串库时,我最终在单独的项目中再次遇到此问题。我正在重新安装 MacPorts 以确保它没有贡献。这就像链接一个使用 C++ 字符串的项目会导致未定义的符号。我检查了我的 bash 配置文件以确保我没有错误的路径。如果一切都失败了,我将卸载包括 XCode 在内的所有内容,然后再试一次。
-
您可以检查一些额外的事情:在库和二进制文件上使用
otool -L检查它们链接的 C++ 运行时库。确保您使用的 C++ 头文件与 C++ 运行时库匹配。尝试显式使用/usr/bin/clang++ -stdlib=libc++作为编译器,并确保您的环境中没有设置MACOSX_DEPLOYMENT_TARGET(因为它会更改clang 的默认运行时库)。
标签: c++ macos makefile macports openscenegraph