pyproject.toml

Projects that use semiwrap must add a pyproject.toml to the root of their project as specified in PEP 518.

Because semiwrap is a hatchling plugin, you should add semiwrap and hatchling to your build-system.requires. You need meson to build the project, so we recommend also using hatch-meson to do so.

[build-system]
build-backend = "hatchling.build"
requires = ["semiwrap", "hatch-meson", "hatchling"]

Projects must include semiwrap specific sections in their pyproject.toml. semiwrap takes pyproject.toml and converts it to a python dictionary using toml.load. The resulting dictionary is converted to the dataclasses described below.

Required sections:

  • RobotpyBuildConfig - base project configuration

  • DistutilsMetadata - standard python distutils metadata

Optional sections:

  • WrapperConfig - per-package configuration

  • StaticLibConfig

  • MavenLibDownload - download per-package maven artifacts

  • PatchInfo - patch downloaded sources

Note

For a complete example pyproject.toml file, see tests/cpp/*/pyproject.toml

Reference

class semiwrap.config.pyproject_toml.ConditionalHeader(header, enable_if)

Allows specifying that a header will only be autogenerated if the specified condition is true.

[tool.semiwrap.extension_modules."PACKAGE.NAME".headers]
Name = { header="header.h", enable_if = "platform_machine == 'aarch64'" }
Parameters:
  • header (str)

  • enable_if (str)

enable_if: str

This is a PEP 508 environment marker specification.

The header will not be parsed if this does not evaluate to true

header: str

Name of the header file

class semiwrap.config.pyproject_toml.ExtensionModuleConfig(name=None, libinit=None, wraps=<factory>, depends=<factory>, includes=<factory>, defines=<factory>, headers=<factory>, yaml_path=None, ignore=False)

Configuration for generating pybind11 wrappers around specified header files.

[tool.semiwrap.extension_modules."PACKAGE.NAME"]
Parameters:
  • name (Optional[str])

  • libinit (Optional[str])

  • wraps (List[str])

  • depends (List[str])

  • includes (List[str])

  • defines (Dict[str, Union[str, int]])

  • headers (Dict[str, Union[str, ConditionalHeader]])

  • yaml_path (Optional[str])

  • ignore (bool)

defines: Dict[str, str | int]

#define macros to apply to the compilation

[tool.semiwrap.extension_modules."package.name".defines]
SOMETHING_DEFINED = 1
depends: List[str]

List of pkgconf library dependencies. This affects this wrapper library in the following ways:

  • Any include file directories exported by the dependency will be added to the include path for any source files compiled by this wrapper

  • It will be linked to any libraries the dependency contains

  • The python module for the dependency will be imported in the _init{extension}.py file.

headers: Dict[str, str | ConditionalHeader]

Specifies header files that autogenerated pybind11 wrappers will be created for. Simple C++ headers will most likely ‘just work’, but complex headers will need to have an accompanying generation_data file specified that can customize the autogenerated files.

List of dictionaries: each dictionary key is used for the function name of the initialization function, the value is the header that is being wrapped. The header is searched for in the following order:

  • Relative to include directories specified by ‘wraps’ dependencies

  • Relative to the extra include directories for this module

  • Relative to the package directory

[tool.semiwrap.extension_modules."PACKAGE.NAME".headers]
Name = "header.h"
ignore: bool = False

If True, skip this wrapper

includes: List[str]

List of include directories for this module relative to the project root

libinit: str | None = None

Name of generated file that ensures the shared libraries and any dependencies are loaded. Defaults to _init_XXX.py, where XXX is the last element of the package name

Generally, you should create an __init__.py file that imports this module, otherwise your users will need to do so.

name: str | None = None

The name used internally to refer to this extension module. The name is used as the prefix of variable names in build files.

If not specified, the default name is the package name with invalid characters replaced by underscores.

wraps: List[str]

Name of pkgconf libraries that this is wrapping. This is also added to depends list.

yaml_path: str | None = None

Path to a directory of yaml files. Generation data will be looked up using the key in the headers dictionary.

These YAML files can be generated via the semiwrap command line tool:

semiwrap update-yaml --write
class semiwrap.config.pyproject_toml.SemiwrapHatchlingConfig(autogen_build_path='semiwrap', module_build_path=None)

semiwrap hatchling hook configuration

[tool.hatch.build.hooks.semiwrap]

Note

This section is required

Parameters:
  • autogen_build_path (str)

  • module_build_path (Optional[str])

autogen_build_path: str = 'semiwrap'

Output directory to write meson.build to

module_build_path: str | None = None

Output directory to write second stage meson.build to (defaults to autogen_build_path / 'modules')

class semiwrap.config.pyproject_toml.SemiwrapToolConfig(scan_headers_ignore=<factory>, update_init=<factory>, extension_modules=<factory>, export_type_casters=<factory>)

Contains information for configuring the project

[tool.semiwrap]

Note

This section is required

Parameters:
export_type_casters: Dict[str, TypeCasterConfig]

Type casters to export. The key is the pkgconf package name.

extension_modules: Dict[str, ExtensionModuleConfig]

Modules to autogenerate. The key is the name of the python package that will be generated. For example, “package.name” will cause the shared library ‘package/name-{abi tag}.so’ to be installed

scan_headers_ignore: List[str]

List of headers for the scan-headers tool to ignore

update_init: List[str]

List of python packages with __init__.py to update when python setup.py update_init is called – this is an argument to the semiwrap create-imports command, and may contain a space and the second argument to create-imports.

class semiwrap.config.pyproject_toml.TypeCasterConfig(pypackage, includedir, requires=<factory>, headers=<factory>)

Specifies type casters to be exported as a pkgconf package. When a semiwrap package has a dependency on such a package, it will use this type information at generation time and include the type caster headers in generated wrappers.

[tool.semiwrap.export_type_casters.NAME]
pypackage = "mypkg"
includedirs = ["src/mypkg/type-casters"]

[[tool.semiwrap.export_type_casters.NAME.headers]]
header = "my_type_caster.h"
types = ["foo_t", "ns::ins::bar_t"]

See also

Type Casters

Parameters:
  • pypackage (str)

  • includedir (List[str])

  • requires (List[str])

  • headers (List[TypeCasterHeader])

headers: List[TypeCasterHeader]

Contains header/type mappings for type casters

includedir: List[str]

Location of type caster header files, relative to the root of the project

pypackage: str

Python package to write the .pc and .json file to

requires: List[str]

pkgconf ‘requires’

class semiwrap.config.pyproject_toml.TypeCasterHeader(header, types, default_arg_cast=False)
Parameters:
  • header (str)

  • types (List[str])

  • default_arg_cast (bool)

default_arg_cast: bool = False

If a parameter type that requires this type caster requires a default argument, a C-style (type) cast is used on the default argument.

The default cast can be disabled via param_override’s disable_type_caster_default_cast

header: str

Header file to include when one of the types are detected in a wrapper

types: List[str]

Types to look for to indicate that this type caster header should be included.