diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 862d1c545f..7d5230f894 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -105,6 +106,7 @@ std::pair > CS::Editor::readConfi boost::program_options::notify(variables); mCfgMgr.readConfiguration(variables, desc, false); + setupLogging(mCfgMgr.getLogPath().string(), "OpenMW-CS"); Fallback::Map::init(variables["fallback"].as().mMap); diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index c7d57a256e..1e6e718983 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -79,5 +79,5 @@ int runApplication(int argc, char *argv[]) int main(int argc, char *argv[]) { - return wrapApplication(&runApplication, argc, argv, "OpenMW-CS"); + return wrapApplication(&runApplication, argc, argv, "OpenMW-CS", false); } diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index d5bed4ba25..6b92fa78f5 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -65,6 +65,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat cfgMgr.readConfiguration(variables, desc); Files::mergeComposingVariables(variables, composingVariables, desc); + setupLogging(cfgMgr.getLogPath().string(), "OpenMW"); + Version::Version v = Version::getOpenmwVersion(variables["resources"].as().string()); Log(Debug::Info) << v.describe(); @@ -230,7 +232,7 @@ extern "C" int SDL_main(int argc, char**argv) int main(int argc, char**argv) #endif { - return wrapApplication(&runApplication, argc, argv, "OpenMW"); + return wrapApplication(&runApplication, argc, argv, "OpenMW", false); } // Platform specific for Windows when there is no console built into the executable. diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index 0e372942f2..c84bb39d3d 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -137,61 +137,65 @@ namespace Debug } static std::unique_ptr rawStdout = nullptr; +static std::unique_ptr rawStderr = nullptr; +static boost::filesystem::ofstream logfile; + +#if defined(_WIN32) && defined(_DEBUG) +static boost::iostreams::stream_buffer sb; +#else +static boost::iostreams::stream_buffer coutsb; +static boost::iostreams::stream_buffer cerrsb; +#endif std::ostream& getRawStdout() { return rawStdout ? *rawStdout : std::cout; } -int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[], const std::string& appName) +// Redirect cout and cerr to the log file +void setupLogging(const std::string& logDir, const std::string& appName, std::ios_base::openmode mode) +{ +#if defined(_WIN32) && defined(_DEBUG) + // Redirect cout and cerr to VS debug output when running in debug mode + sb.open(Debug::DebugOutput()); + std::cout.rdbuf(&sb); + std::cerr.rdbuf(&sb); +#else + const std::string logName = Misc::StringUtils::lowerCase(appName) + ".log"; + logfile.open(boost::filesystem::path(logDir) / logName, mode); + + coutsb.open(Debug::Tee(logfile, *rawStdout)); + cerrsb.open(Debug::Tee(logfile, *rawStderr)); + + std::cout.rdbuf(&coutsb); + std::cerr.rdbuf(&cerrsb); +#endif +} + +int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[], + const std::string& appName, bool autoSetupLogging) { #if defined _WIN32 (void)Debug::attachParentConsole(); #endif rawStdout = std::make_unique(std::cout.rdbuf()); - - // Some objects used to redirect cout and cerr - // Scope must be here, so this still works inside the catch block for logging exceptions - std::streambuf* cout_rdbuf = std::cout.rdbuf (); - std::streambuf* cerr_rdbuf = std::cerr.rdbuf (); - -#if defined(_WIN32) && defined(_DEBUG) - boost::iostreams::stream_buffer sb; -#else - boost::iostreams::stream_buffer coutsb; - boost::iostreams::stream_buffer cerrsb; - std::ostream oldcout(cout_rdbuf); - std::ostream oldcerr(cerr_rdbuf); -#endif - - const std::string logName = Misc::StringUtils::lowerCase(appName) + ".log"; - boost::filesystem::ofstream logfile; + rawStderr = std::make_unique(std::cerr.rdbuf()); int ret = 0; try { Files::ConfigurationManager cfgMgr; -#if defined(_WIN32) && defined(_DEBUG) - // Redirect cout and cerr to VS debug output when running in debug mode - sb.open(Debug::DebugOutput()); - std::cout.rdbuf (&sb); - std::cerr.rdbuf (&sb); -#else - // Redirect cout and cerr to the log file - // If we are collecting a stack trace, append to existing log file - std::ios_base::openmode mode = std::ios::out; - if(argc == 2 && strcmp(argv[1], crash_switch) == 0) - mode |= std::ios::app; + if (autoSetupLogging) + { + std::ios_base::openmode mode = std::ios::out; - logfile.open (boost::filesystem::path(cfgMgr.getLogPath() / logName), mode); + // If we are collecting a stack trace, append to existing log file + if (argc == 2 && strcmp(argv[1], crash_switch) == 0) + mode |= std::ios::app; - coutsb.open (Debug::Tee(logfile, oldcout)); - cerrsb.open (Debug::Tee(logfile, oldcerr)); - - std::cout.rdbuf (&coutsb); - std::cerr.rdbuf (&cerrsb); -#endif + setupLogging(cfgMgr.getLogPath().string(), appName, mode); + } #if defined(_WIN32) const std::string crashLogName = Misc::StringUtils::lowerCase(appName) + "-crash.dmp"; @@ -217,8 +221,8 @@ int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, c } // Restore cout and cerr - std::cout.rdbuf(cout_rdbuf); - std::cerr.rdbuf(cerr_rdbuf); + std::cout.rdbuf(rawStdout->rdbuf()); + std::cerr.rdbuf(rawStderr->rdbuf()); Debug::CurrentDebugLevel = Debug::NoLevel; return ret; diff --git a/components/debug/debugging.hpp b/components/debug/debugging.hpp index d8849cd896..a2c5ae9e6c 100644 --- a/components/debug/debugging.hpp +++ b/components/debug/debugging.hpp @@ -133,11 +133,16 @@ namespace Debug std::map mColors; }; #endif + + } // Can be used to print messages without timestamps std::ostream& getRawStdout(); -int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[], const std::string& appName); +void setupLogging(const std::string& logDir, const std::string& appName, std::ios_base::openmode = std::ios::out); + +int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[], + const std::string& appName, bool autoSetupLogging = true); #endif