> For the complete documentation index, see [llms.txt](https://docs.licensespring.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.licensespring.com/sdks/tutorials/getting-started/c++/juce-framework-sample.md).

# JUCE Framework sample

### Prerequisites

* Completed the [Getting Started](/sdks/introduction.md) tutorial, specifically:
  * Initialized `LicenseManager` (or `LicenseHandler`) with your configuration using the appropriate settings.
  * Activated a key-based license of any type.

\
Alongside other samples, the C++ SDK contains a JUCE Framework sample that demonstrates how to set up, build and deploy an app or DAW plugin using the JUCE Framework. The sample is contained in `sample/JUCESamples` with a `README.md` file on how to build the CMake- or Projucer-based project.

The LicenseSpring SDK enables you to:

* Validate a license offline to check for license expiry, device binding, clock tampering. A user on a disconnected machine can still keep using the plugin, and you can define proper entitlement decisions.
* Use a single thread-safe state per user. A DAW that instantiates the plugin multiple times does not need a custom locking mechanism.

### Adding the SDK to a JUCE project

You need three things: the headers on your include path, the import/shared library on your link line, and the runtime libraries next to (or inside) your product.

The SDK package layout is:

```
LicenseSpring/
├── include/LicenseSpring/*.h
├── bin/
│   ├── x64/dynamic/            # Windows: LicenseSpring.lib/.dll, LicenseSpringD.lib/.dll
│   ├── shared/Release/         # macOS / Linux: libLicenseSpring.dylib | .so
│   └── ...
└── samples/
```

#### CMake (recommended)

JUCE has supported CMake since 6.0 and it is the practical default for new JUCE projects. It is also the only one of the two options that covers Linux. The sample folder contains a `CMakeLists.txt` that configures building both a standalone app and a plugin/

#### Projucer

If you are staying on the `.jucer` workflow:

1. Add your licensing sources to the project.
2. Per exporter configuration, set **Header Search Paths** to the SDK's `include` directory and **Extra Library Search Paths** to the relevant `bin/...` directory.
3. **External Libraries to Link**: `LicenseSpring` (or `LicenseSpringD` in Debug on Windows).
4. Add a post-build step that copies the runtime libraries into the built product.
5. Leave the JUCE modules on global paths so the project opens on other machines.

The sample directory contains three `.jucer` project files: a dynamically linked standalone app, a dynamically linked plugin and a statically linked plugin.

***

### Shipping the runtime libraries

Where the shared libraries have to end up differs by platform, and getting this wrong produces a plugin that loads on your machine and fails to load on your customers'.

**Windows**

1. If dynamically linking, place `LicenseSpring.dll`, `libcrypto-3-x64.dll`, `libssl-3-x64.dll` and `libcurl.dll` next to the host DAW `.exe`.
2. If that's not feasible, statically link LicenseSpring libraries so you only need to ship the VST3 plugin directory.

**macOS**

Place `libLicenseSpring.dylib` , and OpenSSL and curl dylibs inside the bundle at `Contents/Frameworks/`, and give the binary an rpath that finds them:

```cmake
foreach (fmt IN ITEMS VST3 AU Standalone)
    if (TARGET MyPlugin_${fmt})
        set_target_properties(MyPlugin_${fmt} PROPERTIES
            BUILD_WITH_INSTALL_RPATH TRUE
            INSTALL_RPATH "@loader_path/../Frameworks")
        add_custom_command(TARGET MyPlugin_${fmt} POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E make_directory
                    "$<TARGET_BUNDLE_CONTENT_DIR:MyPlugin_${fmt}>/Frameworks"
            COMMAND ${CMAKE_COMMAND} -E copy_if_different
                    "$<TARGET_FILE:LicenseSpring>"
                    "$<TARGET_BUNDLE_CONTENT_DIR:MyPlugin_${fmt}>/Frameworks/")
    endif ()
endforeach ()
```

Copying the dylibs *next to* the `.app`/`.vst3` instead of inside it appears to work when you launch from Xcode, and then fails for every real user.

**Linux.** `libLicenseSpring.so` is built with `RPATH=$ORIGIN`, so place it and the OpenSSL/curl `.so` files in the same directory as your `.so`/`.vst3` binary.

#### Unlicensed behavior

Decide deliberately, and remove a small feature that the user can't work without:

* **Periodic noise burst or short mute:** the audio-plugin convention. Fully audible, obviously intentional, not usable for production.
* **Feature-limited:** full audio quality, premium controls disabled.
* **Time-limited session:** degrade after N minutes of playback.&#x20;

#### Where the activation UI goes

Put it in the editor, as an overlay or a page in your existing UI. One constraint is the editor may not exist, so don't make entitlement depend on the editor having been opened. Also, modal loops are hostile in a plugin, and some hosts explicitly disable the&#x6D;**.**

#### Offline and air-gapped studios

A meaningful share of professional audio machines have no network. Support them via [offline activation](/license-entitlements/license-activation-types/offline-license-activation.md) or [air-gapped activation](/sdks/tutorials/licensing-scenarios/air-gapped-licensing.md). See `src/samples/AirGapQtSample` for a complete UI flow.

### Feature gating for plugin tiers

Ship one binary and let the license decide what it does via [license features](/license-entitlements/features.md):

```cpp
bool hasFeature(const std::string& code)
{
    auto& lh = LicenseHandler::instance();
    if (!lh.hasLicenseFeatures())
        return false;
    const auto& feature = lh.getLicenseFeature (code);
    if (lh.wasError())          // unknown code, or wrong feature type
    {
        lh.clearErrorInfo();
        return false;
    }
    return !feature.isExpired();
}
```

Cache the results into atomics at startup alongside the main entitlement flag, and read only the atomics from audio code:

```cpp
struct Entitlements
{
    std::atomic<bool> pro { false };
    std::atomic<bool> renders  { false };
};
```

This is what makes Lite/Pro upgrades a license change rather than a new build and a new installer. It also gives you time-limited feature trials for free: a consumption or expiring feature turns a premium module into a "try it for 14 days" module without shipping anything.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.licensespring.com/sdks/tutorials/getting-started/c++/juce-framework-sample.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
