Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/libraries/core/ApplicationPaths.cc @ 10970

Last change on this file since 10970 was 10547, checked in by landauf, 10 years ago

added support for plugins in the buildsystem. plugins are like modules, but can be loaded/unloaded at runtime

  • Property svn:eol-style set to native
File size: 7.5 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 <vector>
35#include <boost/filesystem.hpp>
36
37#ifdef ORXONOX_PLATFORM_WINDOWS
38#  ifndef WIN32_LEAN_AND_MEAN
39#    define WIN32_LEAN_AND_MEAN
40#  endif
41#  include <windows.h>
42#  undef min
43#  undef max
44#elif defined(ORXONOX_PLATFORM_APPLE)
45#  include <sys/param.h>
46#  include <mach-o/dyld.h>
47#else /* Linux */
48#  include <sys/types.h>
49#  include <unistd.h>
50#endif
51
52#include "SpecialConfig.h"
53#include "util/Output.h"
54#include "util/Exception.h"
55
56// Differentiate Boost Filesystem v2 and v3
57#if (BOOST_FILESYSTEM_VERSION < 3)
58#  define BF_LEAF leaf
59#  define BF_GENERIC_STRING string
60#else
61#  define BF_LEAF path().filename().string
62#  define BF_GENERIC_STRING generic_string
63#endif
64
65namespace orxonox
66{
67    namespace bf = boost::filesystem;
68
69    //! Static pointer to the singleton
70    ApplicationPaths* ApplicationPaths::singletonPtr_s  = 0;
71
72    ApplicationPaths::ApplicationPaths()
73        : rootPath_(*(new bf::path()))
74        , executablePath_(*(new bf::path()))
75        , modulePath_(*(new bf::path()))
76        , pluginPath_(*(new bf::path()))
77        , bBuildDirectoryRun_(false)
78    {
79        //////////////////////////
80        // FIND EXECUTABLE PATH //
81        //////////////////////////
82
83#ifdef ORXONOX_PLATFORM_WINDOWS
84        // get executable module
85        TCHAR buffer[1024];
86        if (GetModuleFileName(NULL, buffer, 1024) == 0)
87            ThrowException(General, "Could not retrieve executable path.");
88
89#elif defined(ORXONOX_PLATFORM_APPLE)
90        char buffer[1024];
91        uint32_t path_len = 1023;
92        if (_NSGetExecutablePath(buffer, &path_len))
93            ThrowException(General, "Could not retrieve executable path.");
94
95#else /* Linux */
96        /* written by Nicolai Haehnle <prefect_@gmx.net> */
97
98        /* Get our PID and build the name of the link in /proc */
99        char linkname[64]; /* /proc/<pid>/exe */
100        if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
101        {
102            /* This should only happen on large word systems. I'm not sure
103               what the proper response is here.
104               Since it really is an assert-like condition, aborting the
105               program seems to be in order. */
106            assert(false);
107        }
108
109        /* Now read the symbolic link */
110        char buffer[1024];
111        int ret;
112        ret = readlink(linkname, buffer, 1024);
113        /* In case of an error, leave the handling up to the caller */
114        if (ret == -1)
115            ThrowException(General, "Could not retrieve executable path.");
116
117        /* Ensure proper NUL termination */
118        buffer[ret] = 0;
119#endif
120
121        // Remove executable filename
122        executablePath_ = bf::path(buffer).branch_path();
123
124        /////////////////////////////////
125        // SET MODULE AND PLUGIN PATHS //
126        /////////////////////////////////
127
128        if (bf::exists(executablePath_ / "orxonox_dev_build.keep_me"))
129        {
130            orxout(internal_info) << "Running from the build tree." << endl;
131            ApplicationPaths::bBuildDirectoryRun_ = true;
132            modulePath_ = specialConfig::moduleDevDirectory;
133            pluginPath_ = specialConfig::pluginDevDirectory;
134        }
135        else
136        {
137
138#ifdef INSTALL_COPYABLE // --> relative paths
139
140            // Also set the root path
141            bf::path relativeExecutablePath(specialConfig::defaultRuntimePath);
142            rootPath_ = executablePath_;
143            while (!bf::equivalent(rootPath_ / relativeExecutablePath, executablePath_) && !rootPath_.empty())
144                rootPath_ = rootPath_.branch_path();
145            if (rootPath_.empty())
146                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
147
148            // Module and plugin paths are fixed as well
149            modulePath_ = rootPath_ / specialConfig::defaultModulePath;
150            pluginPath_ = rootPath_ / specialConfig::defaultPluginPath;
151
152#else
153
154            // There is no root path, so don't set it at all
155            // Module and plugin paths are fixed as well
156            modulePath_ = specialConfig::moduleInstallDirectory;
157            pluginPath_ = specialConfig::pluginInstallDirectory;
158
159#endif
160        }
161    }
162
163    ApplicationPaths::~ApplicationPaths()
164    {
165        delete &rootPath_;
166        delete &executablePath_;
167        delete &modulePath_;
168        delete &pluginPath_;
169    }
170
171    std::vector<std::string> ApplicationPaths::getModulePaths()
172    {
173        return this->getModuleOrPluginPaths(modulePath_, specialConfig::moduleExtension);
174    }
175
176    std::vector<std::string> ApplicationPaths::getPluginPaths()
177    {
178        return this->getModuleOrPluginPaths(pluginPath_, specialConfig::pluginExtension);
179    }
180
181    std::vector<std::string> ApplicationPaths::getModuleOrPluginPaths(boost::filesystem::path& directory, const std::string& extension)
182    {
183        std::vector<std::string> paths;
184
185        // We search for helper files with the following extension
186        size_t extensionlength = extension.size();
187
188        // Make sure the path exists, otherwise don't load modules/plugins
189        if (!boost::filesystem::exists(directory))
190            return paths;
191
192        boost::filesystem::directory_iterator file(directory);
193        boost::filesystem::directory_iterator end;
194
195        // Iterate through all files
196        while (file != end)
197        {
198            std::string filename = file->BF_LEAF();
199
200            // Check if the file ends with the extension in question
201            if (filename.size() > extensionlength)
202            {
203                if (filename.substr(filename.size() - extensionlength) == extension)
204                {
205                    // We've found a helper file
206                    const std::string& library = filename.substr(0, filename.size() - extensionlength);
207                    paths.push_back(directory.BF_GENERIC_STRING() + '/' + library);
208                }
209            }
210            ++file;
211        }
212
213        return paths;
214    }
215
216    /*static*/ std::string ApplicationPaths::getRootPathString()
217    {
218        return getInstance().rootPath_.BF_GENERIC_STRING() + '/';
219    }
220
221    /*static*/ std::string ApplicationPaths::getExecutablePathString()
222    {
223        return getInstance().executablePath_.BF_GENERIC_STRING() + '/';
224    }
225
226    /*static*/ std::string ApplicationPaths::getModulePathString()
227    {
228        return getInstance().modulePath_.BF_GENERIC_STRING() + '/';
229    }
230
231    /*static*/ std::string ApplicationPaths::getPluginPathString()
232    {
233        return getInstance().pluginPath_.BF_GENERIC_STRING() + '/';
234    }
235}
Note: See TracBrowser for help on using the repository browser.