Skip to content

Commit

Permalink
feat(rusile): Enable embedding of Rusile module
Browse files Browse the repository at this point in the history
  • Loading branch information
alerque committed Nov 2, 2024
1 parent 19d68bc commit 693d7d4
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 54 deletions.
13 changes: 2 additions & 11 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,7 @@ nodist_man_MANS =
dist_man_MANS = sile-lua.1
sile_SOURCES = src/bin/sile.rs src/lib.rs src/cli.rs src/types.rs src/types/semver.rs
EXTRA_sile_SOURCES =
if EMBEDDED_RESOURCES
noinst_LIBRARIES = librusile.a
librusile_a_SOURCES = $(RUSILE_SOURCES)
else !EMBEDDED_RESOURCES
if !EMBEDDED_RESOURCES
nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES)
nobase_nodist_pkgdata_DATA = $(BUILT_SOURCES_LUA) $(LUAMODULES)
pkglib_LIBRARIES = rusile.so
Expand Down Expand Up @@ -128,9 +125,7 @@ $(CARGO_BIN): justenough/.libs/justenoughicu.a
$(CARGO_BIN): justenough/.libs/justenoughlibtexpdf.a
$(CARGO_BIN): justenough/.libs/svg.a
$(CARGO_BIN): libtexpdf/.libs/libtexpdf.a
if EMBEDDED_RESOURCES
$(CARGO_BIN): librusile.a
else !EMBEDDED_RESOURCES
if !EMBEDDED_RESOURCES
$(CARGO_BIN): rusile.so
endif !EMBEDDED_RESOURCES

Expand Down Expand Up @@ -176,10 +171,6 @@ rusile.so: $(rusile_so_SOURCES) $(bin_PROGRAMS)
$(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(RUSILE_FEATURE_ARG) $(CARGO_RELEASE_ARGS) -p rusile
$(INSTALL) @builddir@/target/@RUST_TARGET_SUBDIR@/lib$@ $@

librusile.a:
$(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(RUSILE_FEATURE_ARG) $(CARGO_RELEASE_ARGS) -p rusile
$(INSTALL) @builddir@/target/@RUST_TARGET_SUBDIR@/$@ $@

DEPDIR := .deps
LOCALFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf
LOCALPATHS := SILE_PATH="$(PWD);libtexpdf/.libs;justenough/.libs"
Expand Down
8 changes: 0 additions & 8 deletions build-aux/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,6 @@ fn main() {
generate_shell_completions();
#[cfg(feature = "static")]
{
////let dir = env::var("CARGO_TARGET_DIR").unwrap();
//let dir = env::var("CARGO_MANIFEST_DIR").unwrap();
//println!(
// "cargo:rustc-link-search=native={}",
// Path::new(&dir).join("target").join("release").display()
//);
//println!("cargo:rustc-link-arg=-l:librusile.a");

let dir = env::var("CARGO_MANIFEST_DIR").unwrap();
println!(
"cargo:rustc-link-search=native={}",
Expand Down
2 changes: 1 addition & 1 deletion core/sile.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ SILE = {}
--- Load the C module that provides any and all SILE features implemented in Rust. The exports in this module are meant
--- to be moved to approprate places in the Lua API as we load other things and assemble the public facing interface.
--- This location is considered internal and accessing them directly from here is not supported.
-- @table SILE.rusile
-- @table SILE._rusile
SILE._rusile = require("rusile")

--- Machine friendly short-form version.
Expand Down
7 changes: 4 additions & 3 deletions rusile/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Thin wrapper around user facing functions implemented in Rust to expose them in a loadable Lua
// module separate from the Rust CLI.

#![crate_type = "cdylib"]
#![crate_type = "rlib"]
#![crate_type = "staticlib"]
Expand All @@ -6,7 +9,5 @@ use mlua::prelude::*;

#[mlua::lua_module]
fn rusile(lua: &Lua) -> LuaResult<LuaTable> {
let exports = lua.create_table()?;
exports.set("semver", LuaFunction::wrap_raw(sile::types::semver::semver))?;
Ok(exports)
sile::get_rusile_exports(lua)
}
67 changes: 37 additions & 30 deletions src/embed.rs.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use mlua::chunk;
use mlua::prelude::*;
use rust_embed::{EmbeddedFile, RustEmbed};
use std::str;
//use rusile::rusile;

/// Embed everything that would otherwise be installed to datadir
#[derive(RustEmbed)]
Expand Down Expand Up @@ -46,7 +45,6 @@ pub struct SileModules;
// Link Lua loader functions from C modules that Lua would otherwise be loading externally that
// we've linked into the CLI binary. Linking happens in build-aux/build.rs.
extern "C-unwind" {
//fn luaopen_rusile(lua: *mut mlua::lua_State) -> i32;
fn luaopen_fontmetrics(lua: *mut mlua::lua_State) -> i32;
fn luaopen_justenoughfontconfig(lua: *mut mlua::lua_State) -> i32;
fn luaopen_justenoughharfbuzz(lua: *mut mlua::lua_State) -> i32;
Expand All @@ -58,18 +56,27 @@ extern "C-unwind" {
/// Register a Lua function in the loaders/searchers table to return C modules linked into the CLI
/// binary and another to return embedded Lua resources as Lua modules. See discussion in mlua:
/// https://github.com/khvzak/mlua/discussions/322
pub fn inject_embedded_loader(lua: &Lua) {
pub fn inject_embedded_loaders(lua: &Lua) {
let package: LuaTable = lua.globals().get("package").unwrap();
let loaders: LuaTable = match package.get("loaders").unwrap() {
LuaValue::Table(loaders) => loaders,
LuaValue::Nil => package.get("searchers").unwrap(),
_ => panic!("Unable to find appropriate interface to inject embedded loader"),
};
let embedded_ffi_loader = lua.create_function(|lua, module: String| unsafe {

let embedded_rusile_loader = lua
.create_function(|lua, module: String| match module.as_str() {
"rusile" => lua
.create_function(move |lua, _: ()| crate::get_rusile_exports(lua))
.map(LuaValue::Function),
_ => format!("Module '{module}' is embeded in Rust binary").into_lua(lua),
})
.unwrap();
loaders.push(embedded_rusile_loader).unwrap();

let embedded_ffi_loader = lua
.create_function(|lua, module: String| unsafe {
match module.as_str() {
//"rusile" => lua
// .create_c_function(luaopen_rusile)
// .map(LuaValue::Function),
"fontmetrics" => lua
.create_c_function(luaopen_fontmetrics)
.map(LuaValue::Function),
Expand All @@ -88,12 +95,12 @@ pub fn inject_embedded_loader(lua: &Lua) {
"svg" => lua.create_c_function(luaopen_svg).map(LuaValue::Function),
_ => format!("C Module '{module}' is not linked in Rust binary").into_lua(lua),
}
}).unwrap();
loaders
.push(embedded_ffi_loader)
})
.unwrap();
loaders.push(embedded_ffi_loader).unwrap();

let embedded_lua_loader = lua.create_function(|lua, module: String| {
let embedded_lua_loader = lua
.create_function(|lua, module: String| {
let module_path = module.replace('.', "/");
let luaversion: LuaString = lua
.load(chunk! {
Expand Down Expand Up @@ -121,40 +128,40 @@ pub fn inject_embedded_loader(lua: &Lua) {
}
}
match resource_option {
Some(module) => {
lua.create_function(move |lua, _: ()| {
Some(module) => lua
.create_function(move |lua, _: ()| {
let data = str::from_utf8(module.data.as_ref())
.expect("Embedded content is not valid UTF-8");
lua.load(data).call::<LuaValue>(())
}).map(LuaValue::Function)
},
})
.map(LuaValue::Function),

None => format!("Module '{module}' is not embedded in Rust binary").into_lua(lua),
}
}).unwrap();
loaders
.push(embedded_lua_loader)
})
.unwrap();
loaders.push(embedded_lua_loader).unwrap();

let embedded_ftl_loader = lua.create_function(|lua, module: String| {
let embedded_ftl_loader = lua
.create_function(|lua, module: String| {
let module_path = module.replace('.', "/");
let pattern = "?.ftl";
let path = pattern.replace('?', &module_path);
match SileModules::get(&path) {
Some(module) => lua.create_function(move |lua, _: ()| {
let data = str::from_utf8(module.data.as_ref())
.expect("Embedded content is not valid UTF-8");
lua.load(chunk! {
return assert(fluent:add_messages($data))
Some(module) => lua
.create_function(move |lua, _: ()| {
let data = str::from_utf8(module.data.as_ref())
.expect("Embedded content is not valid UTF-8");
lua.load(chunk! {
return assert(fluent:add_messages($data))
})
.call::<LuaValue>(())
})
.call::<LuaValue>(())
}).map(LuaValue::Function),
.map(LuaValue::Function),
_ => format!("FTL resource '{module_path}' is not embedded in Rust binary")
.into_lua(lua),
}
}).unwrap();
loaders
.push(embedded_ftl_loader)
})
.unwrap();

loaders.push(embedded_ftl_loader).unwrap();
}
9 changes: 8 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// rust-embed include attributes have issues with lots of matches...
#![recursion_limit = "2048"]

#[cfg(not(feature = "static"))]
use mlua::chunk;
use mlua::prelude::*;
#[cfg(not(feature = "static"))]
Expand All @@ -19,7 +20,7 @@ pub type Result<T> = anyhow::Result<T>;
pub fn start_luavm() -> crate::Result<Lua> {
let lua = unsafe { Lua::unsafe_new() };
#[cfg(feature = "static")]
crate::embed::inject_embedded_loader(&lua);
crate::embed::inject_embedded_loaders(&lua);
inject_paths(&lua);
load_sile(&lua);
inject_version(&lua);
Expand Down Expand Up @@ -56,6 +57,12 @@ pub fn inject_paths(lua: &Lua) {
}
}

pub fn get_rusile_exports(lua: &Lua) -> LuaResult<LuaTable> {
let exports = lua.create_table()?;
exports.set("semver", LuaFunction::wrap_raw(types::semver::semver))?;
Ok(exports)
}

pub fn inject_version(lua: &Lua) {
let sile: LuaTable = lua.globals().get("SILE").unwrap();
let mut full_version: String = sile.get("full_version").unwrap();
Expand Down

0 comments on commit 693d7d4

Please sign in to comment.