配置:
常见问题:
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代码:
用的版本号是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}" }