Estou tentando acessar bancos de dados SQLite do LuaLaTeX, mas não consigo carregar um lsqlite3
pacote instalado. Aqui está o que tentei até agora:
- Foi necessária uma nova instalação do Xubuntu 14.04
- Instalou um TeX Live 2014 completo
- Instalado Luarocks (que instalou Lua5.1 no caminho)
Usei Luarocks para instalar
lsqlite3
uwe@luabuntu:/media/uwe$ luarocks list
Rochas instaladas:
lsqlite3 0.9.1-2 (instalado) - /usr/local/lib/luarocks/rocks
Anexado
package.path
no seguinte arquivo 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}
O erro que recebo é o seguinte:
! 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*}
O que deve ser configurado para que o LuaLaTeX encontre o lsqlite3
pacote?
EDITAR
Tentei ajustar tudo seguindo os comentários abaixo:
- Ajustado
/usr/local/texlive/2014/texmf.cnf
- Coloque tudo no exemplo
Ainda recebo o erro sobre o
lsqlite3
módulo ausente com o exemplo a seguir\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}
Responder1
É possível modificar o mecanismo de carregamento de pacotes no Lua
. No caso de LuaTeX
, a kpse
biblioteca é usada para carregar módulos em vez do mecanismo padrão que usa package.path
e package.cpath
. Portanto, definir essas variáveis não terá nenhum efeito. Mas nada nos impede de usar os dois métodos usando um Lua
módulo, lualoader.lua
. Salve o trecho abaixo como um arquivo no diretório que contém seu 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 a função make_loader
para inserir uma função pesquisando package.path
ou package.cpath
em um índice especificado na package.searchers
tabela. 2
para arquivos lua, 3
para módulos binários. Também precisamos usar funções diferentes para carregar um módulo dependendo do seu tipo. Usamos loadfile
para Lua
arquivos e funções um pouco mais complicadas para módulos binários que usam package.loadlib
.
Por exemplo, podemos tentar carregar lsqlite3
de 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}
É importante executar LuaLaTeX com a --shell-escape
flag, pois as bibliotecas binárias são bloqueadas por padrão. Com --shell-escape
você pode executar programas externos e chamar bibliotecas binárias.
O exemplo produz:
Editar:
ComoUweapontado, luarocks
conforme instalado por alguns gerenciadores de pacotes Linux pode não funcionar corretamente. Eu experimentei isso no Fedora, então instalei luarocks
a partir do código-fonte. Outra solução pode ser definir package.path
e package.cpath
para os diretórios listados pelo comando
luarocks path
No meu próprio sistema, isso produz:
$ 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'
Portanto, um preâmbulo modificado seria:
\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"
}
Responder2
Em maio de 2017, existe um pacote no CTAN chamadoluapackageloader, que permite modificar o comportamento padrão de busca de pacotes no LuaTeX.
Depois de carregar luapackageloader
, require
primeiro tentará o pesquisador padrão baseado em kpse. Se o módulo não for encontrado, ele também tentará carregar o pacote a partir dos valores package.path
and de Lua package.cpath
.
Exemplo 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: você pode fazer eval $(luarocks path)
em seu shell para definir o caminho do pacote usando variáveis de ambiente que o interpretador Lua irá capturar automaticamente. Dessa forma, você não precisa mexer consigo package.path
mesmo.
Responder3
Com base em comentários sobreessa questão, tenho a seguinte linha em /usr/local/texlive/2014/texmf.cnf
:
CLUAINPUTS = .;$SELFAUTOLOC/lib/{$progname,$engine,}/lua//;/usr/lib/{$progname,$engine,}/lua//
Mas minhas luarocks list
ofertas:
Installed rocks:
lsqlite3
0.9.1-2 (installed) - /usr/lib/luarocks/rocks-5.2
então você pode precisar ajustar o segundo caminho de acordo com sua instalação.
Responder4
Resumo
Procurando pelo pacote
Na Lua normal, um pacote é pesquisado em
package.path
epackage.cpath
.No LuaTeX, um pacote é pesquisado por padrão com kpse.
Existem 2 maneiras de modificar onde o LuaTeX procura por pacotes
modificar o comportamento do kpse
Modifique
texmf.cnf
arquivo, variáveisLUAINPUTS
eCLUAINPUTS
.faça Lua carregar de
package.(c)path
e modifique-osCom
\usepackage{luapackageloader}
, os pacotes são pesquisados em kpse epackage.(c)path
.O valor de
package.(c)path
pode ser definido manualmente pelo usuário dentro do próprio código Lua, masé melhor definir variáveis de ambientepor exemploLUA_PATH
,LUA_CPATH
.Se você executar
eval $(luarocks path)
no bash, todos os processos gerados nesse shell bash herdarão as variáveis de ambiente.
Pacote binário
- Se o pacote exigirarquivos binários,
--shell-escape
deve ser aprovado.
Versionamento
A versão do pacotedeve ser compatível com a versão Lua. Faça
print(_VERSION)
dentro de Lua para verificar.Para especificar uma versão específica para luarocks, faça, por exemplo
luarocks --lua-version 5.3 path
, .