Usare il compilatore nuitka per python3 su Alpine Linux ARMHF (musl)
Motivazione
pidoctor è scritto in Python (poiché non c'era un modo semplice per far funzionare Crystal su ARMHF / musl).
Questo significa una dipendenza da Python - che aggiunge overhead.
Sospetto che questo overhead sia la ragione per cui pidoctor non funziona su Raspberry Pi da 256 MB - perché la RAM è esaurita da tutti i pacchetti richiesti.
Inoltre, è auspicabile che la distribuzione sia il più piccolo download possibile! Questo significa che Python deve essere rimosso dall'equazione in qualche modo, il pacchetto dovrebbe produrre un binario (come sarebbe il modo con Crystal).
Per fortuna, c'è la nuitka.
E - per tua fortuna - ho risolto alcuni problemi di utilizzo di nuitka su Alpine Linux, ARMHF (forse funzionerà anche per x86).
Nuitka
nuitka è un fantastico software che prende uno script Python e lo compila in un eseguibile, velocizzandolo drasticamente.
nuitka fa tutto il lavoro pesante, non hai nemmeno bisogno di aggiustare qualcosa nel tuo codice sorgente (mi sembra). Puoi eseguirlo in questo modo:
python3 -m nuitka -follow-imports -standalone pidoctor.py
Notate il flag -standalone, che compilerà le librerie condivise necessarie nella vostra cartella .dist - quindi l'installazione sarà in grado di funzionare senza qualsiasi dipendenza su Python!
Nota: WordPress sfortunatamente incasina i doppi trattini e li trasforma in trattini singoli. la -m ha un trattino singolo, la -follow-imports e la -standalone hanno doppi trattini.
Installazione di Nuitka su Alpine Linux (in particolare arhmf, potrebbe funzionare su altri obiettivi)
apk add python3-dev
apk aggiungere chrpath
pip3 install -U nuitka
opzionalmente, se si sta eseguendo in modalità senza disco (per aggiungere nuitka ai file che dovrebbero essere persistiti):
lbu add /usr/bin/nuitka3-run
lbu add /usr/bin/nuitka3
lbu add /usr/lib/python3.6/site-packages/nuitka
lbu commit -d
Nota: il sorgente di nuitka è in Python.
Controlla che nuitka funzioni:
python3 -m nuitka
dovrebbe eseguire senza mostrando eventuali errori di sintassi.
Fissare nuitka per funzionare con Alpine Linux armhf
Importante: WordPress purtroppo mastica male la sintassi. Si prega di fare riferimento al problema GitHUB che ho apertodove ho anche allegato i file della patch come riferimento.
nuitka chiama diverse utility binarie di supporto sul vostro sistema, e si aspetta che restituiscano i risultati in un certo modo. È qui che nuitka inizialmente inciampa.
Primo errore
pidoctor:/opt/pidoctor# python3 -m nuitka -follow-imports -standalone pidoctor.py
Traceback (ultima chiamata più recente):
File "/usr/lib/python3.6/site-packages/nuitka/__main__.py", linea 188, in
main()
File "/usr/lib/python3.6/site-packages/nuitka/__main__.py", linea 182, in main
MainControl.main()
File "/usr/lib/python3.6/site-packages/nuitka/MainControl.py", linea 846, in main
Plugins.considerExtraDlls(dist_dir, module)
File "/usr/lib/python3.6/site-packages/nuitka/plugins/Plugins.py", linea 102, in considerExtraDlls
per extra_dll in plugin.considerExtraDlls(dist_dir, module):
File "/usr/lib/python3.6/site-packages/nuitka/plugins/standard/ImplicitImports.py", linea 372, in considerExtraDlls
uuid_dll_path = locateDLL("uuid")
File "/usr/lib/python3.6/site-packages/nuitka/utils/SharedLibraries.py", linea 71, in locateDLL
return dll_map[dll_name]
KeyError: 'libuuid.so.1.3.0'
Motivo dell'errore: nuitka chiama ldconfig -p e si aspetta che elenchi una lista di librerie condivise nella cache, in un formato come questo:
libICE.so.6 (libc6, x86-64) => /usr/lib/x86_64-linux-gnu/libICE.so.6
su Alpine Linux, ldconfig -p fallisce - in quanto non esiste tale opzione. ldconfig su Alpine Linux è incapace di produrre una lista della forma che Nuitka vuole.
Correggere:
in /usr/lib/python3.6/site-packages/nuitka/utils/SharedLibraries.py
aggiungete il seguente codice subito dopo le dichiarazioni di importazione all'inizio:
def find_alpine(name,paths):
per percorso in percorsi:
per root, dirs, files in os.walk(path):
se il nome in file:
return os.path.join(root,name)
e in locateDLL, prima di importare il sottoprocesso, aggiungere il seguente codice:
se os.path.isfile('/etc/alpine-release'):
return find_alpine(dll_name,["/lib","/usr/lib","/usr/local/lib"])
altro:
importa subprocesso(...)
Il (...) sopra indica che il resto del codice di locateDLL dovrebbe essere rientrato sotto else.
Cosa fa questo codice: se il file /etc/alpine-release esiste - indicando che stiamo girando su Alpine Linux, cerchiamo la libreria condivisa in tre directory predefinite:
- /lib
- /usr/lib
- /usr/local/lib
e restituisce il primo file corrispondente. Nota, non gestiamo la situazione nel caso in cui il file non venga trovato - in questo caso non viene restituito nulla.
Secondo errore
Traceback (ultima chiamata più recente):
File "/usr/lib/python3.6/site-packages/nuitka/__main__.py", linea 188, in
main()
File "/usr/lib/python3.6/site-packages/nuitka/__main__.py", linea 182, in main
MainControl.main()
File "/usr/lib/python3.6/site-packages/nuitka/MainControl.py", linea 859, in main
standalone_entry_points = standalone_entry_points
File "/usr/lib/python3.6/site-packages/nuitka/freezer/Standalone.py", linea 1169, in copyUsedDLLs
used_dlls = detectUsedDLLs(source_dir, standalone_entry_points)
File "/usr/lib/python3.6/site-packages/nuitka/freezer/Standalone.py", linea 1062, in detectUsedDLLs
assert os.path.isabs(dll_filename), dll_filename
Errore di asserzione: ldd
Motivo dell'errore: nuitka chiama ldd con ogni libreria condivisa ("dll_filename") da aggiungere alla vostra cartella .dist. Lo scopo è quello di trovare le dipendenze di queste stesse librerie condivise. (Una ricerca ricorsiva, se volete).
Per esempio:
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)
Come vedete, libexpat.so.1 ha due dipendenze:
- libgcc_s.so.1 -> da trovare in /usr/lib/libgcc_s.so.1
- libc.musl-armhf.so.1 -> si trova a ldd
ed è proprio qui che nuitka ha problemi. Vuole copiare un file con un percorso assoluto, e invece gli viene dato il nome "ldd". Di nuovo, qualcosa che è specifico di Alpine Linux.
Perciò l'affermazione fallisce, e nuitka non continua.
Ecco come scoprire a quale file fa effettivamente riferimento:
pidoctor:~# che ldd
/usr/bin/lddpidoctor:~# ls -alh /usr/bin/ldd
lrwxrwxrwx 1 root 28 Jan 1 1970 /usr/bin/ldd -> ../../lib/ld-musl-armhf.so.1
Si noti che ../../lib/ld-musl-armhf.so.1 è un percorso relativo, che in realtà si riferisce a /lib/ld-musl-armhf.so.1 sul mio sistema. E probabilmente anche sul vostro.
Correggere:
ricerca di libutil.so. nel file /usr/lib/python3.6/site-packages/nuitka/freezer/Standalone.py
C'è una linea con result.add(filename) sotto di essa. Solo sopra questa linea, inserire:
se nome del file == 'ldd':
filename = os.path.join(os.path.dirname('/usr/bin/ldd'),os.readlink('/usr/bin/ldd')) #e.g. '/lib/ld-musl-armhf.so.1' fix per Alpine
Terzo errore
Errore, ha bisogno di 'chrpath' sul tuo sistema, a causa delle impostazioni 'RPATH' in usato condiviso
Correggere:
Hai installato chrpath come consigliato sopra?
apk aggiungere chrpath
Questo è tutto - ora nuitka dovrebbe eseguire la sua magia senza intoppi. Invierò all'autore di nuitka le patch e questo articolo del blog, forse potrà includerle in nuitka.
Versione di fabbrica
Aggiornamento 2.2.2019: l'autore di Nuitka ha aggiunto le mie patch (in una forma leggermente modificata). Nell'attuale versione "fabbrica", la compilazione -standalone funziona per me. Si prega di fare riferimento a questa pagina github per i dettagli: