Updates for ROOT
This commit is contained in:
parent
f19057232c
commit
89c222da2c
@ -1,8 +1,9 @@
|
|||||||
|
|
||||||
# ROOT
|
# ROOT
|
||||||
|
|
||||||
ROOT is a C++ Toolkit for High Energy Physics. It is huge. There are really a lot of ways to use it in CMake, though many/most of the examples you'll find are probably wrong. Here's my recommendation.
|
ROOT is a C++ Toolkit for High Energy Physics. It is huge. There are really a lot of ways to use it in CMake, though many/most of the examples you'll find are probably wrong. Here's my recommendation.
|
||||||
|
|
||||||
Most importantly, there are lots of improvements in CMake in more recent versions of ROOT - try to use 6.14+!
|
Most importantly, there are *lots of improvements* in CMake support in more recent versions of ROOT - Using 6.16+ is much, much easier! If you really must support 6.14 or earlier, see the section at the end.
|
||||||
|
|
||||||
## Finding ROOT
|
## Finding ROOT
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ to attempt to find ROOT. If you don't have your paths set up, you can pass `-DRO
|
|||||||
|
|
||||||
## The too-simple way
|
## The too-simple way
|
||||||
|
|
||||||
ROOT [provides a utility](https://root.cern.ch/how/integrate-root-my-project-cmake) to set up a ROOT project, which you can activate using `include("${ROOT_USE_FILE}")`. This will automatically make ugly directory level and global variables for you. It will save you a little time setting up, and will waste massive amounts of time later if you try to do anything tricky. As long as you aren't making a library, it's probably fine for simple scripts. Includes and flags are set globally, but you'll still need to link to `${ROOT_LIBRARIES}` yourself, along with possibly `ROOT_EXE_LINKER_FLAGS` (You will have to `separate_arguments` first before linking or you will get an error if there are multiple flags, like on macOS).
|
ROOT [provides a utility](https://root.cern.ch/how/integrate-root-my-project-cmake) to set up a ROOT project, which you can activate using `include("${ROOT_USE_FILE}")`. This will automatically make ugly directory level and global variables for you. It will save you a little time setting up, and will waste massive amounts of time later if you try to do anything tricky. As long as you aren't making a library, it's probably fine for simple scripts. Includes and flags are set globally, but you'll still need to link to `${ROOT_LIBRARIES}` yourself, along with possibly `ROOT_EXE_LINKER_FLAGS` (You will have to `separate_arguments` first before linking or you will get an error if there are multiple flags, like on macOS). Also, before 6.16, you have to manually fix a bug in the spacing.
|
||||||
|
|
||||||
Here's what it would look like:
|
Here's what it would look like:
|
||||||
|
|
||||||
@ -22,27 +23,17 @@ Here's what it would look like:
|
|||||||
|
|
||||||
## The right way (Targets)
|
## The right way (Targets)
|
||||||
|
|
||||||
ROOT 6.12 and earlier do not add the include directory for imported targets. ROOT 6.14+ has corrected this error. To fix this error for older ROOT versions, you'll need something like:
|
ROOT 6.12 and earlier do not add the include directory for imported targets. ROOT 6.14+ has corrected this error, and required target properties have been getting better.
|
||||||
|
|
||||||
[import:'setup_includes', lang:'cmake'](../../examples/root-simple/CMakeLists.txt)
|
|
||||||
|
|
||||||
You will also often want the compile flags and definitions:
|
|
||||||
|
|
||||||
[import:'setup_flags', lang:'cmake'](../../examples/root-simple/CMakeLists.txt)
|
|
||||||
|
|
||||||
In CMake 3.11, you can replace that last function call with:
|
|
||||||
|
|
||||||
[import:'modern_fix', lang:'cmake'](../../examples/root-simple-3.11/CMakeLists.txt)
|
|
||||||
|
|
||||||
All the ROOT targets will require `ROOT::Core`, so this will be enough regardless of which ROOT targets you need.
|
|
||||||
|
|
||||||
To link, just pick the libraries you want to use:
|
To link, just pick the libraries you want to use:
|
||||||
|
|
||||||
[import:'add_and_link', lang:'cmake'](../../examples/root-simple/CMakeLists.txt)
|
[import:'add_and_link', lang:'cmake'](../../examples/root-simple/CMakeLists.txt)
|
||||||
|
|
||||||
|
If you'd like to see the default list, run `root-config --libs` on the command line.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
Find ROOT allows you to specify components. It will add anything you list to ${ROOT_LIBRARIES}, so you might want to build your own target using that to avoid listing the components twice. This does not solve dependencies though; so it is an error to list `RooFit` but not `RooFitCore`. If you link to `ROOT::RooFit` instead of `${ROOT_LIBRARIES}`, then `RooFitCore` is not required.
|
Find ROOT allows you to specify components. It will add anything you list to `${ROOT_LIBRARIES}`, so you might want to build your own target using that to avoid listing the components twice. This did not solve dependencies; it was an error to list `RooFit` but not `RooFitCore`. If you link to `ROOT::RooFit` instead of `${ROOT_LIBRARIES}`, then `RooFitCore` is not required.
|
||||||
|
|
||||||
## Dictionary generation
|
## Dictionary generation
|
||||||
|
|
||||||
@ -58,7 +49,10 @@ To generate, you should include the following in your CMakeLists:
|
|||||||
|
|
||||||
```cmake
|
```cmake
|
||||||
include("${ROOT_DIR}/modules/RootNewMacros.cmake")
|
include("${ROOT_DIR}/modules/RootNewMacros.cmake")
|
||||||
include_directories(ROOT_BUG)
|
|
||||||
|
# Uncomment for ROOT versions than 6.16
|
||||||
|
# They break if nothing is in the global include list!
|
||||||
|
# include_directories(ROOT_BUG)
|
||||||
```
|
```
|
||||||
|
|
||||||
The second line is due to a bug in the NewMacros file that causes dictionary generation to fail if there is not at least one global include directory or a `inc` folder. Here I'm including a non-existent directory just to make it work. There is no `ROOT_BUG` directory.
|
The second line is due to a bug in the NewMacros file that causes dictionary generation to fail if there is not at least one global include directory or a `inc` folder. Here I'm including a non-existent directory just to make it work. There is no `ROOT_BUG` directory.
|
||||||
@ -79,3 +73,42 @@ The final two output files must sit next to the library output. This is done by
|
|||||||
|
|
||||||
[linkdef-root]: https://root.cern.ch/selecting-dictionary-entries-linkdefh
|
[linkdef-root]: https://root.cern.ch/selecting-dictionary-entries-linkdefh
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Using Old ROOT
|
||||||
|
|
||||||
|
If you really have to use older ROOT, you'll need something like this:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# ROOT targets are missing includes and flags in ROOT 6.10 and 6.12
|
||||||
|
set_property(TARGET ROOT::Core PROPERTY
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${ROOT_INCLUDE_DIRS}")
|
||||||
|
|
||||||
|
# Early ROOT does not include the flags required on targets
|
||||||
|
add_library(ROOT::Flags_CXX IMPORTED INTERFACE)
|
||||||
|
|
||||||
|
|
||||||
|
# ROOT 6.14 and earlier have a spacing bug in the linker flags
|
||||||
|
string(REPLACE "-L " "-L" ROOT_EXE_LINKER_FLAGS "${ROOT_EXE_LINKER_FLAGS}")
|
||||||
|
|
||||||
|
# Fix for ROOT_CXX_FLAGS not actually being a CMake list
|
||||||
|
separate_arguments(ROOT_CXX_FLAGS)
|
||||||
|
set_property(TARGET ROOT::Flags_CXX APPEND PROPERTY
|
||||||
|
INTERFACE_COMPILE_OPTIONS ${ROOT_CXX_FLAGS})
|
||||||
|
|
||||||
|
# Add definitions
|
||||||
|
separate_arguments(ROOT_DEFINITIONS)
|
||||||
|
foreach(_flag ${ROOT_EXE_LINKER_FLAG_LIST})
|
||||||
|
# Remove -D or /D if present
|
||||||
|
string(REGEX REPLACE [=[^[-//]D]=] "" _flag ${_flag})
|
||||||
|
set_property(TARGET ROOT::Flags APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${_flag})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# This also fixes a bug in the linker flags
|
||||||
|
separate_arguments(ROOT_EXE_LINKER_FLAGS)
|
||||||
|
set_property(TARGET ROOT::Flags_CXX APPEND PROPERTY
|
||||||
|
INTERFACE_LINK_LIBRARIES ${ROOT_EXE_LINKER_FLAGS})
|
||||||
|
|
||||||
|
# Make sure you link with ROOT::Flags_CXX too!
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -10,5 +10,4 @@ add_subdirectory(extended-project)
|
|||||||
|
|
||||||
add_subdirectory(root-usefile)
|
add_subdirectory(root-usefile)
|
||||||
add_subdirectory(root-simple)
|
add_subdirectory(root-simple)
|
||||||
add_subdirectory(root-simple-3.11)
|
|
||||||
add_subdirectory(root-dict)
|
add_subdirectory(root-dict)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
## [main]
|
## [main]
|
||||||
cmake_minimum_required(VERSION 3.4)
|
cmake_minimum_required(VERSION 3.4...3.15)
|
||||||
|
|
||||||
project(RootDictExample LANGUAGES CXX)
|
project(RootDictExample LANGUAGES CXX)
|
||||||
|
|
||||||
@ -9,21 +9,14 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(CMAKE_PLATFORM_INDEPENDENT_CODE ON)
|
set(CMAKE_PLATFORM_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
find_package(Threads)
|
|
||||||
|
|
||||||
find_package(ROOT CONFIG REQUIRED)
|
find_package(ROOT CONFIG REQUIRED)
|
||||||
include("${ROOT_DIR}/modules/RootNewMacros.cmake")
|
include("${ROOT_DIR}/modules/RootNewMacros.cmake")
|
||||||
|
|
||||||
# We will set the flags ourselves
|
|
||||||
set_target_properties(ROOT::Core PROPERTIES
|
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${ROOT_INCLUDE_DIRS}")
|
|
||||||
|
|
||||||
include_directories(ROOT_BUG)
|
|
||||||
root_generate_dictionary(G__DictExample DictExample.h LINKDEF DictLinkDef.h)
|
root_generate_dictionary(G__DictExample DictExample.h LINKDEF DictLinkDef.h)
|
||||||
|
|
||||||
add_library(DictExample SHARED DictExample.cxx DictExample.h G__DictExample.cxx)
|
add_library(DictExample SHARED DictExample.cxx DictExample.h G__DictExample.cxx)
|
||||||
target_include_directories(DictExample PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
target_include_directories(DictExample PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
target_link_libraries(DictExample PUBLIC ROOT::Core Threads::Threads)
|
target_link_libraries(DictExample PUBLIC ROOT::Core)
|
||||||
|
|
||||||
## [main]
|
## [main]
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
|
|
||||||
## [main]
|
|
||||||
cmake_minimum_required(VERSION 3.11)
|
|
||||||
|
|
||||||
project(RootSimpleExample311 LANGUAGES CXX)
|
|
||||||
|
|
||||||
find_package(ROOT CONFIG REQUIRED)
|
|
||||||
|
|
||||||
## [modern_fix]
|
|
||||||
target_include_directories(ROOT::Core INTERFACE "${ROOT_INCLUDE_DIRS}")
|
|
||||||
|
|
||||||
add_library(ROOT::Flags_CXX IMPORTED INTERFACE)
|
|
||||||
|
|
||||||
separate_arguments(ROOT_CXX_FLAGS)
|
|
||||||
target_compile_options(ROOT::Flags_CXX INTERFACE ${ROOT_CXX_FLAGS})
|
|
||||||
|
|
||||||
separate_arguments(ROOT_DEFINITIONS)
|
|
||||||
target_compile_definitions(ROOT::Flags_CXX INTERFACE ${ROOT_DEFINITIONS})
|
|
||||||
|
|
||||||
# This fixes a bug in the linker flags
|
|
||||||
string(REPLACE "-L " "-L" ROOT_EXE_LINKER_FLAGS "${ROOT_EXE_LINKER_FLAGS}")
|
|
||||||
separate_arguments(ROOT_EXE_LINKER_FLAGS)
|
|
||||||
# Stuck into using old property method due to separate -L and -l arguments
|
|
||||||
# (A full path to -l is better!)
|
|
||||||
set_property(TARGET ROOT::Flags_CXX PROPERTY
|
|
||||||
INTERFACE_LINK_LIBRARIES ${ROOT_EXE_LINKER_FLAGS})
|
|
||||||
## [modern_fix]
|
|
||||||
|
|
||||||
add_executable(RootSimpleExample311 SimpleExample.cxx)
|
|
||||||
target_link_libraries(RootSimpleExample311 PUBLIC ROOT::Physics ROOT::Flags_CXX)
|
|
||||||
## [main]
|
|
||||||
|
|
||||||
enable_testing()
|
|
||||||
add_test(NAME RootSimpleExample311 COMMAND RootSimpleExample311)
|
|
@ -1,11 +0,0 @@
|
|||||||
# A Simple ROOT Project (CMake 3.11)
|
|
||||||
|
|
||||||
This is a minimal example of a ROOT project using the target system and without a dictionary.
|
|
||||||
This uses the new support in CMake 3.11+ for adding interface properties on an imported interface target.
|
|
||||||
|
|
||||||
#### examples/root-simple-3.11/CMakeLists.txt
|
|
||||||
[import:'main', lang:'cmake'](CMakeLists.txt)
|
|
||||||
|
|
||||||
#### examples/root-simple-3.11/SimpleExample.cxx
|
|
||||||
|
|
||||||
[import](SimpleExample.cxx)
|
|
@ -1,7 +0,0 @@
|
|||||||
#include <TLorentzVector.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
TLorentzVector v(1,2,3,4);
|
|
||||||
v.Print();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,46 +1,19 @@
|
|||||||
|
|
||||||
## [main]
|
## [main]
|
||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1...3.15)
|
||||||
|
|
||||||
project(RootSimpleExample LANGUAGES CXX)
|
project(RootSimpleExample LANGUAGES CXX)
|
||||||
|
|
||||||
|
# Finding the ROOT package
|
||||||
## [find_package]
|
## [find_package]
|
||||||
find_package(ROOT CONFIG REQUIRED)
|
find_package(ROOT 6.16 CONFIG REQUIRED)
|
||||||
## [find_package]
|
## [find_package]
|
||||||
|
|
||||||
# ROOT targets are missing includes and flags
|
|
||||||
## [setup_includes]
|
|
||||||
set_property(TARGET ROOT::Core PROPERTY
|
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${ROOT_INCLUDE_DIRS}")
|
|
||||||
## [setup_includes]
|
|
||||||
|
|
||||||
## [setup_flags]
|
# Adding an executable program and linking to needed ROOT libraries
|
||||||
add_library(ROOT::Flags_CXX IMPORTED INTERFACE)
|
|
||||||
|
|
||||||
# Fix for ROOT_CXX_FLAGS not actually being a CMake list
|
|
||||||
separate_arguments(ROOT_CXX_FLAGS)
|
|
||||||
set_property(TARGET ROOT::Flags_CXX APPEND PROPERTY
|
|
||||||
INTERFACE_COMPILE_OPTIONS ${ROOT_CXX_FLAGS})
|
|
||||||
|
|
||||||
# Add definitions
|
|
||||||
separate_arguments(ROOT_DEFINITIONS)
|
|
||||||
foreach(_flag ${ROOT_EXE_LINKER_FLAG_LIST})
|
|
||||||
# Remove -D or /D if present
|
|
||||||
string(REGEX REPLACE [=[^[-//]D]=] "" _flag ${_flag})
|
|
||||||
set_property(TARGET ROOT::Flags APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${_flag})
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# This also fixes a bug in the linker flags
|
|
||||||
string(REPLACE "-L " "-L" ROOT_EXE_LINKER_FLAGS "${ROOT_EXE_LINKER_FLAGS}")
|
|
||||||
separate_arguments(ROOT_EXE_LINKER_FLAGS)
|
|
||||||
set_property(TARGET ROOT::Flags_CXX APPEND PROPERTY
|
|
||||||
INTERFACE_LINK_LIBRARIES ${ROOT_EXE_LINKER_FLAGS})
|
|
||||||
## [setup_flags]
|
|
||||||
|
|
||||||
# Adding an exectuable program and linking to needed ROOT libraries
|
|
||||||
## [add_and_link]
|
## [add_and_link]
|
||||||
add_executable(RootSimpleExample SimpleExample.cxx)
|
add_executable(RootSimpleExample SimpleExample.cxx)
|
||||||
target_link_libraries(RootSimpleExample PUBLIC ROOT::Physics ROOT::Flags_CXX)
|
target_link_libraries(RootSimpleExample PUBLIC ROOT::Physics)
|
||||||
## [add_and_link]
|
## [add_and_link]
|
||||||
|
|
||||||
## [main]
|
## [main]
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
|
|
||||||
## [main]
|
## [main]
|
||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1...3.15)
|
||||||
|
|
||||||
project(RootUseFileExample LANGUAGES CXX)
|
project(RootUseFileExample LANGUAGES CXX)
|
||||||
|
|
||||||
find_package(ROOT CONFIG REQUIRED)
|
find_package(ROOT 6.16 CONFIG REQUIRED)
|
||||||
|
|
||||||
|
# Sets up global settings
|
||||||
include("${ROOT_USE_FILE}")
|
include("${ROOT_USE_FILE}")
|
||||||
|
|
||||||
|
# This is required for ROOT < 6.16
|
||||||
|
# string(REPLACE "-L " "-L" ROOT_EXE_LINKER_FLAGS "${ROOT_EXE_LINKER_FLAGS}")
|
||||||
|
|
||||||
# This is required on if there is more than one flag (like on macOS)
|
# This is required on if there is more than one flag (like on macOS)
|
||||||
# and this also fixes a bug in the linker flags
|
|
||||||
string(REPLACE "-L " "-L" ROOT_EXE_LINKER_FLAGS "${ROOT_EXE_LINKER_FLAGS}")
|
|
||||||
separate_arguments(ROOT_EXE_LINKER_FLAGS)
|
separate_arguments(ROOT_EXE_LINKER_FLAGS)
|
||||||
|
|
||||||
add_executable(RootUseFileExample SimpleExample.cxx)
|
add_executable(RootUseFileExample SimpleExample.cxx)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user