Skip to content
Draft
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
66 changes: 66 additions & 0 deletions .github/workflows/test-addon.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: test-addon

# Tests the addon against a tagged openFrameworks release (see OF_TAG below).
on:
push:
pull_request:
workflow_dispatch:
inputs:
of_tag:
description: "openFrameworks tag to test against (blank = OF_TAG below)"

env:
# TODO: change to test another OF version, e.g. nightly/master checkout
OF_TAG: ${{ inputs.of_tag || '0.12.1' }}
# TODO: rename to your addon (must match addon_config.mk ADDON_NAME)
ADDON_NAME: ofxMyAddon

jobs:
linux64:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
path: addon
- name: Clone openFrameworks at tag
run: git clone --depth 1 --branch "$OF_TAG" https://github.com/openframeworks/openFrameworks ~/openFrameworks
- name: Install OF dependencies
run: |
cd ~/openFrameworks
sudo ./scripts/ci/linux64/install.sh
./scripts/linux/download_libs.sh
- name: Install addon
run: |
mv "$GITHUB_WORKSPACE/addon" ~/openFrameworks/addons/$ADDON_NAME
cd ~/openFrameworks/addons/$ADDON_NAME
./scripts/download_libs.sh linux64 || echo "no libs release yet, continuing with sources only"
- name: Build examples
run: |
export OF_ROOT=~/openFrameworks
for ex in ~/openFrameworks/addons/$ADDON_NAME/example_*; do
[ -d "$ex" ] || continue
echo "== building $ex"
make -C "$ex" -j"$(nproc)"
done

osx:
runs-on: macos-15
steps:
- uses: actions/checkout@v6
with:
path: addon
- name: Clone openFrameworks at tag
run: git clone --depth 1 --branch "$OF_TAG" https://github.com/openframeworks/openFrameworks ~/openFrameworks
- name: Install addon
run: |
mv "$GITHUB_WORKSPACE/addon" ~/openFrameworks/addons/$ADDON_NAME
cd ~/openFrameworks/addons/$ADDON_NAME
./scripts/download_libs.sh osx || echo "no libs release yet, continuing with sources only"
- name: Build examples
run: |
export OF_ROOT=~/openFrameworks
for ex in ~/openFrameworks/addons/$ADDON_NAME/example_*; do
[ -d "$ex" ] || continue
echo "== building $ex"
make -C "$ex" -j"$(sysctl -n hw.ncpu)"
done
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,19 @@ Desktop.ini
*.log
*.sql
*.sqlite

#########################
# addon prebuilt binaries
#########################

# Binaries are fetched with scripts/download_libs.sh, not committed.
# (Folder skeleton is kept via .gitkeep files.)
libs/*/lib/**/*.[ao]
libs/*/lib/**/*.lib
libs/*/lib/**/*.so
libs/*/lib/**/*.dylib
libs/*/lib/**/*.dll
libs/*/lib/**/*.framework
libs/*/lib/**/*.xcframework
*.tar.bz2
/releases/
92 changes: 92 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# CMakeLists.txt - TEMPLATE for building an openFrameworks addon + example with CMake.
#
# Usage:
# cmake -S . -B build -DOF_ROOT=/path/to/openFrameworks -DOF_TARGET=linux64
# cmake --build build
#
# OF_TARGET must be one of the projectGenerator platform tokens, matching a
# folder under libs/<lib>/lib/ (see addon_config.mk sections):
# osx | ios | tvos | vs | msys2 | linux64 | linuxarmv6l | linuxarmv7l |
# linuxaarch64 | android | emscripten
#
cmake_minimum_required(VERSION 3.16)

# TODO: rename to your addon (must match addon_config.mk ADDON_NAME)
set(ADDON_NAME ofxMyAddon)
project(${ADDON_NAME} LANGUAGES C CXX)

set(OF_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "openFrameworks root")
set(OF_TARGET "linux64" CACHE STRING "OF platform token (see above)")

# Same language standards as apothecary (scripts/apothecary/apothecary/apothecary):
# C 17, C++ 23, honoring apothecary's C_STANDARD / CPP_STANDARD env overrides.
if("$ENV{C_STANDARD}" STREQUAL "")
set(C_STANDARD 17)
else()
set(C_STANDARD "$ENV{C_STANDARD}")
endif()
if("$ENV{CPP_STANDARD}" STREQUAL "")
set(CPP_STANDARD 23)
else()
set(CPP_STANDARD "$ENV{CPP_STANDARD}")
endif()
set(CMAKE_C_STANDARD ${C_STANDARD})
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD ${CPP_STANDARD})
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# --- addon sources: mirrors what PG auto-discovers (src/ + libs/*/src|include).
# PG walks both trees recursively, so this recurses too: sources nested at any
# depth (e.g. libs/<lib>/src/vendor/sub/file.cpp) are picked up. Binaries under
# libs/*/lib/ are ignored by extension. To drop files per-platform, prune the
# lists (the equivalent of addon_config.mk ADDON_SOURCES_EXCLUDE), e.g.:
# list(FILTER ADDON_SOURCES EXCLUDE REGEX ".*port/AndroidJNI.*")
file(GLOB_RECURSE ADDON_SOURCES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cxx"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/*.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/*.cxx")
file(GLOB_RECURSE ADDON_HEADERS CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/libs/*.hpp")

add_library(${ADDON_NAME} STATIC ${ADDON_SOURCES} ${ADDON_HEADERS})
target_include_directories(${ADDON_NAME} PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/src")

# Every lib folder becomes an include path, like the PG does.
file(GLOB LIB_INCLUDE_DIRS LIST_DIRECTORIES true "${CMAKE_CURRENT_SOURCE_DIR}/libs/*")
foreach(d IN LISTS LIB_INCLUDE_DIRS)
if(IS_DIRECTORY "${d}")
target_include_directories(${ADDON_NAME} PUBLIC "${d}/include" "${d}/src")
endif()
endforeach()

# --- prebuilt binaries for this platform (download with scripts/download_libs.sh)
set(OF_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libs")
file(GLOB PREBUILT_LIBS
"${OF_LIB_DIR}/*/lib/${OF_TARGET}/*.a"
"${OF_LIB_DIR}/*/lib/${OF_TARGET}/*.so"
"${OF_LIB_DIR}/*/lib/${OF_TARGET}/*.dylib"
"${OF_LIB_DIR}/*/lib/${OF_TARGET}/*.lib")
if(APPLE)
# PG treats osx/macos as aliases; accept either folder.
file(GLOB PREBUILT_LIBS_MACOS "${OF_LIB_DIR}/*/lib/macos/*")
list(APPEND PREBUILT_LIBS ${PREBUILT_LIBS_MACOS})
endif()
if(PREBUILT_LIBS)
target_link_libraries(${ADDON_NAME} PUBLIC ${PREBUILT_LIBS})
else()
message(WARNING "No prebuilt libs for OF_TARGET=${OF_TARGET}; run scripts/download_libs.sh ${OF_TARGET}")
endif()

# --- OF core headers (compile against a tagged OF checkout, e.g. 0.12.1)
if(IS_DIRECTORY "${OF_ROOT}/libs/openFrameworks")
target_include_directories(${ADDON_NAME} PUBLIC "${OF_ROOT}/libs/openFrameworks")
endif()
11 changes: 10 additions & 1 deletion README_DEPLOY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ State which license you offer your addon under. openFrameworks is distributed un

Installation
------------
Any steps necessary to install your addon. Optimally, this means just dropping the folder into the `openFrameworks/addons/` folder.
Drop the folder into the `openFrameworks/addons/` folder, then fetch the
prebuilt binaries for your platform:

./scripts/download_libs.sh # auto-detects: osx, linux64, msys2, ...
./scripts/download_libs.sh ios # a specific platform, or `all`

(On Windows run it from git-bash, or use `scripts\download_libs.cmd`.)
If your platform has no prebuilt release yet, the addon still builds from the
sources under `libs/*/src/` - see `scripts/build_libs.sh` to build and publish
binaries.

Dependencies
------------
Expand Down
10 changes: 8 additions & 2 deletions addon_config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,15 @@ vs:

linuxarmv6l:
linuxarmv7l:
android/armeabi:
android/armeabi-v7a:
linuxaarch64:
msys2:
emscripten:
android/armeabi-v7a:
android/arm64-v8a:
android/x86:
android/x86_64:
osx:
macos:
# osx/iOS only, any framework that should be included in the project
# ADDON_FRAMEWORKS =
ios:
Expand Down
28 changes: 28 additions & 0 deletions libs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# libs/

Prebuilt binaries live here, one folder per openFrameworks platform token:

libs/<lib>/lib/osx/ macOS (also matches the `macos` alias)
libs/<lib>/lib/ios/ iOS
libs/<lib>/lib/tvos/ tvOS
libs/<lib>/lib/vs/ Windows Visual Studio (.lib)
libs/<lib>/lib/msys2/ Windows MSYS2/MinGW
libs/<lib>/lib/linux64/ Linux x86_64
libs/<lib>/lib/linuxarmv6l/ Linux ARMv6 (Raspberry Pi 1/Zero)
libs/<lib>/lib/linuxarmv7l/ Linux ARMv7 (Raspberry Pi 2/3)
libs/<lib>/lib/linuxaarch64/ Linux ARM64
libs/<lib>/lib/android/<abi>/ armeabi-v7a, arm64-v8a, x86, x86_64
libs/<lib>/lib/emscripten/ Emscripten (WebAssembly)

The names are load-bearing: the projectGenerator links a binary only if its
path contains the platform token, and `scripts/download_libs.sh` resolves the
same names to GitHub release assets.

Binaries are NOT committed (see `.gitignore`). Fetch them with:

./scripts/download_libs.sh # auto-detect host platform
./scripts/download_libs.sh linux64 # or: all, osx, ios, vs, ...

Sources under `libs/<lib>/src/` and headers under `libs/<lib>/include/` are
compiled automatically by the projectGenerator and the CMakeLists template -
no `addon_config.mk` entries needed.
Empty file.
Empty file.
90 changes: 90 additions & 0 deletions scripts/build_libs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env bash
#
# build_libs.sh - TEMPLATE for building addon libs and packaging them as
# GitHub release assets with the naming convention expected by
# scripts/download_libs.sh:
#
# <addon-name>-libs-<platform>-<libs-version>.tar.bz2
#
# Usage:
# scripts/build_libs.sh [platform] [-v <libs-version>]
# scripts/build_libs.sh --upload [platform] [-v <libs-version>] (needs `gh`)
#
# Steps for the addon author:
# 1. Set LIB_NAME / LIB_SRC / BUILD_CMDS below to build your lib.
# 2. Run this on each platform (or in CI), producing one archive per platform.
# 3. Create a GitHub release named <libs-version> and upload the archives:
# gh release create 1.0.0 releases/*.tar.bz2
# 4. Point scripts/download_libs.sh at your repo (GITHUB_REPO) and version.
#
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ADDON_DIR="$(dirname "$SCRIPT_DIR")"
ADDON_NAME="$(basename "$ADDON_DIR")"

# ---------------------------------------------------------------- TODO: edit
LIB_NAME="necessaryLib" # folder under libs/ holding include/ src/ lib/
LIBS_VERSION="1.0.0" # GitHub release tag the archives are uploaded to
RELEASE_DIR="$ADDON_DIR/releases"
# ----------------------------------------------------------------------------

PLATFORM=""
UPLOAD=0
while [ $# -gt 0 ]; do
case "$1" in
-v|--version) LIBS_VERSION="$2"; shift 2 ;;
--upload) UPLOAD=1; shift ;;
-h|--help) sed -n '2,/^$/p' "$0"; exit 0 ;;
*) PLATFORM="$1"; shift ;;
esac
done

if [ -z "$PLATFORM" ]; then
# Same detection as download_libs.sh
case "$(uname -s)" in
Darwin) PLATFORM="osx" ;;
MINGW*|MSYS*|CYGWIN*) PLATFORM="msys2" ;;
Linux)
case "$(uname -m)" in
x86_64) PLATFORM="linux64" ;;
armv6l) PLATFORM="linuxarmv6l" ;;
armv7l) PLATFORM="linuxarmv7l" ;;
aarch64) PLATFORM="linuxaarch64" ;;
*) PLATFORM="linux64" ;;
esac ;;
*) PLATFORM="linux64" ;;
esac
fi
if [ "$PLATFORM" = "macos" ]; then PLATFORM="osx"; fi

LIB_DIR="$ADDON_DIR/libs/$LIB_NAME"
OUT_DIR="$LIB_DIR/lib/$PLATFORM"

echo "==> TODO: build your lib here and install the binaries into:"
echo " $OUT_DIR"
echo " (edit the BUILD section of $0)"
# Example: build from libs/$LIB_NAME/src with cmake/make, then copy:
# cmake -S "$LIB_DIR/src" -B "/tmp/${LIB_NAME}-build" -DCMAKE_BUILD_TYPE=Release
# cmake --build "/tmp/${LIB_NAME}-build" --config Release
# mkdir -p "$OUT_DIR"
# cp "/tmp/${LIB_NAME}-build/libnecessaryLib.a" "$OUT_DIR/"

if [ ! -d "$OUT_DIR" ]; then
echo "ERROR: $OUT_DIR does not exist. Build the lib for $PLATFORM first." >&2
exit 1
fi

ASSET="${ADDON_NAME}-libs-${PLATFORM}-${LIBS_VERSION}.tar.bz2"
mkdir -p "$RELEASE_DIR"
# Archive paths relative to libs/$LIB_NAME so they extract to lib/<platform>/...
tar -cjf "$RELEASE_DIR/$ASSET" -C "$LIB_DIR" "lib/$PLATFORM" "include"
echo "==> wrote $RELEASE_DIR/$ASSET"
tar -tjf "$RELEASE_DIR/$ASSET" | head -n 20

if [ "$UPLOAD" = "1" ]; then
gh release upload "$LIBS_VERSION" "$RELEASE_DIR/$ASSET" --clobber
fi

echo "Upload all platform archives with:"
echo " gh release create $LIBS_VERSION $RELEASE_DIR/*.tar.bz2"
18 changes: 18 additions & 0 deletions scripts/download_libs.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@echo off
REM download_libs.cmd - Windows shim: VS uses the bash script via git-bash.
REM Requires git-bash (ships with Git for Windows). Usage:
REM scripts\download_libs.cmd [platform] [-v <libs-version>] [-u <user/repo>]
REM With no arguments it downloads the `vs` libs (a bare run under git-bash
REM would otherwise auto-detect `msys2`).
setlocal
where bash >nul 2>&1
if errorlevel 1 (
echo bash not found. Install Git for Windows and run this from git-bash:
echo ./scripts/download_libs.sh vs
exit /b 1
)
if "%~1"=="" (
bash "%~dp0download_libs.sh" vs
) else (
bash "%~dp0download_libs.sh" %*
)
Loading