Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,4 @@ libs/openFrameworksCompiled/project/android/build-*/


examples/utils/urlFileLoaderExample/bin/data
tests/graphics/imageFormats/bin/data/*
88 changes: 71 additions & 17 deletions scripts/of.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# of.sh - openFrameworks CLI | Dan Rosser 2025
OF_SCRIPT_VERSION=0.4.3
OF_SCRIPT_VERSION=0.4.4

OF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
OF_DIR="$(realpath "$OF_DIR/../")"
Expand Down Expand Up @@ -1051,14 +1051,25 @@ menuTest(){
printBanner "test"

local -a opts=("All tests/ smoke tests (build + run)|tests-all")
local g gName
local -a testOpts=()
local -a groupOpts=()
local g gName test testName
if [[ -d "${OF_DIR}/tests" ]]; then
for g in "${OF_DIR}/tests"/*/; do
[[ -d "$g" ]] || continue
gName=$(basename "${g%/}")
opts+=("tests/${gName} only|tests-${gName}")
groupOpts+=("All tests/${gName}|tests-${gName}")
for test in "$g"*/; do
[[ -d "${test}src" ]] || continue
testName=$(basename "${test%/}")
testOpts+=("${gName}/${testName}|test:${gName}/${testName}")
done
done
fi
# Keep every directly runnable project together at the top of the menu;
# broader group runs follow them.
opts+=("${testOpts[@]}")
opts+=("${groupOpts[@]}")
local -a smokeScripts=()
local s
for s in "${OF_CORE_SCRIPT_DIR}/dev"/smoke_test_*.sh; do
Expand All @@ -1074,6 +1085,7 @@ menuTest(){
case "$choice" in
tests-all) cmdTest ;;
tests-*) cmdTest "${choice#tests-}" ;;
test:*) cmdTest "${choice#test:}" ;;
script:*)
local scriptName="${choice#script:}"
local scriptPath="${OF_CORE_SCRIPT_DIR}/dev/${scriptName}"
Expand Down Expand Up @@ -1560,9 +1572,52 @@ menuPickApoVsVer(){
return 0
}

menuPickApoArch(){
local type="$1" a
local -a choices=() arches=()
if [[ "$type" == "vs" ]]; then
choices=(
"All (x64 + ARM64 + ARM64EC)|all"
"x64 (64)|64"
"ARM64|arm64"
"ARM64EC|arm64ec"
"ARM64 + ARM64EC|arm64+arm64ec"
)
else
read -r -a arches <<< "$(archesForApoType "$type")"
for a in "${arches[@]}"; do choices+=("${a}|${a}"); done
fi
menuPick "Target architecture · ${type}" "${choices[@]}"
}

# Keep the native platform first in Apothecary's platform menus. In
# particular, Windows users should see Visual Studio before Apple targets.
apoBuildTypesOrdered(){
local type
if [[ "$OF_PLATFORM" == "vs" ]]; then
printf '%s\n' vs
fi
for type in "${APO_BUILD_TYPES[@]}"; do
[[ "$OF_PLATFORM" == "vs" && "$type" == "vs" ]] && continue
printf '%s\n' "$type"
done
}

runApothecaryEngine(){
local type="$1" arch="$2"
shift 2
# Apothecary accepts one VS architecture per invocation. Let the oF menu
# expose useful groups while keeping the underlying calls conventional.
if [[ "$type" == "vs" && ( "$arch" == "all" || "$arch" == *","* || "$arch" == *"+"* ) ]]; then
local expanded="$arch" vsArch
[[ "$expanded" == "all" ]] && expanded="64,arm64,arm64ec"
expanded="${expanded//+/,}"
for vsArch in ${expanded//,/ }; do
echoInfo "Visual Studio libraries · ${vsArch}"
runApothecaryEngine "$type" "$vsArch" "$@" || return $?
done
return 0
fi
local -a cmd=()
resolveApothecary
[[ -f "$APO_ENGINE" ]] || { echoError "apothecary engine missing — git submodule update --init scripts/apothecary"; return 1; }
Expand Down Expand Up @@ -1658,45 +1713,37 @@ menuApothecary(){
;;
build-type)
opts=()
for type in "${APO_BUILD_TYPES[@]}"; do
while IFS= read -r type; do
if [[ "$type" == "macos" ]]; then
opts+=("macos — Apple multi-target xcframeworks|macos")
elif [[ "$type" == "osx" ]]; then
opts+=("osx — desktop host|osx")
else
opts+=("${type}|${type}")
fi
done
done < <(apoBuildTypesOrdered)
[[ "$OF_PLATFORM" == "osx" ]] && echoNote "macos covers osx · ios · tvos · xros · watchos · catos"
menuPick "Build platform" "${opts[@]}" || return 2
type="$UI_MENU_RESULT"
if [[ "$type" == "vs" ]]; then
menuPickApoVsVer || return 2
export OF_APO_VS_VER="$UI_MENU_RESULT"
fi
aopts=()
read -r -a arches <<< "$(archesForApoType "$type")"
for a in "${arches[@]}"; do
aopts+=("${a}|${a}")
done
menuPick "Architecture · ${type}" "${aopts[@]}" || return 2
menuPickApoArch "$type" || return 2
cmdApothecaryBuildAll "$type" "$UI_MENU_RESULT"
;;
build-one)
opts=()
for type in "${APO_BUILD_TYPES[@]}"; do
while IFS= read -r type; do
opts+=("${type}|${type}")
done
done < <(apoBuildTypesOrdered)
menuPick "Platform" "${opts[@]}" || return 2
type="$UI_MENU_RESULT"
if [[ "$type" == "vs" ]]; then
menuPickApoVsVer || return 2
export OF_APO_VS_VER="$UI_MENU_RESULT"
fi
aopts=()
read -r -a arches <<< "$(archesForApoType "$type")"
for a in "${arches[@]}"; do aopts+=("${a}|${a}"); done
menuPick "Architecture · ${type}" "${aopts[@]}" || return 2
menuPickApoArch "$type" || return 2
arch="$UI_MENU_RESULT"
opts=()
local f
Expand Down Expand Up @@ -2542,6 +2589,13 @@ cmdBuild(){
;;
esac
;;
tests|test)
if [[ "$OF_PLATFORM" == "vs" ]]; then
runHostTests "${1:-Debug}" "${2:-${OF_VS_PLATFORM:-$(vsPlatformFromArch)}}" "${3:-${OF_VS_TOOLSET:-$(vsToolsetDefault)}}"
else
runHostTests "$@"
fi
;;
clean)
local path="${1:-}"
[[ -n "$path" ]] || { echoError "usage: of build clean <path>"; return 1; }
Expand Down
103 changes: 97 additions & 6 deletions scripts/of_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,75 @@ runMsbuildProject(){
-nologo -m
}

# Regenerate every unit-test project for Visual Studio, then compile it with
# the same platform/toolset selection used by normal project builds. Tests
# are compile-only here: ARM64/ARM64EC binaries may be cross-built on x64.
runVsTests(){
local config="${1:-Debug}"
local platform="${2:-${OF_VS_PLATFORM:-$(vsPlatformFromArch)}}"
local toolset="${3:-${OF_VS_TOOLSET:-$(vsToolsetDefault)}}"
local pgTemplate="${4:-${OF_PG_TEMPLATE:-vs2026}}"
local pg msbuild project count=0 failed=0

pg=$(findPGBinary) || { echoError "Project Generator missing — run: of update pg"; return 1; }
msbuild=$(findMsbuildBinary) || { echoError "msbuild.exe not found"; return 1; }
printBanner "tests"
echoKV "target" "${platform} · ${config} · ${toolset}"
echoInfo "regenerating Visual Studio projects under tests/"
local -a pgArgs=( -r -o"$OF_DIR" -pvs )
[[ -n "$pgTemplate" ]] && pgArgs+=( -t"$pgTemplate" )
PG_OF_PATH="$OF_DIR" "$pg" "${pgArgs[@]}" "${OF_DIR}/tests" || return $?

while IFS= read -r project; do
count=$((count + 1))
echoInfo "test ${count} · ${project#${OF_DIR}/}"
"$msbuild" "$project" -nologo -m \
"-p:Configuration=${config}" \
"-p:Platform=${platform}" \
"-p:PlatformToolset=${toolset}" || failed=$((failed + 1))
done < <(find "${OF_DIR}/tests" -mindepth 2 -name '*.vcxproj' -type f | sort)
[[ $count -gt 0 ]] || { echoError "no generated test projects found"; return 1; }
[[ $failed -eq 0 ]] || { echoError "${failed}/${count} test projects failed to compile"; return 1; }
echoSuccess "${count} test projects compiled · ${platform}/${config}"
}

menuVsTests(){
local config toolset platform template
menuPickConfig || return 0; config="$UI_MENU_RESULT"
menuPickVsToolset || return 0; toolset="$UI_MENU_RESULT"
menuPickVsPlatform || return 0; platform="$UI_MENU_RESULT"
menuPickPgTemplate || return 0; template="$UI_MENU_RESULT"
runVsTests "$config" "$platform" "$toolset" "$template"
}

runHostTests(){
case "$OF_PLATFORM" in
vs)
runVsTests "$@"
;;
osx|macos)
local runner="${OF_DIR}/scripts/ci/${OF_PLATFORM}/run_tests.sh"
[[ -f "$runner" ]] || runner="${OF_DIR}/scripts/ci/osx/run_tests.sh"
echoInfo "macOS tests · make Debug + RunDebug"
bash "$runner"
;;
*)
echoError "tests() is currently available for macOS and Visual Studio"
return 1
;;
esac
}

menuHostTests(){
case "$OF_PLATFORM" in
vs) menuVsTests ;;
osx|macos)
confirmYes "Build and run the macOS unit tests?" || return 0
runHostTests
;;
esac
}

# ---------------------------------------------------------------------------
# Project file helpers
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -923,18 +992,25 @@ runTestProject(){
# reusable from the CLI/menu. Prints a tick per test, full output only on
# failure, and a pass/fail summary at the end.
cmdTest(){
local filterGroup="${1:-}"
local filter="${1:-}"
local filterGroup="${filter%%/*}"
local filterTest=""
[[ "$filter" == */* ]] && filterTest="${filter#*/}"
local testsDir="${OF_DIR}/tests"
[[ -d "$testsDir" ]] || { echoError "no tests/ directory found"; return 1; }

printBanner "test"
echoInfo "running smoke tests under tests/${filterGroup:+$filterGroup/}"
echoInfo "running smoke tests under tests/${filter:+$filter/}"
printf '\n'

local -a groups=()
local g
if [[ -n "$filterGroup" ]]; then
[[ -d "${testsDir}/${filterGroup}" ]] || { echoError "no tests/${filterGroup} folder"; return 1; }
if [[ -n "$filterTest" && ! -d "${testsDir}/${filterGroup}/${filterTest}/src" ]]; then
echoError "no tests/${filterGroup}/${filterTest} project"
return 1
fi
groups=("${testsDir}/${filterGroup}")
else
for g in "${testsDir}"/*/; do
Expand All @@ -953,6 +1029,7 @@ cmdTest(){
[[ -d "$test" && -d "${test}src" ]] || continue
test="${test%/}"
name=$(basename "$test")
[[ -n "$filterTest" && "$name" != "$filterTest" ]] && continue
total=$((total + 1))
# \r-overwrite the pending marker only when actually attached to a
# terminal -- otherwise (piped/logged output) it just garbles two
Expand Down Expand Up @@ -1230,7 +1307,7 @@ menuBuild(){
echoKV "cmake" "$(command -v cmake >/dev/null 2>&1 && cmake --version 2>/dev/null | head -1 || echo 'not installed')"
printf '\n'

menuPick "Build…" \
local -a buildOpts=(
"OF core library (make)|core" \
"Project under apps/…|apps" \
"Example under examples/…|examples" \
Expand All @@ -1240,15 +1317,26 @@ menuBuild(){
"Generate project files (PG)…|generate" \
"CMake…|cmake" \
"Clean project…|clean" \
"Apothecary — build libraries…|apothecary" \
"Apothecary — build libraries…|apothecary"
)
case "$OF_PLATFORM" in
vs) buildOpts+=("Tests — PG + MSBuild…|tests") ;;
osx|macos) buildOpts+=("Tests — make + run…|tests") ;;
esac
buildOpts+=( \
"Upgrade — Projects / Addons…|upgrade" \
"Help|help" \
"Back|back" \
|| return 0
"Back|back"
)
menuPick "Build…" "${buildOpts[@]}" || return 0
choice="$UI_MENU_RESULT"
printf '\n'

case "$choice" in
tests)
menuHostTests
menuPause
;;
core)
menuPickConfig || continue
cmdBuildCore "$UI_MENU_RESULT"
Expand Down Expand Up @@ -1410,6 +1498,9 @@ printHelpBuild(){
${prog} build generate <path> [platforms]
${prog} build cmake <path> [Debug|Release]
${prog} build cmake status
${prog} build tests macOS: make + run all unit tests
${prog} build tests [cfg] [platform] [toolset]
Windows: PG + MSBuild (compile)
${prog} build clean <path>
${prog} build open-em <path> Open emscripten index.html (Chrome/emrun)

Expand Down
1 change: 1 addition & 0 deletions tests/graphics/imageFormats/addons.make
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ofxUnitTests
Empty file.
8 changes: 8 additions & 0 deletions tests/graphics/imageFormats/icon.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Icon Resource Definition
#define MAIN_ICON 102

#if defined(_DEBUG)
MAIN_ICON ICON "icon_debug.ico"
#else
MAIN_ICON ICON "icon.ico"
#endif
Loading
Loading