| Introduction to build-root/Makefile |
| =================================== |
| |
| The vpp build system consists of a top-level Makefile, a data-driven |
| build-root/Makefile, and a set of makefile fragments. The various parts |
| come together as the result of a set of well-thought-out conventions. |
| |
| This section describes build-root/Makefile in some detail. |
| |
| Repository Groups and Source Paths |
| ---------------------------------- |
| |
| Current vpp workspaces comprise a single repository group. The file |
| .../build-root/build-config.mk defines a key variable called |
| SOURCE\_PATH. The SOURCE\_PATH variable names the set of repository |
| groups. At the moment, there is only one repository group. |
| |
| Single pass build system, dependencies and components |
| ----------------------------------------------------- |
| |
| The vpp build system caters to components built with GNU autoconf / |
| automake. Adding such components is a simple process. Dealing with |
| components which use BSD-style raw Makefiles is a more difficult. |
| Dealing with toolchain components such as gcc, glibc, and binutils can |
| be considerably more complicated. |
| |
| The vpp build system is a **single-pass** build system. A partial order |
| must exist for any set of components: the set of (a before b) tuples |
| must resolve to an ordered list. If you create a circular dependency of |
| the form; (a,b) (b,c) (c,a), gmake will try to build the target list, |
| but there’s a 0.0% chance that the results will be pleasant. Cut-n-paste |
| mistakes in .../build-data/packages/.mk can produce confusing failures. |
| |
| In a single-pass build system, it’s best to separate libraries and |
| applications which instantiate them. For example, if vpp depends on |
| libfoo.a, and myapp depends on both vpp and libfoo.a, it's best to place |
| libfoo.a and myapp in separate components. The build system will build |
| libfoo.a, vpp, and then (as a separate component) myapp. If you try to |
| build libfoo.a and myapp from the same component, it won’t work. |
| |
| If you absolutely, positively insist on having myapp and libfoo.a in the |
| same source tree, you can create a pseudo-component in a separate .mk |
| file in the .../build-data/packages/ directory. Define the code |
| phoneycomponent\_source = realcomponent, and provide manual |
| configure/build/install targets. |
| |
| Separate components for myapp, libfoo.a, and vpp is the best and easiest |
| solution. However, the “mumble\_source = realsource” degree of freedom |
| exists to solve intractable circular dependencies, such as: to build |
| gcc-bootstrap, followed by glibc, followed by “real” gcc/g++ [which |
| depends on glibc too]. |
| |
| .../build-root |
| -------------- |
| |
| The .../build-root directory contains the repository group specification |
| build-config.mk, the main Makefile, and the system-wide set of |
| autoconf/automake variable overrides in config.site. We'll describe |
| these files in some detail. To be clear about expectations: the main |
| Makefile and config.site file are subtle and complex. It's unlikely that |
| you'll need or want to modify them. Poorly planned changes in either |
| place typically cause bugs that are difficult to solve. |
| |
| .../build-root/build-config.mk |
| ------------------------------ |
| |
| As described above, the build-config.mk file is straightforward: it sets |
| the make variable SOURCE\_PATH to a list of repository group absolute |
| paths. |
| |
| The SOURCE\_PATH variable If you choose to move a workspace, make sure |
| to modify the paths defined by the SOURCE\_PATH variable. Those paths |
| need to match changes you make in the workspace paths. For example, if |
| you place the vpp directory in the workspace of a user named jsmith, you |
| might change the SOURCE\_PATH to: |
| |
| SOURCE\_PATH = /home/jsmithuser/workspace/vpp |
| |
| The "out of the box" setting should work 99.5% of the time: |
| |
| :: |
| |
| SOURCE_PATH = $(CURDIR)/.. |
| |
| .../vpp/build-root/Makefile |
| --------------------------- |
| |
| The main Makefile is complex in a number of dimensions. If you think you |
| need to modify it, it's a good idea to do some research, or ask for |
| advice before you change it. |
| |
| The main Makefile was organized and designed to provide the following |
| characteristics: excellent performance, accurate dependency processing, |
| cache enablement, timestamp optimizations, git integration, |
| extensibility, builds with cross-compilation tool chains, and builds |
| with embedded Linux distributions. |
| |
| If you really need to do so, you can build double-cross tools with it, |
| with a minimum amount of fuss. For example, you could: compile gdb on |
| x86\_64, to run on PowerPC, to debug the Xtensa instruction set. |
| |
| The PLATFORM variable |
| --------------------- |
| |
| The PLATFORM make/environment variable controls a number of important |
| characteristics, primarily: |
| |
| - CPU architecture |
| - The list of images to build. |
| |
| With respect to .../build-root/Makefile, the list of images to build is |
| specified by the target. For example: |
| |
| :: |
| |
| make PLATFORM=vpp TAG=vpp_debug install-deb |
| |
| builds vpp debug Debian packages. |
| |
| The main Makefile interprets $PLATFORM by attempting to "-include" the |
| file /build-data/platforms.mk: |
| |
| :: |
| |
| $(foreach d,$(FULL_SOURCE_PATH), \ |
| $(eval -include $(d)/platforms.mk)) |
| |
| By convention, we don't define **platforms** in the |
| ...//build-data/platforms.mk file. |
| |
| In the vpp case, we search for platform definition makefile fragments in |
| .../vpp/build-data/platforms.mk, as follows: |
| |
| :: |
| |
| $(foreach d,$(SOURCE_PATH_BUILD_DATA_DIRS), \ |
| $(eval -include $(d)/platforms/*.mk)) |
| |
| With vpp, which uses the "vpp" platform as discussed above, we end up |
| "-include"-ing .../vpp/build-data/platforms/vpp.mk. |
| |
| The platform-specific .mk fragment |
| ---------------------------------- |
| |
| Here are the contents of .../build-data/platforms/vpp.mk: |
| |
| :: |
| |
| MACHINE=$(shell uname -m) |
| |
| vpp_arch = native |
| ifeq ($(TARGET_PLATFORM),thunderx) |
| vpp_dpdk_target = arm64-thunderx-linuxapp-gcc |
| endif |
| vpp_native_tools = vppapigen |
| |
| vpp_uses_dpdk = yes |
| |
| # Uncoment to enable building unit tests |
| # vpp_enable_tests = yes |
| |
| vpp_root_packages = vpp vom |
| |
| # DPDK configuration parameters |
| # vpp_uses_dpdk_mlx4_pmd = yes |
| # vpp_uses_dpdk_mlx5_pmd = yes |
| # vpp_uses_external_dpdk = yes |
| # vpp_dpdk_inc_dir = /usr/include/dpdk |
| # vpp_dpdk_lib_dir = /usr/lib |
| # vpp_dpdk_shared_lib = yes |
| |
| # Use '--without-libnuma' for non-numa aware architecture |
| # Use '--enable-dlmalloc' to use dlmalloc instead of mheap |
| vpp_configure_args_vpp = --enable-dlmalloc |
| sample-plugin_configure_args_vpp = --enable-dlmalloc |
| |
| # load balancer plugin is not portable on 32 bit platform |
| ifeq ($(MACHINE),i686) |
| vpp_configure_args_vpp += --disable-lb-plugin |
| endif |
| |
| vpp_debug_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 \ |
| -fstack-protector-all -fPIC -Werror |
| vpp_debug_TAG_CXXFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 \ |
| -fstack-protector-all -fPIC -Werror |
| vpp_debug_TAG_LDFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 \ |
| -fstack-protector-all -fPIC -Werror |
| |
| vpp_TAG_CFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Werror |
| vpp_TAG_CXXFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Werror |
| vpp_TAG_LDFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Werror -pie -Wl,-z,now |
| |
| vpp_clang_TAG_CFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Werror |
| vpp_clang_TAG_LDFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -fstack-protector -fPIC -Werror |
| |
| vpp_gcov_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -fPIC -Werror -fprofile-arcs -ftest-coverage |
| vpp_gcov_TAG_LDFLAGS = -g -O0 -DCLIB_DEBUG -fPIC -Werror -coverage |
| |
| vpp_coverity_TAG_CFLAGS = -g -O2 -fPIC -Werror -D__COVERITY__ |
| vpp_coverity_TAG_LDFLAGS = -g -O2 -fPIC -Werror -D__COVERITY__ |
| |
| Note the following variable settings: |
| |
| - The variable \_arch sets the CPU architecture used to build the |
| per-platform cross-compilation toolchain. With the exception of the |
| "native" architecture - used in our example - the vpp build system |
| produces cross-compiled binaries. |
| |
| - The variable \_native\_tools lists the required set of self-compiled |
| build tools. |
| |
| - The variable \_root\_packages lists the set of images to build when |
| specifying the target: make PLATFORM= TAG= [install-deb \| |
| install-rpm]. |
| |
| The TAG variable |
| ---------------- |
| |
| The TAG variable indirectly sets CFLAGS and LDFLAGS, as well as the |
| build and install directory names in the .../vpp/build-root directory. |
| See definitions above. |
| |
| Important targets build-root/Makefile |
| ------------------------------------- |
| |
| The main Makefile and the various makefile fragments implement the |
| following user-visible targets: |
| |
| +------------------+----------------------+--------------------------------------------------------------------------------------+ |
| | Target | ENV Variable Settings| Notes | |
| | | | | |
| +==================+======================+======================================================================================+ |
| | foo | bar | mumble | |
| +------------------+----------------------+--------------------------------------------------------------------------------------+ |
| | bootstrap-tools | none | Builds the set of native tools needed by the vpp build system to | |
| | | | build images. Example: vppapigen. In a full cross compilation case might include | |
| | | | include "make", "git", "find", and "tar | |
| +------------------+----------------------+--------------------------------------------------------------------------------------+ |
| | install-tools | PLATFORM | Builds the tool chain for the indicated <platform>. Not used in vpp builds | |
| +------------------+----------------------+--------------------------------------------------------------------------------------+ |
| | distclean | none | Roto-rooters everything in sight: toolchains, images, and so forth. | |
| +------------------+----------------------+--------------------------------------------------------------------------------------+ |
| | install-deb | PLATFORM and TAG | Build Debian packages comprising components listed in <platform>_root_packages, | |
| | | | using compile / link options defined by TAG. | |
| +------------------+----------------------+--------------------------------------------------------------------------------------+ |
| | install-rpm | PLATFORM and TAG | Build RPMs comprising components listed in <platform>_root_packages, | |
| | | | using compile / link options defined by TAG. | |
| +------------------+----------------------+--------------------------------------------------------------------------------------+ |
| |
| Additional build-root/Makefile environment variable settings |
| ------------------------------------------------------------ |
| |
| These variable settings may be of use: |
| |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| | ENV Variable | Notes | |
| +======================+======================+=====================================================================================+ |
| | BUILD_DEBUG=vx | Directs Makefile et al. to make a good-faith effort to show what's going on in excruciating detail. | |
| | | Use it as follows: "make ... BUILD_DEBUG=vx". Fairly effective in Makefile debug situations. | |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| | V=1 | print detailed cc / ld command lines. Useful for discovering if -DFOO=11 is in the command line or not | |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| | CC=mygcc | Override the configured C-compiler | |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| |
| .../build-root/config.site |
| -------------------------- |
| |
| The contents of .../build-root/config.site override individual autoconf / |
| automake default variable settings. Here are a few sample settings related to |
| building a full toolchain: |
| |
| :: |
| |
| # glibc needs these setting for cross compiling |
| libc_cv_forced_unwind=yes |
| libc_cv_c_cleanup=yes |
| libc_cv_ssp=no |
| |
| Determining the set of variables which need to be overridden, and the |
| override values is a matter of trial and error. It should be |
| unnecessary to modify this file for use with fd.io vpp. |
| |
| .../build-data/platforms.mk |
| --------------------------- |
| |
| Each repo group includes the platforms.mk file, which is included by |
| the main Makefile. The vpp/build-data/platforms.mk file is not terribly |
| complex. As of this writing, .../build-data/platforms.mk file accomplishes two |
| tasks. |
| |
| First, it includes vpp/build-data/platforms/\*.mk: |
| |
| :: |
| |
| # Pick up per-platform makefile fragments |
| $(foreach d,$(SOURCE_PATH_BUILD_DATA_DIRS), \ |
| $(eval -include $(d)/platforms/*.mk)) |
| |
| This collects the set of platform definition makefile fragments, as discussed above. |
| |
| Second, platforms.mk implements the user-visible "install-deb" target. |
| |
| .../build-data/packages/\*.mk |
| ----------------------------- |
| |
| Each component needs a makefile fragment in order for the build system |
| to recognize it. The per-component makefile fragments vary |
| considerably in complexity. For a component built with GNU autoconf / |
| automake which does not depend on other components, the make fragment |
| can be empty. See .../build-data/packages/vpp.mk for an uncomplicated |
| but fully realistic example. |
| |
| Here are some of the important variable settings in per-component makefile fragments: |
| |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| | Variable | Notes | |
| +======================+======================+=====================================================================================+ |
| | xxx_configure_depend | Lists the set of component build dependencies for the xxx component. In plain English: don't try to | |
| | | configure this component until you've successfully built the indicated targets. Almost always, | |
| | | xxx_configure_depend will list a set of "yyy-install" targets. Note the pattern: | |
| | | "variable names contain underscores, make target names contain hyphens" | |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| | xxx_configure_args | (optional) Lists any additional arguments to pass to the xxx component "configure" script. | |
| | | The main Makefile %-configure rule adds the required settings for --libdir, --prefix, and | |
| | | --host (when cross-compiling) | |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| | xxx_CPPFLAGS | Adds -I stanzas to CPPFLAGS for components upon which xxx depends. | |
| | | Almost invariably "xxx_CPPFLAGS = $(call installed_includes_fn, dep1 dep2 dep3)", where dep1, dep2, and | |
| | | dep3 are listed in xxx_configure_depend. It is bad practice to set "-g -O3" here. Those settings | |
| | | belong in a TAG. | |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| | xxx_LDFLAGS | Adds -Wl,-rpath -Wl,depN stanzas to LDFLAGS for components upon which xxx depends. | |
| | | Almost invariably "xxx_LDFLAGS = $(call installed_lib_fn, dep1 dep2 dep3)", where dep1, dep2, and | |
| | | dep3 are listed in xxx_configure_depend. It is bad manners to set "-liberty-or-death" here. | |
| | | Those settings belong in Makefile.am. | |
| +----------------------+------------------------------------------------------------------------------------------------------------+ |
| |
| When dealing with "irritating" components built with raw Makefiles |
| which only work when building in the source tree, we use a specific |
| strategy in the xxx.mk file. |
| |
| The strategy is simple for those components: We copy the source tree |
| into .../vpp/build-root/build-xxx. This works, but completely defeats |
| dependency processing. This strategy is acceptable only for 3rd party |
| software which won't need extensive (or preferably any) modifications. |
| |
| Take a look at .../vpp/build-data/packages/dpdk.mk. When invoked, the |
| dpdk_configure variable copies source code into $(PACKAGE_BUILD_DIR), |
| and performs the BSD equivalent of "autoreconf -i -f" to configure the |
| build area. The rest of the file is similar: a bunch of hand-rolled |
| glue code which manages to make the dpdk act like a good vpp build |
| citizen even though it is not. |