本文介绍一下DPDK的makefile架构。
DPDK的makefile架构
DPDK采用GNUmakefile,并且在source_dir/mk/文件夹中有一系列预定义的文件帮助用户快捷的构建自己的DPDK app, lib等。
DPDK的编译
编译DPDK的方法
1 | #在DPDK的根目录执行: |
下面我们来看,运行make config 和make具体都干了些什么。
1.我们看根目录下的GNUmakefile
1 | RTE_SDK := $(CURDIR) |
首先将当前的根目录定义为RTE_SDK,并export;
然后将需要编译的buildtools, lib, drivers, app目录定义为ROOTDIRS-y,
将test目录定义为ROOTDIRS-。
然后include $(RTE_SDK)/mk/rte.sdkroot.mk
2.在rte.sdkroot.mk中,定义并export
- Q=‘@’
- RTE_SRCDIR=$(CURDIR)
- BUILDING_RTE_SDK = 1
- RTE_CONFIG_TEMPLATE = $(RTE_SRCDIR)/config/defconfig_$(T) 其中T为命令行传入
- RTE_OUTPUT = $(O) 如果命令行有”O=”则为命令行参数,否则为默认的$(RTE_SRCDIR/build)
- BUILDDIR = $(RTE_OUTPUT)/build
1 | MAKEFLAGS += --no-print-directory |
3.看make config T=x86_64-native-linuxapp-gcc的流程
在上一步中,我们看到在rte.sdkroot.mk中对T的定义进行了处理,对RTE_CONFIG_TEMPLATE进行了赋值,然后进入了config对应的目标1
2
3
config defconfig showconfigs showversion showversionum:
$(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkconfig.mk $@
即采用$(RTE_SDK)/mk/rte.sdkconfig.mk进行make config操作
make configinrte.sdkconfig.mk1
2
3
4
5
6
7
8
ifeq ($(RTE_CONFIG_TEMPLATE),)
config: notemplate
else
config: $(RTE_OUTPUT)/include/rte_config.h $(RTE_OUTPUT)/Makefile
@echo "Configuration done using" \
$(patsubst defconfig_%,%,$(notdir $(RTE_CONFIG_TEMPLATE)))
endif可以看到会执行,
$(RTE_OUTPUT)/include/rte_config.h和$(RTE_OUTPUT)/Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 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)/buildtools/relpath.sh $(abspath $(RTE_SRCDIR)) \
$(abspath $(RTE_OUTPUT)))
OUTPUT_RELPATH=$(shell $(RTE_SDK)/buildtools/relpath.sh $(abspath $(RTE_OUTPUT)) \
$(abspath $(RTE_SRCDIR)))
$(RTE_OUTPUT)/Makefile: | $(RTE_OUTPUT)
$(Q)$(RTE_SDK)/buildtools/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)/lib \
$(RTE_OUTPUT)/hostlib $(RTE_OUTPUT)/kmod $(RTE_OUTPUT)/build
$(Q)mkdir -p $(RTE_OUTPUT)/include
$(Q)$(RTE_SDK)/buildtools/gen-config-h.sh $(RTE_OUTPUT)/.config \
> $(RTE_OUTPUT)/include/rte_config.hscripts目录下relpath.sh接受两个路径作为输入,然后获取两个路径间的相对路径。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31$(RTE_OUTPUT):
$(Q)mkdir -p $@
ifdef NODOTCONF
$(RTE_OUTPUT)/.config: ;
else
# Generate config from template, if there are duplicates keep only the last.
# To do so the temp config is checked for duplicate keys with cut/sort/uniq
# Then for each of those identified duplicates as long as there are more than
# just one left the last match is removed.
$(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) ; \
config=$$(cat $(RTE_OUTPUT)/.config_tmp) ; \
echo "$$config" | awk -F '=' 'BEGIN {i=1} \
/^#/ {pos[i++]=$$0} \
!/^#/ {if (!s[$$1]) {pos[i]=$$0; s[$$1]=i++} \
else {pos[s[$$1]]=$$0}} END \
{for (j=1; j<i; j++) print pos[j]}' \
> $(RTE_OUTPUT)/.config_tmp ; \
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
endifCPP是Makefile内置变量,代表C语言预处理器,这里将会在RTE_OUTPUT目录下生成.config和.config.orig两个文件,最后生成了rte_config.h和Makefile文件。
生成完所有依赖文件后,执行make depdirs,这个目标在rte.sdkroot.mk中:1
2
3 make的流程
会执行rte.sdkroot.mk中的1
2
3
4# 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。1
2
3
4
5
6
7
8
9
10
11
build: $(ROOTDIRS-y)
@echo "Build complete [$(RTE_TARGET)]"
$(ROOTDIRS-y) $(ROOTDIRS-):
@[ -d $(BUILDDIR)/$@ ] || mkdir -p $(BUILDDIR)/$@
@echo "== Build $@"
$(Q)$(MAKE) S=$@ -f $(RTE_SRCDIR)/$@/Makefile -C $(BUILDDIR)/$@ all
@if [ $@ = drivers ]; then \
$(MAKE) -f $(RTE_SDK)/mk/rte.combinedlib.mk; \
fi