diff --git a/SUMMARY.md b/SUMMARY.md index 17e42df..4f205a2 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -4,6 +4,8 @@ * [Installing CMake](chapters/installing.md) * [Running CMake](chapters/running.md) +--- + ## Making a CMakeLists * [Introduction to the Basics](chapters/basics.md) @@ -20,9 +22,14 @@ * [Debugging (X)](chapters/debug.md) * [Exporting and Installing](chapters/exporting.md) +--- + ## Specific packages * [CUDA](specifics/CUDA.md) * [OpenMP](specifics/OpenMP.md) * [Boost (X)](specifics/Boost.md) * [MPI](specifics/MPI.md) -* [ROOT (INCOMPLETE)](specifics/ROOT.md) +* [ROOT](specifics/ROOT.md) + * [Simple Example](examples/root-simple/README.md) + * [Simple Example CMake 3.11+](examples/root-simple-3.11/README.md) + * [Dictionary Example](examples/root-dict/README.md) diff --git a/book.json b/book.json index 687de8a..8989dee 100644 --- a/book.json +++ b/book.json @@ -2,7 +2,7 @@ "title": "Modern CMake", "description": "A guide to writing simple, powerful, and clean CMake 3.1+ builds.", "author": "Henry Schreiner", - "plugins": ["hints","term","include-codeblock"], + "plugins": ["collapsible-menu", "hints", "term", "include-codeblock"], "pluginsConfig": { "include-codeblock": { "fixlang": true diff --git a/examples/root-dict/DictExample.cxx b/examples/root-dict/DictExample.cxx index 2145dc6..78c15c7 100644 --- a/examples/root-dict/DictExample.cxx +++ b/examples/root-dict/DictExample.cxx @@ -3,4 +3,3 @@ Double_t Simple::GetX() const {return x;} ClassImp(Simple) - diff --git a/examples/root-dict/DictExample.h b/examples/root-dict/DictExample.h index 4c3fc83..2f2bfad 100644 --- a/examples/root-dict/DictExample.h +++ b/examples/root-dict/DictExample.h @@ -10,5 +10,4 @@ public: Double_t GetX() const; ClassDef(Simple,1) - }; diff --git a/examples/root-dict/DictLinkDef.h b/examples/root-dict/DictLinkDef.h index 9e7fe5e..4fb3997 100644 --- a/examples/root-dict/DictLinkDef.h +++ b/examples/root-dict/DictLinkDef.h @@ -1,13 +1,11 @@ - // See: https://root.cern.ch/selecting-dictionary-entries-linkdefh - #ifdef __CINT__ + #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; #pragma link C++ nestedclasses; - #pragma link C++ class Simple+; #endif diff --git a/examples/root-dict/README.md b/examples/root-dict/README.md new file mode 100644 index 0000000..008ec28 --- /dev/null +++ b/examples/root-dict/README.md @@ -0,0 +1,28 @@ +# Dictionary Example + +This is an example of building a module that includes a dictionary in CMake. + +#### examples/root-dict/CMakeLists.txt +[import:'main', lang:'cmake'](CMakeLists.txt) + +## Supporting files + +This is just a simple-as-possible class definition, with one method: + +#### examples/root-dict/DictExample.cxx +[import, lang:'c_cpp'](DictExample.cxx) + +#### examples/root-dict/DictExample.h +[import, lang:'c_cpp'](DictExample.h) + +We need a `LinkDef.h`, as well. + +#### examples/root-dict/DictLinkDef.h +[import, lang:'c_cpp'](DictLinkDef.h) + +## Testing it + +This is an example of a macro that tests the correct generation from the files listed above. + +#### examples/root-dict/CheckLoad.C +[import, lang:'c_cpp'](CheckLoad.C) diff --git a/examples/root-simple-3.11/CMakeLists.txt b/examples/root-simple-3.11/CMakeLists.txt index da3f181..b9e9362 100644 --- a/examples/root-simple-3.11/CMakeLists.txt +++ b/examples/root-simple-3.11/CMakeLists.txt @@ -1,3 +1,5 @@ + +## [main] cmake_minimum_required(VERSION 3.11) project(RootSimpleExample311 LANGUAGES CXX) @@ -14,6 +16,7 @@ target_compile_options(ROOT::Core INTERFACE "${ROOT_CXX_FLAG_LIST}") add_executable(RootSimpleExample311 SimpleExample.cxx) target_link_libraries(RootSimpleExample311 PUBLIC ROOT::Physics) +## [main] enable_testing() add_test(NAME RootSimpleExample311 COMMAND RootSimpleExample311) diff --git a/examples/root-simple-3.11/README.md b/examples/root-simple-3.11/README.md new file mode 100644 index 0000000..9e34fbc --- /dev/null +++ b/examples/root-simple-3.11/README.md @@ -0,0 +1,11 @@ +# 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) diff --git a/examples/root-simple-3.11/SimpleExample.cxx b/examples/root-simple-3.11/SimpleExample.cxx index 82fe026..9534202 100644 --- a/examples/root-simple-3.11/SimpleExample.cxx +++ b/examples/root-simple-3.11/SimpleExample.cxx @@ -1,5 +1,5 @@ - #include + int main() { TLorentzVector v(1,2,3,4); v.Print(); diff --git a/examples/root-simple/CMakeLists.txt b/examples/root-simple/CMakeLists.txt index c85e32a..741c219 100644 --- a/examples/root-simple/CMakeLists.txt +++ b/examples/root-simple/CMakeLists.txt @@ -21,6 +21,7 @@ set_property(TARGET ROOT::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS ${ROOT_CXX_FLAG_LIST}) ## [setup_properties] +# Adding an exectuable program and linking to needed ROOT libraries ## [add_and_link] add_executable(RootSimpleExample SimpleExample.cxx) target_link_libraries(RootSimpleExample PUBLIC ROOT::Physics) diff --git a/examples/root-simple/README.md b/examples/root-simple/README.md new file mode 100644 index 0000000..5515653 --- /dev/null +++ b/examples/root-simple/README.md @@ -0,0 +1,10 @@ +# A Simple ROOT Project + +This is a minimal example of a ROOT project using the target system and without a dictionary. + +#### examples/root-simple/CMakeLists.txt +[import:'main', lang:'cmake'](CMakeLists.txt) + +#### examples/root-simple/SimpleExample.cxx + +[import](SimpleExample.cxx) diff --git a/examples/root-simple/SimpleExample.cxx b/examples/root-simple/SimpleExample.cxx index 82fe026..9534202 100644 --- a/examples/root-simple/SimpleExample.cxx +++ b/examples/root-simple/SimpleExample.cxx @@ -1,5 +1,5 @@ - #include + int main() { TLorentzVector v(1,2,3,4); v.Print(); diff --git a/specifics/ROOT.md b/specifics/ROOT.md index 3ee9ad0..2773830 100644 --- a/specifics/ROOT.md +++ b/specifics/ROOT.md @@ -7,7 +7,7 @@ ROOT is a C++ Toolkit for High Energy Physics. It is huge. There are really a lo ROOT supports config file discovery, so you can just do: -[import:'find_package', lang:'cmake'](../examples/root-example/CMakeLists.txt) +[import:'find_package', lang:'cmake'](../examples/root-simple/CMakeLists.txt) to attempt to find ROOT. If you don't have your paths set up, you can pass `-DROOT_DIR=$ROOTSYS/cmake` to find ROOT. (But, really, you should source `thisroot.sh`) @@ -19,20 +19,18 @@ ROOT provides a utility to set up a ROOT project, which you can activate using ` ROOT does not correctly set up it's imported targets. To fix this error, you'll need something like: -[import:'setup_properties', lang:'cmake'](../examples/root-example/CMakeLists.txt) +[import:'setup_properties', lang:'cmake'](../examples/root-simple/CMakeLists.txt) In CMake 3.11, you can replace that last function call with: -```cmake -target_include_directories(ROOT::Core IMPORTED INTERFACE "${ROOT_INCLUDE_DIRS}") -target_compile_options(ROOT::Core IMPORTED INTERFACE "${ROOT_CXX_FLAG_LIST}") -``` + +[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: -[import:'add_and_link', lang:'cmake'](../examples/root-example/CMakeLists.txt) +[import:'add_and_link', lang:'cmake'](../examples/root-simple/CMakeLists.txt) ## Dictionary generation @@ -42,7 +40,7 @@ Dictionary generation is ROOT's way of working around the missing reflection fea * Your class implementation should have `ClassImp(MyClassName)` in it * You should have a file with a name that ends with `LinkDef.h` -The `LinkDef.h` file follows a specific formula and tells ROOT what parts to generate dictionaries for. +The `LinkDef.h` file follows a [specific formula][linkdef-root] and tells ROOT what parts to generate dictionaries for. To generate, you should include the following in your CMakeLists: @@ -50,20 +48,22 @@ To generate, you should include the following in your CMakeLists: include("${ROOT_DIR}/modules/RootNewMacros.cmake") 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. To generate a file: ```cmake -root_generate_dictionary(G__MyExample MyExample.h LINKDEF SimpleLinkDef.h) +root_generate_dictionary(G__Example Example.h LINKDEF ExampleLinkDef.h) ``` -Then include `G__MyExample.cxx` in your sources when you make the library. +The final argument, listed after `LINKDEF`, must have a name that ends in `LinkDef.h`. This command will create three files. If you started output name with `G__`, that will be removed from the name, otherwise it will use the name given; this must match the final output library name you will soon be creating. Assuming this is `${NAME}`: -## Example: Minimal +* `${NAME}.cxx`: This file should be included in your sources when you make the library. +* `lib{NAME}.rootmap` (`G__` prefix removed): The rootmap file in plain text +* `lib{NAME}_rdict.pcm` (`G__` prefix removed): A ROOT file -#### examples/root-example/CMakeLists.txt -[import:'main', lang:'cmake'](../examples/root-example/CMakeLists.txt) +The final two output files must sit next to the library output. This is done by checking `CMAKE_LIBRARY_OUTPUT_DIRECTORY` (it will not pick up local target settings). If you have a libdir set but you don't have (global) install locations set, you'll also need to set `ARG_NOINSTALL` to `TRUE`. + +[linkdef-root]: https://root.cern.ch/selecting-dictionary-entries-linkdefh -## Example: Dictionary -[import:'main', lang:'cmake', title:"CMakeLists.txt"](../examples/root-example-dict/CMakeLists.txt)