- Go 57%
- C++ 15.6%
- Objective-C++ 13.4%
- Zig 8.6%
- CMake 2.4%
- Other 3%
|
stephan_gfx
366adfabbc
Recurse into host directory with build and clean make targets ( #6 )
authored-by: ssteinbach <ssteinbach@users.noreply.github.com> Reviewed-on: meshula/Studiola#6 |
||
|---|---|---|
| TemplateCpp | ||
| TemplateHostCpp | Add app bundling and codesigning workflow | |
| TemplateZig | Update build.zig to reach into the install subdir ( #5 ) | |
| tools | Recurse into host directory with build and clean make targets ( #6 ) | |
| .gitignore | Improve local repo workflow | |
| configure.sh | ||
| install.sh | Improve local repo workflow | |
| README.md | ||
| TODO.md | ||
Studiola
Studiola is an umbrella workspace for a family of C++ creative-tooling
libraries, a host application, and a growing set of plugins. Everything in
this directory is built and installed together by a single orchestrator
(tools/studiola-build) so that the host and its plugins share one install
prefix, one set of headers, and one runtime layout.
The workspace is organized as flat sibling directories rather than a monorepo, because the individual components also live on their own and are usable outside Studiola.
What's in the box
Foundation libraries
- LabText — small text / s-expression parsing utilities.
- LabCamera — camera math and interactive camera controllers.
- LabGL — OpenGL / Metal rendering utilities and sample showcases.
- LabDb9 — graph database layer used by memex-style tools.
- LabLlama — llama.cpp wrapper exposing model hosting to the framework.
Host
- MeshulaLab — the Studiola host application (built as
Studiola). It provides the Studio / Activity / Provider architecture, the plugin loader, the CSP (ZeroMQ) transaction pump, ImGui-based UI, font and resource resolution, and a macOS.appbundle layout.
Plugins
- StudiolaColor — color-science activities (spectral locus, Macbeth chart) and a ColorProvider.
- StudiolaEffekseer — Effekseer particle effects, packaged as an EffectStudio with its EffectViewer activity and provider.
- StudiolaMemex — a memex/knowledge-graph plugin backed by LabDb9 and LabLlama, aggregating several activities into a single plugin.
Third-party foundations
These are cloned into the workspace by the wizard or studiola-build --fetch whenever something depends on them:
llama.cpp— large language model runtime (required by LabLlama).oneTBB,OpenSubdiv,USD— the OpenUSD stack, for eventual StudiolaUSD plugin work. Built with a no-python, shared-libs recipe derived fromtinyusd/recipes/macos-dynamic-nopy(github: meshula/tinyusd).
Architecture
The host exposes a stable C descriptor ABI (LabGetPluginDescriptor)
that plugins implement. A plugin descriptor enumerates the studios,
activities, and providers it ships, plus factory functions to create and
destroy them. The host loads plugins by walking upward from the executable
looking for a sibling plugins/ directory — the same walk-up strategy is
used for resources/fonts/, so one convention handles the dev tree,
installed prefix, and .app bundle shapes uniformly. A Studio may
request activities it does not own (the host wires them up) and
instantiate the ones it does.
Quickstart
Requirements:
- macOS (arm64) — Linux/Windows support exists in the host but the orchestrator's current deployment story targets macOS.
- CMake ≥ 3.26, Ninja, a recent clang, git, Go 1.22+ (to build the orchestrator and the configure wizard).
This repository is a workspace manifest, not a monorepo. It contains
only the build orchestrator and docs. The actual component sources
(LabText, LabGL, MeshulaLab, StudiolaColor, ...) live in their own
upstream repos and are cloned into a workspace directory that you
choose — typically a sibling of this repo.
Cold-clone workflow:
git clone https://codeberg.org/meshula/Studiola.git
cd Studiola
# Launch the configure wizard. The script builds the Go binaries on
# first run (and rebuilds them when sources or the embedded registry
# change), then opens a TUI for selecting components and picking a
# workspace directory.
./configure.sh
In the wizard:
| key | action |
|---|---|
[space] |
toggle a plugin |
[w] |
set the workspace directory (where repos clone to) |
[p] |
choose target platform (macos, ios, ios-simulator) |
[n] |
scaffold a new plugin (see below) |
[a] |
add a plugin from an external git URL |
[o] |
toggle online / offline mode |
[r] |
set the offline repo root (path to local mirrors) |
[u] |
populate — fetch / sync the offline root |
[enter] |
provision the workspace and build |
When you press [enter], the wizard writes studiola-config.toml at the
workspace root, copies tools/ into the workspace, clones the selected
components, and runs the build. Plugins are installed into
<workspace>/install/plugins/ and the host is installed at
<workspace>/install/bin/Studiola.
configure.sh is also the right way to re-enter the wizard on an
existing workspace — pass the saved config to prepopulate selections:
./configure.sh --config <workspace>/studiola-config.toml
Authoring a new plugin in the wizard
Press [n] to open the new-plugin form. Fill in:
- Plugin name — the on-disk directory and CMake target
(e.g.
StudiolaMyPlugin). - Component — the class prefix for the roles (e.g.
MyproducesMyProvider,MyActivity,MyStudio). - Roles — toggle Provider / Activity / Studio with
[space]. - Language — C++ or Zig (radio).
The right-hand panel previews exactly what will be scaffolded: the
classes that will be generated and the file list. Press [enter] to
create the plugin in the workspace. The wizard writes
CMakeLists.txt, studiola-plugin.toml, the role source files, and
a smoke test (or the Zig equivalents).
Offline workflow
The component registry lives at tools/studiola/registry.toml and is
embedded into the configure / build binaries (override with the
STUDIOLA_REGISTRY env var). Offline mode lets you build entirely
from a local mirror of every repo it lists.
- Press
[r]and point at a directory containing one clone per component, named to match the registry (LabText/,LabCamera/,MeshulaLab/, etc.). The path is recorded instudiola-config.tomlwhether or not offline mode is on, so the breadcrumb survives between sessions. - Press
[u]to open populate. The left panel shows the selected configuration; the right panel shows the git status of each repo in the offline root (✓up to date,↑nahead,↓nbehind,⇅diverged,✗missing,·no upstream / detached HEAD). [enter]clones missing repos from upstream and runsgit fetchon the rest, concurrently.[r]re-checks status without touching the network.- Press
[o]to toggle offline. While offline,[enter] installclones the workspace from your local mirror instead of upstream — no network required.
Repos cloned by populate use --depth 1 and the registered ref; if you
want full history, re-clone the offline mirror by hand and the wizard
will leave it alone.
Headless build (no wizard)
The orchestrator can also run standalone, the way the wizard does internally. It expects a workspace that already has components checked out:
cd <workspace>
./tools/studiola-build/studiola-build --fetch # clone what's missing
./tools/studiola-build/studiola-build # build everything
./install/bin/Studiola # run the host
--fetch honours the same registry as the wizard. Other useful flags:
./tools/studiola-build/studiola-build --list # show plan
./tools/studiola-build/studiola-build --plugins X,Y # subset build
./tools/studiola-build/studiola-build --dry-run # print, don't run
./tools/studiola-build/studiola-build --clean # wipe build/ + install/
./tools/studiola-build/studiola-build --bundle # inject into .app
Directory layout
Studiola/ this repo
├── configure.sh first-run launcher
├── tools/
│ ├── studiola/ shared Go package
│ │ └── registry.toml component registry
│ ├── studiola-build/ headless orchestrator
│ ├── studiola-configure/ TUI wizard
│ └── studiola-git/ git helper
└── TemplateCpp/ TemplateZig/ new-plugin scaffolds
<workspace>/ chosen via [w] in wizard
├── studiola-config.toml saved selections + mode
├── LabText/ LabCamera/ LabGL/ foundation libs
├── LabDb9/ LabLlama/
├── MeshulaLab/ host (Studiola)
├── StudiolaColor/ StudiolaEffekseer/ StudiolaMemex/ plugins
├── llama.cpp/ oneTBB/ OpenSubdiv/ USD/ fetched foundations
├── tools/ copied from Studiola
├── build/
│ └── <Component>/ per-component build dirs
└── install/ shared install prefix
├── bin/Studiola
├── lib/ foundation dylibs
├── plugins/ plugin dylibs
├── include/
└── resources/fonts/
Per-component build directories live side-by-side under build/; the
shared install prefix is install/ (a peer of build/, not nested
inside it). Foundations install their exports into
install/lib/cmake/<Package>/ so downstream find_package calls
resolve against the workspace install, not against any system prefix.
The orchestrator passes CMAKE_PREFIX_PATH=<install> on every
configure to enforce that. Cross-compiled builds get suffixed
sibling prefixes (e.g. install-ios-simulator/).
Authoring a plugin by hand
The wizard's [n] flow above is the path of least resistance. If you'd
rather hand-roll a plugin (or you're integrating a pre-existing repo),
drop a studiola-plugin.toml next to your CMakeLists.txt:
name = "StudiolaYourPlugin"
kind = "plugin"
depends = ["LabGL", "MeshulaLab"]
[build]
system = "cmake"
[build.cmake]
generator = "Ninja"
config = "Release"
[install]
artifacts = ["lib/**"]
bundle_subdir = "Contents/PlugIns/StudiolaYourPlugin"
Implement LabGetPluginDescriptor in your plugin (see StudiolaColor or
StudiolaEffekseer for worked examples). The orchestrator will discover
the plugin on its next run. No bookkeeping anywhere else in the workspace
is needed.
Acknowledgments
The fetched third-party components retain their own licenses and remain
owned by their upstream projects. Studiola's own code is licensed
per-repository — see each component's LICENSE file.