mlua-rs / mlua

High level Lua 5.4/5.3/5.2/5.1 (including LuaJIT) and Roblox Luau bindings to Rust with async/await support
Other
1.76k stars 139 forks source link

Require LuaRocks packages fail on execution #452

Closed ASoldo closed 2 months ago

ASoldo commented 2 months ago

Hi, when I use require with packages that are installed with LuaRocks execution fails. Note that all local require statements here are lua scripts that act as plugins and were written by me.

local hook_plugin = require("hook_plugin")
local print_me_plugin = require("print_me_plugin")
local state_plugin = require("state_plugin")
local pwd_plugin = require("pwd_plugin")
local stages_plugin = require("stages_plugin")
local env_plugin = require("env_plugin")
require("lyaml") -- <---------------------------------------------- THIS ONE

But last one fails... Is this possible or disabled by design?

alerque commented 2 months ago

It should work fine, but you probably have to set the package.path and/or package.cpath for your system. The Lua VIM in mlua won't naturally just have the same environment your system Lua knows about it terms of where to look for stuff.

ASoldo commented 2 months ago

this is how I do it so far, i have clap to set --plugin-dir for my scripts that I require and it loads perfectly. but as soon as I try to use any LuaRocks module I get error when it tries to load.

fn load_lua_pipeline(file_path: &str, plugin_dir: Option<&str>) -> Result<(), Error> {
    let lua = Lua::new();

    if let Some(plugin_dir) = plugin_dir {
        let globals = lua.globals();
        let package: mlua::Table = globals.get("package")?;

        // Update package.path
        let current_path: String = package.get("path")?;
        package.set(
            "path",
            format!(
                "{}/?.lua;/usr/share/lua/5.4/?.lua;{}",
                plugin_dir, current_path
            ),
        )?;

        // Update package.cpath
        let current_cpath: String = package.get("cpath")?;

        package.set(
            "cpath",
            format!(
                "{}/?.so;/usr/lib/lua/5.4/?.so;{}",
                plugin_dir, current_cpath
            ),
        )?;
    }

    let lua_script = read_to_string(file_path).expect("Unable to read Lua file");

    lua.load(&lua_script).exec()?;

    Ok(())
}

This is the project and I wanna make simple lua pipeline runner but so far it only works with standard library. Any feedback would be much appreciated. https://github.com/ASoldo/notjen/blob/main/src/main.rs

alerque commented 2 months ago

Your paths don't include all the standard paths LuaRocks might install to. In this case lymal installs to {lua_prefix}/lyaml/init.lua, not {lua_prefix}/lyaml.lua. Your path only searches the latter pattern. Compare with the system default lua path to see all the common iterations of paths you need to look for, e.g. lua -e 'print(package.path)'. You'll see there are patterns in there to find the {lua_prefix}/?/init.lua and similar.

khvzak commented 2 months ago

let lua = Lua::new(); cannot load dynamic modules and does not has C loaders enabled. You need to use let lua = unsafe { Lua::unsafe_new() };

Btw, what error you got? Is it a C module?

ASoldo commented 2 months ago

From what I've tested so far (will do it more) it works with this @khvzak, thank you! :

let lua = unsafe { Lua::unsafe_new() };

If there are any new issue I will update it here.

just a question: now that I use unsafe_new() do i have portability like before or do i need to watch out for some things now?

khvzak commented 2 months ago

now that I use unsafe_new() do i have portability like before or do i need to watch out for some things now?

This option makes Lua environment similar to the vanilla one, all restrictions are lifted. So you should have more portability than before

alerque commented 2 months ago

How did changing to unsafe help this problem? I did a quick check on that before answering this and it just had lua files, hence my answer about it's init path. Does it had a transient dependency on LPEG or something?

khvzak commented 2 months ago

lyaml is bindings to LibYAML, not just lua files.

See https://github.com/gvvaughan/lyaml/tree/master/ext/yaml for the C interface/module

alerque commented 2 months ago

Oh buggers, I see. It installs a bunch of Lua scripts in a lyaml namespace, but the C module is built with a custom command backend and installed to a different namespace. The C module is called just yaml and under a different directory, hence why I didn't see it when looking what files it installed in my rocks tree by grepping for "lyaml".