Changeset 6038 for sandbox/src/libraries/core/Core.cc
- Timestamp:
- Nov 5, 2009, 9:22:22 PM (14 years ago)
- Location:
- sandbox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
sandbox
- Property svn:mergeinfo changed
-
sandbox/src/libraries/core/Core.cc
r5782 r6038 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 #endif 59 60 #include "SpecialConfig.h" 48 #endif 49 50 #include "util/Clock.h" 61 51 #include "util/Debug.h" 62 52 #include "util/Exception.h" 63 53 #include "util/SignalHandler.h" 64 #include " Clock.h"65 #include "CommandLine .h"54 #include "PathConfig.h" 55 #include "CommandLineParser.h" 66 56 #include "ConfigFileManager.h" 67 57 #include "ConfigValueIncludes.h" 68 58 #include "CoreIncludes.h" 69 59 #include "DynLibManager.h" 70 #include "Factory.h"71 60 #include "Identifier.h" 72 61 #include "Language.h" 73 62 #include "LuaState.h" 74 75 // Boost 1.36 has some issues with deprecated functions that have been omitted76 #if (BOOST_VERSION == 103600)77 # define BOOST_LEAF_FUNCTION filename78 #else79 # define BOOST_LEAF_FUNCTION leaf80 #endif81 63 82 64 namespace orxonox … … 85 67 Core* Core::singletonPtr_s = 0; 86 68 87 SetCommandLineArgument(externalDataPath, "").information("Path to the external data files");88 SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");89 69 SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file"); 90 70 #ifdef ORXONOX_PLATFORM_WINDOWS … … 195 175 std::string language_; //!< The language 196 176 bool bInitializeRandomNumberGenerator_; //!< If true, srand(time(0)) is called 197 198 //! Path to the parent directory of the ones above if program was installed with relativ pahts199 boost::filesystem::path rootPath_;200 boost::filesystem::path executablePath_; //!< Path to the executable201 boost::filesystem::path modulePath_; //!< Path to the modules202 boost::filesystem::path dataPath_; //!< Path to the data file folder203 boost::filesystem::path configPath_; //!< Path to the config file folder204 boost::filesystem::path logPath_; //!< Path to the log file folder205 177 }; 206 178 … … 210 182 : identifierDestroyer_(Identifier::destroyAllIdentifiers) 211 183 , configuration_(new CoreConfiguration()) // Don't yet create config values! 212 , bDevRun_(false)213 184 { 214 185 // Set the hard coded fixed paths 215 this-> setFixedPaths();186 this->pathConfig_.reset(new PathConfig()); 216 187 217 188 // Create a new dynamic library manager … … 219 190 220 191 // Load modules 221 try 222 { 223 // We search for helper files with the following extension 224 std::string moduleextension = specialConfig::moduleExtension; 225 size_t moduleextensionlength = moduleextension.size(); 226 227 // Search in the directory of our executable 228 boost::filesystem::path searchpath = this->configuration_->modulePath_; 229 230 // Add that path to the PATH variable in case a module depends on another one 231 std::string pathVariable = getenv("PATH"); 232 putenv(const_cast<char*>(("PATH=" + pathVariable + ";" + configuration_->modulePath_.string()).c_str())); 233 234 boost::filesystem::directory_iterator file(searchpath); 235 boost::filesystem::directory_iterator end; 236 237 // Iterate through all files 238 while (file != end) 192 const std::vector<std::string>& modulePaths = this->pathConfig_->getModulePaths(); 193 for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it) 194 { 195 try 239 196 { 240 std::string filename = file->BOOST_LEAF_FUNCTION(); 241 242 // Check if the file ends with the exension in question 243 if (filename.size() > moduleextensionlength) 244 { 245 if (filename.substr(filename.size() - moduleextensionlength) == moduleextension) 246 { 247 // We've found a helper file - now load the library with the same name 248 std::string library = filename.substr(0, filename.size() - moduleextensionlength); 249 boost::filesystem::path librarypath = searchpath / library; 250 251 try 252 { 253 DynLibManager::getInstance().load(librarypath.string()); 254 } 255 catch (...) 256 { 257 COUT(1) << "Couldn't load module \"" << librarypath.string() << "\": " << Exception::handleMessage() << std::endl; 258 } 259 } 260 } 261 262 ++file; 197 this->dynLibManager_->load(*it); 263 198 } 264 }265 catch (...)266 {267 COUT(1) << "An error occurred while loading modules: " << Exception::handleMessage() << std::endl;199 catch (...) 200 { 201 COUT(1) << "Couldn't load module \"" << *it << "\": " << Exception::handleMessage() << std::endl; 202 } 268 203 } 269 204 270 205 // Parse command line arguments AFTER the modules have been loaded (static code!) 271 CommandLine ::parseCommandLine(cmdLine);206 CommandLineParser::parseCommandLine(cmdLine); 272 207 273 208 // Set configurable paths like log, config and media 274 this-> setConfigurablePaths();209 this->pathConfig_->setConfigurablePaths(); 275 210 276 211 // create a signal handler (only active for linux) 277 212 // This call is placed as soon as possible, but after the directories are set 278 213 this->signalHandler_.reset(new SignalHandler()); 279 this->signalHandler_->doCatch( configuration_->executablePath_.string(), Core::getLogPathString() + "orxonox_crash.log");214 this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log"); 280 215 281 216 // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used 282 OutputHandler::getOutStream().setLogPath( Core::getLogPathString());217 OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString()); 283 218 284 219 // Parse additional options file now that we know its path 285 CommandLine ::parseFile();220 CommandLineParser::parseFile(); 286 221 287 222 #ifdef ORXONOX_PLATFORM_WINDOWS … … 289 224 // do this after ogre has initialised. Somehow Ogre changes the settings again (not through 290 225 // the timer though). 291 int limitToCPU = CommandLine ::getValue("limitToCPU");226 int limitToCPU = CommandLineParser::getValue("limitToCPU"); 292 227 if (limitToCPU > 0) 293 228 setThreadAffinity(static_cast<unsigned int>(limitToCPU)); … … 297 232 this->configFileManager_.reset(new ConfigFileManager()); 298 233 this->configFileManager_->setFilename(ConfigFileType::Settings, 299 CommandLine ::getValue("settingsFile").getString());234 CommandLineParser::getValue("settingsFile").getString()); 300 235 301 236 // Required as well for the config values … … 303 238 304 239 // creates the class hierarchy for all classes with factories 305 Factory::createClassHierarchy();240 Identifier::createClassHierarchy(); 306 241 307 242 // Do this soon after the ConfigFileManager has been created to open up the … … 376 311 } 377 312 378 /*static*/ const boost::filesystem::path& Core::getDataPath()379 {380 return getInstance().configuration_->dataPath_;381 }382 /*static*/ std::string Core::getDataPathString()383 {384 return getInstance().configuration_->dataPath_.string() + '/';385 }386 387 /*static*/ const boost::filesystem::path& Core::getConfigPath()388 {389 return getInstance().configuration_->configPath_;390 }391 /*static*/ std::string Core::getConfigPathString()392 {393 return getInstance().configuration_->configPath_.string() + '/';394 }395 396 /*static*/ const boost::filesystem::path& Core::getLogPath()397 {398 return getInstance().configuration_->logPath_;399 }400 /*static*/ std::string Core::getLogPathString()401 {402 return getInstance().configuration_->logPath_.string() + '/';403 }404 405 /*static*/ const boost::filesystem::path& Core::getRootPath()406 {407 return getInstance().configuration_->rootPath_;408 }409 /*static*/ std::string Core::getRootPathString()410 {411 return getInstance().configuration_->rootPath_.string() + '/';412 }413 414 313 /** 415 314 @note … … 458 357 } 459 358 460 /**461 @brief462 Retrievs the executable path and sets all hard coded fixed path (currently only the module path)463 Also checks for "orxonox_dev_build.keep_me" in the executable diretory.464 If found it means that this is not an installed run, hence we465 don't write the logs and config files to ~/.orxonox466 @throw467 GeneralException468 */469 void Core::setFixedPaths()470 {471 //////////////////////////472 // FIND EXECUTABLE PATH //473 //////////////////////////474 475 #ifdef ORXONOX_PLATFORM_WINDOWS476 // get executable module477 TCHAR buffer[1024];478 if (GetModuleFileName(NULL, buffer, 1024) == 0)479 ThrowException(General, "Could not retrieve executable path.");480 481 #elif defined(ORXONOX_PLATFORM_APPLE)482 char buffer[1024];483 unsigned long path_len = 1023;484 if (_NSGetExecutablePath(buffer, &path_len))485 ThrowException(General, "Could not retrieve executable path.");486 487 #else /* Linux */488 /* written by Nicolai Haehnle <prefect_@gmx.net> */489 490 /* Get our PID and build the name of the link in /proc */491 char linkname[64]; /* /proc/<pid>/exe */492 if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)493 {494 /* This should only happen on large word systems. I'm not sure495 what the proper response is here.496 Since it really is an assert-like condition, aborting the497 program seems to be in order. */498 assert(false);499 }500 501 /* Now read the symbolic link */502 char buffer[1024];503 int ret;504 ret = readlink(linkname, buffer, 1024);505 /* In case of an error, leave the handling up to the caller */506 if (ret == -1)507 ThrowException(General, "Could not retrieve executable path.");508 509 /* Ensure proper NUL termination */510 buffer[ret] = 0;511 #endif512 513 configuration_->executablePath_ = boost::filesystem::path(buffer);514 #ifndef ORXONOX_PLATFORM_APPLE515 configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name516 #endif517 518 /////////////////////519 // SET MODULE PATH //520 /////////////////////521 522 if (boost::filesystem::exists(configuration_->executablePath_ / "orxonox_dev_build.keep_me"))523 {524 COUT(1) << "Running from the build tree." << std::endl;525 Core::bDevRun_ = true;526 configuration_->modulePath_ = specialConfig::moduleDevDirectory;527 }528 else529 {530 531 #ifdef INSTALL_COPYABLE // --> relative paths532 533 // Also set the root path534 boost::filesystem::path relativeExecutablePath(specialConfig::defaultRuntimePath);535 configuration_->rootPath_ = configuration_->executablePath_;536 while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)537 && !configuration_->rootPath_.empty())538 configuration_->rootPath_ = configuration_->rootPath_.branch_path();539 if (configuration_->rootPath_.empty())540 ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");541 542 // Module path is fixed as well543 configuration_->modulePath_ = configuration_->rootPath_ / specialConfig::defaultModulePath;544 545 #else546 547 // There is no root path, so don't set it at all548 // Module path is fixed as well549 configuration_->modulePath_ = specialConfig::moduleInstallDirectory;550 551 #endif552 }553 }554 555 /**556 @brief557 Sets config, log and media path and creates folders if necessary.558 @throws559 GeneralException560 */561 void Core::setConfigurablePaths()562 {563 if (Core::isDevelopmentRun())564 {565 configuration_->dataPath_ = specialConfig::dataDevDirectory;566 configuration_->configPath_ = specialConfig::configDevDirectory;567 configuration_->logPath_ = specialConfig::logDevDirectory;568 }569 else570 {571 572 #ifdef INSTALL_COPYABLE // --> relative paths573 574 // Using paths relative to the install prefix, complete them575 configuration_->dataPath_ = configuration_->rootPath_ / specialConfig::defaultDataPath;576 configuration_->configPath_ = configuration_->rootPath_ / specialConfig::defaultConfigPath;577 configuration_->logPath_ = configuration_->rootPath_ / specialConfig::defaultLogPath;578 579 #else580 581 configuration_->dataPath_ = specialConfig::dataInstallDirectory;582 583 // Get user directory584 # ifdef ORXONOX_PLATFORM_UNIX /* Apple? */585 char* userDataPathPtr(getenv("HOME"));586 # else587 char* userDataPathPtr(getenv("APPDATA"));588 # endif589 if (userDataPathPtr == NULL)590 ThrowException(General, "Could not retrieve user data path.");591 boost::filesystem::path userDataPath(userDataPathPtr);592 userDataPath /= ".orxonox";593 594 configuration_->configPath_ = userDataPath / specialConfig::defaultConfigPath;595 configuration_->logPath_ = userDataPath / specialConfig::defaultLogPath;596 597 #endif598 599 }600 601 // Option to put all the config and log files in a separate folder602 if (!CommandLine::getArgument("writingPathSuffix")->hasDefaultValue())603 {604 std::string directory(CommandLine::getValue("writingPathSuffix").getString());605 configuration_->configPath_ = configuration_->configPath_ / directory;606 configuration_->logPath_ = configuration_->logPath_ / directory;607 }608 609 // Create directories to avoid problems when opening files in non existent folders.610 std::vector<std::pair<boost::filesystem::path, std::string> > directories;611 directories.push_back(std::make_pair(boost::filesystem::path(configuration_->configPath_), "config"));612 directories.push_back(std::make_pair(boost::filesystem::path(configuration_->logPath_), "log"));613 614 for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();615 it != directories.end(); ++it)616 {617 if (boost::filesystem::exists(it->first) && !boost::filesystem::is_directory(it->first))618 {619 ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \620 Please remove " + it->first.string());621 }622 if (boost::filesystem::create_directories(it->first)) // function may not return true at all (bug?)623 {624 COUT(4) << "Created " << it->second << " directory" << std::endl;625 }626 }627 }628 629 359 void Core::preUpdate(const Clock& time) 630 360 {
Note: See TracChangeset
for help on using the changeset viewer.