Some Basic Questions about Make: Compiling a Report with Figures - makefile

I'm trying to get Make working for recompiling reports every time a figure gets updated. I have the following code:
fig1.eps : images/code/fig1.m
matlab -nodesktop -nosplash -r 'run ./images/code/fig1.m'
How do I match on all figures -- like fig*.eps. I want to check all figures and update those that are not up to date.
When I run the command above, it continually reruns. This is to say: fig1.eps is generated. After I run make again, it should give me a message "fig1.eps is up to date." But it doesn't, the script reruns. Why is it doing this?

How do I match on all figures -- like fig*.eps. I want to check all figures and update those that are not up to date.
If you are using GNU's implementation of make, then you can use a pattern rule:
fig%.eps : images/code/fig%.m
matlab -nodesktop -nosplash -r 'run ./$<'
If you are using another version of make then the best you can do without writing a separate rule for each figure is probably to write a suffix rule, which will generate files in the same directory as the corresponding Matlab script, something like:
.m.eps :
matlab -nodesktop -nosplash -r 'run ./$<'
.SUFFIXES: .m .eps
Either of these options, however, requires you to somewhere specify all the figures to be created. At its simplest, you would just enumerate:
FIGS = fig1.eps fig2.eps fig5a.eps fig17.1.eps
... and specify the figures as prerequisites for the default (or some other) target:
all: $(FIGS)
With GNU make, however, if your Matlab files are arranged and named conducively then you could also use wildcard expansion or a shell command to obtain the result:
FIGS = $(shell cd images/code && ls fig*.m | sed 's/\.m$$/.eps')
When I run the command above, it continually reruns. This is to say: fig1.eps is generated. After I run make again, it should give me
a message "fig1.eps is up to date." But it doesn't, the script reruns.
Why is it doing this?
Very likely because your matlab command is not producing the target of the rule. For example, maybe it is creating a file of the same name, but in a different directory, or maybe it is not writing its output to a file at all. Possibly because some other rule is also being triggered that causes the .eps file to be removed.

Related

Makefile execution properly [duplicate]

I tried to use a make file in code::blocks but I am doing it wrong. I have the version installed with the compilers included. http://sourceforge.net/projects/codeblocks/files/Binaries/10.05/Windows/codeblocks-10.05mingw-setup.exe/download. What do I do with the make file? It starts with:
CC=gcc
best, US
You don't tend to execute the make file itself, rather you execute make, giving it the make file as an argument:
make -f pax.mk
If your make file is actually one of the standard names (like makefile or Makefile), you don't even need to specify it. It'll be picked up by default (if you have more than one of these standard names in your build directory, you better look up the make man page to see which takes precedence).
As paxdiablo said make -f pax.mk would execute the pax.mk makefile, if you directly execute it by typing ./pax.mk, then you would get syntax error.
Also you can just type make if your file name is makefile/Makefile.
Suppose you have two files named makefile and Makefile in the same directory then makefile is executed if make alone is given. You can even pass arguments to makefile.
Check out more about makefile at this Tutorial : Basic understanding of Makefile

Problem executing Makefile for FPGA poject-Vivado

Hi I am new to creating makefile.
I have written the following commands in a makefile but they do not seem to execute when i type make in my terminal.
However, if i type the command separately in the terminal, it works.
I am trying to open a vivado project in this tcl file and do some spyglass analysis on it and save the result in a txt file.The tcl file also runs properly if executed separately.
I cd to my project folder where all the files- sources folder, project folder, makefile is present. I named it "makefile" so that i can execute it by typing make in the terminal.The makefile contents are as follows.
.PHONY : vivado_open
vivado_open:
$(info Hello Make)
bsub -Is -q i_soc_rh7 -R "rusage[mem=32000, temp=1GB] affinity[core(8):membind=localonly]" vivado -nolog -nojou -mode batch -source vivado.tcl
Here is the result from the terminal
$make
Hello Make
make: Nothing to be done for `vivado_open'.
Sorry, but there has to be something else going on here, that you haven't told us about. It's simply not possible for you to get that output if you typed make with that makefile.
You are using a variable, not a target named vivado_open, so make would never print nothing to be done for 'vivado_open'. It would say instead something like: nothing to be done for ../projectfiles/test.prj
Further, you didn't answer my question about TABs vs. spaces. If both the info and bsub lines are indented with TABs, there's no possible way that make would print Hello Make, without also printing the bsub command and trying to run it.
You must have another makefile in your directory, maybe named Makefile or GNUmakefile, that is being used instead of makefile. Or maybe you have an environment variable like MAKEFILES set which is causing other makefiles to be read.
If none of those appear to be true, you'll have to run make -d and see if you can figure out what's happening. That output is far too large to post to StackOverflow, so you'll have to try to read it yourself.
EDITED
OK, the problem is you're using spaces to indent your rules. In make, all recipe lines must be indented with a hard TAB character. Normal spaces don't mean anything special to make. Basically your makefile is interpreted as if you'd written this:
.PHONY : vivado_open
vivado_open:
$(info Hello Make)
bsub -Is -q i_soc_rh7 -R "rusage[mem=32000, temp=1GB] affinity[core(8):membind=localonly]" vivado -nolog -nojou -mode batch -source vivado.tcl
This is why you get this message "nothing to be done": you haven't actually defined a recipe for vivaldo_open, so there is literally nothing that make knows to do to update that target.
As an aside, normally you would get a syntax error for the bsub line because make doesn't know what that is. However, if you look carefully at your line you'll see that it contains a :. So, make is interpreting this as a set of targets and set of prerequisites, like this:
bsub ... affinity[core(8) : membind=localonly]" vivado ... vivado.tcl
(make doesn't care about quotes or other special characters like [] etc.)
So. Be sure you indent your recipe lines with TAB characters and you'll be fine. This is probably the single most common issue people have with makefiles.

Force run a recipe (--assume-old=target)

I want to force a recipe for "output.file", even though it is up-to-date.
I have already tried make --assume-old=output.file output.file, but it does not run the recipe again.
In case you are curious: use case:
I want to use this together with --dry-run to find out the command that produce a target.
I ended up hiding the file to run make --dry-run output.file, but I was hoping for something more elegant + FMI: for future debugging makefile.
I think you're misunderstanding what that option does: it does exactly the opposite of what you hoped; from the man page:
-o file, --old-file=file, --assume-old=file
Do not remake the file file even if it is older than its dependenā€
cies, and do not remake anything on account of changes in file.
Essentially the file is treated as very old and its rules are
ignored.
You want output.file to be remade, so using -o is clearly not what you want.
There is no option in GNU make to say "always rebuild this target". What you can do is tell make to pretend that some prerequisite of the target you want to be rebuilt has been updated. See this option:
-W file, --what-if=file, --new-file=file, --assume-new=file
Pretend that the target file has just been modified. When used
with the -n flag, this shows you what would happen if you were to
modify that file. Without -n, it is almost the same as running a
touch command on the given file before running make, except that
the modification time is changed only in the imagination of make.
Say for example your output.file had a prerequisite input.file. Then if you run:
make -W input.file
it will show you what rules it would run, which would include rebuilding output.file.

Using a Makefile for Debain packages

I'm trying to put together a Makefile that will create a folder and clone repositories from GIT
I'm having trouble putting it all together so I'm starting with a generic Makefile
My makefile:
$(shell mkdir -p myDir)
$(shell git.sh)
The shell script that I am trying to get to invoke
#!/bin/sh
REPOSRC="my bitbucket repo URL"
LOCALREPO="myDir"
# We do it this way so that we can abstract if from just git later on
LOCALREPO_VC_DIR=$LOCALREPO/.git
if [ ! -d $LOCALREPO_VC_DIR ]
then
git clone $REPOSRC $LOCALREPO
else
cd $LOCALREPO
git pull $REPOSRC
fi
# End
When I run make I'm getting the following error:
Makefile:2: *** missing separator. Stop.
Also, is this the correct way to go about this task?
What you have is not a makefile. It's really a shell script written in makefile syntax (and, as you've discovered from the errors, not correct makefile syntax).
Make is a tool that allows commands to be run to update a set of target files, or not run if any of the target files don't need to be updated, based on comparing timestamps of the target files and their prerequisite files. These dependency relationships can be chained.
That's all that make is for.
To prototypical example is compiling a program: if any of the source files have been modified then you need to recompile the object files for those sources; if object files are updated then libraries might need to be re-created; if object or library files are updated then programs might need to be re-linked.
If your problem space doesn't map, or can't be made to map, to that mechanism, then make and makefiles are not the correct tool for the job you have in mind. Based on your description of your problem, make is not the right tool for this job.
You should just write a shell script, as you've basically done here already, and move forward.
If you do want to write a makefile you should spend some time understanding the syntax of makefiles and how they work, rather than just searching on Stack Overflow and trying to put together a makefile based on the answers. For example, try reading at least the introduction of the GNU make manual.
With $(shell ...) construct you substitute shell command output into the makefile. Of course after calling mkdir or invoking git the output is not a valid makefile.
Your makefile should be like this
all:
mkdir -p myDir
./git.sh
note that indentation after all: has to be done with tabs.
And it looks like you don't need make for your task. Just shell script would be enough.

gmake repeatedly creates and deletes batch-files before starting to work

I have a C-Project under Windows, which is built with a makefile.
Now I noticed, that after invoking gmake it takes like ~40 seconds until anything happens at all (until then there is not Output generated and nothing is happening).
I then used the -d flag to find the root of this problem - Running gmake with this flag generates the following output in those 40 seconds:
Creating temporary batch file C:\Users\User\AppData\Local\Temp\make564-1.bat
CreateProcess(C:\Users\User\AppData\Local\Temp\make564-1.bat, C:\Users\User\AppData\Local\Temp\make564-1.bat,...)
Cleaning up temporary batch file C:\Users\User\AppData\Local\Temp\make564-1.bat
This operation is happening again and again for the first 40 seconds (same bat-file over and over again).
The bat-file itself contains this:
#echo off
dir /b/a-d/-W/s .\*.c .\*.s
I don't think that this behaviour is normal (or is it?) - I mean it just creates the same file over and over again - I don't see any meaning in this.
The problem with this is just the time I (unnecessarily lose) with everytime I try to compile it.
Please provide the version of the tool you're using (in this case, GNU make), as well as the version of Windows and how you built the command for Windows (cygwin, mingw, MSVC, etc.)
make definitely never invokes a command like that. So that means something in your makefile is doing it. I suggest you look through your makefiles to find the line which contains that command.
My suspicion is that when you find it, it'll be something like this:
FOO = $(shell dir /b/a-d/-W/s .\\*.c .\\*.s)
This will re-evaluate the right-hand side every time the variable is used. So if you use that variable 20 times, it will run that command 20 times.
Change the = to := which will force the command to be run one time, when the variable is defined.
You might also consider using make's built-in $(wildcard ...) function, which is much faster and more portable than dir.

Resources