Closed acsor closed 4 years ago
Prima di tutto grazie per la pull request, l'aggiunta di cmake
arricchisce molto l'esempio.
Detto questo, il problema che stai affrontando sembra essere particolarmente spinoso: mentre cercavo di approcciarmici ne sono emersi altri, non necessariamente collegati all'originale. Descrivo i due problemi che ho incontrato io per completezza.
Prima di tutto non sono riuscito a riprodurre l'errore indicato come causa del problema (error adding symbols: Bad value
). Generando i Makefile e provando a compilare il progetto il procedimento si ferma su una segnalazione diversa sulla mia macchina:
[100%] Linking C executable kernel
/usr/lib/cross-mipsel-linux-gnu/lib/gcc/mipsel-linux-gnu/9.2.0/../../../../mipsel-linux-gnu/bin/ld: cannot find crt1.o: No such file or directory
/usr/lib/cross-mipsel-linux-gnu/lib/gcc/mipsel-linux-gnu/9.2.0/../../../../mipsel-linux-gnu/bin/ld: cannot find crti.o: No such file or directory
/usr/lib/cross-mipsel-linux-gnu/lib/gcc/mipsel-linux-gnu/9.2.0/../../../../mipsel-linux-gnu/bin/ld: cannot find crtbegin.o: No such file or directory
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/kernel.dir/build.make:87: kernel] Error 1
make[2]: *** [CMakeFiles/Makefile2:139: CMakeFiles/kernel.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:173: CMakeFiles/kernel.core.umps.dir/rule] Error 2
make: *** [Makefile:157: kernel.core.umps] Error 2
Dal tipo di errore pare che il compilatore cerchi di linkare la stdlib (i vari crt*.o
che settano l'ambiente runtime di C), ma il progetto vuole essere standalone. Leggendo i log verbosi traspare che il flag -Wl,-nostdlib
e' effettivamente passato al compilatore (e quindi al linker), ma sembra non sortire alcun effetto.
La soluzione e' stata aggiungere lo stesso flag direttamente per gcc
, modificando la linea 14 di umps.cmake
:
set(LDFLAGS_UMPS "-nostdlib -Wl,-G,0,-nostdlib,-T,${LINK_SCRIPT}")
Aggiungendo il flag -nostdlib
ridondante la compilazione si conclude ma con un warning:
[100%] Linking C executable kernel
/usr/lib/cross-mipsel-linux-gnu/lib/gcc/mipsel-linux-gnu/9.2.0/../../../../mipsel-linux-gnu/bin/ld: libtermprint.a(termprint.c.obj): warning: linking abicalls files with non-abicalls files
[100%] Built target kernel
E aggiungendo la variabile VERBOSE=1
si vede che effettivamente termprint.c
e' compilato senza il flag -mno-abicalls
a differenza di tutti gli altri sorgenti (hello.c
):
[ 62%] Building C object CMakeFiles/termprint.dir/termprint.c.obj
/usr/bin/mipsel-linux-gnu-gcc -DTARGET_UMPS -I/home/maldus/Projects/pasticci/umps_uarm_hello_world/include -I/home/maldus/Projects/pasticci/umps_uarm_hello_world/umps -I/home/maldus/Projects/pasticci/umps_uarm_hello_world/umps/umps -ffreestanding -ansi -Wall -std=gnu90 -o CMakeFiles/termprint.dir/termprint.c.obj -c /home/maldus/Projects/pasticci/umps_uarm_hello_world/termprint.c
Non mi e' chiaro cosa questo warning comporti in pratica, perche' il programma finale gira su umps2 senza problemi.
L'unica differenza tra hello.c
e termprint.c
e' che il secondo e' indicato come libreria in umps.cmake
. La mia conoscenza di CMake e' limitata, per cui non so come specificare dei CFLAGS da usare anche per questa tipologia di file; ho risolto rimuovendo termprint
dalle librerie e aggiungendolo come dipendenza dell'eseguibile (righe 27 e 28 di umps.cmake
):
add_executable(kernel ${SRC}/hello.c ${SRC}/termprint.c)
target_link_libraries(kernel crtso libumps)
In questo modo la compilazione va a buon fine senza segnalazioni straordinarie.
Alternativamente, usando i flag -mabicalls
e -fPIC
il problema non si presenta (presumibilmente perche' sono il comportamento di default in assenza di specifiche, per cui librerie ed eseguibile vengono compilate comunque allo stesso modo).
Rimane il fatto che non sono riuscito a riprodurre il tuo errore. La motivazione piu' probabile e' nella differenza nella versione dei nostri compilatori: io ho la 9.2, mentre nei tuoi log vedo la 6. Per testare questa teoria ti chiederei di provare con una versione comune.
Per farlo dovresti compilare una toolchain usando ct-ng
come indicato nel README; dovrebbe risultare un mipsel-linux-gnu-gcc
versione 8.3.0 (o comunque qualcosa di piu' vicino).
Io sono riuscito a farlo e a compilare con successo il progetto con CMake. Per la toolchain ho usato la configurazione che allego (e' sostanzialmente mipsel-unknown-linux-gnu
senza tool di debug e senza supporto per c++, che non ci servono).
La compilazione di una toolchain puo' essere molto lunga, anche qualche ora (a seconda delle prestazioni della tua macchina). Provando con una toolchain piu' simile e vedendo cosa succede posso cercare di capire meglio la situazione.
In teoria avrei completato il setup da giorni, testandolo in locale (Fedora 31, o meglio crosstools-ng 1.24
, gcc 8.3.0
) e in laboratorio (Debian 9.9) dove ogni cosa è filata liscia ad eccezione del messaggio di warning. Sciaguratamente i compagni del mio gruppo, che montano Ubuntu 18.04 LTS e Linux Mint 19.3, ottengono una compilazione apparentemente priva di difetti, ma dei kernel panic
nell'esecuzione del codice.
Vorrei scaricarmi in locale, rapidamente magari con Docker, le versioni dei loro sistemi per controllare ed eventualmente sistemare. Se la cosa dovesse tirare per le lunghe mi limiterò a suggerire il setup proposto, specificando la non interoperabilità per uMPS (con uARM subìto nessuna anomalia finora).
La soluzione e' stata aggiungere lo stesso flag direttamente per gcc, modificando la linea 14 di umps.cmake:
Lo è stata nel suo caso come nel nostro. Pare fosse necessario, nella fase di linkaggio, passare -nostdlib
sia a gcc
che al linker successivamente, tramite -Wl
.
Rimane il fatto che non sono riuscito a riprodurre il tuo errore. La motivazione piu' probabile e' nella differenza nella versione dei nostri compilatori
Guardi, io all'inizio ne avevo uno a 64 bit (gcc-mips64-linux-gnu
) dalle repository di Fedora, ed è più probabile che l'errore dipendesse proprio da qualche incongruenza. Usare crosstools-ng
ha risolto, ora sono soltanto curioso del perché la compilazione non vada su Ubuntu e Mint.
Ho appena caricato le ultime modifiche al file README.md
. Purtroppo i problemi che ho evidenziato nell'ultimo aggiornamento persistono nelle distro dei miei compagni (ho difficoltà a metterci mano di presenza) ma li abbiamo superati installando le toolchain con crosstool-ng
. Confesso che alle volte ho dubitato sul fatto che le toolchain (fornite dalle distro) funzionassero come avrebbero dovuto.
Ho testato in locale (Fedora 31, toolchain uMPS installata con crosstool-ng
) e in laboratorio (Debian 9.9, toolchain di sistema) e tutto è filato liscio. Suggerisco di verificare il setup allo stato corrente e, in caso positivo, chiudere quest'issue.
Edit: testato con successo anche in Debian 10.3 con toolchain di sistema.
Ho finalmente avuto modo di testare la PR; anche sul mio sistema (Arch Linux) la compilazione e l'esecuzione dell'esempio si concludono con successo.
Testato con arm-none-eabi-gcc
versione 9.2.0 (per uARM) e mipsel-linux-gnu-gcc
versione 9.2.0 (per uMPS2).
Grazie per il contributo, procedo con il merge
I makefile di esempio nella repository (in particolare
umpsmake
) mostrano come ottenere gli eseguibili compilando singolarmente i file oggetto congcc
e linkandoli separatamente conld
. CMake possiede un modo diverso di compilare gli stessi, che consiste nell'invocare il solo compilatore (passando i flag utili al linker con-Wl
) ma che non funziona su uMPS.Obiettivo
Specificare l'insieme corretto di flag affinché il compilatore funzioni correttamente.
Problema
I seguenti passi dovrebbero generare
kernel.core.umps
ma producono un erroreCausa
Il compilatore segnala i seguenti messaggi
Tentativi
Si è cercato di sostituire i flag
-fno-abicalls fno-pic
con-fabicalls -fPIC
. Potrebbe essere una strada percorribile, ma per il momento si ottiene un diverso tipo di errore (sulle macchine di laboratorio)Suggerimenti
make VERBOSE=1 kernel.core.umps
umps.cmake
alle righe8
(flag compilatore) e14
(linker)Soluzioni alternative
È già noto un modo alternativo (poco idiomatico, prolisso e un po' difettoso) per compilare correttamente gli eseguibili uMPS, che in essenza imita letteralmente i comandi presenti in
umpsmake
. Funziona, ma mi piacerebbe migliorarlo (come fatto con uARM).