Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm using latex on a small netbook, and with average-sized files (~150 pages at the moment) compilation is already pretty slow. So I am looking for every way to speed up the compilation.

In this search, I found this page explaining how to "precompile a preamble", or, latexically-speaking, how to make a custom format file. That works fine enough.

But my preamble isn't as static as it should be, I keep adding or modifying definitions in there. To mix the two solutions, at the moment, I use a Makefile together with latexmk, the makefile handling the regeneration of the .fmt file if needed, and latexmk taking good care of the rest.

But I have two problems with this :

  • integration with emacs to compile the whole document when working on a single file (make needs to be called in the proper directory)
  • latexmk doesn't recompile the file every time the preamble is modified, because it doesn't count as a dependency.

So I'd like to find a way to get rid of this Makefile, and get all the stuff done by latexmk.

I edited my .latexmkrc to include this :

pdflatex = 'pdflatex -fmt main %O %S';

add_input_ext('pdflatex','fmt');

add_cus_dep('tex', 'fmt', 1, 'compilepreamble');
sub compilepreamble {
    print "Preamble compiling...\n";
    $command = '&.pdflatex ./fmt/preamble.tex\dump';
    system("pdflatex -ini -jobname='$_[0]' '$command'");
};   

But with this, if the file main.fmt is not present or if fmt/preamble.tex is updated, the main.fmt file won't be regenerated. Actually, in the first case, I get an error from pdflatex saying the it can't find main.fmt format file. So I understand latexmk doesn't even try to build main.fmt, it's probably not a problem in my custom dependency. However, I think I've added everything necessary for this to work.

So... Did I forget something? Is there a way round? Or is it a hopeless quest?

share|improve this question
add comment

1 Answer 1

up vote 9 down vote accepted

What you forgot is that a custom dependency is intended to have input and output files that differ only in their extensions, e.g., to convert foo.ltx to foo.fmt. But they don't work to convert, for example, fmt/preamble.tex to main.fmt. A second, but less severe, problem is that when pdfLaTeX doesn't find the .fmt file, it dies with an error message to the screen, but it doesn't put the error message in the log file (so that latexmk doesn't detect that there is a missing file).

If you rename your preamble file to main.ltx (not in a subdirectory), then the following initialization code should work:

$recorder = 1;
$pdflatex = 'pdflatex -fmt main %O %S';
add_input_ext('pdflatex','fmt');
add_cus_dep('ltx', 'fmt', 1, 'compilepreamble');
sub compilepreamble {
    print "Preamble compiling for '$_[0]'...\n";
    my $fls_file = "$_[0].fls";
    my $source = "$_[0].ltx";
    my $fmt_file = "$_[0].fmt";
    my $return = system( "pdflatex", "-interaction=batchmode",
                         "-ini", "-recorder", "-jobname=$_[0]",
                         "&pdflatex $source \\dump" );
    if ($return) { 
        warn "Error in making format file '$fmt_file'\n";
       return $return;
    }
    my %input_files = ();
    my %output_files = ();
    $return = parse_fls( $fls_file, \%input_files, \%output_files );
    if ($return) {
        warn "No fls file '$fls_file' made; I cannot get dependency data\n";
        return 0; 
    }
    # Use latexmk's internal variables and subroutines for setting the
    #   dependency information.
    # Note that when this subroutine is called to implement a custom
    #   dependency, the following variables are set:
    #       $rule  contains the name of the current rule (as in the
    #              fdb_latexmk file)
    #       $PHsource is a pointer to a hash of source file
    #              information for the rule.  The keys of the hash are
    #              the names of the source files of the rule.
    foreach my $file (keys %input_files) {
        rdb_ensure_file( $rule, $file );
    }
    foreach my $file (keys %$PHsource) {
        if ( ! exists $input_files{$file} ) {
            print "   Source file of previous run '$file' ",
                  "IS NO LONGER IN USE\n";
            rdb_remove_files( $rule, $file );
        }
    }
    return 0;
};

I've used an extension .ltx rather than .tex so that you can have a preamble file with the same basename as the main file.

You'll need to run the pdflatex -ini ... manually the first time, to create the .fmt file. After that latexmk should handle things automatically.

Edit (2 April 2012): I improved the code so that it detects dependencies on files used by pdflatex -ini. This uses some of the internal variables and subroutines of latexmk.

share|improve this answer
    
Ok thank you, it works! I had to add the -recorder option for latexmk to acknowledge pdflatex was reading main.fmt, and my poor knowledge of perl didn't result in proper string management, but now it works. :) –  T. Verron Dec 9 '11 at 18:25
    
@John Collins I use your code and split up my preamble in main.ltx and main2.ltx. Now only changes in main.ltx are recognized. Is there a way to fix this other than combining the preambles? –  maetra Dec 13 '11 at 20:16
1  
@John Collins: Is there a way, with the current latexmk, to avoid having to call pdflatex -ini ... manually? I have tried add_cus_dep('fmt', 'tex', 1, 'my_noop'); with a dummy function my_noop, but this didn't change anything. I would like latexmk to call pdflatex -ini ... when the .fmt file is missing, too. –  krlmlr Mar 28 '12 at 8:47
    
@maetra: My new solution will detect changes in all files that are used when pdflatex -ini makes the format file. –  John Collins Apr 2 '12 at 20:28
    
@user946850: Modify the command string for running pdflatex so that if the format file exists, it runs pdflatex, but if the format file doesn't exist it makes a 2 line dummy log file. The first line of the dummy log file starts "This is ", and the second line has the name of the format file in parentheses. This will provoke latexmkrc into thinking there is a correct log file and that the format file is a source file of the run of pdflatex; it will then make the format file. –  John Collins Apr 2 '12 at 21:25
show 3 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.