> 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/vi/co-so-tri-thuc/064-how-does-overleaf-compile-my-project.md).

# Overleaf biên dịch dự án của tôi như thế nào?

## Tự động hóa biên dịch LaTeX

Để hỗ trợ các tính năng như mục lục, danh sách hình, tham chiếu chéo, bảng thuật ngữ, lập chỉ mục và trích dẫn thư mục, LaTeX sử dụng quy trình dàn trang nhiều lượt: dữ liệu được tạo ra trong một lượt (biên dịch) sẽ được ghi ra tệp và dùng làm đầu vào cho các lượt tiếp theo nếu cần. Video sau đây cho thấy điều gì xảy ra mỗi khi bạn nhấp nút “Recompile” trong dự án Overleaf của mình:

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

Khi thực hiện biên dịch thủ công, thường có thể nhận ra nếu cần chạy LaTeX thêm một lượt (pass), nhưng tự động hóa biên dịch LaTeX lại đặt ra nhiều khó khăn. Một thách thức then chốt đối với các giải pháp tự động là xác định *bao nhiêu* lượt LaTeX (biên dịch) là cần thiết để giải quyết mọi phụ thuộc dữ liệu, qua đó bảo đảm tài liệu đã dàn trang cuối cùng là mới nhất và đầy đủ. Một độ phức tạp khác là xác định chính xác các chương trình bên ngoài phải được thực thi để tiền xử lý các phần nội dung tài liệu—chẳng hạn chạy BibTeX/BibLaTeX để tạo danh sách tham khảo hoặc chạy các ứng dụng đồ họa chuyên dụng hơn như [MetaPost](https://tug.org/metapost.html) hoặc [Asymptote](https://asymptote.sourceforge.io/).

## Giới thiệu latexmk

Một gói đã được thiết lập tốt để tự động hóa biên dịch là [`latexmk`](https://ctan.org/pkg/latexmk?lang=en)—một script Perl lớn được bao gồm trong TeX Live và được Overleaf dùng để biên dịch các dự án LaTeX của bạn. `latexmk` tự động kích hoạt số lượt chạy LaTeX cần thiết và thực thi các chương trình bên ngoài (phụ trợ) cần để xử lý các phần nội dung tài liệu của bạn.

### Tùy chỉnh latexmk

Mặc dù `latexmk` rất linh hoạt, các môi trường biên dịch LaTeX khác nhau, cùng phạm vi cực kỳ rộng của các loại tài liệu, khiến việc `latexmk` cố gắng cung cấp các giải pháp tự động hỗ trợ đầy đủ nhu cầu của mọi tài liệu LaTeX có thể tưởng tượng là không thực tế. Thay vào đó, hành vi của `latexmk` có thể được tùy chỉnh thông qua các tệp cấu hình *được triển khai bằng **Perl***:

* một tệp cấu hình “toàn hệ thống” phục vụ cho môi trường/nền tảng tính toán cụ thể, và
* một tệp cấu hình cấp người dùng xử lý các yêu cầu riêng của tài liệu

Tính năng [`sổ tay latexmk`](http://mirrors.ctan.org/support/latexmk/latexmk.pdf) cung cấp thêm chi tiết về việc cài đặt và sử dụng các tệp cấu hình.

## Tệp LatexMk của Overleaf

Tệp cấu hình “toàn hệ thống” của Overleaf tuân theo `latexmk` quy ước (cho Linux): nó được đặt tên là `**LatexMk**` và nằm trong thư mục `/usr/local/share/latexmk/`. **Lưu ý**: tệp đó được đọc *trước khi* trước bất kỳ tệp cấu hình cấp người dùng nào.

Các tệp cấu hình cấp người dùng phải được đặt tên là `latexmkrc` và thêm vào dự án Overleaf của bạn để cung cấp các quy tắc tùy chỉnh nhằm đáp ứng các yêu cầu cụ thể của dự án/tài liệu LaTeX Overleaf của bạn.

Tệp `LatexMk` của Overleaf chứa mã cho quá trình xử lý đặc thù của Overleaf cùng các quy tắc cho bảng thuật ngữ, danh mục ký hiệu và các gói thường dùng khác. Tệp `LatexMk` của Overleaf có thể có đôi chút khác nhau giữa các bản phát hành TeX Live để thích ứng với các thay đổi và cập nhật được thực hiện đối với các gói và công cụ phần mềm ngay trong TeX Live.

### Thay đổi chế độ biên dịch của LaTeX

Mặc định, Overleaf yêu cầu latexmk sử dụng một chế độ biên dịch mà chúng tôi (Overleaf) gọi là **Cố gắng biên dịch dù có lỗi**. Trong chế độ biên dịch đó, trình biên dịch LaTeX không dừng lại, dù gặp phải [lỗi biên dịch LaTeX](/latex/vi/kien-thuc-co-ban-ve-latex/05-errors.md); có thể vẫn tạo ra một tệp PDF, ngay cả khi nó chứa đầu ra sai. Thông thường, các lỗi biên dịch có thể quá nghiêm trọng, hoặc quá nhiều, để trình biên dịch LaTeX có thể tự sửa, vì vậy nó vẫn có thể “bỏ cuộc” mà không tạo ra PDF.

Bạn có thể thay đổi chế độ biên dịch LaTeX sao cho quá trình biên dịch dừng ngay khi gặp lỗi đầu tiên: xem bài trợ giúp [Sử dụng chế độ biên dịch Dừng ở Lỗi Đầu Tiên](/latex/vi/co-so-tri-thuc/149-using-the-stop-on-first-error-compilation-mode.md) để biết thêm thông tin.

### Cách truy cập bản sao của tệp LatexMk của Overleaf

Liên kết sau mở một dự án để dàn trang tệp Overleaf `LatexMk` đang được dùng với trình biên dịch LaTeX và phiên bản TeX Live của dự án của bạn, đồng thời cũng làm cho nó có thể tải xuống được:

```latex
\documentclass[a4paper]{article}
\usepackage[margin=1cm]{geometry}
\usepackage{verbatim,shellesc}
\ShellEscape{cp /usr/local/share/latexmk/LatexMk ./LatexMk}
\begin{document}
\section*{Giới thiệu về dự án này}
Dự án này cung cấp quyền truy cập vào tệp khởi tạo (cấu hình) \texttt{LatexMk} cấp hệ thống mà Overleaf sử dụng. \texttt{LatexMk} là một script Perl có thể thay đổi đôi chút tùy theo phiên bản \TeX{} Live và trình biên dịch được chọn cho dự án. Nếu bạn cần chắc chắn 100\% tệp \texttt{LatexMk} nào đang được dùng, hãy thêm mã từ dự án này vào dự án của bạn và biên dịch để dàn trang một danh sách của \texttt{LatexMk} và làm cho nó có thể tải xuống như một trong các tệp đầu ra.
\section*{Liệt kê tệp \texttt{LatexMk}}
\verbatiminput{./LatexMk}
\end{document}
```

[Mở mã này trong 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)

Sau khi biên dịch dự án ở trên, `LatexMk` tệp có thể được tải xuống qua **Nhật ký và tệp đầu ra** nút như thể hiện trong đoạn video ngắn sau:

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

### Các ghi chú và lời khuyên khác

Nếu bạn muốn đặt, hoặc kiểm tra, phiên bản TeX Live được dùng để biên dịch dự án của mình, vui lòng tham khảo [bài đăng trên blog Overleaf](https://www.overleaf.com/blog/new-feature-select-your-tex-live-compiler-version#How-Switch) này hoặc hình minh họa sau:

![Chọn phiên bản TeX Live của Overleaf](/files/b81b1776aabae19fdded47a6e344d6c70f585375)

Nếu bạn muốn xây dựng dự án Overleaf của mình ngoại tuyến bằng latexmk, bạn có thể muốn dùng một bản sao của tệp LatexMk của Overleaf để bảo đảm nó áp dụng quy trình xây dựng của Overleaf—lưu ý tên công việc (job name) của Overleaf được đặt thành output.

Overleaf biên dịch các dự án bằng `-cd` cờ dòng lệnh của latexmk, và quá trình biên dịch luôn được chạy từ thư mục gốc của dự án. Lưu ý rằng một số `latexmk` tùy chọn không tương thích với Overleaf—đặc biệt, nếu bạn đặt các tùy chọn `$preview_continuous_mode` hoặc `$output_dir` thì điều đó có thể làm hỏng bản xem trước trên Overleaf.

Để biết thêm thông tin về `latexmkrc` các tệp được đọc, hãy xem bài viết [Cách sử dụng latexmkrc với Overleaf](/latex/vi/bai-viet-chuyen-sau/28-how-to-use-latexmkrc-with-overleaf.md) với những mẹo và thủ thuật hữu ích từ các TeXpert thân thiện của chúng tôi tại Overleaf.

## Danh sách tệp LatexMk của Overleaf (2023)

Để tiện lợi, danh sách dưới đây cho thấy `LatexMk` tệp của Overleaf như được dùng với TeX Live 2023—hãy dùng liên kết ở trên để truy cập phiên bản mới nhất.

```perl
# Cài đặt
$xdvipdfmx = "xdvipdfmx -z 6 -i dvipdfmx-unsafe.cfg -o %D %O %S";

# Cách khắc phục để cho phép độ trong suốt pstricks (https://github.com/overleaf/issues/issues/3449)
$dvipdf = "dvipdf -dNOSAFER -dALLOWPSTRANSPARENCY %O %S %D";

###############################
# Xử lý hậu kỳ của tệp pdf #
###############################

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

# tương đương với tùy chọn -gt. Dùng để ngăn latexmk bỏ qua việc biên dịch lại
# của output.log và output.pdf
$go_mode = 3;

# tương đương với tùy chọn -bibtex. Chạy bibtex vô điều kiện khi các tệp bbl
# đã lỗi thời.
$bibtex_use = 2;

my $ORIG_PDF_AGE;

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

    # lấy tuổi của pdf hiện có nếu có
    $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;

    # Tìm một tệp concordance của knitr
    my $concordance_file = "${source_without_ext}-concordance.tex";
    if (-e $concordance_file) {
        print "Đang vá tệp synctex cho knitr...\n";
        system("patchSynctex.R", $source_without_ext, $output_without_ext);
    }

    # Trả về sớm nếu tệp pdf không tồn tại hoặc chưa được cập nhật
    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;

    # Xác định qpdf nằm ở đâu
    $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});

    # Chạy qpdf
    my $optimised_file = "${output_file}.opt";
    system($qpdf, split(' ', $qpdf_opts), $output_file, $optimised_file);
    $qpdf_exit_code = ($? >> 8);
    print "mã thoát của qpdf=$qpdf_exit_code\n";

    # Thay thế tệp đầu ra nếu qpdf thành công
    # qpdf trả về 0 khi thành công, 3 khi có cảnh báo (tệp pdf đầu ra vẫn được tạo)
    return if !($qpdf_exit_code == 0 || $qpdf_exit_code == 3);
    print "Đổi tên tệp đã tối ưu thành $output_file\n";
    rename($optimised_file, $output_file);

    print "Đang trích xuất bảng xref cho $output_file\n";
    my $xref_file = "${output_file}xref";
    system("$qpdf --show-xref ${output_file} > ${xref_file}");
    $qpdf_xref_exit_code = ($? >> 8);
    print "mã thoát của qpdf --show-xref=$qpdf_xref_exit_code\n";
}

##############
# Bảng thuật ngữ #
##############
add_cus_dep( 'glo', 'gls', 0, 'glo2gls' );
add_cus_dep( 'acn', 'acr', 0, 'glo2gls');  # từ Overleaf v1
sub glo2gls {
    system("makeglossaries $_[0]");
}

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

################
# danh mục ký hiệu #
################
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: Không thể tìm thấy tệp hình (.*); tiếp tục.$');
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  #  # từ 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;

    # xác định tệp chính
    my $target = $ARGV[-1];
    my $file = basename($target);

    if ($file =~ /\.tex$/) {
        # thay đổi thư mục trong phạm vi giới hạn
        my $orig_dir = cwd();
        my $subdir = dirname($target);
        chdir($subdir);
        # chạy chktex trên tệp chính
        $status = system("/usr/local/bin/run-chktex.sh", $orig_dir, $file);
        # quay lại thư mục gốc
        chdir($orig_dir);

        # ở chế độ VALIDATE chúng ta luôn thoát sau khi chạy chktex
        # còn lại thì thoát nếu CHKTEX_EXIT_ON_ERROR được đặt

        if ($ENV{'CHKTEX_EXIT_ON_ERROR'} || $ENV{'CHKTEX_VALIDATE'}) {
            # chktex không cho phép chúng ta truy cập thông tin lỗi qua mã thoát
            # vì vậy hãy xem qua đầu ra
            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/vi/co-so-tri-thuc/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.
