【问题标题】:define LOCAL_SRC_FILES in ndk{} DSL在 ndk{} DSL 中定义 LOCAL_SRC_FILES
【发布时间】:2015-12-14 15:59:33
【问题描述】:

我想知道是否可以在 gradle.build ndk {} 块中定义 LOCAL_SRC_FILES。

我目前正在使用:

dependencies {
    classpath 'com.android.tools.build:gradle:1.3.0'
}

在我的顶级 gradle.build 文件中。

我的 jni 模块 gradle.build 文件如下所示:

apply plugin: 'com.android.library'

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
}

android {
    compileSdkVersion 11
    buildToolsVersion "22.0.1"

    def jniSrc = System.getProperty("user.home") + "/srcs/jni"

    defaultConfig {
        ndk {
            moduleName "core"
            stl "gnustl_shared"
            cFlags "-std=c++11"
        }
    }

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
            jni.srcDirs = ["${jniSrc}"]
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            jniDebuggable true
        }
    }

    productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }
        }
        arm {
            ndk {
                abiFilter "armeabi-v7a"
            }
        }
        mips {
            ndk {
                abiFilter "mips"
            }
        }
    }
}

我问的原因是在我的 jni 源下有针对不同平台的代码,不仅是 Android,还有 iOS 和 WinRT。

我有点不愿意迁移到实验性“com.android.tools.build:gradle-experimental:0.2.0”,但如果上述模块解决了问题,我可以试一试。

我也不想用:

jni.srcDirs = []

并覆盖 Android.mk 的创建,从而使用我自己的自定义的,因为我不确定我是否可以在此后从 Android Studio 本地调试 C++(虽然我在这里可能错了,我绝对不是专家用户Android Studios ndk 插件)。

非常感谢,

马诺斯

【问题讨论】:

    标签: android c++ android-ndk android-gradle-plugin


    【解决方案1】:

    使用实验性插件 0.4.0,可以通过模式从 NDK 构建中排除文件,例如

    android.sources {
        main {
           jni.source {
                srcDirs = ["~/srcs/jni"]
                exclude "**/win.cpp"
            }
        }
    }
    

    感谢Paul Spark

    P.S.(感谢rajveer):更改exclude后不要错过Build/Clean

    旧答案

    很遗憾,当前的 gradle 插件不支持此功能。甚至 "experimental" 插件也只允许添加目录。我建议保留可靠地完成这项工作的传统 Android.mk

    我还建议不要设置jni.srcDirs = [],而是保留${jniSrc},让Android Studio 显示这些文件以便于访问和语法高亮。如果您正确设置了cppFlagscFlags,您也将拥有通过标头交叉引用的全部功能。

    诀窍是禁用常规 NDK 构建任务,并改为注入 buildNative 任务:

    def ndkBuild = android.ndkDirectory
    import org.apache.tools.ant.taskdefs.condition.Os
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        ndkBuild += '.cmd'
    }
    
    task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
        commandLine '$ndkBuild', 'NDK_PROJECT_PATH="$jniSrc/..'
    }
    
    task cleanNative(type: Exec, description: 'Clean JNI object files') {
        commandLine '$ndkBuild', 'clean', 'NDK_PROJECT_PATH="$jniSrc/..'
    }
    
    clean.dependsOn 'cleanNative'
    
    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn buildNative
    }
    
    tasks.all {
        task -> if (task.name.contains('compileDebugNdk') || task.name.contains('compileReleaseNdk')) task.enabled = false
    }
    

    类似的方法适用于 'com.android.tools.build:gradle-experimental:0.2.0',但任务匹配不同:

    tasks.all {
        task ->
            if (task.name.startsWith('compile') && task.name.contains('MainC')) {
                task.enabled = false
            }
            if (task.name.startsWith('link')) {
                task.enabled = false
            }
            if (task.name.endsWith("SharedLibrary") ) {
                task.dependsOn buildNative
            }
    }
    

    更新

    buildNative 不会产生可调试的设置。具体来说,在运行 Android Native 调试配置时,Android Studio 会抱怨它在模块 app 中找不到包含带有符号的目标文件的文件夹

    我建议以下解决方法,我仅在本机源被拆分为(至少)两个目录的情况下进行测试:Android 特定文件(我将它们称为 JNI 桥)是在一个单独的目录中,其余的在其他地方。解决方法是使用 ndk-build 构建一个静态库,并将其与最小的对象集链接,这些对象将从该库中提取所有必要的符号。

    为简单起见,让我们假设特定于 Android 的文件(Application.mkAndroid.mk 和“android-jni.cpp”位于目录中~/srcs/jni,而与平台无关的文件位于~/srcs及其其他子目录中。

    这里是build.gradle的相关片段:

    def LOCAL_MODULE = "staticLib"
    def appAbi = "armeabi-v7a"
    def ndkOut = "build/intermediates/$LOCAL_MODULE"
    def staticLibPath = "$ndkOut/local/$appAbi/lib${LOCAL_MODULE}.a"
    task buildStaticLib(type: Exec, description: 'Compile Static lib via NDK') {
        commandLine "$ndkBuild", "$staticLibPath", "NDK_PROJECT_PATH=~/srcs", "NDK_OUT=$ndkOut", "APP_ABI=$appAbi", "APP_STL=gnustl_static"
    }
    
    tasks.all {
        task ->
            if (task.name.startsWith('link')) {
                task.dependsOn buildStaticLib
            }
    }
    
    model {
        android.ndk {
            moduleName = "hello-jni"
            abiFilters += "$appAbi".toString()
            ldFlags += "$staticLib".toString()
            ldLibs += "log"
            cppFlags += "-std=c++11"
        }
    
        android.sources {
            main.jni.source {
                srcDirs = ["~/srcs/jni"]
            }
    }
    }
    

    ~/srcs/Android.mk 文件可能如下所示:

    LOCAL_PATH := $(call my-dir)/..
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := staticLib
    LOCAL_SRC_FILES := HelloJni.cpp
    
    LOCAL_CPPFLAGS += -std=c++11
    
    include $(BUILD_STATIC_LIBRARY)
    

    Android.mk 中的 LOCAL_MODULE 必须适合您在 build 中用于 LOCAL_MODULE 的名称.gradle.

    更新 2

    感谢jforce,它仍然是可能的,请参阅“Link individual native source file to Android Studio project”!

    【讨论】:

    • 嗨,Alex,非常感谢您的回复。如果我使用这种方法,我是否能够从 Android Studio 调试 C++?
    • 不幸的是,这种简单的方法无法启动本机调试(符号信息不可用)。但是只要再复杂一步,就可以实现原生调试。一旦我有一个干净的设置,我会发布更新。
    • @Pankaj:小心 DSL:当我尝试编写 model.android.sources {…} 而不是 model { 时收到消息 could not find property "android" android.sources {…} }
    • @Rajveer:它对我来说就像魅力一样。现在,也许你错过了 works like charm 的要点:AS 仍然显示并让我编辑排除的文件,但不会将其编译为 app/build/intermediates/objectFiles/armeabi-v7aDebugArm7Native-activitySharedLibrary/native-activityMainCpp/dw4leoehkvku3fcud7ljazweo。此外,如果source_file_1.o 从先前的构建中卡在那里,则链接器将失败。 构建/清理项目可以解决这个问题。
    • 这很奇怪。你真的和其他一些人相信在 Android Studio Clean and Rebuild are synonyms
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    相关资源
    最近更新 更多