Evolution of ROOT’s CMake Build System

G. Amadio for the ROOT Team

ROOT Data Analysis Framework https://root.cern Installing ROOT What’s the easiest way to install ROOT?

● Arch 6.14/02 → https://aur.archlinux.org/packages/root ● CentOS 6.14/02 → https://fedoraproject.org/wiki/EPEL ● Fedora 6.14/04 → https://apps.fedoraproject.org/packages/root ● Gentoo 6.14/04 → https://packages.gentoo.org/packages/sci-physics/root ● Ubuntu 6.14/04 → https://root.cern.ch/content/release-61404 ▶ Mac OS X ● Homebrew 6.14/02 → https://formulae.brew.sh/formula/root ▶ Windows ● Preview binaries 6.14/04 → https://root.cern.ch/content/release-61402

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 3 I need to customize ROOT to my needs!

# Install dependencies from your OS # An up to date list for your distro can be found in # https://github.com/root-project/root-docker $ git clone http://root.cern/git/root.git -b v6-14-04 $ mkdir build && cd build $ cmake ../root -DCMAKE_CXX_FLAGS=”-march=native” [...] $ cmake --build .

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 4 Anaconda and ROOT

▶ Avoid building ROOT with Anaconda if you can ▶ Many people use system GCC to compile against Anaconda Python ▶ ++ ABI of your system libraries and Anaconda may differ ▶ libPyROOT.so needs to link to C++ standard library and Python ▶ Bad experience and sadness, because the two are not compatible

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 5 How to install ROOT with Anaconda?

▶ Install GCC from Anaconda and use that to build ROOT ▶ Do not mix system with Anaconda packages ▶ Ensure no ROOT dependencies come from your system ▶ Set PYTHONPATH, PATH, etc, to use Anaconda ▶ It’s not ROOT’s fault it’s difficult to this work!

Do not mix system + anaconda dependencies, pick everything from only one of them, including Python and the itself

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 6 ROOT is also available on CVMFS

▶ LCG Releases — http://lcginfo.cern.ch/pkg/ROOT ● All the work has already been done for you ● Just source the right setup script ● source /cvmfs/sft.cern.ch/lcg/views/LCG_93//setup.sh ▶ Gentoo Prefix on CVMFS ● Linux /cvmfs/sft.cern.ch/lcg/contrib/gentoo/linux/x86_64/startprefix ● Mac OS X /cvmfs/sft.cern.ch/lcg/contrib/gentoo//10.13/startprefix ● More information: Robust Linux Binaries, CHEP 2018, Sofia

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 7 Modern CMake 9 10 Motivation

▶ Reduce complexity of the build system ▶ Make it easier to maintain for developers ▶ Make it easier to understand for contributors ▶ Improve experience of those who need to build ROOT ▶ Improve modularization of the project ▶ Improve performance when running CMake

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 11 Modern CMake Resources

▶ Daniel Pfiffer’s talk at cppcon https://www.youtube.com/watch?v=bsXLMQ6WgIk ▶ Manuel Binna’s Gist on Modern CMake https://gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1 ▶ An Introduction to Modern CMake https://cliutils.gitlab.io/modern-cmake ▶ Kitware’s Blog on CMake Superbuilds https://blog.kitware.com/cmake-superbuilds-git-submodules

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 12 What is modern CMake?

▶ Available starting with CMake 3.0 ▶ Think in targets rather than variables ▶ Treat CMake code like production code, it is code afterall ▶ Keep off CMAKE_CXX_FLAGS and don’t use custom variables ▶ Don’t abuse usage requirements: -Wall is not a requirement ▶ Forget global commands like include_directories, link_directories, link_libraries, etc ▶ Write a Config.cmake file for dependent projects

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 13 How is ROOT doing?

▶ Available starting with CMake 3.0 ✔ ▶ Think in targets rather than variables ✔ ▶ Treat CMake code like production code, it is code afterall ✔ ▶ Keep off CMAKE_CXX_FLAGS and don’t use custom variables ✘ ▶ Don’t abuse usage requirements: -Wall is not a requirement ✘ ▶ Forget global commands like include_directories, link_directories, link_libraries, etc ✘ ▶ Write a Config.cmake file for dependent projects ✔

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 14 What is modern CMake?

▶ Put CI-specific settings in CTest scripts, not in the project

▶ Use exported targets of external packages when available

▶ Write a Find.cmake for dependencies that don’t provide it

▶ Do not use file(GLOB), but watch out for CONFIGURE_DEPENDS

▶ Use toolchain files to support cross compilation

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 15 How is ROOT doing?

▶ Put CI-specific settings in CTest scripts, not in the project ✘

▶ Use exported targets of external packages when available ✔

▶ Write a Find.cmake for dependencies that don’t provide it ✔

▶ Do not use file(GLOB), but watch out for CONFIGURE_DEPENDS ✔

▶ Use toolchain files to support cross compilation ✘

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 16 Future Plans Things that we want to improve

▶ Follow the filesystem hierarchy standard

▶ Make it easier to install and use multiple versions of ROOT

▶ Do not mix ExternalProject_Add and regular CMake targets

▶ Wrap find_package for builtins and use add_subdirectory with same effect

▶ Do not rely on ROOTSYS, LD_LIBRARY_PATH, etc

▶ Reduce complexity of configuration options (all=ON, fail-on-missing)

▶ Increase modularity of ROOT’s sub-packages

▶ Avoid usage from the build directory, install instead, and test install

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 18 Better macros to generate dictionaries

▶ ROOT already has ROOT_STANDARD_LIBRARY_PACKAGE function

● Creates library with rootcling dictionary attached

▶ Current CMake functions to generate dictionary are not optimal

● Generate dictionary sources (.cxx files) from headers

● Use generated sources to add into call to add_library

● Cannot inherit target properties (e.g. include directories) from the library target ▶ Add new add_dictionary macro that can be used after library target is created

● Create library target with add_library

● Generate dictionary using target properties of library target

● Add dictionary source to the library target with target_sources

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 19 Example usage for ROOT’s Davix Library

cmake_minimum_required(VERSION 3.6 FATAL_ERROR) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules) option(BUILD_SHARED_LIBS "Build shared libraries" ON)

find_package(Davix 0.6.7 REQUIRED) find_package(ROOT 6.14 REQUIRED COMPONENTS RIO Net)

include(ROOTMacros) # contains add_dictionary function

add_library(RDAVIX TDavixFile.cxx TDavixSystem.cxx) target_link_libraries(RDAVIX PUBLIC Davix::Davix ROOT::Net ROOT::RIO)

add_dictionary(TARGET RDAVIX HEADERS TDavixFile.h TDavixSystem.h LINKDEF LinkDef.h)

Example available at https://gitlab.cern.ch/amadio/root-davix

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 20 Future dictionary generation functions

▶ Proof of concept for now ▶ Need to further discuss interface, installation ▶ Target 6.16/00 for integration into ROOT ▶ Becomes usable by dependent projects ▶ Use similar style in ROOT to make packages independent

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 21 Summary

▶ ROOT is moving towards modern CMake

▶ Future macros will make it easier for dependent projects to use ROOT

● Find ROOT and use compatible settings

● Create libraries with dictionaries

▶ More modularity

● Allow parts of ROOT to be updated without rebuilding ROOT

● Faster development

▶ New CMake super build to simplify process of building ROOT

▶ Making an effort to make ROOT available in official distribution channels

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 22 Backup slides New add_dictionary function

function(add_dictionary) cmake_parse_arguments(G "" "TARGET;LINKDEF" "HEADERS;OPTIONS" "${ARGN}") set(G_DEFINES "$") set(G_INCLUDES "$")

target_include_directories(${G_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(${G_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/G_${G_TARGET}.cxx BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/G_${G_TARGET}.cxx DEPENDS ${G_HEADERS} COMMAND ${ROOT_rootcling_CMD} -f ${CMAKE_CURRENT_BINARY_DIR}/G_${G_TARGET}.cxx ${G_OPTIONS} "$<$:-D$>" "$<$:-I$>" ${G_HEADERS} ${G_LINKDEF} COMMAND_EXPAND_LISTS) target_sources(${G_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/G_${G_TARGET}.cxx) endfunction()

G. Amadio, Evolution of ROOT’s CMake Build System, ROOT Workshop 2018, Sarajevo 24