DuneInstance ============ This module can be used to generate explicit template instantiations. Suppose you have a template test function that you want to call for a number of template arguments. You want to explicitly instantiate the function for each set of template arguments, and put the instantiation into its own translation unit. (This can be beneficial in that it limits the amount of code that the optimizer sees at once, and thus it can reduce both memory and cpu requirements during compilation.) A typical workflow is: .. code-block:: cmake dune_instance_begin(FILES mytest.cc mytest.hh) foreach(TYPE IN ITEMS bool char int double) dune_instance_add(ID "${TYPE}" FILES mytest_instance.cc) endforeach() dune_instance_end() list(FILTER DUNE_INSTANCE_GENERATED INCLUDE REGEX [[\\.cc$]]) dune_add_test(NAME mytest SOURCES ${DUNE_INSTANCE_GENERATED}) The call to :cmake:command:`dune_instance_begin()` reads ``mytest.cc.in`` and ``mytest.hh.in`` and splits them into embedded templates and other content. It will replace occurrences of ``@VAR@`` now in the other content and save the result for later. The call to :cmake:command:`dune_instance_add()` occurs in a loop. Each call will instantiate the embedded templates extracted earlier to replace an occurrence of ``@TYPE@`` by the value of the variable ``TYPE`` set in the for loop. Then files containing explicit instantiatons will be generated as ``mytest_instance_bool.cc``, ``mytest_instance_bool.cc``, etc, from a template file ``mytest_instance.cc.in``. The name of the generated files are the base file name from the template definition with the ``ID`` inserted before the extension. The name of the template file is the same base file name with ``.in`` appended. :cmake:command:`dune_instance_end()` is used to write ``mytest.cc`` and ``mytest.hh`` with the collected content from the embedded templates. The list of generated files will be available in the variable ``DUNE_INSTANCE_GENERATED``. The template files then look like this: ``mytest.cc.in``:: // @GENERATED_SOURCE@ #include #include int main() { MyTestSuite suite; #cmake @template@ suite.test<@TYPE@>(); #cmake @endtemplate@ return suite.good() ? EXIT_SUCCESS : EXIT_FAILURE; } ``mytest.hh.in``:: // @GENERATED_SOURCE@ #include #cmake @template@ extern template void MyTestSuite::test<@TYPE@>(); #cmake @endtemplate@ ``mytest_instance.cc.in``:: // @GENERATED_SOURCE@ #include #include template void MyTestSuite::test<@TYPE@>(); The ``@GENERATED_SOURCE@`` substitution is good practice, it tells a human reader that this file was generated and what the template file was, and it hints editors to go into read-only mode. The begin of an embedded template is marked by a line containing ``@template@`` or ``@template NAME@``. Leaving off the name is equivalent to an empty name. ``dune_instance_add(TEMPLATE NAME)`` will only instantiate embedded templates whose name matches and ignore all others. The end of an embedded template is marked by a line containing ``@endtemplate@`` or ``@endtemplate NAME@``. If a name is given, it must match the name of the embedded template it closes. If no name is given (or the name is empty), that check is omitted. There may be arbitrary characters on the same line before or after the begin and end markers. These are ignored, so you can use them for comments or to trick your editor into proper indentation. The one exception is that the line surrounding the marker may not contain any ``@`` characters to avoid ambiguities. The generation is done using the cmake command :dune:cmake-command:`configure_file` for template files and ``string(CONFIGURE ...)`` for template strings. These simply substitute the current variable values, so make sure to set up the variables to substitute before calling :cmake:command:`dune_instance_add()` or :cmake:command:`dune_instance_begin()`. Refrain from using substitutions that begin with an underscore (``@_my_local_var@``). The generation functions in this module use such names for their local variables and may hide the variable you are trying to substitute. .. cmake:command:: dune_instance_begin Prepare generation of a family of explicit instantiations. .. code-block:: cmake dune_instance_begin(FILES ...) ``FILES`` List of template files with embedded templates. Read the given template files, and extract embedded templates. Run the generator on the remaining file content with the variables currently in effect. .. note:: A matching :cmake:command:`dune_instance_end()` is required. Since information is communicated through variables in the callers scope, :cmake:command:`dune_instance_begin()` / :cmake:command:`dune_instance_end()` blocks may not be nested inside the same scope. Since a function is a new scope, it may safely contain a :cmake:command:`dune_instance_begin()` / :cmake:command:`dune_instance_end()` block, even if it is itself called from one. .. cmake:command:: dune_instance_add Instantiate a template with the currently set variable values. .. code-block:: cmake dune_instance_add( FILES ... ID [TEMPLATE ] ) ``FILES`` List of template file specifications. These are usually the names of template files with the ``.in`` extension removed. See the ``ID`` parameter for details. ``ID`` Used to build the names of generated files. Each file specification together with this id is given to :cmake:command:`dune_instance_from_id()` to determine the name of a template file and the name of an instance file. To get unique instance file names this ID should usually be a list of variable values joined together by ``_``. Specifically, each file specification may be of the form ``template_file_name:base_instance_file_name``, or it may be a single token not containing ``:``. In the latter case, if that token contains a trailing ``.in``, that is removed and the result is the base instance file name. The base instance file name has the ``.in`` appended again to form the template file name. The template file name is used as-is to generate files from. The ID is mangled by replacing any runs of non-alphanumeric characters with an underscore ``_``, and stripping any resulting underscore from the beginning and the end. The result is inserted before any extension into the base instance file name to form the instance file name. ``TEMPLATE`` Instantiate embedded templates by this name. Defaults to an empty name, matching embedded templates without name. Instantiate any embedded templates that match the given template name, substituting the current variables values. Then, generate files according the the file specifications in the template, doing substitutions as well. .. cmake:command:: dune_instance_end Close a block started by :cmake:command:`dune_instance_begin()`, and write the files generated from the templates given there. .. code-block:: cmake dune_instance_end() Write the files generated from the template files given in :cmake:command:`dune_instance_begin()`, including any content generated from embedded templates in :cmake:command:`dune_instance_add()`. .. cmake:command:: dune_instance_parse_file_spec .. dune:internal:: Parse a file specification into a template file name and an instance file name. .. code-block:: cmake dune_instance_parse_file_spec( ) ``spec`` File specification to parse. ``template-var`` Variable name receiving the template file name. It may be empty. ``instance-var`` Variable name receiving the instance file name. It may be empty. The file specification can be the name of a template file if it has ``.in`` at the end, or the name of an instance file if it doesn't. The name of the other file is obtained by appending or removing ``.in``, as applicable. Both file names can also be given explicitly in the form ``template_file_name:instance_file_name``. .. note:: This is the function use to parse the file specifications in :cmake:command:`dune_instance_begin()`. It is also used as a helper in :cmake:command:`dune_instance_from_id()` to determine template file name and base instance file name. .. cmake:command:: dune_instance_from_id .. dune:internal:: Determine a template file name and an instance file name from a file specification and a unique id. .. code-block:: cmake dune_instance_from_id( ) ``file-spec`` File specification to interpret. ``id`` The id specification. This should uniquely identify an instance. ``template-var`` Variable name receiving the template file name. It may be empty. ``instance-var`` Variable name receiving the instance file name. It may be empty. The file specification is handed to :cmake:command:`dune_instance_parse_file_spec()` to determine a template file name and a *base* instance file name. The ID is mangled by replacing any runs of non-alphanumeric characters with an underscore ``_``, and stripping any resulting underscore from the beginning and the end. The result is inserted before any extension into the base instance file name to form the instance file name. .. note:: This is the function use to parse the file specifications given in ``dune_instance_add(FILES ...)``. .. cmake:command:: dune_instance_apply_bindir .. dune:internal:: Modify a filename to be relative to ``CMAKE_CURRENT_BINARY_DIR``. .. code-block:: cmake dune_instance_apply_bindir() ``filename-var`` The name of the variable containing the file name. This is used to mimic the behaviour of :dune:cmake-command:`configure_file`. If the file name given is not absolute, it is modified by prepending ``${CMAKE_CURRENT_BINARY_DIR}``. .. cmake:command:: dune_instance_generate_file .. dune:internal:: Convenience replacement for :dune:cmake-command:`configure_file`: enable standard substitutions, register files as generated, and flag the same file being generated twice. .. code-block:: cmake dune_instance_generate_file(