gazebosim / gz-rendering

C++ library designed to provide an abstraction for different rendering engines. It offers unified APIs for creating 3D graphics applications.
https://gazebosim.org
Apache License 2.0
56 stars 51 forks source link

MacOS collision between OGRE1.9 and OGRE2.1 #185

Open ahcorde opened 3 years ago

ahcorde commented 3 years ago

While I was debugging the issue with OGRE + QML on MacOS I founded this issue:

objc[37280]: Class OgreConfigWindowDelegate is implemented in both /usr/local/opt/ogre1.9/lib/libOgreMain.1.9.0.dylib (0x14b388dc0) and /usr/local/opt/ogre2.1/lib/libOgreMain.2.1.0.dylib (0x1539eb838). One of the two will be used. Which one is undefined.

I talked with @iche033 about this issue in the past:

As for loading the right OgreMain version, I think on ubuntu, we worked around it by installing to different directories, e.g. /usr/lib/x86_64-linux-gnu/OGRE-2.1 and /usr/lib/x86_64-linux-gnu/OGRE-1.9.0. I think we are using the same approach on MacOS but it's not working properly.

iche033 commented 3 years ago

I think we made the ubuntu debs work with debian rules in ignition-forks/ogre-2.1-release#1 but since macOS builds and installs ogre2 from source, the two ogre libraries both just get installed to the same directory.

srmainwaring commented 3 years ago

I'm not sure this a problem that can be solved by installing ogre and ogre2 to different directories. The issue seems to be that for macOS both Ogre libraries contain an objective C class with the same name: when the render engine attempts to load the second ogre rendering plugin the choice is not uniquely defined.

No fix at this stage, but some more detail on causes below.

Test case: ign-rendering/examples/mesh_viewer

The following traces are from the example ign-rendering/examples/mesh_viewer modified to load both engines "ogre" and "ogre2".

The behaviour can be replicated using either CMAKE_BUILD_TYPE=Debug or CMAKE_BUILD_TYPE=RelWithDebInfo.

The application works when either ignition-rendering-ogre or ignition-rendering-ogre2 is loaded, but fails when both are loaded. Furthermore the ogre2 case will fail if there is any linkage with Ogre1.9, for example if mesh_viewer is linked against Ogre1.9 in order to catch Ogre::Exception.

The good news is that some of the Ogre2 examples work on macOS, just not combined with Ogre1

The conflict error is the same as given above:

@"objc[54119]: Class OgreConfigWindowDelegate is implemented in both /usr/local/Cellar/ogre1.9/1.9.0/lib/libOgreMain.1.9.0.dylib (0x10fb93628) and /usr/local/opt/ogre2.1/lib/libOgreMain.2.1.0.dylib (0x11cffb290). One of the two will be used. Which one is undefined.\r\n"

On macOS Ogre libraries are installed in different directories. Both have symlinks in /usr/local/lib but I do not think that is the problem. Inspecting the symbols shows both have an entry for _OBJC_CLASS_$_OgreConfigWindowDelegate:

$ nm /usr/local/Cellar/ogre1.9/1.9.0/lib/libOgreMain.1.9.0.dylib | grep OgreConfigWindowDelegate
00000000002886c0 t -[OgreConfigWindowDelegate cancelButtonPressed:]
0000000000288280 t -[OgreConfigWindowDelegate dealloc]
0000000000288a90 t -[OgreConfigWindowDelegate getConfigWindow]
0000000000288b00 t -[OgreConfigWindowDelegate getOgreLogo]
0000000000288b40 t -[OgreConfigWindowDelegate getOptionsPopUp]
0000000000288b20 t -[OgreConfigWindowDelegate getOptionsTable]
0000000000288ab0 t -[OgreConfigWindowDelegate getOptions]
0000000000288ad0 t -[OgreConfigWindowDelegate getRenderSystemsPopUp]
0000000000287820 t -[OgreConfigWindowDelegate init]
0000000000288790 t -[OgreConfigWindowDelegate numberOfRowsInTableView:]
0000000000288710 t -[OgreConfigWindowDelegate okButtonPressed:]
0000000000288360 t -[OgreConfigWindowDelegate popUpValueChanged:]
0000000000288aa0 t -[OgreConfigWindowDelegate setConfigWindow:]
0000000000288af0 t -[OgreConfigWindowDelegate setOgreLogo:]
0000000000288ac0 t -[OgreConfigWindowDelegate setOptions:]
0000000000288b30 t -[OgreConfigWindowDelegate setOptionsPopUp:]
0000000000288b10 t -[OgreConfigWindowDelegate setOptionsTable:]
0000000000288ae0 t -[OgreConfigWindowDelegate setRenderSystemsPopUp:]
0000000000288750 t -[OgreConfigWindowDelegate tableView:objectValueForTableColumn:row:]
00000000002887b0 t -[OgreConfigWindowDelegate tableView:shouldSelectRow:]
0000000000288680 t -[OgreConfigWindowDelegate windowShouldClose:]
0000000000393628 S _OBJC_CLASS_$_OgreConfigWindowDelegate
0000000000393610 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mCancelButton
00000000003935e0 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mConfigWindow
00000000003935e8 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mOgreLogo
0000000000393608 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mOkButton
0000000000393618 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mOptionLabel
0000000000393620 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mOptions
00000000003935f8 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mOptionsPopUp
0000000000393600 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mOptionsTable
00000000003935f0 S _OBJC_IVAR_$_OgreConfigWindowDelegate.mRenderSystemsPopUp
0000000000393650 S _OBJC_METACLASS_$_OgreConfigWindowDelegate
0000000000392ea0 s __OBJC_$_INSTANCE_METHODS_OgreConfigWindowDelegate
00000000003930a0 s __OBJC_$_INSTANCE_VARIABLES_OgreConfigWindowDelegate
00000000003931c8 s __OBJC_$_PROP_LIST_OgreConfigWindowDelegate
0000000000392e30 s __OBJC_CLASS_PROTOCOLS_$_OgreConfigWindowDelegate
0000000000393210 s __OBJC_CLASS_RO_$_OgreConfigWindowDelegate
0000000000392e58 s __OBJC_METACLASS_RO_$_OgreConfigWindowDelegate
$ nm /usr/local/opt/ogre2.1/lib/libOgreMain.2.1.0.dylib | grep OgreConfigWindowDelegate
000000000023fb31 t -[OgreConfigWindowDelegate cancelButtonPressed:]
000000000023fdf9 t -[OgreConfigWindowDelegate getConfigWindow]
000000000023fe3f t -[OgreConfigWindowDelegate getOgreLogo]
000000000023fe67 t -[OgreConfigWindowDelegate getOptionsPopUp]
000000000023fe53 t -[OgreConfigWindowDelegate getOptionsTable]
000000000023fe0d t -[OgreConfigWindowDelegate getOptions]
000000000023fe21 t -[OgreConfigWindowDelegate getRenderSystemsPopUp]
000000000023eff5 t -[OgreConfigWindowDelegate init]
000000000023fbf0 t -[OgreConfigWindowDelegate numberOfRowsInTableView:]
000000000023fb78 t -[OgreConfigWindowDelegate okButtonPressed:]
000000000023f939 t -[OgreConfigWindowDelegate popUpValueChanged:]
000000000023fe03 t -[OgreConfigWindowDelegate setConfigWindow:]
000000000023fe35 t -[OgreConfigWindowDelegate setOgreLogo:]
000000000023fe17 t -[OgreConfigWindowDelegate setOptions:]
000000000023fe5d t -[OgreConfigWindowDelegate setOptionsPopUp:]
000000000023fe49 t -[OgreConfigWindowDelegate setOptionsTable:]
000000000023fe2b t -[OgreConfigWindowDelegate setRenderSystemsPopUp:]
000000000023fbb0 t -[OgreConfigWindowDelegate tableView:objectValueForTableColumn:row:]
000000000023fc06 t -[OgreConfigWindowDelegate tableView:shouldSelectRow:]
000000000023faf6 t -[OgreConfigWindowDelegate windowShouldClose:]
00000000002ce290 s _OBJC_CLASS_$_OgreConfigWindowDelegate
00000000002ce278 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mCancelButton
00000000002ce248 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mConfigWindow
00000000002ce250 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mOgreLogo
00000000002ce270 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mOkButton
00000000002ce280 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mOptionLabel
00000000002ce288 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mOptions
00000000002ce260 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mOptionsPopUp
00000000002ce268 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mOptionsTable
00000000002ce258 s _OBJC_IVAR_$_OgreConfigWindowDelegate.mRenderSystemsPopUp
00000000002ce2b8 s _OBJC_METACLASS_$_OgreConfigWindowDelegate

The error is raised as soon as the second plugin ignition-rendering-ogre2 is loaded here:

https://github.com/ignitionrobotics/ign-rendering/blob/9ca3a59c721e0a11cc835083d8efad88919fdcf7/src/RenderEngineManager.cc#L467

The application subsequently exits with an Ogre RenderingAPIException.

In the case we load the ignition-rendering-ogre plugin before the ignition-rendering-ogre2 plugin the exception is thrown in: OgreGLTexture.cpp - GLTexture::_createSurfaceList() on a GLTextureBuffer call. It's not clear at this stage why the reported name conflict is causing this to fail. It's possible this is not the only conflict, just the first reported.

Location of conflicting Ogre class

In OGRECave/ogre the conflicting class is currently defined here (it appears to have moved since 1.9):

https://github.com/OGRECave/ogre/blob/2dc0861786db9019d8e862ada666f1450edf3006/Components/Bites/src/OgreOSXConfigDialog.mm#L41

In OGRECave/ogre-next (Ogre2) it is here:

https://github.com/OGRECave/ogre-next/blob/184741a085af54464210fb6de80fd29bfcf9b401/OgreMain/include/OSX/OgreConfigDialogImp.h#L42