From df1730a734e3084bd1a9fd47c07403d808d78aa0 Mon Sep 17 00:00:00 2001 From: Aokromes Date: Sat, 1 Apr 2017 07:20:43 +0200 Subject: [PATCH] Core/ScriptReloadMgr: Fixed scripts hot swapping on OS X --- cmake/macros/ConfigureScripts.cmake | 4 +- src/server/game/Scripting/ScriptReloadMgr.cpp | 75 ++++++++++++------- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/cmake/macros/ConfigureScripts.cmake b/cmake/macros/ConfigureScripts.cmake index f6371a32f96..1658f47e9e2 100644 --- a/cmake/macros/ConfigureScripts.cmake +++ b/cmake/macros/ConfigureScripts.cmake @@ -85,10 +85,12 @@ function(IsDynamicLinkingRequired variable) set(${variable} ${IS_REQUIRED} PARENT_SCOPE) endfunction() -# Stores the native variable name +# Stores the native variable name function(GetNativeSharedLibraryName module variable) if(WIN32) set(${variable} "${module}.dll" PARENT_SCOPE) + elseif(APPLE) + set(${variable} "lib${module}.dylib" PARENT_SCOPE) else() set(${variable} "lib${module}.so" PARENT_SCOPE) endif() diff --git a/src/server/game/Scripting/ScriptReloadMgr.cpp b/src/server/game/Scripting/ScriptReloadMgr.cpp index e06b3bb4b27..72f935e5cd1 100644 --- a/src/server/game/Scripting/ScriptReloadMgr.cpp +++ b/src/server/game/Scripting/ScriptReloadMgr.cpp @@ -67,6 +67,9 @@ namespace fs = boost::filesystem; #ifdef _WIN32 #include #define HOTSWAP_PLATFORM_REQUIRES_CACHING +#elif __APPLE__ + #include + #define HOTSWAP_PLATFORM_REQUIRES_CACHING #else // Posix #include // #define HOTSWAP_PLATFORM_REQUIRES_CACHING @@ -87,11 +90,13 @@ static char const* GetSharedLibraryPrefix() #endif } -// Returns "dll" on Windows and "so" on posix. +// Returns "dll" on Windows, "dylib" on OS X, and "so" on posix. static char const* GetSharedLibraryExtension() { #ifdef _WIN32 return "dll"; +#elif __APPLE__ + return "dylib"; #else // Posix return "so"; #endif @@ -103,6 +108,18 @@ typedef HMODULE HandleType; typedef void* HandleType; #endif +static fs::path GetDirectoryOfExecutable() +{ + ASSERT((!sConfigMgr->GetArguments().empty()), + "Expected the arguments to contain at least 1 element!"); + + fs::path path(sConfigMgr->GetArguments()[0]); + if (path.is_absolute()) + return path.parent_path(); + else + return fs::canonical(fs::absolute(path)).parent_path(); +} + class SharedLibraryUnloader { public: @@ -350,15 +367,6 @@ namespace std }; } -/// Escapes spaces in the given path -static std::string EscapeWindowsPath(std::string str) -{ -#ifdef _WIN32 - boost::algorithm::replace_all(str, " ", "\\ "); -#endif - return str; -} - /// Invokes a synchronous CMake process with the given arguments template static int InvokeCMakeCommand(T&&... args) @@ -554,7 +562,13 @@ public: /// Returns the absolute path to the script module directory static fs::path GetLibraryDirectory() { - return fs::absolute(sConfigMgr->GetStringDefault("HotSwap.ScriptDir", "scripts")); + // When an absolute path is given in the config use it, + // otherwise interpret paths relative to the executable. + fs::path path(sConfigMgr->GetStringDefault("HotSwap.ScriptDir", "scripts")); + if (path.is_absolute()) + return path; + else + return fs::absolute(path, GetDirectoryOfExecutable()); } /// Returns the absolute path to the scripts directory in the source tree. @@ -574,6 +588,17 @@ public: if (!sWorld->getBoolConfig(CONFIG_HOTSWAP_ENABLED)) return; + if (BuiltInConfig::GetBuildDirectory().find(" ") != std::string::npos) + { + TC_LOG_ERROR("scripts.hotswap", "Your build directory path \"%s\" " + "contains spaces, which isn't allowed for compatibility reasons! " + "You need to create a build directory which doesn't contain any space character " + "in it's path!", + BuiltInConfig::GetBuildDirectory().c_str()); + + return; + } + { auto const library_directory = GetLibraryDirectory(); if (!fs::exists(library_directory) || !fs::is_directory(library_directory)) @@ -740,7 +765,6 @@ private: static fs::path CalculateTemporaryCachePath() { auto path = fs::temp_directory_path(); - path /= Trinity::StringFormat("tc_script_cache_%s_%s", GitRevision::GetBranch(), CalculateSHA1Hash(sConfigMgr->GetFilename()).c_str()); @@ -1008,8 +1032,10 @@ private: FIXME: Currently crashes the server TC_LOG_INFO("scripts.hotswap", "Terminating the running build of module \"%s\"...", _build_job->GetModuleName().c_str()); + _build_job->GetProcess()->Terminate(); _build_job.reset(); + // Continue with the default execution path DispatchRunningBuildJobs(); return; @@ -1219,7 +1245,7 @@ private: TC_LOG_INFO("scripts.hotswap", "Rerunning CMake because there were sources added or removed..."); _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_RERUN_CMAKE, - InvokeAsyncCMakeCommand(EscapeWindowsPath(BuiltInConfig::GetBuildDirectory()))); + InvokeAsyncCMakeCommand(BuiltInConfig::GetBuildDirectory())); } /// Invokes a new build of the current active module job @@ -1232,9 +1258,9 @@ private: _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_COMPILE, InvokeAsyncCMakeCommand( - "--build", EscapeWindowsPath(BuiltInConfig::GetBuildDirectory()), - "--target", EscapeWindowsPath(_build_job->GetProjectName()), - "--config", EscapeWindowsPath(_build_job->GetBuildDirective()))); + "--build", BuiltInConfig::GetBuildDirectory(), + "--target", _build_job->GetProjectName(), + "--config", _build_job->GetBuildDirective())); } /// Invokes a new asynchronous install of the current active module job @@ -1247,10 +1273,10 @@ private: _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_INSTALL, InvokeAsyncCMakeCommand( - "-DCOMPONENT=" + EscapeWindowsPath(_build_job->GetProjectName()), - "-DBUILD_TYPE=" + EscapeWindowsPath(_build_job->GetBuildDirective()), - "-P", EscapeWindowsPath(fs::absolute("cmake_install.cmake", - BuiltInConfig::GetBuildDirectory()).generic_string()))); + "-DCOMPONENT=" + _build_job->GetProjectName(), + "-DBUILD_TYPE=" + _build_job->GetBuildDirective(), + "-P", fs::absolute("cmake_install.cmake", + BuiltInConfig::GetBuildDirectory()).generic_string())); } /// Sets the CMAKE_INSTALL_PREFIX variable in the CMake cache @@ -1321,7 +1347,7 @@ private: #ifndef _WIN32 // The worldserver location is ${CMAKE_INSTALL_PREFIX}/bin // on all other platforms then windows - current_path = current_path.remove_leaf(); + current_path = current_path.parent_path(); #endif if (value != current_path) @@ -1337,7 +1363,7 @@ private: if (base == branch) return true; - branch = branch.remove_leaf(); + branch = branch.parent_path(); } return false; @@ -1361,8 +1387,8 @@ private: TC_LOG_INFO("scripts.hotswap", "Invoking CMake cache correction..."); auto const error = InvokeCMakeCommand( - "-DCMAKE_INSTALL_PREFIX:PATH=" + EscapeWindowsPath(fs::current_path().generic_string()), - EscapeWindowsPath(BuiltInConfig::GetBuildDirectory())); + "-DCMAKE_INSTALL_PREFIX:PATH=" + fs::current_path().generic_string(), + BuiltInConfig::GetBuildDirectory()); if (error) { @@ -1619,4 +1645,3 @@ ScriptReloadMgr* ScriptReloadMgr::instance() } #endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING -