Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/ApplicationPaths.cc

Last change on this file was 11696, checked in by landauf, 6 years ago

whoops. must remove the extensions from the library's file name before loading it

  • Property svn:eol-style set to native
File size: 8.2 KB
RevLine 
[1505]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
[2896]23 *      Reto Grieder
[1505]24 *   Co-authors:
[2896]25 *      ...
[1505]26 *
27 */
28
[10509]29#include "ApplicationPaths.h"
[1505]30
[1756]31#include <cassert>
[2710]32#include <cstdlib>
33#include <cstdio>
[11692]34#include <fstream>
[5836]35#include <vector>
[2710]36#include <boost/filesystem.hpp>
37
38#ifdef ORXONOX_PLATFORM_WINDOWS
[2896]39#  ifndef WIN32_LEAN_AND_MEAN
40#    define WIN32_LEAN_AND_MEAN
41#  endif
[2710]42#  include <windows.h>
[3214]43#  undef min
44#  undef max
[2710]45#elif defined(ORXONOX_PLATFORM_APPLE)
46#  include <sys/param.h>
47#  include <mach-o/dyld.h>
48#else /* Linux */
49#  include <sys/types.h>
50#  include <unistd.h>
51#endif
52
53#include "SpecialConfig.h"
[8858]54#include "util/Output.h"
[2710]55#include "util/Exception.h"
[1505]56
[8351]57// Differentiate Boost Filesystem v2 and v3
58#if (BOOST_FILESYSTEM_VERSION < 3)
59#  define BF_LEAF leaf
60#  define BF_GENERIC_STRING string
[5693]61#else
[8351]62#  define BF_LEAF path().filename().string
63#  define BF_GENERIC_STRING generic_string
[5693]64#endif
65
[1505]66namespace orxonox
67{
[5836]68    namespace bf = boost::filesystem;
69
[3196]70    //! Static pointer to the singleton
[11071]71    ApplicationPaths* ApplicationPaths::singletonPtr_s  = nullptr;
[2662]72
[10509]73    ApplicationPaths::ApplicationPaths()
[5836]74        : rootPath_(*(new bf::path()))
75        , executablePath_(*(new bf::path()))
76        , modulePath_(*(new bf::path()))
[10547]77        , pluginPath_(*(new bf::path()))
[8366]78        , bBuildDirectoryRun_(false)
[3280]79    {
[5693]80        //////////////////////////
81        // FIND EXECUTABLE PATH //
82        //////////////////////////
83
[2710]84#ifdef ORXONOX_PLATFORM_WINDOWS
85        // get executable module
86        TCHAR buffer[1024];
[11071]87        if (GetModuleFileName(nullptr, buffer, 1024) == 0)
[2710]88            ThrowException(General, "Could not retrieve executable path.");
89
90#elif defined(ORXONOX_PLATFORM_APPLE)
91        char buffer[1024];
[8351]92        uint32_t path_len = 1023;
[2710]93        if (_NSGetExecutablePath(buffer, &path_len))
94            ThrowException(General, "Could not retrieve executable path.");
95
96#else /* Linux */
97        /* written by Nicolai Haehnle <prefect_@gmx.net> */
98
99        /* Get our PID and build the name of the link in /proc */
100        char linkname[64]; /* /proc/<pid>/exe */
101        if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
102        {
103            /* This should only happen on large word systems. I'm not sure
104               what the proper response is here.
105               Since it really is an assert-like condition, aborting the
106               program seems to be in order. */
107            assert(false);
108        }
109
110        /* Now read the symbolic link */
111        char buffer[1024];
112        int ret;
113        ret = readlink(linkname, buffer, 1024);
114        /* In case of an error, leave the handling up to the caller */
115        if (ret == -1)
116            ThrowException(General, "Could not retrieve executable path.");
117
118        /* Ensure proper NUL termination */
119        buffer[ret] = 0;
120#endif
121
[8351]122        // Remove executable filename
123        executablePath_ = bf::path(buffer).branch_path();
[2710]124
[10547]125        /////////////////////////////////
126        // SET MODULE AND PLUGIN PATHS //
127        /////////////////////////////////
[5693]128
[5836]129        if (bf::exists(executablePath_ / "orxonox_dev_build.keep_me"))
[2710]130        {
[8858]131            orxout(internal_info) << "Running from the build tree." << endl;
[10509]132            ApplicationPaths::bBuildDirectoryRun_ = true;
[5836]133            modulePath_ = specialConfig::moduleDevDirectory;
[10547]134            pluginPath_ = specialConfig::pluginDevDirectory;
[2710]135        }
136        else
137        {
[5693]138
[2710]139#ifdef INSTALL_COPYABLE // --> relative paths
[5693]140
[2710]141            // Also set the root path
[5836]142            bf::path relativeExecutablePath(specialConfig::defaultRuntimePath);
143            rootPath_ = executablePath_;
144            while (!bf::equivalent(rootPath_ / relativeExecutablePath, executablePath_) && !rootPath_.empty())
145                rootPath_ = rootPath_.branch_path();
146            if (rootPath_.empty())
[2710]147                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
148
[10547]149            // Module and plugin paths are fixed as well
[5836]150            modulePath_ = rootPath_ / specialConfig::defaultModulePath;
[10547]151            pluginPath_ = rootPath_ / specialConfig::defaultPluginPath;
[5693]152
153#else
154
155            // There is no root path, so don't set it at all
[10547]156            // Module and plugin paths are fixed as well
[5836]157            modulePath_ = specialConfig::moduleInstallDirectory;
[10547]158            pluginPath_ = specialConfig::pluginInstallDirectory;
[5693]159
160#endif
161        }
162    }
163
[10509]164    ApplicationPaths::~ApplicationPaths()
[5693]165    {
[5836]166        delete &rootPath_;
167        delete &executablePath_;
168        delete &modulePath_;
[10547]169        delete &pluginPath_;
[5836]170    }
171
[11692]172    std::map<std::string, std::string> ApplicationPaths::getModulePaths()
[5836]173    {
[10547]174        return this->getModuleOrPluginPaths(modulePath_, specialConfig::moduleExtension);
175    }
[5836]176
[11692]177    std::map<std::string, std::string> ApplicationPaths::getPluginPaths()
[10547]178    {
179        return this->getModuleOrPluginPaths(pluginPath_, specialConfig::pluginExtension);
180    }
181
[11692]182    std::map<std::string, std::string> ApplicationPaths::getModuleOrPluginPaths(boost::filesystem::path& directory, const std::string& extension)
[10547]183    {
[11692]184        std::map<std::string, std::string> paths;
[10547]185
[5836]186        // We search for helper files with the following extension
[10547]187        size_t extensionlength = extension.size();
[5836]188
[10547]189        // Make sure the path exists, otherwise don't load modules/plugins
190        if (!boost::filesystem::exists(directory))
191            return paths;
[6105]192
[10547]193        boost::filesystem::directory_iterator file(directory);
[5836]194        boost::filesystem::directory_iterator end;
195
196        // Iterate through all files
197        while (file != end)
[3370]198        {
[8351]199            std::string filename = file->BF_LEAF();
[5836]200
[8351]201            // Check if the file ends with the extension in question
[10547]202            if (filename.size() > extensionlength)
[5836]203            {
[10547]204                if (filename.substr(filename.size() - extensionlength) == extension)
[5836]205                {
206                    // We've found a helper file
[11692]207                    const std::string& moduleName = filename.substr(0, filename.size() - extensionlength);
208
209                    // Read it's content to get the library's name
210                    std::ifstream infile(file->path().string().c_str());
211                    std::string libraryName;
212                    if (infile >> libraryName)
213                    {
[11696]214                        std::string libraryNameWithoutExtension = libraryName.substr(0, libraryName.find_first_of('.'));
215                        std::string libraryPath = directory.BF_GENERIC_STRING() + '/' + libraryNameWithoutExtension;
[11692]216                        paths[moduleName] = libraryPath;
217                    }
218                    else
219                    {
220                        orxout(internal_warning) << "Could not file " << filename << endl;
221                    }
[5836]222                }
223            }
224            ++file;
[3370]225        }
[5836]226
[10547]227        return paths;
[2896]228    }
[3370]229
[10509]230    /*static*/ std::string ApplicationPaths::getRootPathString()
[3370]231    {
[8351]232        return getInstance().rootPath_.BF_GENERIC_STRING() + '/';
[3370]233    }
[5836]234
[10509]235    /*static*/ std::string ApplicationPaths::getExecutablePathString()
[5836]236    {
[8351]237        return getInstance().executablePath_.BF_GENERIC_STRING() + '/';
[5836]238    }
239
[10509]240    /*static*/ std::string ApplicationPaths::getModulePathString()
[5836]241    {
[8351]242        return getInstance().modulePath_.BF_GENERIC_STRING() + '/';
[5836]243    }
[10547]244
245    /*static*/ std::string ApplicationPaths::getPluginPathString()
246    {
247        return getInstance().pluginPath_.BF_GENERIC_STRING() + '/';
248    }
[1505]249}
Note: See TracBrowser for help on using the repository browser.