简体   繁体   中英

External gradle dependency on libGDX project

I am working on an android game and external library using LibGDX. I'm getting the following error:

Error:Execution failed for task ':android:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: 
    org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files\Android\Android Studio\jre\bin\java.exe'' 
    finished with non-zero exit value 1

I'm trying to create an external shared project that all my other games can depend on for common code. The problem is my shared library project depends on Libgdx as well as my game project which also depends on libgdx. When launching my game on android devices. The gradle sync and also the build project works fine, it only occurs when trying to deploy onto a device. I can also deploy to desktop with no issues.

I think I may be exceeding the android method count limit of 65,536 due to the repeating library dependencies, but can't work out a better solution. Or it could be that android doesn't like nested dependencies that aren't in the root.


I have included my project structure and gradle files below. Would really appreciate a solution that allows me to continue to edit the library within the IDE of the game project. I would also be open to having an alternate project structure if anyone recommends something else.




Directory / Project Structure:

C:\
    Projects\
        SharedProject
        Project1
        Project2
        ...

My android module dependancy tree (by running "gradlew -q dependencies android:dependencies --configuration compile"):

+--- project :core
|    +--- com.badlogicgames.gdx:gdx:1.9.6
|    \--- project :APD_Core
|         \--- com.badlogicgames.gdx:gdx:1.9.6
\--- com.badlogicgames.gdx:gdx-backend-android:1.9.6
     \--- com.badlogicgames.gdx:gdx:1.9.6

(Note: APD_Core is the shared project)


Possible Solutions:

I have tried to use multiDexEnabled but this has not helped. I think I might need to exclude the gdx module when I compile the shared library into core but I have not worked that out yet. (I'm thinking that android does not like the shared library having the same dependancy on gdx that the android module also has) Another possibility is that android needs my shared project to be built into a jar and then put into the libs folder within the android module. And this might be doable via the android gradle file, but I'm new to gradle and dont know if this is needed or how to do it.


What I have changed :

added the shared project to the settings gradle

include ':APD_Core'
project(':APD_Core').projectDir = new File(settingsDir, '../APD_Core')

added the dependency to the shared project in the core module

project(":core") {
    ...
    dependencies {
        ...
        compile project(':APD_Core')
    }
}

have the shared project depend on libgdx

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile "com.badlogicgames.gdx:gdx:$gdxVersion"
}

Not much else has changed from the default generated project structure when using the gdx-setup.jar Note the shared project is was created from intellij as a new gradle project and not using the gdx-setup.jar Full gradle files bellow


GRADLE SETTINGS FILE:

include 'desktop', 'android', 'ios', 'core', ':APD_Core'
project(':APD_Core').projectDir = new File(settingsDir, '../APD_Core')

MAIN GRADLE FILE:
buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
        maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
        classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.2.0'
    }
}

allprojects {
    apply plugin: "eclipse"
    apply plugin: "idea"

    version = '1.0'
    ext {
        appName = "MyGame"
        gdxVersion = '1.9.6'
        roboVMVersion = '2.2.0'
        box2DLightsVersion = '1.4'
        ashleyVersion = '1.7.0'
        aiVersion = '1.8.0'
    }

    repositories {
        mavenLocal()
        mavenCentral()
        maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
        maven { url "https://oss.sonatype.org/content/repositories/releases/" }
    }
}

project(":desktop") {
    apply plugin: "java"


    dependencies {
        compile project(":core")
        compile "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
        compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
        compile "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop"
        compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
    }
}

project(":android") {
    apply plugin: "android"

    configurations { natives }

    dependencies {
        compile project(":core")
        compile "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
        natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
    }
}

project(":ios") {
    apply plugin: "java"
    apply plugin: "robovm"


    dependencies {
        compile project(":core")
        compile "com.mobidevelop.robovm:robovm-rt:$roboVMVersion"
        compile "com.mobidevelop.robovm:robovm-cocoatouch:$roboVMVersion"
        compile "com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion"
        compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios"
        compile "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-ios"
        compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios"
    }
}

project(":core") {
    apply plugin: "java"


    dependencies {
        compile "com.badlogicgames.gdx:gdx:$gdxVersion"
        compile project(':APD_Core')
    }
}

tasks.eclipse.doLast {
    delete ".project"
}

CORE GRADLE FILE:

apply plugin: "java"

sourceCompatibility = 1.6
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

sourceSets.main.java.srcDirs = [ "src/" ]


eclipse.project {
    name = appName + "-core"
}

dependencies {
    compile project(':APD_Core')
}

ANDROID GRADLE FILE(unmodified from the default generated one):

android {
    buildToolsVersion "25.0.1"
    compileSdkVersion 23
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }

        instrumentTest.setRoot('tests')
    }
    packagingOptions {
        exclude 'META-INF/robovm/ios/robovm.xml'
    }
    defaultConfig {
        applicationId "com.mygame"
        minSdkVersion 10
        targetSdkVersion 23
        multiDexEnabled true
    }
}

// called every time gradle gets executed, takes the native dependencies of
// the natives configuration, and extracts them to the proper libs/ folders
// so they get packed with the APK.
task copyAndroidNatives() { 
    file("libs/armeabi/").mkdirs();
    file("libs/armeabi-v7a/").mkdirs();
    file("libs/arm64-v8a/").mkdirs();
    file("libs/x86_64/").mkdirs();
    file("libs/x86/").mkdirs();

    configurations.natives.files.each { jar ->
        def outputDir = null
        if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a")
        if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")        
        if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
        if(jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64")
        if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
        if(outputDir != null) {
            copy {
                from zipTree(jar)
                into outputDir
                include "*.so"
            }
        }
    }
}

task run(type: Exec) {
    def path
    def localProperties = project.file("../local.properties")
    if (localProperties.exists()) {
        Properties properties = new Properties()
        localProperties.withInputStream { instr ->
            properties.load(instr)
        }
        def sdkDir = properties.getProperty('sdk.dir')
        if (sdkDir) {
            path = sdkDir
        } else {
            path = "$System.env.ANDROID_HOME"
        }
    } else {
        path = "$System.env.ANDROID_HOME"
    }

    def adb = path + "/platform-tools/adb"
    commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.mygame/com.mygame.AndroidLauncher'
}

// sets up the Android Eclipse project, using the old Ant based build.
eclipse {
    // need to specify Java source sets explicitly, SpringSource Gradle Eclipse plugin
    // ignores any nodes added in classpath.file.withXml
    sourceSets {
        main {
            java.srcDirs "src", 'gen'
        }
    }

    jdt {
        sourceCompatibility = 1.6
        targetCompatibility = 1.6
    }

    classpath {
        plusConfigurations += [ project.configurations.compile ]        
        containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'       
    }

    project {
        name = appName + "-android"
        natures 'com.android.ide.eclipse.adt.AndroidNature'
        buildCommands.clear();
        buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
        buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
        buildCommand "org.eclipse.jdt.core.javabuilder"
        buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
    }
}

// sets up the Android Idea project, using the old Ant based build.
idea {
    module {
        sourceDirs += file("src");
        scopes = [ COMPILE: [plus:[project.configurations.compile]]]        

        iml {
            withXml {
                def node = it.asNode()
                def builder = NodeBuilder.newInstance();
                builder.current = node;
                builder.component(name: "FacetManager") {
                    facet(type: "android", name: "Android") {
                        configuration {
                            option(name: "UPDATE_PROPERTY_FILES", value:"true")
                        }
                    }
                }
            }
        }
    }
}

SHARED PROJECT GRADLE FILE:

group 'APD_Core'
version '1.0'

apply plugin: 'java'

sourceCompatibility = 1.8

allprojects {
    apply plugin: "eclipse"
    apply plugin: "idea"

    version = '1.0'
    ext {
        gdxVersion = '1.9.6'
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile "com.badlogicgames.gdx:gdx:$gdxVersion"
}

If you are making common libraries for many games I'd suggest you to create a separate project containing these libraries, publish it to your local maven repo with the gradle maven-publish plugin and then declare the dependencies to these libraries in your game projects. That will help you now debug your problem, and it will make easier to modify those libraries and use them in other games in the future.

Adding:

compileJava   {
    sourceCompatibility = '1.7'
    targetCompatibility = '1.7'
}

to the root gradle file of the library project and removing the settings.gradle file from the library project resolved the issue.

Works with both maven local dependency and external gradle dependency.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM