ffmpeg-makefile compilation analysis

This article is based on the version of ffmpeg-n4.4.1, and mainly analyzes the logic of Makefile in the ffmpeg project.

My environment is window10 + msys2, and I will explain it based on this environment.

"ffmpeg-configure Compilation Analysis" has explained the function of configure before, that is, according to different compilation environments, the corresponding configure.h and config.mak are generated. For example, if --toolchain=msvc is specified, the rules in the makefile will use cl.exe and link.exe of vs2019 to compile and link C code. If no toolchain is specified, gcc.exe in msys2 will be used by default to compile and link C code.

./configure --toolchain=msvc The differences between the execution and  ./configure the generated config.mak in msys2 are as follows.
 

As can be seen from the figure above, when configuring, you can use --toolchain to influence what kind of compiler is used when compiling.

Common errors:

1,Makefile:25: *** missing separator. Stop.

The above error is basically because the command to be executed in the makefile is not preceded by the tab key, but several spaces, and the editor is wrong.

Before starting the analysis, let’s talk about a makefile debugging technique. It is recommended to read "How to Debug MAKEFILE Variables"

make -f Makefile -f vars.mk HOSTPROGS

Here I have made some modifications to vars.mk, because the source vars.mk does not handle special characters, so direct echo will report an error. The variables of ffmpeg makefile have a lot of special characters. If I use warning to output, no error will be reported.

The content of the vars.mk file is as follows:

%:
    $(warning '$*=$($*)')
d-%:
#   @printf "%s =888 %s\n" "abc" $($*)
    $(warning '$*=$($*)')
#   @echo '$*=$($*)'
#   @echo '  origin = $(origin $*)'
#   @echo '   value = $(value  $*)'
#   @echo '  flavor = $(flavor $*)'

Now start to analyze the logic of the Makefile in ffmpeg from the first line of code. If you are not familiar with makefile, you can read "Write Makefile with Me" first.

Lines 1~2 of the code are as follows:

MAIN_MAKEFILE=1
include ffbuild/config.mak

Define MAIN_MAKEFILE, and then include config.mak. The config.mak file is full of variable definitions.
PS: MAIN_MAKEFILE can affect and change the SRC_PATH variable of config.mak, which is estimated to deal with different directories.

Lines 4~16 of the code are as follows:
 

vpath %.c    $(SRC_PATH)
vpath %.cpp  $(SRC_PATH)
vpath %.h    $(SRC_PATH)
vpath %.inc  $(SRC_PATH)
省略

This is actually the file search path when guiding make. For the usage of vpath, please read  "Write Makefile with Me (4)"

Lines 18-19 of the code are as follows:

TESTTOOLS   = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 audiomatch
HOSTPROGS  := $(TESTTOOLS:%=tests/%) doc/print_options

The above code is just declaring variables. It is recommended to read "The difference between := ?= += = in Makefile"

Lines 37~39 of the code are as follows:

# first so "all" becomes default target
all: all-yes

The first target (compilation target) is defined above. The syntax of the makefile is that if you do not specify a target when making, the first target that does not start with . is the default target. Recommended reading "makefile default target"

Finally, define all all-yes as a pseudo-target. False targets prevent files from being generated.
 

.PHONY: all all-yes alltools build check config testprogs

Spoiler here, because the all target depends on all-yes at this time, so make will look for the all-yes target, and the all-yes target is defined in  ffbuild/library.mak  , as follows

all-$(CONFIG_STATIC): $(SUBDIR)$(LIBNAME)  $(SUBDIR)lib$(FULLNAME).pc
all-$(CONFIG_SHARED): $(SUBDIR)$(SLIBNAME) $(SUBDIR)lib$(FULLNAME).pc

Lines 40~41 of the code are as follows:

include $(SRC_PATH)/tools/Makefile
include $(SRC_PATH)/ffbuild/common.mak

Two Makefiles are introduced. First, tools/Makefile has the following key points:

1. tools\Makefile There is a variable COMPILE_C inside which is more complicated, and is used to compile the C code in the tool directory.

I executed this command in the shell, make tools/target_dec_tiff_fuzzer.o, the * in the above picture is the content matched by %, so ∗ is * = tiff

The following is the specific value of the variable COMPILE_C

You can see that COMPILE_C actually executes 3 commands.

  • Use the cl.exe compiler to generate content, pass it to awk, and then output it to tools/target_dec_tiff_fuzzer.d, which will include the .d suffix file later.
  • printf Print the prompt information.
  • Officially compile the code of target_dec_fuzer.c with cl.exe,

2, -include $(wildcard tools/*.d) with a - in front to prevent error reporting, it is recommended to read the important knowledge points of " Difference between "include" and "-include" in a makefile" :

  1. The -D behind gcc.exe or cl.exe means to define a macro and pass it into the C code. For example -DFFMPEG_DECODER=tiff
  2. makefile syntax, ∗ is * is the content matched by %, so ∗ is * = tiff

There is another important knowledge point, the COMPILE_C variable used in tools/Makefile is defined in ffbuild/common.mak, but the lack of tools/Makefile is included before ffbuild/common.mak.

It should be noted that the grammatical order of the makefile is relatively vague. He first expands all the makefiles and then evaluates them. It is recommended to read "Differences in Makefile:= ?= += =", which fully demonstrates  = that  := makefile It is evaluated after expansion.

Next, analyze the imported  ffbuild/common.mak files, part of the code is as follows:

#
# common bits used by all libraries
#
DEFAULT_X86ASMD=.dbg
ifeq ($(DBG),1)
X86ASMD=$(DEFAULT_X86ASMD)
else
X86ASMD=
endif
ifndef SUBDIR
ifndef V
Q      = @
ECHO   = printf "$(1)\t%s\n" $(2)
BRIEF  = CC CXX OBJCC HOSTCC HOSTLD AS X86ASM AR LD STRIP CP WINDRES NVCC

The debugging of makefile is very troublesome. Here is a method. For example, if I want to know whether the condition of ifndef SUBDIR has been entered, I can use this command to  make -f Makefile -f vars.mk d-ECHO print out the ECHO variable.

The common.mak file is some common variable definitions, and the places that are not easy to understand are as follows:

1. Please look at the following code. For these rules, there is only one (COMPILEMMI) in the command, and the file name is not connected to it. It seems that you don’t know what file to compile. In fact, the file name to be compiled is in (COMPILE_MMI), followed by The file name is not connected, and it seems that I don’t know what file to compile. In fact, the file name to be compiled is (COMPILEM​MI), and the file name is not connected after it. It seems that I don’t know what file to compile. In fact, The name of the file to be compiled is in the (COMPILE_MMI) variable, pass the characters matched by the above % to (COMPILEMMI), you can print out (COMPILE_MMI), you can print (COMPILEM​MI), and you can print out (COMPILE_MMI) , you can know the specific logic.
 

%_mmi.o: %_mmi.c
   $(COMPILE_MMI)
%_msa.o: %_msa.c
   $(COMPILE_MSA)
%.o: %.c
   $(COMPILE_C)

2. Please look at the following code, there is one after the target  | , I don't know what it is for.

$(OBJS):     | $(sort $(dir $(OBJS)))
$(HOBJS):    | $(sort $(dir $(HOBJS)))
$(HOSTOBJS): | $(sort $(dir $(HOSTOBJS)))
$(SLIBOBJS): | $(sort $(dir $(S

Lines 98~107 of the code are as follows:

define DOSUBDIR
$(foreach V,$(SUBDIR_VARS),$(eval $(call RESET,$(V))))
SUBDIR := $(1)/
include $(SRC_PATH)/$(1)/Makefile
-include $(SRC_PATH)/$(1)/$(ARCH)/Makefile
-include $(SRC_PATH)/$(1)/$(INTRINSICS)/Makefile
include $(SRC_PATH)/ffbuild/library.mak
endef
$(foreach D,$(FFLIBS),$(eval $(call DOSUBDIR,lib$(D))))

The above code is particularly important, there is a command package DOSUBDIR. In this command package, the dependencies of FFmpeg class libraries (such as libavformat, libavcodec, libavutil, etc.) are defined by including files such as libavXXX/Makefile and library.mak.

Pay attention to see that the last  ffbuild/library.mak makefile is the last one to be included, and it specifically handles the files that were included before. DOSUBDIR is called in a foreach loop, for example:

libavdevice\Makefile It is defined in the file  DESC = FFmpeg device handling library , and then  library.mak the DESC variable will be used to expand it, as follows, the 42nd line of code in library.mak.
 

$(SUBDIR)lib$(FULLNAME).pc: $(SUBDIR)version.h ffbuild/config.sh | $(SUBDIR)
    $$(M) $$(SRC_PATH)/ffbuild/pkgconfig_generate.sh $(NAME) "$(DESC)"

Different class libraries have different DESC definitions. The DESC definition of libavformat\Makefile is as follows:

DESC = FFmpeg container format library

ffbuild/library.mak  is the most important file. It is the entry point of the make command. You can understand it as the entry function of the main() function. The first compilation command is run from here. What is the specific process? Please continue to read, as I said before, the Makefile in the root directory defines all: all-yes at the entry, so all is the default target of make, the default target.

all depends on all-yes, so it will cause   the following code in ffbuild/library.mak to be executed.

all-$(CONFIG_STATIC): $(SUBDIR)$(LIBNAME)  $(SUBDIR)lib$(FULLNAME).pc
all-$(CONFIG_SHARED): $(SUBDIR)$(SLIBNAME) $(SUBDIR)lib$(FULLNAME).pc

After the above $(CONFIG_STATIC) is expanded, it is yes or no, that is, all-yes. You can see that there are a bunch of prerequisites behind it, and this pile of prerequisites will lead to continue to look for dependencies, look for .o files, and .o files If it is not found, it will execute cl.exe or gcc.exe to compile the .o file from the C code. Probably such a logic. You can use make -n to view specific compilation commands.

So  ffbuild/library.mak  is the most important file.

The entry is found, and some other compilation rules can be checked by yourself. The makefile analysis is completed.

Download:

1. Download address of Makefile with my comments, Baidu network disk , extraction code: f5aj

Original  ffmpeg-makefile compilation analysis - Nuggets

★The business card at the end of the article can receive audio and video development learning materials for free, including (FFmpeg, webRTC, rtmp, hls, rtsp, ffplay, srs) and audio and video learning roadmaps, etc.

see below!

 

Guess you like

Origin blog.csdn.net/yinshipin007/article/details/132092127