2016-06-05 3 views
2

나는에있는 안드로이드 스튜디오 실험 플러그인 사용 설명서의 지시 사항을 따르 시도하고있다 :디버그 Mapbox 안드로이드 NDK 라이브러리

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

에있는 Mapbox GL 네이티브 라이브러리 수정 :

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

구체적으로 다음 Android 파일을 수정했습니다.

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

내 목표는 그래서 그것을 디버깅 할 수있는 라이브러리를 수정하는 것입니다 https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/build.gradle

76,

. 이상적으로는 Android Studio를 사용하여 라이브러리를 만들고 C/C++ 코드를 디버깅 할 수 있습니다. 지금까지는 빌드 할 수 있지만 디버깅 할 수는 없습니다. Mapbox에서 일하는 프로그래머는 안드로이드 코드를 디버깅하는 방법이 없다고 말했기 때문에 이것이 도달하기 쉬운 목표는 아니라고 생각합니다.

나는 안드로이드 스튜디오 실험 플러그인 사용 설명서의 지침을 적용하는 방법에는 여러 시도를했지만, 나는 Gradle을에 경험이 아니에요 내 최신 시도가 이해가 안 다음 오류 메시지와 함께 나를 떠나 :

Gradle 'android' project refresh failed Error:Cause:org.gradle.api.internal.ExtensibleDynamicObject

누구든지 디버깅 할 수있는 Android NDK 라이브러리를 만들려면이 파일을 수정하는 방법을 알고 있습니까? 위의 오류의 원인은 무엇입니까?

내가 사용하고 있습니다 : 나는 현재 그들이 수정 한 아래

> 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 

은 4 개 파일입니다. 나는 Gradle을 처음 사용하기 때문에 modfication을 올바르게 작성했다고 가정하지 마십시오. 빌드를 성공적으로 완료하기 전까지 Android Studio 실험용 플러그인 사용자 가이드 지침을 적용하려고 시도했을뿐입니다.

감사


#// 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 
} 
} 
+0

ndk-build 등을 통해 ndk 라이브러리를 빌드하는 원래의 "수동"방법을 살펴볼 수도 있습니다. 또한 일반적으로 apk를 통해 장치에 설치된 .so 파일은 디버그 정보를 제거합니다. (개발 호스트에서 실행되는) 디버거 자체를 커다란 스트라이핑되지 않은 버전으로 지정합니다. 또한 대화식 디버그 세션이 코드의 문제가되는 영역을 추론하고 로그 출력으로 계측하는 것보다 실제로 노력할 가치가 있는지 고려하십시오. –

+0

더 설명 할 수 있습니까? "apk를 통해 장치에 설치된 .so는 일반적으로 개발 호스트에서 실행되는 디버거 자체를 가리키는 동안 디버그 정보가 제거 될 것입니다." 디버거가 라이브러리의 스트립 해제/디버그 버전에 액세스 할 수 있도록하는 몇 가지 기술이 있다고 말하는 것입니까? 대화 형 디버깅이 가치가 있는지 생각해 봤지만 라이브러리를 진지하게 수정해야하므로 그럴 가치가 있다고 생각했습니다. 지금 그렇게하는 것이 어렵다는 것을 확신 할 수는 없습니다. – Mitch

+0

원격 디버깅은 거의 항상 대상에서 스트립 된 실행 파일 (또는이 경우 라이브러리)을 실행하고보다 완전한 파일의 위치로 개발 호스트에서 디버거를 호출하여 수행됩니다. ndk-build 메서드를 사용하고 명시 적으로 또는 암시 적으로 컴파일 플래그에서 -g로 끝나면 출력 트리에 여러 .so가 있어야합니다. 더 큰 명령은 unstripped 일 것입니다. 이것은 ndk-gdb에 공급할 항목입니다. 호스트에. 그러나 디버그 출력을 통찰력있게 사용하면 문제를 해결할 수 없다는 것은 드문 일입니다. 보통 영리 도구가 툴을 능가합니다. –

답변

1

귀하의 Gradle을 접근 방식은 본질적으로 Android SDK Makefile을 gradle로 다시 작성하거나 이식하는 것입니다. Linux에서 수행중인 작업을 해결하려면 기존 Makefile을 수정해야 할 수 있습니다.

이유는 Mapbox Android SDK build processmake android을 사용하여 대상인 libmapbox-gl.so을 빌드하기 때문입니다. 보유하고있는 Gradle 프로젝트에는 일반적인 Java 코드와 함께 .so 파일이 포함되어 있습니다.

make androidmapbox-gl-native/Makefile

에 전화를하게하고 또한 크리스 스트래튼 위의 댓글에서 언급으로 디버그 정보를 생성 수정하는 방법을 연구 할 수있는, mapbox-gl-native/build/android-arm-v7/Makefile를 생성합니다.

C++를 수정하려고 할 때 수정 된 .so를 Android 용으로 사용하려면 settings.gradle을 수정해야합니다.

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

또 다른 고려 사항 - Linux 용 디버그 가능 버전을 구축 할 수 있습니까?

우리는 iOS 응용 프로그램을 빌드 할 때 Xcode 디버거를 사용하여 Mapbox SDK 용 C++를 성공적으로 디버깅했습니다. 저는 이것이 여러분의 정확한 요구에 맞지 않을 것이라는 것을 알고 있습니다 만, 연구소 나 조직의 다른 누구도 OS X에서 Xcode에 액세스 할 수 있고 make iproj을 사용하여 디버깅을 시작할 수 있다고 언급합니다.

+0

의견을 보내 주셔서 감사합니다. Xcode에 액세스 할 수 없도록 직접 작업하고 있습니다. :-(그래도 디버깅하기 쉽다는 가정하에 Linux 용 디버깅 버전을 구축하는 것으로 바꿔 줄 수있는 좋은 제안 인 것 같습니다. 이미 libmapbox -gl.so의 디버그 버전이 있습니다. 걱정하지 않아도됩니다. 응용 프로그램을로드 한 후 내 지역의 디버그 소스를 "가리키는"방법을 모르겠다. 거기에서 조사해야 할 것이다. 결국 Android에서 디버깅하는 것이 좋을 것이다. 결국 앱이 모바일이 될 것입니다. – Mitch

+0

.gypi Gradle에 파일을 빌드하면 Android Studio에서 디버깅 할 수 있으므로 가치가있을 것입니다. 다른 사람들이 유용하다고 생각되면 Gradle 빌드 파일을 소스를 열어 보길 원할 것입니다. 위에 게시 한 링크와이 빌드 소스를 사용하여이 파일을 .gypi에서 Gradle로 변환하십시오. 행운을 빌어 요 !! https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/platform. gyp – RobLabs

+0

이 기능을 사용할 수 있다면 내가 가지고있는 것을 분명히 공유 할 것입니다. 귀하가 게시 한 링크 된 파일을 볼 수는 있지만 나는 .gypi 파일이 사용되는 곳을 모른다. 이것은 Gradle 또는 Android의 것입니까? 이 파일에 대해 어떻게 알 수 있습니까? 내가 Mapbox에서 위에 나열된 Gradle 파일을 얻었으므로 ".gypi에서 파일을 Gradle로 마이그레이션"이라는 것이 무엇을 의미하는지 명확하지 않습니다. Mapbox 파일이 Gradle 파일이라고 생각했습니다. – Mitch