From 2d7cb87893284d64e11f8451838a0a5bdf12fcc8 Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Wed, 28 Mar 2018 20:50:38 +0200 Subject: [PATCH] Adding ROOT, moving to term --- README.md | 8 ++++-- book.json | 2 +- chapters/installing.md | 8 +++--- chapters/running.md | 18 ++++++------ examples/root-example-dict/CMakeLists.txt | 24 ++++++++++++++++ examples/root-example-dict/CheckLoad.C | 11 ++++++++ examples/root-example-dict/MyExample.cxx | 6 ++++ examples/root-example-dict/MyExample.h | 14 ++++++++++ examples/root-example-dict/SimpleLinkDef.h | 13 +++++++++ examples/root-example/CMakeLists.txt | 20 ++++++++++++++ examples/root-example/MyExample.cxx | 7 +++++ specifics/ROOT.md | 32 ++++++++++++++++++++++ 12 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 examples/root-example-dict/CMakeLists.txt create mode 100644 examples/root-example-dict/CheckLoad.C create mode 100644 examples/root-example-dict/MyExample.cxx create mode 100644 examples/root-example-dict/MyExample.h create mode 100644 examples/root-example-dict/SimpleLinkDef.h create mode 100644 examples/root-example/CMakeLists.txt create mode 100644 examples/root-example/MyExample.cxx create mode 100644 specifics/ROOT.md diff --git a/README.md b/README.md index e434bcc..28b96c6 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,10 @@ Certainly there are no shortage of problems when building. But I think that, in 2017, we have a very good solution to quite a few of those problems. It's CMake. Not CMake 2.8 though; that was released before C++11 even existed! Nor the horrible examples out there for CMake (even those posted on KitWare's own tutorials list). -I'm talking about Modern CMake. CMake 3.1+, maybe even CMake 3.8+! +I'm talking about [Modern CMake]. CMake 3.1+, maybe even CMake 3.11+! It's clean, powerful, and elegant, so you can spend most of your time coding, not adding lines to an unreadable, unmaintainable Make (Or CMake 2) file. +And CMake 3.11 is significantly faster, as well! + {% hint style='working' %} This document is a work in progress. @@ -68,5 +70,7 @@ And, since CMake will dumb itself down to the minimum required version in your C You should *at least* install it locally. It's easy (1-2 lines in many cases), and you'll find that 5 minutes of work will save you hundreds of lines and hours of CMakeLists.txt writing, and will be much easier to maintain in the long run. -This book tries to solve the problem of the poor examples and best practices that you'll find proliferating the web. A nice, slighly dated post with a similar intent can be found [here](https://rix0r.nl/blog/2015/08/13/cmake-guide/). You might also find that helpful for a fast introduction. +This book tries to solve the problem of the poor examples and best practices that you'll find proliferating the web. A nice, slightly dated post with a similar intent can be found [here](https://rix0r.nl/blog/2015/08/13/cmake-guide/). You might also find that helpful for a fast introduction. + +[Modern CMake]: https://steveire.wordpress.com/2017/11/05/embracing-modern-cmake/ diff --git a/book.json b/book.json index 3b47cc8..31c31d0 100644 --- a/book.json +++ b/book.json @@ -2,5 +2,5 @@ "title": "Modern CMake", "description": "A guide to writing simple, powerful, and clean CMake 3.1+ builds.", "author": "Henry Schreiner", - "plugins": ["hints","terminal@https://github.com/henryiii/gitbook-plugin-terminal.git"] + "plugins": ["hints","term"] } diff --git a/chapters/installing.md b/chapters/installing.md index 6f88b11..7961b26 100644 --- a/chapters/installing.md +++ b/chapters/installing.md @@ -12,16 +12,16 @@ You can [download CMake from KitWare][cmake-download]. This is how you'll probab On Linux, there are binaries provided, but you'll need to pick an install location. If you already use `~/.local` for user-space packages, the following single line command will get CMake for you [^1]: -{% terminal %} +{% term %} ~ $ wget -qO- "https://cmake.org/files/v3.9/cmake-3.9.4-Linux-x86_64.tar.gz" | tar --strip-components=1 -xz -C ~/.local -{% endterminal %} +{% endterm %} If you just want a local folder with CMake only: -{% terminal %} +{% term %} ~ $ mkdir -p cmake39 && wget -qO- "https://cmake.org/files/v3.9/cmake-3.9.4-Linux-x86_64.tar.gz" | tar --strip-components=1 -xz -C cmake39 ~ $ export PATH=`pwd`/cmake39/bin:$PATH -{% endterminal %} +{% endterm %} You'll obviously want to append to the PATH every time you start a new terminal, or add it to your `.bashrc` or to an [LMod] system. diff --git a/chapters/running.md b/chapters/running.md index 2863f54..3850a71 100644 --- a/chapters/running.md +++ b/chapters/running.md @@ -7,12 +7,12 @@ Unless otherwise noted, you should always make a build directory and build from Here's the CMake Build Procedure (TM): -{% terminal %} +{% term %} ~/package $ mkdir build ~/package $ cd build ~/package/build $ cmake .. ~/package/build $ make -{% endterminal %} +{% endterm %} You can replace the make line with `cmake --build .` if you'd like, and it will call `make` or whatever build tool you are using. You can follow it by `make install` or `cmake --build . --target install` if you want to install it. @@ -20,9 +20,9 @@ You can replace the make line with `cmake --build .` if you'd like, and it will Selecting a compiler must be done on the first run in an empty directory. It's not CMake syntax per-say, but you might not be familiar with it. To pick Clang: -{% terminal %} +{% term %} ~/package/build $ CC=clang CXX=clang++ cmake .. -{% endterminal %} +{% endterm %} That sets the environment variables in bash for CC and CXX, and CMake will respect those variables. This sets it just for that one line, but that's the only time you'll need those; afterwards CMake continues to use the paths it deduces from those values. @@ -30,9 +30,9 @@ That sets the environment variables in bash for CC and CXX, and CMake will respe You can build with a variety of tools; `make` is usually the default. To see all the tools CMake knows about on your system, run -{% terminal %} +{% term %} ~/package/build $ cmake --help -{% endterminal %} +{% endterm %} And you can pick a tool with `-G"My Tool"` (quotes only needed if spaces are in the tool name). You should pick a tool on your first CMake call in a directory, just like the compiler. Feel free to have several build directories, like `build/` and `buildXcode`. @@ -44,9 +44,9 @@ You set options in CMake with `-D`. You can see a list of options with `-L`, or Again, not really CMake, but if you are using a command line build tool like `make`, you can get verbose builds: -{% terminal %} +{% term %} ~/package/build $ VERBOSE=1 make -{% endterminal %} +{% endterm %} You can actually write `make VERBOSE=1`, and make will also do the right thing, though that's a feature of `make` and not the command line in general. @@ -58,4 +58,4 @@ These are common CMake options to most packages: * `-DCMAKE_BUILD_TYPE=` Pick from Release, RelWithDebInfo, Debug, or sometimes more. * `-DCMAKE_INSTALL_PREFIX=` The location to install to. System install on UNIX would often be `/usr/local` (the default), user directories are often `~/.local`, or you can pick a folder. -* `-D BUILD_SHARED_LIBS=` You can set this `ON` or `OFF` to control the default for shared libraries (the author can pick one vs. the other explicitly instead of using the default, though) \ No newline at end of file +* `-D BUILD_SHARED_LIBS=` You can set this `ON` or `OFF` to control the default for shared libraries (the author can pick one vs. the other explicitly instead of using the default, though) diff --git a/examples/root-example-dict/CMakeLists.txt b/examples/root-example-dict/CMakeLists.txt new file mode 100644 index 0000000..6024d72 --- /dev/null +++ b/examples/root-example-dict/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.1) + +project(RootExampleDict LANGUAGES CXX) + +find_package(ROOT CONFIG REQUIRED) +include("${ROOT_DIR}/modules/RootNewMacros.cmake") + +message(STATUS "Found ROOT: ${ROOT_VERSION} at ${ROOT_DIR}") + +string(REPLACE " " ";" ROOT_CXX_FLAG_LIST "${ROOT_CXX_FLAGS}") + +set_target_properties(ROOT::Core PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${ROOT_INCLUDE_DIRS}" + INTERFACE_COMPILE_OPTIONS "${ROOT_CXX_FLAG_LIST}" + ) + +include_directories(ROOT_BUG) +root_generate_dictionary(G__MyExample MyExample.h LINKDEF SimpleLinkDef.h) + +add_library(MyExample SHARED MyExample.cxx MyExample.h G__MyExample.cxx) +target_link_libraries(MyExample PUBLIC ROOT::Core) + +#enable_testing() +#add_test(NAME MyExample COMMAND ) diff --git a/examples/root-example-dict/CheckLoad.C b/examples/root-example-dict/CheckLoad.C new file mode 100644 index 0000000..ce20810 --- /dev/null +++ b/examples/root-example-dict/CheckLoad.C @@ -0,0 +1,11 @@ +{ +gSystem->Load("libMyExample"); +Simple s; +cout << s.GetX() << endl; +TFile *_file = TFile::Open("tmp.root", "RECREATE"); +gDirectory->WriteObject(&s, "MyS"); +Simple *MyS = nullptr; +gDirectory->GetObject("MyS", MyS); +cout << MyS->GetX() << endl; +_file->Close(); +} diff --git a/examples/root-example-dict/MyExample.cxx b/examples/root-example-dict/MyExample.cxx new file mode 100644 index 0000000..628515d --- /dev/null +++ b/examples/root-example-dict/MyExample.cxx @@ -0,0 +1,6 @@ +#include "MyExample.h" + +Double_t Simple::GetX() const {return x;} + +ClassImp(Simple) + diff --git a/examples/root-example-dict/MyExample.h b/examples/root-example-dict/MyExample.h new file mode 100644 index 0000000..4c3fc83 --- /dev/null +++ b/examples/root-example-dict/MyExample.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +class Simple { + Double_t x; + +public: + Simple() : x(2.5) {} + Double_t GetX() const; + + ClassDef(Simple,1) + +}; diff --git a/examples/root-example-dict/SimpleLinkDef.h b/examples/root-example-dict/SimpleLinkDef.h new file mode 100644 index 0000000..9e7fe5e --- /dev/null +++ b/examples/root-example-dict/SimpleLinkDef.h @@ -0,0 +1,13 @@ + +// 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-example/CMakeLists.txt b/examples/root-example/CMakeLists.txt new file mode 100644 index 0000000..4c28309 --- /dev/null +++ b/examples/root-example/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.1) + +project(RootExample LANGUAGES CXX) + +find_package(ROOT CONFIG REQUIRED) + +message(STATUS "Found ROOT: ${ROOT_VERSION} at ${ROOT_DIR}") + +string(REPLACE " " ";" ROOT_CXX_FLAG_LIST "${ROOT_CXX_FLAGS}") + +set_target_properties(ROOT::Core PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${ROOT_INCLUDE_DIRS}" + INTERFACE_COMPILE_OPTIONS "${ROOT_CXX_FLAG_LIST}" + ) + +add_executable(MyExample MyExample.cxx) +target_link_libraries(MyExample PUBLIC ROOT::Physics) + +enable_testing() +add_test(NAME MyExample COMMAND MyExample) diff --git a/examples/root-example/MyExample.cxx b/examples/root-example/MyExample.cxx new file mode 100644 index 0000000..82fe026 --- /dev/null +++ b/examples/root-example/MyExample.cxx @@ -0,0 +1,7 @@ + +#include +int main() { + TLorentzVector v(1,2,3,4); + v.Print(); + return 0; +} diff --git a/specifics/ROOT.md b/specifics/ROOT.md new file mode 100644 index 0000000..62ca1c8 --- /dev/null +++ b/specifics/ROOT.md @@ -0,0 +1,32 @@ +# 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. + + +## Finding ROOT + +ROOT supports config file discovery, so you can just do: + +```cmake +find_package(ROOT CONFIG) +``` + +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`) + +## The wrong way + +ROOT provides a utility to set up a ROOT project, which you can activate using `include(${ROOT_USE_FILE})`. This will automatically make ugly global variables for you. Don't use it. + +## The right way (Targets) + +ROOT does not correctly set up it's imported targets. To fix this error, you'll need something like: + +```cmake + +``` + +In CMake 3.11, you can just do: + +```cmake +``` +