1 环境
目标机器:10.30.0.225
目录:/mnt/vdb1/vpp
2 在哪里编译?
cd /mnt/vdb1/vpp
[root@devel-ng-exporter-225 vpp]# make help
Make Targets:
install-dep - install software dependencies
wipe - wipe all products of debug build
wipe-release - wipe all products of release build
build - build debug binaries
build-release - build release binaries
build-coverity - build coverity artifacts
rebuild - wipe and build debug binares
rebuild-release - wipe and build release binares
run - run debug binary
run-release - run release binary
debug - run debug binary with debugger
debug-release - run release binary with debugger
test - build and run (basic) functional tests
[root@devel-ng-exporter-225 vpp]# make wipe
我们看到:
export WS_ROOT=$(CURDIR)
export BR=$(WS_ROOT)/build-root
PLATFORM?=vpp
......
$(BR)/.deps.ok:
ifeq ($(findstring y,$(UNATTENDED)),y) #备注 1
make install-dep
......
define make
#make -C ./build-root PLATFORM=vpp TAG=vpp_debug vpp-install
@make -C $(BR) PLATFORM=$(PLATFORM) TAG=$(1) $(2)
endef
build: $(BR)/.deps.ok
$(call make,$(PLATFORM)_debug,$(addsuffix -install,$(TARGETS)))
总结上面,简洁执行如下的命令:
build:
make -C ./build-root PLATFORM=vpp TAG=vpp_debug vpp-install
总结:
cd /mnt/vdb1/vpp/build-root
make PLATFORM=vpp TAG=vpp_debug vpp-clean
清理工作最好使用 : make PLATFORM=vpp TAG=vpp_debug vpp-wipe
make PLATFORM=vpp TAG=vpp_debug vpp-build
make PLATFORM=vpp TAG=vpp_debug vpp-install
file: /mnt/vdb1/vpp/build-root/Makefile
依赖关系:
vpp-build -> vpp-configure -> vpp-find-source -> external-find-source
3 寻找源文件
[root@devel-ng-exporter-225 build-root]# pwd
/mnt/vdb1/vpp/build-root
make PLATFORM=vpp TAG=vpp_debug -n
调试看看:
make PLATFORM=vpp TAG=vpp_debug vpp-build -n --debug -p --warn-undefined-variables
三个最适合用来调试的命令行选项:
--just-print(-n)
--print-database(-p)
--warn-undefined-variables
make PLATFORM=vpp TAG=vpp_debug vpp-find-source -ndp
调试: rm -f ccc && make PLATFORM=vpp TAG=vpp_debug vpp-find-source -ndp -f Makefile_1> ccc
457 # carry over packages dependencies to image install, wipe, pull-all, push-all
458 # ALL_PACKAGES = libmemif build external vpp sample-plugin src gmod extras vom
459 #
460 #
461 # vpp_configure_depend = external-install
462 # vom_configure_depend = vpp-install
463 # sample-plugin_configure_depend = vpp-install
464 # package_dependencies_fn = $(patsubst %-install, %, $(filter %-install,$($(1)_configure_depend)))
465 #
466 #
467 # p = libmemif build external vpp sample-plugin src gmod extras vom
468 # s = image_install wipe diff push-all pull-all find-source
469 #
470 #
471 $(foreach p,$(ALL_PACKAGES), \
472 $(if $($(p)_configure_depend), \
473 $(foreach s,$(TARGETS_RESPECTING_DEPENDENCIES), \
474 $(eval $(p)-$(s): \
475 $(addsuffix -$(s), $(call package_dependencies_fn,$(p)))))))
---------------------
下面这一条参考上面:
vpp-find-source: external-find-source
# Command line target.
# 对隐含规则的搜索已完成。
# 文件不存在。
# 文件尚未被更新。
- 1 find_source_for_package(%-find-source)
BUILD_ENV = \
export CCACHE_DIR=$(CCACHE_DIR) ; \
export PATH=$(wildcard /usr/lib*/ccache):$(TOOL_INSTALL_DIR)/bin:$${PATH} ; \
$(if $(call configure_var_fn,PATH), export PATH=$${PATH}:$(call configure_var_fn,PATH);,) \
export PATH="`echo $${PATH} | sed -e s/[.]://`" ; \
$(if $(not_native),export CONFIG_SITE=$(MU_BUILD_ROOT_DIR)/config.site ;,) \
set -eu$(BUILD_DEBUG) ; \
set -o pipefail
.PHONY: %-find-source
%-find-source:
$(find_source_for_package)
BUILD_ENV 执行如下:
export CCACHE_DIR=/mnt/vdb1/vpp/build-root/.ccache ;
export PATH=/usr/lib64/ccache:/mnt/vdb1/vpp/build-root/tools/bin:${PATH} ;
export PATH="`echo ${PATH} | sed -e s/[.]://`" ;
set -e表示一旦脚本中有命令的返回值为非0,则脚本立即退出,后续命令不再执行;
set -o pipefail表示在管道连接的命令序列中,只要有任何一个命令返回非0值,则整个管道返回非0值,即使最后一个命令返回0.
/mnt/vdb1/vpp/build-root/Makefile
如果我删除了 /mnt/vdb1/vpp/build-data/../build
make PLATFORM=vpp TAG=vpp_debug vpp-find-source
@@@@ Arch for platform 'vpp' is native @@@@
@@@@ Finding source for external @@@@
PACKAGE: external echo PACKAGE_SOURCE : build
@@@@ Makefile fragment found in /mnt/vdb1/vpp/build-data/packages/external.mk @@@@
@@@@ Fetching source: git clone https://github.com/FDio/build /mnt/vdb1/vpp/build-data/../build @@@@
正克隆到 '/mnt/vdb1/vpp/build-data/../build'...
Username for 'https://github.com': sssss
Password for 'https://[email protected]':
remote: Repository not found.
fatal: repository 'https://github.com/FDio/build/' not found
@@@@ No source for external in https://github.com/FDio @@@@
总结:
cd /mnt/vdb1/vpp/build-root
make PLATFORM=vpp TAG=vpp_debug vpp-find-source
vpp源文件在:/mnt/vdb1/vpp/src
external源文件在:/mnt/vdb1/vpp/build
两者是依赖关系 vpp-find-source: external-find-source
4 vpp-configure
vpp-configure: vpp-find-source external-install
external-install: external-build
external-build: external-configure
external-configure: external-find-source
4.1 external-configure 部分:
# Tools (e.g. gcc, binutils, gdb) required a platform to build for
check_platform = \
is_tool="$(is_build_tool)" ; \ is_tool=""
is_cross_package="$(findstring $(PACKAGE),$(CROSS_TOOLS))" ; \ is_cross_package=""
is_arch_native="$(if $(subst native,,$(ARCH)),,yes)" ; \ is_arch_native="yes"
if [ "$${is_tool}" == "yes" \
-a "$${is_cross_package}" != "" \
-a "$${is_arch_native}" != "" ]; then \
$(call build_msg_fn,You must specify PLATFORM for building tools) ; \
exit 1 ; \
fi ; \
: check that platform gcc can be found ; \
target_gcc=gcc ; \
if [ "$${is_arch_native}" != "yes" ] ; then \
target_gcc=$(TARGET)-gcc ; \
fi ; \
if [ "$${is_tool}" != "yes" \
-a "$${is_arch_native}" != "yes" \
-a ! -x "`which 2> /dev/null $${target_gcc}`" ] ; then \
$(call build_msg_fn, \
No cross-compiler found for platform $(PLATFORM) target $(TARGET); \
try make PLATFORM=$(PLATFORM) install-tools) ; \
exit 1 ; \
fi
configure_check_timestamp = \
@$(BUILD_ENV) ; \
$(check_platform) ; \
mkdir -p $(PACKAGE_BUILD_DIR) ; \
mkdir -p $(PACKAGE_INSTALL_DIR) ; \
conf="$(TIMESTAMP_DIR)/$(CONFIGURE_TIMESTAMP)" ; \
dirs="$(call package_mk_fn,$(PACKAGE)) \
$(SOURCE_PATH_BUILD_DATA_DIRS)/platforms/$(PLATFORM).mk \
$(wildcard $(call find_source_fn,$(PACKAGE_SOURCE))/cmake) \
$(shell find $(call find_source_fn,$(PACKAGE_SOURCE)) \
-name CMakeLists.txt) \
$(wildcard $(call find_source_fn, \
$(PACKAGE_SOURCE))$(PACKAGE_SUBDIR)/configure) \
$(MU_BUILD_ROOT_DIR)/config.site" ; \
if [[ $(call find_newer_fn, $${conf}, $${dirs}, $?) ]]; then \
$(configure_package) ; \
touch $${conf} ; \
else \
$(call build_msg_fn,Configuring $(PACKAGE): nothing to do) ; \
fi
.PHONY: %-configure
%-configure: %-find-source
$(configure_check_timestamp)
$(PACKAGE_BUILD_DIR) = /mnt/vdb1/vpp/build-root/build-vpp_debug-native/external
$(PACKAGE_INSTALL_DIR)= /mnt/vdb1/vpp/build-root/install-vpp_debug-native/external
上面 conf, dirs为空
Configuring external: nothing to do。
创建了上面两个目录:
/mnt/vdb1/vpp/build-root/build-vpp_debug-native/external 和 /mnt/vdb1/vpp/build-root/install-vpp_debug-native/external
4.2 external-build 部分
/mnt/vdb1/vpp/build-root/build-vpp_debug-native/external/.mu_build_build_timestamp
/mnt/vdb1/vpp/build-root/build-vpp_debug-native/external/.mu_build_configure_timestamp
if [[ $${conf} -nt $${comp}
filename1 -nt filename2,判断文件1是否比文件2新
如果我删除:/mnt/vdb1/vpp/build-root/build-vpp_debug-native/external/.mu_build_build_timestamp
build_package +++++++++++++
@@@@ Building external in /mnt/vdb1/vpp/build-root/build-vpp_debug-native/external @@@@
make[1]: 进入目录“/mnt/vdb1/vpp/build/external”
make check-rpm
make[2]: 进入目录“/mnt/vdb1/vpp/build/external”
make[2]: 警告: jobserver 不存在: 使用 -j1。添加 “+” 到父 make 的规则。
==========================================================
Out of date vpp-ext-deps package installed.
Installed: 未安装软件包 vpp-ext-deps
Needed: 19.08-11
Please upgrade by invoking 'make install-ext-deps'
from the top level directory.
==========================================================
make[2]: 离开目录“/mnt/vdb1/vpp/build/external”
make[1]: 离开目录“/mnt/vdb1/vpp/build/external”
在 /mnt/vdb1/vpp/目录下执行:
make install-ext-deps他会自动生成所有的依赖EPM包,例如DPDK。
并且会执行 rpm -Uih --force vpp-ext-deps-19.08-11.x86_64.rpm
安装DPDK。
[root@devel-ng-exporter-225 vpp]# rpm -qpl /mnt/vdb1/vpp/build/external/vpp-ext-deps-19.08-11.x86_64.rpm
/opt/vpp/external/x86_64
/opt/vpp/external/x86_64/bin
/opt/vpp/external/x86_64/bin/dpdk-pdump
/opt/vpp/external/x86_64/include/dpdk/rte_atomic_32.h
/opt/vpp/external/x86_64/lib/librte_pmd_enic.a
到此外部依赖就算安装完了,他被DPDK(19.08-11)下载下来,编译好之后又生成了一个RPM包,直接安装RPM包。 模块已经安装了 uio_pci_generic
4.3 configure_check_timestamp(vpp-configure)
创建两个目录:
/mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
/mnt/vdb1/vpp/build-root/install-vpp_debug-native/vpp
conf="/mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp/.mu_build_configure_timestamp"
dirs="/mnt/vdb1/vpp/build-data/packages/vpp.mk /mnt/vdb1/vpp/build-data/platforms/vpp.mk /mnt/vdb1/vpp/build-data/../src/cmake
/mnt/vdb1/vpp/build-data/../src/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/cmake/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/examples/handoffdemo/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/examples/sample-plugin/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/examples/sample-plugin/sample/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/pkg/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/plugins/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/plugins/abf/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/plugins/acl/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/plugins/avf/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/plugins/cdp/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/plugins/crypto_ia32/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/plugins/crypto_ipsecmb/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/vlib/CMakeLists.txt
/mnt/vdb1/vpp/build-data/../src/vlibapi/CMakeLists.txt
/mnt/vdb1/vpp/build-root/config.site" ;
Configuring vpp in /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
mkdir -p /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp ;
cd /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp && cmake3 -G Ninja
-DCMAKE_INSTALL_PREFIX:PATH=/mnt/vdb1/vpp/build-root/install-vpp_debug-native/vpp
-DCMAKE_C_FLAGS="-O0 -DCLIB_DEBUG -g -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Wall -Werror -fno-common"
-DCMAKE_LINKER_FLAGS="-O0 -DCLIB_DEBUG -g -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Wall -Werror -fno-common"
-DCMAKE_PREFIX_PATH:PATH="/opt/vpp/external/x86_64;/mnt/vdb1/vpp/build-root/install-vpp_debug-native/external"
-DCMAKE_PROGRAM_PATH:PATH="/opt/rh/devtoolset-7/root/bin"
/mnt/vdb1/vpp/build-data/../src
-- Found assembler: /opt/rh/devtoolset-7/root/bin/cc
-- Looking for libuuid
-- Found uuid in /usr/include
-- Intel IPSecMB found: /opt/vpp/external/x86_64/include
-- dpdk plugin needs libdpdk.a library - found at /opt/vpp/external/x86_64/lib/libdpdk.a
-- Found DPDK 19.5.0 in /opt/vpp/external/x86_64/include/dpdk
-- dpdk plugin needs numa library - found at /usr/lib64/libnuma.so
-- dpdk plugin needs libIPSec_MB.a library - found at /opt/vpp/external/x86_64/lib/libIPSec_MB.a
-- Looking for quicly
-- Found quicly in /opt/vpp/external/x86_64/include
-- rdma plugin needs libibverbs.a library - found at /opt/vpp/external/x86_64/lib/libibverbs.a
-- rdma plugin needs libmlx5.a library - found at /opt/vpp/external/x86_64/lib/libmlx5.a
-- Performing Test IBVERBS_COMPILES_CHECK
-- Performing Test IBVERBS_COMPILES_CHECK - Success
-- tlsmbedtls plugin needs mbedtls library - found at /usr/lib64/libmbedtls.so
-- tlsmbedtls plugin needs mbedx509 library - found at /usr/lib64/libmbedx509.so
-- tlsmbedtls plugin needs mbedcrypto library - found at /usr/lib64/libmbedcrypto.so
-- Looking for SSL_set_async_callback
-- Looking for SSL_set_async_callback - not found
-- Found PythonInterp: /usr/bin/python2.7 (found suitable version "2.7.5", minimum required is "2.7")
-- Configuration:
VPP version : 19.08-rc0~771-g874a31e
VPP library version : 19.08
GIT toplevel dir : /mnt/vdb1/vpp
Build type :
C flags : -Wno-address-of-packed-member -march=corei7 -mtune=corei7-avx -O0 -DCLIB_DEBUG -g -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Wall -Werror -fno-common
Linker flags : -O0 -DCLIB_DEBUG -g -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Wall -Werror -fno-common
Host processor : x86_64
Target processor : x86_64
Prefix path : /opt/vpp/external/x86_64;/mnt/vdb1/vpp/build-root/install-vpp_debug-native/external
Install prefix : /mnt/vdb1/vpp/build-root/install-vpp_debug-native/vpp
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
总结:
vpp-configure 安装好外部依赖主要是DPDK安装到/opt/vpp/external/x86_64。
然后cmake /mnt/vdb1/vpp/build-data/../src 源文件迁移到 /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
原则是新建立一个目录进行build事务,不要在原来的目录下执行。
5 vpp-build
/mnt/vdb1/vpp/build-root/Makefile
build_package = \
$(call build_msg_fn,Building $* in $(PACKAGE_BUILD_DIR)) ; \
mkdir -p $(PACKAGE_BUILD_DIR) ; \
cd $(PACKAGE_BUILD_DIR) ; \
$(if $($(PACKAGE)_build), \
$($(PACKAGE)_build), \
$(PACKAGE_MAKE))
翻译:
mkdir -p /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
cd /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
vpp_build = `cmake3 --build /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp`
如果定义了vpp_build就执行他,如果没有定义 就执行PACKAGE_MAKE
PACKAGE_MAKE = $(MAKE) -C $(PACKAGE_BUILD_DIR) $($(PACKAGE)_make_args) $(MAKE_PARALLEL_FLAGS)
touch ${comp}
touch /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp/.mu_build_build_timestamp
总结:
(/mnt/vdb1/vpp/build-root)
make PLATFORM=vpp TAG=vpp_debug vpp-build:
cd /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
cmake3 --build /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
make PLATFORM=vpp TAG=vpp_debug vpp-wipe:
rm -rf /mnt/vdb1/vpp/build-root/install-vpp_debug-native/vpp
/mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
make PLATFORM=vpp TAG=vpp_debug vpp-install:
mkdir -p /mnt/vdb1/vpp/build-root/install-vpp_debug-native/vpp
cmake3 --build /mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp -- install
为了能够显示详细信息:
[root@devel-ng-exporter-225 vpp]# pwd
/mnt/vdb1/vpp/build-root/build-vpp_debug-native/vpp
[root@devel-ng-exporter-225 vpp]# vim ./CMakeCache.txt
备注:
1 findstring
#$(findstring , )
#功能:在字串中查找字串。
#返回:如果找到,那么返回,否则返回空字符串。
str1 := a b c
str2 := b c
#第一个函数返回“a”字符串,第二个返回空字符串
all:
@echo $(findstring a,$(str1))
@echo $(findstring a,$(str2))
2 Ninja
Ninja 作为一个新型的编译工具,小巧而又高效,它就是为此而生
这个Google的程序员在开发Chrome的时候因为忍受不了Makefile的速度,自己重新开发出来一套新的控制编译的工具叫作Ninja,Ninja相对于Makefile这套工具更注重于编译速度。除了Chrome现在还有一些其他的比较大的项目也在开始使用Ninja,比如LLVM。我试用了一下感觉还是不错,比如编译Cmake时间大概是原来的1/4。
使用Ninja的一个问题就是需要生成这个build.ninja文件,对于大型项目来说这样一条一条地写配置文件是不可能的。幸好我们可以使用Cmake来生成这个配置文件,Cmake对应的是automake这样的东西。在Cmake的最新版本中已经支持参数Camke -G Ninja,Cmake会根据用户给定的CMakeLists.txt来生成build.ninja文件。而CmakeLists文件相对来说要简单一些,只要写清楚编译的可执行文件的名字,和其依赖的包含main函数的源文件。
写好CmakeList.txt后运行Cmake -G Ninja, 然后运行ninja all就能编译这个工程。具体的Cmake语法参考这里