summaryrefslogtreecommitdiff
path: root/Runtime/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Modules')
-rw-r--r--Runtime/Modules/ExportModules.h32
-rw-r--r--Runtime/Modules/LoadDylib.cpp230
-rw-r--r--Runtime/Modules/LoadDylib.h13
-rw-r--r--Runtime/Modules/ModuleRegistration.cpp93
-rw-r--r--Runtime/Modules/ModuleRegistration.h21
-rw-r--r--Runtime/Modules/RegisterStaticallyLinkedModules.cpp73
-rw-r--r--Runtime/Modules/RegisterStaticallyLinkedModules.h3
7 files changed, 465 insertions, 0 deletions
diff --git a/Runtime/Modules/ExportModules.h b/Runtime/Modules/ExportModules.h
new file mode 100644
index 0000000..47f6b02
--- /dev/null
+++ b/Runtime/Modules/ExportModules.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#ifndef BUILDING_COREMODULE
+#define BUILDING_COREMODULE 1
+#endif
+
+#if UNITY_WIN && UNITY_STANDALONE && !UNITY_WINRT && 0
+
+#if BUILDING_COREMODULE
+#define EXPORT_COREMODULE __declspec(dllexport)
+#else
+#define EXPORT_COREMODULE __declspec(dllimport)
+#endif
+
+#define EXPORT_MODULE __declspec(dllexport)
+
+#elif UNITY_OSX && UNITY_STANDALONE && 0
+
+#if BUILDING_COREMODULE
+#define EXPORT_COREMODULE __attribute__((visibility("default")))
+#else
+#define EXPORT_COREMODULE
+#endif
+
+#define EXPORT_MODULE __attribute__((visibility("default")))
+
+#else
+
+#define EXPORT_COREMODULE
+#define EXPORT_MODULE
+
+#endif
diff --git a/Runtime/Modules/LoadDylib.cpp b/Runtime/Modules/LoadDylib.cpp
new file mode 100644
index 0000000..581a770
--- /dev/null
+++ b/Runtime/Modules/LoadDylib.cpp
@@ -0,0 +1,230 @@
+#include "UnityPrefix.h"
+#include "LoadDylib.h"
+#include <map>
+
+#if UNITY_OSX || UNITY_LINUX
+#include "dlfcn.h"
+#endif
+
+#if UNITY_WIN
+#include "PlatformDependent/Win/PathUnicodeConversion.h"
+#endif
+
+#if UNITY_WINRT
+#include "PlatformDependent/MetroPlayer/MetroUtils.h"
+#endif
+
+using namespace std;
+
+map<string, void*> gLoaded;
+
+
+std::string GetPathWithPlatformSpecificDllExtension(const std::string& path)
+{
+ string extended = path;
+
+ #if UNITY_OSX
+ extended += ".dylib";
+ #elif UNITY_WIN
+ extended += ".dll";
+ #elif UNITY_LINUX
+ extended += ".so";
+ #else
+ ErrorString ("Dynamic module loading not implemented");
+ #endif
+
+ return extended;
+}
+
+
+void* LoadDynamicLibrary (const std::string& absolutePath)
+{
+ void* library = NULL;
+
+ // load library if needed
+ if (gLoaded.find(absolutePath) != gLoaded.end())
+ {
+ library = gLoaded[absolutePath];
+ }
+ else
+ {
+ #if UNITY_OSX || UNITY_LINUX
+ /// RTLD_LOCAL is supposedly default and also completely fails on 10.3.9
+ library = dlopen (absolutePath.c_str (), RTLD_NOW);
+ if ( !library )
+ ErrorStringMsg( "ERROR: LoadDynamicLibrary(): %s\n", dlerror() );
+
+ #elif UNITY_WIN
+
+ #if UNITY_WINRT
+ HMODULE module = LoadPackagedLibrary (ConvertToWindowsPath(absolutePath.c_str())->Data(), 0);
+ #else
+ std::wstring widePath;
+ ConvertUnityPathName( absolutePath, widePath );
+ HINSTANCE module = LoadLibraryW( widePath.c_str() );
+ #endif
+ library = module;
+
+ #endif
+
+ if (library)
+ {
+ gLoaded[absolutePath] = library;
+ }
+ }
+
+ return library;
+}
+
+
+void* LoadAndLookupSymbol (const std::string& absolutePath, const std::string& name)
+{
+ void* library = LoadDynamicLibrary(absolutePath);
+ void* symbol = LookupSymbol(library, name);
+ return symbol;
+}
+
+
+void UnloadDynamicLibrary (void* libraryReference)
+{
+ map<string, void*>::iterator it;
+ for (it = gLoaded.begin(); it != gLoaded.end(); ++it)
+ {
+ if (it->second == libraryReference)
+ {
+ #if UNITY_OSX || UNITY_LINUX
+ dlclose (it->second);
+ #elif UNITY_WIN
+ FreeLibrary( (HMODULE)it->second );
+ #endif
+
+ gLoaded.erase(it);
+ break;
+ }
+ }
+}
+
+
+void UnloadDynamicLibrary (const std::string& absolutePath)
+{
+ if (gLoaded.count (absolutePath) && gLoaded[absolutePath])
+ {
+ #if UNITY_OSX || UNITY_LINUX
+ dlclose (gLoaded[absolutePath]);
+ #elif UNITY_WIN
+ FreeLibrary( (HMODULE)gLoaded[absolutePath] );
+ #endif
+ }
+ gLoaded.erase (absolutePath);
+}
+
+
+bool LoadAndLookupSymbols (const char* path, ...)
+{
+ va_list ap;
+ va_start (ap, path);
+ while (true)
+ {
+ const char* symbolName = va_arg (ap, const char*);
+ if (symbolName == NULL)
+ return true;
+
+ void** functionHandle = va_arg (ap, void**);
+ AssertIf(functionHandle == NULL);
+
+ *functionHandle = LoadAndLookupSymbol (path, symbolName);
+ if (*functionHandle == NULL)
+ return false;
+ }
+
+ return false;
+}
+
+void* LookupSymbol(void* libraryReference, const std::string& symbolName)
+{
+#if UNITY_OSX || UNITY_LINUX
+
+ void *sym = dlsym (libraryReference, symbolName.c_str ());
+ if (!sym)
+ ErrorStringMsg("Could not load symbol %s : %s\n", symbolName.c_str(), dlerror());
+ return sym;
+
+#elif UNITY_WIN
+
+ if( !libraryReference )
+ return NULL;
+ return GetProcAddress( (HMODULE)libraryReference, symbolName.c_str() );
+
+#else
+ ErrorStringMsg("LoadAndLookupSymbol is not supported on this platform.\n");
+ return NULL;
+#endif
+}
+
+/*
+
+#include <Carbon/Carbon.h>
+#import <mach-o/dyld.h>
+#import <stdlib.h>
+#import <string.h>
+#include "FileUtilities.h"
+
+using namespace std;
+
+CFBundleRef LoadDynamicLibrary (const string& absolutePath)
+{
+ CFStringRef cfstring = CFStringCreateWithCString (NULL, ResolveSymlinks(absolutePath).c_str (), kCFStringEncodingUTF8);
+
+ CFURLRef url = CFURLCreateWithFileSystemPath(
+ kCFAllocatorDefault,
+ cfstring,
+ kCFURLPOSIXPathStyle,
+ false);
+// CFURLRef url = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, (const UInt8*)absolutePath.c_str (), absolutePath.size (), false);
+
+ CFBundleRef bundle = CFBundleCreate (NULL, url);
+ CFRelease (url);
+ CFRelease (cfstring);
+ if (!bundle)
+ return false;
+
+ // Check if already loaded
+ if (CFBundleIsExecutableLoaded (bundle))
+ return bundle;
+
+ // Load the bundle
+ if (!CFBundleLoadExecutable (bundle))
+ return NULL;
+
+ return bundle;
+}
+
+void UnloadDynamicLibrary (const string& absolutePath)
+{
+// CFURLRef url = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, (const UInt8*)absolutePath.c_str (), absolutePath.size (), false);
+ CFStringRef cfstring = CFStringCreateWithCString (kCFAllocatorDefault, absolutePath.c_str (), kCFStringEncodingUTF8);
+
+ CFURLRef url = CFURLCreateWithFileSystemPath(
+ kCFAllocatorDefault,
+ cfstring,
+ kCFURLPOSIXPathStyle,
+ true);
+
+ CFBundleRef bundle = CFBundleCreate (kCFAllocatorDefault, url);
+ CFRelease (url);
+ CFRelease (cfstring);
+ if (!bundle)
+ return;
+
+ CFBundleUnloadExecutable (bundle);
+}
+
+void* LoadAndLookupSymbol (const std::string& absolutePath, const std::string& name)
+{
+ CFBundleRef bundle = LoadDynamicLibrary (absolutePath);
+ CFStringRef cfstring = CFStringCreateWithCString (kCFAllocatorDefault, name.c_str (), kCFStringEncodingUTF8);
+ if (bundle == NULL)
+ return NULL;
+
+ return CFBundleGetFunctionPointerForName(bundle, cfstring);
+}*/
diff --git a/Runtime/Modules/LoadDylib.h b/Runtime/Modules/LoadDylib.h
new file mode 100644
index 0000000..7e019d6
--- /dev/null
+++ b/Runtime/Modules/LoadDylib.h
@@ -0,0 +1,13 @@
+#ifndef LOADDYLIB_H
+#define LOADDYLIB_H
+#include <string>
+
+std::string GetPathWithPlatformSpecificDllExtension(const std::string& path);
+void* LoadDynamicLibrary (const std::string& absolutePath);
+void* LoadAndLookupSymbol (const std::string& absolutePath, const std::string& name);
+void UnloadDynamicLibrary (void* libraryReference);
+void UnloadDynamicLibrary (const std::string& absolutePath);
+bool LoadAndLookupSymbols (const char* path, ...);
+void* LookupSymbol(void* libraryReference, const std::string& symbolName);
+
+#endif
diff --git a/Runtime/Modules/ModuleRegistration.cpp b/Runtime/Modules/ModuleRegistration.cpp
new file mode 100644
index 0000000..960ae96
--- /dev/null
+++ b/Runtime/Modules/ModuleRegistration.cpp
@@ -0,0 +1,93 @@
+#include "UnityPrefix.h"
+#include "ModuleRegistration.h"
+#include "LoadDylib.h"
+#include "RegisterStaticallyLinkedModules.h"
+#include "Runtime/Utilities/FileUtilities.h"
+#include "Runtime/Utilities/PathNameUtility.h"
+
+#if UNITY_WINRT
+#include "PlatformDependent/MetroPlayer/MetroUtils.h"
+#endif
+
+enum { kMaxModuleCount = 10 };
+
+static int gAvailableModuleCount = 0;
+static ModuleRegistrationInfo gModuleRegistrationInfos[kMaxModuleCount];
+
+void RegisterAllAvailableModuleClasses (ClassRegistrationContext& context)
+{
+ RegisterAvailableModules ();
+
+ for(int i=0;i<gAvailableModuleCount;i++)
+ {
+ if (gModuleRegistrationInfos[i].registerClassesCallback != NULL)
+ gModuleRegistrationInfos[i].registerClassesCallback (context);
+ }
+}
+
+void RegisterAllAvailableModuleICalls ()
+{
+ RegisterAvailableModules ();
+
+ for(int i=0;i<gAvailableModuleCount;i++)
+ {
+ if (gModuleRegistrationInfos[i].registerIcallsCallback != NULL)
+ gModuleRegistrationInfos[i].registerIcallsCallback ();
+ }
+}
+
+void RegisterModuleInfo(ModuleRegistrationInfo& info)
+{
+ gModuleRegistrationInfos[gAvailableModuleCount] = info;
+ gAvailableModuleCount++;
+
+ // Bump up kMaxModuleCount if we have too many modules.
+ Assert(gAvailableModuleCount < kMaxModuleCount);
+}
+
+#if !UNITY_WP8
+
+void RegisterModuleInDynamicLibrary (const char* dllName, const char* modulename)
+{
+ std::string dllFullName = dllName;
+#if WEBPLUG
+ ErrorString ("Dynamic module loading not implemented for web plug");
+#elif UNITY_OSX
+ dllFullName = AppendPathName (GetApplicationPath (), "Contents/Frameworks/MacStandalonePlayer_"+dllFullName+".dylib");
+#elif UNITY_WIN
+ dllFullName = "StandalonePlayer_"+dllFullName+".dll";
+#elif UNITY_LINUX
+ dllFullName += "LinuxStandalonePlayer_"+dllFullName+".so";
+#endif
+
+ std::string funcName("RegisterModule_");
+ funcName.append(modulename);
+ void (*registerModuleFunction)() = (void(*)())LoadAndLookupSymbol(dllFullName, funcName);
+ if (registerModuleFunction == NULL)
+ return;
+
+ registerModuleFunction();
+}
+
+#endif
+
+static void RegisterDynamicallyLinkedModules()
+{
+ //Work in progress:
+// RegisterModuleInDynamicLibrary("GfxDeviceModule_Dynamic","GfxDevice");
+// RegisterModuleInDynamicLibrary("TerrainModule_Dynamic","Terrain");
+// RegisterModuleInDynamicLibrary("NavMeshModule_Dynamic","Navigation");
+// RegisterModuleInDynamicLibrary("AnimationModule_Dynamic","Animation");
+// RegisterModuleInDynamicLibrary("Dynamics2DModule_Dynamic","Physics2D");
+// RegisterModuleInDynamicLibrary("PhysicsModule_Dynamic","Physics");
+// RegisterModuleInDynamicLibrary("PhysicsEditorModule_Dynamic","PhysicsEditor");
+}
+
+void RegisterAvailableModules ()
+{
+ if (gAvailableModuleCount != 0)
+ return;
+
+ RegisterStaticallyLinkedModules();
+ RegisterDynamicallyLinkedModules();
+}
diff --git a/Runtime/Modules/ModuleRegistration.h b/Runtime/Modules/ModuleRegistration.h
new file mode 100644
index 0000000..8493f79
--- /dev/null
+++ b/Runtime/Modules/ModuleRegistration.h
@@ -0,0 +1,21 @@
+#pragma once
+
+/// Modules are not guaranteed to exist. You must always check if the module getter function returns non-null.
+
+struct ClassRegistrationContext;
+
+
+void RegisterAllAvailableModuleClasses (ClassRegistrationContext& context);
+void RegisterAllAvailableModuleICalls ();
+void RegisterAvailableModules ();
+
+typedef void RegisterClassesCallback (ClassRegistrationContext& context);
+typedef void RegisterIcallsCallback ();
+
+struct ModuleRegistrationInfo
+{
+ RegisterClassesCallback* registerClassesCallback;
+ RegisterIcallsCallback* registerIcallsCallback;
+};
+
+EXPORT_COREMODULE void RegisterModuleInfo(ModuleRegistrationInfo& info); \ No newline at end of file
diff --git a/Runtime/Modules/RegisterStaticallyLinkedModules.cpp b/Runtime/Modules/RegisterStaticallyLinkedModules.cpp
new file mode 100644
index 0000000..8a1c284
--- /dev/null
+++ b/Runtime/Modules/RegisterStaticallyLinkedModules.cpp
@@ -0,0 +1,73 @@
+#include "UnityPrefix.h"
+
+extern "C" void RegisterModule_Navigation();
+extern "C" void RegisterModule_Physics2D();
+extern "C" void RegisterModule_Physics();
+extern "C" void RegisterModule_PhysicsEditor();
+extern "C" void RegisterModule_Terrain();
+extern "C" void RegisterModule_Audio();
+extern "C" void RegisterModule_Animation();
+extern "C" void RegisterModule_ClusterRenderer();
+
+//we diverge from our usual convention that all defines have to be set to either 0 or 1.
+//Jam will set the *_IS_DYNAMICALLY_LINKED defines on this single cpp file only, based on if
+//jam is planning to link a certain module statically or dynamically. by doing the define check
+//with ifndef like this, it avoids having to add all these defines to all targets that do not yet
+//support modularization. this method also creates support for having some modules statically linked
+//and some modules dynamically, which is incredibly helpful during development of the modularization
+
+void RegisterStaticallyLinkedModules()
+{
+#ifndef NAVMESH_IS_DYNAMICALLY_LINKED
+ #if !UNITY_WEBGL
+ RegisterModule_Navigation();
+ #endif
+#endif
+
+#ifndef ANIMATION_IS_DYNAMICALLY_LINKED
+ RegisterModule_Animation();
+#endif
+
+#ifndef PHYSICS_IS_DYNAMICALLY_LINKED
+ #if ENABLE_PHYSICS
+ RegisterModule_Physics();
+ #endif
+#endif
+
+#ifndef TERRAIN_IS_DYNAMICALLY_LINKED
+ #if ENABLE_TERRAIN
+ RegisterModule_Terrain();
+ #endif
+#endif
+
+#ifndef DYNAMICS2D_IS_DYNAMICALLY_LINKED
+ #if ENABLE_2D_PHYSICS
+ RegisterModule_Physics2D();
+ #endif
+#endif
+
+#ifndef AUDIO_IS_DYNAMICALLY_LINKED
+ #if ENABLE_AUDIO
+ RegisterModule_Audio();
+ #endif
+#endif
+
+#ifndef CLUSTER_SYNC_IS_DYNAMICALLY_LINKED
+ #if ENABLE_CLUSTER_SYNC
+ RegisterModule_ClusterRenderer();
+ #endif
+#endif
+
+#if UNITY_EDITOR
+#ifndef PHYSICSEDITOR_IS_DYNAMICALLY_LINKED
+ RegisterModule_PhysicsEditor();
+#endif
+#endif
+
+#if ENABLE_CLUSTER_SYNC
+#ifndef CLUSTERRENDERER_IS_DYNAMICALLY_LINKED
+ RegisterModule_ClusterRenderer();
+#endif
+#endif
+
+} \ No newline at end of file
diff --git a/Runtime/Modules/RegisterStaticallyLinkedModules.h b/Runtime/Modules/RegisterStaticallyLinkedModules.h
new file mode 100644
index 0000000..9445630
--- /dev/null
+++ b/Runtime/Modules/RegisterStaticallyLinkedModules.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void RegisterStaticallyLinkedModules();