File::currentExecutableFile for shared libraries fix


#1

When the File::getSpecialLocation is used in a plugin shared library, most of the time the currentExecutable filename doesn’t exists, as the juce_setCurrentExecutableFileName function is not called cause we don’t have the command line arguments to correctly determine the name of the app.

in juce_linux_Files.cpp:

//==============================================================================
const File File::getSpecialLocation (const SpecialLocationType type)
{
    switch (type)
    {
    case userHomeDirectory:
    {
        const char* homeDir = getenv ("HOME");

        if (homeDir == 0)
        {
            struct passwd* const pw = getpwuid (getuid());
            if (pw != 0)
                homeDir = pw->pw_dir;
        }

        return File (String::fromUTF8 ((const uint8*) homeDir));
    }

    case userDocumentsDirectory:
    case userMusicDirectory:
    case userMoviesDirectory:
    case userApplicationDataDirectory:
        return File ("~");

    case userDesktopDirectory:
        return File ("~/Desktop");

    case commonApplicationDataDirectory:
        return File ("/var");

    case globalApplicationsDirectory:
        return File ("/usr");

    case tempDirectory:
    {
        File tmp ("/var/tmp");

        if (! tmp.isDirectory())
        {
            tmp = T("/tmp");

            if (! tmp.isDirectory())
                tmp = File::getCurrentWorkingDirectory();
        }

        return tmp;
    }

    case currentExecutableFile:
    case currentApplicationFile:
        // try to obtain info from dladdr (as this could be a shared library !)
        if (! executableFile.exists())
        {
            Dl_info executableInfo;
            dladdr ((const void*) juce_getFileTimes, &executableInfo);

            if (executableInfo.dli_fname != 0)
                executableFile = File (String (executableInfo.dli_fname));
        }

        // if this fails, it's probably because juce_setCurrentExecutableFileName()
        // was never called to set the filename - this should be done by the juce
        // main() function, so maybe you've hacked it to use your own custom main()?
        jassert (executableFile.exists());

        return executableFile;

    default:
        jassertfalse // unknown type?
        break;
    }

    return File::nonexistent;
}

obviously we need to include:

#include <dlfcn.h>

on the top of the file.

now doing a query of the currentExecutableFile inside plugins works as expected !!


#2

Ah! Cunning stuff. Thanks kraken!