Я пытаюсь получить доступ к базам данных SQLite из LuaLaTeX, но не могу загрузить установленный lsqlite3
пакет. Вот что я пробовал до сих пор:
- Произвел совершенно новую установку Xubuntu 14.04
- Установлен полный TeX Live 2014
- Установлен Luarocks (который по пути установил Lua5.1)
Использовал Luarocks для установки
lsqlite3
uwe@luabuntu:/media/uwe$ список luarocks
Установленные камни:
lsqlite3 0.9.1-2 (установлен) - /usr/local/lib/luarocks/rocks
Добавлен
package.path
в следующий 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}
Я получаю следующую ошибку:
! 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*}
Что необходимо настроить, чтобы LuaLaTeX нашел lsqlite3
пакет?
РЕДАКТИРОВАТЬ
Я постарался все отрегулировать, следуя комментариям ниже:
- Скорректировано
/usr/local/texlive/2014/texmf.cnf
- Поместите все в пример
Все еще получаю ошибку об отсутствующем
lsqlite3
модуле в следующем примере\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}
решение1
Можно изменить механизм загрузки пакетов в Lua
. В случае LuaTeX
библиотека kpse
используется для загрузки модулей вместо механизма по умолчанию, который использует package.path
и package.cpath
. Поэтому установка этих переменных не даст никакого эффекта. Но ничто не мешает нам использовать оба метода с помощью Lua
модуля lualoader.lua
. Сохраните фрагмент ниже как файл в каталоге, содержащем ваш документ:
-- 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)
Мы используем функцию make_loader
для вставки функции поиска package.path
или package.cpath
по указанному индексу в package.searchers
таблице. 2
для lua-файлов, 3
для бинарных модулей. Нам также нужно использовать разные функции для загрузки модуля в зависимости от его типа. Мы используем loadfile
для Lua
файлов и немного более сложную функцию для бинарных модулей, которая использует package.loadlib
.
В качестве примера можно попробовать выполнить загрузку lsqlite3
из 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}
Важно запускать LuaLaTeX с --shell-escape
флагом, так как бинарные библиотеки по умолчанию заблокированы. С помощью --shell-escape
можно запускать внешние программы и вызывать бинарные библиотеки.
Пример дает:
Редактировать:
КакУвеуказано, luarocks
что при установке некоторыми менеджерами пакетов Linux может работать некорректно. Я столкнулся с этим в Fedora, поэтому я установил luarocks
из исходников. Другим решением может быть установка package.path
и package.cpath
в каталоги, перечисленные командой
luarocks path
В моей системе это дает:
$ 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'
Таким образом, измененная преамбула будет выглядеть так:
\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"
}
решение2
По состоянию на май 2017 года на CTAN есть пакет под названиемluapackageloader, который позволяет изменить поведение поиска пакетов по умолчанию в LuaTeX.
После загрузки luapackageloader
, выполнение require
сначала попробует поисковик по умолчанию на основе kpse. Если модуль не найден, он также попытается загрузить пакет из значений Lua package.path
и .package.cpath
Пример использования
\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}
Дополнительное примечание: вы можете сделать eval $(luarocks path)
в своей оболочке, чтобы задать путь к пакету, используя переменные окружения, которые интерпретатор Lua подхватит автоматически. Таким образом, вам не нужно возиться с собой package.path
.
решение3
На основе комментариевэтот вопрос, у меня есть следующая строка /usr/local/texlive/2014/texmf.cnf
:
CLUAINPUTS = .;$SELFAUTOLOC/lib/{$progname,$engine,}/lua//;/usr/lib/{$progname,$engine,}/lua//
Но мой luarocks list
дает:
Installed rocks:
lsqlite3
0.9.1-2 (installed) - /usr/lib/luarocks/rocks-5.2
поэтому вам может потребоваться настроить второй путь в соответствии с вашей установкой.
решение4
Краткое содержание
Поиск пакета
В обычном Lua пакет ищется в
package.path
иpackage.cpath
.В LuaTeX поиск пакетов по умолчанию выполняется с помощью kpse.
Есть 2 способа изменить место, где LuaTeX ищет пакеты.
изменить поведение kpse
Измените
texmf.cnf
файл, переменныеLUAINPUTS
иCLUAINPUTS
.заставить Lua загрузиться из
package.(c)path
, затем изменить ихПри использовании
\usepackage{luapackageloader}
пакеты ищутся как в kpse, так и вpackage.(c)path
.Значение
package.(c)path
может быть установлено пользователем вручную в самом коде Lua, нолучше установить переменные окружениянапримерLUA_PATH
,LUA_CPATH
.Если вы работаете
eval $(luarocks path)
в bash, все процессы, порожденные этой оболочкой bash, унаследуют переменные среды.
Двоичный пакет
- Если пакет требуетдвоичные файлы,
--shell-escape
необходимо пройти.
Версионирование
Версия пакетадолжен быть совместим с версией Lua. Сделайте это
print(_VERSION)
в Lua для проверки.Чтобы указать конкретную версию luarocks, выполните, например
luarocks --lua-version 5.3 path
, .