vpp源码分析(1) - Makefile

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

修改CMAKE_VERBOSE_MAKEFILE

备注:

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语法参考这里

你可能感兴趣的:(vpp源码分析(1) - Makefile)