Search code examples
c++xcodelinkerbuild-processopenscenegraph

Running a compiled executable in Xcode gives a different result from directly invoking the executable in the shell


The program uses OpenSceneGraph to generate an .osg file.

int main( int, char** )
{
    osg::ref_ptr<osg::Node> root = createSceneGraph();
    if (!root.valid())
    {
        osg::notify(osg::FATAL) << "Failed in createSceneGraph()." << endl;
    }
    bool result = osgDB::writeNodeFile( *(root.get()), "Simple.osg" );
    if ( !result )
    {
        osg::notify(osg::FATAL) << "Failed in osgDB::writeNode()." << endl;
    }
}

The code excerpt is from openscenegraph Quick Start Guide http://www.lulu.com/items/volume_51/767000/767629/3/print/OSGQSG.pdf page 40

The program can be compiled and run in XCode. But, it shows the following error:

Error writing file Simple.osg: Warning: Could not find plugin to 
write nodes to file "Simple.osg".
Failed in osgDB::writeNode().



However, the compiled binary can be executed without error by directly running in the shell.(./program) And the program correctly generates the Simple.osg file.


This is not the end of story. It is most likely because xcode invokes the compile program differently from invoking it in the shell. So, I copy and paste two dependent libraries into the directory where the compiled binary resides.
(In case who knows OSG, the two libraries are osgdb_deprecated_osg.so and osgdb_osg.so)

This time, the Xcode correctly runs the program without errors, generating the Simple.osg file.
Therefore, there are two questions.
1) Why the shell is able to locate the dependent libraries automatically whereas the Xcode cannot?
2) How to make Xcode work without manually copying the dependent libraries or via post compile copy options?


Solution

  • OK. After several hours I finally get it resolved.
    The reason why the libraries are loaded under the shell is because of the shell's default environmental variable settings in ~/.profile, so that the program can search the libraries with these variables.
    As XenonofArcticus pointed out, xcode doesn't inherit the environmental variable settings in the ~/.profile so the program running under xcode cannot resolve the actual path of the libraries.
    However, at first I copied those variables in the environmental variable settings in the xcode but it didn't work.
    It turns out that the environmental variable settings in xcode is not expandable across different ones. e.g:

    HELLO=123/hi
    WORLD=$HELLO/enter
    

    The second WORLD variable does not replace the HELLO defined previously into the path.
    Therefore, I need to manually write like this:

    HELLO=123/hi
    WORLD=123/hi/enter