Un développeur parvient à faire fonctionner du code Swift sur Android
en attendant la sortie de Swift sous licence open source
Depuis la sortie de Swift, le nouveau langage de développement d’Apple, nombreux sont ceux qui ont tourné le dos à Objective-C. Étant considéré comme le successeur de ce dernier, Swift a gravi les échelons dans les classements et fait l’objet d’apprentissage de la part de nombreux développeurs.
Aussi, pour ouvrir son langage à plus de contributeurs, Apple a annoncé à la dernière conférence WWDC 2015 que Swift allait passer au format open source d’ici la fin de l’année. Communiqué qui a renforcé l’attrait des développeurs vers ce langage considéré par Apple comme le prochain grand langage de programmation qui servira à créer des applications et faire la programmation système pendant les 20 années à venir.
En attendant la sortie de Swift sous licence open source, un développeur s’est lancé dans un exercice assez intéressant et est parvenu à faire tourner du code Swift sur Android. Pour y arriver, ce dernier a été aidé par les caractéristiques intrinsèques de Swift.
Il faut rappeler que Swift a été construit afin d’être compatible avec l’environnement de développement intégré (EDI) Xcode. Dans cet EDI, le compilateur utilisé est la machine virtuelle de bas niveau LLVM (Low Level Virtual Machine). Une des particularités de ce compilateur est qu’il permet de créer un générateur de code pour plusieurs types d’architectures et des optimiseurs de compilation indépendants de la plate-forme sur laquelle et de tout langage.
Ainsi donc, au lieu de générer du code ciblant une architecture spécifique, LLVM génère d’abord du code assembleur, puis convertit ce dernier afin qu’il soit utilisé sur l’architecture souhaitée. En profitant de cette caractéristique modulaire, le développeur est parvenu à réutiliser le code binaire généré avec Swift afin de l’utiliser sur Android. Pour ce faire, il est passé par les différentes étapes suivantes :
Code du fichier Hello World
1 2
| // hello.swift
print("Hello, world!"); |
Instruction pour compiler le fichier Hello World
$ $SDK/usr/bin/swiftc -emit-object hello.swift
Contenu du fichier objet compilé hello.o
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| $ nm hello_swift.o
U __TFSSCfMSSFT21_builtinStringLiteralBp8byteSizeBw7isASCIIBi1__SS
U __TFSs27_allocateUninitializedArrayurFBwTGSaq__Bp_
U __TFSs5printFTGSaP__9separatorSS10terminatorSS_T_
U __TIFSs5printFTGSaP__9separatorSS10terminatorSS_T_A0_
U __TIFSs5printFTGSaP__9separatorSS10terminatorSS_T_A1_
0000000000000140 S __TMLP_
0000000000000100 S __TMaP_
U __TMdSS
U __TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__
U __TZvOSs7Process5_argcVSs5Int32
U _globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_func6
U _globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6
0000000000000000 T _main
U _swift_getExistentialTypeMetadata
U _swift_once |
Ensuite, il a fourni le code objet à l’éditeur de liens afin de générer l’exécutable.
1 2 3 4 5 6
| $ ld -arch x86_64 -o hello hello.o
-L$SDK/usr/lib/swift/macosx
-lSystem -lswiftCore
$ DYLD_LIBRARY_PATH=$SDK/usr/lib/swift/macosx ./hello
Hello, world! |
Il faut souligner que lorsque le compilateur Swift effectue la compilation, il génère dans un premier temps une représentation intermédiaire du code Swift, puis traduit cette représentation intermédiaire en code machine x86_64.
En continuant, le développeur a généré un fichier ARM qui est le format binaire utilisé sur Android. Voici le code utilisé pour générer le code binaire.
1 2 3 4 5 6 7
| $SDK/usr/bin/swiftc
-parse-as-library # We don't need a "main" function
-target armv7-apple-ios9.0
-emit-ir
add.swift
| grep -v "^!" # Filter-out iOS metadata
> add.ll |
À partir du code intermédiaire obtenu, le développeur a généré un fichier objet ARM ELF en s’appuyant sur le compilateur statique dans LLVM. Voici le code exécuté pour obtenir le fichier objet.
1 2 3 4
| $NDK/toolchains/llvm-3.5/prebuilt/darwin-x86_64/bin/llc
-mtriple=armv7-none-linux-androideabi
-filetype=obj
add.ll |
Enfin, il a créé un package pour être utilisé dans une application Android. Pour cela, il a utilisé le framework Java JNI Bridge et écrit le code en C.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // jni-bridge.c
// Let's work around Swift symbol mangling
#define SWIFT_ADD _TF3add13addTwoNumbersFTVSs5UInt86secondS0__S0_
uint8_t SWIFT_ADD(uint8_t, uint8_t);
jstring jni_bridge(JNIEnv * env, jobject thiz ) {
uint8_t a = 123;
uint8_t b = 45;
uint8_t c = SWIFT_ADD(a,b);
char result[255];
sprintf(result, "The result is %d", c);
return (*env)->NewStringUTF(env, result);
} |
Le tout a été regroupé dans une bibliothèque partagée et finalement le fichier objet a été compilé dans une application Android.
1 2 3 4 5 6
| $NDK_GCC/bin/arm-linux-androideabi-ld
add.o
jni_bridge.o
-shared # Build a shared library
-lc # We'll need the libc
-L$NDK/platforms/android-13/arch-arm/usr/lib |
Ci-dessous le résultat final sur Android.
Il est bon de savoir que le code Swift utilisé sur Android ne requiert pas de bibliothèque Swift pour être exécuté, d’où la relative facilité dans sa mise en œuvre. Pour ceux qui souhaitent tirer profit de cette application, l’auteur du projet l’a mise à la disposition du public sur GitHub.
Télécharger la démo de l'application Hello World sur GitHub
Source : Page de présentation du projet
Et vous ?
Que pensez-vous de ce projet ?
Voir aussi
Forum langages de programmation
Partager