Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: ABI: Defining public (exported) symbols #1576

Merged
merged 1 commit into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/best_practices/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Best practices
* If clang-format produces sub-optimal output, consider using ``// clang-format off|on`` where appropriate
* Use templates and lambdas only if really necessary
* Avoid ``shared_ptr`` because it isn't supported in all SWIG bindings
* Set symbol visibility - ABI

We follow the following coding style:

Expand All @@ -18,3 +19,4 @@ We follow the following coding style:
coding_style_py
documentation_strings
project_layout
symbol_visibility
48 changes: 48 additions & 0 deletions doc/best_practices/symbol_visibility.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Symbol visibility
=================

The DNF5 build is configured so that the symbols in the generated dynamic libraries are hidden by default - they are not exported.
Therefore, all non-inline public functions and classes (structures) must be explicitly marked for export.
If a class (struct) is marked for export, all its symbols are automatically exported. For this reason,
private members of public classes (structures) must be explicitly marked as local to avoid exporting their symbols.
We do not want to expose private symbols in the ABI.

The public API is defined in public header files. It is the only place where symbols are marked for export or as local
in the case of private members.

To mark whether a symbol should be exported, we use macros. The macros are defined in the `defs.h` files.
The different parts of the project have their own specific macros. This is because the public header files are shared.
For example, the libdnf5 header file marks the symbol for export when compiling the libdnf5 library, but the same symbol
for import when including that header file in the libdnf5-cli library.

Macros used
-----------

* ``LIBDNF_API``, ``LIBDNF_LOCAL``, ``LIBDNF_PLUGIN_API``
* ``LIBDNF_CLI_API``, ``LIBDNF_CLI_LOCAL``
* ``DNF_API``, ``DNF_LOCAL``

| Macros ending with ``_API`` denote symbols for export.
| Macros ending with ``_LOCAL`` denote private symbols and are used for private members of public classes (structures).

Example
-------

::

#include "libdnf5/defs.h"

class LIBDNF_API PublicExampleClass {
public:
void public_method1();
int public_method2();

private:
LIBDNF_LOCAL void private_method();

class LIBDNF_LOCAL Impl; // Impl is private class

ImplPtr<Impl> p_impl;
}

LIBDNF_API void public_function();
Loading