Android Cross Compilation

 druide

But

J'aimerais faire un simple "Hello World!" en C pour Android.

Mon objectif étant de pouvoir lancer le programme en ligne de commande. Je travail sur un Android Samsung S4 (ARMv7) installé avec cyanogenmod 13.0-NIGHTLY-jfltexx


$ adb shell
shell@jfltexx:/ $ hello
Hello World!
shell@jfltexx:/ $

Pré requis

Pour pouvoir faire ce travail, il faut dans un premier temps avoir activé les options développeurs sur son smartphone et les paramétrer pour permettre un accès au smartphone via adb. Il faut également donner un accès « root » à adb (toujours dans les options développeurs).


Côté PC, je tourne actuellement sur une Fedora 24.

Mise en place

  1. Installation d'android-ndk. Pour ma part, j'ai téléchargé cette version. Décompressez l'archive.
  2. Dans le répertoire nouvellement crée (chez moi android-ndk-r12b), démarré le script python make_standalone_toolchain.py
    
    druide@druide:~/android-ndk-r12b$ build/tools/make_standalone_toolchain.py
    usage: make_standalone_toolchain.py [-h] --arch
                                        {arm,arm64,mips,mips64,x86,x86_64}
                                        [--api API]
                                        [--stl {gnustl,libc++,stlport}] [--force]
                                        [-v]
                                        [--package-dir PACKAGE_DIR | --install-dir INSTALL_DIR]
    

    Par exemple:

    
    druide@druide:~/android-ndk-r12b$ build/tools/make_standalone_toolchain.py --arch arm --api 21 --stl gnustl -v --install-dir ~/android/
    
  3. Préparation d'un script pour régler toutes les variables d'environnements nécessaires. A la fin, le script lance un nouveau shell avec toutes les variables préparées.
    
    #!/usr/bin/env sh
    
    export TOOLCHAIN=$HOME/android
    export SYSROOT="$TOOLCHAIN/sysroot"
    export PATH="$PATH:$TOOLCHAIN/bin:$SYSROOT/usr/local/bin"
    export PREFIX=$HOME/Android/out
    
    export ARCH=armv7
     
    export CROSS_COMPILE=arm-linux-androideabi
    export CC=arm-linux-androideabi-gcc
    export CXX=arm-linux-androideabi-g++
    export AR=arm-linux-androideabi-ar
    export AS=arm-linux-androideabi-as
    export LD=arm-linux-androideabi-ld
    export RANLIB=arm-linux-androideabi-ranlib
    export NM=arm-linux-androideabi-nm
    export STRIP=arm-linux-androideabi-strip
    export CHOST=arm-linux-androideabi
     
    export CFLAGS="${CFLAGS} --sysroot=${SYSROOT} -I${SYSROOT}/usr/include -I${TOOLCHAIN_PATH}/include -I${PREFIX}/include"
    export CPPFLAGS="-std=c++14 ${CFLAGS}"
    export CXXFLAGS="${CFLAGS}"
    export LDFLAGS="${LDFLAGS} -L${SYSROOT}/usr/lib -L${TOOLCHAIN}/lib -L${PREFIX}/lib -lgnustl_shared"
    
    /usr/bin/env bash
    


    Il faut encore mettre le droit d'exécution au script pour l'utilisateur

    
    druide@druide:~/android$ chmod u+x prepare.sh
    druide@druide:~/android$ ./prepare.sh
    druide@druide:~/android$ echo $TOOLCHAIN
    /home/druide/android
    

Code & compilation

Dans un répertoire « test », je place mon fichier « hello.c » qui contient ce code

#include


int main(int argc, char** argv) {
fprintf(stdout, "Hello World!\n");
return 0;
}


Reste plus qu'à le compiler. Comme mon script « prepare.sh » à définit une variable CC pointant sur le bon compilateur, je vais utiliser cette variable pour compiler mon programme.


druide@druide:~/test$ $CC -fPIE -pie -o hello hello.c
druide@druide:~/test$ ls -l
total 12
-rwxrwxr-x. 1 piferrari piferrari 6352  7 sep 09:03 hello
-rw-r--r--. 1 piferrari piferrari  103  7 sep 09:01 hello.c
druide@druide:~/test$ file hello
hello: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /system/bin/linker, not stripped

Test sur la bête

En utilisant « adb », on peut pousser le fichier binaire sur la bête, par exemple dans /sdcard/Download. Ensuite, on ouvre un shell distant sur le smartphone.

druide@druide:~/test$ adb push hello /sdcard/Download
[100%] /sdcard/Download/hello
druide@druide:~/test$ adb shell
Il faut maintenant déplacer le fichier binaire sur une partition qui puisse contenir des fichiers exécutables et pour laquelle on a le droit d'écriture. Mon choix se porte sur /data. Il faut quand même devenir root pour ce travail.

shell@jfltexx:/ $ ls -l /sdcard/Download/                                       
total 16
-rw-rw---- 1 root sdcard_rw 6352 2016-09-07 09:20 hello
shell@jfltexx:/ $ su
root@jfltexx:/ # mv /sdcard/Download/hello /data
root@jfltexx:/ # chmod u+x /data/hello
root@jfltexx:/ # /data/hello
Hello World!

That's all folks

  • 2 years 8 months before
  • |