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
85 changes: 85 additions & 0 deletions .github/workflows/run_unix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,91 @@ jobs:
ninja install
env:
BRAINFLOW_VERSION: ${{ steps.version.outputs.version }}
- name: Build Swift Package MacOS
if: (matrix.os == 'macos-14')
run: |
cd $GITHUB_WORKSPACE/swift_package
swift --version
BRAINFLOW_LIB_DIR=$GITHUB_WORKSPACE/installed/lib swift build
- name: Test Swift Package MacOS
if: (matrix.os == 'macos-14')
run: |
cd $GITHUB_WORKSPACE/swift_package
BRAINFLOW_LIB_DIR=$GITHUB_WORKSPACE/installed/lib swift test
- name: Swift CLI Synthetic Board MacOS
if: (matrix.os == 'macos-14')
run: |
cd $GITHUB_WORKSPACE/swift_package
BRAINFLOW_LIB_DIR=$GITHUB_WORKSPACE/installed/lib swift run brainflow-swift-cli

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add all examples to CI as in brainflow dosc https://brainflow.readthedocs.io/en/stable/Examples.html#python

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c030c76. I added all documented Swift examples as SwiftPM executable products and added a macOS CI step that runs them all with BRAINFLOW_LIB_DIR=$GITHUB_WORKSPACE/installed/lib swift run <example>.

- name: Swift Examples MacOS
if: (matrix.os == 'macos-14')
run: |
cd $GITHUB_WORKSPACE/swift_package
for example in \
swift-brainflow-get-data \
swift-markers \
swift-read-write-file \
swift-downsampling \
swift-transforms \
swift-signal-filtering \
swift-denoising \
swift-band-power \
swift-eeg-metrics \
swift-ica
do
BRAINFLOW_LIB_DIR=$GITHUB_WORKSPACE/installed/lib swift run "$example"
done
- name: Build Apple XCFramework Artifacts
if: (matrix.os == 'macos-14')
run: |
$GITHUB_WORKSPACE/tools/apple/build_xcframeworks.sh \
--output $GITHUB_WORKSPACE/build/apple_xcframeworks
env:
BRAINFLOW_VERSION: ${{ steps.version.outputs.version }}
- name: Verify Apple XCFramework Artifacts
if: (matrix.os == 'macos-14')
run: |
$GITHUB_WORKSPACE/tools/apple/verify_xcframeworks.sh $GITHUB_WORKSPACE/build/apple_xcframeworks
- name: Build Generated Swift Binary Package MacOS
if: (matrix.os == 'macos-14')
run: |
cd $GITHUB_WORKSPACE/build/apple_xcframeworks/BrainFlowSwiftBinaryPackage
swift build
- name: Test Generated Swift Binary Package MacOS
if: (matrix.os == 'macos-14')
run: |
$GITHUB_WORKSPACE/tools/apple/test_swift_binary_package.sh $GITHUB_WORKSPACE/build/apple_xcframeworks
- name: Build iOS Demo With Generated XCFrameworks
if: (matrix.os == 'macos-14')
run: |
BRAINFLOW_APPLE_XCFRAMEWORKS_DIR=$GITHUB_WORKSPACE/build/apple_xcframeworks/XCFrameworks \
xcodebuild -quiet \
-project $GITHUB_WORKSPACE/swift_package/examples/apps/ios/BrainFlowiOSDemo/BrainFlowiOSDemo.xcodeproj \
-scheme BrainFlowiOSDemo \
-configuration Debug \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath $GITHUB_WORKSPACE/build/ios-demo-derived \
CODE_SIGNING_ALLOWED=NO \
build
- name: Package macOS Demo With Generated XCFrameworks
if: (matrix.os == 'macos-14')
run: |
BRAINFLOW_APPLE_XCFRAMEWORKS_DIR=$GITHUB_WORKSPACE/build/apple_xcframeworks/XCFrameworks \
$GITHUB_WORKSPACE/tools/apple/package_macos_demo_app.sh $GITHUB_WORKSPACE/build/apple_xcframeworks/BrainFlowMacDemo.app
- name: Upload Apple XCFramework Artifacts
if: (matrix.os == 'macos-14')
uses: actions/upload-artifact@v4
with:
name: brainflow-apple-xcframeworks
path: |
${{ github.workspace }}/build/apple_xcframeworks/BrainFlowAppleXCFrameworks.zip
${{ github.workspace }}/build/apple_xcframeworks/BrainFlowAppleXCFrameworks.zip.sha256
${{ github.workspace }}/build/apple_xcframeworks/checksums.sha256
${{ github.workspace }}/build/apple_xcframeworks/swiftpm-checksums.txt
${{ github.workspace }}/build/apple_xcframeworks/swiftpm-checksums.json
${{ github.workspace }}/build/apple_xcframeworks/manifest.json
${{ github.workspace }}/build/apple_xcframeworks/SwiftPMArtifacts/*.xcframework.zip
${{ github.workspace }}/build/apple_xcframeworks/BrainFlowSwiftPackageRemote
- name: Compile BrainFlow Ubuntu
if: (matrix.os == 'ubuntu-latest')
run: |
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ BenchmarkDotNet.Artifacts/
project.lock.json
project.fragment.lock.json
artifacts/
swift_package/Artifacts/Apple/

# StyleCop
StyleCopReport.xml
Expand Down Expand Up @@ -96,6 +97,10 @@ ipch/
*.opensdf
*.sdf
*.cachefile
.swiftpm/
.build/
xcuserdata/
DerivedData/
*.VC.db
*.VC.VC.opendb

Expand Down Expand Up @@ -343,6 +348,7 @@ ASALocalRun/
.vscode/

installed*
build_ios_sim/
compiled/
python/flowcat.egg-info/
.Rproj.user
Expand All @@ -369,6 +375,7 @@ src/ml/train/data/
src/ml/train/data/*.onnx
tools/brainflow-android.aar
build_android_aar/
build_apple/
tools/simpleble-bridge.jar
tools/simpleble-bridge-classes/
tools/simpleble-bridge-sources.txt
Expand Down
47 changes: 47 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Agent Notes

## Apple XCFramework Artifacts

Apple binary artifacts are generated build outputs. They contain framework-wrapped XCFrameworks
for iOS device, iOS simulator, and macOS app integration, plus a generated
`BrainFlowSwiftBinaryPackage` for app developers.

Regenerate the artifacts from the repository root:

```bash
tools/apple/regenerate_artifacts.sh
```

Verify an existing artifact tree:

```bash
tools/apple/verify_xcframeworks.sh build/apple_xcframeworks
```

The regeneration script builds native BrainFlow Apple slices, packages the XCFrameworks, verifies
the required core frameworks, and creates:

- `BrainFlowAppleXCFrameworks.zip` for complete archive downloads.
- `SwiftPMArtifacts/*.xcframework.zip` with each `.xcframework` at the ZIP root.
- `BrainFlowSwiftPackageRemote`, a generated URL-based SwiftPM package manifest.
- `swiftpm-checksums.txt` and `swiftpm-checksums.json` from `swift package compute-checksum`.

By default, `tools/apple/regenerate_artifacts.sh` and `tools/apple/build_xcframeworks.sh` write to
`build/apple_xcframeworks`. Do not commit `build/`, `build_apple/`, `swift_package/Artifacts/Apple`,
or local `installed/` outputs.

The iOS demo and macOS packaging script default to `build/apple_xcframeworks/XCFrameworks`.
CI may override artifact paths with
`BRAINFLOW_APPLE_XCFRAMEWORKS_DIR`.

When changing Apple artifact generation, regenerate locally and run verification. CI uploads the
aggregate archive, the individual SwiftPM `.xcframework.zip` assets, checksums, generated remote
Swift package, and `manifest.json` as the distributable artifact set. Generated framework headers
and binaries should come from the scripts, not from files copied into the repository.

For a BrainFlow release or Apple-library refresh, build from the release commit/tag with
`BRAINFLOW_VERSION` set. Set `BRAINFLOW_APPLE_RELEASE_BASE_URL` when release assets are hosted
outside the default GitHub Release tag URL. Regenerate artifacts, verify the generated tree,
smoke-test the generated Swift binary package, validate the iOS/macOS sample apps against the
regenerated XCFrameworks, and publish the individual SwiftPM ZIPs next to their checksum files.
Do not manually patch release frameworks after generation; update source and rerun the script.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ option (BUILD_ONNX "BUILD_ONNX" OFF)
option (BUILD_TESTS "BUILD_TESTS" OFF)
option (BUILD_PERIPHERY "BUILD_PERIPHERY" OFF)
option (BRAINFLOW_COPY_TO_PACKAGE_DIRS "Copy built artifacts into language package folders" ON)
option (BRAINFLOW_APPLE_DYNAMIC_FRAMEWORKS "Build Apple iOS native libraries as dynamic libraries for framework/XCFramework packaging" OFF)

set (BRAINFLOW_IOS OFF)
if (CMAKE_SYSTEM_NAME STREQUAL "iOS")
Expand All @@ -44,6 +45,11 @@ set (BRAINFLOW_CORE_LIBRARY_TYPE SHARED)
if (BRAINFLOW_IOS)
set (BRAINFLOW_CORE_LIBRARY_TYPE STATIC)

if (BRAINFLOW_APPLE_DYNAMIC_FRAMEWORKS)
message (STATUS "Building iOS BrainFlow native libraries as dynamic libraries for XCFramework packaging.")
set (BRAINFLOW_CORE_LIBRARY_TYPE SHARED)
endif ()

if (BRAINFLOW_COPY_TO_PACKAGE_DIRS)
message (STATUS "Disabling BRAINFLOW_COPY_TO_PACKAGE_DIRS for iOS builds.")
set (BRAINFLOW_COPY_TO_PACKAGE_DIRS OFF CACHE BOOL "Copy built artifacts into language package folders" FORCE)
Expand Down
74 changes: 74 additions & 0 deletions docs/AppStoreReadiness.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
.. _app-store-readiness-label:

App Store Readiness
===================

This checklist is intentionally separate from the sample source because final App Store submission
requires a developer account, bundle IDs, certificates, provisioning profiles, App Store Connect
records, screenshots, and final product metadata.

Shared
------

- Build with the current App Store-required SDK in Xcode.
- Replace placeholder bundle IDs.
- Add production app icons and screenshots.
- Keep the synthetic-board demo path available so App Review can exercise the app without external
hardware.
- Embed BrainFlow XCFramework products in the app bundle and sign them with the app.
- Use the generated :code:`BrainFlowSwiftBinaryPackage` for production app integration. Do not rely
on :code:`BRAINFLOW_LIB_DIR`, local :code:`installed/lib` folders, or loose development dylibs in
App Store builds.
- Confirm final privacy answers reflect real-board connectivity, Bluetooth, networking, files, and
any third-party native dependencies actually shipped.
- Run an archive build and install it on a physical device or clean Mac before upload.
- Verify the archive contains only device slices for iOS, with embedded framework install names in
the form :code:`@rpath/<Framework>.framework/<Framework>`.

iOS
---

- Use :code:`examples/apps/ios/BrainFlowiOSDemo` as the Xcode app project.
- Use the generated Swift binary package or embed framework slices from
:code:`build/apple_xcframeworks/XCFrameworks`.
- Provide iOS-compatible BrainFlow native binaries through XCFrameworks. The high-level Swift
package compiles for iOS, but BrainFlow calls can only run when matching native frameworks are
embedded and signed.
- For Muse native BLE boards, build BrainFlow native libraries with BLE support enabled for the
target platform and keep the Bluetooth privacy string in the app plist.
- Keep permissions minimal. The synthetic-board demo needs no network or file permissions.
- Test via TestFlight before App Store submission.

macOS
-----

- Use :code:`swift_package` product :code:`BrainFlowMacDemo` for local development, or package it
with :code:`tools/apple/package_macos_demo_app.sh` for app-bundle smoke testing.
- Add the files from :code:`examples/apps/macos/BrainFlowMacDemo`.
- Enable App Sandbox.
- Embed and sign BrainFlow XCFramework products.
- Verify dynamic loading works inside the app bundle, not only with :code:`BRAINFLOW_LIB_DIR`.

Production Gate
---------------

- Swift package builds.
- Swift tests pass with native libraries present.
- CLI smoke test succeeds with the synthetic board.
- :code:`tools/apple/build_xcframeworks.sh` and :code:`tools/apple/verify_xcframeworks.sh` pass.
- :code:`tools/apple/regenerate_artifacts.sh` refreshes :code:`build/apple_xcframeworks`, and
:code:`tools/apple/verify_xcframeworks.sh build/apple_xcframeworks` passes.
- The Apple release artifact set includes the individual SwiftPM XCFramework zips,
:code:`swiftpm-checksums.txt`, :code:`swiftpm-checksums.json`,
:code:`BrainFlowSwiftPackageRemote`, :code:`BrainFlowAppleXCFrameworks.zip`,
:code:`BrainFlowAppleXCFrameworks.zip.sha256`, :code:`checksums.sha256`, and
:code:`manifest.json` from the same build.
- :code:`manifest.json` records the BrainFlow version, source revision, toolchain versions,
deployment targets, optional native feature flags, SwiftPM release URL base, and binary target
checksums.
- A clean app consumes :code:`BrainFlowSwiftBinaryPackage` without building native BrainFlow
locally.
- iOS and macOS app targets launch, handle missing native frameworks gracefully, and run the
synthetic-board workflow when frameworks are embedded.
- Accessibility labels and dynamic text behavior are reviewed in the sample apps.
- Crash logs are clean after repeated start, stop, read, and release cycles.
Loading
Loading