Utilisation du compilateur nuitka pour python3 sur Alpine Linux ARMHF (musl)
Motivation
pidoctor est écrit en Python (car il n'y avait pas de moyen facile de faire fonctionner Crystal sur ARMHF / musl).
Cela signifie qu'il faut dépendre de Python, ce qui ajoute des frais généraux.
Je soupçonne que cette surcharge est la raison pour laquelle pidoctor ne fonctionne pas sur les Raspberry Pi de 256 MB - parce que la RAM est épuisée par tous les paquets qui sont nécessaires.
De plus, il est souhaitable que la distribution soit un téléchargement aussi petit que possible ! Cela signifie que Python doit être retiré de l'équation d'une manière ou d'une autre, et que le paquetage doit produire un binaire (comme ce serait le cas avec Crystal).
Heureusement, il y a la nuitka.
Et - vous avez de la chance - j'ai résolu quelques problèmes d'utilisation de nuitka sur Alpine Linux, ARMHF (peut-être que cela fonctionnera aussi pour x86).
Nuitka
nuitka est un logiciel fantastique, qui prend un script Python et le compile en un exécutable, ce qui l'accélère considérablement.
nuitka fait le gros du travail, vous n'avez même pas besoin d'ajuster quoi que ce soit dans votre code source (je pense). Vous pouvez l'exécuter comme ceci :
python3 -m nuitka -follow-imports -standalone pidoctor.py
Notez le drapeau -standalone, qui compilera les bibliothèques partagées nécessaires dans votre dossier .dist - ainsi l'installation pourra fonctionner sans toute dépendance sur Python !
Veuillez noter que WordPress ne tient pas compte des doubles tirets et les transforme en tirets simples. Le -m a un tiret simple, le -follow-imports et le -standalone ont des doubles tirets.
Installation de Nuitka sur Alpine Linux (spécifiquement arhmf, pourrait fonctionner sur d'autres cibles)
apk add python3-dev
apk add chrpath
pip3 install -U nuitka
facultativement, si vous êtes en mode sans disque (pour ajouter nuitka aux fichiers qui doivent être persistés) :
lbu add /usr/bin/nuitka3-run
lbu add /usr/bin/nuitka3
lbu add /usr/lib/python3.6/site-packages/nuitka
lbu commit -d
Note : la source de nuitka est en Python.
Vérifiez que nuitka fonctionne :
python3 -m nuitka
devrait exécuter sans montrant toute erreur de syntaxe.
Correction de nuitka pour fonctionner avec Alpine Linux armhf
Important : WordPress malmène malheureusement la syntaxe. Veuillez vous référer à la question GitHUB que j'ai ouverte.où j'ai également joint les fichiers de correction pour référence.
nuitka appelle plusieurs utilitaires binaires de support sur votre système, et attend d'eux qu'ils renvoient les résultats d'une certaine manière. C'est là que nuitka trébuche.
Première erreur
pidoctor:/opt/pidoctor# python3 -m nuitka -follow-imports -standalone pidoctor.py
Traceback (dernier appel le plus récent) :
File "/usr/lib/python3.6/site-packages/nuitka/__main__.py", line 188, in
main()
Fichier "/usr/lib/python3.6/site-packages/nuitka/__main__.py", ligne 182, dans main
MainControl.main()
Fichier "/usr/lib/python3.6/site-packages/nuitka/MainControl.py", ligne 846, dans main
Plugins.considerExtraDlls(dist_dir, module)
Fichier "/usr/lib/python3.6/site-packages/nuitka/plugins/Plugins.py", ligne 102, in considerExtraDlls
for extra_dll in plugin.considerExtraDlls(dist_dir, module) :
Fichier "/usr/lib/python3.6/site-packages/nuitka/plugins/standard/ImplicitImports.py", ligne 372, in considerExtraDlls
uuid_dll_path = locateDLL("uuid")
Fichier "/usr/lib/python3.6/site-packages/nuitka/utils/SharedLibraries.py", ligne 71, in locateDLL
return dll_map[dll_name]
KeyError : 'libuuid.so.1.3.0' (erreur de clé)
La raison de l'erreur : nuitka appelle ldconfig -p et s'attend à ce qu'il énumère une liste de bibliothèques partagées mises en cache, dans un format comme celui-ci :
libICE.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libICE.so.6
sur Alpine Linux, ldconfig -p échoue - car cette option n'existe pas. ldconfig sur Alpine Linux est incapable de produire une liste de la forme que Nuitka souhaite.
Fixe :
dans /usr/lib/python3.6/site-packages/nuitka/utils/SharedLibraries.py
ajoutez le code suivant immédiatement après les déclarations d'importation en haut :
def find_alpine(name,paths) :
pour path dans paths :
pour root, dirs, files in os.walk(path) :
si nom dans fichiers :
return os.path.join(root,name)
et dans locateDLL, avant d'importer le sous-processus, ajoutez le code suivant :
si os.path.isfile('/etc/alpine-release') :
return find_alpine(dll_name,["/lib","/usr/lib","/usr/local/lib"])
autre :
Importation de sous-processus(...)
Le (...) ci-dessus indique que le reste du code de locateDLL doit être indenté sous le else.
Ce que fait ce code : si le fichier /etc/alpine-release existe - indiquant que nous tournons sous Alpine Linux, nous recherchons la bibliothèque partagée dans trois répertoires prédéfinis :
- /lib
- /usr/lib
- /usr/local/lib
et renvoie le premier fichier correspondant. Notez que nous ne gérons pas le cas où le fichier n'est pas trouvé - dans ce cas, rien n'est renvoyé..
Deuxième erreur
Traceback (dernier appel le plus récent) :
File "/usr/lib/python3.6/site-packages/nuitka/__main__.py", line 188, in
main()
Fichier "/usr/lib/python3.6/site-packages/nuitka/__main__.py", ligne 182, dans main
MainControl.main()
Fichier "/usr/lib/python3.6/site-packages/nuitka/MainControl.py", ligne 859, dans main
standalone_entry_points = standalone_entry_points
Fichier "/usr/lib/python3.6/site-packages/nuitka/freezer/Standalone.py", ligne 1169, in copyUsedDLLs
used_dlls = detectUsedDLLs(source_dir, standalone_entry_points)
Fichier "/usr/lib/python3.6/site-packages/nuitka/freezer/Standalone.py", ligne 1062, in detectUsedDLLs
assert os.path.isabs(dll_filename), dll_filename
AssertionError : ldd
La raison de cette erreur : nuitka appelle ldd pour chaque bibliothèque partagée ("dll_filename") à ajouter à votre dossier .dist. Le but de cette opération est de trouver les dépendances de ces bibliothèques partagées elles-mêmes. (Une recherche récursive si vous voulez).
Par exemple :
pidoctor:/opt/pidoctor# ldd /usr/lib/libexpat.so.1
ldd (0x76f43000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x76efd000)
libc.musl-armhf.so.1 => ldd (0x76f43000)
Comme vous le voyez, libexpat.so.1 a deux dépendances :
- libgcc_s.so.1 -> se trouve dans /usr/lib/libgcc_s.so.1
- libc.musl-armhf.so.1 -> se trouve à l'adresse suivante ldd
et c'est précisément là que nuitka a des problèmes. Il veut copier un fichier avec un chemin absolu, et on lui donne le nom "ldd" à la place. Encore une fois, quelque chose qui est spécifique à Alpine Linux.
Par conséquent, l'assertion échoue, et nuitka ne continue pas.
Voici comment découvrir le fichier auquel il fait réellement référence :
pidoctor:~# qui ldd
/usr/bin/lddpidoctor:~# ls -alh /usr/bin/ldd
lrwxrwxrwx 1 root root 28 Jan 1 1970 /usr/bin/ldd -> ../../lib/ld-musl-armhf.so.1
Notez que ../../lib/ld-musl-armhf.so.1 est un chemin relatif, qui se réfère en fait à /lib/ld-musl-armhf.so.1 sur mon système. Et sur le vôtre, probablement, aussi.
Fixe :
recherche de libutil.so. dans le fichier /usr/lib/python3.6/site-packages/nuitka/freezer/Standalone.py
Il y a une ligne avec result.add(filename) en dessous. Juste au-dessus de cette ligne, insérer :
si le nom du fichier == 'ldd' :
filename = os.path.join(os.path.dirname('/usr/bin/ldd'),os.readlink('/usr/bin/ldd')) 1TP3Par exemple, '/lib/ld-musl-armhf.so.1' pour Alpine.
Troisième erreur
Erreur, 'chrpath' est nécessaire sur votre système, en raison des paramètres 'RPATH' dans le partage utilisé.
Fixe :
Avez-vous installé chrpath comme conseillé ci-dessus ?
apk add chrpath
C'est tout - maintenant nuitka devrait accomplir sa magie sans accroc. Je vais envoyer à l'auteur de nuitka les correctifs et cet article de blog, il pourra peut-être les inclure dans nuitka.
Version d'usine
Mise à jour 2.2.2019 : L'auteur de Nuitka a ajouté mes correctifs (sous une forme légèrement modifiée). Dans la version actuelle "factory", la compilation -standalone fonctionne pour moi. Veuillez vous référer à cette page github pour plus de détails :