使用bundledoc打包LaTeX宏包依赖
我遇到过由于宏包不够新导致的latex编译失败。那么有没有办法将我们编译当前文档需要的宏包打包呢?
办法就是使用bundledoc. 我用的texlive2017(脚本位置:E:\texlive\2016\texmf-dist\scripts\bundledoc\bundledoc), 看起来这个宏包有点旧了, 需要修复下。
脚本的修复
P.S. 最新版的bundledoc(2018/05/23, Version 3.3)一下两个问题都已经修复。请直接更新。
首先它是一个perl脚本, 其中有个新建临时目录的函数tmpnam已经弃用了, 这个好像不是非常影响。
# Create a bundled file.
my @dependencies = find_dependencies();
if ($keepdirs) {
# Put absolute pathnames in the tar file.
# QUESTIONS: Does this work with multiple drive letters in Windows?
# What about UNC names?
chdir rootdir() || die "${progname}: $! (".rootdir().")\n";
$ENV{"BDINPUTS"} = join (" ", map {s|^/+||; s/\"//g; "\"$_\""} @dependencies);
executecmd $uservariable{"bundle"};
}
else {
# Copy each of the dependencies to a temporary directory and tar it up.
my $tempdir = tmpnam();
my $tempdir2 = catfile $tempdir, $docdirname;
print "CREATING $tempdir\n" if $verbose;
mkdir ($tempdir, 0777) || die "${progname}: $! ($tempdir)\n";
print "CREATING $tempdir2\n" if $verbose;
mkdir ($tempdir2, 0777) || die "${progname}: $! ($tempdir2)\n";
foreach my $dep (@dependencies) {
# If the current dependency is in a subdirectory of the
# original location, create the same subdirectory in the
# temporary directory and copy the file there. Otherwise just
# copy it to the root of the temporary directory.
my $targetdir = $tempdir2;
if (my $sd = $subdirs{$dep}) {
$targetdir = catfile($targetdir, $sd);
unless (-d $targetdir) {
print "CREATING $targetdir\n" if $verbose;
mkpath($targetdir, 0, 0777) || die "${progname}: $! ($targetdir)\n";
}
}
copy ($dep, $targetdir) || die "${progname}: $! ($targetdir)\n";
}
if ($manifest ne "") {
my $manifest = catfile $tempdir2, $manifest;
my $manifestdir = dirname $manifest;
unless (-d $manifestdir) {
print "CREATING $manifestdir\n" if $verbose;
mkpath($manifestdir, 0, 0777) || die "${progname}: $! ($manifestdir)\n";
}
print "WRITING $manifest\n" if $verbose;
open (MANIFEST, ">$manifest") || die "${progname}: $! ($manifest)\n";
print MANIFEST join ("\n", @dependencies), "\n";
close MANIFEST;
}
chdir $tempdir || die "${progname}: $! ($tempdir)\n";
$ENV{"BDINPUTS"} = "\"$docdirname\"";
executecmd $uservariable{"bundle"};
# Clean up our mess.
# NOTE: We rmtree $tempdir2 and rmdir $tempdir because rmtree
# complained on WinNT when trying to remove a top-level
# directory (e.g., "\s4r.").
print "REMOVING $tempdir2\n" if $verbose;
rmtree $tempdir2, 0, 1;
chdir (updir());
print "REMOVING $tempdir\n" if $verbose;
rmdir $tempdir || die "${progname}: $! ($tempdir)\n";
}
print "FINISHED.\n" if $verbose;
exit 0;
其次, 它的正则表达式{([^\}]*)}不正确, 因为根据*.dep的结构, 我们需要将其改成\\{([^}]*)\\}.
# Find all dependencies listed in the input file.
sub find_dependencies ()
{
open (DEPFILE, "<$depfile") || die "${progname}: $! ($depfile)\n";
my $braced = "{([^\}]*)}"; # Regular expression for a braced name
my @dependencies; # List of fully-qualified filenames
@dependencies = qualifyname $texfile;
while (my $oneline=<DEPFILE>) {
# Parse an input line into its component fields.
next if !($oneline =~ /^\s*\*$braced\s*$braced\s*$braced\s*$/);
my $filetype = $1;
my $filename = $2;
my $versioninfo = $3;
# Extract the subdirectory if one exists.
my $subdir = dirname $filename;
my $qname = "";
如果我们只需要将2017年以后的宏包打包, 则可以将上述代码片段改为
# Find all dependencies listed in the input file.
sub find_dependencies ()
{
open (DEPFILE, "<$depfile") || die "${progname}: $! ($depfile)\n";
my $braced = "\\{([^}]*)\\}"; # Regular expression for a braced name
my @dependencies; # List of fully-qualified filenames
@dependencies = qualifyname $texfile;
while (my $oneline=<DEPFILE>) {
# Parse an input line into its component fields.
next if !($oneline =~ /^\s*\*$braced\s*$braced\s*\{((2017|2018)[^}]*)\}\s*$/);
my $filetype = $1;
my $filename = $2;
my $versioninfo = $3;
# Extract the subdirectory if one exists.
my $subdir = dirname $filename;
my $qname = "";
脚本的使用
新建test.tex文档如下:
\RequirePackage{snapshot}
\documentclass{amsart}
\begin{document}
Hello world!
\end{document}
这里的关键是需要第一行的\RequirePackage{snapshot}产生宏包依赖列表test.dep. 例如上面的代码产生的宏包依赖列表为:
\RequireVersions{
*{application}{TeX} {1990/03/25 v3.x}
*{format} {LaTeX2e} {2017-04-15 v2.e}
*{package}{snapshot} {2002/03/05 v1.14}
*{class} {amsart} {2017/10/31 v2.20.4}
*{package}{amsmath} {2017/09/02 v2.17a}
*{package}{amstext} {2000/06/29 v2.01}
*{package}{amsgen} {1999/11/30 v2.0}
*{package}{amsbsy} {1999/11/29 v1.2d}
*{package}{amsopn} {2016/03/08 v2.02}
*{file} {umsa.fd} {2013/01/14 v3.01}
*{package}{amsfonts} {2013/01/14 v3.01}
*{file} {umsa.fd} {2013/01/14 v3.01}
*{file} {umsb.fd} {2013/01/14 v3.01}
}
接着, 我们需要在test.tex同目录下创建bundledoc配置文件bundledoc.cfg
# basic config file for use of arlatex + bundledoc bundle: (arlatex --document=$BDBASE.tex $BDINPUTS | tar -cvf - $BDINPUTS | gzip --best > $BDBASE-all.tar.gz ) sink: > /dev/null 2>&1 find: kpsewhich -progname=latex $BDINPUTS
最后, 如果你使用修改后的脚本的话, 运行
bundledoc --config=bundledoc.cfg --verbose test.dep
则得到打包后的压缩文件test-all.tar.gz
需要注意的是, 我们需要压缩文件的软件tar与gzip.
本作品采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本站内容必须也遵循署名-非商业用途-保持一致的创作共用协议.

发表回复