Estoy intentando acceder a bases de datos SQLite desde LuaLaTeX pero no puedo cargar un lsqlite3
paquete instalado. Esto es lo que probé hasta ahora:
- Tomó una nueva instalación de Xubuntu 14.04
- Instalé un TeX Live 2014 completo
- Luarocks instalado (que instaló Lua5.1 en el camino)
Luarocks usados para instalar
lsqlite3
uwe@luabuntu:/media/uwe$ lista de luarocks
Rocas instaladas:
lsqlite3 0.9.1-2 (instalado) - /usr/local/lib/luarocks/rocks
Adjunto el
package.path
en el siguiente archivo TeX:\documentclass{article} \usepackage{luacode} \begin{document} \begin{luacode*} package.path="/usr/local/lib/luarocks/rocks;/usr/local/lib/luarocks/rocks/lsqlite3; /usr/local/lib/lua/5.1/lsqlite3.so" .. package.path require("lsqlite3") \end{luacode*} Hello Lua! \end{document}
El error que recibo es el siguiente:
! LuaTeX error [\directlua]:3: module 'lsqlite3' not found: no field package.preload['lsqlite3'] [luatexbase.loader] Search failed [kpse lua searcher] file not found: 'lsqlite3' [kpse C searcher] file not found: 'lsqlite3' [oberdiek.luatex.kpse_module_loader]-eroux Search failed stack traceback: [C]: in function 'require' [\directlua]:3: in main chunk. \luacode@dbg@exec ...code@maybe@printdbg {#1} #1 } l.9 \end{luacode*}
¿Qué se debe configurar para que LuaLaTeX encuentre el lsqlite3
paquete?
EDITAR
Intenté ajustar todo siguiendo los comentarios a continuación:
- Equilibrado
/usr/local/texlive/2014/texmf.cnf
- Pon todo en el ejemplo.
Aún aparece el error sobre el
lsqlite3
módulo que falta con el siguiente ejemplo\documentclass{article} \directlua{ require "lualoader" } \usepackage{fontspec} \usepackage[english]{babel} \begin{document} \directlua{package.path='/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/home/uwe/.luarocks/share/lua/5.1/?.lua;/home/uwe/.luarocks/share/lua/5.1/?/init.lua;/usr/share/lua/5.1//?.lua;/usr/share/lua/5.1//?/init.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua' package.cpath='/usr/local/lib/lua/5.1/?.so;/home/uwe/.luarocks/lib/lua/5.1/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/lib/x86_64-linux-gnu/lua/5.1/?.so;/usr/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so' require "lualoader" } \directlua{% local sqlite3 = require("lsqlite3") local db = sqlite3.open_memory() db:exec[[ CREATE TABLE test (id INTEGER PRIMARY KEY, content); INSERT INTO test VALUES (NULL, 'Hello World'); INSERT INTO test VALUES (NULL, 'Hello Lua'); INSERT INTO test VALUES (NULL, 'Hello Sqlite3') ]] for row in db:nrows("SELECT * FROM test") do tex.print(row.id .. " : ".. row.content ) end } \end{document}
Respuesta1
Es posible modificar el mecanismo de carga de paquetes en Lua
. En el caso de LuaTeX
, la kpse
biblioteca se usa para cargar módulos en lugar del mecanismo predeterminado que usa package.path
y package.cpath
. Por lo tanto, configurar estas variables no tendrá ningún efecto. Pero nada nos impide utilizar ambos métodos utilizando un Lua
módulo, lualoader.lua
. Guarde el fragmento a continuación como un archivo en el directorio que contiene su documento:
-- lualoader.lua
-- this is copied from luatexbase.loader
local make_loader = function(path, pos, loadfunc)
local default_loader = package.searchers[pos]
local loader = function(name)
local file, _ = package.searchpath(name,path)
if not file then
local msg = "\n\t[lualoader] Search failed"
local ret = default_loader(name)
if type(ret) == "string" then
return msg ..ret
elseif type(ret) == "nil" then
return msg
else
return ret
end
end
local loader,err = loadfunc(file, name)
if not loader then
return "\n\t[lualoader] Loading error:\n\t"..err
end
return loader
end
package.searchers[pos] = loader
end
local binary_loader = function(file, name)
local symbol = name:gsub("%.","_")
return package.loadlib(file, "luaopen_"..symbol)
end
make_loader(package.path,2,loadfile)
make_loader(package.cpath,3, binary_loader)
Usamos la función make_loader
para insertar una función de búsqueda package.path
o package.cpath
en un índice específico en la package.searchers
tabla. 2
para archivos lua, 3
para módulos binarios. También necesitamos usar diferentes funciones para cargar un módulo según su tipo. Usamos loadfile
para Lua
archivos y una función un poco más complicada para módulos binarios que usa package.loadlib
.
Como ejemplo, podemos intentar cargar lsqlite3
desde LuaTeX
:
\documentclass{article}
\directlua{
require "lualoader"
}
\usepackage{fontspec}
\usepackage[english]{babel}
\begin{document}
\directlua{%
local sqlite3 = require("lsqlite3")
local db = sqlite3.open_memory()
db:exec[[
CREATE TABLE test (id INTEGER PRIMARY KEY, content);
INSERT INTO test VALUES (NULL, 'Hello World');
INSERT INTO test VALUES (NULL, 'Hello Lua');
INSERT INTO test VALUES (NULL, 'Hello Sqlite3')
]]
for row in db:nrows("SELECT * FROM test") do
tex.print(row.id .. " : ".. row.content )
end
}
\end{document}
Es importante ejecutar LuaLaTeX con la --shell-escape
bandera, porque las bibliotecas binarias están bloqueadas de forma predeterminada. Con --shell-escape
él puedes ejecutar programas externos y llamar a bibliotecas binarias.
El ejemplo produce:
Editar:
ComouweComo se señaló, luarocks
tal como lo instalan algunos administradores de paquetes de Linux, es posible que no funcione correctamente. Experimenté esto en Fedora, así que lo instalé luarocks
desde la fuente. Otra solución puede ser configurar package.path
y package.cpath
acceder a los directorios enumerados por el comando
luarocks path
En mi propio sistema, esto produce:
$ luarocks path
export LUA_PATH='/home/michal/.luarocks/share/lua/5.2/?.lua;/home/michal/.luarocks/share/lua/5.2/?/init.lua;/usr/local/share/lua/5.2/?.lua;/usr/local/share/lua/5.2/?/init.lua;/usr/share/lua/5.2/?.lua;/usr/share/lua/5.2/?/init.lua;/usr/lib/lua/5.2/?.lua;/usr/lib/lua/5.2/?/init.lua;./?.lua'
export LUA_CPATH='/home/michal/.luarocks/lib/lua/5.2/?.so;/usr/local/lib/lua/5.2/?.so;/usr/lib/lua/5.2/?.so;/usr/lib/lua/5.2/loadall.so;./?.so'
Entonces un preámbulo modificado sería:
\directlua{
package.cpath = '/home/michal/.luarocks/lib/lua/5.2/?.so;/usr/local/lib/lua/5.2/?.so;/usr/lib/lua/5.2/?.so;/usr/lib/lua/5.2/loadall.so;./?.so'
package.path = '/home/michal/.luarocks/share/lua/5.2/?.lua;/home/michal/.luarocks/share/lua/5.2/?/init.lua;/usr/local/share/lua/5.2/?.lua;/usr/local/share/lua/5.2/?/init.lua;/usr/share/lua/5.2/?.lua;/usr/share/lua/5.2/?/init.lua;/usr/lib/lua/5.2/?.lua;/usr/lib/lua/5.2/?/init.lua;./?.lua'
require "lualoader"
}
Respuesta2
A partir de mayo de 2017, existe un paquete en CTAN llamadocargador de paquetes lua, que le permite modificar el comportamiento de búsqueda de paquetes predeterminado en LuaTeX.
Una vez que cargue luapackageloader
, require
primero probará el buscador predeterminado basado en kpse. Si no se encuentra el módulo, también intentará cargar el paquete desde los valores package.path
y de Lua package.cpath
.
Ejemplo de uso
\documentclass{article}
\usepackage{luacode}
\usepackage{luapackageloader}
\begin{document}
\begin{luacode*}
package.path="/usr/local/lib/luarocks/rocks;/usr/local/lib/luarocks/rocks/lsqlite3;
/usr/local/lib/lua/5.1/lsqlite3.so" .. package.path
require("lsqlite3")
\end{luacode*}
Hello Lua!
\end{document}
Nota adicional: puede hacerlo eval $(luarocks path)
en su shell para establecer la ruta del paquete utilizando variables de entorno que el intérprete de Lua recogerá automáticamente. De esa manera, no es necesario que juegues contigo package.path
mismo.
Respuesta3
Basado en comentarios sobreesta pregunta, tengo la siguiente línea en /usr/local/texlive/2014/texmf.cnf
:
CLUAINPUTS = .;$SELFAUTOLOC/lib/{$progname,$engine,}/lua//;/usr/lib/{$progname,$engine,}/lua//
Pero mi luarocks list
da:
Installed rocks:
lsqlite3
0.9.1-2 (installed) - /usr/lib/luarocks/rocks-5.2
por lo que es posible que deba ajustar la segunda ruta según su instalación.
Respuesta4
Resumen
Buscando el paquete
En Lua normal, se busca un paquete en
package.path
ypackage.cpath
.En LuaTeX, un paquete se busca de forma predeterminada con kpse.
Hay 2 formas de modificar dónde busca paquetes LuaTeX
modificar el comportamiento de kpse
Modificar
texmf.cnf
archivo, variablesLUAINPUTS
yCLUAINPUTS
.hacer que Lua se cargue desde
package.(c)path
, luego modificarlosCon
\usepackage{luapackageloader}
, los paquetes se buscan tanto en kpse como enpackage.(c)path
.El valor de
package.(c)path
puede ser establecido manualmente por el usuario dentro del propio código Lua, peroes mejor establecer variables de entornop.ejLUA_PATH
,LUA_CPATH
.Si ejecuta
eval $(luarocks path)
bash, todos los procesos generados desde ese shell bash heredarán las variables de entorno.
paquete binario
- Si el paquete lo requierearchivos binarios,
--shell-escape
debe aprobarse.
Versionado
La versión del paquetedebe ser compatible con la versión Lua. Hazlo
print(_VERSION)
dentro de Lua para comprobarlo.Para especificar una versión particular de luarocks, haga, por ejemplo
luarocks --lua-version 5.3 path
, .