ROOT macros and shared libraries
A ROOT macro contains pure C++ code, which additionally can contain ROOT classes and other ROOT objects (→ see ROOT classes, data types and global variables). A ROOT macro can consist of simple or multi-line commands, but also of arbitrarily complex class and function definitions.
You can save a ROOT macro in a file and execute it at the ROOT prompt or the system prompt (→ see Creating ROOT macros).
You also can compile a ROOT macro with ACLiC (→ see Compiling ROOT macros with ACLiC).
ROOT provides many tutorials that are available as ROOT macros (→ see ROOT tutorial page).
Creating ROOT macros
The name of the ROOT macro and the file name (without file extension) in which the macro is saved must match.
-
Create a new file in your preferred text editor.
-
Use the following general structure for the ROOT macro, preferably with a function that has the same name as the file:
- Save the file ROOT macro, using the macro name as file name: MacroName.C
Note
It’s not necessary to
#include
anything in the ROOT macros. Everything in the include paths is automatically included. Note that you can type.I
in the ROOT prompt to see the include paths, and.I [path]
to add an extra path.
Executing ROOT macros
You can execute a ROOT macro in one of three ways:
-
Execute a ROOT macro at the system prompt:
$ root MacroName.C
Note
By adding further space-separated file names to the line above, you can sequentially execute multiple macros in the same ROOT session, as long as they don’t share the same name. You can also replace MacroName.C with MacroName_C.so if you compiled your macro with ACLiC beforehand.
-
Execute a macro at the ROOT prompt:
root [0] .x MacroName.C
Note
You can also replace MacroName.C with MacroName_C.so if you compiled your macro with ACLiC beforehand.
-
Load a macro from within a ROOT session and then call the function:
root [0] .L MacroName.C root [1] MacroName()
Note
You can load multiple macros in the same ROOT session (one .L statement for each), as long as they don’t have the same name. You can also replace MacroName.C with MacroName_C.so if you compiled your macro with ACLiC beforehand.
It is also possible to pass parameters directly to the macro function:
$ root 'MacroName.C("some String", 12)'
The same structure applies when executing from the ROOT prompt, but single quotes are no longer necessary:
root [0] .x MacroName.C("some String", 12)
If you preload the library, specify the function arguments on the call to the macro name, rather than on the first line.
root [0] .L MacroName.C
root [1] MacroName("some String", 12)
In addition, you can execute a ROOT macro from a ROOT macro.
Executing a ROOT macro from a ROOT macro
You can execute a ROOT macro conditionally inside another ROOT macro by calling directly the interpreter using TROOT::ProcessLine().
ProcessLine()
takes in addition to the code to be executed an optional parameter, which is a pointer to an int
or to a
TInterpreter::EErrorCode
to let you access the interpreter error code after an attempt to interpret.
It returns the return value of the called macro casted to a Longptr_t
.
Example
The example
cernstaff.C
calls another macro cernbuild.C
to build a ROOT file, if it does not exist.
The function in the cernbuild.C
macro returns an error code that we get as the return value from ProcessLine()
.
Compiling ROOT macros with ACLiC
ROOT macros are by default just-in-time compiled with Cling, ROOT’s C++ interpreter. Alternatively, you can use ACLiC to compile your macro to a shared library from within a ROOT session. Using ACLiC, the code is compiled with the system compiler rather than Cling. This has the following advantages:
- full compiler optimizations can be enabled
- code can be compiled with debug symbols
- compiled code is cached across ROOT sessions
- dictionaries for C++ classes in the compiled code are automatically generated (see also Storing data with ROOT)
ACLiC is implemented in TSystem::CompileMacro(). When using ACLiC, ROOT checks what library really needs to be built and calls your system’s C++ compiler, linker and dictionary generator.
ACLiC executes the following steps:
-
Calling
rootcling
to create automatically a dictionary.
For what a dictionary is used for, → see I/O of custom classes. -
Calling the system’s C++ compiler to build the shared library.
-
Load the shared library and optionally execute the macro.
Before you can compile your interpreted ROOT macro, you need to add the include statements for the classes used in the ROOT macro. Only then you can build and load a shared library containing your ROOT macro.
You can tweak for instance the compilation’s optimization and debug symbols; see the documentation of TSystem::CompileMacro().
Example
To compile a ROOT macro and build a shared library, type:
root [0] .L MyScript.C+
The +
option compiles the code and generates a shared library MyScript_C.so
(MyScript_C.dll
on Windows).
The +
command rebuilds the library only if the ROOT macro or any of the files it includes
are newer than the library. To force a recompilation of the library, use ++
.
Once compiled, the shared library name can be directly passed in place of MyScript.C
when calling .L
or .x
.
You can also compile, build and run with arguments in a one-liner using:
root [0] .x MyScript.C+("some String", 12)
or from the command line (outside the ROOT prompt):
$ root 'MyScript.C+("some String", 12)'
And variations thereof with ++
.
Example
To force compilation with debug symbols, type:
root [0] .L MyScript.C+g
To see the full list of possible flags, see the TSystem::CompileMacro documentation.
Note
When a ROOT macro has a function called
main()
your can compile the macro with ACLiC or the Cling ROOT interpreter, but you cannot execute themain()
function from within the ROOT session.
Setting the include path
The $ROOTSYS/include
directory is automatically appended to the include path.
To get the include path, type:
root [0] .include
To append the include path, type:
root [0] .include $HOME/mypackage/include
Add the following line in the ROOT macro to append a new path to the existing include paths:
To overwrite an existing include path, type:
To add any static or shared library that should be used during linking, type:
If the library is a shared library, you can also load it before compiling the macro: