Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Feb 27, 2009, 2:13:29 PM (16 years ago)
Author:
rgrieder
Message:

Completed work on installation:

  • The CMake switch INSTALL_COPYABLE tells whether you will be able to move the installed directory or not. If TRUE then all folders, including log and config directory, will be put into the CMAKE_INSTALL_PREFIX. Furthermore, relative paths are used, which get resolved at run time.
  • If INSTALL_COPYABLE is set to FALSE, the standard operating system directories will be used. That also means on Windows files get written to the Application Data/.orxonox folder instead of Program Files/Orxonox
  • Default configuration is INSTALL_COPYABLE=TRUE for Windows and FALSE for Unix
  • Split OrxonoxConfig.h.in in two to avoid complete recompiles when changing only a path or INSTALL_COPYABLE
  • Added a global constant character: CP_SLASH which stands for cross platform slash, meaning '/' on Unix and '
    ' on Windows
  • Core class now has methods getFooPath(), getFooPathString() and getFooPathPOSIXString() where Foo can be Media, Log or Config
  • getFooPathPOSIXString() will always return a directory formatted with slashes, even on Windows
  • getFooPath() returns a reference to the boost::filesystem::path
  • boost/filesystem.hpp does not get included to Core.h because it has a very large rat tail
  • The platform specific directory stuff gets done in Core::postMainInitialisation()
  • Adjusted all classes using the media path
File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/buildsystem3/src/core/Core.cc

    r2692 r2702  
    3333
    3434#include "Core.h"
     35
    3536#include <cassert>
    3637#include <fstream>
     38#include <cstdlib>
     39#include <cstdio>
    3740#include <boost/filesystem.hpp>
    3841
     42#ifdef ORXONOX_PLATFORM_WINDOWS
     43#  include <windows.h>
     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"
    3953#include "util/Exception.h"
    4054#include "Language.h"
     
    4660namespace orxonox
    4761{
     62    //! Path to the parent directory of the ones above if program was installed with relativ pahts
     63    static boost::filesystem::path rootPath_g;
     64    static boost::filesystem::path executablePath_g;            //!< Path to the executable
     65    static boost::filesystem::path mediaPath_g;                 //!< Path to the media file folder
     66    static boost::filesystem::path configPath_g;                //!< Path to the config file folder
     67    static boost::filesystem::path logPath_g;                   //!< Path to the log file folder
     68
    4869    bool Core::bShowsGraphics_s = false;
    4970    bool Core::bHasServer_s     = false;
     
    5374
    5475    bool Core::isDevBuild_s     = false;
    55     std::string Core::configPath_s(ORXONOX_CONFIG_INSTALL_PATH); // from OrxonoxConfig.h
    56     std::string Core::logPath_s   (ORXONOX_LOG_INSTALL_PATH);    // from OrxonoxConfig.h
    57     std::string Core::mediaPath_s (ORXONOX_MEDIA_INSTALL_PATH);  // from OrxonoxConfig.h
    58 
    59     Core* Core::singletonRef_s = 0;
     76    Core* Core::singletonRef_s  = 0;
    6077
    6178    SetCommandLineArgument(mediaPath, "").information("PATH");
     
    7693
    7794        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
    78         OutputHandler::getOutStream().setLogPath(Core::logPath_s);
     95        OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
    7996
    8097        // Possible media path override by the command line
    8198        if (!CommandLine::getArgument("mediaPath")->hasDefaultValue())
    8299        {
    83             std::string mediaPath = CommandLine::getValue("mediaPath");
    84             Core::tsetMediaPath(mediaPath);
     100            //std::string mediaPath = CommandLine::getValue("mediaPath");
     101            Core::tsetMediaPath(CommandLine::getValue("mediaPath"));
    85102        }
    86103    }
     
    119136        SetConfigValue(bInitializeRandomNumberGenerator_, true).description("If true, all random actions are different each time you start the game").callback(this, &Core::initializeRandomNumberGenerator);
    120137
    121         // Media path (towards config and log path) is ini-configurable
    122         const char* defaultMediaPath = ORXONOX_MEDIA_INSTALL_PATH;
    123         if (Core::isDevBuild())
    124             defaultMediaPath = ORXONOX_MEDIA_DEV_PATH;
    125 
    126         SetConfigValue(mediaPath_s, defaultMediaPath)
     138        SetConfigValue(mediaPathString_, Core::getMediaPathPOSIXString())
    127139            .description("Relative path to the game data.").callback(this, &Core::mediaPathChanged);
    128 
    129140    }
    130141
     
    162173    void Core::mediaPathChanged()
    163174    {
    164         if (mediaPath_s != "" && mediaPath_s[mediaPath_s.size() - 1] != '/')
    165         {
    166             ModifyConfigValue(mediaPath_s, set, mediaPath_s + "/");
    167         }
    168 
    169         if (mediaPath_s == "")
    170         {
    171             ModifyConfigValue(mediaPath_s, set, "/");
    172             COUT(2) << "Warning: Data path set to \"/\", is that really correct?" << std::endl;
    173         }
     175        mediaPath_g = boost::filesystem::path(this->mediaPathString_);
    174176    }
    175177
     
    248250    void Core::_tsetMediaPath(const std::string& path)
    249251    {
    250         if (*path.end() != '/' && *path.end() != '\\')
    251         {
    252             ModifyConfigValue(mediaPath_s, tset, path + "/");
    253         }
    254         else
    255         {
    256             ModifyConfigValue(mediaPath_s, tset, path);
    257         }
     252        ModifyConfigValue(mediaPathString_, tset, path);
     253    }
     254
     255    /*static*/ const boost::filesystem::path& Core::getMediaPath()
     256    {
     257        return mediaPath_g;
     258    }
     259    /*static*/ std::string Core::getMediaPathString()
     260    {
     261        return mediaPath_g.directory_string() + CP_SLASH;
     262    }
     263    /*static*/ std::string Core::getMediaPathPOSIXString()
     264    {
     265        return mediaPath_g.string() + '/';
     266       
     267    }
     268
     269    /*static*/ const boost::filesystem::path& Core::getConfigPath()
     270    {
     271        return configPath_g;
     272    }
     273    /*static*/ std::string Core::getConfigPathString()
     274    {
     275        return configPath_g.directory_string() + CP_SLASH;
     276    }
     277    /*static*/ std::string Core::getConfigPathPOSIXString()
     278    {
     279        return configPath_g.string() + '/';
     280    }
     281
     282    /*static*/ const boost::filesystem::path& Core::getLogPath()
     283    {
     284        return logPath_g;
     285    }
     286    /*static*/ std::string Core::getLogPathString()
     287    {
     288        return logPath_g.directory_string() + CP_SLASH;
     289    }
     290    /*static*/ std::string Core::getLogPathPOSIXString()
     291    {
     292        return logPath_g.string() + '/';
    258293    }
    259294
     
    271306    /**
    272307    @brief
    273         Checks for "orxonox_dev_build.keep_me" in the working diretory.
     308        Performs the rather lower level operations just after
     309        int main() has been called.
     310    @remarks
     311        This gets called AFTER pre-main stuff like AddFactory,
     312        SetConsoleCommand, etc.
     313    */
     314    /*static*/ void Core::postMainInitialisation()
     315    {
     316        // set location of the executable
     317        Core::setExecutablePath();
     318
     319        // Determine whether we have an installed or a binary dir run
     320        // The latter occurs when simply running from the build directory
     321        Core::checkDevBuild();
     322
     323        // Make sure the directories we write in exist or else make them
     324        Core::createDirectories();
     325    }
     326
     327    /**
     328    @brief
     329        Compares the executable path with the working directory
     330    */
     331    /*static*/ void Core::setExecutablePath()
     332    {
     333#ifdef ORXONOX_PLATFORM_WINDOWS
     334        // get executable module
     335        TCHAR buffer[1024];
     336        if (GetModuleFileName(NULL, buffer, 1024) == 0)
     337            ThrowException(General, "Could not retrieve executable path.");
     338
     339#elif defined(ORXONOX_PLATFORM_APPLE)
     340        char buffer[1024];
     341        unsigned long path_len = 1023;
     342        if (_NSGetExecutablePath(buffer, &path_len))
     343            ThrowException(General, "Could not retrieve executable path.");
     344
     345#else /* Linux */
     346        /* written by Nicolai Haehnle <prefect_@gmx.net> */
     347
     348        /* Get our PID and build the name of the link in /proc */
     349        char linkname[64]; /* /proc/<pid>/exe */
     350        if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
     351        {
     352            /* This should only happen on large word systems. I'm not sure
     353               what the proper response is here.
     354               Since it really is an assert-like condition, aborting the
     355               program seems to be in order. */
     356            assert(false);
     357        }
     358
     359        /* Now read the symbolic link */
     360        char buffer[1024];
     361        int ret;
     362        ret = readlink(linkname, buffer, 1024);
     363        /* In case of an error, leave the handling up to the caller */
     364        if (ret == -1)
     365            ThrowException(General, "Could not retrieve executable path.");
     366
     367        /* Ensure proper NUL termination */
     368        buf[ret] = 0;
     369#endif
     370
     371        executablePath_g = boost::filesystem::path(buffer);
     372#ifndef ORXONOX_PLATFORM_APPLE
     373        executablePath_g = executablePath_g.branch_path(); // remove executable name
     374#endif
     375    }
     376
     377    /**
     378    @brief
     379        Checks for "orxonox_dev_build.keep_me" in the executable diretory.
    274380        If found it means that this is not an installed run, hence we
    275381        don't write the logs and config files to ~/.orxonox
     
    277383    /*static*/ void Core::checkDevBuild()
    278384    {
    279         std::ifstream probe;
    280         probe.open("orxonox_dev_build.keep_me");
    281         if (probe)
    282         {
     385        if (boost::filesystem::exists(executablePath_g / "orxonox_dev_build.keep_me"))
     386        {
     387            COUT(1) << "Running from the build tree." << std::endl;
    283388            Core::isDevBuild_s = true;
    284             // Constants are taken from OrxonoxConfig.h
    285             Core::configPath_s = ORXONOX_CONFIG_DEV_PATH;
    286             Core::logPath_s    = ORXONOX_LOG_DEV_PATH;
    287             Core::mediaPath_s  = ORXONOX_MEDIA_DEV_PATH;
    288             probe.close();
     389            mediaPath_g  = ORXONOX_MEDIA_DEV_PATH;
     390            configPath_g = ORXONOX_CONFIG_DEV_PATH;
     391            logPath_g    = ORXONOX_LOG_DEV_PATH;
     392        }
     393        else
     394        {
     395#ifdef INSTALL_COPYABLE // --> relative paths
     396            // Also set the root path
     397            boost::filesystem::path relativeExecutablePath(ORXONOX_RUNTIME_INSTALL_PATH);
     398            rootPath_g = executablePath_g;
     399            while (!boost::filesystem::equivalent(rootPath_g / relativeExecutablePath, executablePath_g) || rootPath_g.empty())
     400                rootPath_g = rootPath_g.branch_path();
     401            if (rootPath_g.empty())
     402                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
     403
     404            // Using paths relative to the install prefix, complete them
     405            mediaPath_g  = rootPath_g / ORXONOX_MEDIA_INSTALL_PATH;
     406            configPath_g = rootPath_g / ORXONOX_CONFIG_INSTALL_PATH;
     407            logPath_g    = rootPath_g / ORXONOX_LOG_INSTALL_PATH;
     408#else
     409            // There is no root path, so don't set it at all
     410
     411            mediaPath_g  = ORXONOX_MEDIA_INSTALL_PATH;
     412
     413            // Get user directory
     414#  ifdef ORXONOX_PLATFORM_UNIX /* Apple? */
     415            char* userDataPathPtr(getenv("HOME"));
     416#  else
     417            char* userDataPathPtr(getenv("APPDATA"));
     418#  endif
     419            if (userDataPathPtr == NULL)
     420                ThrowException(General, "Could not retrieve user data path.");
     421            boost::filesystem::path userDataPath(userDataPathPtr);
     422            userDataPath /= ".orxonox";
     423
     424            configPath_g = userDataPath / ORXONOX_CONFIG_INSTALL_PATH;
     425            logPath_g    = userDataPath / ORXONOX_LOG_INSTALL_PATH;
     426#endif
    289427        }
    290428    }
     
    299437        std::vector<std::pair<boost::filesystem::path, std::string> > directories;
    300438        directories.push_back(std::pair<boost::filesystem::path, std::string>
    301             (boost::filesystem::path(Core::configPath_s), "config"));
     439            (boost::filesystem::path(configPath_g), "config"));
    302440        directories.push_back(std::pair<boost::filesystem::path, std::string>
    303             (boost::filesystem::path(Core::logPath_s),    "log"));
     441            (boost::filesystem::path(logPath_g),    "log"));
    304442
    305443        for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();
Note: See TracChangeset for help on using the changeset viewer.