Restart make target from failure point - makefile

Is there a way to restart a make target from the point it failed at before? Or perhaps some other technology that can achieve this?
If make testtarget failed at the line command b
testtarget:
command a
command b
command c
I would like to be able to run command b manually with whatever changes are necessary, then run make testtarget --resume or something like that.

I suggest you separate commands from recipe of testtarget target into separate recipes. Something like this:
# Separate recipe of 'testtarget' target into sub targets and order them.
testtarget: testtarget_a testtarget_b testtarget_c
testtarget_c:|testtarget_b
testtarget_b:|testtarget_a
testtarget_a:; command a
testtarget_b:; command b || $(MAKE) testtarget_b_failed
testtarget_c:; command c
# Add commands to recipe of this target to fix failure of "command b"
testtarget_b_failed:;
.PHONY: testtarget_b_failed testtarget testtarget_a testtarget_b testtarget_c

Related

Modify working makefile to do pre-stage before compiling and linking

I'm using this makefile as an example:
https://gist.github.com/mihaitodor/bfb8e7ad908489fdf3ceb496573f306a
Before compiling/linking I need to do a pre-stage, consisting of cd to a directory and run a script. Without the pre-stage it compiles & links fine.
I think I need to change the all rule:
all : $(TESTS)
I have tried this:
all : cd /bla/bla ./my_script $(TESTS)
and I have tried this:
all :
cd /bla/bla ./my_script
$(TESTS)
but it stops the compile/linking stage.
Given the URL above, where should I insert my pre-stage?
The short answer is you should likely create a new recipe, and make any bottom level target that is dependent on your script running be dependent on it. Something like:
.ran_my_script: $(GTEST_SRCS_)
cd /bla/bla ./my_script
touch $#
test_mihai.o gtest_main.o gtest.o : .ran_my_script
This way it will run your script before it attempts to generate any of the listed targets. It then touches a file $# (.ran_my_script). This will then be newer than any of the .o files meaning the script will not rerun unless someone modifies one of the scripts dependencies (i.e. $(GTEST_SRCS_)). You'll have to figure out what artifcats are actually dependent on your script, and what artifacts your script is dependent on.
Notice that if any of the sources change, then .ran_my_script will be considered out of date, as will anything that depends on it. This means that if you modify any source, it will rebuild all .o files. I'm assuming this is what you want.
Because I'm assuming you're new to makefiles, I will point out two things: first $# resolves to the target name (.ran_my_script in the above example), and second, that the last line of this causes .ran_my_script to be a dependency of test_mihai.o and friends -- but because it does not have any recipes associated with it, this line does not override any other recipes against the same targets specified prior to or later on in the makefile.
As to why what you were doing doesn't work:
all: cd /bla/blah ./my_script $(TESTS)
indicates that the target all is dependent on the targets cd, /bla/bla, ./my_script, and $(TESTS). It will attempt to build all of these before it builds all. Of course, you likely do not have a rule to build cd, etc, so this will fail.
Your next example,
all :
cd /bla/bla ./my_script
$(TESTS)
You create a target all, with two recipes. First, it will attempt to run your script, and then it will attempt to run whatever $(TESTS) resolves to. Notice that $(TESTS) in this case is not a bash command, so this would fail as well.
You might be tempted to do something like this:
all : $(TESTS)
cd /bla/bla ./my_script
but this would cause your script to be run as part of the all target, which runs after everything in $(TESTS) has already been completed.

How can I pass arguments to a make rule?

Suppose I had a python project that uses make to install. I want to be able to run the project without installing it first. So I created this make rule:
run:
#echo "Running projectname"
#PYTHONPATH=${PYTHONPATH}:$(abs_srcdir)/..; ./projectname
Where ./projectname runs a simple python script that sets up and runs the project, but that's not important here. Like that, I can simply execute make run in the root folder of the project to execute and test my application, which works perfectly fine. Now, I want to pass some command line arguments to the program. I tried make run --help, which just printed make's help text. Running make run -- --help printed
Running projectname
make: *** No rule to make target '--help'. Stop.
The application is run, and after I exit it, make tries to execute a target --help.
Now, how can I pass for example a --help argument to my application through make ?
make run ARGS=“arg1 arg2”
$(ARGS) in your makefiles would be expanded to what you have passed.

How to save and return exit code in makefile target

I have a make target that looks something like this:
.PHONY: run-my-test
run-my-test: all
run_test_suite.sh --all --log-to-file
post_process_logs.sh
If a test case fails, the exit code of run_test_suite.sh will cause Make to not continue with running post_process_logs.sh. This is a problem, because i want to get the processed logs even for failed tests. How should i update my target to do this?
I've thought of saving the exit code somehow and perhaps exit with it in the end of the target definition. Or do I split the calls up into separate targets?
I can add that I'm pretty much forced to do this from Make because of how our build system works. And I would prefer not having to add more targets as the make files tend to be cluttered with these as it is.
If you want the build to fail after running post_process_logs.sh, put both commands in the same entry.
.PHONY: run-my-test
run-my-test: all
run_test_suite.sh --all --log-to-file; \
e=$$?; \
post_process_logs.sh; \
exit $$e
The exit status of run_test_suite.sh is saved in the shell variable e, which is used as the argument to exit after post_process_logs.sh to set the exit status of the overall command.

Ignore clean command in Makefile

I have a project to compile with a lot of makefiles including a clean command. That's why i always have to start over again if there is an error (because the clean command is called in many Makefiles)
Question:
Is there any possibility to tell make to ignore the clean command? I would have to touch > 100 Makefiles otherwise. I would like make to start on the last error, not compiling all done stuff again
Example Makefile entries:
clean: cleansubdirs $(DIR) $(DIR1)
$(DIR2)
It's possible to redefine the recipe of an explicit target as simple as that:
noclean.mk
clean:;
cleansubdirs:;
# more stuff...
Now run make -f Makefile -f noclean.mk and it will work without actual cleaning files. However, make will issue several warnings about "overriding/ignoring old recipes".

How can I ctreate a simple makefile for minGW + gfortran

I am absolutely new in gfortran+minGW.
I need to create makefile.
When I run
$ gfortran -c q.f
All is ok!
But how can I run makefile like this?
CC = gfortran
q.o : q.f
$(CC) -c q2.o q2.f
I receive error “CC: command not found”.
(OS – Win 7 (64))
Tanks!!!
It kind of looks like you're trying to run the makefile as a regular script. Try
$ make
or
$ make -f mymakefilename
if you named the file something other than "makefile" or "Makefile".
You can potentially just execute the makefile, but if so you need a "shebang" line, something like
#!/usr/bin/make
at the top of the file, but frankly hardly anyone uses that option. Just use the make(1) command.
Update
It's because they're in the wrong order. Makefiles process (by default) the first target in the file. When you run make it sees the rule to make, q.o from q.f, it compiles it, and says, "Okay, I'm done."
If you put the q.exe target first, it says "Hmmm, I want to build q.exe and to do that I need a q.o. Do I have a q.o? No? Okay, hen I'll build a q.o. I have a rule for that -- I can build a q.o from q.f. okay, that's done. Now can I build q.exe? Oh, yes, I can. I'll build q.exe. Anything? Nope, I'm done."
If you were to use the commend
$ make q.exe
then you'd explicitly tell make to make q.exe, which would cause the same thing to happen, but better you should reorder your makefile and get used to the way they work.

Resources