After reading this answer for "How do I check if file exists in Makefile?" question, I decided to try. I have a file tact1.pdf in the same folder with the makefile.
Code:
FILE = 'tact1.pdf'
all:
ifneq ("$(wildcard $(FILE))","")
#echo "File exists"
else
#echo "No file"
endif
Output:
$ make
No file
I tried the full path to the file: same result. What's wrong? OS: Windows XP, using cygwin.
Drop the quotes around the filename. They might be okay in bash or perl, but in a makefile, they are considered the first and last characters of the filename.
FILE = tact1.pdf
Related
Remark: Put this Question on tex.stackexchange and was adviced to also ask here
Under Windows (using make from GnuWin32) i want to set my TEXINPUTS variable in a makefile
My Structure is as follows:
./
|-texmf_project/
|-Package.sty
|-main.tex
|-makefile
I want to be able to use Package.sty in my compilation process. The files look like this:
Package.sty contains:
\ProvidesClass{Package}[]
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{xcolor}
\newcommand{\red}[1]{\textcolor{red}{#1}}
main.tex contains:
\documentclass[11pt,a4paper]{report}
\usepackage{xcolor}
\usepackage{Package}
\begin{document}
Hello World\\
\red{Hello World}
\end{document}
Now i want to set the TEXINPUTS to include what is in ./texmf-project/
Hence my Makefile:
edit:
set TEXINPUTS=./texmf-project//;
pdflatex -synctex=1 -interaction=nonstopmode main.tex
del *.log
del *.aux
However this does not seem to make the location available for compilation.
However if I put the line
set TEXINPUTS=./texmf-project//; directly into the cmd and run make afterwards it works.
I believe I am making a mistake with the set, but I am far from beeing an expert.
Any helps or hints would be greatly appreciated.
Edit: Fixed a spelling mistake
Please remember that every recipe line is executed in a separate shell, so your set is executed in a different shell than pdflatex. Either put those two commands on a single line, or concatenate lines with \ so that lines are executed in a single shell, i.e.:
edit:
set TEXINPUTS=./texmf-project//; \
pdflatex -synctex=1 -interaction=nonstopmode main.tex
Edit:
Since this is Windows, it gets more complicated. Just adding \ and even & is not enough, since make will run it in a single line (through a batch file):
> type Makefile
all:
set TEXINPUTS=./texmf-project// & \
echo %TEXINPUTS%
> make -dr
...
Must remake target 'all'.
Creating temporary batch file C:\Users\user\AppData\Local\Temp\make11444-1.bat
Batch file contents:
#echo off
set TEXINPUTS=./texmf-project// & echo %TEXINPUTS%
...
ECHO is off.
...
Now, cmd.exe uses a line parser that expands variables when the line is parsed, so it first expands %TEXINPUTS% to an empty string (since it was not yet defined) and after that it evaluates the code which sets the variable. Therefore it is crucial that those commands are on separate lines to have variable set before it is used. The easiest way (if you use quite modern make) is including a .ONESHELL directive which would place all recipe into the batch and execute all at once:
> type Makefile
.ONESHELL:
all:
set TEXINPUTS=./texmf-project//
echo %TEXINPUTS%
> make -dr
...
Must remake target 'all'.
Creating temporary batch file C:\Users\user\AppData\Local\Temp\make29908-1.bat
Batch file contents:
#echo off
set TEXINPUTS=./texmf-project//
echo %TEXINPUTS%
...
./texmf-project//
...
Alternatively, if you don't somehow calculate the value, you can just set the variable at the make level (global or target level) and export it to the process, i.e.:
> type Makefile
all: export TEXINPUTS := ./texmf-project//
all:
echo %TEXINPUTS%
> make -dr
...
Must remake target 'all'.
Creating temporary batch file C:\Users\user\AppData\Local\Temp\make25392-1.bat
Batch file contents:
#echo off
echo %TEXINPUTS%
...
./texmf-project//
...
I have a Makefile like so:
T:=$(shell mktemp)
include ${T}
I:=$(shell rm ${T})
all:
echo done
In theory, mktemp should create an empty file and return its name. The next line should include that file. The following line should delete it.
When I run it I get:
make: *** No rule to make target `/tmp/tmp.Cwe7kiNBA3'. Stop.
If I comment out the third line like so:
T:=$(shell mktemp)
include ${T}
#I:=$(shell rm ${T})
all:
echo done
The Makefile works as expected, but leaves the temporary file behind.
Why doesn't the original example work as expected?
Your Makefile seems good without the include ${T} command. As described by GNU, the include directive is useful to:
suspend reading the current makefile and read one or more other
makefiles before continuing.
So, the following Makefile:
T:=$(shell mktemp)
I:=$(shell rm ${T})
all:
echo done
will produce this output and it will not report errors:
echo done
done
Make is trying to remake your included Makefile - for example, it works if you replace include with -include (which doesn't complain when the remake fails). You can fix it by adding an empty recipe for it: ${T}: ;.
I am trying to check the existence of a file using Makefile conditionals.
I've tried the following syntax which don't seem to work:
Path = /usr/local/myFileVer1
ifeq ($(wildcard $(Path)),)
version = 1
else
version = 2
endif
I thought the wildcard statement would evaluate to an empty string if the file did not exist so it would fall into the else statement. That isn't happening.
Any idea what else I can try?
You're close to the syntax. You can try something like this:
File = /usr/local/myFileVer1
ifeq ($(wildcard $(File)),)
all:
echo 1
else
all:
echo 2
endif
Or better, you can write two separate makefiles and include them at the right places:
File = /usr/local/myFileVer1
ifeq ($(wildcard $(File)),)
include Makefile1.mk
else
include Makefile2.mk
endif
Make, like all UNIX utilities, is case-sensitive. PATH is not the same as Path.
Also, you should not set the variable PATH as this will change the PATH when commands are invoked, and then your recipes will all fail.
I want to make automatically the documentation of my project with my makefile.
I also create a target doc (and a variable DOC_DIRECTORY = ../doc) to specify the directory of the documentation. In my doxygen file, I added a log file name "doxyLog.log" in the ../doc/ directory.
Here is my target definition :
#Creation of the Doxygen documentation
doc: $(DOC_DIRECTORY)/path_finder_doc
doxygen $(DOC_DIRECTORY)/path_finder_doc
#echo $(shell test -s ../doc/doxyLog.log; echo $$?)
ifeq ($(shell test -s ../doc/doxyLog.log; echo $$?),1)
#echo "Generation of the doxygen documentation done"
else
#echo "Error during the creation of the documentation, please check $(DOC_DIRECTORY)/doxyLog.log"
endif
To test if my check is working, I manually introduce an error in my documentation (a bad command like \retufjdkshrn instead of \return). But, when I launch the make doc, this error appears after the second time :
First make doc (with an error in the doc ) --> Generation of the doxygen documentation done
Second make doc (always the error in the doc) --> Error during the creation of the documentation, please check ../doc/doxyLog.log
I don't understand why, can someone help me please?
There appear to be two things wrong here, so parts of this answer must be guesswork.
First:
ifeq ($(shell test -s ../doc/doxyLog.log; echo $$?),1)
#echo "Generation of the doxygen documentation done"
As I understand test, it will return 0 if the file exists and 1 if the file does not exist. I suspect that you didn't test this before putting it into your makefile.
Second, you are confusing shell commands with Make commands. This:
ifeq ($(shell test -s ../doc/doxyLog.log; echo $$?),1)
#echo "Generation of the doxygen documentation done"
else
#echo "Error..."
endif
is a Make conditional. Make will evaluate it before running any rule. Since the log file does not yet exist, the shell command will return 1 (see First), the conditional will evaluate to true and the entire if-then-else statement will become
#echo "Generation of the doxygen documentation done"
This will become part of the rule before the rule is executed. On the next pass, the file already exists, the shell command returns 0 and the the statement becomes
#echo "Error..."
This explains why you're getting strange results.
If you want Make to report on the results of the attempt it's just made, you must put a shell conditional in a command in the rule:
doc: $(DOC_DIRECTORY)/path_finder_doc
doxygen $(DOC_DIRECTORY)/path_finder_doc
#if [ -s ../doc/doxyLog.log ]; then echo Log done; else echo error...; fi
I want to copy a file to a server using scp. But I want to use my current folder name in my makefile as variable.
I know I get my current path using $(CURDIR) but my local path isn't the same on my remote server.
E.g. my path is /Users/obstschale/Documents/Lab2/ and I want to copy Lab2.tar to user#server.au:/home/path/Lab2/.
copy2server:
echo $(CURDIR)
scp Lab2.tar user#server.au:/home/path/{folder}
I probably have to pipe $(CURDIR) into something and find my last folder.
Update: $(CURDIR) is the right variable. $(CURID) is the wrong one at least it didn't work for me.
I didn't have luck with the backtick syntax in makefiles (GNU Make 3.81) as Sylvain describes it. If it doesn't work for you either, use
$(shell basename $(CURDIR))
instead of
`basename $(CURDIR)`
I tried this rule:
test:
#echo $(CURDIR) # e.g. /tmp/foobar/blafoor/baz
#echo $(notdir $(CURDIR)) # gives "baz" here.
which worked fine for me.
maybe this is not intended to work, because notdir should
Extract the non-directory part of each file name.
If you're looking to strip the last folder name in the path out, there are a number of built in makefile functions. See http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_8.html#SEC74 for a quick overview of file operations.
copytoserver:
scp Lab2.tar user#server.au:/home/path/$(notdir $(CURDIR))
The key item of this is of course $(notdir $(CURDIR)). As you discovered, the $(CURDIR) contains the path to the directory in which the makefile was run, without the final '/'. The notdir function strips off everything up to and including the last '/' in a filename. This ends up stripping off everything but the final directory.
If $(CURDIR) still has the trailing '/', you can strip that off so the notdir function will do what you want like so:
$(notdir $(patsubst %/,%,$(CURDIR)))
Note that spacing in this case is critically important, placing a space before or after any of the commas will insert a space when it does the greedy pattern substitution.
You can use basename shell command to extract the last component part of $(CURDIR).
copyserver:
folder=`basename "$(CURDIR)"`; scp Lab2.tar user#server.au:/home/path/${folder}
As of GNU Make 4.3, you can use the native basename Make function, like so:
CURRENT_DIRECTORY := $(basename $(CURDIR))
$(info current directory is: $(CURRENT_DIRECTORY))
For more information about available functions, see the GNU Make info manual: info "(make) File Name Functions".