.. toctree::
:maxdepth: 1
:hidden:
.. _bskExtensions:
About Extensions
================
.. sidebar:: What is an Extension?
A Basilisk extension is an independently built Python package containing
one or more custom C or C++ modules, custom message definitions, and
supporting code. It is installed alongside a compatible Basilisk release
without becoming part of the core Basilisk build.
Basilisk ships a curated set of simulation modules for common astrodynamics
tasks. Extensions let developers add new dynamics models, environment models,
sensors, effectors, algorithms, messages, and other simulation capabilities
without modifying the Basilisk source tree.
An extension can own:
* one or more C or C++ modules that use Basilisk base classes and APIs;
* custom message payloads and their generated Python bindings;
* shared support code used by those modules;
* pure-Python helpers and modules; and
* its own tests, examples, version, and release process.
The extension normally lives in a separate repository controlled by its
developer or organization. Core Basilisk and the extension can therefore
evolve as separate projects. Extension developers do not need to place files
inside Basilisk, modify core modules, or carry local source changes that can
conflict when updating the Basilisk checkout. An extension must still be
rebuilt when moving to a different Basilisk version because it uses Basilisk's
compiled C/C++ and SWIG interfaces.
Why the Package Boundary Matters
--------------------------------
Independent Ownership
~~~~~~~~~~~~~~~~~~~~~
The extension repository contains the custom source, messages, tests, and
packaging configuration. Its maintainers decide when to change or release it.
Basilisk remains a separately installed dependency rather than a source tree
that must contain every local customization.
Isolated Builds
~~~~~~~~~~~~~~~
An extension has its own build graph. Rebuilding it compiles the affected
extension targets and a small set of support sources supplied by
``bsk-sdk``. It does not rebuild the installed core Basilisk package.
This distinction is especially important for custom messages. Changing an
extension-owned payload regenerates that payload's bindings and recompiles the
extension targets that depend on it. The change does not regenerate or
recompile the core Basilisk message system.
Native In-Process Execution
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The package boundary is a build and distribution boundary, not a process
boundary. Extension modules and Basilisk run in the same Python process and
exchange compatible Basilisk objects and messages directly. There is no IPC
or serialization step on each module update, so a compiled extension retains
the native execution characteristics of a built-in C or C++ module.
Distribution
~~~~~~~~~~~~
An extension can be built as a standard Python wheel and distributed through
PyPI, a private package index, or another artifact store. End users can install
a prebuilt wheel without a compiler or Basilisk source checkout, provided a
wheel exists for their operating system, processor architecture, Python
version, and Basilisk version.
.. _extensions-vs-external-modules:
Extensions vs. Integrated External Modules
------------------------------------------
Basilisk also supports the :ref:`buildExtModules` external-folder option. That
option keeps custom source outside the repository but folds it into a
from-source Basilisk build. The result is one customized Basilisk installation
containing both core and external modules.
.. list-table:: Extension and external-folder build comparison
:header-rows: 1
:widths: 27 36 37
* - Characteristic
- Extension
- External-folder build
* - Project ownership
- Independent repository, package, and release lifecycle
- Separate source folder incorporated into one Basilisk build
* - Basilisk source checkout
- Not required for a released Basilisk version
- Required
* - Build product
- Separate wheel installed alongside Basilisk
- One customized Basilisk installation
* - Normal module rebuild
- Rebuilds affected extension targets and SDK support sources
- Rebuilds affected targets inside the integrated Basilisk build
* - Custom message rebuild
- Regenerates the extension message bindings and affected extension
targets; core Basilisk remains untouched
- Updates the combined message system and can trigger broad regeneration
and recompilation across the Basilisk build
* - Runtime execution
- Native and in-process
- Native and in-process
* - Distribution
- Can publish platform-specific wheels for ``pip install``
- Distribute the customized build or its source and build instructions
* - Basilisk API access
- Uses the headers, base classes, messages, and utilities exported by
``bsk-sdk``
- Builds with the complete Basilisk source tree and can use internal
implementation details
* - Version relationship
- Rebuild against the SDK matching each targeted Basilisk version
- Core and custom code are rebuilt together
* - Python import
- Extension-defined package, such as ``my_extension``
- ``Basilisk.ExternalModules``
Extensions are the recommended choice for custom modules and messages that can
be built with the interfaces exported by ``bsk-sdk``. The external-folder
option remains useful when custom code must participate in the complete
Basilisk source build, depends on non-exported internals, or must be delivered
as one customized Basilisk implementation.
How Extensions Work
-------------------
Extensions are built with
`bsk-sdk `_, a companion package that
contains a versioned subset of Basilisk needed for out-of-tree development:
* public headers and SWIG interface files;
* custom-message generation tools;
* CMake helpers for C and C++ modules; and
* a small set of Basilisk runtime and utility sources compiled into extension
targets.
The build-time and runtime relationships are different:
.. graphviz::
digraph extension_arch {
graph [rankdir=TB, splines=ortho, bgcolor=transparent, nodesep=0.45,
ranksep=0.55]
node [shape=box, style="rounded,filled", fontname="Helvetica",
fontsize=12, margin="0.35,0.18"]
edge [fontname="Helvetica", fontsize=10]
subgraph cluster_build {
label="Build time"
color="#9aa0a6"
style="rounded"
source [label="Extension source\n(modules and messages)",
fillcolor="#dce8fb"]
sdk [label="bsk-sdk\n(headers, generators, CMake, support sources)",
fillcolor="#d4edda"]
wheel [label="Extension wheel", fillcolor="#f1f3f4"]
source -> wheel [label=" compile "]
sdk -> wheel [label=" build against "]
}
subgraph cluster_runtime {
label="Runtime"
color="#9aa0a6"
style="rounded"
bsk [label="Matching Basilisk wheel", fillcolor="#fff3cd"]
installed [label="Installed extension wheel", fillcolor="#dce8fb"]
sim [label="One Basilisk simulation process", fillcolor="#f1f3f4"]
bsk -> sim [label=" import "]
installed -> sim [label=" import "]
}
wheel -> installed [label=" pip install "]
}
At build time, ``bsk-sdk`` checks the installed Basilisk version and SWIG
runtime compatibility. It then generates any custom message bindings and
builds the extension's native Python modules. The already installed Basilisk
wheel is not rebuilt.
At runtime, the matching Basilisk and extension wheels are imported into the
same simulation process. This allows extension modules to inherit supported
Basilisk base classes, use built-in and custom messages, and participate in the
normal task scheduling and message-passing system.
Custom Messages
---------------
An extension can define payload headers in its own repository and use
``bsk_generate_messages`` to create the same style of Python message,
recorder, and optional C interface support used by core Basilisk messages. The
generated bindings are packaged inside the extension's Python namespace.
Both extension modules and Python simulation code can import these custom
message types. Because the payload definitions belong to the extension, a
payload change remains local to that extension's build and does not modify the
installed ``Basilisk.architecture.messaging`` package.
Version and ABI Compatibility
-----------------------------
An extension has its own package version, but each compiled wheel targets a
specific Basilisk version. ``bsk-sdk`` versions track Basilisk versions; for
example, ``bsk-sdk==2.11.0`` contains the interfaces from Basilisk ``v2.11.0``.
Extension authors should pin the same Basilisk version in their build and
runtime dependencies:
.. code-block:: toml
[build-system]
requires = ["bsk-sdk==2.X.Y", "bsk==2.X.Y"]
[project]
dependencies = ["bsk==2.X.Y"]
CMake reports a version or SWIG ABI mismatch while building an extension. For
a prebuilt wheel, the extension's runtime dependency metadata is what prevents
``pip`` from selecting an incompatible Basilisk release. Upgrading Basilisk
therefore requires rebuilding the extension or installing an extension wheel
built for the new version.
Next Steps
----------
* To install an already built extension, see :ref:`extensionsInstall`.
* To build the working example and create an extension of your own, follow
:ref:`writingExtensions`.
* To build custom modules as part of one integrated Basilisk implementation,
see :ref:`buildExtModules`.
* For a complete extension containing C++, C, and custom-message examples, see
the `custom atmosphere extension
`_.