What does "all-yes" mean in ffmpeg Makefile - ffmpeg

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.

Related

Matching a dependency using `subst` function in Makefile

I have a rule for the target
data/processed/21.12.2021/experiment6/written_piv21122021.005.exp6.mp4
in my makefile such that it has a dependency
data/raw/21.12.2021/experiment6/piv21122021.005.exp6.mov
Using subst functions, I'm trying to create the dependency by pattern matching as
%/written_*.mp4: \
$(subst processed,raw, $$*)/*.mov \
<do something>
However, the above rule can't find the *.mov dependency. i have tried many versions of $(subst processed,raw, $$*)/*.mov to match the dependency but didn't work.
How to do this? What is the correct syntax?
First, you can't do this:
%/written_*.mp4:
You can't combine a pattern % with a wildcard *. You have to realize that make works in two very discrete steps: first, all the makefiles are parsed and an internal representation of all the targets and prerequisites are constructed into a graph. Then, make walks that graph figuring out what needs to be built and how to build it, and running recipes.
Make variables, functions, and wildcards in targets and prerequisites are expanded when makefiles are parsed (in the first step). Automatic variables like $* are not set until a recipe is invoked (the second step), and patterns like % are not matched/expanded until make tries to decide how to build something (again in the second step).
So, a rule like:
%/written_*.mp4: $(subst processed,raw, $$*)/*.mov
can't work because the wildcard will expand to files matching the literal filename %/written_*.mp4 which clearly has no matches since you won't have a directory named %. In any event you can't use wildcards in targets because when make is parsing the makefile those targets won't exist (since that's what you want make to build) so the wildcards won't match anything. Also, $$* is the literal string $* and there is no processed string in that so the subst function will do nothing. And, even if /*.mov did match something it would put ALL the files matching that wildcard as prerequisites of every target so they'd all get rebuilt whenever any one changed.
And finally, you definitely should not use a backslash after your prerequisites: this just turns your recipe into prerequisites.
Your problem is very difficult to solve because your target and prerequisite differ in multiple distinct places and make doesn't support multiple % matching. You can get most of the way there with this:
data/processed/%.mp4: data/raw/%.mov
<do something>
However this is not quite right because the % in the target is written_... while in the prerequisite it's just ... and this is not possible to represent in make.
If you can rework the filenames so that instead of written_piv21122021.005.exp6.mp4 you can use piv21122021.005.exp6.written.mp4 (or even better you don't need the written_ prefix at all) then you can easily do this. If not you'll need to get very fancy to make this work.
Here is an imperfect kludge.
Delegate the work to another makefile I'll call adjunct.mk. In the main makefile:
data/processed/%.mp4:
#$(MAKE) -f adjunct.mk $#
And in adjunct.mk this ugly transformation:
.SECONDEXPANSION:
$(MAKECMDGOALS): $$(patsubst data/processed/%,data/raw/%,$$(subst written_,,$$(patsubst %.mp4,%.mov,$$#)))
...do whatever with $< and $#...
This incurs the usual cost of recursive Make: it blinds the higher-level Make to the dependency relations being tracked by the lower one. So if your Make must build that mov file, or you try to build the mp4 when the mov does not exist, then this solution will require some more careful pipefitting before it will work correctly.

Recipe that produces multiple targets

In our makefile, we have one recipe that links together all our object and library files to make an executable (an .elf file). As a side effect, this step also produces a map-file and an Intel .hex file:
$(ELF_FILE) : <list of dependencies here>
<linker command line>
Until now, since we never actually had a $(MAP_FILE) or a $(HEX_FILE) target, when ever another target depended on one of the $(ELF_FILE)'s side products, we simply declared it to be dependent on $(ELF_FILE), even if the recipe of that target didn't want to access the $(ELF_FILE) itself at all. For instance:
# Target that needs map-file, which is a side product of the $(ELF_FILE) target.
$(TARGET_THAT_NEEDS_MAP_FILE) : $(ELF_FILE)
<build-recipe>
# Target that needs hex-file, which is also a side product of the $(ELF_FILE) target.
$(TARGET_THAT_NEEDS_HEX_FILE) : $(ELF_FILE)
<build-recipe>
We have recently found out that a recipe can be used for more than one target, like so:
$(MAP_FILE) $(HEX_FILE) $(ELF_FILE) : <list of dependencies here>
<linker command line>
With this new-found knowledge, we figured we could get rid of the above "hack" and just directly state each target's direct dependencies:
$(TARGET_THAT_NEEDS_MAP_FILE) : $(MAP_FILE)
<build-recipe>
$(TARGET_THAT_NEEDS_HEX_FILE) : $(HEX_FILE)
<build-recipe>
Having implemented these changes, we now observe an odd effect that makes us suspect that we've either misunderstood this multiple-targets-one-recipe feature of make, or we're not using it correctly. The odd effect is that the recipe that produces the .elf, .map and .hex files now appears to run twice. This doesn't seem to have caused any immediate problems, but it does seem to indicate that something is fishy here. So my question, can our new approach work at all, or should we stick to the hack I described above?
EDIT: We're running our make in a multi-threaded manner (i.e. with -j).
It might be that when make is trying to update a target (whether it is $(MAP_FILE), $(HEX_FILE) or $(ELF_FILE), it does not know that its recipe will also update another target, therefore it starts a recipe for that one too, even if it's the same.
Of course, that would only happen when using the -j option. (Did you had the possibility to try without ?)
To illustrate :
$(TARGET): $(ELF_FILE) $(MAP_FILE)
<update target>
Here make will try to update $(ELF_FILE) and $(MAP_FILE) and fire the recipe twice. (That should also applies if the dependencies are on different target, as long as the targets are updated by a one execution of make and that there is no bottlenecks between them.
I'm not completely sure about that, though, make might be able to know that this is the same recipe.
======
This answer might be of use to you.
Specifically :
However, if your output files and your input file share a common base,
you CAN write a pattern rule like this:
%.foo %.bar %.baz : %.boz ; $(BUILDIT)
Strangely, for implicit rules with multiple targets GNU make assumes
that a single invocation of the recipe WILL build all the targets, and it will behave exactly as you want.
MadScientist
It refers to that part of the make manual :
Pattern rules may have more than one target. Unlike normal rules, this
does not act as many different rules with the same prerequisites and
recipe. If a pattern rule has multiple targets, make knows that the
rule’s recipe is responsible for making all of the targets. The recipe
is executed only once to make all the targets. When searching for a
pattern rule to match a target, the target patterns of a rule other
than the one that matches the target in need of a rule are incidental:
make worries only about giving a recipe and prerequisites to the file
presently in question. However, when this file’s recipe is run, the
other targets are marked as having been updated themselves.
EDIT:
Gnu Make has now gained a feature that would support this usecase (in version 4.3) : grouped explicit targets. It allows make to be aware that one recipe generate several targets, and it used like this (from the gnu make manual) :
foo bar biz &: baz boz
echo $^ > foo
echo $^ > bar
echo $^ > biz
foo, bar, and biz are generated by this rule (note the use of &: instead of :.
Full documentation : https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html ("Rules with Grouped Targets")

How to create a generic Makefile that checks sources for any given target name?

I want to have a generic Makefile that takes any target name and for that target name, checks to see if certain sources exist and then executes some commands. So for example I want to be able to enter:
make mytarget
then make should check to see if mytarget.src1 and mytarget.src2 exist, and if so execute some commands.
I have the following makefile:
%:
$(MYCOMMANDS) $*.scr1 $*.scr2
the only problem with this is that it doesn't check to see if $.scr1 and $.scr2 exist before running $(MYCOMMANDS). This is understandable because I haven't specified any dependencies. However when I try:
%: $*.src1 $*.src2
$(MYCOMMANDS) $*.scr1 $*.scr2
it now doesn't ever run $(MYCOMMAND) and says no rule to make the specified target.
Can someone please explain why in my second code make cannot find the target? Also, how can I achieve the behavior that I want?
The correct way to write a pattern rule is to use the pattern (%) in both the target and the prerequisites:
%: %.src1 %.src2
$(MYCOMMANDS) $^
See Pattern Rules in the GNU make manual. Also see Automatic Variables. By the way, the third paragraph in the second link will explain why your second attempt, using $* in the prerequisites, cannot work.
I was able to get the behavior I want using the MAKECMDGOALS variable. So:
$(MAKECMDGOALS): $(MAKECMDGOALS).src1 $(MAKECMDGOALS).src2
$(MYCOMMANDS) $(MAKECMDGOALS).scr1 $(MAKECMDGOALS).scr2
does what I am looking for. It checks to make sure .src1 and .src2 exist. If they don't make will report an error and if they do it will run $(MYCOMMANDS).

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).

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