GNU make: variable for command line arguments - makefile

How to pass the entire command line (including goals, link lines, make options etc) from top level make to recursive make:
targets : prerequisites
$(MAKE) $(this should expand to top level command line) additional_args
Thanks.

I think the closest you can get is using a combination of $(MAKE), which contains the exact filename make was invoked with, $(MAKECMDGOALS), which contains the goals you specified on the command line, and $(MAKEFLAGS), which contains any variable definitions and (a subset of) the switches specified on the command line.

The $(MAKE) macro is special and expands to include some relevant options. See the section How the MAKE variable works in the Make documentation for more details. However, this doesn't include the complete line including goals etc, and I'm not sure that is possible.
Usually I try to avoid using Make recursively, there's a good article about that here: Recursive Make Considered Harmful.

Related

What does "all-yes" mean in ffmpeg Makefile

In ffmpeg Makefile,
https://github.com/FFmpeg/FFmpeg/blob/master/Makefile#L37
https://github.com/FFmpeg/FFmpeg/blob/master/Makefile#L189
It defined phony targets "all" and "all-yes", but I can't find prerequisites and command of "all-yes" by searching whole ffmpeg directory. So can anyone help to explain what "all-yes" exactly means?
There is another "all" target in the "include $(SRC_PATH)/fftools/Makefile": https://github.com/FFmpeg/FFmpeg/blob/master/fftools/Makefile#L30
$(foreach P,$(AVPROGS-yes),$(eval $(call DOFFTOOL,$(P))))
all: $(AVPROGS)
fftools/ffprobe.o fftools/cmdutils.o: libavutil/ffversion.h | fftools
OUTDIRS += fftools
4.11 Multiple Rules for One Target
There can only be one recipe to be executed for a file. If more than one rule gives a recipe for the same file, make uses the last one given and prints an error message. (As a special case, if the file’s name begins with a dot, no error message is printed. This odd behavior is only for compatibility with other implementations of make… you should avoid using it). Occasionally it is useful to have the same target invoke multiple recipes which are defined in different parts of your makefile; you can use double-colon rules (see Double-Colon) for this.
There are two targets and make only uses the last one, so you could delete the "all-yes" or delete "all:all-yes" then use "make all" command, and it has no effect on the compilation. the command line "all:all-yes" is just ensure the "all" is the default target.

Finding dependencies by grep in Make

I'm working on a rather large project in pure C, and for various reasons we are not using CMake.
We have a good system which uses various shell commands to require very little maintanence. It will automatically find new headers and C files and add the headers to the dependencies and will compile the C files and include them in the output. However, we've gotten to the point where any changes we make to the header files becomes a problem because it requires a recompilation of the entire project, rather than just the C files that include it directly or indirectly.
I've worked on a system to ensure that the only header files which are added as dependencies are ones which are required by the C file itself (recursively up the tree).
I had thought I would be able to solve this myself, but it seems that make has rather inconsistent rules for expansion of variables.
The solution I came up with was to try to use ag and get all the includes out of the file. This works as intended, and I pipe it into tr so that I can ensure that no newlines are added, thereby messing up make. The issue that I'm having though is in determining which file to search in. This is the recipe that it's using for the section in question:
$(GAMEOBJDIR)/%.o : $(GAMEDIR)/%.c $(shell ag -o '(?<=(^#include "))(.*?)(?=("$$))' $(GAMEDIR)/%.c | tr '\n' ' ')
$(CC) $(CFLAGS) $(if $(RELEASE),$(RELFLAGS),$(DBFLAGS)) -c -o $# $<
The problem is that $(GAMEDIR)/%.c is expanding to src/game/%.c and not src/game/<filename>.c. I'm unsure how to fix this issue based on the expansion rules of make.
Once I can figure this out I'll be able to make sure this walks up the chain of header files too, but until I can get this figured out I have no reason to work on that.
Make's rules for expansion are completely consistent... but sometimes they aren't what people want. That's not the same thing :)
Rules for expansion are explained in the manual. In your case you're working with a prerequisite list which means the variables are expanded as the makefile is parsed. That includes the shell command and all other variables. Because you are working with a pattern rule, it means that at the time the makefile is parsed it doesn't match any particular file, it's just defining the pattern rule itself. So, % can't be expanded here. It will be expanded later, when make starts walking the dependency graph and trying to locate ways to build targets.
In general your method cannot work efficiently. You could defer the expansion of these parts of the prerequisites list using Secondary Expansion. However, that means every time make wants to TRY to use this pattern it will run these commands--that will just be slow.
Have you considered using a more standard way to manage detecting prerequisites? Try reading this description for example to see if it would work for you.

GNU Make does not execute first target

I am working on a complex make file that was written by other developers, this makefile also includes other makefiles.
I put a dumb rule at the beginning of the makefile, then invoked the makefile without specifying a target expecting that the first rule executes only (which echoes something), but I found that other rules got invoked.
I wonder is there any cases where other rules may get evaluated before the first rule (maybe because of includes or secondary expansions or others)?
The very first (non-pattern non-leading-dot) rule that make sees is the default target (by default). Whether that comes from the Makefile or some included makefile doesn't matter.
Additionally, a makefile can override that by setting the .DEFAULT_GOAL special variable.
This is discussed in the How make Processes a Makefile section of the GNU make manual.
By default, make starts with the first target (not targets whose names start with ‘.’). This is called the default goal. (Goals are the targets that make strives ultimately to update. You can override this behavior using the command line (see Arguments to Specify the Goals) or with the .DEFAULT_GOAL special variable (see Other Special Variables).

GNU Makefile "preprocessor"?

Is there an option to output the "preprocessed" makefile, something equivalent to the GCC's -E option?
I have a project comprised of an hierarchy of dozens of modules, each with its makefile. The build is invoked from a master makefile. That master makefile contains includes, variable definitions, command line option dependent variables, etc.
So, essentially, I am looking for the processed makefile, including all substitutions.
Not that I'm aware of. The closest thing you can get to this is the output from make -qp (or similar) which will dump the make database out at you.
Part of the problem with this request is that many of the substitutions/etc. happen as targets are processed and the list of targets isn't necessarily known without actually attempting a build (at least to an extent) so it isn't necessarily possible to fully expand/etc. a makefile in-place.
The make -d output is also useful for certain incidental information related to how make has processed the makefiles but doesn't contain makefile contents directly.
Remake might also be able to provide some extra useful information.
If you are looking for the computed value of some assembled/etc. global make variable then this blog post by Eric Melski is likely to be very helpful.
tl;dr It adds a target like this to the Makefile (though there's more magic in the blog post so I suggest reading it).
print-%:
#echo '$*=$($*)'
#echo ' origin = $(origin $*)'
#echo ' flavor = $(flavor $*)'
#echo ' value = $(value $*)'
Though in personal use I replaced that first line with something more like this
#echo '$*=$(subst ','\'',$($*))'
to keep the quoting of the result correct.

How such makefile works? (is it normal?)

I encountered such pattern in makefile
CXXOBJ = f1.o f2.o f3.o
$(CXXOBJ): %.o: %.cpp
g++ -c $< -o $#
f1.o: f1.cpp f1.hpp f2.hpp
f2.o: f2.cpp f2.hpp f3.hpp macros.h
f3.o: f3.cpp f3.hpp
It works (at least with GNU make 4.0).
It uses generic recipe from 4th line,
but in addition uses dependencies defined at the bottom.
Questions
Is it standard make behavior? (or is it specific to GNU-make?)
Is it standard way to write make file? (i.e. are people usualy doing it this way or is it something 'exotic'?)
How exactly does it work?
How does make combine 2 distinct rules for same file? (just append dependency list or something more?)
(I was browsing through GNU-make manual, but could not find relevant part)
This is called static pattern rules (https://www.gnu.org/software/make/manual/html_node/Static-Usage.html). It is specific to GNU make. It might be useful when different targets require different recipes to build, but match the same pattern.
As for third question, there are no distinct rules for the same file. Everything is quite well defined, each target have corresponding .cpp file.
GNU Make manual:
One file can be the target of several rules. All the dependencies
mentioned in all the rules are merged into one list of dependencies
for the target....
There can only be one set of commands to be executed for a file. If
more than one rule gives commands for the same file, make uses the
last set given and prints an error message...

Resources