> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/ru/baza-znanii/064-how-does-overleaf-compile-my-project.md).

# Как Overleaf компилирует мой проект?

## Автоматизация компиляции LaTeX

Чтобы поддерживать такие возможности, как оглавление, списки рисунков, перекрёстные ссылки, глоссарии, индексирование и библиографические цитаты, LaTeX использует многоэтапный процесс набора: данные, полученные за один проход (компиляцию), записываются в файл(ы) и используются как входные данные для любых последующих проходов, которые могут потребоваться. Следующее видео показывает, что происходит каждый раз, когда вы нажимаете кнопку «Recompile» в вашем проекте Overleaf:

{% embed url="<https://videos.ctfassets.net/nrgyaltdicpt/Uo3I2FXEI8H6aFPBZq171/e2139f9575a4db6955dc2278dc08283c/latexmk-ol.mp4>" %}

При ручной компиляции обычно понятно, нужен ли ещё один запуск LaTeX (проход), но автоматизация компиляции LaTeX создаёт ряд трудностей. Ключевая задача для автоматизированных решений — определить *сколько* проходов LaTeX (компиляций) нужно, чтобы устранить любые зависимости данных и тем самым обеспечить, что итоговый набранный документ актуален и завершён. Ещё одна сложность — правильно определить внешние программы, которые необходимо выполнить для предварительной обработки частей содержимого документа — например, запуск BibTeX/BibLaTeX для формирования списков литературы или выполнение более специализированных графических приложений, таких [MetaPost](https://tug.org/metapost.html) или [Asymptote](https://asymptote.sourceforge.io/).

## Представляем latexmk

Один хорошо зарекомендовавший себя пакет для автоматизации компиляции — [`latexmk`](https://ctan.org/pkg/latexmk?lang=en), большой Perl-скрипт, входящий в состав TeX Live и используемый Overleaf для компиляции ваших проектов LaTeX. `latexmk` автоматически запускает необходимое число прогонов LaTeX и выполняет внешние (вспомогательные) программы, требуемые для обработки частей содержимого вашего документа.

### Настройка latexmk

Хотя `latexmk` чрезвычайно универсален, разные среды компиляции LaTeX и огромный диапазон типов документов делают практически невозможным для `latexmk` предложить автоматизированные решения, полностью поддерживающие потребности любого мыслимого документа LaTeX. Вместо этого поведение `latexmk` можно настраивать через конфигурационные файлы *реализованные на **Perl***:

* конфигурационный файл «для всей системы», который учитывает конкретную вычислительную среду/платформу, и
* конфигурационный файл уровня пользователя, который обрабатывает требования, специфичные для документа

Это [`Руководство latexmk`](http://mirrors.ctan.org/support/latexmk/latexmk.pdf) содержит более подробные сведения об установке и использовании конфигурационных файлов.

## Файл LatexMk Overleaf

«Системный» конфигурационный файл Overleaf следует `latexmk` соглашениям (для Linux): он называется `**LatexMk**` и находится в папке `/usr/local/share/latexmk/`. **Примечание**: этот файл считывается *до* перед любыми конфигурационными файлами уровня пользователя.

Файлы конфигурации уровня пользователя должны называться `latexmkrc` и добавляться в ваш проект Overleaf, чтобы предоставлять пользовательские правила, учитывающие конкретные требования вашего проекта/документа Overleaf LaTeX.

Файл `LatexMk` Overleaf содержит код для обработки, специфичной для Overleaf, а также правила для глоссариев, номенклатуры и других часто используемых пакетов. Файл Overleaf `LatexMk` может немного отличаться между выпусками TeX Live, чтобы учитывать изменения и обновления, внесённые в пакеты и программные инструменты внутри самого TeX Live.

### Изменение режима компиляции LaTeX

По умолчанию Overleaf instructs latexmk to use a compilation mode that we (Overleaf) refer to as **Попытаться компилировать, несмотря на ошибки**режим nonstop [ошибки компиляции LaTeX](/latex/ru/osnovy-latex/05-errors.md)ошибок

Вы можете изменить режим компиляции LaTeX так, чтобы компиляция останавливалась немедленно при возникновении первой ошибки: см. справочную статью [Использование режима компиляции «Остановка при первой ошибке»](/latex/ru/baza-znanii/149-using-the-stop-on-first-error-compilation-mode.md) для получения дополнительной информации.

### Как получить копию файла LatexMk Overleaf

Следующая ссылка открывает проект для набора файла Overleaf `LatexMk` файл, используемый с компилятором LaTeX вашего проекта и версией TeX Live, а также делает его доступным для загрузки:

```latex
\documentclass[a4paper]{article}
\usepackage[margin=1cm]{geometry}
\usepackage{verbatim,shellesc}
\ShellEscape{cp /usr/local/share/latexmk/LatexMk ./LatexMk}
\begin{document}
\section*{Об этом проекте}
Этот проект предоставляет доступ к системному \texttt{LatexMk} файлу инициализации (конфигурации), используемому Overleaf. \texttt{LatexMk} — это Perl-скрипт, который может немного отличаться в зависимости от версии \TeX{} Live и выбранного для проекта компилятора. Если вам нужно быть на 100\% уверенными, какой именно \texttt{LatexMk} используется, добавьте код из этого проекта в свой проект и выполните компиляцию, чтобы получить список \texttt{LatexMk} и сделать его доступным для загрузки как один из выходных файлов.
\section*{Список файла \texttt{LatexMk}}
\verbatiminput{./LatexMk}
\end{document}
```

[Откройте этот код в Overleaf.](https://www.overleaf.com/docs?engine=\&snip_name=Display+Overleaf+latexmkrc+file\&snip=%5Cdocumentclass%5Ba4paper%5D%7Barticle%7D%0A%5Cusepackage%5Bmargin%3D1cm%5D%7Bgeometry%7D%0A%5Cusepackage%7Bverbatim%2Cshellesc%7D%0A%5CShellEscape%7Bcp+%2Fusr%2Flocal%2Fshare%2Flatexmk%2FLatexMk+.%2FLatexMk%7D%0A%5Cbegin%7Bdocument%7D%0A%5Csection%2A%7BAbout+this+project%7D%0AThis+project+provides+access+to+the+system+%5Ctexttt%7BLatexMk%7D+initialization+%28configuration%29+file+used+by+Overleaf.++%5Ctexttt%7BLatexMk%7D+is+a+Perl+script+which+may+vary+slightly+according+to+the+%5CTeX%7B%7D+Live+version+and+compiler+chosen+for+the+project.+If+you+need+to+be+100%5C%25+certain+which++%5Ctexttt%7BLatexMk%7D+is+being+used%2C+add+code+from+this+project+to+your+project+and+compile+to+typeset+a+listing+of+%5Ctexttt%7BLatexMk%7D+and+make+it+available+for+download+as+one+of+the+output+files.%0A%5Csection%2A%7BListing+the+%5Ctexttt%7BLatexMk%7D+file%7D%0A%5Cverbatiminput%7B.%2FLatexMk%7D%0A%5Cend%7Bdocument%7D)

После компиляции проекта выше, `LatexMk` файл можно скачать через **Журналы и выходные файлы** кнопку, как показано в следующем коротком видеоклипе:

{% embed url="<https://videos.ctfassets.net/nrgyaltdicpt/1re6AeMUF2EQnlZ8Cse5ke/ae6ee91fa7e2b2efa8ffb27ad8bab1a0/latexmkrc.mp4>" %}

### Другие примечания и советы

Если вы хотите задать или проверить версию TeX Live, используемую для компиляции вашего проекта, см. этот [пост в блоге Overleaf](https://www.overleaf.com/blog/new-feature-select-your-tex-live-compiler-version#How-Switch) или следующую иллюстрацию:

![Выбор версии TeX Live в Overleaf](/files/83b035c633a957173422547af96e40cdbd86334a)

Если вы хотите собирать проект Overleaf офлайн с помощью latexmk, возможно, вам стоит использовать копию файла LatexMk Overleaf, чтобы гарантировать применение процесса сборки Overleaf — обратите внимание, что имя задания Overleaf установлено в output.

Overleaf компилирует проекты, используя `-cd` флаг командной строки latexmk, и компиляция всегда запускается из корневого каталога проекта. Обратите внимание, что некоторые `latexmk` параметры несовместимы с Overleaf — в частности, если вы задаёте `$preview_continuous_mode` или `$output_dir` параметры, это может нарушить предпросмотр в Overleaf.

Для получения дополнительной информации о `latexmkrc` файлах читайте статью [Как использовать latexmkrc с Overleaf](/latex/ru/podrobnye-stati/28-how-to-use-latexmkrc-with-overleaf.md) которая содержит полезные советы и приёмы от наших дружелюбных Overleaf TeXperts.

## Список файла LatexMk Overleaf (2023)

Для удобства ниже приведён список файла Overleaf `LatexMk` файл, используемый с TeX Live 2023 — воспользуйтесь ссылкой выше, чтобы получить доступ к самой последней версии.

```perl
# Настройки
$xdvipdfmx = "xdvipdfmx -z 6 -i dvipdfmx-unsafe.cfg -o %D %O %S";

# Обходной путь, позволяющий прозрачность pstricks (https://github.com/overleaf/issues/issues/3449)
$dvipdf = "dvipdf -dNOSAFER -dALLOWPSTRANSPARENCY %O %S %D";

###############################
# Постобработка PDF-файла #
###############################

$compiling_cmd = "internal overleaf_pre_process %T %D";
$success_cmd = "internal overleaf_post_process %T %D";
$failure_cmd = $success_cmd;

# эквивалентно опции -gt. Используется, чтобы предотвратить пропуск latexmk повторной компиляции
# файла output.log и output.pdf
$go_mode = 3;

# эквивалентно опции -bibtex. Запускать bibtex безусловно, когда файлы bbl
# устарели.
$bibtex_use = 2;

my $ORIG_PDF_AGE;

sub overleaf_pre_process {
    my $source_file = $_[0];
    my $output_file = $_[1];

    # получить возраст существующего pdf, если он есть
    $ORIG_PDF_AGE = -M $output_file
}

sub overleaf_post_process {
    my $source_file = $_[0];
    my $output_file = $_[1];
    my $source_without_ext = $source_file =~ s/\.tex$//r;
    my $output_without_ext = $output_file =~ s/\.pdf$//r;

    # Ищем concordance-файл knitr
    my $concordance_file = "${source_without_ext}-concordance.tex";
    if (-e $concordance_file) {
        Патчим synctex-файл для knitr...\n
        system("patchSynctex.R", $source_without_ext, $output_without_ext);
    }

    # Вернуть управление раньше, если PDF-файл не существует или не был обновлён
    my $NEW_PDF_AGE = -M $output_file;
    return if !defined($NEW_PDF_AGE);
    return if defined($ORIG_PDF_AGE) && $NEW_PDF_AGE == $ORIG_PDF_AGE;

    # Определить, где находится qpdf
    $qpdf //= "/usr/bin/qpdf";
    $qpdf = $ENV{QPDF} if defined($ENV{QPDF}) && -x $ENV{QPDF};
    return if ! -x $qpdf;
    $qpdf_opts //= "--linearize --newline-before-endstream";
    $qpdf_opts = $ENV{QPDF_OPTS} if defined($ENV{QPDF_OPTS});

    # Запускаем qpdf
    my $optimised_file = "${output_file}.opt";
    system($qpdf, split(' ', $qpdf_opts), $output_file, $optimised_file);
    $qpdf_exit_code = ($? >> 8);
    код завершения qpdf=$qpdf_exit_code\n

    # Заменить выходной файл, если qpdf успешно выполнился
    # qpdf возвращает 0 при успехе, 3 при предупреждениях (выходной pdf всё равно создаётся)
    return if !($qpdf_exit_code == 0 || $qpdf_exit_code == 3);
    Переименовываем оптимизированный файл в $output_file\n
    rename($optimised_file, $output_file);

    Извлекаем таблицу xref для $output_file\n
    my $xref_file = "${output_file}xref";
    system("$qpdf --show-xref ${output_file} > ${xref_file}");
    $qpdf_xref_exit_code = ($? >> 8);
    код завершения qpdf --show-xref=$qpdf_xref_exit_code\n
}

##############
# Глоссарии #
##############
add_cus_dep( 'glo', 'gls', 0, 'glo2gls' );
add_cus_dep( 'acn', 'acr', 0, 'glo2gls');  # из Overleaf v1
sub glo2gls {
    system("makeglossaries $_[0]");
}

#############
# makeindex #
#############
@ist = glob("*.ist");
if (scalar(@ist) > 0) {
    $makeindex = "makeindex -s $ist[0] %O -o %D %S";
}

################
# номенклатура #
################
add_cus_dep("nlo", "nls", 0, "nlo2nls");
sub nlo2nls {
        system("makeindex $_[0].nlo -s nomencl.ist -o $_[0].nls -t $_[0].nlg");
}

#########
# Knitr #
#########
add_cus_dep( 'Rtex', 'tex', 0, 'do_knitr');
add_cus_dep( 'Rnw', 'tex', 0, 'do_knitr');
sub do_knitr {
    Run_subst(qq{Rscript -e '
        library("knitr");
        opts_knit\$set(concordance=T);
        knitr::knit(%S, output=%D);
        '}
    );
}

##########
# feynmf #
##########
push(@file_not_found, '^feynmf: Files .* and (.*) not found:$');
add_cus_dep("mf", "tfm", 0, "mf_to_tfm");
sub mf_to_tfm { system("mf '\\mode:=laserjet; input $_[0]'"); }

push(@file_not_found, '^feynmf: Label file (.*) not found:$');
add_cus_dep("mf", "t1", 0, "mf_to_label1");
sub mf_to_label1 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t1"); }
add_cus_dep("mf", "t2", 0, "mf_to_label2");
sub mf_to_label2 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t2"); }
add_cus_dep("mf", "t3", 0, "mf_to_label3");
sub mf_to_label3 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t3"); }
add_cus_dep("mf", "t4", 0, "mf_to_label4");
sub mf_to_label4 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t4"); }
add_cus_dep("mf", "t5", 0, "mf_to_label5");
sub mf_to_label5 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t5"); }
add_cus_dep("mf", "t6", 0, "mf_to_label6");
sub mf_to_label6 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t6"); }
add_cus_dep("mf", "t7", 0, "mf_to_label7");
sub mf_to_label7 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t7"); }
add_cus_dep("mf", "t8", 0, "mf_to_label8");
sub mf_to_label8 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t8"); }
add_cus_dep("mf", "t9", 0, "mf_to_label9");
sub mf_to_label9 { system("mf '\\mode:=laserjet; input $_[0]' && touch $_[0].t9"); }

##########
# feynmp #
##########
push(@file_not_found, '^dvipdf: Не удалось найти файл рисунка (.*); продолжаем.$');
add_cus_dep("mp", "1", 0, "mp_to_eps");
sub mp_to_eps {
    system("mpost $_[0]");
    return 0;
}

#############
# asymptote #
#############

sub asy {return system("asy \"$_[0]\"");}
add_cus_dep("asy","eps",0,"asy");
add_cus_dep("asy","pdf",0,"asy");
add_cus_dep("asy","tex",0,"asy");

#############
# metapost  #  # из Overleaf v1
#############
add_cus_dep('mp', '1', 0, 'mpost');
sub mpost {
    my $file = $_[0];
    my ($name, $path) = fileparse($file);
    pushd($path);
    my $return = system "mpost $name";
    popd();
    return $return;
}

##########
# chktex #
##########
unlink 'output.chktex' if -f 'output.chktex';
if (defined $ENV{'CHKTEX_OPTIONS'}) {
    use File::Basename;
    use Cwd;

    # определить основной файл
    my $target = $ARGV[-1];
    my $file = basename($target);

    if ($file =~ /\.tex$/) {
        # изменить каталог в пределах ограниченной области
        my $orig_dir = cwd();
        my $subdir = dirname($target);
        chdir($subdir);
        # запустить chktex для основного файла
        $status = system("/usr/local/bin/run-chktex.sh", $orig_dir, $file);
        # вернуться в исходный каталог
        chdir($orig_dir);

        # в режиме VALIDATE мы всегда выходим после запуска chktex
        # в противном случае мы выходим, если задан EXIT_ON_ERROR

        if ($ENV{'CHKTEX_EXIT_ON_ERROR'} || $ENV{'CHKTEX_VALIDATE'}) {
            # chktex не позволяет нам получить информацию об ошибке через код завершения
            # поэтому просматриваем вывод
            open(my $fh, "<", "output.chktex");
            my $errors = 0;
            {
                local $/ = "\n";
                while(<$fh>) {
                    if (/^\S+:\d+:\d+: Error:/) {
                        $errors++;
                        print;
                    }
                }
            }
            close($fh);
            exit(1) if $errors > 0;
            exit(0) if $ENV{'CHKTEX_VALIDATE'};
        }
    }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/ru/baza-znanii/064-how-does-overleaf-compile-my-project.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
