当前位置: 动力学知识库 > 问答 > 编程问答 >

c++ - Debug Mapbox Android NDK library

问题描述:

I am attempting to follow the Android Studio Experimental Plugin User Guide instructions located at:

http://tools.android.com/tech-docs/new-build-system/gradle-experimental

to modify the Mapbox GL Native library located at:

https://github.com/mapbox/mapbox-gl-native

In specific, I have modified the following Android files:

https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/gradle/wrapper/gradle-wrapper.properties

https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/build.gradle

https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/MapboxGLAndroidSDK/build.gradle

https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/MapboxGLAndroidSDKTestApp/build.gradle

My goal is to modify the library so I can debug it. Ideally I would be able to use Android Studio to build the library and debug the C/C++ code. So far I can build it, but I can't debug it. A programmer working at Mapbox told me they don't how to debug the Android code either, so I suspect this isn't an easy goal to reach.

I have made many different attempts to apply the Android Studio Experimental Plugin User Guide instructions, but I'm not experienced at Gradle and my latest attempt is leaving me with the following error message which I don't understand:

Gradle 'android' project refresh failed

Error:Cause:org.gradle.api.internal.ExtensibleDynamicObject

Does anyone know how to modify these files to have them build a debuggable Android NDK Library? What is causing the above error?

I am using:

> Linux Mint 17.2

> Android Studio 2.1.1

> Build #AI-143.2821654, built on April 28, 2016

> JRE: 1.8.0_65-b17 amd64

> JVM: Java HotSpot(TM) 64-Bit Server VM by Oracle Corporation

Below are the 4 files as I currently have them modified. Since I am new to Gradle, do not assume I have made any modfications correctly. I was merely attempting to apply the Android Studio Experimental Plugin User Guide instructions until I got a successful build.

Thanks


#// mapbox-gl-native/platform/android/gradle/wrapper/gradle-wrapper.properties

#Thu Apr 07 14:21:05 CDT 2016

distributionBase=GRADLE_USER_HOME

distributionPath=wrapper/dists

zipStoreBase=GRADLE_USER_HOME

zipStorePath=wrapper/dists

#//distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip

#//distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip

distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-all.zip

distributionSha256Sum=e77064981906cd0476ff1e0de3e6fef747bd18e140960f1915cca8ff6c33ab5c


// mapbox-gl-native/platform/android/MapboxGLAndroidSDKTestApp/build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {

repositories {

jcenter()

maven { url 'https://jitpack.io' }

}

dependencies {

// classpath 'com.android.tools.build:gradle:2.1.0'

//classpath 'com.android.tools.build:gradle-experimental:0.7.0'

classpath 'com.android.tools.build:gradle-experimental:0.8.0-alpha2'

classpath 'com.github.JakeWharton:sdk-manager-plugin:220bf7a88a7072df3ed16dc8466fb144f2817070'

// NOTE: Do not place your application dependencies here; they belong

// in the individual module build.gradle files

}

}

allprojects {

repositories {

jcenter()

maven { url "http://oss.sonatype.org/content/repositories/snapshots/" }

}

}

task wrapper(type: Wrapper) {

gradleVersion = '2.12'

}


// mapbox-gl-native/platform/android/MapboxGLAndroidSDK/build.gradle

apply plugin: 'android-sdk-manager'

apply plugin: 'com.android.model.library'

apply plugin: 'checkstyle'

apply plugin: 'maven'

apply plugin: 'signing'

allprojects {

group project.GROUP

version project.VERSION_NAME

repositories {

mavenCentral()

}

}

repositories {

mavenCentral()

}

ext {

supportLibVersion = '23.4.0'

}

dependencies {

compile "com.android.support:support-annotations:${supportLibVersion}"

compile "com.android.support:support-v4:${supportLibVersion}"

compile "com.android.support:design:${supportLibVersion}"

compile 'com.squareup.okhttp3:okhttp:3.3.0'

compile 'com.mapzen.android:lost:1.1.0'

}

model {

android {

compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)

buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION

defaultConfig {

minSdkVersion Integer.parseInt(project.ANDROID_MIN_SDK)

targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)

}

sourceSets {

main.res.srcDirs += 'src/main/res-public'

}

repositories {

mavenCentral()

}

compileOptions {

sourceCompatibility JavaVersion.VERSION_1_7

targetCompatibility JavaVersion.VERSION_1_7

}

lintOptions {

checkAllWarnings true

warningsAsErrors true

}

buildTypes {

debug {

jniDebuggable true

buildConfigField "String", "MAPBOX_EVENTS_USER_AGENT_BASE", new StringBuilder().append("\"").append("MapboxEventsAndroid/").append(project.VERSION_NAME).append("\"").toString()

}

release {

jniDebuggable false

buildConfigField "String", "MAPBOX_EVENTS_USER_AGENT_BASE", new StringBuilder().append("\"").append("MapboxEventsAndroid/").append(project.VERSION_NAME).append("\"").toString()

consumerProguardFiles 'proguard-rules.pro'

}

}

}

}

configurations {

all*.exclude group: 'commons-logging', module: 'commons-logging'

all*.exclude group: 'commons-collections', module: 'commons-collections'

}

model {

android.libraryVariants.all { variant ->

def name = variant.name

task "javadoc$name"(type: Javadoc) {

description = "Generates javadoc for build $name"

failOnError = false

destinationDir = new File(destinationDir, variant.baseName)

source = files(variant.javaCompile.source)

classpath = files(variant.javaCompile.classpath.files) + files(android.bootClasspath)

exclude '**/R.java', '**/BuildConfig.java', 'com/almeros/**'

options.windowTitle("Mapbox Android SDK $VERSION_NAME Reference")

options.docTitle("Mapbox Android SDK $VERSION_NAME")

options.header("Mapbox Android SDK $VERSION_NAME Reference")

options.bottom("© 2015–2016 Mapbox. All rights reserved.")

options.links("http://docs.oracle.com/javase/7/docs/api/")

options.linksOffline("http://d.android.com/reference/", "$System.env.ANDROID_HOME/docs/reference")

options.overview("src/main/java/overview.html")

options.group("Mapbox Android SDK", "com.mapbox.*")

options.group("Third Party Libraries", "com.almeros.*")

// TODO exclude generated R, BuildConfig, com.almeros.*

}

}

}

checkstyle {

configFile project.file('../checks.xml')

showViolations true

}

/*

task cleanJNIBuilds {

def jniLibsDir = new File("MapboxGLAndroidSDK/src/main/jniLibs")

delete jniLibsDir.absolutePath

}

*/

model

{

android.libraryVariants.all { variant ->

def name = variant.buildType.name

def checkstyle = project.tasks.create "checkstyle${name.capitalize()}", Checkstyle

checkstyle.dependsOn variant.javaCompile

checkstyle.source variant.javaCompile.source

checkstyle.classpath = project.fileTree(variant.javaCompile.destinationDir)

checkstyle.exclude('**/BuildConfig.java')

checkstyle.exclude('**/R.java')

checkstyle.exclude('**/com/almeros/android/multitouch/**')

project.tasks.getByName("check").dependsOn checkstyle

}

// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/jar.gradle

android.libraryVariants.all { variant ->

def jarTask = project.tasks.create(name: "jar${variant.name.capitalize()}", type: Jar) {

from variant.javaCompile.destinationDir

exclude "**/R.class"

exclude "**/BuildConfig.class"

}

jarTask.dependsOn variant.javaCompile

artifacts.add('archives', jarTask);

}

}

// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/gradle-mvn-push.gradle

def isReleaseBuild() {

return VERSION_NAME.contains("SNAPSHOT") == false

}

def getReleaseRepositoryUrl() {

return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL :

"https://oss.sonatype.org/service/local/staging/deploy/maven2/"

}

def getSnapshotRepositoryUrl() {

return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL :

"https://oss.sonatype.org/content/repositories/snapshots/"

}

def getRepositoryUsername() {

return hasProperty('USERNAME') ? USERNAME :

(hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "")

}

def getRepositoryPassword() {

return hasProperty('PASSWORD') ? PASSWORD :

(hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "")

}

task apklib(type: Zip) {

appendix = extension = 'apklib'

from 'AndroidManifest.xml'

into('res') {

from 'res'

}

into('src') {

from 'src'

}

}

artifacts {

archives apklib

}

afterEvaluate { project ->

uploadArchives {

repositories {

mavenDeployer {

beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

pom.groupId = GROUP

pom.artifactId = POM_ARTIFACT_ID

pom.version = VERSION_NAME

repository(url: getReleaseRepositoryUrl()) {

authentication(userName: getRepositoryUsername(),

password: getRepositoryPassword())

}

snapshotRepository(url: getSnapshotRepositoryUrl()) {

authentication(userName: getRepositoryUsername(),

password: getRepositoryPassword())

}

/*

// Leaving out as artifact was incorrectly named when found

addFilter('aar') { artifact, file ->

artifact.name == archivesBaseName

}

addFilter('apklib') { artifact, file ->

artifact.name == archivesBaseName + '-apklib'

}

*/

pom.project {

name POM_NAME

packaging POM_PACKAGING

description POM_DESCRIPTION

url POM_URL

scm {

url POM_SCM_URL

connection POM_SCM_CONNECTION

developerConnection POM_SCM_DEV_CONNECTION

}

licenses {

license {

name POM_LICENCE_NAME

url POM_LICENCE_URL

distribution POM_LICENCE_DIST

}

}

developers {

developer {

id POM_DEVELOPER_ID

name POM_DEVELOPER_NAME

}

}

}

}

}

}

signing {

required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }

sign configurations.archives

}

model {

task androidJavadocs(type: Javadoc) {

source = android.sourceSets.main.java.sourceFiles

classpath = files(android.bootClasspath)

}

}

task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {

classifier = 'javadoc'

from androidJavadocs.destinationDir

}

model {

task androidSourcesJar(type: Jar) {

classifier = 'sources'

from android.sourceSets.main.java.sourceFiles

}

}

artifacts {

archives androidSourcesJar

archives androidJavadocsJar

}

}

task makeClean(type: Exec) {

workingDir '../../'

commandLine 'make', 'clean'

}

task makeAndroid(type: Exec) {

workingDir '../../'

commandLine 'make', 'android'

}

task makeAndroidAll(type: Exec) {

workingDir '../../'

commandLine 'make', 'apackage'

}


// mapbox-gl-native/platform/android/MapboxGLAndroidSDKTestApp/build.gradle

apply plugin: 'android-sdk-manager'

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

apply plugin: 'checkstyle'

task accessToken {

def tokenFile = new File("MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml")

if (!tokenFile.exists()) {

String tokenFileContents = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +

"<resources>\n" +

" <string name=\"mapbox_access_token\">" + "$System.env.MAPBOX_ACCESS_TOKEN" + "</string>\n" +

"</resources>"

if (tokenFileContents == null) {

throw new InvalidUserDataException("You must set the MAPBOX_ACCESS_TOKEN environment variable.")

}

tokenFile.write(tokenFileContents)

}

}

gradle.projectsEvaluated {

// preBuild.dependsOn('accessToken')

}

ext {

supportLibVersion = '23.4.0'

}

model {

android {

compileSdkVersion 23

buildToolsVersion "23.0.3"

defaultConfig {

applicationId "com.mapbox.mapboxsdk.testapp"

minSdkVersion.apiLevel 15

targetSdkVersion.apiLevel 23

versionCode 9

versionName "4.1.0"

// Specify AndroidJUnitRunner as the default test instrumentation runner

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

compileOptions {

sourceCompatibility JavaVersion.VERSION_1_7

targetCompatibility JavaVersion.VERSION_1_7

}

packagingOptions {

exclude 'META-INF/LICENSE.txt'

exclude 'META-INF/NOTICE.txt'

exclude 'LICENSE.txt'

}

lintOptions {

checkAllWarnings true

warningsAsErrors true

disable 'IconDensities'

disable 'InvalidPackage'

}

testOptions {

unitTests.returnDefaultValues = true

}

buildTypes {

debug {

// run code coverage reports

testCoverageEnabled = true

}

release {

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}

}

}

}

dependencies {

compile(project(':MapboxGLAndroidSDK')) {

transitive = true

}

// Support libraries

compile "com.android.support:support-annotations:${supportLibVersion}"

compile "com.android.support:support-v4:${supportLibVersion}"

compile "com.android.support:appcompat-v7:${supportLibVersion}"

compile "com.android.support:design:${supportLibVersion}"

compile "com.android.support:recyclerview-v7:${supportLibVersion}"

// Leak Canary

//debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'

//releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'

// Directions SDK

compile('com.mapbox.mapboxsdk:mapbox-android-directions:[email protected]') {

transitive = true

}

// Geocoder SDK

compile('com.mapbox.mapboxsdk:mapbox-android-geocoder:[email protected]') {

transitive = true

}

// Testing dependencies

testCompile 'junit:junit:4.12'

testCompile 'org.mockito:mockito-core:1.10.19'

androidTestCompile "com.android.support:support-annotations:${supportLibVersion}"

androidTestCompile 'com.android.support.test:runner:0.4.1'

androidTestCompile 'com.android.support.test:rules:0.4.1'

androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'

androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.5.4'

}

checkstyle {

configFile project.file('../checks.xml')

showViolations true

}

model {

android.applicationVariants.all { variant ->

def name = variant.buildType.name

def checkstyle = project.tasks.create "checkstyle${name.capitalize()}", Checkstyle

checkstyle.dependsOn variant.javaCompile

checkstyle.source variant.javaCompile.source

checkstyle.classpath = project.fileTree(variant.javaCompile.destinationDir)

checkstyle.exclude('**/BuildConfig.java')

checkstyle.exclude('**/R.java')

project.tasks.getByName("check").dependsOn checkstyle

}

}

网友答案:

Your gradle approach is essentially rewriting or porting the Android SDK Makefile to gradle. To solve what you are doing on Linux, you will likely need to modify the existing Makefiles.

The reason is that the Mapbox Android SDK build process uses make android to build the target libmapbox-gl.so. The Gradle project you have includes the .so file in with your usual Java code.

make android makes a call into mapbox-gl-native/Makefile

and also generates mapbox-gl-native/build/android-arm-v7/Makefile, which you may have to research how to modify to generate debug information as Chris Stratton mentions in the comments above.

When you do get around to modifying your C++, you will then need to modify the settings.gradle to make use of your modified .so for Android.

include ':MapboxGLAndroidSDK'
project(':MapboxGLAndroidSDK').projectDir = new File(rootProject.projectDir, '<relative-path-to>/../mapbox-gl-native/platform/android/MapboxGLAndroidSDK')
include ':app'

Another thing to consider — Can you build a debuggable version for Linux?

We have successfully debugged C++ for the Mapbox SDK using the Xcode debugger, as we built an iOS app as well. I know this will not fit your exact needs, but I mention it in case anyone else in your lab or organization has access to Xcode on OS X and can start debugging using make iproj.

分享给朋友:
您可能感兴趣的文章:
随机阅读: