简体   繁体   English

如何防止C ++重新编译Android NDK中的所有文件?

[英]How to prevent from C++ to recompile all files in Android NDK?

Hello, 你好,

I'm using the Android Studio with NDK and JNI in a project with a large amount of C++ files. 我在带有大量C ++文件的项目中使用带有NDK和JNI的Android Studio。 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. 当我在单个C ++文件中进行更改时, 除非重新构建整个项目并刷新整个C ++文件, 否则它们将不会应用在代码中,因此必须重新编译它们。 The compilation process takes more than 3 minutes for every small change, make it 20 times a day and you have lost an hour. 每次小的更改,编译过程都会花费3分钟以上的时间,每天进行20次,而您却损失了一个小时。

According to today, after I make a change to a file I go to 根据今天,在我更改文件后,我转到

Build >> Refresh Linked C++ Projects, 构建>>刷新链接的C ++项目,

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. 注意:此问题仅出现在Windows中,当我在Mac上运行Android Studio时,编译器仅重新编译相关文件。

This is my CMakeLists.txt file: 这是我的CMakeLists.txt文件:

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: 和我的gradle.build文件:

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! 提前致谢!

Introduction 介绍

I think this has been a problem for a long time (judging by the complaints) in Android Studio (more specifically the NDK build system). 我认为这在Android Studio(更具体而言是NDK构建系统)中已经存在很长时间了 (根据投诉来判断)。 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 ). 注意: gradlew构建要比使用Android Studio IDE快得多,并且可以使用批处理文件脚本( .bat )构建。

CMake possible problems(P = problem, C = cause, S = solution) CMake可能的问题(P =问题,C =原因,S =解决方案)

(P1) Android Studio rebuilds everything every time if multiple ABIs are supported See this SO Q/A . (P1)如果支持多个ABI, Android Studio每次都会重新构建所有内容。请参阅此SO Q / A。
(C1) Build variants all had the same output directory for the .o files. (C1)构建变体的.o文件都具有相同的输出目录。
(S1) You need to split out the build directory into release/debug and into the different ABIs. (S1)您需要将构建目录拆分为release / debug和不同的ABI。

My Setup (ndkBuild) 我的设置(ndkBuild)

Android Studio 3.1 , NDK release 10 , gradle version 4.4 (plugin 3.1.0) Android Studio 3.1NDK release 10gradle版本4.4(插件3.1.0)

I have 2 libraies to build ( libhello_world.so with 1 c++ file, and libjni_photoeditor.so with 24 c++ files). 我有2个libraies构建( libhello_world.so用1个C ++文件,和libjni_photoeditor.so 24个C ++文件)。

I am using externalNativeBuild -> ndkBuild to build my native code (you could use CMake also, I have not tested that). 我正在使用externalNativeBuild > ndkBuild构建我的本机代码(您也可以使用CMake ,但我尚未对此进行测试)。

app level build.gradle : 应用程序级别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 : Application.mk

APP_ABI := armeabi-v7a
APP_PLATFORM := android-19
APP_STL := stlport_static

Android.mk : 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)

Test 1. Android Studio Build -> Build APK(s) build 测试1. Android Studio Build -> Build APK(s) build

(A) Modify one of my projects 24 C++ files ( quantize.cpp ) and rebuild. (A) 修改我的项目之一的24个C++文件( quantize.cpp )并重建。

(B) Build -> Build APK(s) (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). (C)仅更改了C:\\ Android \\ PhotoRend1 \\ app \\ build \\ intermediates \\ ndkBuild \\ debug \\ obj \\ local \\ armeabi-v7a \\ objs-debug \\ jni_photoeditor \\ quantize.o时间戳(和库)。

Test 2. gradlew terminal window (command line) build 测试2. gradlew终端窗口(命令行)构建

From the project root I use gradlew in a terminal window to assemble my apk . 从项目根目录,我在terminal window使用gradlew assemble我的apk

(1) Every thing is up-to-date build: (1)每件事都是最新的版本:

C:\\Android\\PhotoRend1>gradlew assembleDebug 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. (2) 修改我的项目之一24个C++文件(quantize.cpp)并重新组装。

(3) One file changes is up-to-date build: (3)一个文件更改是最新版本:

C:\\Android\\PhotoRend1>gradlew assembleDebug 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. (4)如您所见,它进行了增量构建。

Structure (with abiFilters 'x86', 'armeabi-v7a' ): 结构(使用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 一些链接: 手动NDK更新

Finally I have found the cause to the problem. 最后,我找到了问题的原因。

In my project I have worked with symlink C++ files. 在我的项目中,我使用了symlink C ++文件。 The NDK cannot immediately apply the changes made in these files and they won't be expressed in your app unless you rebuild the whole project. NDK无法立即应用对这些文件所做的更改,除非您重建整个项目,否则它们不会在您的应用程序中表示出来。

The solution is to work with hard copy files. 解决方案是使用硬拷贝文件。

If I find some way to work correctly with symlink files it would be better for my needs. 如果我找到一些正确使用symlink文件的方法,则对我的需求会更好。 Until then I can at least edit single or multiple files without recompiling the whole project. 在此之前,我至少可以编辑一个或多个文件,而无需重新编译整个项目。

This is a relatively esoteric situation but might be helpful for someone in the future. 这是一个相对深奥的情况,但将来可能对某人有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM