编译DPDK的的方法是在根目录下执行:
make config T=x86_64-native-linuxapp-gcc
make
根目录下make使用的使GNUmakefile,内容如下:
RTE_SDK := $(CURDIR)
export RTE_SDK
#
# directory list
#
ROOTDIRS-y := lib drivers app
include $(RTE_SDK)/mk/rte.sdkroot.mk
这里include了mk目录下的rte.sdkroot.mk文件,首先该文件定义了几个变量:
RTE_SRCDIR = $(CURDIR)
export RTE_SRCDIR
BUILDING_RTE_SDK := 1
export BUILDING_RTE_SDK
#
# We can specify the configuration template when doing the "make
# config". For instance: make config T=x86_64-native-linuxapp-gcc
#
RTE_CONFIG_TEMPLATE :=
ifdef T
ifeq ("$(origin T)", "command line")
RTE_CONFIG_TEMPLATE := $(RTE_SRCDIR)/config/defconfig_$(T)
endif
endif
export RTE_CONFIG_TEMPLATE
#
# Default output is $(RTE_SRCDIR)/build
# output files wil go in a separate directory
#
ifdef O
ifeq ("$(origin O)", "command line")
RTE_OUTPUT := $(abspath $(O))
endif
endif
RTE_OUTPUT ?= $(RTE_SRCDIR)/build
export RTE_OUTPUT
# the directory where intermediate build files are stored, like *.o,
# *.d, *.cmd, ...
BUILDDIR = $(RTE_OUTPUT)/build
export BUILDDIR
export ROOTDIRS-y ROOTDIRS- ROOTDIRS-n
先看第一个make config语句的流程,首先在rte.sdkroot.mk里对T定义进行了处理,对RTE_CONFIG_TEMPLATE进行了赋值,然后进入config对应的目标:
.PHONY: config showconfigs showversion
config showconfigs showversion:
$(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkconfig.mk $@
可以看到这里采用mk目录下的rte.sdkconfig.mk进行make操作。
.PHONY: config
ifeq ($(RTE_CONFIG_TEMPLATE),)
config: notemplate
else
config: $(RTE_OUTPUT)/include/rte_config.h $(RTE_OUTPUT)/Makefile
$(Q)$(MAKE) depdirs
@echo "Configuration done"
endif
# generate a Makefile for this build directory
# use a relative path so it will continue to work even if we move the directory
SDK_RELPATH=$(shell $(RTE_SDK)/scripts/relpath.sh $(abspath $(RTE_SRCDIR)) \
$(abspath $(RTE_OUTPUT)))
OUTPUT_RELPATH=$(shell $(RTE_SDK)/scripts/relpath.sh $(abspath $(RTE_OUTPUT)) \
$(abspath $(RTE_SRCDIR)))
$(RTE_OUTPUT)/Makefile: | $(RTE_OUTPUT)
$(Q)$(RTE_SDK)/scripts/gen-build-mk.sh $(SDK_RELPATH) $(OUTPUT_RELPATH) \
> $(RTE_OUTPUT)/Makefile
# clean installed files, and generate a new config header file
# if NODOTCONF variable is defined, don't try to rebuild .config
$(RTE_OUTPUT)/include/rte_config.h: $(RTE_OUTPUT)/.config
$(Q)rm -rf $(RTE_OUTPUT)/include $(RTE_OUTPUT)/app \
$(RTE_OUTPUT)/hostapp $(RTE_OUTPUT)/lib \
$(RTE_OUTPUT)/hostlib $(RTE_OUTPUT)/kmod $(RTE_OUTPUT)/build
$(Q)mkdir -p $(RTE_OUTPUT)/include
$(Q)$(RTE_SDK)/scripts/gen-config-h.sh $(RTE_OUTPUT)/.config \
> $(RTE_OUTPUT)/include/rte_config.h
# generate the rte_config.h
scripts目录下relpath.sh接受两个路径作为输入,然后获取两个路径间的相对路径。
$(RTE_OUTPUT):
$(Q)mkdir -p $@
ifdef NODOTCONF
$(RTE_OUTPUT)/.config: ;
else
$(RTE_OUTPUT)/.config: $(RTE_CONFIG_TEMPLATE) FORCE | $(RTE_OUTPUT)
$(Q)if [ "$(RTE_CONFIG_TEMPLATE)" != "" -a -f "$(RTE_CONFIG_TEMPLATE)" ]; then \
$(CPP) -undef -P -x assembler-with-cpp \
-ffreestanding \
-o $(RTE_OUTPUT)/.config_tmp $(RTE_CONFIG_TEMPLATE) ; \
if ! cmp -s $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config; then \
cp $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config ; \
cp $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config.orig ; \
fi ; \
rm -f $(RTE_OUTPUT)/.config_tmp ; \
else \
$(MAKE) -rRf $(RTE_SDK)/mk/rte.sdkconfig.mk notemplate; \
fi
endif
CPP是Makefile内置变量,代表C语言预处理器,这里将会在RTE_OUTPUT目录下生成.config和.config.orig两个文件,最后生成了rte_config.h和Makefile文件。
生成完所有依赖文件后,执行make depdirs,这个目标在rte.sdkroot.mk中:
.PHONY: depdirs depgraph
depdirs depgraph:
$(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkdepdirs.mk $@
又对rte.sdkdepdirs.mk进行make,有:
# use a "for" in a shell to process dependencies: we don't want this
# task to be run in parallel.
.PHONY: depdirs
depdirs: $(RTE_OUTPUT)/.depdirs
$(RTE_OUTPUT)/.depdirs: $(RTE_OUTPUT)/.config
@rm -f $(RTE_OUTPUT)/.depdirs ; \
for d in $(ROOTDIRS-y); do \
if [ -f $(RTE_SRCDIR)/$$d/Makefile ]; then \
[ -d $(BUILDDIR)/$$d ] || mkdir -p $(BUILDDIR)/$$d ; \
$(MAKE) S=$$d -f $(RTE_SRCDIR)/$$d/Makefile depdirs \
>> $(RTE_OUTPUT)/.depdirs ; \
fi ; \
done
对变量ROOTDIRS-y中的变量进行遍历,也就是app,lib,driver,在构建目录建立相应的目录,然后分别调用它们原来目录下相应的Makefile去生成RTE_OUTPUT目录下的.depdirs。
至此,make config T=x86_64-native-linuxapp-gcc执行完毕。
对于make命令,则会执行rte.sdkroot.mk中的:
# all other build targets
%:
$(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkconfig.mk checkconfig
$(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkbuild.mk $@
首先会检查是否完成了.config的生成,然后对rte.sdkbuild.mk进行make。
.PHONY: all
all: build
.PHONY: build
build: $(ROOTDIRS-y)
@echo "Build complete [$(RTE_TARGET)]"
.PHONY: $(ROOTDIRS-y)
$(ROOTDIRS-y):
@[ -d $(BUILDDIR)/$@ ] || mkdir -p $(BUILDDIR)/$@
@echo "== Build $@"
$(Q)$(MAKE) S=$@ -f $(RTE_SRCDIR)/$@
细节尚待补充。