Do I have to put .NOTPARALLEL in every makefile?
I'd like to put it in a top-level one and then propagate it down.
You can add:
MAKEFLAGS += -j1
to your top-level makefile and it should disable parallel builds in the sub-makes (note I didn't test this but it should work :)).
Related
I have a Makefile with tons of targets and would like for a certain script to get executed first, irrespective of what target is being called. I like to call it a global prerequisite.
I do not want to create a target for the script and set it as a prerequisite for all existing targets (which, as I said aren't few). Besides, someone else could add a target in future and not add my script as a prerequisite for their target, so the global prerequisite would take care of that.
Does GNU-make provide for a means to achieve this?
Another approach:
-include dummy
.PHONY: dummy
dummy:
run-the-script
Make will always attempt to rebuild any file which the makefile attempts to include (if it is out of date or does not exist). In this case there is no such file, and the rule to build it runs the script and does nothing else.
There is a solution without modifying your existing Makefile (main difference with the answers pointed to by tripleee). Just create a makefile containing:
.PHONY: all
all:
pre-script
#$(MAKE) -f Makefile --no-print-directory $(MAKECMDGOALS) MAKE='$(MAKE) -f Makefile'
post-script
$(MAKECMDGOALS): all ;
The only drawback is that the pre- and post- scripts will always be run, even if there is nothing else to do. But they will not be run if you invoke make with one of the --dry-run options (other difference with the answers pointed to by tripleee).
I have a project with a Makefile.am in each of the multiple subdirectories.
How do you propagate a AM_CFLAGS variable setting from that parent Makefile.am to other subdirectories' Makefile.am (sub-make)?
I'm aware of the following methods:
export a variable
include statement to a common ${top_srcdir}/Makefile_cflags.am file.
MAKEFLAGS
Recursive make is not an option and I'm shying away from include and MAKEFLAGS statement approaches.
The GNU manual doesn't seem to clearly outline about propagating compiler/linker settings to sub-make.
Turns out that this is a autoconf/configure.ac solution after all. GNU calls it outputting a variable.
To propagate the CFLAGS from the parent Makefile to each and every sub-makes (subdirectories' Makefile), I added the following lines toconfigure.ac`:
AC_SUBST(AM_CFLAGS)
Then for each sub-make, I added the following line to 'import' that variable:
AM_CPPFLAGS = #AM_CPPFLAGS#
Then executed an autogen.sh to rebuild both configure.in, Makefile.in and Makefile. Then executed configure and it propagated the AM_CFLAGS then and there.
Also a useful solution for AM_CPPFLAGS, AM_CXXFLAGS, and AM_LDFLAGS as well.
More details of AC_SUBST given here: https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html
Using make's ''Remaking Makefiles'' feature I am generating parts of my makefile with include directives (see Makefile: defining rules and prerequisites in recipes). Now I'm stuck with being unable to see how I can express dependencies between included makefiles. They seem to be all evaluated at once.
Consider the following minimal makefile that illustrates my problem:
all:
-include foo.make
-include bar.make
foo.make: Makefile
echo FOO:=blub bla baz > foo.make
bar.make: Makefile foo.make
echo BAR:=$(FOO) > bar.make
If I now run make I will get:
$ cat foo.make
FOO:=blub bla baz
$ cat bar.make
BAR:=
Why? Since bar.make depends on foo.make, shouldn't the evaluation of bar.make wait until it successfully included foo.make?
And how do I fix this problem and make sure that bar.make is either re-evaluated later or only evaluated once foo.make exists, is included and can define the variable BAR?
The reason I cannot combine foo.make and bar.make into a single makefile and rule is two-fold:
Firstly, in my real setup, bar.make depends on more intermediate targets which in turn transitively depend on foo.make. So at the time foo.make can be created, the content of bar.make cannot yet be made.
Secondly, in my real setup, foo.make and bar.make do not just define variables but also eval() define/endef blocks. So I have to write:
-include makefile_with_prerequisite_variables
define MYDEF
sometarget-$1: $(TARGET_$1_PREREQUISITES)
[...]
endf
-include makefile_with_eval_call_statements
The content of makefile_with_prerequisite_variables and makefile_with_eval_call_statements cannot go into a single makefile snippet:
If I would put makefile_with_eval_call_statements above MYDEF together with makefile_with_prerequisite_variables then the $eval( $call( MYDEF)) statements in it would not work because MYDEF is only declared afterward.
If I would put makefile_with_prerequisite_variables below MYDEF together with makefile_with_eval_call_statements then the recipes defined in MYDEF would not have proper prerequisits because the $(TARGET_$1_PREREQUISITES) variables would then be declared afterward by makefile_with_prerequisite_variables.
In summary, I need to include two different makefiles where one depends upon the other. I do not know how I can express this relationship such that the content of one makefile would only be created after the other makefile is up-to-date and included into the main makefile.
First, your makefile creation in this simple example can easily be fixed by escaping the value of $(FOO) so that it's not expanded when bar.make is created but rather deferred until it's read in. So:
bar.make: Makefile foo.make
echo 'BAR:=$$(FOO)' > $#
However, that might not be sufficient in your more complex real-life makefiles.
GNU make works like this: first parse all the makefiles. Then for every included makefile, treat it as a goal and try to build it (e.g., act as if the user invoked make include1.mk include2.mk include3.mk ...). Then at the end of that, if any of the included makefiles was rebuilt, re-exec ourselves and start the entire process over from scratch.
GNU make does NOT work like this: parse makefiles, try to rebuild the first included makefile and if it's rebuilt, re-exec; if it's not rebuilt go on to the next included makefile, etc.
A simple trick you can use if you have to have this type of order is to put the include of bar.make into foo.make:
all:
-include foo.make
foo.make: Makefile
printf -- '-include bar.make' > $#
echo FOO:=blub bla baz >> $#
bar.make: Makefile foo.make
echo 'BAR:=$$(FOO)' > $#
By doing this you ensure that if foo.make doesn't exist, make can't see the include of bar.make and so it won't try to build it. Only after the first re-exec will make see the include of bar.make and try to build it.
One thing: if you get the latest version of GNU make you no longer need to use the -include trick. You can just use include even with generated makefiles.
I have a makefile which calls multiple other makefiles.
I'd like to pass the -j param along to the other makefile calls.
Something like (make -j8):
all:
make -f libpng_linux.mk -j$(J)
Where $(J) is the value 8 from -j8. I absolutely swear I've done this before but I cannot locate my example.
$(MAKEFLAGS) seems to contain --jobserver-fds=3,4 -j regardless of what -j2 or -j8
Edit: Possible Solution:
Will post this as an answer soon.
It appears one solution to not worry about it. Include -j8 when you call the main makefile. The sub calls to make should look like this:
all:
+make -f libpng_linux.mk -j$(J)
Notice the "+" in front of make. I noticed make tossing a warning when I tried parallel builds: make[1]: warning: jobserver unavailable: using -j1. Add `+' to parent make rule.
Only certain flags go into $(MAKEFLAGS). -j isn't included because the sub-makes communicate with each other to ensure the appropriate number of jobs are occuring
Also, you should use $(MAKE) instead of make, since $(MAKE) will always evaluate to the correct executable name (which might not be make).
"Do not do that" is not always the answer, but in this case it is, at least for GNU make.
GNU make parent process has an internal jobserver. If top-level Makefile is run with -j, subprocess makes will talk to the jobserver and read a parallelism level from it, without an explicit -j.
Ongoing coordination with parent's jobserver is much better for core utilization. For example, during the same build with -j6, parent could be running 2 jobs and the child 4 more, next moment both could be running 3 jobs each, then a parent would run 1 and the child 5.
I'm trying to glue two build systems together. Both are recursive (rules in the makefile use make to call other makefiles to build components of the project).
I'll call them 'A' and 'B' where 'A' builds the application and 'B' builds libraries used by 'A'.
The top level makefile in A calls 'make TARGET=whatever' which means that all the recursively-invoked bits of the build inherit the value of TARGET as a read-only variable, including the build system from B, which is called as part of the recursive build.
I don't want this to happen in the build system for 'B' (which come from a different project) as the makefiles there use TARGET for their own purposes and the build fails since TARGET has the wrong value and is read-only.
I can only see two solutions to this, neither of which is palettable;
1) Rename TARGET to something else in the makefile in A that sets it and in the makefiles in A that use it, to avoid the clash with the lower levels of the build system.
2) Use the 'override' directive everywhere in the makefiles in B where the TARGET variable is set, to override its read-only status.
Anyone got any better ideas? - ideally, I want nothing to be inherited by the B's build system from A's, except those options I explicitly pass to the B build system from A.
Incidentally, I'm using GNU Make v3.80.
You could set MAKEOVERRIDES to nothing in the second-level makefile in A.
callb:
cd subdir && $(MAKE) MAKEOVERRIDES=
This passes down the normal commandline parameters like -k and -s but not commandline variable definitions.
Or you use the historical MFLAGS which is the same as MAKEFLAGS except MFLAGS doesn't contain the commandline variable definitions.
callb:
cd subdir && $(MAKE) $(MFLAGS)
Details about this two options can be read here: The GNU Make Manual
Perhaps you can use the "unexport" directive to prevent TARGET from being propagated to B's makefile?
At the point where build system A invokes build system B, do not use '${MAKE}' directly; invoke a shell script that invokes build system B (possibly after sanitizing the environment).
To achieve the behaviour where the commands are executed by 'make -n', prefix the command line in the makefile with '+' (similar to prefixing the line with '#' or '-').
It sounds like you have modified the A makefile to recursively invoke the B makefile, and thus your problem. Why not instead introduce a new toplevel makefile which recursively invokes the B makefile, and then recursively invokes the A makefile? For example, combined.mk:
all:
$(MAKE) -f Makefile.B
$(MAKE) -f Makefile.A
That way the B makefile inherits nothing from the A makefile.