# Compiled ROOT dictionaries The procedure in {ref}`interpreted-dictionary` is fine when you're prototyping your data structures and other initial development tasks. But at some point it becomes more convenient to compile your dictionaries rather than dynamically interpreting them: - Interpreting a ROOT dictionary takes longer than compiling it. - If you're developing a program that you want to be distributed as part of a large project, you may want to distribute compiled binary libraries rather than potentially allowing "mysterious" `AutoDict*` files to be added to users' working areas. - If you're developing a program that will be distributed to a computational grid as described in {ref}`batch-systems`, you may not want the remote jobs to be potentially delayed with interpreting ROOT dictionaries. The ROOT command for [generating a compiled dictionary](https://root.cern/manual/io_custom_classes/) is **`rootcling`**. I find the [older rootcling documentation](https://root.cern.ch/root/htmldoc/guides/users-guide/Cling.html) to be a better guide than that the newer page in the first link in this paragraph. To use **`rootcling`** to compile a dictionary, you need to create a {file}`LinkDef.h` file. Take a look at the file [STL_LinkDef.h](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STL_LinkDef.h). The key lines are: :::{code-block} c++ :name: compiled-dict-generation :caption: The key `LinkDef.h` lines for generating a dictionary for `STL_TrackList.h` and other TTree branches. Compare this with {numref}`Listing %s `. #pragma link C++ class std::map+; #pragma link C++ class std::tuple+; #pragma link C++ class std::map,double>+; #pragma link C++ struct trackInfo+; #pragma link C++ class TrackList+; ::: A {file}`LinkDef.h` file tells **`rootcling`** every C++ class, struct, and non-fundamental C++ type that are present in the objects that we'll read/write. Here's a summary of the commands you'll see in the comments within [STL_LinkDef.h](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STL_LinkDef.h) and [STLntupleCreateDict.cxx](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STLntupleCreateDict.cxx) to create a dictionary for the C++ types in [STL_TrackList.h](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STL_TrackList.h). :::{code-block} bash :name: compiling-dictionary-library :caption: The commands to generate, compile, and link the dictionary for the example {file}`STL_TrackList.h`. rootcling -f STLntupleDict.cxx STL_TrackList.h STL_LinkDef.h g++ `root-config --cflags --libs` -shared STLntupleDict.cxx -o STLntupleDict.so -fPIC g++ `root-config --cflags --libs` STLntupleCreateDict.cxx ./STLntupleDict.so -o STLntupleCreateDict ::: :::::{admonition} Don't delete the .pcm files :class: warning You'll note that a .pcm[^define] file is created as part of the process in {numref}`Listing %s `, {file}`STLntupleDict_rdict.pcm`. In general, such a file is needed by the corresponding .so file ({file}`STLntupleDict.so` in this case). If you start moving files around, the .pcm file and .so file should be moved together. [^define]: "PCM" stands for "pre-compiled module". It's surprisingly difficult to find this definition in either the ROOT documentation or via web searches! If you know what [$LD_LIBRARY_PATH](https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html) means: You can include a directory containing a `.pcm` file, in the same way you can with a `.so` file. ::::: [STLntupleCreateDict.cxx](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STLntupleCreateDict.cxx) is functionally identical to [STLntupleCreate.cxx](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STLntupleCreate.cxx). The only difference it relies on the dictionary for {file}`STL_TrackList.h` to have been compiled as part of the program, so no `gInterpreter` lines are needed. Similarly, [STLntupleReadDict.cxx](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STLntupleReadDict.cxx) is functionally identical to [STLntupleRead.cxx](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STLntupleRead.cxx).[^ex16] [^ex16]: {file}`STLntupleReadDict.cxx` is essentially the solution to {ref}`data-reduction`. This is another example of how reading ahead can give you all the answers! Finally, [STLntupleReadDict.py](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STLntupleReadDict.py) is functionally identical to [STLntupleRead.py](https://www.nevis.columbia.edu/~seligman/root-class/files/root-dict/STLntupleRead.py). Since we can't compile a Python script with an external C++ library (at least, not in any simple way) we have to use ROOT to load the dictionary library: :::{code-block} python :name: python-dictionary-library gSystem.Load("STLntupleDict.so") ::: :::::{admonition} cmake :class: note If the commands in {numref}`Listing %s ` seem long and elaborate to you, you're right. Fortunately, in a project that's complex enough to involve ROOT dictionaries, it's not likely you'd have to have to type them (or rather, copy, paste, edit, and use up-arrow from some other source like {numref}`Listing %s `). Complex and shared programming projects in UNIX are typically handled using the [cmake](https://cmake.org/cmake/help/latest/manual/cmake.1.html) utility.[^xcode] From the [ROOT custom I/O page](https://root.cern/manual/io_custom_classes/), it seems that equivalent of {numref}`Listing %s ` for a [CMakeLists.txt](https://www.jetbrains.com/help/clion/cmakelists-txt-file.html) file might be ROOT_GENERATE_DICTIONARY( STLntupleDict STL_TrackList.h LINKDEF STL_LinkDef.h MODULE STLntupleReadDict ) Before you copy-and-paste this blindly, bear in mind that: - I have not tested that `ROOT_GENERATE_DICTIONARY` line. - Typically a {file}`CMakeLists.txt` can be quite involved. I made some assumptions about target names and the like. - This overall example based on the contents of {file}`STL_TrackList.h` was intended to be a quick-and-dirty study on my part. I added comments afterwards for this tutorial. My goal was to understand ROOT dictionaries, not to understand **`cmake`**. That comes next! ::::: [^xcode]: If you've never encountered **`cmake`** before, you can think of it as a command-line equivalent of [Xcode](https://developer.apple.com/documentation/xcode) on MacOS, or the [Visual Studio](https://code.visualstudio.com/) platform.