* Made findLaTeXIncludes pure. Previously find-includes.pl looked

outside of the Nix store for the dependencies of the root source
  file, which is impure.  That's why it needed the
  `builtins.currentTime' hack to force a rebuild.  It also didn't work
  in a chroot.  Now find-includes.pl only scans the source file at
  hand, and we use builtins.genericClosure to find all includes
  recursively.

svn path=/nixpkgs/trunk/; revision=16414
This commit is contained in:
Eelco Dolstra 2009-07-17 15:10:01 +00:00
parent 3451ae1a64
commit 04cc6b721a
3 changed files with 83 additions and 102 deletions

View File

@ -10,7 +10,6 @@ rec {
, extraFiles ? [] , extraFiles ? []
, compressBlanksInIndex ? true , compressBlanksInIndex ? true
, packages ? [] , packages ? []
, searchRelativeTo ? dirOf (toString rootFile) # !!! duplication
, copySources ? false , copySources ? false
}: }:
@ -25,31 +24,57 @@ rec {
inherit rootFile generatePDF generatePS extraFiles inherit rootFile generatePDF generatePS extraFiles
compressBlanksInIndex copySources; compressBlanksInIndex copySources;
includes = import (findLaTeXIncludes {inherit rootFile searchRelativeTo;}); includes = map (x: [x.key (baseNameOf (toString x.key))])
(findLaTeXIncludes {inherit rootFile;});
buildInputs = [ pkgs.tetex pkgs.perl ] ++ packages; buildInputs = [ pkgs.tetex pkgs.perl ] ++ packages;
}; };
# Returns the closure of the "dependencies" of a LaTeX source file.
# Dependencies are other LaTeX source files (e.g. included using
# \input{}), images (e.g. \includegraphics{}), bibliographies, and
# so on.
findLaTeXIncludes = findLaTeXIncludes =
{ rootFile { rootFile
, searchRelativeTo ? dirOf (toString rootFile)
}: }:
pkgs.stdenv.mkDerivation { builtins.genericClosure {
name = "latex-includes"; startSet = [{key = rootFile;}];
operator =
{key, ...}:
realBuilder = pkgs.perl + "/bin/perl"; let
args = [ ./find-includes.pl ];
rootFile = toString rootFile; # !!! hacky trace = x: builtins.trace x x;
inherit searchRelativeTo; # `find-includes.pl' returns the dependencies of the current
# source file (`key') as a list, e.g. [{type = "tex"; name =
# "introduction.tex";} {type = "img"; name = "example"}].
# The type denotes the kind of dependency, which determines
# what extensions we use to look for it.
deps = import (pkgs.runCommand "latex-includes"
{ src = trace key; }
"${pkgs.perl}/bin/perl ${./find-includes.pl}");
# Forces rebuilds. # Look for the dependencies of `key', trying various
hack = builtins.currentTime; # extensions determined by the type of each dependency.
# TODO: support a search path.
foundDeps = dep: xs:
let
exts =
if dep.type == "img" then [".pdf" ".png" ".ps" ".jpg"]
else if dep.type == "tex" then [".tex" ""]
else [""];
fn = pkgs.lib.findFirst (fn: builtins.pathExists fn) null
(map (ext: "${dirOf key}/${dep.name}${ext}") exts);
in if fn != null then [{key = fn;}] ++ xs
else builtins.trace "not found: ${dep.name}" xs;
in pkgs.lib.fold foundDeps [] deps;
}; };
dot2pdf = dot2pdf =
{ dotGraph { dotGraph
@ -158,7 +183,6 @@ rec {
inherit packages; inherit packages;
generatePDF = false; generatePDF = false;
generatePS = true; generatePS = true;
searchRelativeTo = dirOf (toString body);
}; };
}; };
@ -176,7 +200,6 @@ rec {
inherit body preamble; inherit body preamble;
}; };
inherit packages; inherit packages;
searchRelativeTo = dirOf (toString body);
}; };

View File

@ -1,102 +1,60 @@
use strict; use strict;
use File::Basename; use File::Basename;
my $root = $ENV{"rootFile"}; my $src = $ENV{"src"};
my $out = $ENV{"out"}; my $out = $ENV{"out"};
my $path = $ENV{"searchRelativeTo"}; my $path = $ENV{"searchRelativeTo"};
my $store = $ENV{"NIX_STORE"};
open OUT, ">$out" or die; open OUT, ">$out" or die;
print OUT "[\n"; print OUT "[\n";
my @workset = (); open FILE, "< $src" or die;
my %doneset = ();
sub addToWorkSetExts { sub addName {
my $base = shift; my ($type, $name) = @_;
foreach my $ext (@_) { print OUT "{ type = \"$type\"; name = \"$name\"; }\n";
push @workset, "$base$ext"; }
while (<FILE>) {
if (/\\input\{(.*)\}/) {
my $fn2 = $1;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "tex", "$fn2";
} elsif (/\\usepackage(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "misc", "$fn2.sty";
} elsif (/\\documentclass(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "misc", "$fn2.cls";
} elsif (/\\bibliographystyle\{(.*)\}/) {
my $fn2 = $1;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "misc", "$fn2.bst";
} elsif (/\\bibliography\{(.*)\}/) {
foreach my $bib (split /,/, $1) {
$bib =~ s/^\s+//; # remove leading / trailing whitespace
$bib =~ s/\s+$//;
addName "misc", "$bib.bib";
}
} elsif (/\\includegraphics(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "img", "$fn2";
} elsif (/\\pgfdeclareimage(\[.*\])?\{.*\}\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "img", "$fn2";
} elsif (/\\pgfimage(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "img", "$fn2";
} }
# !!! also support \usepackage
} }
push @workset, $root; close FILE;
while (scalar @workset > 0) {
my $fn = pop @workset;
next if (defined $doneset{$fn});
$doneset{$fn} = 1;
if (!-e "$fn") {
print STDERR "cannot access `$fn': $!\n" if !$!{ENOENT};
next;
}
next unless -e "$fn";
# Print out the full path *and* its relative path to $root.
if (substr($fn, 0, length $path) eq $path) {
my $relFN = substr($fn, (length $path) + 1);
print OUT "$fn \"$relFN\"\n";
} else {
my $base = basename $fn;
my $x = substr($fn, 0, length($store) + 1);
if (substr($fn, 0, length($store) + 1) eq "$store/") {
$base = substr($base, 33);
}
print OUT "$fn \"$base\"\n";
}
# If this is a TeX file, recursively find include in $fn.
next unless $fn =~ /.tex$/ or $fn =~ /.ltx$/;
open FILE, "< $fn" or die;
while (<FILE>) {
if (/\\input\{(.*)\}/) {
my $fn2 = $1;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
push @workset, "$path/$fn2.tex";
push @workset, "$path/$fn2";
} elsif (/\\usepackage(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
push @workset, "$path/$fn2.sty";
} elsif (/\\documentclass(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
push @workset, "$path/$fn2.cls";
} elsif (/\\bibliographystyle\{(.*)\}/) {
my $fn2 = $1;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
push @workset, "$path/$fn2.bst";
} elsif (/\\bibliography\{(.*)\}/) {
foreach my $bib (split /,/, $1) {
$bib =~ s/^\s+//; # remove leading / trailing whitespace
$bib =~ s/\s+$//;
push @workset, "$path/$bib.bib";
}
} elsif (/\\includegraphics(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addToWorkSetExts("$path/$fn2", ".pdf", ".png", ".ps", ".jpg");
} elsif (/\\pgfdeclareimage(\[.*\])?\{.*\}\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addToWorkSetExts("$path/$fn2", ".pdf", ".png", ".jpg");
} elsif (/\\pgfimage(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addToWorkSetExts("$path/$fn2", ".pdf", ".png", ".jpg");
}
# !!! also support \usepackage
}
close FILE;
}
print OUT "]\n"; print OUT "]\n";
close OUT; close OUT;

View File

@ -7851,7 +7851,7 @@ let
}; };
texFunctions = import ../misc/tex/nix { texFunctions = import ../misc/tex/nix {
inherit stdenv perl tetex graphviz ghostscript makeFontsConf imagemagick; inherit stdenv perl tetex graphviz ghostscript makeFontsConf imagemagick runCommand lib;
}; };
texLive = builderDefsPackage (import ../misc/tex/texlive) { texLive = builderDefsPackage (import ../misc/tex/texlive) {