Hello,
I'm using the Android Studio with NDK and JNI in a project with a large amount of C++ files. When I make changes in a single C++ file it won't apply in the code unless I rebuild the whole project and refresh the entire C++ files so they have to recompile. The compilation process takes more than 3 minutes for every small change, make it 20 times a day and you have lost an hour.
According to today, after I make a change to a file I go to
Build >> Refresh Linked C++ Projects,
and then run the project, resulting in a full, redundant compilation of all files.
I'm looking for way for the compiler to refresh only the changed file, and as a result shorten the build process.
NOTE: This problem only occurs in windows, when I run Android Studio on a Mac, the compiler recompiles only the relevant files.
This is my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.4.1)
FILE(GLOB CPP_SRC
"src/main/cpp/*.c"
"src/main/cpp/*.h"
"src/main/cpp/*.cpp"
"src/main/cpp/*.hpp"
)
add_library(MyLib
SHARED
${CPP_SRC} )
find_library(
log-lib
log )
target_link_libraries(
MyLib
${log-lib} )
target_link_libraries(MyLib
android
log
EGL
GLESv2)
And my gradle.build file:
apply plugin: 'com.android.library'
android {
signingConfigs {
config {
keyAlias '*****'
keyPassword '*****'
storeFile file(*****)
storePassword '*****'
}
}
compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_STL=c++_shared", "-DCMAKE_BUILD_TYPE=Release", "-DANDROID_CPP_FEATURES=rtti exceptions"
cppFlags "-D__STDC_FORMAT_MACROS", '-Ofast', '-fsigned-char', "-std=c++14", "-frtti", "-fexceptions", "-mtune=arm7", "-mfpu=vfpv3-d16", "-mfloat-abi=softfp", "-Wall",
"-DCOMPILE_EUROPE_ID_AND_FACE_OCR_MANAGER",
"-DCOMPILE_FRENCH_PASSPORT_SIGNATURE",
"-DCOMPILE_FRENCH_ID_BACK_OCR",
"-DCOMPILE_FRENCH_PASSPORT_SIGNATURE_MANAGER",
"-DCOMPILE_PASSPORT_AND_FACE_OCR_MANAGER",
"-DCOMPILE_MRZ_OCR",
"-DCOMPILE_FRENCH_ID_BACK_OCR_MANAGER"
}
ndk {
abiFilters 'x86', 'armeabi-v7a'
}
}
splits {
abi {
enable true
reset()
include 'x86', 'armeabi-v7a'
universalApk true
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
signingConfig signingConfigs.config
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
libraryVariants.all { variant -> variant.outputs.all { output ->
outputFileName = "${"libScanovateImaging"}.aar" }
}
}
allprojects {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
}
dependencies {
implementation 'com.google.android.gms:play-services-vision:15.0.0'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta6'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
}
Thanks in advance!
I think this has been a problem for a long time (judging by the complaints) in Android Studio (more specifically the NDK
build system). Now, in the latest version, it is finally ready and working (hopefully).
Note: gradlew
builds are significantly faster than using the Android Studio IDE
, and can be built using a batch file script (.bat
).
(P1) Android Studio
rebuilds everything every time if multiple ABIs are supported See this SO Q/A.
(C1) Build variants all had the same output directory for the .o files.
(S1) You need to split out the build directory into release/debug and into the different ABIs.
Android Studio 3.1
, NDK release 10
, gradle
version 4.4 (plugin 3.1.0)
I have 2 libraies to build (libhello_world.so
with 1 c++ file, and libjni_photoeditor.so
with 24 c++ files).
I am using externalNativeBuild
-> ndkBuild
to build my native code (you could use CMake
also, I have not tested that).
app level build.gradle
:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
defaultConfig {
applicationId "xxxxxxxxxxxxxxxxxxxxx"
minSdkVersion 16
targetSdkVersion 16
versionCode 1
versionName "1.0"
ndk {
abiFilters 'armeabi-v7a' //,'x86'
}//ndk
}//defaultConfig
buildTypes {
release {
minifyEnabled true
proguardFiles.add(file('proguard-android-optimize.txt'))
proguardFiles.add(file('proguard-rules.pro'))
}//release
debug {
minifyEnabled false
jniDebuggable true
renderscriptDebuggable true
}//debug
}//buildTypes
externalNativeBuild {
// Encapsulates your CMake build configurations.
// cmake {
// // Provides a relative path to your CMake build script.
// path "src/main/cpp/CMakeLists.txt"
// }
ndkBuild {
//****this is the working build****
path 'src/main/cpp/Android.mk'
}//ndkBuild
}//externalNativeBuild
}//android
dependencies {
}//dependencies
Application.mk
:
APP_ABI := armeabi-v7a
APP_PLATFORM := android-19
APP_STL := stlport_static
Android.mk
:
#================================================
LOCAL_PATH := $(call my-dir) #only call it ONCE !
#================================================
include $(CLEAR_VARS)
LOCAL_MODULE := hello_world
LOCAL_MULTILIB := 32
LOCAL_SRC_FILES := hello_world.cpp
include $(BUILD_SHARED_LIBRARY)
#================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libjni_photoeditor
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := libm liblog libjnigraphics
LOCAL_LDLIBS := -lm -llog -ljnigraphics -lbcc
LOCAL_LDLIBS := -lm -llog -ljnigraphics
LOCAL_SRC_FILES := _jni.cpp utils.cpp quantize.cpp #etc.. 24 files
LOCAL_CFLAGS := -Werror \
-I$(OUT)/../../../../frameworks/compile/libbcc/include
LOCAL_LDFLAGS := -L$(OUT)/system/lib
include $(BUILD_SHARED_LIBRARY)
Build -> Build APK(s)
build(A) Modify one of my projects 24 C++
files (quantize.cpp
) and rebuild.
(B) Build -> Build APK(s)
(C) Only the C:\Android\PhotoRend1\app\build\intermediates\ndkBuild\debug\obj\local\armeabi-v7a\objs-debug\jni_photoeditor\quantize.o timestamp changed (and the library).
gradlew
terminal window (command line) buildFrom the project root I use gradlew
in a terminal window
to assemble
my apk
.
(1) Every thing is up-to-date build:
C:\Android\PhotoRend1>gradlew assembleDebug
Starting a Gradle Daemon, 1 busy and 1 incompatible and 1 stopped Daemons could not be reused, use --status for details
> Configure project :app
> Task :app:externalNativeBuildDebug
Build hello_world armeabi-v7a
make.exe: `C:/Android/PhotoRend1/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/libhello_world.so' is up to date.
Build jni_photoeditor armeabi-v7a
make.exe: `C:/Android/PhotoRend1/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/libjni_photoeditor.so' is up to date.
BUILD SUCCESSFUL in 3m 46s
(2) Modify one of my projects 24 C++
files (quantize.cpp) and re-assemble.
(3) One file changes is up-to-date build:
C:\Android\PhotoRend1>gradlew assembleDebug
> Configure project :app
> Task :app:externalNativeBuildDebug
Build hello_world armeabi-v7a
make.exe: `C:/Android/PhotoRend1/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/libhello_world.so' is up to date.
Build jni_photoeditor armeabi-v7a
[armeabi-v7a] Compile++ thumb: jni_photoeditor <= quantize.cpp
[armeabi-v7a] SharedLibrary : libjni_photoeditor.so
BUILD SUCCESSFUL in 59s
(4) As you can see it did an incremental build.
Structure (with abiFilters 'x86', 'armeabi-v7a'
):
C:\Android\PhotoRend1\app\build\intermediates\ndkBuild
|
V
└───debug
└───obj
└───local
├───armeabi-v7a
│ └───objs-debug
│ ├───hello_world
│ └───jni_photoeditor
└───x86
└───objs-debug
├───hello_world
└───jni_photoeditor
Some links:
Manual NDK
updates
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With