Introduction to cmake and ninja
Cmake plus ninja is approximately equal to GNU autotools plus GNU make, respectively. Both cmake and GNU autotools support self and cross-compilation, checking for required components and versions.
For a decent-sized project - such as vpp - build performance is drastically better with (cmake, ninja).
The cmake input language looks like an actual language, rather than a shell scripting scheme on steroids.
Ninja doesn't pretend to support manually-generated input files. Think of it as a fast, dumb robot which eats mildly legible byte-code.
See the cmake website, and the ninja website for additional information.
vpp cmake configuration files
The top of the vpp project cmake hierarchy lives in .../src/CMakeLists.txt. This file defines the vpp project, and (recursively) includes two kinds of files: rule/function definitions, and target lists.
Rule/function definitions live in .../src/cmake/{*.cmake}. Although the contents of these files is simple enough to read, it shouldn't be necessary to modify them very often
Build target lists come from CMakeLists.txt files found in subdirectories, which are named in the SUBDIRS list in .../src/CMakeLists.txt
##############################################################################
# subdirs - order matters
##############################################################################
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
find_package(OpenSSL REQUIRED)
set(SUBDIRS
vppinfra svm vlib vlibmemory vlibapi vnet vpp vat vcl plugins
vpp-api tools/vppapigen tools/g2 tools/perftool)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
set(SUBDIRS vppinfra)
else()
message(FATAL_ERROR "Unsupported system: ${CMAKE_SYSTEM_NAME}")
endif()
foreach(DIR ${SUBDIRS})
add_subdirectory(${DIR})
endforeach()
The vpp cmake configuration hierarchy discovers the list of plugins to be built by searching for subdirectories in .../src/plugins which contain CMakeLists.txt files
##############################################################################
# find and add all plugin subdirs
##############################################################################
FILE(GLOB files RELATIVE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/*/CMakeLists.txt
)
foreach (f ${files})
get_filename_component(dir ${f} DIRECTORY)
add_subdirectory(${dir})
endforeach()
How to write a plugin CMakeLists.txt file
It's really quite simple. Follow the pattern:
add_vpp_plugin(mactime
SOURCES
mactime.c
node.c
API_FILES
mactime.api
INSTALL_HEADERS
mactime_all_api_h.h
mactime_msg_enum.h
API_TEST_SOURCES
mactime_test.c
)
Adding a target elsewhere in the source tree
Within reason, adding a subdirectory to the SUBDIRS list in .../src/CMakeLists.txt is perfectly OK. The indicated directory will need a CMakeLists.txt file.
Here's how we build the g2 event data visualization tool:
option(VPP_BUILD_G2 "Build g2 tool." OFF)
if(VPP_BUILD_G2)
find_package(GTK2 COMPONENTS gtk)
if(GTK2_FOUND)
include_directories(${GTK2_INCLUDE_DIRS})
add_vpp_executable(g2
SOURCES
clib.c
cpel.c
events.c
main.c
menu1.c
pointsel.c
props.c
g2version.c
view1.c
LINK_LIBRARIES vppinfra Threads::Threads m ${GTK2_LIBRARIES}
NO_INSTALL
)
endif()
endif()
The g2 component is optional, and is not built by default. There are a couple of ways to tell cmake to include it in build.ninja [or in Makefile.]
When invoking cmake manually [rarely done and not very easy], specify -DVPP_BUILD_G2=ON:
$ cmake ... -DVPP_BUILD_G2=ON
Take a good look at .../build-data/packages/vpp.mk to see where and how the top-level Makefile and .../build-root/Makefile set all of the cmake arguments. One strategy to enable an optional component is fairly obvious. Add -DVPP_BUILD_G2=ON to vpp_cmake_args.
That would work, of course, but it's not a particularly elegant solution.
Tinkering with build options: ccmake
The easy way to set VPP_BUILD_G2 - or frankly any cmake parameter - is to install the "cmake-curses-gui" package and use it.
Do a straightforward vpp build using the top level Makefile, "make build" or "make build-release"
Ajourn to .../build-root/build-vpp-native/vpp or .../build-root/build-vpp_debug-native/vpp
Invoke "ccmake ." to reconfigure the project as desired
Here's approximately what you'll see:
CCACHE_FOUND /usr/bin/ccache
CMAKE_BUILD_TYPE
CMAKE_INSTALL_PREFIX /scratch/vpp-gate/build-root/install-vpp-nati
DPDK_INCLUDE_DIR /scratch/vpp-gate/build-root/install-vpp-nati
DPDK_LIB /scratch/vpp-gate/build-root/install-vpp-nati
MBEDTLS_INCLUDE_DIR /usr/include
MBEDTLS_LIB1 /usr/lib/x86_64-linux-gnu/libmbedtls.so
MBEDTLS_LIB2 /usr/lib/x86_64-linux-gnu/libmbedx509.so
MBEDTLS_LIB3 /usr/lib/x86_64-linux-gnu/libmbedcrypto.so
MUSDK_INCLUDE_DIR MUSDK_INCLUDE_DIR-NOTFOUND
MUSDK_LIB MUSDK_LIB-NOTFOUND
PRE_DATA_SIZE 128
VPP_API_TEST_BUILTIN ON
VPP_BUILD_G2 OFF
VPP_BUILD_PERFTOOL OFF
VPP_BUILD_VCL_TESTS ON
VPP_BUILD_VPPINFRA_TESTS OFF
CCACHE_FOUND: Path to a program.
Press [enter] to edit option Press [d] to delete an entry CMake Version 3.10.2
Press [c] to configure
Press [h] for help Press [q] to quit without generating
Press [t] to toggle advanced mode (Currently Off)
Use the cursor to point at the VPP_BUILD_G2 line. Press the return key to change OFF to ON. Press "c" to regenerate build.ninja, etc.
At that point "make build" or "make build-release" will build g2. And so on.
Note that toggling advanced mode ["t"] gives access to substantially all of the cmake option, discovered directories and paths.