代码之家  ›  专栏  ›  技术社区  ›  Evandro Coan

如何多次调用Makefile配方/规则?

  •  1
  • Evandro Coan  · 技术社区  · 7 年前

    使用以下示例:

    .PHONY: hook1 hook2
    
    # Default target
    all: hook1 hook2 hook1
        echo "Calling all"
    
    hook1:
        echo "Calling hook1"
    
    hook2:
        echo "Calling hook2"
    

    我得到了输出:

    $ make
    echo "Calling hook1"
    Calling hook1
    echo "Calling hook2"
    Calling hook2
    echo "Calling all"
    Calling all
    

    hook1

    $ make
    echo "Calling hook1"
    Calling hook1
    echo "Calling hook2"
    Calling hook2
    echo "Calling hook1"
    Calling hook1
    echo "Calling all"
    Calling all
    

    两次调用同一规则。如果有人感兴趣的话,下面是我完整的主Makefile代码。我试图创建虚拟规则 pdflatex_hook1 pdflatex_hook2 pdflatex_hook biber_hook pdflatex_hook ,但这并没有被愚弄 make 它仍然忽略了我最后一个电话 :

    #!/usr/bin/make -f
    # https://stackoverflow.com/questions/7123241/makefile-as-an-executable-script-with-shebang
    ECHOCMD:=/bin/echo -e
    
    # The main latex file
    THESIS_MAIN_FILE = modelomain.tex
    
    # This will be the pdf generated
    THESIS_OUTPUT_NAME = thesis
    
    # This is the folder where the temporary files are going to be
    CACHE_FOLDER = setup/cache
    
    # Find all files ending with `main.tex`
    LATEX_SOURCE_FILES := $(wildcard *main.tex)
    
    # Create a new variable within all `LATEX_SOURCE_FILES` file names ending with `.pdf`
    LATEX_PDF_FILES := $(LATEX_SOURCE_FILES:.tex=.pdf)
    
    
    # GNU Make silent by default
    # https://stackoverflow.com/questions/24005166/gnu-make-silent-by-default
    MAKEFLAGS += --silent
    .PHONY: clean pdflatex_hook1 pdflatex_hook2 %.pdf %.tex
    
    # How do I write the 'cd' command in a makefile?
    # http://stackoverflow.com/questions/1789594/how-do-i-write-the-cd-command-in-a-makefile
    .ONESHELL:
    
    # Default target
    all: biber
    
    
    ##
    ## Usage:
    ##   make <target>
    ##
    ## Targets:
    ##   biber             build the main file with bibliography pass
    ##   pdflatex          build the main file with no bibliography pass
    ##
    
    # Print the usage instructions
    # https://gist.github.com/prwhite/8168133
    help:
        @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
    
    
    # Where to find official (!) and extended documentation for tex/latex's commandline options (especially -interaction modes)?
    # https://tex.stackexchange.com/questions/91592/where-to-find-official-and-extended-documentation-for-tex-latexs-commandlin
    PDF_LATEX_COMMAND = pdflatex --time-statistics --synctex=1 -halt-on-error -file-line-error
    LATEX = $(PDF_LATEX_COMMAND)\
    --interaction=batchmode\
    -jobname="$(THESIS_OUTPUT_NAME)"\
    -output-directory="$(CACHE_FOLDER)"\
    -aux-directory="$(CACHE_FOLDER)"
    
    
    # Run pdflatex, biber, pdflatex
    biber: biber_hook pdflatex_hook2
    
        # Calculate the elapsed seconds and print them to the screen
        . ./setup/scripts/timer_calculator.sh
        showTheElapsedSeconds "$(current_dir)"
    
    # Internally called rule which does not attempt to show the elapsed time
    biber_hook: pdflatex_hook1
    
        # Creates the shell variable `current_dir` within the current folder path
        $(eval current_dir := $(shell pwd)) echo $(current_dir) > /dev/null
    
        biber "$(CACHE_FOLDER)/$(THESIS_OUTPUT_NAME)"
    
    
    # This rule will be called for every latex file and pdf associated
    pdflatex: $(LATEX_PDF_FILES)
    
        # Calculate the elapsed seconds and print them to the screen
        . ./setup/scripts/timer_calculator.sh
        showTheElapsedSeconds "$(current_dir)"
    
    # Not show the elapsed time when called internally
    pdflatex_hook1: $(LATEX_PDF_FILES)
    pdflatex_hook2: $(LATEX_PDF_FILES)
    
    
    %.pdf: %.tex
    
        # Start counting the compilation time and import its shell functions
        . ./setup/scripts/timer_calculator.sh
    
        # Creates the shell variable `current_dir` within the current folder path
        $(eval current_dir := $(shell pwd)) echo $(current_dir) > /dev/null
    
        @$(LATEX) $<
        cp $(CACHE_FOLDER)/$(THESIS_OUTPUT_NAME).pdf $(current_dir)/$(THESIS_OUTPUT_NAME).pdf
    

    当我称之为规则时 make biber 我得到了输出:

    $ make biber
    This is pdfTeX, Version 3.14159265-2.6-1.40.18 (MiKTeX 2.9.6400)
    entering extended mode
    gross execution time: 62751 ms
    
    user mode: 58406 ms, kernel mode: 1359 ms, total: 59765
    INFO - This is Biber 2.7
    INFO - Logfile is 'setup/cache/thesis.blg'
    INFO - Reading 'setup/cache/thesis.bcf'
    INFO - Found 14 citekeys in bib section 0
    INFO - Processing section 0
    INFO - Looking for bibtex format file 'modeloreferences.bib' for section 0
    INFO - Decoding LaTeX character macros into UTF-8
    INFO - Found BibTeX data source 'modeloreferences.bib'
    INFO - Overriding locale 'pt-BR' defaults 'normalization = NFD' with 'normalization = prenormalized'
    INFO - Overriding locale 'pt-BR' defaults 'variable = shifted' with 'variable = non-ignorable'
    INFO - Sorting list 'nty/global/' of type 'entry' with scheme 'nty' and locale 'pt-BR'
    INFO - No sort tailoring available for locale 'pt-BR'
    INFO - Writing 'setup/cache/thesis.bbl' with encoding 'UTF-8'
    INFO - Output to setup/cache/thesis.bbl
    Could not calculate the seconds to run
    

    ,仅第一次调用 pdflatex_hook1

    我已经知道了 latexmk 使用它,但为了 biber 以上我想做这些电话,因为他们是。对于 latexmk公司 我使用这个配方/规则:

    thesis: $(THESIS_MAIN_FILE)
    
        # Start counting the compilation time and import its shell functions
        . ./setup/scripts/timer_calculator.sh
    
        # Creates the shell variable `current_dir` within the current folder path
        $(eval current_dir := $(shell pwd)) echo $(current_dir) > /dev/null
    
        # What is the difference between “-interaction=nonstopmode” and “-halt-on-error”?
        # https://tex.stackexchange.com/questions/258814/what-is-the-difference-between-interaction-nonstopmode-and-halt-on-error
        #
        # What reasons (if any) are there for compiling in interactive mode?
        # https://tex.stackexchange.com/questions/25267/what-reasons-if-any-are-there-for-compiling-in-interactive-mode
        latexmk \
        -pdf \
        -silent \
        -jobname="$(THESIS_OUTPUT_NAME)" \
        -output-directory="$(CACHE_FOLDER)" \
        -aux-directory="$(CACHE_FOLDER)" \
        -pdflatex="$(PDF_LATEX_COMMAND) --interaction=batchmode" \
        -use-make $(THESIS_MAIN_FILE)
    
        # Copy the generated PDF file from the cache folder
        cp $(CACHE_FOLDER)/$(THESIS_OUTPUT_NAME).pdf $(current_dir)/$(THESIS_OUTPUT_NAME).pdf
    
        # Calculate the elapsed seconds and print them to the screen
        showTheElapsedSeconds "$(current_dir)"
    

    相关问题:

    1. Change a make variable, and call another rule, from a recipe in same Makefile?
    2. How to manually call another target from a make target?
    3. multiple targets from one recipe and parallel execution
    2 回复  |  直到 7 年前
        1
  •  1
  •   David White    7 年前

    要回答您最初的问题:

    .PHONY: hook1 hook2
    
    # Default target
    all: hook1a hook2 hook1b
        echo "Calling all"
    
    hook1a hook1b:
        echo "Calling hook1"
    
    hook2:
        echo "Calling hook2"
    

    产生以下输出:

    echo "Calling hook1"
    Calling hook1
    echo "Calling hook2"
    Calling hook2
    echo "Calling hook1"
    Calling hook1
    echo "Calling all"
    Calling all
    

    如所示 make recipe execute twice

        2
  •  0
  •   Evandro Coan    7 年前

    @David White 答:我用双递归修复了我的主脚本:

    #!/usr/bin/make -f
    # https://stackoverflow.com/questions/7123241/makefile-as-an-executable-script-with-shebang
    ECHOCMD:=/bin/echo -e
    
    # The main latex file
    THESIS_MAIN_FILE = modelomain.tex
    
    # This will be the pdf generated
    THESIS_OUTPUT_NAME = thesis
    
    # This is the folder where the temporary files are going to be
    CACHE_FOLDER = setup/cache
    
    # Find all files ending with `main.tex`
    LATEX_SOURCE_FILES := $(wildcard *main.tex)
    
    # Create a new variable within all `LATEX_SOURCE_FILES` file names ending with `.pdf`
    LATEX_PDF_FILES := $(LATEX_SOURCE_FILES:.tex=.pdf)
    
    
    # GNU Make silent by default
    # https://stackoverflow.com/questions/24005166/gnu-make-silent-by-default
    MAKEFLAGS += --silent
    .PHONY: clean biber pdflatex_hook1 pdflatex_hook2
    
    # How do I write the 'cd' command in a makefile?
    # http://stackoverflow.com/questions/1789594/how-do-i-write-the-cd-command-in-a-makefile
    .ONESHELL:
    
    # Default target
    all: thesis
    
    
    ##
    ## Usage:
    ##   make <target>
    ##
    ## Targets:
    ##   all        call the `thesis` make rule
    ##   biber      build the main file with bibliography pass
    ##   latex      build the main file with no bibliography pass
    ##   thesis     completely build the main file with minimum output logs
    ##   verbose    completely build the main file with maximum output logs
    ##
    
    # Print the usage instructions
    # https://gist.github.com/prwhite/8168133
    help:
        @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
    
    
    # Where to find official (!) and extended documentation for tex/latex's commandline options (especially -interaction modes)?
    # https://tex.stackexchange.com/questions/91592/where-to-find-official-and-extended-documentation-for-tex-latexs-commandlin
    PDF_LATEX_COMMAND = pdflatex --time-statistics --synctex=1 -halt-on-error -file-line-error
    LATEX = $(PDF_LATEX_COMMAND)\
    --interaction=batchmode\
    -jobname="$(THESIS_OUTPUT_NAME)"\
    -output-directory="$(CACHE_FOLDER)"\
    -aux-directory="$(CACHE_FOLDER)"
    
    
    # Run pdflatex, biber, pdflatex
    biber: start_timer pdflatex_hook1 biber_hook pdflatex_hook2
    
        # Creates the shell variable `current_dir` within the current folder path
        $(eval current_dir := $(shell pwd)) echo $(current_dir) > /dev/null
    
        # Copies the PDF to the current folder
        cp $(CACHE_FOLDER)/$(THESIS_OUTPUT_NAME).pdf $(current_dir)/$(THESIS_OUTPUT_NAME).pdf
    
        # Calculate the elapsed seconds and print them to the screen
        . ./setup/scripts/timer_calculator.sh
        showTheElapsedSeconds "$(current_dir)"
    
    
    start_timer:
    
        # Start counting the elapsed seconds to print them to the screen later
        . ./setup/scripts/timer_calculator.sh
    
    
    # Internally called rule which does not attempt to show the elapsed time
    biber_hook:
    
        # Creates the shell variable `current_dir` within the current folder path
        $(eval current_dir := $(shell pwd)) echo $(current_dir) > /dev/null
    
        # Call biber to process the bibliography
        biber "$(CACHE_FOLDER)/$(THESIS_OUTPUT_NAME)"
    
    
    # How to call Makefile recipe/rule multiple times?
    # https://stackoverflow.com/questions/46135614/how-to-call-makefile-recipe-rule-multiple-times
    pdflatex_hook1 pdflatex_hook2:
    
        @$(LATEX) $(LATEX_SOURCE_FILES)
    
    
    # This rule will be called for every latex file and pdf associated
    latex: $(LATEX_PDF_FILES)
    
        # Calculate the elapsed seconds and print them to the screen
        . ./setup/scripts/timer_calculator.sh
        showTheElapsedSeconds "$(current_dir)"
    
    
    # Dynamically generated recipes for all PDF and latex files
    %.pdf: %.tex
    
        # Start counting the compilation time and import its shell functions
        . ./setup/scripts/timer_calculator.sh
    
        # Creates the shell variable `current_dir` within the current folder path
        $(eval current_dir := $(shell pwd)) echo $(current_dir) > /dev/null
    
        @$(LATEX) $<
        cp $(CACHE_FOLDER)/$(THESIS_OUTPUT_NAME).pdf $(current_dir)/$(THESIS_OUTPUT_NAME).pdf
    
    
    thesis: $(THESIS_MAIN_FILE)
    
        # Start counting the compilation time and import its shell functions
        . ./setup/scripts/timer_calculator.sh
    
        # Creates the shell variable `current_dir` within the current folder path
        $(eval current_dir := $(shell pwd)) echo $(current_dir) > /dev/null
    
        # What is the difference between “-interaction=nonstopmode” and “-halt-on-error”?
        # https://tex.stackexchange.com/questions/258814/what-is-the-difference-between-interaction-nonstopmode-and-halt-on-error
        #
        # What reasons (if any) are there for compiling in interactive mode?
        # https://tex.stackexchange.com/questions/25267/what-reasons-if-any-are-there-for-compiling-in-interactive-mode
        latexmk \
        -pdf \
        -silent \
        -jobname="$(THESIS_OUTPUT_NAME)" \
        -output-directory="$(CACHE_FOLDER)" \
        -aux-directory="$(CACHE_FOLDER)" \
        -pdflatex="$(PDF_LATEX_COMMAND) --interaction=batchmode" \
        -use-make $(THESIS_MAIN_FILE)
    
        # Copy the generated PDF file from the cache folder
        cp $(CACHE_FOLDER)/$(THESIS_OUTPUT_NAME).pdf $(current_dir)/$(THESIS_OUTPUT_NAME).pdf
    
        # Calculate the elapsed seconds and print them to the screen
        showTheElapsedSeconds "$(current_dir)"
    
    
    verbose: $(THESIS_MAIN_FILE)
    
        # Start counting the compilation time and import its shell functions
        . ./setup/scripts/timer_calculator.sh
    
        # Creates the shell variable `current_dir` within the current folder path
        $(eval current_dir := $(shell pwd)) echo $(current_dir) > /dev/null
    
        # What is the difference between “-interaction=nonstopmode” and “-halt-on-error”?
        # https://tex.stackexchange.com/questions/258814/what-is-the-difference-between-interaction-nonstopmode-and-halt-on-error
        #
        # What reasons (if any) are there for compiling in interactive mode?
        # https://tex.stackexchange.com/questions/25267/what-reasons-if-any-are-there-for-compiling-in-interactive-mode
        latexmk \
        -pdf \
        -jobname="$(THESIS_OUTPUT_NAME)" \
        -output-directory="$(CACHE_FOLDER)" \
        -aux-directory="$(CACHE_FOLDER)" \
        -pdflatex="$(PDF_LATEX_COMMAND) --interaction=nonstopmode" \
        -use-make $(THESIS_MAIN_FILE)
    
        # Copy the generated PDF file from the cache folder
        cp $(CACHE_FOLDER)/$(THESIS_OUTPUT_NAME).pdf $(current_dir)/$(THESIS_OUTPUT_NAME).pdf
    
        # Calculate the elapsed seconds and print them to the screen
        showTheElapsedSeconds "$(current_dir)"
    
    
    # Using Makefile to clean subdirectories
    # https://stackoverflow.com/questions/26007005/using-makefile-to-clean-subdirectories
    #
    # Exclude directory from find . command
    # https://stackoverflow.com/questions/4210042/exclude-directory-from-find-command
    GARBAGE_TYPES := "*.gz(busy)" *.aux *.log *.pdf *.aux *.bbl *.log *.out *.toc *.dvi *.blg\
    *.synctex.gz *.fdb_latexmk *.fls *.lot *.lol *.lof *.idx
    
    DIRECTORIES_TO_CLEAN  := $(shell /bin/find -not -path "./**.git**" -not -path "./pictures**" -type d)
    GARBAGE_TYPED_FOLDERS := $(foreach DIR, $(DIRECTORIES_TO_CLEAN), $(addprefix $(DIR)/,$(GARBAGE_TYPES)))
    
    clean:
        rm -rfv $(GARBAGE_TYPED_FOLDERS)
    
    
    # veryclean:
    #   git clean -dxf