diff --git a/crates/mun_libloader/Cargo.toml b/crates/mun_libloader/Cargo.toml new file mode 100644 index 000000000..f0c7880b4 --- /dev/null +++ b/crates/mun_libloader/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "mun_libloader" +version = "0.1.0" +authors = ["The Mun Team "] +edition = "2018" +description = "Functionality for loading Mun libraries" +documentation = "https://docs.mun-lang.org/v0.2" +readme = "README.md" +homepage = "https://mun-lang.org" +repository = "https://github.com/mun-lang/mun" +license = "MIT OR Apache-2.0" +keywords = ["game", "hot-reloading", "language", "mun", "scripting"] +categories = ["game-development", "mun"] + +[dependencies] +abi = { version = "=0.2.0", path = "../mun_abi", package = "mun_abi" } +anyhow = "1.0" +libloading = "0.6" +tempfile = "3" diff --git a/crates/mun_libloader/LICENSE-APACHE b/crates/mun_libloader/LICENSE-APACHE new file mode 100644 index 000000000..1cd601d0a --- /dev/null +++ b/crates/mun_libloader/LICENSE-APACHE @@ -0,0 +1 @@ +../../LICENSE-APACHE \ No newline at end of file diff --git a/crates/mun_libloader/LICENSE-MIT b/crates/mun_libloader/LICENSE-MIT new file mode 100644 index 000000000..b2cfbdc7b --- /dev/null +++ b/crates/mun_libloader/LICENSE-MIT @@ -0,0 +1 @@ +../../LICENSE-MIT \ No newline at end of file diff --git a/crates/mun_libloader/README.md b/crates/mun_libloader/README.md new file mode 100644 index 000000000..fe8400541 --- /dev/null +++ b/crates/mun_libloader/README.md @@ -0,0 +1 @@ +../../README.md \ No newline at end of file diff --git a/crates/mun_libloader/src/lib.rs b/crates/mun_libloader/src/lib.rs new file mode 100644 index 000000000..10cc8e6cc --- /dev/null +++ b/crates/mun_libloader/src/lib.rs @@ -0,0 +1,65 @@ +mod temp_library; + +use std::{ffi::c_void, path::Path}; + +pub use temp_library::TempLibrary; + +pub struct MunLibrary(TempLibrary); + +impl MunLibrary { + pub fn new(library_path: &Path) -> Result { + let library = TempLibrary::new(library_path)?; + + // Verify that the `*.munlib` contains all required functions + let _get_abi_version_fn: libloading::Symbol<'_, extern "C" fn() -> u32> = + unsafe { library.library().get(abi::GET_VERSION_FN_NAME.as_bytes()) }?; + + let _get_info_fn: libloading::Symbol<'_, extern "C" fn() -> abi::AssemblyInfo> = + unsafe { library.library().get(abi::GET_INFO_FN_NAME.as_bytes()) }?; + + let _set_allocator_handle_fn: libloading::Symbol<'_, extern "C" fn(*mut c_void)> = unsafe { + library + .library() + .get(abi::SET_ALLOCATOR_HANDLE_FN_NAME.as_bytes()) + }?; + + Ok(MunLibrary(library)) + } + + pub fn into_inner(self) -> TempLibrary { + self.0 + } + + pub fn get_abi_version(&self) -> u32 { + let get_abi_version_fn: libloading::Symbol<'_, extern "C" fn() -> u32> = unsafe { + self.0 + .library() + .get(abi::GET_VERSION_FN_NAME.as_bytes()) + .unwrap() + }; + + get_abi_version_fn() + } + + pub fn get_info(&self) -> abi::AssemblyInfo { + let get_info_fn: libloading::Symbol<'_, extern "C" fn() -> abi::AssemblyInfo> = unsafe { + self.0 + .library() + .get(abi::GET_INFO_FN_NAME.as_bytes()) + .unwrap() + }; + + get_info_fn() + } + + pub fn set_allocator_handle(&mut self, allocator_ptr: *mut c_void) { + let set_allocator_handle_fn: libloading::Symbol<'_, extern "C" fn(*mut c_void)> = unsafe { + self.0 + .library() + .get(abi::SET_ALLOCATOR_HANDLE_FN_NAME.as_bytes()) + .unwrap() + }; + + set_allocator_handle_fn(allocator_ptr); + } +} diff --git a/crates/mun_runtime/src/assembly/temp_library.rs b/crates/mun_libloader/src/temp_library.rs similarity index 100% rename from crates/mun_runtime/src/assembly/temp_library.rs rename to crates/mun_libloader/src/temp_library.rs diff --git a/crates/mun_runtime/Cargo.toml b/crates/mun_runtime/Cargo.toml index 88952083e..dfb40793d 100644 --- a/crates/mun_runtime/Cargo.toml +++ b/crates/mun_runtime/Cargo.toml @@ -14,21 +14,21 @@ categories = ["game-development", "mun"] [dependencies] abi = { version = "=0.2.0", path = "../mun_abi", package = "mun_abi" } -anyhow = "1.0.31" -libloading = "0.5" +anyhow = "1.0" +libloader = { version = "=0.1.0", path = "../mun_libloader", package = "mun_libloader" } md5 = "0.7.0" memory = { version = "=0.1.0", path = "../mun_memory", package = "mun_memory" } notify = "4.0.12" once_cell = "1.4.0" parking_lot = "0.10" -tempfile = "3" rustc-hash = "1.1" [dev-dependencies] -mun_compiler = { path="../mun_compiler" } +compiler = { path="../mun_compiler", package = "mun_compiler" } criterion = "0.3" -termcolor = "1.1" mlua = { package ="mlua", version="0.2", default-features = false, features=["vendored", "luajit"] } +tempfile = "3" +termcolor = "1.1" wasmer-runtime = "0.16" [[bench]] diff --git a/crates/mun_runtime/src/assembly.rs b/crates/mun_runtime/src/assembly.rs index a4bc1774b..3b9493d23 100644 --- a/crates/mun_runtime/src/assembly.rs +++ b/crates/mun_runtime/src/assembly.rs @@ -3,11 +3,8 @@ use std::path::{Path, PathBuf}; use crate::DispatchTable; use abi::AssemblyInfo; -use libloading::Symbol; +use libloader::{MunLibrary, TempLibrary}; -mod temp_library; - -use self::temp_library::TempLibrary; use crate::garbage_collector::{GarbageCollector, UnsafeTypeInfo}; use memory::mapping::{Mapping, MemoryMapper}; use std::{collections::HashSet, ptr::NonNull, sync::Arc}; @@ -29,22 +26,9 @@ impl Assembly { gc: Arc, runtime_dispatch_table: &DispatchTable, ) -> Result { - let library = TempLibrary::new(library_path)?; - - // Check whether the library has a symbols function - let get_info: Symbol<'_, extern "C" fn() -> AssemblyInfo> = - unsafe { library.library().get(abi::GET_INFO_FN_NAME.as_bytes()) }?; - - let get_version: Symbol<'_, extern "C" fn() -> u32> = - unsafe { library.library().get(abi::GET_VERSION_FN_NAME.as_bytes()) }?; - - let set_allocator_handle: Symbol<'_, extern "C" fn(*mut std::ffi::c_void)> = unsafe { - library - .library() - .get(abi::SET_ALLOCATOR_HANDLE_FN_NAME.as_bytes()) - }?; + let mut library = MunLibrary::new(library_path)?; - let version = get_version(); + let version = library.get_abi_version(); if abi::ABI_VERSION != version { return Err(anyhow::anyhow!( "ABI version mismatch. munlib is `{}` but runtime is `{}`", @@ -54,12 +38,12 @@ impl Assembly { } let allocator_ptr = Arc::into_raw(gc.clone()) as *mut std::ffi::c_void; - set_allocator_handle(allocator_ptr); + library.set_allocator_handle(allocator_ptr); - let info = get_info(); + let info = library.get_info(); let assembly = Assembly { library_path: library_path.to_path_buf(), - library, + library: library.into_inner(), legacy_libs: Vec::new(), info, allocator: gc, diff --git a/crates/mun_runtime/tests/util.rs b/crates/mun_runtime/tests/util.rs index 76ca0cb07..0a78c0a04 100644 --- a/crates/mun_runtime/tests/util.rs +++ b/crates/mun_runtime/tests/util.rs @@ -1,6 +1,6 @@ #![allow(dead_code, unused_macros)] -use mun_compiler::{Config, DisplayColor, Driver, FileId, PathOrInline, RelativePathBuf}; +use compiler::{Config, DisplayColor, Driver, FileId, PathOrInline, RelativePathBuf}; use mun_runtime::{IntoFunctionDefinition, Runtime, RuntimeBuilder}; use std::{ cell::{Ref, RefCell},