equivalent command for gnumake (for...do, if exist,del) - shell

I'm converting a makefile so it can be used with gnu make. In the other make program (can't find what was the version...) this part was executed :
#******************************************************************************
# Explicit Rules
#******************************************************************************
#
# This section contents the explicit rules to create the Virtual File system.
# This file system actualy contains the files used by the Web interface.
#
#******************************************************************************
CFGFILE = $(WEBDST)/vfs.cfg
# Compiling vfsdata
$(OBJDIR)vfsdata.o : vfsdata.c
#echo .
#echo ::. COMPILING1 : vfsdata.c
#echo ::::.
$(NOECHOC)$(CC) $(CFLAGS) $(DEBUGFLASG) $(subst \,/,$(VFSDIR))/vfsdata.c -o"$#" $(INCLUDE)
# Dependance of vfsdata.c
vfsdata.c : $(addprefix $(WEBSRC)\,$(WEBGLOBAL)) $(addprefix $(WEBDST)\,$(WEBLOCAL))
# Make vfsdata.c writable
#if exist $(VFSDIR)\vfsdata.c \
chmod 777 $(VFSDIR)\vfsdata.c
#
# Generate the configuration file needed by vfscomp
#
#echo [general] > $(CFGFILE)
#echo vfs_root_dir = $(WEBDST)>> $(CFGFILE)
#echo vfs_data_file = $(VFSDIR)\vfsdata>> $(CFGFILE)
#echo vfs_image_var = vfsimage>> $(CFGFILE)
#echo far_pointer = yes>> $(CFGFILE)
#echo compress = yes>> $(CFGFILE)
#echo [file] >> $(CFGFILE)
#echo $(sort $(WEBGLOBAL) $(WEBLOCAL)) | $(TR) -s " " "[\n*]" \
| $(SED) "s/gif/gif -u/g" \
>> $(CFGFILE)
#
# Create the local directory tree
#
#for %%f in ($(subst /,\,$(dir $(WEBGLOBAL)))) do \
if not exist $(WEBDST)\%%f mkdir $(WEBDST)\%%f
#
# Copy the WEB pages directory tree localy
#
#for %%f in ($(subst /,\,$(WEBGLOBAL))) do \
cp -rf $(WEBSRC)\%%f $(WEBDST)\%%f
#
# Generate the virtual file system
#
#$(TOOLDIR)/vfscomp $(subst \,/,$(CFGFILE))
#
# Delete the local directory tree
#
#delete the directory recursively exept the one in the exclusion list
#for %%f in ($(filter-out $(EXCLUSION), $(WEBDIR))) do \
if exist $(WEBDST)\%%f \
rm -rf $(WEBDST)\%%f
#delete the remaining files.
#for %%f in ($(subst /,\,$(WEBGLOBAL))) do \
if exist $(WEBDST)\%%f \
rm -f $(WEBDST)\%%f
#del $(subst /,\,$(CFGFILE))
When I build my code, I get this error
The syntax of the command is incorrect.
I have the feeling that some commands like #for #del #if exist are command that are not supported(or with a different syntax) in the gnu make.
I checked in the online GNU make documentation but I didn't found commands that are similar to those used below.
Is there any equivalent in gnu make to the command used in this part of the makefile?
Thanks in advance!
EDIT :
I removed the # and executed make. I can see when the message "The syntax of the command is incorrect" appear :
if exist ../Pa/Filesys\vfsdata.c \
chmod 777 ../Pa/Filesys\vfsdata.c
echo [general] > ../Pa/Filesys/vfs.cfg
echo vfs_root_dir = ../Pa/Filesys>> ../Pa/Filesys/vfs.cfg
echo vfs_data_file = ../Pa/Filesys\vfsdata>> ../Pa/Filesys/vfs.cfg
echo vfs_image_var = vfsimage>> ../Pa/Filesys/vfs.cfg
echo far_pointer = yes>> ../Pa/Filesys/vfs.cfg
echo compress = yes>> ../Pa/Filesys/vfs.cfg
echo [file] >> ../Pa/Filesys/vfs.cfg
echo behavior/datasync/datasync.htc behavior/defered/defered.htc behavior/inputs/indirect.htc behavior/inputs/inputs.htc behavior/progress/progress.htc behavior/slider/slBottom.gif behavior/slider/slLeft.gif behavior/slider/slRight.gif behavior/slider/slTop.gif behavior/slider/slider.htc css/env.css html/cfgmain.html html/changepass.html html/diagpa.html html/firmhlp.html html/firmware.html html/home.html html/logpage.html html/progressend.html html/progressstart.html html/soundhlp.html html/support.html html/uplmain.html html/uploadstart.html img/button.gif img/logo.gif index.html xslt/activate.xslt xslt/main.xslt xslt/netmenu.xslt xslt/page.xslt xslt/page_func.xslt xslt/progress.xslt xslt/tlmenu.xslt xslt/upload.xslt | tr -s " " "[\n*]" \
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
The syntax of the command is incorrect.
| sed "s/gif/gif -u/g" \
>> ../Pa/Filesys/vfs.cfg
for %%f in (.\ css\ img\ img\ xslt\ xslt\ xslt\ xslt\ xslt\ xslt\ xslt\ xslt\ html\ html\ html\ html\ html\ html\ html\ html\ html\ html\ html\ html\ behavior\slider\ behavior\slider\ behavior\slider\ behavior\slider\ behavior\slider\ behavior\datasync\ behavior\progress\ behavior\inputs\ behavior\inputs\ behavior\defered\) do \
It appear that the syntax error is somewhere on the line
echo $(sort $(WEBGLOBAL) $(WEBLOCAL)) | $(TR) -s " " "[\n*]" \
| $(SED) "s/gif/gif -u/g" \

To be clear, none of the commands you mention are make commands. They are all shell commands. Make is invoking a shell and passing those commands to the shell. As mentioned elsewhere, the "#" is a special command to make (supported by all POSIX-based make implementations including GNU make) that tells make to not print the command before sending it to the shell (the "#" is removed by make before sending the command to the shell).
Second, the error message "the syntax of the command is incorrect" is not anything GNU make ever prints. Either you have paraphrased the error message rather than repeating it verbatim (never a good idea when asking for help), or that message is being printed not by make but by some shell command that make invokes.

This will take a few iterations (especially since you haven't given us a complete sample).
There are two rules here; try them separately.
Try the second rule with only the first command:
# Make vfsdata.c writable
#if exist $(VFSDIR)\vfsdata.c \
chmod 777 $(VFSDIR)\vfsdata.c
Let us know the results of these experiments, and we'll go from there.
EDIT:
Interesting. I'd guess that either tr doesn't like your syntax, or the length of that command has exceeded some limit of your Make or OS.
Try doing it from the command line:
echo behavior/datasync/datasync.htc behavior/defered/defered.htc behavior/inputs/indirect.htc behavior/inputs/inputs.htc behavior/progress/progress.htc behavior/slider/slBottom.gif behavior/slider/slLeft.gif behavior/slider/slRight.gif behavior/slider/slTop.gif behavior/slider/slider.htc css/env.css html/cfgmain.html html/changepass.html html/diagpa.html html/firmhlp.html html/firmware.html html/home.html html/logpage.html html/progressend.html html/progressstart.html html/soundhlp.html html/support.html html/uplmain.html html/uploadstart.html img/button.gif img/logo.gif index.html xslt/activate.xslt xslt/main.xslt xslt/netmenu.xslt xslt/page.xslt xslt/page_func.xslt xslt/progress.xslt xslt/tlmenu.xslt xslt/upload.xslt | tr -s " " "[\n*]" \
| sed "s/gif/gif -u/g" \
>> ../Pa/Filesys/vfs.cfg
If that succeeds, it's a Make length limit; try with fewer file names.If it fails, try omitting the last term:
echo blah blah blah \
| sed "s/gif/gif -u/g"
Tell us the results, and we'll proceed...

Related

Makefile: command line argument -e of echo is passed to the file

In Makefile, when I write to file using echo -e "text" >, -e is also passed:
APIM_5 = echo -e "[Desktop Entry]\nName=$(MAIN)\nExec=$(MAIN)\nIcon=$(MAIN)\nType=Application\nVersion=1.0\nCategories=Utility;" > AppDir/usr/share/applications/$(MAIN).desktop;
But the file I echo into ($(MAIN).desktop) looks like below:
-e [Desktop Entry]
Name=main
Exec=main
Icon=main
Type=Application
Version=1.0
Categories=Utility;
All definitions together and how I call them:
APIM_1 = cd output;
APIM_2 = $(RM) AppDir appimage-build;
APIM_3 = mkdir -p AppDir/usr/bin AppDir/usr/share/applications AppDir/usr/share/icons/hicolor/256x256/apps/ AppDir/usr/lib;
APIM_4 = touch AppDir/usr/share/applications/$(MAIN).desktop;
APIM_5 = echo -e "[Desktop Entry]\nName=$(MAIN)\nExec=$(MAIN)\nIcon=$(MAIN)\nType=Application\nVersion=1.0\nCategories=Utility;" > AppDir/usr/share/applications/$(MAIN).desktop;
APIM_6 = cp $(MAIN) AppDir/usr/bin/;
APIM_7 = cp ../meta/icon/$(MAIN).png AppDir/usr/share/icons/hicolor/256x256/apps/;
APIM_8 = appimage-builder --skip-test;
appimage: all
$(APIM_1) $(APIM_2) $(APIM_3) $(APIM_4) $(APIM_5) $(APIM_6) $(APIM_7) $(APIM_8)
#echo Executing 'appimage' complete!
What causes this?

make on ubuntu vs Mingw32-make on windows -- unable to execute ! and other commands

The following structure works fine on a native ubuntu machine:
Makefile
Makefile-Debug
Makefile-impl
I call make with make CONF=Debug
Contents of Makefile are:
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin
build: .build-post
.build-pre:
.build-post: .build-impl
clean: .clean-post
.clean-pre:
.clean-post: .clean-impl
clobber: .clobber-post
.clobber-pre:
.clobber-post: .clobber-impl
all: .all-post
.all-pre:
.all-post: .all-impl
build-tests: .build-tests-post
.build-tests-pre:
.build-tests-post: .build-tests-impl
test: .test-post
.test-pre: build-tests
.test-post: .test-impl
help: .help-post
.help-pre:
.help-post: .help-impl
include Makefile-impl.mk <<----this file gets executed
include Makefile-variables.mk
Now, Makefile-impl.mk has the following line where it is checked whether the makefile corresponding to the Debug configuration -- Makefile-Debug -- actually exists:
.validate-impl:
#if [ ! -f Makefile-${CONF}.mk ]; \ <<------ this line produces an error in MinGW
then \
echo ""; \
echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \
echo "See 'make help' for details."; \
echo "Current directory: " `pwd`; \
echo ""; \
fi
#if [ ! -f Makefile-${CONF}.mk ]; \
then \
exit 1; \
fi
The above works perfectly fine on the native ubuntu machine.
When mingw32-make.exe processes the above on a windows machine, I obtain an error:
! was unexpected at this time.
mingw32-make: *** [Makefile-impl.mk:90: .validate-impl] Error 255
Is there any workaround for this? I also obtain other errors, such as for -n on the following different line in Makefile-impl.mk
#if [ -n "${MAKE_VERSION}" ]; then \
Here the error is:
-n was unexpected at this time.
mingw32-make: *** [Makefile-impl.mk:78: .depcheck-impl] Error 255

Converting Windows path to Unix path in a makefile

This question is related to Convert Cygwin path to Windows path in a makefile but it is not the same.
I need to convert a Windows path like:
C:\src\bin
into a Unix path like:
/c/src/bin
Inside a makefile, I can use the following code to convert such paths:
slashedpath = $(subst \\,\/,$(windowspath))
unixpath = $(shell cygpath -u $(slashedpath))
How can I perform the same conversion in a makefile that is being processed by GNU Make, when the cygpath function is not available?
p.s.
What if $(windowspath) contains multiple paths? How to convert them all ?
The makefile:
windowspath=C:\src\bin
unixpath=$(subst \,/,$(subst C:\,/c/,$(windowspath)))
all:
#echo "$(windowspath)"
#echo "$(unixpath)"
gives the output:
C:\src\bin
/c/src/bin
This will also work if $(windowspath) contains multiple paths. Tested on GNU Make 4.2.1 for i686-pc-cygwin, and also on GNU Make 3.81 built for i686-redhat-linux-gnu.
I was surprised that this worked.
Update: This second version will handle various drives such as C:, D:, etc. Some of these ideas are from Eric Melski's answer to In GNU Make, how do I convert a variable to lower case?. If the Makefile is:
DRIVE = $(subst \
A:,/a,$(subst B:,/b,$(subst C:,/c,$(subst D:,/d,$(subst \
E:,/e,$(subst F:,/f,$(subst G:,/g,$(subst H:,/h,$(subst \
I:,/i,$(subst J:,/j,$(subst K:,/k,$(subst L:,/l,$(subst \
M:,/m,$(subst N:,/n,$(subst O:,/o,$(subst P:,/p,$(subst \
Q:,/q,$(subst R:,/r,$(subst S:,/s,$(subst T:,/t,$(subst \
U:,/u,$(subst V:,/v,$(subst W:,/w,$(subst X:,/x,$(subst \
Y:,/y,$(subst Z:,/z,$1))))))))))))))))))))))))))
drive = $(subst \
a:,/a,$(subst b:,/b,$(subst c:,/c,$(subst d:,/d,$(subst \
e:,/e,$(subst f:,/f,$(subst g:,/g,$(subst h:,/h,$(subst \
i:,/i,$(subst j:,/j,$(subst k:,/k,$(subst l:,/l,$(subst \
m:,/m,$(subst n:,/n,$(subst o:,/o,$(subst p:,/p,$(subst \
q:,/q,$(subst r:,/r,$(subst s:,/s,$(subst t:,/t,$(subst \
u:,/u,$(subst v:,/v,$(subst w:,/w,$(subst x:,/x,$(subst \
y:,/y,$(subst z:,/z,$1))))))))))))))))))))))))))
windowspath = c:\src\bin D:\FOO\BAR
unixpath = $(subst \,/,$(call DRIVE,$(call drive,$(windowspath))))
all:
#echo Original: "$(windowspath)"
#echo Modified: "$(unixpath)"
then the output to make is:
Original: c:\src\bin D:\FOO\BAR
Modified: /c/src/bin /d/FOO/BAR
Update 2: The most straight-forward approach, and the most flexible, is to use a standard regular-expression handler such as perl or sed, if these are available. For example, with GNU sed, this Makefile will work as required:
windowspath = c:\src\bin D:\FOO\BAR
unixpath = $(shell echo '$(windowspath)' | \
sed -E 's_\<(.):_/\l\1_g; s_\\_/_g')
all:
#echo Original: "$(windowspath)"
#echo Modified: "$(unixpath)"
Explanation of sed:
s_\<(.):_/\l\1_g For every word starting with something like A: or a:, replace the start with /a.
s_\\_/_g Replace all backslashes with forward slashes.

How to call Makefile recipe/rule multiple times?

With the following example:
.PHONY: hook1 hook2
# Default target
all: hook1 hook2 hook1
echo "Calling all"
hook1:
echo "Calling hook1"
hook2:
echo "Calling hook2"
I got the output:
$ make
echo "Calling hook1"
Calling hook1
echo "Calling hook2"
Calling hook2
echo "Calling all"
Calling all
But I would expect it to call the rule hook1 two times. This is because on Latex, I need to call the same program with the same command line, multiple times. Then I would like to reuse the make rules. For example, I would expect the above minimal code to be ran as:
$ make
echo "Calling hook1"
Calling hook1
echo "Calling hook2"
Calling hook2
echo "Calling hook1"
Calling hook1
echo "Calling all"
Calling all
Which call the same rule twice. This is code bellow my full main Makefile code, if anyone is interested. I tried to create the dummy rules pdflatex_hook1 and pdflatex_hook2 so I could do the call hierarchy pdflatex_hook biber_hook pdflatex_hook, but this do not fooled make and it still ignoring my last call to pdflatex_hook2:
#!/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
Here when I call the rule make biber I got the output:
$ 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
Which is missing the second call to the rule pdflatex_hook2, only the first call to pdflatex_hook1 is being performed.`
I already know about latexmk and use it, but for biber above I would like to do these calls as they are. For latexmk I use this recipe/rule:
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)"
Related questions:
Change a make variable, and call another rule, from a recipe in same Makefile?
How to manually call another target from a make target?
multiple targets from one recipe and parallel execution
To answer your initial question:
.PHONY: hook1 hook2
# Default target
all: hook1a hook2 hook1b
echo "Calling all"
hook1a hook1b:
echo "Calling hook1"
hook2:
echo "Calling hook2"
Produces the following output:
echo "Calling hook1"
Calling hook1
echo "Calling hook2"
Calling hook2
echo "Calling hook1"
Calling hook1
echo "Calling all"
Calling all
As illustrated in make recipe execute twice
Based on #David White answer I fixed my main script with the double recursion:
#!/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

Syntax error: end of file unexpected

I define a function in Makefile
define write_file
for i in $( seq 1 10 )
do
echo "1234567" >> "tmp/test.txt"
done
endef
And
pre:
mkdir -p exe tmp
${call write_file}
But when I make pre,I got error:
mkdir -p exe tmp
for i in
/bin/sh: 1: Syntax error: end of file unexpected
Each line of a make-recipe is a single command that make runs in a single
new shell. So you need to make the body of the macro write_file into a single
shell command.
In addition, make expands anything of the unescaped form $(....),
treating .... as a defined or undefined make expression. So in your
case, make expands $( seq 1 10 ) to nothing. To stop make doing
that and let the shell expand $( seq 1 10 ), you need to escape $ for make,
which you do by writing $$ instead. The same goes for any $ in a make-recipe
that you intend to be expanded by the shell.
Putting these points together, you want:
define write_file
for i in $$( seq 1 10 ); \
do \
echo "1234567" >> "tmp/test.txt"; \
done
endef

Resources