Skip to content

Commit

Permalink
Better faq
Browse files Browse the repository at this point in the history
  • Loading branch information
adamryczkowski committed Jun 16, 2019
1 parent 7a7201d commit 024d751
Showing 1 changed file with 26 additions and 16 deletions.
42 changes: 26 additions & 16 deletions docs/faq.rst
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
Frequently Asked Questions
==========================

Q: How does the system mix with the plain CMake? What if I define some targets directly in ``CMakeLists.txt``?
A: No problem.

How does the system mix with the plain CMake?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

First of all, remember that the ``CMakeLists.txt`` can be run twice - once for superbuild, and then second time for the project build. So unless you are sure there will be no superbuild run, you should desing your code in such a way, that the targets are defined only in the proper phase (usually in the project build, unless they define external projects). To tell if the current phase is superbuild or project build use a boolean variable ``IS_SUPERBUILD``.
Beetroot-managed targets can be interact with the "legacy" CMake code, if you want to use each target as either dependency, or the dependees - but not both.

Targets defined in ``CMakeLists.txt`` targets will work.
First thing to be aware of is that the Beetroot by default can automatically decide to employ the superbuild idiom. In this case the ``CMakeLists.txt`` will be run *twice* in a single build - once, directly called by you when you type ``cmake ..`` or simmilar, and second time, when you type ``make``, in the so-called project build. So unless you are sure there will be no superbuild run, you should desing your code in such a way, that the targets are defined only in the proper phase, usually in the project build, unless they define external projects. To tell if the current phase is superbuild or project build use a boolean variable ``IS_SUPERBUILD``.

If they need to depend on the targets governed by the Beetroot you need to remember two things.
#. Is to know or get the name of the target. If the target names are fixed, you simply use that name, as usually. If targets are not fixed you need to get the name of the targets using the functions ``get_target()`` or ``get_existing_target()``.
#. Beetroot targets will not get defined until you call the ``finalize()`` function, so write any code depending on them after the call to that function.
Another issue is the existance of calls to the global target-modifying functions, such as ``??``. If you need to use them, just remember that they still affect the whole project including the beetroot-managed code, otherwise you are fine. Sincerelly, the best thing to do is to hunt them down using "find" method in your code editor and turn them into the target-specific equivalents.

If you are in a reverse situation - you manually defined target which is a dependency of target(s) inside the Beetroot, you need to
1. Write the dependency code (usually ``target_link_libraries``) inside the ``apply_dependency_to_target()``. If you need to write this function, make sure you put flag ``LINK_TO_DEPENDEE`` inside ``TEMPLATE_OPTIONS`` to make sure you don't interfere with the linking process.
2. Make sure you define the targets *before* the call to ``finalize()``.
Usage of the "legacy" target as a dependency
---------------------------------------------

Targets defined in the ``CMakeLists.txt`` will be accessible to the beetroot-managed code as the possible dependency *if they are defined before the call to the ``finalize()``*. You would then need to link with those targets manually in the body of the function ``apply_dependency_to_target()``.

"Legacy" target depends on the target(s) managed by the Beetroot
----------------------------------------------------------------

Beetroot can designate the name of the managed targets itself, so if the "legacy" targets need to depend on the targets governed by the Beetroot, you need to either know those names because you defined them as being fixed, or dynamically get them. You get the name of the targets using the function ``get_target_name()``. Beetroot targets will not get defined until you call the ``finalize()`` function, so write any code depending on them after the call to that function.

What does it take to turn a "legacy" CMake code into being managed by the Beetroot?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

First of you need to isolate the code that defines each target, and put it into a separate ``targets.cmake``. In case if that would lead to a significant code duplication, you have an option to define several targets in one ``targets.cmake`` file.

Inside the ``targets.cmake`` you need to separate the code into two groups and put them accordingly to its purpose:

#. The code that defines the targets and its properties (such as a call to the ``add_library()`` or ``target_compile_definitions()``) and does not mention any dependee - put into a definition of ``generate_targets()``.

#. The code that mentions the dependee. If it is just a call to the ``target_link_libraries(DEPENDEE_TARGET OUR_TARGET)`` you can simply remove it, since Beetroot would call it by itself. If it involves something more unusual, like calls to ``add_custom_command()`` and ``target_sources()`` (common pattern when you have a code generator) - put that code into an ``apply_dependency_to_target()``.



Q: How exactly Beetroot can interefere with my own CMake code?
A: Beetroot goes to great lengths to make sure it will not interfere with any other CMake code. It is still possible (although unlikely) to interfere with the Beetroot project. In particular you should not:
#. Call Beetroot code (in particular ``finalize``) after you (re)defined functions that have the same name as the ones that are used by the Beetroot. All internal Beetroot functions start with the underscore.
#. Use any of the reserved global properties. All global properties that the Beetroot uses start with double underscore.

Is there any unexpected way the Beetroot can interefere with my own CMake code?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

CMake does not support namespaces, so however unlikely, it is still possible that your own code can interfere with the internal workings of the Beetroot project. To stay clear of trouble you should remember that all internal Beetroot variables are prefixed with double underscore, and all functions with a single underscore. In future, they will have even more unique prefix.

0 comments on commit 024d751

Please sign in to comment.