Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[*.md]
indent_style = space
markdown_list_style = asterisk
18 changes: 18 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,21 @@
- When using a third-party action (one not hosted in a Google-managed org), a fixed version of the action MUST be used by [specifying a specific commit](https://help.github.com/en/github/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsuses), rather than a branch like "main", or a tagged release, which can be overwritten by any maintainer of the action.
- Docker and [GitHub runner](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources) images should always be run at a fixed version rather than "latest".
- If an action is granted additional GitHub access (by being passed the GITHUB_TOKEN variable), all main development branches (typically, "main") must use [branch protection](https://help.github.com/en/github/administering-a-repository/about-protected-branches) with "Require pull request reviews before merging" enabled and/or "Restrict who can push to matching branches" limited to repository admins.

## Publishing to pub.dev

The `publish.yml` workflow publishes `tflite_core` when a `v<version>` tag is pushed. It checks that the tag matches the package version, runs formatting, analysis, tests, and a pub.dev dry run, then publishes using GitHub Actions OIDC trusted publishing. No pub.dev token is stored in GitHub secrets.

Before using the workflow for releases:

1. Set up and verify the `kmmhanan.com` publisher on pub.dev.
2. Publish the first `tflite_core` version manually from a signed-in user account with `flutter pub publish`. Pub does not currently allow the first version of a new package to be published directly to a verified publisher.
3. Transfer the package from your user account to the `kmmhanan.com` publisher in the package's pub.dev admin page. This transfer is irreversible.
4. Enable GitHub Actions automated publishing from the package's **Admin** page. Use repository `kmmhanan/tflite-core` and tag pattern `v{{version}}`.
5. For later versions, update the package version and changelog, then push a matching version tag. For example, with `version: 0.12.6` in `pubspec.yaml`, push `v0.12.6`.

The GitHub repository and tag pattern are configured on pub.dev; no workflow filename, GitHub secret, pub.dev API key, or GitHub environment is required for this workflow. See the [pub.dev automated publishing guide](https://dart.dev/tools/pub/automated-publishing).

To create a GitHub Release and trigger the publish workflow manually, run **Actions → Create release → Run workflow** on the `main` branch. It reads the version from `pubspec.yaml`, creates and pushes the corresponding `v<version>` tag, then creates a GitHub Release with generated notes. The tag push triggers `publish.yml`.

This workflow uses a repository secret named `RELEASE_TOKEN` so pushing its tag triggers other workflows (GitHub suppresses those triggers when using the default `GITHUB_TOKEN`). Create a fine-grained personal access token scoped to this repository with **Contents: Read and write**, then add it under **Settings → Secrets and variables → Actions**. The token does not authenticate to pub.dev; pub.dev publishing still uses OIDC trusted publishing. Only trusted users should be able to run this release workflow.
113 changes: 113 additions & 0 deletions .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
name: Create Release
run-name: Create Release for v${{ inputs.version }}

on:
workflow_dispatch:
inputs:
version:
description: Package version from pubspec.yaml, without the v prefix
required: true
type: string

permissions:
contents: write

concurrency:
group: create-release
cancel-in-progress: false

jobs:
release:
runs-on: ubuntu-24.04
steps:
- name: Require main branch
if: github.ref != 'refs/heads/main'
run: |
echo "Run this workflow from the main branch."
exit 1

- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
with:
ref: main
token: ${{ secrets.RELEASE_TOKEN }}
fetch-depth: 0

- name: Validate release version
id: version
shell: bash
env:
RELEASE_VERSION: ${{ inputs.version }}
run: |
package_name=$(sed -n 's/^name: *//p' pubspec.yaml | tr -d "\"'")
package_version=$(sed -n 's/^version: *//p' pubspec.yaml | tr -d "\"'")
if [[ "$package_name" != "tflite_core" ]]; then
echo "Expected package name 'tflite_core', got '$package_name'."
exit 1
fi
if [[ ! "$package_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([+-][0-9A-Za-z.-]+)?$ ]]; then
echo "Invalid package version: '$package_version'."
exit 1
fi
if [[ "$RELEASE_VERSION" != "$package_version" ]]; then
echo "Requested version '$RELEASE_VERSION' does not match pubspec.yaml version '$package_version'."
exit 1
fi
version_gt() {
local candidate="${1%%+*}"
local previous="${2%%+*}"
local candidate_prerelease=""
local previous_prerelease=""
if [[ "$candidate" == *-* ]]; then
candidate_prerelease="${candidate#*-}"
candidate="${candidate%%-*}"
fi
if [[ "$previous" == *-* ]]; then
previous_prerelease="${previous#*-}"
previous="${previous%%-*}"
fi
local candidate_major candidate_minor candidate_patch
local previous_major previous_minor previous_patch
IFS=. read -r candidate_major candidate_minor candidate_patch <<< "$candidate"
IFS=. read -r previous_major previous_minor previous_patch <<< "$previous"
if ((10#$candidate_major != 10#$previous_major)); then
((10#$candidate_major > 10#$previous_major))
return
fi
if ((10#$candidate_minor != 10#$previous_minor)); then
((10#$candidate_minor > 10#$previous_minor))
return
fi
if ((10#$candidate_patch != 10#$previous_patch)); then
((10#$candidate_patch > 10#$previous_patch))
return
fi
[[ -n "$previous_prerelease" && -z "$candidate_prerelease" ]]
}
tag="v$package_version"
latest_version=$(git tag --list 'v[0-9]*' --sort=-version:refname | head -n 1 | sed 's/^v//')
if [[ -n "$latest_version" ]]; then
if ! version_gt "$package_version" "$latest_version"; then
echo "Skipping release: '$package_version' is not newer than the latest release '$latest_version'."
echo "release=false" >> "$GITHUB_OUTPUT"
exit 0
fi
fi
echo "release=true" >> "$GITHUB_OUTPUT"
echo "tag=$tag" >> "$GITHUB_OUTPUT"

- name: Create and push version tag
if: steps.version.outputs.release == 'true'
env:
RELEASE_TAG: ${{ steps.version.outputs.tag }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag -a "$RELEASE_TAG" -m "Release $RELEASE_TAG"
git push origin "$RELEASE_TAG"

- name: Create GitHub Release
if: steps.version.outputs.release == 'true'
env:
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
RELEASE_TAG: ${{ steps.version.outputs.tag }}
run: gh release create "$RELEASE_TAG" --verify-tag --title "tflite_core $RELEASE_TAG" --generate-notes
109 changes: 109 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Publish to pub.dev
run-name: ${{ github.ref_name }}

on:
push:
tags:
- 'v*'

permissions:
contents: read
id-token: write

concurrency:
group: publish-${{ github.ref }}
cancel-in-progress: false

jobs:
publish:
runs-on: macos-15
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
with:
fetch-depth: 0

- name: Verify release tag
id: version
shell: bash
run: |
package_version=$(sed -n 's/^version: *//p' pubspec.yaml | tr -d "\"'")
if [[ -z "$package_version" || "$GITHUB_REF_NAME" != "v$package_version" ]]; then
echo "Release tag '$GITHUB_REF_NAME' must match pubspec.yaml version 'v$package_version'."
exit 1
fi
version_gt() {
local candidate="${1%%+*}"
local previous="${2%%+*}"
local candidate_prerelease=""
local previous_prerelease=""
if [[ "$candidate" == *-* ]]; then
candidate_prerelease="${candidate#*-}"
candidate="${candidate%%-*}"
fi
if [[ "$previous" == *-* ]]; then
previous_prerelease="${previous#*-}"
previous="${previous%%-*}"
fi
local candidate_major candidate_minor candidate_patch
local previous_major previous_minor previous_patch
IFS=. read -r candidate_major candidate_minor candidate_patch <<< "$candidate"
IFS=. read -r previous_major previous_minor previous_patch <<< "$previous"
if ((10#$candidate_major != 10#$previous_major)); then
((10#$candidate_major > 10#$previous_major))
return
fi
if ((10#$candidate_minor != 10#$previous_minor)); then
((10#$candidate_minor > 10#$previous_minor))
return
fi
if ((10#$candidate_patch != 10#$previous_patch)); then
((10#$candidate_patch > 10#$previous_patch))
return
fi
[[ -n "$previous_prerelease" && -z "$candidate_prerelease" ]]
}
latest_version=$(git tag --list 'v[0-9]*' --sort=-version:refname | grep -Fxv "$GITHUB_REF_NAME" | head -n 1 | sed 's/^v//')
if [[ -n "$latest_version" ]]; then
if ! version_gt "$package_version" "$latest_version"; then
echo "Skipping publish: '$package_version' is not newer than the latest release '$latest_version'."
echo "publish=false" >> "$GITHUB_OUTPUT"
exit 0
fi
fi
echo "publish=true" >> "$GITHUB_OUTPUT"

- uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa
if: steps.version.outputs.publish == 'true'
with:
channel: stable
cache: true
cache-key: flutter-:os:-:channel:-:version:-:arch:-

- uses: dart-lang/setup-dart@23b5a66dd43e5c8366051dd2dde53e89fa2ef1ea
if: steps.version.outputs.publish == 'true'
with:
problem-matcher: false

- name: Install dependencies
if: steps.version.outputs.publish == 'true'
run: flutter pub get

- name: Verify formatting
if: steps.version.outputs.publish == 'true'
run: dart format --output=none --set-exit-if-changed lib test

- name: Analyze
if: steps.version.outputs.publish == 'true'
run: flutter analyze lib test

- name: Test
if: steps.version.outputs.publish == 'true'
run: flutter test

- name: Validate package
if: steps.version.outputs.publish == 'true'
run: flutter pub publish --dry-run

- name: Publish to pub.dev
if: steps.version.outputs.publish == 'true'
run: flutter pub publish --force
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,28 @@ example/object_detection_ssd_mobilenet/assets/models/ssd_mobilenet.tflite
**/assets/models/!README
**/assets/models/.gitkeep

# Keep checked-in example assets visible to pub's package validation.
!example/audio_classification/assets/models/
!example/image_classification_mobilenet/assets/models/
!example/live_object_detection_ssd_mobilenet/assets/models/
!example/object_detection_ssd_mobilenet/assets/models/
!example/reinforcement_learning/assets/models/
!example/style_transfer/assets/models/
!example/super_resolution_esrgan/assets/models/
!example/text_classification/assets/models/
!example/audio_classification/assets/models/README.md
!example/audio_classification/assets/models/yamnet.tflite
!example/audio_classification/assets/models/yamnet_label_list.txt
!example/image_classification_mobilenet/assets/models/README.md
!example/image_classification_mobilenet/assets/models/labels.txt
!example/image_classification_mobilenet/assets/models/mobilenet_quant.tflite
!example/live_object_detection_ssd_mobilenet/assets/models/README.md
!example/object_detection_ssd_mobilenet/assets/models/README.md
!example/reinforcement_learning/assets/models/README.md
!example/style_transfer/assets/models/README.md
!example/super_resolution_esrgan/assets/models/README.md
!example/text_classification/assets/models/README.md

# FVM Version Cache
.fvm/
.fvmrc
46 changes: 46 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"editor.formatOnSave": false,
"cSpell.words": [
"ARCHS",
"argmax",
"codesign",
"DCMAKE",
"dlsym",
"dyld",
"esrgan",
"ffigen",
"FMWK",
"Garg",
"initialising",
"iphonesimulator",
"jank",
"kewlbear",
"libtensorflowlite",
"lipo",
"logit",
"logits",
"mobilenet",
"NNAPI",
"otool",
"podspec",
"probs",
"pthreadpool",
"pubspec",
"Relu",
"Rfft",
"Rsqrt",
"RTLD",
"Schyler",
"Softmax",
"statefulness",
"Strided",
"Svdf",
"tflite",
"TFLM",
"xcconfig",
"xcframework",
"XCFW",
"XFWK",
"xnnpack"
]
}
36 changes: 35 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
## 0.12.11 (October 16, 2026)
- Restored the standard versioned macOS framework layout, with `Info.plist` under `Versions/A/Resources` as required by Xcode.
- Moved the macOS framework `Info.plist` to the framework root; corrected to the required versioned location in 0.12.13.
- Rebuilt the macOS framework using a flat layout without versioned symlinks.

## 0.12.10 (October 16, 2026)
- Fixed iOS and macOS Swift Package Manager integration by exporting the `tflite-core` product required by Flutter's generated plugin package.

## 0.12.9 (October 16, 2026)
- Expanded public API documentation and added a package example.
- Fixed half-precision float byte decoding and added a regression test.

## 0.12.8 (October 16, 2026)
- Renamed the public Dart entrypoints and platform package files to use the `tflite_core` name.
- Updated example imports, platform package references, and documentation to match the new package name.

## 0.12.7 (October 16, 2026)
- Example references updated.

## 0.12.6 (October 15, 2026)
- Package documentation updated.

## 0.12.5 (October 15, 2026)
- **NEW IDENTITY**: This package converted from "tflite_flutter" to "tflite_core".

## 0.12.4 (July 30, 2026)
- **Critical**: Resolved Flutter Kotlin Gradle Plugin (KGP) deprecated warning.

## 0.12.3 (June 6, 2026)
- **Critical**: Resolved Flutter Kotlin capability issues causing build failures.
- **Critical**: Added full Swift Package Manager (SPM) support for iOS/macOS plugins.
- Verified support for Flutter `3.44.0` across Android and iOS.


## 0.12.1 (October 28, 2025)
* **CRITICAL FIX**: Properly implement Android 16KB page size support
* Migrated from TensorFlow Lite 2.12.0 to Google AI Edge LiteRT 1.4.0
Expand All @@ -23,7 +57,7 @@
* Various bug fixes

## 0.10.0 (May 22, 2023)
* Use ffi for binding to iOS dependencies. Use the ios/tflite_flutter.podspec file to specify tensorflow lite library version. Dependencies are automatically downloaded without user intervention (no need for releases/download folder)
* Use ffi for binding to iOS dependencies. Use the ios/tflite_core.podspec file to specify tensorflow lite library version. Dependencies are automatically downloaded without user intervention (no need for releases/download folder)
* Use ffi for binding with Android dependencies. Use the android/build.gradle file to specify tensorflow lite library version. Dependencies are automatically downloaded without user intervention (no need for releases/download folder)
* Use ffigen to generate the binding code in dart
* Enable delegates in text_classification example
Expand Down
Loading
Loading