Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: config plugin for android gpu libraries #109

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,45 @@ If you are on bare React Native, you need to include the CoreML/Metal code in yo

#### Android GPU/NNAPI (Android)

To enable GPU or NNAPI delegate in Android, you **may** need to include `OpenCL` library with `uses-native-library` on `application` scope in AndroidManifest.xml, starting from Android 12.
To enable GPU or NNAPI delegate in Android, you **may** need to include some native libraries, starting from Android 12.

##### Expo

For Expo, just use the config plugin in your expo config (`app.json`, `app.config.json` or `app.config.js`) with `enableAndroidGpuLibraries`:

```json
{
"name": "my app",
"plugins": [
[
"react-native-fast-tflite",
{
"enableAndroidGpuLibraries": true
}
]
]
}
```

By default, when enabled, `libOpenCl.so` will be included in your AndroidManifest.xml. You can also include more libraries by passing an array of string:

```json
{
"name": "my app",
"plugins": [
[
"react-native-fast-tflite",
{
"enableAndroidGpuLibraries": ["libOpenCL-pixel.so", "libGLES_mali.so"]
}
]
]
}
```

##### Bare React Native

If you are on bare React Native, you will need to include all needed libraries with `uses-native-library` on `application` scope in AndroidManifest.xml.

```xml
<!-- Like this -->
Expand Down
27 changes: 27 additions & 0 deletions src/expo-plugin/@types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,31 @@ export type ConfigProps = {
* @default false
*/
enableCoreMLDelegate?: boolean
/**
* Whether to enable the GPU acceleration delegate for GPU, by including related native libraries.
* You can leave it as boolean for an array of native libraries.
*
* If enabled, "libOpenCL.so" will always be included.
*
* When ran prebuild, it will yield following result.
*
* ```xml
* <uses-native-library android:name="libOpenCL.so" android:required="false"/>
* ```
*
* @example
* You can include more native libraries if needed.
* ```json
* [
* "react-native-fast-tflite",
* {
* "enableAndroidGpuLibraries": ["libOpenCL-pixel.so", "libGLES_mali.so"]
* }
* ]
* ```
*
*
* @default false
*/
enableAndroidGpuLibraries?: boolean | string[]
} | void
54 changes: 54 additions & 0 deletions src/expo-plugin/withAndroidGpuLibraries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
ConfigPlugin,
AndroidConfig,
withAndroidManifest,
} from '@expo/config-plugins'
import {
ManifestApplication,
prefixAndroidKeys,
} from '@expo/config-plugins/build/android/Manifest'

function addUsesNativeLibraryItemToMainApplication(
mainApplication: AndroidConfig.Manifest.ManifestApplication & {
'uses-native-library'?: AndroidConfig.Manifest.ManifestUsesLibrary[]
},
item: { name: string; required?: boolean }
): ManifestApplication {
let existingMetaDataItem
const newItem = {
$: prefixAndroidKeys(item),
} as AndroidConfig.Manifest.ManifestUsesLibrary

if (mainApplication['uses-native-library'] != null) {
TkTioNG marked this conversation as resolved.
Show resolved Hide resolved
existingMetaDataItem = mainApplication['uses-native-library'].filter(
(e) => e.$['android:name'] === item.name
)
if (existingMetaDataItem.length > 0 && existingMetaDataItem[0] != null)
TkTioNG marked this conversation as resolved.
Show resolved Hide resolved
existingMetaDataItem[0].$ = newItem.$
else mainApplication['uses-native-library'].push(newItem)
} else {
mainApplication['uses-native-library'] = [newItem]
}
return mainApplication
}

export const withAndroidGpuLibraries: ConfigPlugin<boolean | string[]> = (
cfg,
enabledLibraries
) =>
withAndroidManifest(cfg, (config) => {
const mainApplication = AndroidConfig.Manifest.getMainApplicationOrThrow(
config.modResults
)
const gpuLibraries = [{ name: 'libOpenCL.so', required: false }]

if (Array.isArray(enabledLibraries)) {
gpuLibraries.push(
...enabledLibraries.map((lib) => ({ name: lib, required: false }))
)
}
gpuLibraries.forEach((lib) => {
addUsesNativeLibraryItemToMainApplication(mainApplication, lib)
})
return config
})
6 changes: 6 additions & 0 deletions src/expo-plugin/withFastTFLite.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { ConfigPlugin, createRunOncePlugin } from '@expo/config-plugins'
import { ConfigProps } from './@types'
import { withCoreMLDelegate } from './withCoreMLDelegate'
import { withAndroidGpuLibraries } from './withAndroidGpuLibraries'
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires
const pkg = require('../../../package.json') // from the lib directory, the package.json is three levels up

const withFastTFLite: ConfigPlugin<ConfigProps> = (config, props) => {
if (props?.enableCoreMLDelegate) config = withCoreMLDelegate(config)
if (
props?.enableAndroidGpuLibraries === true ||
Array.isArray(props?.enableAndroidGpuLibraries)
)
config = withAndroidGpuLibraries(config, props.enableAndroidGpuLibraries)

return config
}
Expand Down
Loading