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?
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
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.
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
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