Changeset 5836 for code/branches/core5/src/libraries/core/Core.cc
- Timestamp:
- Sep 30, 2009, 12:00:16 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/core5/src/libraries/core/Core.cc
r5778 r5836 37 37 38 38 #include <cassert> 39 #include <fstream> 40 #include <cstdlib> 41 #include <cstdio> 42 #include <boost/version.hpp> 43 #include <boost/filesystem.hpp> 39 #include <vector> 44 40 45 41 #ifdef ORXONOX_PLATFORM_WINDOWS … … 50 46 # undef min 51 47 # undef max 52 #elif defined(ORXONOX_PLATFORM_APPLE)53 # include <sys/param.h>54 # include <mach-o/dyld.h>55 #else /* Linux */56 # include <sys/types.h>57 # include <unistd.h>58 48 #endif 59 49 60 #include "SpecialConfig.h"61 50 #include "util/Debug.h" 62 51 #include "util/Exception.h" 63 52 #include "util/SignalHandler.h" 53 #include "PathConfig.h" 64 54 #include "Clock.h" 65 55 #include "CommandExecutor.h" … … 80 70 #include "input/InputManager.h" 81 71 82 // Boost 1.36 has some issues with deprecated functions that have been omitted83 #if (BOOST_VERSION == 103600)84 # define BOOST_LEAF_FUNCTION filename85 #else86 # define BOOST_LEAF_FUNCTION leaf87 #endif88 89 72 namespace orxonox 90 73 { … … 92 75 Core* Core::singletonPtr_s = 0; 93 76 94 SetCommandLineArgument(externalDataPath, "").information("Path to the external data files");95 SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");96 77 SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file"); 97 78 #ifdef ORXONOX_PLATFORM_WINDOWS … … 116 97 RegisterRootObject(CoreConfiguration); 117 98 this->setConfigValues(); 118 119 // External data directory only exists for dev runs120 if (Core::isDevelopmentRun())121 {122 // Possible data path override by the command line123 if (!CommandLine::getArgument("externalDataPath")->hasDefaultValue())124 tsetExternalDataPath(CommandLine::getValue("externalDataPath"));125 }126 99 } 127 100 … … 193 166 } 194 167 195 /**196 @brief197 Temporary sets the external data path198 @param path199 The new data path200 */201 void tsetExternalDataPath(const std::string& path)202 {203 externalDataPath_ = boost::filesystem::path(path);204 }205 206 168 void initializeRandomNumberGenerator() 207 169 { … … 221 183 std::string language_; //!< The language 222 184 bool bInitializeRandomNumberGenerator_; //!< If true, srand(time(0)) is called 223 224 //! Path to the parent directory of the ones above if program was installed with relativ pahts225 boost::filesystem::path rootPath_;226 boost::filesystem::path executablePath_; //!< Path to the executable227 boost::filesystem::path modulePath_; //!< Path to the modules228 boost::filesystem::path dataPath_; //!< Path to the data file folder229 boost::filesystem::path externalDataPath_; //!< Path to the external data file folder230 boost::filesystem::path configPath_; //!< Path to the config file folder231 boost::filesystem::path logPath_; //!< Path to the log file folder232 185 }; 233 186 … … 239 192 , consoleCommandDestroyer_(CommandExecutor::destroyExternalCommands) 240 193 , configuration_(new CoreConfiguration()) // Don't yet create config values! 241 , bDevRun_(false)242 194 , bGraphicsLoaded_(false) 243 195 { 244 196 // Set the hard coded fixed paths 245 this-> setFixedPaths();197 this->pathConfig_.reset(new PathConfig()); 246 198 247 199 // Create a new dynamic library manager … … 249 201 250 202 // Load modules 251 try 252 { 253 // We search for helper files with the following extension 254 std::string moduleextension = specialConfig::moduleExtension; 255 size_t moduleextensionlength = moduleextension.size(); 256 257 // Search in the directory of our executable 258 boost::filesystem::path searchpath = this->configuration_->modulePath_; 259 260 // Add that path to the PATH variable in case a module depends on another one 261 std::string pathVariable = getenv("PATH"); 262 putenv(const_cast<char*>(("PATH=" + pathVariable + ";" + configuration_->modulePath_.string()).c_str())); 263 264 boost::filesystem::directory_iterator file(searchpath); 265 boost::filesystem::directory_iterator end; 266 267 // Iterate through all files 268 while (file != end) 203 std::vector<std::string>& modulePaths = this->pathConfig_->getModulePaths(); 204 for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it) 205 { 206 try 269 207 { 270 std::string filename = file->BOOST_LEAF_FUNCTION(); 271 272 // Check if the file ends with the exension in question 273 if (filename.size() > moduleextensionlength) 274 { 275 if (filename.substr(filename.size() - moduleextensionlength) == moduleextension) 276 { 277 // We've found a helper file - now load the library with the same name 278 std::string library = filename.substr(0, filename.size() - moduleextensionlength); 279 boost::filesystem::path librarypath = searchpath / library; 280 281 try 282 { 283 DynLibManager::getInstance().load(librarypath.string()); 284 } 285 catch (...) 286 { 287 COUT(1) << "Couldn't load module \"" << librarypath.string() << "\": " << Exception::handleMessage() << std::endl; 288 } 289 } 290 } 291 292 ++file; 208 this->dynLibManager_->load(*it); 293 209 } 294 }295 catch (...)296 {297 COUT(1) << "An error occurred while loading modules: " << Exception::handleMessage() << std::endl;210 catch (...) 211 { 212 COUT(1) << "Couldn't load module \"" << *it << "\": " << Exception::handleMessage() << std::endl; 213 } 298 214 } 299 215 … … 302 218 303 219 // Set configurable paths like log, config and media 304 this-> setConfigurablePaths();220 this->pathConfig_->setConfigurablePaths(); 305 221 306 222 // create a signal handler (only active for linux) 307 223 // This call is placed as soon as possible, but after the directories are set 308 224 this->signalHandler_.reset(new SignalHandler()); 309 this->signalHandler_->doCatch( configuration_->executablePath_.string(), Core::getLogPathString() + "orxonox_crash.log");225 this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log"); 310 226 311 227 // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used 312 OutputHandler::getOutStream().setLogPath( Core::getLogPathString());228 OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString()); 313 229 314 230 // Parse additional options file now that we know its path … … 343 259 344 260 // initialise Tcl 345 this->tclBind_.reset(new TclBind( Core::getDataPathString()));261 this->tclBind_.reset(new TclBind(PathConfig::getDataPathString())); 346 262 this->tclThreadManager_.reset(new TclThreadManager(tclBind_->getTclInterpreter())); 347 263 … … 456 372 } 457 373 458 /*static*/ void Core::tsetExternalDataPath(const std::string& path)459 {460 getInstance().configuration_->tsetExternalDataPath(path);461 }462 463 /*static*/ const boost::filesystem::path& Core::getDataPath()464 {465 return getInstance().configuration_->dataPath_;466 }467 /*static*/ std::string Core::getDataPathString()468 {469 return getInstance().configuration_->dataPath_.string() + '/';470 }471 472 /*static*/ const boost::filesystem::path& Core::getExternalDataPath()473 {474 return getInstance().configuration_->externalDataPath_;475 }476 /*static*/ std::string Core::getExternalDataPathString()477 {478 return getInstance().configuration_->externalDataPath_.string() + '/';479 }480 481 /*static*/ const boost::filesystem::path& Core::getConfigPath()482 {483 return getInstance().configuration_->configPath_;484 }485 /*static*/ std::string Core::getConfigPathString()486 {487 return getInstance().configuration_->configPath_.string() + '/';488 }489 490 /*static*/ const boost::filesystem::path& Core::getLogPath()491 {492 return getInstance().configuration_->logPath_;493 }494 /*static*/ std::string Core::getLogPathString()495 {496 return getInstance().configuration_->logPath_.string() + '/';497 }498 499 /*static*/ const boost::filesystem::path& Core::getRootPath()500 {501 return getInstance().configuration_->rootPath_;502 }503 /*static*/ std::string Core::getRootPathString()504 {505 return getInstance().configuration_->rootPath_.string() + '/';506 }507 508 374 /** 509 375 @note … … 552 418 } 553 419 554 /**555 @brief556 Retrievs the executable path and sets all hard coded fixed path (currently only the module path)557 Also checks for "orxonox_dev_build.keep_me" in the executable diretory.558 If found it means that this is not an installed run, hence we559 don't write the logs and config files to ~/.orxonox560 @throw561 GeneralException562 */563 void Core::setFixedPaths()564 {565 //////////////////////////566 // FIND EXECUTABLE PATH //567 //////////////////////////568 569 #ifdef ORXONOX_PLATFORM_WINDOWS570 // get executable module571 TCHAR buffer[1024];572 if (GetModuleFileName(NULL, buffer, 1024) == 0)573 ThrowException(General, "Could not retrieve executable path.");574 575 #elif defined(ORXONOX_PLATFORM_APPLE)576 char buffer[1024];577 unsigned long path_len = 1023;578 if (_NSGetExecutablePath(buffer, &path_len))579 ThrowException(General, "Could not retrieve executable path.");580 581 #else /* Linux */582 /* written by Nicolai Haehnle <prefect_@gmx.net> */583 584 /* Get our PID and build the name of the link in /proc */585 char linkname[64]; /* /proc/<pid>/exe */586 if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)587 {588 /* This should only happen on large word systems. I'm not sure589 what the proper response is here.590 Since it really is an assert-like condition, aborting the591 program seems to be in order. */592 assert(false);593 }594 595 /* Now read the symbolic link */596 char buffer[1024];597 int ret;598 ret = readlink(linkname, buffer, 1024);599 /* In case of an error, leave the handling up to the caller */600 if (ret == -1)601 ThrowException(General, "Could not retrieve executable path.");602 603 /* Ensure proper NUL termination */604 buffer[ret] = 0;605 #endif606 607 configuration_->executablePath_ = boost::filesystem::path(buffer);608 #ifndef ORXONOX_PLATFORM_APPLE609 configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name610 #endif611 612 /////////////////////613 // SET MODULE PATH //614 /////////////////////615 616 if (boost::filesystem::exists(configuration_->executablePath_ / "orxonox_dev_build.keep_me"))617 {618 COUT(1) << "Running from the build tree." << std::endl;619 Core::bDevRun_ = true;620 configuration_->modulePath_ = specialConfig::moduleDevDirectory;621 }622 else623 {624 625 #ifdef INSTALL_COPYABLE // --> relative paths626 627 // Also set the root path628 boost::filesystem::path relativeExecutablePath(specialConfig::defaultRuntimePath);629 configuration_->rootPath_ = configuration_->executablePath_;630 while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)631 && !configuration_->rootPath_.empty())632 configuration_->rootPath_ = configuration_->rootPath_.branch_path();633 if (configuration_->rootPath_.empty())634 ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");635 636 // Module path is fixed as well637 configuration_->modulePath_ = configuration_->rootPath_ / specialConfig::defaultModulePath;638 639 #else640 641 // There is no root path, so don't set it at all642 // Module path is fixed as well643 configuration_->modulePath_ = specialConfig::moduleInstallDirectory;644 645 #endif646 }647 }648 649 /**650 @brief651 Sets config, log and media path and creates folders if necessary.652 @throws653 GeneralException654 */655 void Core::setConfigurablePaths()656 {657 if (Core::isDevelopmentRun())658 {659 configuration_->dataPath_ = specialConfig::dataDevDirectory;660 configuration_->externalDataPath_ = specialConfig::externalDataDevDirectory;661 configuration_->configPath_ = specialConfig::configDevDirectory;662 configuration_->logPath_ = specialConfig::logDevDirectory;663 }664 else665 {666 667 #ifdef INSTALL_COPYABLE // --> relative paths668 669 // Using paths relative to the install prefix, complete them670 configuration_->dataPath_ = configuration_->rootPath_ / specialConfig::defaultDataPath;671 configuration_->configPath_ = configuration_->rootPath_ / specialConfig::defaultConfigPath;672 configuration_->logPath_ = configuration_->rootPath_ / specialConfig::defaultLogPath;673 674 #else675 676 configuration_->dataPath_ = specialConfig::dataInstallDirectory;677 678 // Get user directory679 # ifdef ORXONOX_PLATFORM_UNIX /* Apple? */680 char* userDataPathPtr(getenv("HOME"));681 # else682 char* userDataPathPtr(getenv("APPDATA"));683 # endif684 if (userDataPathPtr == NULL)685 ThrowException(General, "Could not retrieve user data path.");686 boost::filesystem::path userDataPath(userDataPathPtr);687 userDataPath /= ".orxonox";688 689 configuration_->configPath_ = userDataPath / specialConfig::defaultConfigPath;690 configuration_->logPath_ = userDataPath / specialConfig::defaultLogPath;691 692 #endif693 694 }695 696 // Option to put all the config and log files in a separate folder697 if (!CommandLine::getArgument("writingPathSuffix")->hasDefaultValue())698 {699 std::string directory(CommandLine::getValue("writingPathSuffix").getString());700 configuration_->configPath_ = configuration_->configPath_ / directory;701 configuration_->logPath_ = configuration_->logPath_ / directory;702 }703 704 // Create directories to avoid problems when opening files in non existent folders.705 std::vector<std::pair<boost::filesystem::path, std::string> > directories;706 directories.push_back(std::make_pair(boost::filesystem::path(configuration_->configPath_), "config"));707 directories.push_back(std::make_pair(boost::filesystem::path(configuration_->logPath_), "log"));708 709 for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();710 it != directories.end(); ++it)711 {712 if (boost::filesystem::exists(it->first) && !boost::filesystem::is_directory(it->first))713 {714 ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \715 Please remove " + it->first.string());716 }717 if (boost::filesystem::create_directories(it->first)) // function may not return true at all (bug?)718 {719 COUT(4) << "Created " << it->second << " directory" << std::endl;720 }721 }722 }723 724 420 void Core::preUpdate(const Clock& time) 725 421 {
Note: See TracChangeset
for help on using the changeset viewer.