This lesson is being piloted (Beta version)

Building With CMake

Overview

Teaching: 60 min
Exercises: 30 min
Questions
  • Is it easier to compile using CMake and GNU Make?

  • What are the basic organizational principles of building your code with CMake?

Objectives
  • Use CMake to compile and link program while parameterize our ignorance for the time being.

As we saw in the previous section, building our analysis code to work with the ATLAS release is possible when starting from nothing more than g++ and using flags judiciously. However, executing this same command over and over will become very tedious. You could perhaps put it in a file called build.sh but you will soon find that extending your code to use other functionality is challenging and tedious. You could use a makefile that you write manually but this too would become tedious.

To circumvent both of these approaches, ATLAS uses the CMake tool to generate makefiles itself and then perform the build using these makefiles. More details will be taught on Tuesday of the bootcamp. For now, the main point is that this will require that you reorganize your code a bit and also create a configuration called a CMakeLists.txt file.

Reorganize

In the previous example, the AnalysisPayload was built in the same directory as where the AnalysisPayload.cxx source code lived. When using CMake, we will follow a different organizational paradigm. Now, you will be dividing your work into two “areas”. The first, your source directory, is where your source code lives. The second, your build directory, is where you will use CMake to perform the build and where you executables will appear.

If you haven’t already, you might as well delete the AnalysisPayload that you created before and the .o file. You will be creating it again now. Then, start by creating a separate directory within Bootcamp called source and move AnalysisPayload.cxx into it

cd Bootcamp
mkdir source
mv AnalysisPayload.cxx source/.

Now create a build directory that is at the same level as source

mkdir build

You will do nothing within this directory yet, but it will function as you “staging area” later. Now Your directory structure is ready to insert the CMake configuration file.

Make CMakeLists.txt File

At the heart of using CMake is the CMakeLists.txt file. It lives with the code that it builds and contains information about dependencies and diretory structures. To use it in this limited scope, within the source directory make a file called CMakeLists.txt and add the following to it

cmake_minimum_required(VERSION 3.14)

project(AnalysisPayload)

find_package(ROOT)
find_package(AnalysisBase)

target_compile_definitions(ROOT::Core
  INTERFACE ${ROOT_DEFINITIONS}
)

add_executable(AnalysisPayload AnalysisPayload.cxx)

target_link_libraries(AnalysisPayload
  PRIVATE
    ROOT::Core ${ROOT_LIBRARIES}
    AnalysisBase::xAODEventInfo
    AnalysisBase::xAODRootAccess
    AnalysisBase::xAODJet
)

That’s it, now let’s use it!

Building with CMake

To use this new setup, boot up the image as before and setup the release using the release_setup.sh script.

docker run --rm -it -v $PWD:/home/atlas/Bootcamp atlas/analysisbase:21.2.125 bash
cd /home/atlas/Bootcamp
source /release_setup.sh

Your directory structure should now look a little something like this

.

├── build

├── Data

       └── DAOD_EXOT27.17882744._000026.pool.root.1

└── source

       ├── AnalysisPayload.cxx

       └── CMakeLists.txt

3 directories, 3 files

Now it is time to let CMake and GNU Make do things for us. This is carried out within the build directory.

cd build
cmake ../source/

[bash][atlas AnalysisBase-21.2.125]:build > cmake ../source/

– The C compiler identification is GNU 8.3.0

– The CXX compiler identification is GNU 8.3.0

– Check for working C compiler: /opt/lcg/gcc/8.3.0-cebb0/x86_64-centos7/bin/gcc

– Check for working C compiler: /opt/lcg/gcc/8.3.0-cebb0/x86_64-centos7/bin/gcc – works

– Detecting C compiler ABI info

– Detecting C compiler ABI info - done

– Detecting C compile features

– Detecting C compile features - done

– Check for working CXX compiler: /opt/lcg/gcc/8.3.0-cebb0/x86_64-centos7/bin/g++

– Check for working CXX compiler: /opt/lcg/gcc/8.3.0-cebb0/x86_64-centos7/bin/g++ – works

– Detecting CXX compiler ABI info

– Detecting CXX compiler ABI info - done

– Detecting CXX compile features

– Detecting CXX compile features - done

– Found AnalysisBase: /usr/AnalysisBase/21.2.125/InstallArea/x86_64-centos7-gcc8-opt (version: 21.2.125)

– Found AnalysisBaseExternals: /usr/AnalysisBaseExternals/21.2.125/InstallArea/x86_64-centos7-gcc8-opt (version: 21.2.125)

– Setting ATLAS specific build flags

– checker_gccplugins library not found

– Package(s) in AnalysisBaseExternals: 22

– Using the LCG modules without setting up a release

– Package(s) in AnalysisBase: 194

– Looking for pthread.h

– Looking for pthread.h - found

– Looking for pthread_create

– Looking for pthread_create - not found

– Check if compiler accepts -pthread

– Check if compiler accepts -pthread - yes

– Found Threads: TRUE

– Configuring done

– Generating done

– Build files have been written to: /home/atlas/Bootcamp/build

make

[bash][atlas AnalysisBase-21.2.125]:build > make

Scanning dependencies of target AnalysisPayload

[ 50%] Building CXX object CMakeFiles/AnalysisPayload.dir/AnalysisPayload.cxx.o

[100%] Linking CXX executable AnalysisPayload

[100%] Built target AnalysisPayload

It was that simple! Your AnalysisPayload executable should have been created within the build directory and you can execute it as before.

./AnalysisPayload

Hopefully you get the same results as before with a small percentage of the hassle. You will learn more about each line of the CMakeLists.txt file is doing in the CMake session, though there is a tutorial if you are super eager. This is in no way mandatory or recommended! As long as you got the above to work, you are good-to-go!

Key Points

  • CMake is easier … when it works.

  • You will learn all the ins and outs of CMake on Tuesday. For now, it can function as little more than a tool to circumvent the long g++ commands.