使用Android Studo开发NDK之Gradle的配置(能debug C代码)

Posted slgkaifa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Android Studo开发NDK之Gradle的配置(能debug C代码)相关的知识,希望对你有一定的参考价值。

配置:

用的版本号是AS1.5(也能够尝试更高版本号)。 Gradle地址是distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip

NDK用的是CrystaX NDK

有參考:https://github.com/TsinStudio/androidDev/blob/master/Android%20NDK%20C%2B%2B%20开发利器:Android%20Studio.md


常见问题:
1.我在mk的NDK配置和gradle的NDK配置间切换时,突然不能debug进C++代码了。然后通过
清空main/jni/android.mk文件,
点击build->clean,
在debug界面右键tab标题(如 ctbManager Native)->close tab(关闭全部debug的tab)后又能debug进去了,
不知道是哪一步fix了问题。假设遇到编译成功但不能debug C++文件,尝试这几个步骤吧。同一时候不建议mk和gradle配置之间切换。
2.假设C文件报错。考虑能否改动C文件,比解决报错要简单

gradle代码:
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.internal.os.OperatingSystem;


apply plugin: ‘com.android.model.application‘


final APP_ABIS = ["armeabi", "armeabi-v7a","arm64-v8a"]
final BOOST_SHARED_LIBS = ["boost_serialization","boost_system","boost_filesystem","boost_thread"]


model {


    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.2"
        defaultConfig.with {
            applicationId = "com.duotin.ctblib"
            minSdkVersion.apiLevel = 15
            targetSdkVersion.apiLevel = compileSdkVersion.asType(Integer)
            versionCode = 1
            versionName = "1.0"
        }
    }


    android.ndk {
        toolchain = "gcc"
        toolchainVersion = "4.9"
        moduleName = "ctblib"
        cppFlags.add("-std=c++11")
        cppFlags.add("-fexceptions")
        cppFlags.add("-frtti")
        cppFlags.add("-I" + getBoostIncDir())
        cppFlags.addAll(["-fvisibility=hidden", "-Wno-error=format-security",
                         "-I${file("src/main/jni/jnisrc")}".toString(),
                         "-I${file("src/main/jni/src/Jelly")}".toString(),
                         "-I${file("src/main/jni/src/Papaya")}".toString(),
                         "-I${file("src/main/jni/src/Helper")}".toString(),
                         "-I${file("src/main/jni/src/Helper/utf8")}".toString(),
                         "-I${file("src/main/jni/src/CTBModel")}".toString(),
                         "-I${file("src/main/jni/src/CTBModel/CTBAlbum")}".toString(),
                         "-I${file("src/main/jni/src/CTBModel/CTBAlbumParser")}".toString(),
                         "-I${file("src/main/jni/src/CTBModel/CTBBaseModel")}".toString(),
                         "-I${file("src/main/jni/src/CTBModel/CTBTrack")}".toString(),
                         "-I${file("src/main/jni/src/Xml")}".toString(),
                         "-I${file("src/main/jni/src/Xml/XmlModel")}".toString(),
                         "-I${file("src/main/jni/src/Xml/XmlModel/XmlAttrNode")}".toString(),
                         "-I${file("src/main/jni/src/Xml/XmlModel/XmlBaseNode")}".toString(),
                         "-I${file("src/main/jni/src/Xml/XmlModel/XmlElementNode")}".toString(),
                         "-I${file("src/main/jni/src/Xml/XmlModel/XmlTextNode")}".toString(),
                         "-I${file("src/main/jni/src/Xml/XmlUtil")}".toString(),
                         "-I${file("src/main/jni/src/Xml/XmlUtil/BoostXmlUtil")}".toString(),
                         "-I${file("src/main/jni/src/Module")}".toString(),
                         "-I${file("src/main/jni/src/CTBDataManager")}".toString(),
                         "-I${file("src/main/jni/src/Sync/SyncProcess")}".toString(),
                         "-I${file("src/main/jni/src/Sync/Task")}".toString(),
                         "-I${file("src/main/jni/src/SyncLog")}".toString(),
                         "-I${file("src/main/jni/src/Utils")}".toString()]
        )
        cppFlags.add("-I${file("src/main/jni/neon/include")}".toString())
        CFlags.addAll(["-I${file("src/main/jni/jnisrc")}".toString(),
                       "-I${file("src/main/jni/src/Jelly")}".toString(),
                       "-I${file("src/main/jni/src/Papaya")}".toString(),
                       "-I${file("src/main/jni/src/Helper")}".toString(),
                       "-I${file("src/main/jni/src/Helper/utf8")}".toString(),
                       "-I${file("src/main/jni/src/CTBModel")}".toString(),
                       "-I${file("src/main/jni/src/CTBModel/CTBAlbum")}".toString(),
                       "-I${file("src/main/jni/src/CTBModel/CTBAlbumParser")}".toString(),
                       "-I${file("src/main/jni/src/CTBModel/CTBBaseModel")}".toString(),
                       "-I${file("src/main/jni/src/CTBModel/CTBTrack")}".toString(),
                       "-I${file("src/main/jni/src/Xml")}".toString(),
                       "-I${file("src/main/jni/src/Xml/XmlModel")}".toString(),
                       "-I${file("src/main/jni/src/Xml/XmlModel/XmlAttrNode")}".toString(),
                       "-I${file("src/main/jni/src/Xml/XmlModel/XmlBaseNode")}".toString(),
                       "-I${file("src/main/jni/src/Xml/XmlModel/XmlElementNode")}".toString(),
                       "-I${file("src/main/jni/src/Xml/XmlModel/XmlTextNode")}".toString(),
                       "-I${file("src/main/jni/src/Xml/XmlUtil")}".toString(),
                       "-I${file("src/main/jni/src/Xml/XmlUtil/BoostXmlUtil")}".toString(),
                       "-I${file("src/main/jni/src/Module")}".toString(),
                       "-I${file("src/main/jni/src/CTBDataManager")}".toString(),
                       "-I${file("src/main/jni/src/Sync/SyncProcess")}".toString(),
                       "-I${file("src/main/jni/src/Sync/Task")}".toString(),
                       "-I${file("src/main/jni/src/SyncLog")}".toString(),
                       "-I${file("src/main/jni/src/Utils")}".toString(),
                       "-I${file("src/main/jni/neon//external/android")}".toString(),
                       "-I${file("src/main/jni/neon/external/openssl/include/openssl")}".toString(),
                       "-I${file("src/main/jni/neon/external/openssl/include")}".toString(),
                       "-I${file("src/main/jni/neon/external/expat/include")}".toString(),
                       "-I${file("src/main/jni/src/SyncLog")}".toString(),
                       "-I${file("src/main/jni/src/SyncLog")}".toString(),
                       "-I${file("src/main/jni/src/SyncLog")}".toString(),
                       "-I${file("src/main/jni/src/SyncLog")}".toString(),
                       "-I${file("src/main/jni/src/SyncLog")}".toString(),
                       "-I${file("src/main/jni/src/SyncLog")}".toString()])
        CFlags.addAll(["-DDEBUG"])
        ldLibs.addAll BOOST_SHARED_LIBS
        ldLibs.addAll(["log", "m", "z"])
        ldFlags.addAll(["-llog","-fvisibility=hidden","-L/usr/lib ","-lm"])
        stl = "gnustl_shared"
    }


    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles.add(file(‘proguard-rules.pro‘))
        }
    }


    android.sources {
        main {
            jni {
                source {
                    srcDir "src/main/jni"
                    dependencies {
                        APP_ABIS.each { abi ->
                            library file("src/main/jni/neonlib/${abi}/libneon.a") abi "${abi}"
                            library file("src/main/jni/neon/external/expat/${abi}/libexpat.a") abi "${abi}"
                            library file("src/main/jni/openssllib/${abi}/libcrypto.so") abi "${abi}"
                            library file("src/main/jni/openssllib/${abi}/libssl.so") abi "${abi}"
                        }
                    }
                }
            }
            jniLibs {
                source {
                    srcDir "src/main/libs"
                }
            }
        }
    }


    android.productFlavors {
        APP_ABIS.each { abi ->
            create(getFlavorName(abi)) {
                ndk.with {
                    abiFilters.add(abi)
                    getPrebuiltLibPaths(abi).each { path ->
                        ldFlags.add("-L" + path)
                    }
                }
            }
        }
    }
}










tasks.all {


    task ->
            println "printTask#${task}"
        if (task.name.startsWith(‘link‘)) {
            println "${task.name}.startsWith(‘link‘)"
            task.dependsOn copyNativeLibs
        }
}


task copyNativeLibs {
    ["debug", "release"].each { buildType ->
        APP_ABIS.each { abi ->
            def libs = [:]
            BOOST_SHARED_LIBS.each { name ->
                libs[name] = "${getBoostLibDir(abi)}/lib${name}.so"
            }
            libs.crystax = getLibCrystax(abi)


            libs.each { name, file ->
                dependsOn tasks.create(name: "copy-native-library-${name}-${abi}-${buildType}", type: Copy) {
                    from file
                    into getTargetLibDir(abi, buildType)
                }
            }
        }
    }
}


task stripNativeLibs(dependsOn: copyNativeLibs) {
    ["debug", "release"].each { buildType ->
        APP_ABIS.each { abi ->
            def libs = []
            libs.addAll(BOOST_SHARED_LIBS)
            libs += "crystax"


            libs.each { name ->
                dependsOn tasks.create(name: "strip-native-library-${name}-${abi}-${buildType}", type: Exec) {
                    commandLine getStripExecutable(abi), "--strip-unneeded", "${getTargetLibDir(abi, buildType)}/lib${name}.so"
                }
            }


        }
    }
}


dependencies {
    compile fileTree(dir: ‘libs‘, include: [‘*.jar‘])
    compile project(‘:ApiClient‘)
    compile ‘de.greenrobot:eventbus:2.4.0‘
}


def getNdkDir() {
    if (System.env.ANDROID_NDK_ROOT != null)
        return System.env.ANDROID_NDK_ROOT


    Properties properties = new Properties()
    properties.load(project.rootProject.file(‘local.properties‘).newDataInputStream())
    def ndkdir = properties.getProperty(‘ndk.dir‘, null)
    if (ndkdir == null)
        throw new GradleException("""                NDK location not found.
                Define location with ndk.dir in the local.properties file
                or with an ANDROID_NDK_ROOT environment variable.""")


    return ndkdir
}


def getCrystaxNdkDir() {
    def ndkDir = getNdkDir()
    if (!(new File(ndkDir, "sources/crystax").exists()))
        throw new GradleException("""            ‘${ndkDir}‘ is not a CrystaX NDK.
            Edit ndk.dir in local.properties or set ANDROID_NDK_ROOT
            environment variable pointing to CrystaX NDK""")


    return ndkDir
}


def getFlavorName(abi) {
    switch (abi) {
        case "armeabi":
            return "arm";
        case "armeabi-v7a":
            return "arm7"
        case "arm64-v8a":
            return "arm64"
        default:
            return abi.replaceAll(‘-‘, ‘_‘)
    }
}


def getToolchainName(abi) {
    switch (abi) {
        case ~/^armeabi.*/:
            return "arm-linux-androideabi"
        case ~/^arm64.*/:
            return "aarch64-linux-android"
        case "mips":
            return "mipsel-linux-android"
        case "mips64":
            return "mips64el-linux-android"
        case ["x86", "x86_64"]:
            return abi
        default:
            throw new GradleException("Unsupported ABI: ‘${abi}‘")
    }
}


def getToolchainPrefix(abi) {
    switch (abi) {
        case ~/^armeabi.*/:
            return "arm-linux-androideabi"
        case ~/^arm64.*/:
            return "aarch64-linux-android"
        case "mips":
            return "mipsel-linux-android"
        case "mips64":
            return "mips64el-linux-android"
        case "x86":
            return "i686-linux-android"
        case "x86_64":
            return "x86_64-linux-android"
        default:
            throw new GradleException("Unsupported ABI: ‘${abi}‘")
    }
}


def getHostOS() {
    if (OperatingSystem.current().isLinux())
        return "linux"
    if (OperatingSystem.current().isMacOsX())
        return "darwin"
    if (OperatingSystem.current().isWindows())
        return "windows"
    throw new GradleException("Unsupported host OS")
}


def getHostArch() {
    def arch = System.getProperty("os.arch")
    switch (arch) {
        case ["x86_64", "amd64"]:
            return "x86_64"
        case ~/^i[3456]86/:
        case "x86":
            return "x86"
        default:
            throw new GradleException("Can‘t detect host‘s CPU architecture: ‘${arch}‘")
    }
}


def getHostTag() {
    def tag = getHostOS()
    def arch = getHostArch()
    if (tag != "windows" || arch != "x86")
        tag += "-${arch}"
    return tag
}


def getStripExecutable(abi) {
    def ndk = getCrystaxNdkDir()
    def toolchainName = getToolchainName(abi)
    def toolchainPrefix = getToolchainPrefix(abi)
    def hostTag = getHostTag()
    def strip = "${ndk}/toolchains/${toolchainName}-4.9/prebuilt/${hostTag}/bin/${toolchainPrefix}-strip"
    if (OperatingSystem.current().isWindows())
        strip = strip.replaceAll(‘/‘, ‘\\\\‘) + ‘.exe‘
    return strip
}


def getPrebuiltLibPaths(abi) {
    def paths = []
    paths += getBoostLibDir(abi)
    paths += getLibCrystaxDir(abi)
    return paths
}


def getTargetLibDir(abi, buildType) {
    return "${buildDir}/intermediates/binaries/${buildType}/${getFlavorName(abi)}/lib/${abi}"
}


def getLibCrystaxDir(abi) {
    return "${getCrystaxNdkDir()}/sources/crystax/libs/${abi}"
}


def getLibCrystax(abi) {
    return "${getLibCrystaxDir(abi)}/libcrystax.so"
}


def getBoostDir() {
    return "${getCrystaxNdkDir()}/sources/boost/1.58.0"
}


def getBoostIncDir() {
    return "${getBoostDir()}/include"
}


def getBoostLibDir(abi) {
    return "${getBoostDir()}/libs/${abi}"
}

















以上是关于使用Android Studo开发NDK之Gradle的配置(能debug C代码)的主要内容,如果未能解决你的问题,请参考以下文章

我的Android进阶之旅Android开发之NDK相关版本下载链接

我的Android进阶之旅Android开发之NDK相关版本下载链接

Android Studio 之 NDK篇

[Android] 环境配置之Android Studio开发NDK

我的Android进阶之旅NDK开发之C++如何相互转换jstring和char*

我的Android进阶之旅NDK开发之C++如何相互转换jstring和char*