aGrUM 3.2.0
a C++ library for (probabilistic) graphical models
Code modularization (aGrUM and pyAgrum)
Collaboration diagram for Code modularization (aGrUM and pyAgrum):

aGrUM's C++ sources are split into 9 modules (BASE, BN, PRM, MRF, CN, FMDP, ID, CM, KTBN, declared in src/modules.txt with their dependencies). Depending on the target and the platform, these modules are assembled into a final binary in one of three ways.

Build configurations

Target / platformResulting binaries
Pure aGrUM, Linux/macOS (default)9 genuinely separate shared libraries (libagrumBASE.so, libagrumBN.so, ...), each simultaneously a producer of its own symbols and a consumer of the modules it depends on.
Pure aGrUM, WindowsAlways statically linked into a single binary (--static_lib, enforced by act) – no DLL boundary exists between modules there.
pyAgrum, any platformBASE and BN are statically whole-archived into one shared core extension (_pyagrumcpp.so/.pyd); PRM, MRF, CN, ID, CM and KTBN each get their own separate shared leaf extension (pyagrum.prm, .markov_random_field, .credal_net, .influence_diagram, .causal_model, .ktbn) that links against that core. FMDP has no pyAgrum extension.

Visibility macros

Whenever a symbol defined in one module/extension is used from another one, the compiler needs to know whether it is producing that symbol (exporting it) or consuming it (importing it) – on Windows this is not optional: without the right __declspec(dllexport)/dllimport annotation, a symbol is invisible from one .dll to another. Two independent macro families cover the two topologies above.

pyAgrum: PYGUM_PUBLIC / PYGUM_SHARED_PUBLIC

  • PYGUM_PUBLIC – a symbol that is self-contained: declared, defined and used within the same extension (typically a leaf module's own class). Always exports, no producer/consumer split needed.
  • PYGUM_SHARED_PUBLIC – a BASE/BN symbol that a leaf extension needs but that actually lives in core's object files. Resolves to dllexport only on BASE/BN's own compilation (which also produces core), dllimport everywhere else.

Pure aGrUM: GUM_SHARED_PUBLIC / GUM_PUBLIC_<MODULE>

  • GUM_SHARED_PUBLIC – for a BASE symbol. BASE has no dependencies of its own (BASE_DEPS is empty), so it only ever produces, never consumes, under this family – a single unqualified name is safe for it.
  • GUM_PUBLIC_<MODULE> – for a BN/PRM/MRF/CN/FMDP/ID/CM/KTBN symbol, one macro name per module (GUM_PUBLIC_BN, GUM_PUBLIC_PRM, ...). A module both produces its own symbols and consumes others' – a single shared macro name could not tell "I own this" from "I merely included the header that declares it" in the same translation unit, so each module needs its own name.

On Windows, pure aGrUM never crosses a real DLL boundary (see the table above), so GUM_SHARED_PUBLIC/GUM_PUBLIC_<MODULE> quietly expand to nothing there: a tagged symbol behaves exactly like an untagged one, resolved by ordinary static linking. Tagging is therefore never harmful on Windows, it is simply without effect – its value on that platform is purely documentary.

Which macro applies to a given symbol?

| Symbol lives in... | Consumed only within its own module/extension | Consumed across a module/extension boundary | |—|—|—| | pyAgrum leaf extension's own code | PYGUM_PUBLIC | (leaf extensions don't export to each other) | | BASE or BN, needed by a pyAgrum leaf extension | PYGUM_PUBLIC | PYGUM_SHARED_PUBLIC | | BASE, in a pure aGrUM build | (no tag needed) | GUM_SHARED_PUBLIC | | BN/PRM/MRF/CN/FMDP/ID/CM/KTBN, in a pure aGrUM build | (no tag needed) | GUM_PUBLIC_<MODULE> | | Still-generic template (template <typename T> class Foo) | never tagged | never tagged |

A symbol used both by pyAgrum and by a pure aGrUM cross-module consumer carries both its pyAgrum-family tag and its pure-aGrUM-family tag – the two macro families are independent and both apply. A still-generic template is never tagged with either family: it is re-instantiated locally in every consumer from its header definition, so it never needs to cross a binary boundary as a distinct symbol.

See How to tag a symbol's visibility in aGrUM/pyAgrum ? for how to apply these macros when adding a new class, function or module, and Visibility tags for the current, auto-generated inventory of every tagged symbol.