How to use synchronization in makefile? - makefile

From the docs:
To avoid this you can use the --output-sync (-O) option. This
option instructs make to save the output from the commands it invokes
and print it all once the commands are completed. Additionally, if
there are multiple recursive make invocations running in parallel,
they will communicate so that only one of them is generating output at a
time.
So, given a makefile:
# A "recipe" that will always fail.
all::
#foo bar baz
And running, we get:
# A "non-synchronized" run
$ make
make: foo: Command not found
makefile:3: recipe for target 'all' failed
make: *** [all] Error 127
# Synchronize!
$ make --output-sync
makefile:3: recipe for target 'all' failed
make: *** [all] Error 127
Can you see a difference between the 2 runs?
Well, they both fail!
But, in the first run, Make let's us know why it failed, as it "let-through" the failing error(s) from the recipe:
make: foo: Command not found
But, for the second run, all we get, is:
makefile:3: recipe for target 'all' failed
make: *** [all] Error 127
But why? Why did it fail..Were there any debugging errors - from the recipe - that it failed? Sure there were! As evident by the 1st run! So, Why is Make so quick to hide them?
Now - that Make is hiding the error message - all we can do here, is: to guess!
We are very lucky here, because we know that "foo..." is an invalid command, so probably, somewhere, behind the curtains, this command was not acceptable, for this very reason.
But, consider this:
Imagine, when you have some typo in a command?
Now, imagine a typo in complex makefile!
Now, imagine the typo in a complex makefile run recursively!
Now, imagine all that in a makefile that runs for long period of times, outputting considerable amount of output!
How, then, could it be still justified for Make to "hide" some debugging errors, and show others?
(Versions note: All versions supporting synchronization, hence: 4.0 and up).

I had opened a bug report on this the other day here https://savannah.gnu.org/bugs/index.php?47365
It should be fixed now http://git.savannah.gnu.org/cgit/make.git/commit/?id=14b2d7effb0afd75dfd1ed2534e331784f7d2977
I guess you can build the latest version from source or wait until they make another official release. I'll be building from source as I need this fix ASAP :)

Related

Receiving message, "make: Nothing to be done for 'all.'" [duplicate]

This question already has an answer here:
make: Nothing to be done for `all'. when i tried to compile
(1 answer)
Closed 5 months ago.
Here is my snippet of code that's giving me this error, it is in Fortran. If you want more code I can amend this one if it helps.
[cba78749#bridges2-login012 ~]$ cd FFB0D
[cba78749#bridges2-login012 FFB0D]$ ls
BGKVDCF0D_commvar.f90 BGKVDCF0D_spat_oper_mod.o DGV_commvar.f90 DGV_miscsetup.o Makefile_debug bgkvdcf0d_spat_oper_mod.mod dgv_readwrite.mod gaussquad.mod nrroutines_mod.o
BGKVDCF0D_commvar.o BGKVDCF0D_time_integr_mod.f90 DGV_commvar.o DGV_mpiroutines.f90 Makefile_production bgkvdcf0d_time_integr_mod.mod dgv_sf02.mod gaussquad.o nrtype.f90
BGKVDCF0D_miscset.f90 BGKVDCF0D_time_integr_mod.o DGV_dgvtools_mod.f90 DGV_readwrite.f90 algama.f dgv_collision_mod.mod ffbM300.a makemake.perl nrtype.mod
BGKVDCF0D_miscset.o BGKVDCF0Driver.f90 DGV_dgvtools_mod.o DGV_readwrite.o algama.o dgv_commvar.mod gaussian_mod.f90 mkl_dft_type.mod nrtype.o
BGKVDCF0D_readwrite.f90 BGKVDCF0Driver.o DGV_distributions_mod.f90 DGV_sf02.f90 bgkvdcf0d_commvar.mod dgv_dgvtools_mod.mod gaussian_mod.mod mkl_dfti.mod nrutil.f90
BGKVDCF0D_readwrite.o DGV_collision_mod.f90 DGV_distributions_mod.o DGV_sf02.o bgkvdcf0d_miscset.mod dgv_distributions_mod.mod gaussian_mod.o nrroutines_mod.f90 nrutil.mod
BGKVDCF0D_spat_oper_mod.f90 DGV_collision_mod.o DGV_miscsetup.f90 Makefile bgkvdcf0d_readwrite.mod dgv_miscset.mod gaussquad.f90 nrroutines_mod.mod nrutil.o
[cba78749#bridges2-login012 FFB0D]$ make
make: Nothing to be done for 'all'.
I'm very new to PuTTY, and I'm trying to compile the code
It has nothing to do with putty. When you run make it looks for the Makefile (with exactly this capitalisation) and tries to make the first target it sees, in your Makefile that seems to be the target "all".
If the first target depends on other targets that haven't been met yet, it will also make those.
It is not uncommon to have the all target as the first target that simply depends on all the targets in the Makefile, that way running make will create all targets.
But if all targets are already made, meaning the files declared as target are newer than their own dependencies (sources), nothing needs to be made, and you get the message that you are inquiring about.
I strongly recommend reading up on the make command, for example here: https://linuxhint.com/gnu-make-tutorial/

Difficulties with a Makefile

So I'm trying to install the Homotopy Type Theory library for Coq from github following these instructions. Running the command etc/install_coq.sh sets it off messing with a bunch of files before it hits an error as so:
$ make clean
make: *** No rule to make target `clean'. Stop.
Apparently there's one or more bugs present within Makefile.am, and according to what I've read while googling the issue it's likely related to improper whitespace. Running make clean myself yields the same thing:
make: *** No rule to make target `clean'. Stop.
Meanwhile running make -f Makefile.am clean yields:
Makefile.am:4: *** missing separator. Stop.
Lines 4-6 in the file are simply:
if make_hoqide
bin_SCRIPTS += hoqide
endif
What's wrong with that that's causing the problem?
Makefile.am is generally paired with Makefile.in; these need to be processed with automake or configure before you get a usable real Makefile.
If you've got a script "autogen.sh" in your top-level source directory, run that
first, then configure:
$ ./autogen.sh
$ ./configure
$ make
This is, in fact, step 3 of the instructions that you linked to. Perhaps the install_coq.sh script isn't finding all of the dependencies that you need?

Specifying different GNUmakefile for GNU make command

I have two GNUmakefiles in my directory as follows,
GNUmakefile &
GNUmakefile2
Could someone please let me know the command I have to use, if I have to let the "make" command to process "GNUmakefile2" instead of "GNUmakefile".
I used the below command,
make -f GNUmakefile2
but in that case, I am getting the following errors,
This is gnustep-make 2.6.1. Type 'make print-gnustep-make-help' for help.
make[1]: ** No rule to make target `internal-master-tool-all'. Stop.*
make: ** [internal-all] Error 2*
I think it is considering GNUmakefile as makefile (when I use make with -f command), so it is checking for rules in GNUmakefile.
At present what I am doing is I am renaming the required file (which I want, make command to execute) to "GNUmakefile". And I am not getting any errors while executing "make" command, but I don't think this is the correct solution.
Please let me know which command I need to use for this scenario. Thanks for your help.
After checking Beta's solution (i.e.,but that makefile is invoking Make a second time, and the second Make process is probably reading GNUmakefile) what I have done is I renamed existing "GNUmakefile" to "GNUmakefile3".
So at present in my directory the following makefiles are present:- "GNUmakefile2" & "GNUmakefile3".
And then I executed the following command:- $ make -f GNUmakefile2
I recieved the below errors,
This is gnustep-make 2.6.1. Type 'make print-gnustep-make-help' for help.
make[1]: GNUmakefile: No such file or directory
make[1]: * No rule to make target `GNUmakefile'. Stop.
make: * [internal-all] Error 2
Please let me know what is the problem here
Your makefile includes two huge makefiles from the FSF. The second, library.make, contains this rule:
ifeq ($(GNUSTEP_MAKE_PARALLEL_BUILDING), no)
# Standard building
...
else
# Parallel building. ...
internal-library-all_:: $(GNUSTEP_OBJ_INSTANCE_DIR) $(OBJ_DIRS_TO_CREATE)
$(ECHO_NOTHING_RECURSIVE_MAKE)$(MAKE) -f $(MAKEFILE_NAME) ...
endif
and the first, common.make contains this assignment:
# The default name of the makefile to be used in recursive invocations of make
ifeq ($(MAKEFILE_NAME),)
MAKEFILE_NAME = GNUmakefile
endif
So try either make -f GNUmakefile2 GNUSTEP_MAKE_PARALLEL_BUILDING=no or make -f GNUmakefile2 MAKEFILE_NAME=GNUmakefile2, and see if that solves the problem.

make error: "make[1]: *** [directories] Error 1"

When I try to run "make all" on a makefile with some complexity I get this errors:
C:\BITCLOUD\BitCloud_PS_SAM3S_EK_1_10_0\BitCloud_PS_SAM3S_EK_1_10_0\Applications\ZAppSi\Dem o\SEDevice>make all
make -C makefiles/PC -f Makefile_PC_Gcc all APP_NAME=DemoSE
make[1]: Entering directory
'C:/BITCLOUD/BitCloud_PS_SAM3S_EK_1_10_0/BitCloud_PS_SAM3S_EK_1_10_0/Applications/ZAppSi/Demo/SEDevice/makefiles/PC'
A sintaxe do comando está incorrecta.
make[1]: *** [directories] Error 1
make[1]: Leaving directory
'C:/BITCLOUD/BitCloud_PS_SAM3S_EK_1_10_0/BitCloud_PS_SAM3S_EK_1_10_0/Applications/ZAppSi/Demo/SEDevice/makefiles/PC'
make: *** [all] Error 2
where the line
A sintaxe do comando está incorrecta.
translated to english means: "The syntax of the command is incorrect"
I already tried to change the project to different directories, check spaces in file names, using GNU make and also use MinGW make (mingw32-make) and the result is the same with both "make". I also checked for all files that are included in the makefile and they correspond.
Im not an expert in makefiles, so Im asking for help.
What is the main problem that occurs when make throws this type of error?
It is likely not make that throws this error, but a command executed by make returns with a nonzero exit status, in this case with status 1 (due to Error 1); then the top level make stops with Error 2. Note that make by default stops as soon as a command fails.
Since the output doesn't show what command was executed, there is no way to tell what went wrong exactly.
EDIT: from the GNU make manual:
-d Print debugging information in addition to normal processing.
The debugging information says which files are being considered
for remaking, which file-times are being compared and with what
results, which files actually need to be remade, which implicit
rules are considered and which are applied---everything inter‐
esting about how make decides what to do.
--debug[=FLAGS]
Print debugging information in addition to normal processing.
If the FLAGS are omitted, then the behavior is the same as if -d
was specified. FLAGS may be a for all debugging output (same as
using -d), b for basic debugging, v for more verbose basic
debugging, i for showing implicit rules, j for details on invo‐
cation of commands, and m for debugging while remaking make‐
files.
I suggest running make --debug=j to see the commands.

Get error for "make: Nothing to be done for 'target'"

Let me illustrate it with an example.
mkdir test
cd test
touch target
make target
This will result in: make: Nothing to be done for 'target'.
So make tells me there is nothing to do. This is because make did not find a rule to make target, but because the target already exists make tells me there is nothing to do.
Now, I don't want that. I want make to give me an error when it cannot find a rule for target, even though the target already exists.
I have tried the following:
echo '.DEFAULT:
echo make: *** No rule to make target `$#'. Stop.
false'> Makefile
But this does not stop the make when making multiple targets.
The problem is, that make assumes the target name is also a file which will be build by the given commands.
But sometimes this is not true (e.g. think of "clean").
To tell make that some targets don't build this file, you need to make them "phony". Put the following line into your Makefile:
.PHONY: target
If you think about it, you would end up with a chicken-and-egg situation (or infinite regress). Suppose you managed to have a rule that said 'You must have a rule to create target before it is legitimate', then you'd have a rule that says 'target depends on X' for some other file X. That's written:
target: X
command to build target from X
But then you'd be back to the starting point: you'd also want a rule to create X. How can you do that? You might have a rule that depends on nothing and magically creates the file X when it is needed:
X:
command to build X from nothing
Without a rule like that, you have an infinite regress.
So, make is designed to ensure that files exist and are up to date. If a file exists and there are no rules - implicit or explicit - to specify how it is made, then the file is up to date. What you are seeking to do is not possible.
Actually this sounds like a perfectly reasonable (if misguided ;-)) request. You will have to explicitly list every source file with a rule with an empty recipe though.
Here you go:
Makefile: ;
.PHONY: dodgy
dodgy%: dodgy; $(error You must provide a rule for $*)
%: dodgy% ;
The proof of the pudding:
$ rm aa
$ make aa
Makefile:4: *** You must provide a rule for aa. Stop.
$ touch aa
$ make aa
Makefile:4: *** You must provide a rule for aa. Stop.
Note that the line Makefile: ; is necessary. After all, the first thing make tries to do is rebuild the Makefile.
Note also that the catch-all pattern rule is non-terminal. This can be a massive performance hit. As the manual says about match anything rules "They are very useful, but it can take a lot of time for make to think about them."

Resources