Android的工作室14原生开发+ CrystaX NDK [英] Android Studio 14 Native Development + CrystaX NDK
问题描述
我想我使用CrystaX NDK的提升和C ++ 14一个巨大的跨平台的C ++ 11(IOS +安卓)应用程序项目迁移到Android的工作室14。有在其网站上的博客的官方Android工作室+ CrystaX教程这里但它是过时的。
I am trying to migrate a huge crossplatform C++11 (iOS+Android) app project into Android Studio 14. I am using CrystaX NDK for boost and C++14. There's an official Android Studio + CrystaX tutorial on their website's blog here but it's outdated.
我下载的是为了与Android 1.4工作室工作,并试图去适应它CrystaX NDK工作正式HELLO-JNI的例子。这是我的摇篮2.5设置:
I've downloaded the official hello-jni example that is meant to work with Android Studio 1.4 and tried to adapt it to work with CrystaX NDK. These are my Gradle 2.5 settings:
项目build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.2.0'
}
}
allprojects {
repositories {
jcenter()
}
}
模块build.gradle
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.1"
defaultConfig.with {
applicationId = "com.tableair.app"
minSdkVersion.apiLevel = 4
targetSdkVersion.apiLevel = 23
}
}
compileOptions.with {
sourceCompatibility=JavaVersion.VERSION_1_7
targetCompatibility=JavaVersion.VERSION_1_7
}
/*
* native build settings
*/
android.ndk {
moduleName = "tableair-framework"
cppFlags += "-std=c++11"
cppFlags += "-Werror"
ldLibs = ["android", "log", "GLESv2", "crystax"]
stl = "gnustl_static"
/*
* Other ndk flags configurable here are
* cppFlags += "-fno-rtti"
* cppFlags += "-fno-exceptions"
* ldLibs = ["android", "log"]
* stl = "system"
*/
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles += file('proguard-rules.txt')
}
}
android.productFlavors {
// for detailed abiFilter descriptions, refer to "Supported ABIs" @
// https://developer.android.com/ndk/guides/abis.html#sa
create("arm") {
ndk.abiFilters += "armeabi"
}
create("arm7") {
ndk.abiFilters += "armeabi-v7a"
}
create("arm8") {
ndk.abiFilters += "arm64-v8a"
}
create("x86") {
ndk.abiFilters += "x86"
}
create("x86-64") {
ndk.abiFilters += "x86_64"
}
create("mips") {
ndk.abiFilters += "mips"
}
create("mips-64") {
ndk.abiFilters += "mips64"
}
// To include all cpu architectures, leaves abiFilters empty
create("all")
}
}
local.properties
ndk.dir=/Users/vilius/Software/Android/crystax-ndk-10.2.1
sdk.dir=/Users/vilius/Library/Android/sdk
当我尝试运行应用程序。我得到这个错误:
When I try to run the app. I get this error:
....
:app:generateAllDebugAndroidTestSources UP-TO-DATE
:app:copyArm64-v8aDebugAllTableair-frameworkSharedLibraryGdbServer UP-TO-DATE
:app:createArm64-v8aDebugAllTableair-frameworkSharedLibraryGdbsetup
:app:compileArm64-v8aDebugAllTableair-frameworkSharedLibraryTableair-frameworkMainC UP-TO-DATE
:app:linkArm64-v8aDebugAllTableair-frameworkSharedLibrary
/Users/vilius/Software/Android/crystax-ndk-10.2.1/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/bin/ld: cannot find -lcrystax
/Users/vilius/Software/Android/crystax-ndk-10.2.1/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/bin/ld: cannot find -lcrystax
Error:error: ld returned 1 exit status
Error:Execution failed for task ':app:linkArm64-v8aDebugAllTableair-frameworkSharedLibrary'.
> A build operation failed.
Linker failed while linking libtableair-framework.so.
See the complete log at: file:///Users/vilius/TableAir/Mobile/app/android-studio-project/app/build/tmp/linkArm64-v8aDebugAllTableair-frameworkSharedLibrary/output.txt
在... / output.txt的是在消息窗口中显示完全相同的信息。
The .../output.txt displays exactly the same information as in the message window.
有没有人有想法关于这个问题?
Does anyone have ideas about this problem?
推荐答案
是的,例如这里一>是有点过时,所以我们计划很快发布新文章,对如何使用CrystaX NDK新的实验摇篮插件更新后的描述。在此期间,你可以看一下例如我推到github上。这个例子中最有趣的部分是应用程序的build.gradle,所以我在这里复制的方便:
Yes, example here is bit outdated, so we plan to publish new article soon, with updated description of how to use CrystaX NDK with new experimental Gradle plugin. In the meantime, you can look on example I've pushed to github. The most interesting part of that example is app's build.gradle, so I copy it here for convenience:
import org.gradle.internal.os.OperatingSystem;
apply plugin: 'com.android.model.application'
final APP_ABIS = ["armeabi", "armeabi-v7a", "x86"]
final BOOST_SHARED_LIBS = ["boost_serialization"]
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.1"
defaultConfig.with {
applicationId = "net.crystax.testboost2"
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = compileSdkVersion.asType(Integer)
versionCode = 1
versionName = "1.0"
}
}
compileOptions.with {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
android.ndk {
moduleName = "test-boost2"
cppFlags += "-std=c++11"
cppFlags += "-fexceptions"
cppFlags += "-frtti"
cppFlags += "-Werror"
cppFlags += "-I" + getBoostIncDir()
ldLibs.addAll BOOST_SHARED_LIBS
ldLibs += "log"
stl = "gnustl_shared"
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles += file('proguard-rules.pro')
}
}
android.productFlavors {
APP_ABIS.each { abi ->
create(getFlavorName(abi)) {
ndk.with {
abiFilters += abi
getPrebuiltLibPaths(abi).each { path ->
ldFlags += "-L" + path
}
}
}
}
}
}
tasks.all {
task ->
if (task.name.startsWith('link')) {
task.dependsOn copyNativeLibs, stripNativeLibs
}
}
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 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:design:23.0.1'
}
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 1.4工作室和摇篮实验插件0.2.0进行了测试。
I've tested it with Android Studio 1.4 and gradle experimental plugin 0.2.0.
事实上,自 copyNativeLibs
任务只需要对包括共享库的apk;如果你使用静态库链接, copyNativeLibs
是没有必要的。
In fact, custom copyNativeLibs
task needed only for including shared libraries into apk; if you link with static libraries, copyNativeLibs
is not needed at all.
更新:我添加 stripNativeLibs
任务,只是因为我已经意识到,APK得到了包括调试信息剥开库,使得它的大小过大没有在任何实际需要。
UPDATE: I've added stripNativeLibs
task just because I've realized that APK got included unstripped libraries with debug information, making its size too big without any real need in that.
这篇关于Android的工作室14原生开发+ CrystaX NDK的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!