48 votes

Comment configurer NDK avec Android Gradle plugin 0.7

Le nouveau Android plugin gradle (0.7) semble inclure un nouveau support pour le NDK, mais dans la documentation il y a peu ou pas de mention de celui-ci (la seule référence que j'ai trouvé est un test appelé le" ndkSanAngeles).

Il ressemble à gradle est à la recherche pour le NDK, que j'ai inclus dans mon CHEMIN. Cependant, la construction du projet échoue avec

  • Ce qui s'est passé: Échec de l'exécution de la tâche:OGLTests:compileDefaultFlavorDebugNdk'. NDK n'est pas configuré

Comment puis-je configurer le NDK dans gradle?

Ma version actuelle.gradle ressemble à ceci:

task nativeLibsToJar(type: Zip, description: 'create a jar with native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    extension 'jar'
    from fileTree(dir: 'src/main/libs', include: '**/*.so')
    from fileTree(dir: 'src/main/libs', include: '**/gdb*')
    into 'lib/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn nativeLibsToJar
}

dependencies {
    compile fileTree(dir: "$buildDir/native-libs", include: '*.jar')
}

android {
    compileSdkVersion 19
    buildToolsVersion '19.0.0'

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 19
        versionCode 1
        versionName "0.1"

    }
    buildTypes {
        release {
            runProguard false
        }
        debug {
           // jniDebugBuild true
            runProguard false
            debuggable true
        }
    }
    productFlavors {
        defaultFlavor {
            proguardFile 'proguard-rules.txt'
        }
    }
}

Merci.

76voto

reactive-core Points 497

En regardant à travers le plugin gradle code, j'ai trouvé le suivant qui m'a aidé à utiliser à la fois NDK et prêts à l'emploi bibliothèques natives:

Simplement le Lien dans Prédéfinis Bibliothèques Natives, il suffit d'ajouter le ndk la section de votre tâche. Par exemple, je l'ai ajouté ci-dessous dans productFlavors. Le abiFilter est le nom du dossier les libs sont stockés dans. abiFilters signifie à la fois libs à partir de la liste séparée par des virgules sera ajouté à votre final APK (de sorte que vous pourrait théoriquement avoir "armeabi", "armeabi-v7a", "x86", et "mips" tout en un APK, et l'O/S choisir l'architecture de prise en charge lib lors de l'installation):

productFlavors {
    arm {
        ndk {
            abiFilters "armeabi", "armeabi-v7a"
        }
    }
    x86 {
        ndk {
            abiFilter "x86"
        }
    }
}

Dans cet exemple, le bras de construire permettra de créer un APK avec la V5 et V7A bras libs, et la x86 construire permettra de créer un APK avec juste x86 libs en elle. Ce sera à la recherche pour les bibliothèques natives dans votre projet jniLibs répertoire. Le jniLibs répertoire doivent être des structures de l'ancien jni répertoire, c'est à dire:

[project]/[app]/src/main/jniLibs/armeabi/libmyNative.so
[project]/[app]/src/main/jniLibs/armeabi-v7a/libmyNative.so
[project]/[app]/src/main/jniLibs/x86/libmyNative.so

Ensuite, vous pouvez le charger en Java comme suit:

static
{
    loadLibrary("myNative");
}

Maintenant, disons une bibliothèque native dépend d'un autre. Vous DEVEZ (si le réglage de votre min API API de 17 ans ou moins) de charger les bibliothèques dépendantes d'abord:

static
{
    loadLibrary("myDependency");
    loadLibrary("myNative");
}

Vous pouvez également placer le ndk {} la section de votre defaultconfig.ini.php ou un buildType (comme debug ou release ou ce que vous pouvez utiliser). Par exemple:

buildTypes {
    debug {
        ndk {
            abiFilters "armeabi", "armeabi-v7a"
        }
    }
}

Par prédéfinis, je veux dire, 3e partie libs que vous avez téléchargé ou une bibliothèque, vous construit à l'aide de la NDK chaîne d'outils ou de votre propre BRAS de la chaîne (pas le ndk-build script lui-même).

L'API de 18 ans, ils ont fixé depuis longtemps un problème d'architecture qui a empêché le natif lib chargeur de "automatiquement" chargement des dépendances, car il ne savait pas à propos de l'application de la lib (des raisons de sécurité, etc). L'API de 18 ans et plus, si myNative dépend myDependency ci-dessus, vous pouvez simplement appeler la fonction loadLibrary("myNative") et le système d'exploitation de la poignée de chargement myDependency. Ne COMPTEZ pas sur ce que, jusqu'à ce que le taux de pénétration du marché des appareils fonctionnant API 17 et ci-dessous est à un faible nombre acceptable pour vous.


Explicitement Construire NDK Bibliothèques De la Source dans la version actuelle d'Android Studio, vous pouvez effectuer les opérations suivantes:

Définir le ndk.dir valeur dans votre local.propriétés de point de NDK à la maison, comme mentionné précédemment. Personne ne sait si vous pouvez utiliser env vars directement dans le local.propriétés? :)

Dans votre construction.gradle de fichiers, d'ajouter quelque chose comme ceci à votre tâche (encore une fois, peut être defaultconfig.ini.php, debug, release, un productFlavor, etc):

ndk {
    moduleName "myNDKModule"
    stl "stlport_shared"
    ldLibs "log", "z", "m"
    cFlags "-I/some/include/path"
}

C'est la structure de base avec des types pris en charge actuellement (moduleName, stl, ldLibs, et cFlags). J'ai regardé et n'a pas trouvé plus que cela. Il y a un problème, je crois, avec ldLibs parce qu'il ajoute automatiquement "-l" à l'avant de chaque champ ci-dessus. Vous pouvez tromper bien (j'ai dû) en disant: ldLibs "journal -lz -lm -Wl,-toute-archive-l/chemin/vers/someOtherLib -Wl,-non-ensemble-archive"

Dans cette ligne, vous êtes juste de marquage à la fin du premier paramètre pour ajouter des paramètres qui ne commencent pas par -l, de sorte que vous pouvez vous en tirer pour l'instant. Dans le cas ci-dessus, je suis à la liaison d'un ensemble statique de la bibliothèque dans mon NDK module pour une utilisation à partir de l'intérieur de Java. J'ai demandé à google développeurs d'ajouter des fonctionnalités supplémentaires à autoriser, voire à la possibilité de fusionner votre propre Android.mk fichier dans le NDK processus de génération, mais comme c'est tout nouveau, il peut être un certain temps.

Actuellement, tout ce que vous mettez dans la construction.gradle supprime le temp répertoire de construction et recrée à chaque fois, donc à moins que vous souhaitez télécharger et de modifier le gradle android plugin code source (ce qui serait le fun), il y a certains "faire"comme cette nécessaire pour obtenir vos trucs copié dans la construction. Le android gradle script qui fournit cette ndk soutien à essence génère un Android.mk fichier et construit à l'aide de la NDK système dans un répertoire temporaire.

Dérouté pour une seconde. Le nom de module doit correspondre à un c ou cpp fichier dans votre projet en vertu de la jni répertoire comme:

[project]/[app]/src/main/jni/myNDKModule.cpp

La stl valeur doit être définie sur une valeur de "stlport_shared" ou "stlport_static" si vous souhaitez utiliser le stlport bibliothèques en C++. Vous pouvez laisser stl si vous n'avez pas besoin d'étendre le support du C++. Rappelez-vous Android fournit de très de base le support du C++ par défaut. Pour les autres bibliothèques C++, afficher votre NDK directives de documentation dans le NDK que vous avez téléchargé. Notez que par la mise à stlport_shared ici, gradle des copies de la libstlport_shared.afin de lib de votre NDK sources/cxx-stl/stlport/répertoire libs pour votre APK de la lib. Il gère également le chemin d'inclusion dans le compilateur (techniquement le gradle ne pas faire tout cela, mais l'Android NDK système de construction). Afin de ne pas mettre votre propre copie de stlport dans votre jniLibs répertoire.

Enfin, je pense que cFlags est assez évident.

Vous ne pouvez pas définir ANDROID_NDK_HOME sur Mac OSX (voir ci-dessous), mais à partir de quelques recherches que j'ai fait semble peut-être que cela fonctionne encore sur d'autres systèmes d'exploitation. Il sera supprimé si.

Je voulais commenter, mais n'ont pas la réputation encore. Dennis, les variables d'environnement sont ignorés complètement, et pas seulement remplacé. En fait, vous ne recevez pas l'un de vos variables d'environnement. À partir de ce que je peux dire, Android Studio IDE crée son propre environnement avec seulement quelques variables d'environnement (Système de contrôle.la fonction getenv() et l'imprimer à partir d'un gradle script).

J'ai écrit ça comme un bug ici parce que l'utilisation d'env vars construit une amende de ligne de commande:
https://code.google.com/p/android/issues/detail?id=65213

mais comme vous pouvez le voir, Google a décidé qu'ils ne voulaient pas les variables d'environnement utilisées par les IDE à tous; je suis encore sur la clôture sur cette décision. Il me rend la vie pénible d'avoir à mettre à jour locale.propriétés à point pour les chemins d'accès absolus qui peuvent être chargés dans mon gradle scripts, ce que je n'ai toujours pas trouvé comment faire pour l'instant (mais je n'ai pas regardé en qui dure). Cela signifie que je force les membres de mon équipe à utiliser le même chemin que moi, jouer avec des liens, faire de tous les taper à chaque fois qu'ils tirent les pensions de titres, ou d'ajouter un script d'automatisation. Je crois que c'est une mauvaise décision, d'un coût de temps pour les développeurs qui s'appuient sur env vars qui peut être faible au niveau micro, mais grand à l'échelle macro.

boucle de masse, je crois que l'IDE sera mis à jour bientôt avec la possibilité d'ajouter le NDK chemin d'accès au dossier de votre projet, et il va automatiquement générer les locaux.les propriétés de fichier (au moins, il n'aurait pas de sens s'ils n'avaient pas pensé à cela).

Pour des exemples plus détaillés de Google, voici les exemples les plus récents (recherche de la jni ou ndk): https://docs.google.com/viewer?a=v&pid=sites&srcid=YW5kcm9pZC5jb218dG9vbHN8Z3g6NDYzNTVjMjNmM2YwMjhhNA


croix-plate-forme de graisse Apk en utilisant NDK pas pris en charge:

Enfin, un inconvénient à l'utilisation de l'Android Studio gradle version et de ne pas être en mesure de fournir votre propre Android.mk fichier, c'est que vous ne pouvez lien dans une architecture à votre NDK. Remarque j'ai dit: "lien". Vous pouvez construire le NDK Modules (moduleName ci-dessus) dans plusieurs architectures avec le "abiFilters de la commande", et ils seront placés dans votre application, tels que les mêmes APK pourrait être utilisé sur plusieurs architectures. Aussi longtemps que vous n'avez pas de liaison à l'encontre d'autres libs.

Cependant, dans mon cas, j'avais besoin de lien dans la 3ème partie des bibliothèques natives. La raison en est que si vous spécifiez abiFilters, disons armeabi et x86, mais vous avez besoin de lien dans libSomeLib, vous n'avez aucun moyen de dire Gradle le lien dans le bras de version pour le armeabi NDK construire et la version x86 pour le x86 NDK construire.

La seule solution que j'ai trouvé jusqu'à présent dans Gradle est de créer de construction séparé de tâches ou de produit de saveurs pour chaque architecture. Bien que les moyens de séparer les Apk. Dans le ndk-build script, vous pouvez spécifier par l'architecture C Drapeaux, LD LIBS, etc dans le Android.mk fichier. Dans Gradle, il n'y a pas d'option pour le faire (encore). Donc, juste être conscient que si vous voulez construire un "gros" apk qui a toutes vos prises en charge native des architectures en elle, tout en les reliant avec des libs externes d'origine, vous devez sortir de votre façon.

Je n'ai pas essayé encore, mais si je décide de la graisse APK est la direction que je veux aller, mon plan est de construire le NDK libs à l'aide de ndk-build de l'extérieur à l'ancienne avec un Android.mk fichier, puis lier la finale libs en utilisant le haut une partie de ce post (liaison native libs) sans utiliser le NDK fonctionnalités de génération en Gradle. Il est trop mauvais, j'ai passé beaucoup de temps à essayer de comprendre exactement comment l'utiliser, alors j'espère que le temps a été utile pour tous ceux qui lisent ceci. haha. Mais pour 75% de la population, ce n'est pas un besoin probablement. Je peux me charger de multiples Apk pour chaque architecture de la boutique à la fin.

34voto

user1906 Points 725

Trouvé la réponse. L'inclusion de ndk.dir=path/to/ndk dans le fichier local.properties fait l'affaire.

15voto

stefan.nsk Points 390

vous pouvez également définir la variable d'environnement ANDROID_NDK_HOME

1voto

peacepassion Points 76

J'ai passé beaucoup de temps à configurer ndk dans build.gradle. J'ai un bon blog qui résout mon problème.

0voto

groundloop Points 1

Comme indiqué précédemment, l'ajout de ndk.dir = dans local.properties aide. Il est intéressant de noter que local.properties remplace toute valeur définie pour la variable d’environnement ANDROID_NDK_HOME, même si vous n’avez pas configuré ndk.dir dans local.properties . (au moins avec le plugin Gradle android v 0.7.3).

Ceci est déroutant car Android Studio peut écraser le fichier local.properties et ne semble pas fournir un moyen de configurer ndk.dir :(

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X