Skip to content
Open
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 @@ -28,6 +28,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 @@ -38,6 +39,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
37 changes: 36 additions & 1 deletion docs/BuildBrainFlow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,42 @@ Rust
Swift
-------

You can build Swift binding for BrainFlow using xcode. Before that you need to compile C/C++ code :ref:`compilation-label` and ensure that native libraries are properly placed. Keep in mind that currently it supports only MacOS.
You can build Swift bindings for BrainFlow with Swift Package Manager or Xcode. Before running examples or tests you need to compile C/C++ code :ref:`compilation-label` and ensure that native libraries are available to the Swift runtime loader.

Local build example:

.. code-block:: bash

python3 tools/build.py
cd swift_package
BRAINFLOW_LIB_DIR=../installed/lib swift build
BRAINFLOW_LIB_DIR=../installed/lib swift test
BRAINFLOW_LIB_DIR=../installed/lib swift run brainflow-swift-cli
BRAINFLOW_LIB_DIR=../installed/lib swift run swift-brainflow-get-data

The Swift package intentionally does not vendor BrainFlow native binaries. Like source builds for other bindings, it dynamically loads native libraries built from this repository. The loader searches :code:`BRAINFLOW_LIB_DIR`, system library paths, :code:`installed/lib`, and app bundle resource/framework directories for :code:`libBoardController`, :code:`libDataHandler`, and :code:`libMLModule`.

For production iOS and macOS applications, use Apple XCFramework artifacts and the generated Swift binary package. Regenerate Apple artifacts with:

.. code-block:: bash

tools/apple/regenerate_artifacts.sh
tools/apple/verify_xcframeworks.sh build/apple_xcframeworks

The default generated artifact directory is :code:`build/apple_xcframeworks`. It contains :code:`XCFrameworks`, :code:`BrainFlowSwiftBinaryPackage`, :code:`BrainFlowSwiftPackageRemote`, :code:`SwiftPMArtifacts/*.xcframework.zip`, :code:`BrainFlowAppleXCFrameworks.zip`, and checksum files. These generated headers and binaries are release/CI artifacts, not source files committed to the repository.

The generated :code:`BrainFlowSwiftBinaryPackage` contains the Swift API and binary targets for :code:`BoardController.xcframework`, :code:`DataHandler.xcframework`, and :code:`MLModule.xcframework`. Add this package to an app through Xcode or Swift Package Manager so embedded frameworks are handled by standard Apple build, embed, and signing flows.

For public Swift Package distribution, publish the individual zips from :code:`SwiftPMArtifacts` and use :code:`BrainFlowSwiftPackageRemote`, which declares URL-based binary targets with checksums generated by :code:`swift package compute-checksum`. Set :code:`BRAINFLOW_APPLE_RELEASE_BASE_URL` before regeneration if release assets are hosted outside the default GitHub Release tag URL.

The macOS demo can be built with:

.. code-block:: bash

cd swift_package
BRAINFLOW_LIB_DIR=../installed/lib swift run BrainFlowMacDemo

iOS and Mac App Store sample source and release-preparation notes are available in :code:`swift_package/examples/apps`, :code:`swift_package/Docs/AppleBinaryDistribution.md`, and :code:`swift_package/Docs/AppStoreReadiness.md`. App runtime support requires matching BrainFlow native frameworks embedded and signed inside the app bundle; App Store builds should not depend on :code:`BRAINFLOW_LIB_DIR` or local development directories.

Docker Image
--------------
Expand Down
2 changes: 2 additions & 0 deletions docs/Examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@ Typescript ICA
Swift
------------

The Swift examples below are also Swift Package Manager executable products. After building native BrainFlow libraries, run them from :code:`swift_package` with :code:`BRAINFLOW_LIB_DIR=../installed/lib swift run <example-name>`. For example, :code:`swift run swift-brainflow-get-data`.

Swift Get Data from a Board
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion docs/UserAPI.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ Example:
Swift
------

Swift binding calls C/C++ code as any other binding. Use Swift examples and API reference for other languaes as a starting point.
Swift binding calls C/C++ code as any other binding. The Swift package exposes BoardShim, DataFilter, MLModel, params, errors, and BrainFlow constants using the same public API groups as Python and Java. In-place signal-processing methods use Swift :code:`inout [Double]` arguments.

Example:

Expand Down
Loading