Skip to content
Open
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
5 changes: 5 additions & 0 deletions docs/source/Build/installOnMacOS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ In order to run Basilisk on macOS, the following software is necessary:
#. (Optional) Get the `PyCharm <https://www.jetbrains.com/pycharm/>`__
application to be able to edit python source files

#. (Optional, required to build docs locally) Install `Doxygen <https://www.doxygen.nl>`__ and
`Graphviz <https://graphviz.org>`__ via Homebrew::

$ brew install doxygen graphviz

Install Python 3
----------------
To install Python 3 on macOS there are two common options:
Expand Down
59 changes: 30 additions & 29 deletions docs/source/Plugins/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,24 @@ Basilisk plugins are built with `bsk-sdk <https://pypi.org/project/bsk-sdk/>`_,
a companion Python package that ships the headers, SWIG interface files, and
CMake helpers needed to compile out-of-tree modules.

.. code-block:: text
.. graphviz::

digraph plugin_arch {
graph [rankdir=TB, splines=ortho, bgcolor=transparent, nodesep=0.5]
node [shape=box, style="rounded,filled", fontname="Helvetica",
fontsize=13, margin="0.4,0.2", width=4, fixedsize=false]
edge [fontname="Helvetica", fontsize=11, minlen=2]

plugin [label="Your plugin\n(separate repo / wheel)",
fillcolor="#dce8fb"]
sdk [label="bsk-sdk\n(BSK headers · SWIG interfaces · CMake helpers)",
fillcolor="#d4edda"]
bsk [label="Basilisk: pip install bsk",
fillcolor="#fff3cd"]

┌─────────────────────────────────────┐
│ Your plugin (separate repo/wheel) │
│ │
│ myModule.cpp / myModule.h │
│ myModule.i │
│ CMakeLists.txt │
└──────────────┬──────────────────────┘
│ links against
┌──────────────▼──────────────────────┐
│ bsk-sdk wheel │
│ (vendored BSK headers + cmake) │
└──────────────┬──────────────────────┘
│ compatible with
┌──────────────▼──────────────────────┐
│ Basilisk (pip install bsk) │
└─────────────────────────────────────┘
plugin -> sdk [label=" compiles against "]
sdk -> bsk [label=" compatible with "]
}

The plugin compiles against the same BSK headers and SWIG runtime that
Basilisk uses, so message types, base classes, and the module API are
Expand All @@ -126,19 +126,21 @@ Quick Start

pip install bsk-sdk

**2. Create your plugin layout** (following BSK module conventions)
**2. Create your plugin layout**

.. code-block:: text

my-plugin/
├── pyproject.toml
├── CMakeLists.txt
└── myModule/
├── myModule.h
├── myModule.cpp
├── myModule.i
├── my_plugin/ # importable Python package
│ └── __init__.py
└── exampleCppModule/ # C++/SWIG source
├── exampleCppModule.h
├── exampleCppModule.cpp
├── exampleCppModule.i
└── _UnitTest/
└── test_myModule.py
└── test_exampleCppModule.py

**3. Wire up CMakeLists.txt**

Expand All @@ -158,10 +160,9 @@ Quick Start
find_package(bsk-sdk CONFIG REQUIRED)

bsk_add_swig_module(
TARGET myModule
INTERFACE myModule/myModule.i
SOURCES myModule/myModule.cpp
LINK_LIBS bsk::plugin
TARGET exampleCppModule
INTERFACE exampleCppModule/exampleCppModule.i
SOURCES exampleCppModule/exampleCppModule.cpp
OUTPUT_DIR "${SKBUILD_PLATLIB_DIR}/my_plugin"
)

Expand All @@ -177,11 +178,11 @@ Quick Start

.. code-block:: python

from my_plugin import myModule
from my_plugin import exampleCppModule
from Basilisk.utilities import SimulationBaseClass

sim = SimulationBaseClass.SimBaseClass()
mod = myModule.MyModule()
mod = exampleCppModule.ExampleCppModule()
sim.AddModelToTask("task", mod)

A complete working example is provided in the
Expand Down
55 changes: 34 additions & 21 deletions docs/source/Plugins/writing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,29 @@ Prerequisites
Plugin Layout
-------------

Follow the same folder convention as BSK — one folder per module, named
identically to the module:
Every plugin needs a Python package directory (``my_plugin/`` below). This
is the importable namespace your users will ``import`` from, and where both
compiled SWIG extensions and pure-Python modules are installed. C++/SWIG
source trees live alongside it at the repo root and get compiled into that
package at build time. Pure-Python modules can be added directly inside the
package directory with no extra build steps:

.. code-block:: text

my-plugin/
├── pyproject.toml
├── CMakeLists.txt
├── messages/ # (optional) custom message definitions
├── my_plugin/ # Python package (SWIG outputs install here too)
│ ├── __init__.py
│ └── examplePythonModule.py # (optional) pure-Python modules
├── messages/ # (optional) custom message definitions
│ └── MyMsgPayload.h
└── myModule/
├── myModule.h
├── myModule.cpp
├── myModule.i
└── exampleCppModule/ # C++/SWIG module source
├── exampleCppModule.h
├── exampleCppModule.cpp
├── exampleCppModule.i
└── _UnitTest/
└── test_myModule.py
└── test_exampleCppModule.py

SWIG Interface
--------------
Expand All @@ -55,14 +62,14 @@ The ``.i`` file is the same as any BSK module. For C++ use

.. code-block:: swig

%module myModule
%module exampleCppModule
%{
#include "myModule.h"
#include "exampleCppModule.h"
%}

%include "swig_common_model.i" /* C++ modules */
/* %include "swig_c_wrap.i" C modules — use %c_wrap_2 instead */
%include "myModule.h"
%include "exampleCppModule.h"

If subclassing a BSK base class, ``%include`` its ``.i`` file before yours:

Expand Down Expand Up @@ -107,24 +114,23 @@ plugin-specific section:
# Plugin-specific configuration
# ==========================================================================

file(GLOB PLUGIN_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/myModule/*.cpp")
file(GLOB PLUGIN_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/exampleCppModule/*.cpp")

# If subclassing a BSK base class (AtmosphereBase, DynamicEffector, etc.),
# add its implementation from the SDK:
# list(APPEND PLUGIN_SOURCES "${BSK_SDK_RUNTIME_MIN_DIR}/atmosphereBase.cpp")

# An example of this is in the `custom-atm-plugin` example in the SDK repo.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new comment says the custom-atm-plugin example shows appending BSK_SDK_RUNTIME_MIN_DIR/atmosphereBase.cpp, but the actual SDK example says the opposite: bsk_add_swig_module adds SDK runtime sources automatically. This advice can lead plugin authors to duplicate SDK sources or chase a nonexistent requirement.

bsk_add_swig_module(
TARGET myModule
INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/myModule/myModule.i"
TARGET exampleCppModule
INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/exampleCppModule/exampleCppModule.i"
SOURCES ${PLUGIN_SOURCES}
INCLUDE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}/myModule"
"${CMAKE_CURRENT_SOURCE_DIR}/exampleCppModule"
"${CMAKE_CURRENT_SOURCE_DIR}/messages"
LINK_LIBS bsk::plugin
OUTPUT_DIR "${PKG_DIR}"
)

# Optional: generate Python bindings for custom messages
# Optionally generate Python bindings for custom messages
bsk_generate_messages(
OUTPUT_DIR "${PKG_DIR}/messaging"
MSG_HEADERS
Expand All @@ -137,7 +143,7 @@ pyproject.toml
.. code-block:: toml

[build-system]
requires = ["scikit-build-core>=0.9"]
requires = ["scikit-build-core>=0.9.3", "bsk-sdk==2.X.Y", "bsk==2.X.Y"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new build-system.requires example omits swig==4.4.1, but the SDK CMake macro calls find_package(SWIG REQUIRED) and the working SDK example includes the pip SWIG package. On a clean machine without system SWIG, python -m build --wheel can fail at configure time.

build-backend = "scikit_build_core.build"

[project]
Expand All @@ -147,7 +153,14 @@ pyproject.toml
dependencies = ["bsk"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sample pyproject.toml still declares runtime dependencies = ["bsk"] while the new text says plugin and Basilisk versions must match. Since wheels use [project].dependencies at install time, this can install or accept an incompatible Basilisk runtime. Show bsk==2.X.Y there too, or an explicit compatible version constraint.


[tool.scikit-build]
wheel.packages = []
wheel.packages = ["my_plugin"]

.. note::

Both ``bsk-sdk`` and ``bsk`` must be **pinned to the same version** in
``build-system.requires``. The SDK compiles BSK sources into your plugin
at build time, so mismatched versions will produce a CMake error.
Replace ``2.X.Y`` with the Basilisk version you are targeting.

Building and Installing
-----------------------
Expand All @@ -162,7 +175,7 @@ Building and Installing
pip install dist/*.whl

# Run unit tests
pytest myModule/_UnitTest/ -v
pytest exampleCppModule/_UnitTest/ -v

Publishing to PyPI
------------------
Expand Down
4 changes: 3 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# -- Path setup --------------------------------------------------------------

import datetime
import shutil
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
Expand Down Expand Up @@ -133,6 +134,8 @@ def build_supportdata_index_rst(output_file: str):
]

graphviz_output_format = "svg"
_dot_candidates = ["/opt/homebrew/bin/dot", "/usr/local/bin/dot"]
graphviz_dot = shutil.which("dot") or next((p for p in _dot_candidates if os.path.exists(p)), "dot")

# Use MathJax SVG output instead of CHTML to avoid browser/font-metric
# rendering artifacts (e.g., vertically offset multi-character symbols).
Expand Down Expand Up @@ -323,7 +326,6 @@ def build_supportdata_index_rst(output_file: str):
# breathe_projects = {"Basilisk": "../../src/*"}

from glob import glob
import shutil

class fileCrawler():
def __init__(self, newFiles=False):
Expand Down
Loading