New feature in VTK: VTK ABI Namespace

Overview

The feature allowing projects to wrap VTK in an namespace has officially landed on master! The ABI namespace is intended to add a namespace that is visible in the compiled libraries, but opaque to the code. This was accomplished using the C++ feature inline namespace introduced in the C++11 standard.

CMake Configuration

To enable the use of the ABI namespace, set the configuration option VTK_ABI_NAMESPACE_NAME to a desired name to prefix the ABI symbols of all VTK objects, functions, and variables. The name must follow the conventions of the C++ namespace naming rules, ie. the first character must be [_a-zA-Z][_a-zA-Z0-9]*. The default option for this configuration is <DEFAULT> which will set the namespace to an empty string. Therefore, unless configured to do so, VTK will not apply the inline namespace and will configure and compile in exactly the same way as it has previously.

Here is an example configuring VTK to build using a namespace that adds __paraview__ to the mangled symbols names.

$ cmake -DVTK_ABI_NAMESPACE_NAME:STRING=__paraview__ ...

The configuration for this option is in the Common::Core module, which includes the generation and installation of the vtkABINamespace.h header.

In the Code

A new macro pair was introduced to inject the ABI namespace, VTK_ABI_NAMESPACE_BEGIN and VTK_ABI_NAMESPACE_END. These macros are defined in the configured header vtkABINamespace.h, which is automatically included in all <ModuleName>Module.h headers but may also be included independently.

How to use the macros

The macros should wrap everything that is externally visible that is not already uniquely mangled in an anonymous namespaces, static declarations, etc. or in an extern "C" block.

Old without namespace New with namespace
#include "vtkObject.h"



class thirdPartyType;



extern "C" void vtkFoo_init();

// --



void foo();
class vtkObject;

class vtkMyObject : 
  public vtkObject
{
  // ...
};
// --
#include "vtkObject.h"

// Do not put forward declarations
// of externals in ABI namespace
class thirdPartyType;

// Unmangled interfaces may not
// be inside ABI namespace
extern "C" void vtkFoo_init();

VTK_ABI_NAMESPACE_BEGIN
// Forward declarations of VTK
// classes and functions must be
// inside namespace
void foo();
class vtkArray;

class vtkMyObject : 
  public vtkObject
{
  // ...
};
VTK_ABI_NAMESPACE_END

Nesting Namespaces

If there are already namespaces involved, the ABI namespace must be the inner most namespace. If this is not done, then all instances of the namespace must also be wrapped inside of the ABI namespace, which is not always possible and make it difficult to work with such code. Failure to do this can result in an ambiguous namespace lookup.

Wrong Correct
VTK_ABI_NAMESPACE_BEGIN
namespace my_namespace
{
  // ...
};
VTK_ABI_NAMESPACE_END
namespace my_namespace
{
VTK_ABI_NAMESPACE_BEGIN
  // ...
VTK_ABI_NAMESPACE_END
};

Optional Cases

In the case of anonymous namespaces and static declarations it is optional to apply the ABI namespace since these symbols will already be mangled based on the translation unit they are compiled in. Adding the ABI namespace with an anonymous namespace still follows the same rules for nesting. Since it is possible to include a header that contains an anonymous namespace that did not use the ABI namespace, this would create an ambiguous namespace deduction.

Wrong Correct
VTK_ABI_NAMESPACE_BEGIN
namespace
{
  // ...
};
VTK_ABI_NAMESPACE_END
namespace
{
VTK_ABI_NAMESPACE_BEGIN
  // ...
VTK_ABI_NAMESPACE_END
};

Adding Namespace Test

A new module test was introduced and should be added to all new modules to verify they are properly supporting the ABI namespace.

example.

vtk_module_add_module(VTK::Foo
  ...)

vtk_add_test_mangling(VTK::Foo)

Exemptions

In the case a module includes symbols that cannot be mangled, it is possible to add those symbols, or a prefix pattern of those symbols, to the mangling test.

example from IO/XML/CMakeLists.txt using a prefix pattern

vtk_module_add_module(VTK::IOXML
  ...)

vtk_add_test_mangling(VTK::IOXML
  EXEMPTIONS vtkXMLWriterC_)

exmple from Common/Core/CMakeLists.txt listing specific symbols

vtk_module_add_module(VTK::CommonCore
  ...)

vtk_add_test_mangling(VTK::CommonCore
  EXEMPTIONS GetVTKVersion)

VTK Symbols not in the ABI namespace

Some of the VTK symbols could not be wrapped in the namespace for technical reasons.

VTK modules have C interfaces that cannot be mangled.

  • VTK::CommonCore (GetVTKVersion)
  • VTK::IOXML (Provides a C API, vtkXMLWriterC_*)
  • VTK::WrappingPythonCore (Python Wrapping cannot have mangling)
  • VTK::IOImport mtlsyntax.cxx:parseMTL (ragel generated source)
  • VTK::RenderingTk

Thirdpary Libraries and their VTK module wrappers do not have mangling

  • VTK::metaio
  • VTK::xdmf2
  • VTK::vpic
  • All C libraries (ie. HDF5, netCDF, etc.)

VTKm CUDA Accelerators do not get mangled

  • VTK::AcceleratorsVTKmCore
  • VTK::AcceleratorsVTKmDataModel
  • VTK::AcceleratorsVTKmFilters
3 Likes

Acknowledgements

Thank you to @ben.boeckel and @vbolea for their reviews and feedback. Their efforts have been key to moving this forward in VTK!

1 Like

Thank you to @dgobbi for helping update the wrapping tools!