You must sort headers in the following order : same module, framework libraries, bundles, external libraries, standard library. This way, this helps to make each header independent. The rule can be broken if a different include order is necessary to get a successful build.
You must sort headers in the following order : same module, framework libraries, modules, external libraries, standard library. This way, this helps to make each header independent. The rule can be broken if a different include order is necessary to get a successful build.
.. code-block :: cpp
...
...
@@ -125,6 +125,61 @@ Source and files
#include <map>
#include <vector>
.. rule :: Deprecated code
When you want to deprecate a piece of code, you need to warn other developers that the piece of code they are using is deprecated.
1. Use C++17 deprecated keyword (always)
The general rule is that you need to use the keyword ``[[deprecated("message")]]``.
The "message" should indicate **when** the function will be removed.
We use a timelapse of **two(2)** major versions before removing previously deprecated function. Ex: you want to remove ``functionA()`` and the current release is sight 20.0
the code will look like:
.. code-block :: cpp
[[deprecated("will be removed in sight 22.0, please use functionB().")]]
void functionA();
In case of deprecating an entire class, you may need to add the keyword on constructor, or at class level.
2. Use doxygen tag ``@deprecated`` (when needed)
In addition of the C++17 keyword, you may also want to add doxygen tag ``@deprecated``,
like the keyword it must contain the version where the function will be removed.
.. code-block :: cpp
/**
* @brief Computes the A value.
* @deprecated: will be removed in sight 22.0, please use functionB() instead.
**/
[[deprecated("will be removed in sight 22.0, please use functionB().")]]
void functionA();
3. Use a logging macro (carefully)
In some particular cases, you will need to use a macro that prints a deprecated message as output (console or SLM.log file).
Be careful when using macro, because if the function is widely used, it can slow down the whole application.
That's why deprecated macros are reserved for very specific usages:
- **slots**: since our slots can be called by an xml configuration, you may need to warn the user using a message.
- **piece of code**: when you want to deprecate just a piece of code (loop, if/else, ...).
- **Changing XML parameters/config**:when an xml configuration or a parameter is deprecated you may want to print a message when user use it.
.. code-block :: cpp
void SNegato2D::newImageDeprecatedSlot()
{
FW_DEPRECATED_MSG("The 'newImage' slot will be removed in sight 21.0. Call 'update' instead.", "21.0");
this->newImage();
}
For more details about macros, please check the doxygen page of spyLog.hpp
Naming conventions
------------------
...
...
@@ -230,7 +285,8 @@ Naming conventions
.. rule :: Enumerated type
An enumerated type name must be written in upper camel case. Labels must be written in capitals. If a ``typedef`` is defined, it follows the upper camel case standard.
An enumerated type name must be written in upper camel case. Labels must be written in capitals.
If a ``typedef`` is defined, it follows the upper camel case standard.
.. code-block :: cpp
...
...
@@ -503,7 +559,7 @@ Miscellaneous
.. rule :: Use of namespaces
You have to organize your code inside namespaces. By default, you will have at least one namespace for your module (application or bundle). Inside this namespace, it is recommended to split your code into sub-namespaces. This helps notably to prevent naming conflicts.
You have to organize your code inside namespaces. By default, you will have at least one namespace for your module (application or module). Inside this namespace, it is recommended to split your code into sub-namespaces. This helps notably to prevent naming conflicts.
It is forbidden to use the expression``using namespace`` in header files but it is allowed in implementation files. It is however recommended to use aliases in this latter case.
@@ -10,7 +10,7 @@ Sight and its dependencies are built with `CMake <http://www.cmake.org/>`_ .
Note that the minimal version of cmake to have is 3.9.
Each project (apps, bundles, libs) has two "CMake" files:
Each project (apps, modules, libs) has two "CMake" files:
- CMakeLists.txt_
- Properties.cmake_
...
...
@@ -23,7 +23,7 @@ CMakeLists.txt
The *CMakeLists.txt* should contain at least the function *fwLoadProperties()* to load the Properties.cmake.
But it can also contain others functions useful to link with external libraries.
Here is an example of CMakeLists.txt from guiQt Bundle :
Here is an example of CMakeLists.txt from guiQt Module :
.. code-block:: cmake
...
...
@@ -60,7 +60,7 @@ Actually if you're accustomed to CMake these two macros are strictly equivalent
They are proposed as a convenience so people won't forget for instance to specify `SYSTEM`,
which prevents compilation warnings from third-part libraries to be displayed.
If the rare case where your bundle may be a dependency of an another one,
If the rare case where your module may be a dependency of an another one,
you can forward the include directories and the libraries with ``fwForwardInclude`` and ``fwForwardLink``,
which are still equivalent to ``target_include_directories``
and ``target_link_libraries`` CMake commands but with ``PUBLIC`` set instead of ``PRIVATE``.
...
...
@@ -94,7 +94,7 @@ TYPE:
Define the type of the target:
- APP for an "Application"
- BUNDLE for a "bundle"
- MODULE for a "module"
- LIBRARY for a "library"
- EXECUTABLE for an executable
...
...
@@ -104,19 +104,19 @@ DEPENDENCIES:
REQUIREMENTS:
Ensure that the dependencies are built before the targets (see `add_dependencies <http://www.cmake.org/cmake/help/v3.0/command/add_dependencies.html?highlight=add_dependencies>`_ ).
The REQUIREMENTS should contain only "bundles".
The REQUIREMENTS should contain only "modules".
In some Properties.cmake (mostly in applications), you can see the line:
In sight, the bundles, libraries, applications and executables are folders containing:
In sight, the modules, libraries, applications and executables are folders containing:
- [required] two files to generate the *CMake* target: ``CMakeLists.txt``
and ``Properties.cmake`` (see :ref:`HowCMake`).
...
...
@@ -10,33 +10,33 @@ In sight, the bundles, libraries, applications and executables are folders conta
- [optional] *rc* folder to contain resources and XML configuration files
- [optional] *test* folder to contain the unit tests
.. _bundleCreation:
.. _moduleCreation:
How to create a bundle ?
How to create a module ?
==========================
In sight, you will encounter two types of bundles:
In sight, you will encounter two types of modules:
- the bundles containing only XML configurations
- the bundles containing services or other cpp code
- the modules containing only XML configurations
- the modules containing services or other cpp code
It is possible to contain at the same time configurations and services (or C++ code), but for the sake of clarity and
reusability we recommend to separate the two.
.. _configBundle:
.. _configModule:
XML configurations bundles
XML configurations modules
--------------------------
These bundles does not contain C++ code, they only contain XML files and the required *CMake* files.
In the bundle folder, there is only the *CMake* files and the *rc* folder.
These modules does not contain C++ code, they only contain XML files and the required *CMake* files.
In the module folder, there is only the *CMake* files and the *rc* folder.
CMake files
~~~~~~~~~~~~
The CMakeLists.txt contains only ``fwLoadProperties()`` to load the Properties.cmake
The Properties.cmake defines the bundles needed to launch the configuration (ie. the bundle of all the services present
The Properties.cmake defines the modules needed to launch the configuration (ie. the module of all the services present
in the configurations).
Example:
...
...
@@ -45,10 +45,10 @@ Example:
set( NAME dataManagerConfig )
set( VERSION 0.1 )
set( TYPE BUNDLE )
set( TYPE MODULE )
set( DEPENDENCIES ) # no dependency
set( REQUIREMENTS # required bundle
set( REQUIREMENTS # required module
gui
guiQt
uiMedDataQt
...
...
@@ -60,7 +60,7 @@ Example:
Configurations
~~~~~~~~~~~~~~~
A bundle could contain several configurations, they are in the ``plugin.xml`` file in the *rc* folder.
A module could contain several configurations, they are in the ``plugin.xml`` file in the *rc* folder.
.. code-block:: xml
...
...
@@ -75,7 +75,7 @@ A bundle could contain several configurations, they are in the ``plugin.xml`` fi
The ``@PROJECT_VERSION@`` will be automatically replaced by the version defined in the Properties.cmake.
The ``<requirement>`` tags contain the bundles that must be started before to start your bundle (see https://sight.pages.ircad.fr/sight/group__requirement.html).
The ``<requirement>`` tags contain the modules that must be started before to start your module (see https://sight.pages.ircad.fr/sight/group__requirement.html).
Then the extensions are defined. There are different types of extensions, the most common are:
...
...
@@ -90,19 +90,19 @@ Then the extensions are defined. There are different types of extensions, the mo
To separate the configuration in several files, you can use ``<xi:include href="..." />``
.. _serviceBundle:
.. _serviceModule:
Service bundles
Service modules
----------------
You don't need to create the ``plugin.xml`` file for the bundle that contains only services,
You don't need to create the ``plugin.xml`` file for the module that contains only services,
it will be automatically generated.
A ``CMake`` script parses the services macro and doxygen
to generate the ``::fwServices::registry::ServiceFactory`` extension
(see :ref:`serviceCreation` and :ref:`serviceNotFound`)
The bundle contains the service header files in the `include` folder and the `source` files in the `src` folder.
It must also contain a ``Plugin`` class used to register the bundle.
The module contains the service header files in the `include` folder and the `source` files in the `src` folder.
It must also contain a ``Plugin`` class used to register the module.
The ``Plugin.hpp`` in the *include* folder should look like:
...
...
@@ -112,10 +112,10 @@ The ``Plugin.hpp`` in the *include* folder should look like:
#include <fwRuntime/Plugin.hpp>
namespace myBundle
namespace myModule
{
class MYBUNDLE_CLASS_API Plugin : public ::fwRuntime::Plugin
class MYMODULE_CLASS_API Plugin : public ::fwRuntime::Plugin
{
public:
...
...
@@ -123,21 +123,21 @@ The ``Plugin.hpp`` in the *include* folder should look like:
/// Plugin destructor
~Plugin() noexcept;
/// This method is used by runtime to start the bundle.
/// This method is used by runtime to start the module.
void start();
/// This method is used by runtime to stop the bundle.
/// This method is used by runtime to stop the module.
void stop() noexcept;
/// This method is used by runtime to initialize the bundle.
/// This method is used by runtime to initialize the module.
void initialize();
/// This method is used by runtime to uninitialize the bundle.
/// This method is used by runtime to uninitialize the module.
void uninitialize() noexcept;
};
} // namespace myBundle
} // namespace myModule
The ``Plugin.cpp`` in the *src* folder should be like:
...
...
@@ -146,14 +146,14 @@ The ``Plugin.cpp`` in the *src* folder should be like: