嵌入仅限 Perl 的模块以及嵌入式 Perl 解释器

2023-12-15

我跟着https://perldoc.perl.org/perlembed并成功建立了interp二进制。当我使用static_ext,输出目录有*.pm文件安装到前缀目录中。

如何添加自定义简单*.pm模块如TLUtils.pm无需将模块文件解压到临时目录中?基本上,作为一个例子,我想嵌入https://github.com/TeX-Live/texlive-source/blob/trunk/texk/texlive/linked_scripts/texlive/fmtutil.pl and https://github.com/TeX-Live/texlive-source/blob/trunk/texk/texlive/linked_scripts/texlive/updmap.pl取决于 TLUtils。更复杂的目标可能是包装biber不使用 PAR。

我可以以某种方式将此模块导入到给定的解释器中吗*.pm的源代码?

在虚拟文件系统方面,是否有人有滚动原始只读虚拟文件系统的示例(例如通过覆盖lstat, open, read)用于从内存导入包?

我意识到 PAR 解决了这个问题,但我想知道是否有一些简单的拐杖可以让我在不依赖 PAR 的情况下使用。

谢谢你!

UPD:

mkdir -p source build/native/perl
wget -nc https://www.cpan.org/src/5.0/perl-5.30.0.tar.gz -P source
tar -xf source/*.tar.gz --strip-components=1 --directory=build/native/perl
cd build/native/perl
bash ./Configure -sde -Dprefix=$PWD/../prefix -Aldflags=-lm -Accflags=-lm -Dstatic_ext="IO Fcntl"
make miniperl generate_uudmap
make perl
make install

../prefix/bin/perl5.30.0 -e 'print 123; use Fcntl; print 456;'
# prints 123456

../prefix/bin/perl5.30.0 -MExtUtils::Embed -e ccopts -e ldopts
# -Wl,-E  -lm -fstack-protector-strong -L/usr/local/lib /home/runner/work/buildbiber/buildbiber/build/native/perl/../prefix/lib/5.30.0/x86_64-linux/auto/Fcntl/Fcntl.a /home/runner/work/buildbiber/buildbiber/build/native/perl/../prefix/lib/5.30.0/x86_64-linux/auto/IO/IO.a -L/home/runner/work/buildbiber/buildbiber/build/native/perl/../prefix/lib/5.30.0/x86_64-linux/CORE -lperl -lpthread -lnsl -ldl -lm -lcrypt -lutil -lc           -lm -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64  -I/home/runner/work/buildbiber/buildbiber/build/native/perl/../prefix/lib/5.30.0/x86_64-linux/CORE

cc -o emperl ../../../emperl.c `../prefix/bin/perl5.30.0 -MExtUtils::Embed -e ccopts -e ldopts`
./emperl -e 'print 123; use Fcntl; print 456;'
# prints Can't load module Fcntl, dynamic loading not available in this perl.
#  (You may need to build a new perl executable which either supports
#  dynamic loading or has the Fcntl module statically linked into it.)
# at -e line 1.
# Compilation failed in require at -e line 1.

# This is an extremely strange error because Fcntl is indeed built and linked statically as evidenced by the linking flags above

echo '{' > fmtutil_.pl
curl https://raw.githubusercontent.com/TeX-Live/installer/master/tlpkg/TeXLive/TLUtils.pm >> fmtutil_.pl
echo '}' >> fmtutil_.pl
curl https://raw.githubusercontent.com/TeX-Live/texlive-source/trunk/texk/texlive/linked_scripts/texlive/fmtutil.pl >> fmtutil_.pl

./emperl fmtutil_.pl --help
# also fails with Fcntl problem

第一期:

无法加载模块 Fcntl,动态加载在此 perl 中不可用。

根据佩伦贝德您需要将一些 XS 粘合代码插入到嵌入式解释器中emperl.c:

#include <EXTERN.h>               /* from the Perl distribution     */
#include <perl.h>                 /* from the Perl distribution     */
static PerlInterpreter *my_perl;  /***    The Perl interpreter    ***/
EXTERN_C void xs_init (pTHX);

int main(int argc, char **argv, char **env)
{
       PERL_SYS_INIT3(&argc,&argv,&env);
       my_perl = perl_alloc();
       perl_construct(my_perl);
       PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
       perl_parse(my_perl, xs_init, argc, argv, (char **)NULL);
       perl_run(my_perl);
       perl_destruct(my_perl);
       perl_free(my_perl);
       PERL_SYS_TERM();
       exit(EXIT_SUCCESS);
}

注意perl_parse()现在运行时带有一个指向xs_init子例程作为第二个参数。这xs_init()可以生成函数并编译成emperl使用这些命令进行二进制:

PERL=build/native/prefix/bin/perl5.34.0
$PERL -MExtUtils::Embed -e xsinit -- -o perlxsi.c
cc -c perlxsi.c `$PERL -MExtUtils::Embed -e ccopts`
cc -c emperl.c `$PERL -MExtUtils::Embed -e ccopts`
cc -o emperl perlxsi.o emperl.o `$PERL -MExtUtils::Embed -e ldopts`

如果我现在像您一样测试嵌入式二进制文件,它似乎工作正常:

$ ./emperl -e 'print 123; use Fcntl; print 456;'
123456

第二期:

如何添加自定义简单*.pm模块如TLUtils.pm无需将模块文件解压到临时目录中?

根据INSTALL文档:

如果您解压任何其他扩展ext/运行前的目录Configure, then Configure也将提供构建这些额外的扩展。

我用一个简单的 XS 模块尝试了这个Sort::Key像这样(这里我使用Configure option -Uusedl强迫perl完全静态编译):

mkdir -p source build/native/perl
wget -nc https://www.cpan.org/src/5.0/perl-5.34.0.tar.gz -P source
tar -xf source/*.tar.gz --strip-components=1 --directory=build/native/perl
cd build/native/perl
cd ext
wget https://cpan.metacpan.org/authors/id/S/SA/SALVA/Sort-Key-1.33.tar.gz
mkdir -p Sort-Key
tar -xf Sort-Key-1.33.tar.gz --strip-components=1 --directory=Sort-Key
cd ..
sh ./Configure -sde -Dman1dir=none -Dman3dir=none -Dprefix=$PWD/../prefix -Uusedl
make
make install

然后嵌入这个perl使用emperl.c代码如前:

PERL=build/native/prefix/bin/perl5.34.0
$PERL -MExtUtils::Embed -e xsinit -- -o perlxsi.c
# Note: for some reason you need to comment out the two lines with 
#   Devel::PPPort from perlxsi.c in order to compile it..
perl -i -ne 'print if !/PPPort/' perlxsi.c
cc -c perlxsi.c `$PERL -MExtUtils::Embed -e ccopts`
cc -c emperl.c `$PERL -MExtUtils::Embed -e ccopts`
cc -o emperl perlxsi.o emperl.o `$PERL -MExtUtils::Embed -e ldopts`

然后用以下命令测试了嵌入式解释器Sort::Key module:

$ ./emperl -e 'print 123; use Sort::Key; print 456'
123456
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入仅限 Perl 的模块以及嵌入式 Perl 解释器 的相关文章

随机推荐