Skip to content

Commit

Permalink
feat: config plugin for android gpu libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
TkTioNG committed Nov 20, 2024
1 parent 284a5ef commit 685eaf9
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 1 deletion.
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) {
existingMetaDataItem = mainApplication['uses-native-library'].filter(
(e) => e.$['android:name'] === item.name
)
if (existingMetaDataItem.length > 0 && existingMetaDataItem[0] != null)
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

0 comments on commit 685eaf9

Please sign in to comment.