Core/ScriptReloadMgr: Fixed scripts hot swapping on OS X

This commit is contained in:
Aokromes
2017-04-01 07:20:43 +02:00
parent 84cba8496c
commit df1730a734
2 changed files with 53 additions and 26 deletions

View File

@@ -67,6 +67,9 @@ namespace fs = boost::filesystem;
#ifdef _WIN32
#include <windows.h>
#define HOTSWAP_PLATFORM_REQUIRES_CACHING
#elif __APPLE__
#include <dlfcn.h>
#define HOTSWAP_PLATFORM_REQUIRES_CACHING
#else // Posix
#include <dlfcn.h>
// #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<typename... T>
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