xref: /aosp_15_r20/external/fbjni/docs/android_setup.md (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1*65c59e02SInna Palant## Android Build Setup
2*65c59e02SInna Palant
3*65c59e02SInna Palant**These instructions require the Android Gradle Build Plugin 4.0.0 or newer
4*65c59e02SInna Palantas it relies on the new [prefab](https://android-developers.googleblog.com/2020/02/native-dependencies-in-android-studio-40.html) integration.
5*65c59e02SInna PalantCheck below for a pre-4.0.0 workaround.**
6*65c59e02SInna Palant
7*65c59e02SInna Palant```groovy
8*65c59e02SInna Palantrepositories {
9*65c59e02SInna Palant  maven {
10*65c59e02SInna Palant    mavenCentral()
11*65c59e02SInna Palant  }
12*65c59e02SInna Palant}
13*65c59e02SInna Palant
14*65c59e02SInna Palantandroid {
15*65c59e02SInna Palant  dependencies {
16*65c59e02SInna Palant    implementation 'com.facebook.fbjni:fbjni:0.2.2'
17*65c59e02SInna Palant  }
18*65c59e02SInna Palant}
19*65c59e02SInna Palant```
20*65c59e02SInna Palant
21*65c59e02SInna PalantNow, in your CMake setup, you can refer to the `fbjni` package. The header files (e.g. `fbjni.h`)
22*65c59e02SInna Palantwill available implicitly.
23*65c59e02SInna Palant
24*65c59e02SInna Palant```cmake
25*65c59e02SInna Palantset(build_DIR ${CMAKE_SOURCE_DIR}/build)
26*65c59e02SInna Palantset(PACKAGE_NAME "myapp")
27*65c59e02SInna Palant
28*65c59e02SInna Palantfind_package(fbjni REQUIRED CONFIG)
29*65c59e02SInna Palant
30*65c59e02SInna Palanttarget_link_libraries(${PACKAGE_NAME} fbjni::fbjni mylibrary)
31*65c59e02SInna Palant```
32*65c59e02SInna Palant
33*65c59e02SInna Palant## Android Build Setup (pre-4.0.0)
34*65c59e02SInna Palant
35*65c59e02SInna PalantThe Android Gradle plugin does not provide built-in support for artifacts that
36*65c59e02SInna Palantinclude native libraries (for linking against) and header files. Because of
37*65c59e02SInna Palantthat, some manual additions to your build system are required. The following
38*65c59e02SInna Palantis an example of what this can look like but by no means prescriptive.
39*65c59e02SInna Palant
40*65c59e02SInna PalantIn your app-specific `build.gradle`:
41*65c59e02SInna Palant
42*65c59e02SInna Palant```groovy
43*65c59e02SInna Palantrepositories {
44*65c59e02SInna Palant  maven {
45*65c59e02SInna Palant    jcenter()
46*65c59e02SInna Palant  }
47*65c59e02SInna Palant}
48*65c59e02SInna Palant
49*65c59e02SInna Palantandroid {
50*65c59e02SInna Palant  // Create new configurations that can be referred to in dependencies.
51*65c59e02SInna Palant  // The Android Gradle Plugin 3.* does not allow hooking into existing
52*65c59e02SInna Palant  // configurations like `implementation`.
53*65c59e02SInna Palant  configurations {
54*65c59e02SInna Palant    extractHeaders
55*65c59e02SInna Palant    extractJNI
56*65c59e02SInna Palant  }
57*65c59e02SInna Palant
58*65c59e02SInna Palant  dependencies {
59*65c59e02SInna Palant    implementation 'com.facebook.fbjni:fbjni:0.0.1'
60*65c59e02SInna Palant    // If headers are required.
61*65c59e02SInna Palant    extractHeaders 'com.facebook.fbjni:fbjni:0.0.1:headers'
62*65c59e02SInna Palant    // If the `.so` files are required for linking.
63*65c59e02SInna Palant    extractJNI 'com.facebook.fbjni:fbjni:0.0.1'
64*65c59e02SInna Palant  }
65*65c59e02SInna Palant}
66*65c59e02SInna Palant
67*65c59e02SInna Palanttask extractAARHeaders {
68*65c59e02SInna Palant    doLast {
69*65c59e02SInna Palant        configurations.extractHeaders.files.each {
70*65c59e02SInna Palant            def file = it.absoluteFile
71*65c59e02SInna Palant            copy {
72*65c59e02SInna Palant                from zipTree(file)
73*65c59e02SInna Palant                into "$buildDir/$file.name"
74*65c59e02SInna Palant                include "**/*.h"
75*65c59e02SInna Palant            }
76*65c59e02SInna Palant        }
77*65c59e02SInna Palant    }
78*65c59e02SInna Palant}
79*65c59e02SInna Palant
80*65c59e02SInna Palanttask extractJNIFiles {
81*65c59e02SInna Palant    doLast {
82*65c59e02SInna Palant        configurations.extractJNI.files.each {
83*65c59e02SInna Palant            def file = it.absoluteFile
84*65c59e02SInna Palant            copy {
85*65c59e02SInna Palant                from zipTree(file)
86*65c59e02SInna Palant                into "$buildDir/$file.name"
87*65c59e02SInna Palant                include "jni/**/*"
88*65c59e02SInna Palant            }
89*65c59e02SInna Palant        }
90*65c59e02SInna Palant    }
91*65c59e02SInna Palant}
92*65c59e02SInna Palant
93*65c59e02SInna Palanttasks.whenTaskAdded { task ->
94*65c59e02SInna Palant    if (task.name.contains('externalNativeBuild')) {
95*65c59e02SInna Palant        task.dependsOn(extractAARHeaders)
96*65c59e02SInna Palant        task.dependsOn(extractJNIFiles)
97*65c59e02SInna Palant    }
98*65c59e02SInna Palant}
99*65c59e02SInna Palant```
100*65c59e02SInna Palant
101*65c59e02SInna PalantWith this setup in place, prior to any native build jobs, the header files
102*65c59e02SInna Palantand JNI shared libraries will be extracted under the build directory.
103*65c59e02SInna Palant
104*65c59e02SInna PalantNow, in your CMake setup, you can refer to the extracted paths:
105*65c59e02SInna Palant
106*65c59e02SInna Palant```cmake
107*65c59e02SInna Palantset(build_DIR ${CMAKE_SOURCE_DIR}/build)
108*65c59e02SInna Palantset(PACKAGE_NAME "myapp")
109*65c59e02SInna Palant
110*65c59e02SInna Palantfile(GLOB libfbjni_link_DIRS "${build_DIR}/fbjni*.aar/jni/${ANDROID_ABI}")
111*65c59e02SInna Palantfile(GLOB libfbjni_include_DIRS "${build_DIR}/fbjni-*-headers.jar/")
112*65c59e02SInna Palant
113*65c59e02SInna Palantfind_library(FBJNI_LIBRARY fbjni PATHS ${libfbjni_link_DIRS}
114*65c59e02SInna PalantNO_CMAKE_FIND_ROOT_PATH)
115*65c59e02SInna Palant
116*65c59e02SInna Palanttarget_include_directories(${PACKAGE_NAME} PRIVATE
117*65c59e02SInna Palant  // Additional header directories here
118*65c59e02SInna Palant  ${libfbjni_include_DIRS}
119*65c59e02SInna Palant)
120*65c59e02SInna Palanttarget_link_libraries(${PACKAGE_NAME} ${FBJNI_LIBRARY} mylibrary)
121*65c59e02SInna Palant```
122