Jacques Foucry bio photo

Jacques Foucry

IT, râleur et faiseur de pain

Email Twitter

Lassé de Linux et de systemd j’ai décidé de passer mon poste de travail (un simple portable) sous FreeBSD.



Après quelques mésaventures il reste quelques petites choses qui ne fonctionnent pas (impossible d’avoir le son correct dans le casque), j’ai maintenant un environnement graphique qui n’a rien à envier à un bureau Linux.

Le contexte

J’ai envie de continuer le développement d’une application Android et pour cela j’ai besoin Android Studio, l’IDE de Google.

J’ai donc téléchargé la dernière version disponible (au moment où j’écris ces lignes, il s’agit de la version 2.3.3 pour Linux 64 bits).

Après décompression du fichier .zip, j’obtiens le répertoire andrdoid_studio dans mon répertoire de téléchargement. Vous pouvez déplacer le nouveau répertoire à votre guise. Dans ce répertoire se trouve le script bin/studio.sh qui lance l’IDE.

En lançant ce script dans un terminal, outre tous les messages d’initialisation on obtient la notification suivante :

Android Studio ne fonctionne pas sur FreeBSD…
… et on reste coincé jusqu’à ce l’on tue le processus

Il est alors nécessaire de tuer le processus lancé dans la fenêtre de Terminal.

Alors, on abandonne ?

Certainement pas !

J’ai longuement cherché et je suis tombé sur un site intéressant. Celui-ci propose de créer un environnement d´intégration continue1 pour des applications Android sur FreeBSD. Nous n’allons pas forcément aller jusqu’au bout de la démarche, mais une partie de celle-ci nous intéresse, celle qui propose un patch pour le SDK Android.

Téléchargement du SDK

Normalement, le SDK s’installe au premier lancement de l’IDE. Mais comme l’IDE ne fonctionne pas, nous devons récupérer le SDK depuis les serveurs de Google et le mettre dans dataset ZFS spécifique.

Note: si vous n’utilisez pas, ZFS, faite un répertoire. Vous devez bien sûr remplacer <username> par votre nom d’utilisateur et <usergroup> par le nom de votre groupe principal. Vous pouvez aussi faire ce dataset (ou ce répertoire) dans /opt si vous êtes plusieurs à utiliser la machine.

% sudo zfs create – o mountpoint=/usr/home/<username>/Android zroot/usr/home/<username>/Android
% sudo chown <username>:<usergroup>/Android

Nous allons télécharger une version du SDK et la déposer dans /tmp puis, la décompresser dans notre nouveau dataset.

% cd /tmp
% fetch ´https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz´
% tar zxf android-sdk_r24.4.1-linux.tgz – C /usr/home/<usernane>/Android

À ce stade nous avons dans le répertoire /usr/home/<username>/Android un nouveau répertoire android-sdk-linux, issue de la décompression de l’archive téléchargée précédemment.

Nous allons tout de suite ajouter une variable dans le fichier de configuration de notre shell (.basrc, .kshrc, .cshrc, .zshrc, etc). À vous d’adapter selon le votre.

% export ANDROID_HOME=/usr/home/<username>/Android/android-sdk-linux
% source ~/.zshrc

Mise à jour du SDK

Le SDK que ne venons de télécharger n’est pas à jour. Nous allons utiliser les outils fournis dans celui-ci pour faire les mises à jour.

% $ANDROID_HOME/tools/android update sdk --no-ui

Nous allons devoir accepter les licences (par trois fois) pour que le téléchargement et les mises à jour se fassent. Le processus peut être assez long, vous pouvez prendre une pose café.

Clone des sources de base

Nous allons maintenant, depuis un dépôt git de Google récupérer les sources d’une partie du SDK, la base. Nous allons nous mettre dans /tmp parce que nous allons jeter cette partie une fois notre manipulation terminée (vous pouvez bien sûr souhaiter conserver cette extraction, à vous de voir.)

% cd /tmp
% git clone https://android.googlesource.com/platform/tools/base

Note : là aussi le processus est long.

Nous obtenons un répertoire /tmp/base.

Appliquer le patch

Voici le patch à appliquer, brut de fonderie :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
diff – r – u a/common/src/main/java/com/android/SdkConstants.java b/common/src/main/java/com/android/SdkConstants.java
--- a/common/src/main/java/com/android/SdkConstants.java 2016-09-0607:56:56.325948102 +0000
+++ b/common/src/main/java/com/android/SdkConstants.java 2016-09-0607:58:10.721944140 +0000
@@ -635,6 +635,8 @@
return PLATFORM_WINDOWS;
} else if (os.startsWith(“Linux”)) { //$NON-NLS-1$
return PLATFORM_LINUX;
+ } else if (os.startsWith(“FreeBSD”)) { //$NON-NLS-1$
+ return PLATFORM_LINUX;
}

return PLATFORM_UNKNOWN;
diff – r – u a/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java b/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java
--- a/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java 2016-09-0607:56:56.828948347 +0000
+++ b/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java 2016-09-0607:58:35.160941890 +0000
@@ -216,6 +216,8 @@
hostOS = HostOs. WINDOWS;
} else if (os.startsWith(“Linux”)) { //$NON-NLS-1$
hostOS = HostOs. LINUX;
+ } else if (os.startsWith(“FreeBSD”)) { //$NON-NLS-1$
+ hostOS = HostOs. LINUX;
}

BitSize jvmBits;

Note : il ne faut jamais copier/coller un patch. En effet, les espaces et tabulations peuvent poser des problèmes. C’est pourquoi je vous propose de le télécharger que vous n’aurez plus qu’à «  dézipper » pour avoir le fichier.patch

Nous allons appliquer le patch en deux fois. Une première fois «  pour de rire » afin de vérifier que tout va bien se passer et le seconde fois «  pour de vrai ».

Note  nous allons supposer que vous avez télécharger et « dézippé » le fichier de patch dans $HOME.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
% cd /tmp/base
% patch -u -p1 -b -l -C < ~/AndroidStudo4freeBSD.patch
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff -r -u a/common/src/main/java/com/android/SdkConstants.java b/common/src/main/java/com/android/SdkConstants.java
|--- a/common/src/main/java/com/android/SdkConstants.java        2016-09-06 07:56:56.325948102 +0000
|+++ b/common/src/main/java/com/android/SdkConstants.java        2016-09-06 07:58:10.721944140 +0000
--------------------------
Patching file common/src/main/java/com/android/SdkConstants.java using Plan A...
Hunk #1 succeeded at 635.
Hmm...  The next patch looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff -r -u a/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java b/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java
|--- a/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java      2016-09-06 07:56:56.828948347 +0000
|+++ b/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java      2016-09-06 07:58:35.160941890 +0000
--------------------------
Patching file sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java using Plan A...
Hunk #1 succeeded at 216.
done

Note : je ne suis pas un grand spécialiste de commande patch, référez vous à la page de manuel pour avoir une explication sur chacune de options. Sachez toutefois que -C est l’option pour vérifier que tout va bien se passer.

Si vous n’avez pas d’erreur avec cette commande retirer simplement l’option -C pour appliquer le patch.

Recompiler les fichiers patchés

Nous avons les sources de base avec les deux fichiers patchés, il faut maintenant les compiler (nous n’allons pas compiler tout base).

1
2
% javac common/src/main/java/com/android/SdkConstants.java
% javac sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java -cp "sdklib/src/main/java:common/src/main/java:annotations/src/main/java"

Remplacement des fichiers dans les .jar

Vous le savez sans doute, les fichiers .jar ne sont en fait que des fichiers zip quelque peu déguisés. Il est donc «  facile » d’extraire un fichier d’un .jar pour le mettre dans un autre.

C’est ce que nous allons faire maintenant en récupérant les deux .class java qui nous intéressent dans les fichiers que nous venons de patcher pour les injecter dans les .jar du SDK, les remplaçant par la même occasion.

% cd sdklib/src/main/java/ && jar uf ${ANDROID_HOME}/tools/lib/sdklib.jar com/android/sdklib/internal/repository/archives/ArchFilter.class
% cd /tmp/base
% cd common/src/main/java && jar uf ${ANDROID_HOME}/tools/lib/common.jar com/android/SdkConstants.class

Note : ces deux commandes ne renvoient rien en cas de succès, comme la majorité des commandes UNIX. Vous pouvez toutefois vérifier le code retour de la commande pour vous assurer qu’il est bien positionné à 0, avec la commande echo $?

Vérification

Il est temps de vérifier si notre hack a fonctionné.

Si vous lancez à nouveau bin/studio.sh pour lancer AndroidStudio, vous ne devriez plus voir la boite de dialogue vous annonçant que AndroidStudio ne tourne pas sur cette plate forme

Après un petit laps de temps (environ 10´´) vous devriez voir apparaître une autre fenêtre, celle-ci indiquant que notre pari est presque gagné (il va falloir indiquer au programme où se trouvent les SDK, dans $ANDROID_HOME en l’occurrence).

Bonus

En bonus, je vous propose le fichier .desktop qui vous permettra d’ajouter le lancement de AndroidStudio dans votre menu.

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env xdg-open
[Desktop Entry]
Version=1.0
Type=Application
Name=Android Studio
Exec="/usr/home/<username>/Downloads/android-studio/bin/studio.sh» %f
Icon=/usr/home/<username>/Downloads/android-studio/bin/bin/studio.png
Categories=Development; IDE;
Terminal=false
StartupNotify=true
StartupWMClass=jetbrains-android-studio
Name[en_GB]=android-studio.desktop

Pensez à changer les valeurs des chemins pour adapter ce script à votre configuration.

Nommez le AndroidStudio.desktop et déposez le dans ~/.local/share/applications. Au prochain redémarrage de l’interface graphique, vous devriez trouver dans le menu Programmation une nouvelle entrée, Android Studio.

Le nouveau menu

Les problèmes commencent

Vous allez vite vous rendre compte que la compilation échoue sur une histoire de GLIBC-2.14 qui ne permet de faire fonctionner une partie des outils de compilation.

Cela vient de la couche d’émulation dont Android Studio à besoin. Par défaut, même avec FreeBSD-11.0 c’est le paquet linux_base-c6 qui est installé et qui utilise la GLIBC de CentOS 6. Il faudrait utiliser le paquet linux_base-c7 qui nous apporterait la GLIBC de CentOS 7, la GLIBC-2.17.

Il suffit donc de supprimer le paquet linux_base-c6 et d’installer le paquet linux_base-c7. Mais beaucoup d’autres logiciel déjà installé utilisent la paquet c6.

Par exemple ce blog est écrit avec l’éditeur sublime text 3. Et celui-ci a disparu lorsque j’ai changé de version de linux_base. J’ai donc essayé de le compiler à partir des sources dans /usr/ports/editor/linux-sublime3.

Et j’ai eu un avertissement (warning) qui m’indiquait que OVERRIDDE_LINUX_BASE_PORT=c6_64 était obsolète et qu’il fallait utiliser DEFAULT_VERSIONS+=linux=c6_64. Cette option se trouve dans le fichier /etc/make.conf.

Après cette modification mon cher sublime text 3 a été compilé sans erreur.

Il faut maintenant faire quelques manipulation au niveau des SDK pour que les fichiers linux soient bien pris en compte.

Un peu de shell, ça ne fait pas de mal

Tout d’abord, nous allons constater l’étendu du travail à faire en recherchant les fichiers au format ELF, le format des fichiers exécutable linux

% find build-tools/26.0.1/ -maxdepth 1 -type f -print0 | xargs -0 -n 10 file | grep "ELF"

Et nous allons faire en sorte qu’ils soient pris en charge par brandelf, la passerelle linuxde FreeBSD. Nous changeons aussi les droits d’exécution de ces mêmes fichiers.

% find build-tools/24.0.3/ -maxdepth 1 -type f -print0 | xargs -0 -n 10 file | grep "ELF" | awk 'BEGIN { FS = ":" } ; {print $1}' | xargs brandelf -t Linux
% find build-tools/24.0.3/ -maxdepth 1 -type f -print0 | xargs -0 -n 10 file | grep "ELF" | awk 'BEGIN { FS = ":" } ; {print $1}' | xargs chmod +x

Il faut faire de même pour toutes les versions de SDK que vous avec installé.

Conclusion

Ce n’est pas sans mal que nous avons modifié AndroidStudio pour le faire tourner sur FreeBSD surtout pour les novices. C’est maintenant à l’usage que nous verrons si ces efforts valaient le coup.

  1. n’oubliez pas de visiter le blog de zerwaren.net qui non seulement nous fournis le patch que nous utilisons, mais regorge d’autres articles passionnant. Merci à lui. 


Laisser un commentaire

Les commentaires sont soumis à modération.