Issue
I am trying to add documentation to the build process of a CMake project, a lot like in this chapter from CMake's own "Mastering CMake." Here is the excerpt:
# Add the rule to build the .pdf file from the .tex
# file. This relies on LATEX and DVIPDF being set correctly
#
add_custom_command(
OUTPUT ${PROJECT_BINARY_DIR}/doc1.pdf
DEPENDS ${PROJECT_SOURCE_DIR}/doc1.tex
COMMAND ${LATEX} ${PROJECT_SOURCE_DIR}/doc1.tex
COMMAND ${DVIPDF} ${PROJECT_BINARY_DIR}/doc1.dvi
)
# finally add the custom target that when invoked
# will cause the generation of the pdf file
add_custom_target(TDocument ALL
DEPENDS ${PROJECT_BINARY_DIR}/doc1.pdf
)
The behavior of this bit of CMake, in alignment with the documentation for add_custom_target
, compiles my latex document every time I build my project. I want the latex document to be built only when it's dependencies are altered. So, I modified it to be
# Add the rule to build the .pdf file from the .tex
# file. This relies on LATEX and DVIPDF being set correctly
#
add_custom_command(
OUTPUT ${PROJECT_BINARY_DIR}/doc1.pdf
DEPENDS ${PROJECT_SOURCE_DIR}/doc1.tex
COMMAND ${LATEX} ${PROJECT_SOURCE_DIR}/doc1.tex
COMMAND ${DVIPDF} ${PROJECT_BINARY_DIR}/doc1.dvi
)
# finally add the custom target that when invoked
# will cause the generation of the pdf file
add_custom_target(TDocument # no longer specifying ALL
DEPENDS ${PROJECT_BINARY_DIR}/doc1.pdf
)
I thought this would be as simple as removing ALL
from the custom target, but instead of building the PDF whenever its dependencies are altered, it is not built at all, whether doc1.tex
is edited or even if doc1.pdf
is deleted.
I have used this pattern successfully to manage, for example, CSV files that are created by C++ executables before so it's not at all clear to me why it wouldn't work with latex.
Solution
Adds a target with the given name that executes the given commands. The target has no output file and is always considered out of date even if the commands try to create a file with the name of the target. Use the
add_custom_command()
command to generate a file with dependencies.
Since the target is always out-of-date it will always build, regardless of its status. If you want a target with dependencies on source files and/or output use add_custom_command()
.
After re-reading your question and code more carefully, your CMakeLists.txt
is correct.
$ ls
CMakeLists.txt doc1.tex
$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(q)
set(LATEX "latex")
set(DVIPDF "dvipdf")
add_custom_command(
OUTPUT ${PROJECT_BINARY_DIR}/doc1.pdf
DEPENDS ${PROJECT_SOURCE_DIR}/doc1.tex
COMMAND ${LATEX} ${PROJECT_SOURCE_DIR}/doc1.tex
COMMAND ${DVIPDF} ${PROJECT_BINARY_DIR}/doc1.dvi
)
add_custom_target(TDocument ALL
DEPENDS ${PROJECT_BINARY_DIR}/doc1.pdf
)
$ cmake .
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/nega/q
$ make VERBOSE=1
/usr/bin/cmake -S/home/nega/q -B/home/nega/q --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/nega/q/CMakeFiles /home/nega/q//CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/nega/q'
make -f CMakeFiles/TDocument.dir/build.make CMakeFiles/TDocument.dir/depend
make[2]: Entering directory '/home/nega/q'
cd /home/nega/q && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/nega/q /home/nega/q /home/nega/q /home/nega/q /home/nega/q/CMakeFiles/TDocument.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/nega/q'
make -f CMakeFiles/TDocument.dir/build.make CMakeFiles/TDocument.dir/build
make[2]: Entering directory '/home/nega/q'
[100%] Generating doc1.pdf
latex /home/nega/q/doc1.tex
This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(/home/nega/q/doc1.tex
LaTeX2e <2021-11-15> patch level 1
L3 programming layer <2022-01-21>
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-dvips.def)
No file doc1.aux.
[1] (./doc1.aux) )
Output written on doc1.dvi (1 page, 1760 bytes).
Transcript written on doc1.log.
dvipdf /home/nega/q/doc1.dvi
make[2]: Leaving directory '/home/nega/q'
[100%] Built target TDocument
make[1]: Leaving directory '/home/nega/q'
/usr/bin/cmake -E cmake_progress_start /home/nega/q/CMakeFiles 0
$ make VERBOSE=1
/usr/bin/cmake -S/home/nega/q -B/home/nega/q --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/nega/q/CMakeFiles /home/nega/q//CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/nega/q'
make -f CMakeFiles/TDocument.dir/build.make CMakeFiles/TDocument.dir/depend
make[2]: Entering directory '/home/nega/q'
cd /home/nega/q && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/nega/q /home/nega/q /home/nega/q /home/nega/q /home/nega/q/CMakeFiles/TDocument.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/nega/q'
make -f CMakeFiles/TDocument.dir/build.make CMakeFiles/TDocument.dir/build
make[2]: Entering directory '/home/nega/q'
make[2]: Nothing to be done for 'CMakeFiles/TDocument.dir/build'.
make[2]: Leaving directory '/home/nega/q'
[100%] Built target TDocument
make[1]: Leaving directory '/home/nega/q'
/usr/bin/cmake -E cmake_progress_start /home/nega/q/CMakeFiles 0
$ touch doc1.tex
$ make
[100%] Generating doc1.pdf
This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(/home/nega/q/doc1.tex
LaTeX2e <2021-11-15> patch level 1
L3 programming layer <2022-01-21>
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-dvips.def)
(./doc1.aux) [1] (./doc1.aux) )
Output written on doc1.dvi (1 page, 1760 bytes).
Transcript written on doc1.log.
[100%] Built target TDocument
$
You'll notice that with the second invocation of make VERBOSE=1
that latex
and dvipdf
are not run, since doc1.tex
hasn't changed. After touch
ing doc1.tex
changing its timestamp, and running make
for the third time, latex
and dvipdf
are run again.
If your doc1.tex
is being processed every time you build, I suspect either something in your greater build process is touching your source file (doc1.tex
), changing its timestamp, or your source file has a "future date". A future date for a timestamp will cause the source file to be out-of-date until that time has passed.
Answered By - nega Answer Checked By - Robin (WPSolving Admin)