Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 11772 was 11696, checked in by landauf, 7 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
Line 
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:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "ApplicationPaths.h"
30
31#include <cassert>
32#include <cstdlib>
33#include <cstdio>
34#include <fstream>
35#include <vector>
36#include <boost/filesystem.hpp>
37
38#ifdef ORXONOX_PLATFORM_WINDOWS
39#  ifndef WIN32_LEAN_AND_MEAN
40#    define WIN32_LEAN_AND_MEAN
41#  endif
42#  include <windows.h>
43#  undef min
44#  undef max
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"
54#include "util/Output.h"
55#include "util/Exception.h"
56
57// Differentiate Boost Filesystem v2 and v3
58#if (BOOST_FILESYSTEM_VERSION < 3)
59#  define BF_LEAF leaf
60#  define BF_GENERIC_STRING string
61#else
62#  define BF_LEAF path().filename().string
63#  define BF_GENERIC_STRING generic_string
64#endif
65
66namespace orxonox
67{
68    namespace bf = boost::filesystem;
69
70    //! Static pointer to the singleton
71    ApplicationPaths* ApplicationPaths::singletonPtr_s  = nullptr;
72
73    ApplicationPaths::ApplicationPaths()
74        : rootPath_(*(new bf::path()))
75        , executablePath_(*(new bf::path()))
76        , modulePath_(*(new bf::path()))
77        , pluginPath_(*(new bf::path()))
78        , bBuildDirectoryRun_(false)
79    {
80        //////////////////////////
81        // FIND EXECUTABLE PATH //
82        //////////////////////////
83
84#ifdef ORXONOX_PLATFORM_WINDOWS
85        // get executable module
86        TCHAR buffer[1024];
87        if (GetModuleFileName(nullptr, buffer, 1024) == 0)
88            ThrowException(General, "Could not retrieve executable path.");
89
90#elif defined(ORXONOX_PLATFORM_APPLE)
91        char buffer[1024];
92        uint32_t path_len = 1023;
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
122        // Remove executable filename
123        executablePath_ = bf::path(buffer).branch_path();
124
125        /////////////////////////////////
126        // SET MODULE AND PLUGIN PATHS //
127        /////////////////////////////////
128
129        if (bf::exists(executablePath_ / "orxonox_dev_build.keep_me"))
130        {
131            orxout(internal_info) << "Running from the build tree." << endl;
132            ApplicationPaths::bBuildDirectoryRun_ = true;
133            modulePath_ = specialConfig::moduleDevDirectory;
134            pluginPath_ = specialConfig::pluginDevDirectory;
135        }
136        else
137        {
138
139#ifdef INSTALL_COPYABLE // --> relative paths
140
141            // Also set the root path
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())
147                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
148
149            // Module and plugin paths are fixed as well
150            modulePath_ = rootPath_ / specialConfig::defaultModulePath;
151            pluginPath_ = rootPath_ / specialConfig::defaultPluginPath;
152
153#else
154
155            // There is no root path, so don't set it at all
156            // Module and plugin paths are fixed as well
157            modulePath_ = specialConfig::moduleInstallDirectory;
158            pluginPath_ = specialConfig::pluginInstallDirectory;
159
160#endif
161        }
162    }
163
164    ApplicationPaths::~ApplicationPaths()
165    {
166        delete &rootPath_;
167        delete &executablePath_;
168        delete &modulePath_;
169        delete &pluginPath_;
170    }
171
172    std::map<std::string, std::string> ApplicationPaths::getModulePaths()
173    {
174        return this->getModuleOrPluginPaths(modulePath_, specialConfig::moduleExtension);
175    }
176
177    std::map<std::string, std::string> ApplicationPaths::getPluginPaths()
178    {
179        return this->getModuleOrPluginPaths(pluginPath_, specialConfig::pluginExtension);
180    }
181
182    std::map<std::string, std::string> ApplicationPaths::getModuleOrPluginPaths(boost::filesystem::path& directory, const std::string& extension)
183    {
184        std::map<std::string, std::string> paths;
185
186        // We search for helper files with the following extension
187        size_t extensionlength = extension.size();
188
189        // Make sure the path exists, otherwise don't load modules/plugins
190        if (!boost::filesystem::exists(directory))
191            return paths;
192
193        boost::filesystem::directory_iterator file(directory);
194        boost::filesystem::directory_iterator end;
195
196        // Iterate through all files
197        while (file != end)
198        {
199            std::string filename = file->BF_LEAF();
200
201            // Check if the file ends with the extension in question
202            if (filename.size() > extensionlength)
203            {
204                if (filename.substr(filename.size() - extensionlength) == extension)
205                {
206                    // We've found a helper file
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                    {
214                        std::string libraryNameWithoutExtension = libraryName.substr(0, libraryName.find_first_of('.'));
215                        std::string libraryPath = directory.BF_GENERIC_STRING() + '/' + libraryNameWithoutExtension;
216                        paths[moduleName] = libraryPath;
217                    }
218                    else
219                    {
220                        orxout(internal_warning) << "Could not file " << filename << endl;
221                    }
222                }
223            }
224            ++file;
225        }
226
227        return paths;
228    }
229
230    /*static*/ std::string ApplicationPaths::getRootPathString()
231    {
232        return getInstance().rootPath_.BF_GENERIC_STRING() + '/';
233    }
234
235    /*static*/ std::string ApplicationPaths::getExecutablePathString()
236    {
237        return getInstance().executablePath_.BF_GENERIC_STRING() + '/';
238    }
239
240    /*static*/ std::string ApplicationPaths::getModulePathString()
241    {
242        return getInstance().modulePath_.BF_GENERIC_STRING() + '/';
243    }
244
245    /*static*/ std::string ApplicationPaths::getPluginPathString()
246    {
247        return getInstance().pluginPath_.BF_GENERIC_STRING() + '/';
248    }
249}
Note: See TracBrowser for help on using the repository browser.