Building Modules with CMake¶
If you haven’t follow the initial example in Hello, Cyclus! [C++], you should get the Cycstub repo by either cloning the repository or by downloading the zip file (see Hello, Cyclus! [C++] for further instructions).
The Cycstub repo provides a number of critical tools for building your own module:
install.py
: a basic installation scriptcmake
: a directory of CMake modules (e.g. finding Cyclus and its dependencies on your system)cmake/UseCyclus.cmake
: a CMake module that defines important Cyclus module build/install macrosCMakeLists.txt
: a generic CMake driver that will work for most build configurations out of the boxsrc/CMakeLists.txt
: a starter file that determines how the module build is executed (utilizing the macros inUseCyclus.cmake
)
The remaining portion of this page covers the various features provided in
UseCyclus.cmake
and their use in the src
directory’s CMakeLists.txt
file.
Using UseCyclus¶
UseCyclus.cmake
defines the following macros for building and installing
Cyclus modules:
USE_CYCLUS
: informs the build system of the source files related to an archetype implementation and its tests, if tests existINSTALL_CYCLUS_MODULE
: install a collection of archetypes that all belong to the same moduleINSTALL_CYCLUS_STANDALONE
: install an archetype as a standalone module
UseCyclus Vocabulary¶
The UseCyclus.cmake
macro suite uses the following terms:
lib_root
: The root name for the to-be-installed library (e.g.,MyAgent
for a standalone install ormy_module
for a module install).src_root
: The common prefix for all source files required to implement and test an archetypes. For example if yoursrc_root
ismy_agent
, the macro suite will be aware of the following files:my_agent.cc
my_agent.h
my_agent_tests.cc
my_agent_tests.h
lib_dir
: The install directory relative the Cyclus library installation directory. For example, iflib_dir
is blank (i.e. “”), the module will be installed in$CYCLUS_INSTALL_PREFIX/lib/cyclus/
; iflib_dir
is something else, e.g.my_module_dir
, the module will be installed in$CYCLUS_INSTALL_PREFIX/lib/cyclus/my_module_dir/
. The value of$CYCLUS_INSTALL_PREFIX
can be queried by$ cyclus --install-path
test_driver
: (optional) A custom GTest test driver. This is an advanced feature which will not be needed by most archetype developers.
UseCyclus Macro Arguments¶
Each UseCyclus.cmake
macro has arguments included in the above vocabulary
listing:
USE_CYCLUS
:USE_CYCLUS(lib_root src_root)
INSTALL_CYCLUS_STANDALONE
:INSTALL_CYCLUS_STANDALONE(lib_root src_root lib_dir [test_driver])
INSTALL_CYCLUS_MODULE
:INSTALL_CYCLUS_MODULE(lib_root lib_dir [test_driver])
Examples¶
Standalone Installation¶
Through the hello_world example, three standalone modules are installed
using a src/CMakeLists.txt
file that looks something like
INSTALL_CYCLUS_STANDALONE("TutorialFacility" "tutorial_facility" "tutorial")
INSTALL_CYCLUS_STANDALONE("TutorialInst" "tutorial_inst" "tutorial")
INSTALL_CYCLUS_STANDALONE("TutorialRegion" "tutorial_region" "tutorial")
This setup will install three shared object libraries in
$CYCLUS_INSTALL_PREFIX/lib/cyclus/tutorial
:
libTutorialFacility.so
(*nix) orlibTutorialFacility.dylib
(mac)libTutorialInstitution.so
(*nix)libTutorialInstitution.dylib
(mac)libTutorialRegion.so
(*nix)libTutorialRegion.dylib
(mac)
and three unit test executables in $CYCLUS_INSTALL_PREFIX/bin
:
TutorialFacility_unit_tests
TutorialInstitution_unit_tests
TutorialRegion_unit_tests
Module Installation¶
A valid criticism of the hello world standalone approach is that a lot of libraries and executables are generated for three modules that are grouped together. We can do better!
What if we wanted to install one module named helloworld
? Specifically, we
would want:
a single shared object library in
$CYCLUS_INSTALL_PREFIX/lib/cyclus/tutorial
namedlibhelloworld.so
(*nix) orlibhelloworld.dylib
(mac)a single unit test executable in
$CYCLUS_INSTALL_PREFIX/bin
namedhelloworld_unit_tests
where both incorporate the TutorialFacility
, TutorialInstitution
, and
TutorialRegion
archetypes.
Such behavior is pretty simple to achieve. We first must call UseCyclus
on
each of our source file roots to inform the build system of their presence and
follow up with a call to INSTALL_CYCLUS_MODULE
:
USE_CYCLUS("helloworld" "tutorial_facility")
USE_CYCLUS("helloworld" "tutorial_inst")
USE_CYCLUS("helloworld" "tutorial_region")
INSTALL_CYCLUS_MODULE("helloworld" "tutorial")