# Build your first plugin

This tutorial creates a compiled C++ panel with a button, an editable name and
persistent panel state. It uses the public SDK and runs in the EpicTuner worker.

## 1. Prepare your tools

Extract the SDK into a new directory. Install CMake 3.24 or newer, Ninja, and a
native C++20 compiler. Use an **x64** compiler shell on Windows. MinGW and MSVC
produce separate binaries; both use the same C ABI. Python is needed for the
generator and package tools, not for running a plugin.

You also need an EpicTuner host build containing `epictuner`,
`epictuner-plugin-host` and `epictuner-plugin-check`. Windows executable names
end in `.exe`. The host ships separately from the SDK.

## 2. Generate the project

Run from the extracted SDK root:

```sh
python tools/new-plugin.py /absolute/my-plugin --id com.example.analysis --name "My analysis"
```

The generator writes a standalone CMake project, a development manifest and
`plugin.cpp`. It refuses to overwrite an existing directory. Choose a reverse
domain ID you control; the library and manifest must agree.

## 3. Compile

```sh
cmake -S /absolute/my-plugin -B /absolute/my-plugin/out -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/absolute/sdk
cmake --build /absolute/my-plugin/out
```

For MSVC, run in an initialized x64 developer shell and add
`-DCMAKE_CXX_COMPILER=cl`. For MinGW, select `g++` or its absolute path.
Use a fresh output directory when changing compilers.

For MSYS2, use the **UCRT64** or **MINGW64** shell with its matching native CMake,
Ninja and compiler packages, for example `mingw-w64-ucrt-x86_64-cmake`,
`mingw-w64-ucrt-x86_64-ninja`, and `mingw-w64-ucrt-x86_64-gcc`. `which cmake`
should point into `/ucrt64/bin` (or `/mingw64/bin`), not `/usr/bin`.
Always specify `-G Ninja`. MSYS `/usr/bin/cmake` plus Unix Makefiles and native
`mingw32-make` mixes `/c/` paths with Windows paths and does not form a supported
toolchain. The SDK CMake project is the recommended build path.

Alternatively set `EPICTUNER_SDK_ROOT`, change into the generated directory,
and run `cmake --preset sdk` followed by `cmake --build --preset sdk`.
The result is `starter.dll` on Windows or `starter.so` on Linux, beside
`plugin.json`. The CMake helper also places the manifest beside multi-config
output such as `Release/starter.dll`.

## 4. Check the worker

Run the checker from your host installation:

```sh
epictuner-plugin-check --development --manifest /absolute/my-plugin/out/plugin.json --ui-panel com.example.analysis.main
```

Expect `READY` and `UI registration/open/focus/close passed`. This verifies
loading and panel registration; the next step verifies actual rendering and input.
A missing native dependency is diagnosed before the panel can register.

## 5. Open it in EpicTuner

```sh
epictuner --plugin-development --plugin-manifest /absolute/my-plugin/out/plugin.json
```

Open **Plugins → Examples → My analysis**, then click **Say hello**. The status
changes to “Hello from your compiled plugin!” Edit Name, close the panel and
reopen it. The name is opt-in persistent state. The panel supports workspace and
floating placement. Plugin diagnostics are available through **Tools → Plugins**.

Unsigned development manifests require these launch flags every time.
`--safe-mode` suppresses plugin startup, including development plugins.

Alternatively launch with only `--plugin-development`, open **Tools > Plugins**,
and choose **Load development manifest…**. This loads the plugin for this launch;
unsigned development registration is intentionally not persisted. Repeat the load
after restarting, or use the CLI manifest argument on each launch. The supported
CLI form is two arguments: `--plugin-manifest /absolute/path/plugin.json`.

## How the code works

The complete, buildable source is
[the panel template](../templates/panel/plugin.cpp). It subclasses
`et::sdk::Plugin`, declares its identity/capabilities, and exports the
`et_plugin_query` entry point through `ET_PLUGIN(Starter)`.

`start` negotiates `Ui`, builds a `PanelBuilder`, and defines it. The host creates
the real controls. Click events run on the worker dispatcher. The handler sends
an atomic `Ui::patch` using the event's revision and origin, and receives a
completion result. A returned `ET_OK` means the request was accepted for
processing; check the completion for the final outcome.

The template keeps its callback owner and completion options in the plugin object.
The builder owns its temporary strings; service calls copy input data before
returning. Never retain pointers into a borrowed event or reply.

## Add your workflow

Use [read services](READ.md) for telemetry and logs, [jobs](JOBS.md) for background
calculation, and [calibration proposals](TUNE.md) to preview edits before an
explicit Apply. Try the [examples](EXAMPLES.md) with their synthetic fixtures.
Package your result using the [publishing guide](PUBLISHING.md).
