.. _pm3-cmake-doc:


|project|'s Share Of |cmake|
===============================================================================

Introduction
--------------------------------------------------------------------------------

This section describes the set of |project|'s own set of |cmake| functions (or
macros) fed from the :file:`cmake_support` directory. Those could be easily put
into three categories of varying relevance for you:

1. Functions used to integrate your contribution into |project|. Its all about
   adding files to the documentation, declaring unit tests and code management.
   Almost all of them have their home in the file :file:`PROMOD3.cmake`.

2. Then there is a set of functions needed to set up |cmake| itself. Those are
   little helpers to find tools, external packages and such. These are found in
   :file:`Find<DEPENDENCY>.cmake` files.

3. The last and probably least relevant category for you is also to be found in
   :file:`PROMOD3.cmake`. There is a set of functions used to define more
   |cmake| functionality. You only need to consider those if you dare to extend
   this set up.

Best practices for using our home-brew |cmake| functions are found in the
various :file:`CMakeLists.txt` files in the project's directory tree.

Functions For Module/ Action Maintenance
--------------------------------------------------------------------------------

Module definition
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Default dependencies in a module ``NAME``:

- ``_NAME`` depends on ``NAME_pymod`` and ``promod3_NAME`` (if that exists)
- ``promod3_NAME`` depends on ``promod3_NAME_headers``

.. cmake:command:: module

  .. code-block:: cmake

                  module(NAME name
                         SOURCES source1 source2
                         HEADERS header1 header2 [IN_DIR dir]
                                 [header3 header4 [IN_DIR dir]]
                         [DEPENDS_ON dep1 dep2]
                         [HEADER_OUTPUT_DIR dir]
                         [LINK link_cmds])

  Define a |project| module from a set of |C++| files. This will define the
  following make targets (where ``NAME`` is the provided module name):

  - ``promod3_NAME``: builds library :file:`libpromod3_NAME`
  - ``promod3_NAME_headers``: copies all header files

  The parameters are:

  ``NAME``
    Specify the name of the module.

  ``SOURCES``
    Set of |C++| source files to be compiled.

  ``HEADERS``
    Set of |C++| header files to be copied. If the headers are located in
    a different directory than the current one, you must group them by directory
    and provide the directory name ``dir`` with ``IN_DIR dir`` after listing the
    header files in said directory.

  ``DEPENDS_ON``
    Add dependencies on other targets (e.g. ``promod3_MOD`` for another
    |project| module).

  ``HEADER_OUTPUT_DIR``
    Define alternative folder to which to copy header files. Default is
    :file:`promod3/NAME`.

  ``LINK``
    Add dependencies to external libraries. You may use some predefines set of
    libraries here, such as ``${OST_LIBRARIES}`` and ``${BOOST_LIBRARIES}``.


.. cmake:command:: pymod

  .. code-block:: cmake

                  pymod(NAME name
                        CPP source1 source2
                        PY source source2 [IN_DIR dir] 
                           [source3 source4 [IN_DIR dir]]
                           [TRANSLATE dict END_TRANSLATE]
                        [OUTPUT_DIR dir]
                        [DEPENDS_ON dep1 dep2]
                        [NEED_CONFIG_HEADER])

  Define the |python| interface of a |project| module from a set of |C++|
  wrappers and/or Python files. This will define the following make targets
  (where ``NAME`` is the provided module name):

  - ``_NAME``: builds library :file:`_NAME` for |python| wrapper around |C++|
  - ``NAME_pymod``: copies (and/or translates) all |python| files

  The parameters are:

  ``NAME``
    Specify the name of the module.

  ``CPP``
    Set of |C++| source files to be compiled.

  ``PY``
    Set of |python| source files to be copied. If the files are located in
    a different directory than the current one, you must group them by directory
    and provide the directory name ``dir`` with ``IN_DIR dir`` after listing the
    header files in said directory.

    If a |python| source file needs to be translated by |cmake|, provide the
    dictionary after putting ``TRANSLATE``. This assumes a ``<FILE>.py.in`` for
    ``<FILE>.py``. ``END_TRANSLATE`` marks the end of the translation
    dictionary.

  ``OUTPUT_DIR``
    Define alternative folder (within Python tree) to place python files.
    Default is :file:`promod3/NAME`.

  ``DEPENDS_ON``
    Add dependencies on other targets (e.g. ``promod3_MOD`` for another
    |project| module). 

  ``NEED_CONFIG_HEADER``
    Makes the module depending on the config_header target, which provides the
    headers in the :file:`config` directory.


.. cmake:command:: convert_module_data

  .. code-block:: cmake

                  convert_module_data(MODULE name
                                      FILE file
                                      SCRIPT script
                                      [ARGS args])

  Use a Python script to convert a portable binary file to a non-portable one.
  Calls ``python SCRIPT in_path out_path ARGS`` (with access to |ost_s| and 
  |project|),
  where ``in_path`` = :file:`portable_FILE`
  (within path of current :file:`CMakeLists.txt`)
  and ``out_path`` = :file:`share/promod3/MODULE_data/FILE`
  (within the :file:`stage` directory).
  If given, ``args`` can also be multiple arguments (must be put in "" then).


Unit Tests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. cmake:command:: promod3_unittest

  .. code-block:: cmake

                  promod3_unittest(MODULE name
                                   SOURCES source1 [source2 ...]
                                   [LINK library1/ linker flag1 [library2/ linker flag2 ...]]
                                   [DATA data1 [data2 ...]]
                                   [TARGET target]
                                   [BASE_TARGET base_target])

  Add unit tests to |project|. Unit tests should go in module-wise so all
  source files containing test code go by a single call of
  :cmake:command:`promod3_unittest`. Test data also needs to be registered
  here, since it will be copied to the build directory. That way, inside your
  code you do not need to set a special path to your data. Additionally, since
  it is out of the source tree, you may change test data as you like, without
  the |git| repository noticing. Calling :cmake:command:`promod3_unittest` will
  create a set of certain ``make`` targets for you, beside feeding ``codetest``.

  The parameters are:

  ``MODULE``
    Specify the name of the module these tests are made for. Needs to be set,
    needs to be a single word. Ends up in ``make help`` as a prefix, nothing
    will break if it does not match the name of any existing module.

  ``SOURCES``
    Describe a set of files hosting unit test code here. If its a wild mix of
    |C++| and |python| files does not matter, |cmake| will sort this out for
    you. But the programming language makes a difference for the ``make``
    targets produced. |C++| files will all be gathered in a single
    ``test_suite_<MODULE>_run`` target (there is also a ``_xml`` target but
    this is for tools for automated testing). |python| code works on a 'one
    target per file' basis. So :file:`test_foo.py` will have own target
    ``test_foo.py_run``.

  ``LINK``
    Add additional libraries and linker flags for |C++| source files. Has no
    effect on |python| tests.

  ``DATA``
    Define test data. Instead of giving data directories its own
    :file:`CMakeLists.txt`, those files are added here. Usually located
    somewhere in a dedicated :file:`data` subtree, files need to be given with
    a path relative to this directory. That path will then be created in the
    build directory.

  ``TARGET``
    This defines an additional dependency for the unit test. That is, before
    running this unit test, this target will be built.

  ``BASE_TARGET``
    This defines an alternative base target to which to add this unit test.
    By default all unit tests are registered to be executed with the 
    ``codetest`` target. This can be overridden by using this argument.

Documentation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. cmake:command:: add_doc_source

  .. code-block:: cmake

                  add_doc_source(NAME name
                                 RST rst1 [rst2...])

  Add reStructuredText sources for the doc build system. This is most preferable
  used in :file:`doc` directories for keeping the documentation sorted per
  module. This does not create any ``make`` targets. Lists filled here will all
  be evaluated in the :file:`doc/CMakeLists.txt` of the repository root.

  The parameters are:

  ``NAME``
    Specify the name of the module this branch of documentation belongs to.
    Needs to be set, needs to be a single word. Using module names is best
    practice, while nothing will break if it does not refer to an existing one.
    You will find a directory in :file:`doc/source` with that name in the build
    root.

  ``RST``
    Describe a set of files containing the documentation. Feed it a single file
    name or a |cmake| list.

.. cmake:command:: add_doc_dependency

  .. code-block:: cmake

                  add_doc_dependency(NAME name
                                     DEP dependency1 [dependency2...])

  Add a dependency to the doc build system. For an existing name, add some
  dependencies when it comes to building documentation. Mostly for internal use.

  The parameters are:

  ``NAME``
    Specify a name the dependencies belong to. This name needs to be already
    known in the doc build system. Names of |python| modules are good, otherwise
    names introduced by :cmake:command:`add_doc_source` work well. Dependencies
    will be create for all reStructuredText files listed by
    :cmake:command:`add_doc_source` under this name and for all ``make``
    targets related to the documentation.

  ``DEP``
    Hand over a dependency here or a |cmake| list. Files work, if given with
    absolute path.

Actions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. cmake:command:: pm_action

  .. code-block:: cmake

                  pm_action(ACTION action-script
                            TARGET target)

  Add an action to |project|. Actions are scripts called by the ``pm`` launcher
  and should all live in the :file:`actions` directory as executable files.
  Adding an action means connecting its file with the given target to be copied
  to the :file:`libexec` directory. No dedicated ``make`` target will be
  created.

  The parameters are:

  ``ACTION``
    Name of the action to be added. Should start with :file:`pm-`. Needs to be
    an existing file in the same directory as the invoking
    :file:`CMakeLists.txt`.

  ``TARGET``
    Provide a ``make`` target to trigger copying the action's script file. The
    target has to be created **before** any action may be attached to it.

.. Finding packages
.. -----------------

.. Extending |cmake|
.. -----------------

..  LocalWords:  cmake PROMOD CMakeLists txt promod unittest codetest xml py
..  LocalWords:  libexec reStructuredText RST subtree rst DEP
