Installare e usare librerie esterne in semplice programma

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3788
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Installare e usare librerie esterne in semplice programma

Messaggio da joe »

Sono alle prese con un programmino che in sintesi deve estrarre degli array da un file CSV e uno dei campi è composto da "data e ora". Questo campo và "trattato" aggiungendo le "date e ore mancanti" ecc ecc... Insomma mi serviva un sistema comodo per gestire facilmente la data e ora in modo che fosse possibile anche incrementare il valore a step di un ora...

Ho provato prima con bash. Fattibile grazie al comando "date", un po' contorto e da trattarsi con attenzione, meglio sempre far finta che i tempi siano in UTC. Purtroppo è parecchio lento.
Ho provato con python importando datetime e roba del genere. Mi è sembrato facile e molto rapido.. davvero molto rapido per essere un linguaggio interpretato.

Per diversi motivi mi verrebbe meglio ottenere la stessa cosa in Fortran.
Per ora non ho ancora capito bene come estrarre i campi di un CSV in modo efficiente. Ma per la gestione della data e ora esiste una libreria chiamata Flibs che contiene diversi moduli utilizzabili nei propri programmi e in particolare c'è libdate:
http://flibs.sourceforge.net/libdate.html

Non sono qui a chiedere consigli sulla programmazione, piuttosto sulla gestione di librerie del genere.
Mi è stato consigliato ad esempio di usare "libdate" come segue:

Codice: Seleziona tutto

main.f90:                                                                                                                                                      
program justademo                                                                                                                                              
    use libdate                                                                                                                                                
                                                                                                                                                               
    type(datetype) :: date
                                                                                                                                                               
    date = datetype( 2008, 1, 1, 0, 0 ) ! 1 january 2008, 0:00)

    write(*,*) 'Day of the year: ', doy(date)
end program justademo

Codice: Seleziona tutto

gfortran -o justademo libdate.f90 main.f90
Ma questo implica prendere il pacchetto di Flibs, estrarre libdate.f90, piazzarlo da qualche parte, e compilare grosso modo come indicato sopra.
Non ci sarebbe secondo voi un modo più conveniente di installare completamente Flibs sul sistema per poter poi richiamare le librerie che servono in modo più "diretto"...
Ad esempio ho visto che in python basta un:

Codice: Seleziona tutto

from datetime import timedelta, datetime
e così si possono usare le funzioni timedelta e datetime.
Quello che conta è che non devo indicare all'interprete dov'è piazzata la libreria "timedate" sul sistema.

In fortran la cosa è analoga nell'uso della libraria:

Codice: Seleziona tutto

use libdate
Il problema è che in fase di compilazione bisogna dare immagino il percorso assoluto della libreria, e non è molto comodo.

Purtroppo non ho trovato uno slackbuild o un pacchetto salckware per Flibs. Probabilmente mi avrebbe risolto il problema.
Al di là del linguaggio, penso che la cosa sia comune anche ad altri linguaggi compilati.

Mi date qualche consiglio su come eventualmente installare flibs?
Anche crearne un pacchetto non sarebbe male.

Graie in anticipo!

Avatar utente
conraid
Staff
Staff
Messaggi: 13630
Iscritto il: gio 14 lug 2005, 0:00
Nome Cognome: Corrado Franco
Slackware: current64
Desktop: kde
Località: Livorno
Contatta:

Re: Installare e usare librerie esterne in semplice programm

Messaggio da conraid »

Non devi farlo perché la libreria è in qualche path di sistema. Cioè se tu installi una libreria in /usr/lib (o lib64) la trovi, se fosse in /home/pippo/lib dovresti dire dove si trova. Tramite configure, cflags, etc... i modi sono diversi.
Naturalmente parlo in generale, non conosco fortran.

Quindi secondo me dovresti cercare il percorso delle librerie fortran (quelle di python sono in /usr/lib64/python2.7/ per es. in current) e installarla lì.

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3788
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Installare e usare librerie esterne in semplice programm

Messaggio da joe »

Cercando in rete non vedo però "standard path" per librerie fortran...
Ho trovato solo qualche "idea" dove si spiega che è meglio non metterle in /usr/lib perchè lì ci sono quelle per programmi in C (in gran parte roba di sistema insomma, da non mescolare). E lì si consigliava ad esempio /usr/local/lib/fortran... Su slackware avrebbe più senso forse "/usr/lib/fortran".
Mi sarei aspettato però qualcosa di più standardizzato, programmare in C, python, ecc da questo punto di vista è molto più comodo e soprattutto "popolare".

Avatar utente
conraid
Staff
Staff
Messaggi: 13630
Iscritto il: gio 14 lug 2005, 0:00
Nome Cognome: Corrado Franco
Slackware: current64
Desktop: kde
Località: Livorno
Contatta:

Re: Installare e usare librerie esterne in semplice programm

Messaggio da conraid »

Va beh, ma devi anche vedere come è configurato il sistema. E se poi sono librerie compilate, include, etc...

In C se è in /usr/include basta che fai "include pippolib.h", se invece è in /usr/inlude/pippo allora "include pippo/pippolib.h e le librerie per la compilazione le cerca nei path definiti in "/etc/ld.so.conf". Essendo il compilatore fortrand della suite gnu probabilmente fa la stessa cosa, dovresti fare prove. Al limite ti crea dei path personali e li aggiunti nel file /etc/ld.so.conf

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3788
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Installare e usare librerie esterne in semplice programm

Messaggio da joe »

Ho fatto qualche ricerca e qualche prova, e pare che il percorso in cui piazzare il nostro "modulo" esterno sia:

Codice: Seleziona tutto

/usr/lib/gcc/i486-slackware-linux/4.7.1/finclude/
Da quanto ho detto nel mio primo post e da quanto ho letto in giro... Sembrerebbe che il mio esempietto in cima dovrebbe funzionare come segue.
Poniamo di avere ad esempio:

Codice: Seleziona tutto

[root@darkstar finclude]# ls
libdate.f90  libdate.mod  libdate.o  omp_lib.f90  omp_lib.h  omp_lib.mod  omp_lib_kinds.mod
come vedete c'è "libdate.f90" (il sorgente del modulo richiamato dal mio programmino con la direttiva "use libdate").
Poi ci sono anche:
libdate.mod
libdate.o

Li ho ottenuti compilando ilmodulo con l'opzione "-c".

Codice: Seleziona tutto

gfortran -c libdate.f90
Ora immaginiamo di trovarci in una dir di lavoro a caso, ad esempio "~/tmp/fortran-test", in cui abbiamo creato il programmino in cima che richiama al suo interno il modulo "libdate" (presente e "precompilato" nella dir vista prima "finclude").
Lo scopo è compilare il programmino con successo e ottenere un eseguibile funzionante.
A leggere queste righe:
When compiling a Fortran source code that contains modules, a .mod (typically the name of the file is the same as the module name) file is created along with the object file. The .mod file should be in the same directory as the source file that is using that module, or it should be pointed to at compilation time using -I flag:

gfortran -c bar.f90
gfortran -c foo.f90 -I$PATH_TO_MOD_FILE
gfortran -o foo.exe foo.o bar.o
Note that .mod needs to exist at the foo.f90 compilation time.
In pratica nel mio esempio sopra il modulo l'ho già compilato nella dir di sistema "finclude". E la compilazione ha dato vita a il file ".mod" e il file oggetto ".o".
Siccome la directory in cui sta il modulo compilato è "finclude", buone notizie: non serve lo switch "-I", il percorso è riconosciuto. E quindi quando vado a creare il file oggetto per il mio programmino "main.f90", viene creato senza problemi un "main.o".
Il problema è che nella dir di lavoro ho solo i files:

Codice: Seleziona tutto

main.f90
main.o
Non c'è alcun file oggetto del modulo libdate.o che invece giustamente si trova nella dir di sistema "finlcude".
Se tentassi di creare l'eseguibile col solo main.o ecco cosa salterebbe fuori:

Codice: Seleziona tutto

gfortran -o main.bin main.o
main.o: nella funzione "MAIN__":
main.f90:(.text+0x9d): riferimento non definito a "__libdate_MOD_doy"
collect2: error: ld returned 1 exit status
A quanto pare insomma, almeno il file oggetto libdate.o deve essere richiamato esplicitamente...

Codice: Seleziona tutto

$ gfortran -o main.bin main.o /usr/lib/gcc/i486-slackware-linux/4.7.1/finclude/libdate.o 
$ lls
main.bin*
main.f90
main.o
Ma è davvero scomodo...
A quel punto tanto vale compilare tutto direttamente col sorgente del modulo:

Codice: Seleziona tutto

$ gfortran -o main.bin main.f90 /usr/lib/gcc/i486-slackware-linux/4.7.1/finclude/libdate.f90
Qualche vostro commento mi aiuterebbe a capire come sia meglio gestire questa roba.
Per ora ho sempre avuto a che fare con programmi che non richiamavano librerie esterne... roba tutto sommato semplice dal punto di vista della gestione sul sistema.
Adesso però vorrei sfruttare anche librerie già pronte, per non reinventare la ruota e concentrarmi su altri aspetti.
Se avete qualche consiglio è il benvenuto.

Grazie intanto conraid per le risposte.

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3788
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Installare e usare librerie esterne in semplice programm

Messaggio da joe »

Grazie a qualche consiglio, esempi in rete e qualche test sono riuscito a capire come funziona il meccanismo.
Poniamo di avere creato una directory di sistema che contiene i moduli fortran esterni precompilati, nell'esempio il modulo "libdate".

Codice: Seleziona tutto

# pwd
/usr/lib/fortran
# ls
libdate.f90
# gfortran -c libdate.f90 
# ls
libdate.f90  libdate.mod  libdate.o
Poniamo poi di avere scritto il nostro programmino di test. "main.f90" che richiama il modulo "libdate". Vedi primo post.
È possibile compilare il nostro programmino creando un file oggetto "main.o" e quindi creare l'eseguibile finale, eseguendo il "linking" del nostro "main.o" con "libdate.o".

Per il Il primo step è richiesto che il file "libdate.mod" sia in una directory appartenente a una serie di percorsi di sistema dove gfortran cerca automaticamente. Altrimenti ecco cosa succede:

Codice: Seleziona tutto

$ gfortran -c main.f90
main.f90:2.8:

    use libdate
        1
Fatal Error: Can't open module file 'libdate.mod' for reading at (1): File o directory non esistente
Questo errore sarebbe risolvibile se riuscissi a capire come si aggiunge il mio percorso "/usr/lib/fortran" alle directory in cui gfortran cerca i file ".mod".
In questo senso ho provato ad aggiungere il path a ld.so.conf, ma senza successo visto l'errore sopra:

Codice: Seleziona tutto

# cat /etc/ld.so.conf 
/usr/local/lib
/usr/i486-slackware-linux/lib
/usr/lib/seamonkey
/usr/lib/fortran
Ad ogni modo, se il nostro file .mod e il nostro file oggetto non sono in un path riconosciuto da gfortran, possiamo indicarglielo esplicitamente con l'opzione "-I/path/to/dot-mod/files" (i-maiuscolo).

Codice: Seleziona tutto

$ gfortran -c main.f90 -I /usr/lib/fortran/
$ ls
main.f90 main.o
A questo punto abbiamo creato il file oggetto per il nostro programmino. E ora bisogna linkarlo al file oggetto del modulo "libdate". In teoria si potrebbe fare così:

Codice: Seleziona tutto

$ gfortran main.o -l libdate
/usr/lib/gcc/i486-slackware-linux/4.7.1/../../../../i486-slackware-linux/bin/ld: impossibile trovare -llibdate
collect2: error: ld returned 1 exit status
L'opzione "-l" specifica che gfortran deve cercare nelle directory del suo path e linkare il nostro oggetto a libdate.o ...
In realtà non funziona proprio così... perchè il nome "libdate.o" non viene riconosciuto da gfortran/ld.
Inoltre il nostro libdate non sta in un path riconosciuto da gfortran. Ed ecco che dà errore.

L'opzione "-L" ci dà la possibilità di specificare il percorso in cui cercare il file oggetto o la libreira a cui linkare il nostro file oggetto. Così risolviamo un problema.

Codice: Seleziona tutto

$ gfortran main.o -llibdate -L /usr/lib/fortran
/usr/lib/gcc/i486-slackware-linux/4.7.1/../../../../i486-slackware-linux/bin/ld: impossibile trovare -llibdate
collect2: error: ld returned 1 exit status
L'errore persiste per via del nome libdate.o, dobbiamo cambiarlo a mano (che io sappia).
Infatti ld riconosce la libreria richiamata con l'opzione "-lLIBRARY" se il file di libreria si chiama "libLIBRARY.so" o "libLIBRARY.a". IN pratica vuole il prefisso "lib" e l'estensione "so" oppure "a".

Codice: Seleziona tutto

# mv libdate.o liblibdate.so
Ok, questo passaggio andrebbe fatto in fase di installazione sul sistema del pacchetto di moduli esterni. Il nome "liblibdate.so" non è dei più felici, ma altrimenti non saprei come farlo digerire al linker "ld". Certo si potrebbe rinominare libdate.so e richiamare con '-ldate'. Ma non è corretto per poi il modulo "libdate.mod" sarebbe da nominare coerentemente date.mod ecc ecc... insomma l'autore di libdate l'ha chiamato così e mi pare giusto rispettare la scelta.

In definitiva con questa modifica il comando precedente funge e il nostro eseguibile "a.out" viene finalmente creato:

Codice: Seleziona tutto

$ gfortran main.o -llibdate -L /usr/lib/fortran
$ ls
a.out  main.f90  main.o
Se avete idea di cosa si debba modificare per indurre gfortran a cercare le librerie o i files oggetto, ma anche i files .mod nel path di esempio "/usr/lib/fortran", sarebbe molto utile, perchè così si può eliminare, sia l'opzione "-L/path/" che l'opzione "-I/path/".
Immagino che ci sia di mezzo un file di configurazione oppure una variabile d'ambiente... Avete suggerimenti?

Avatar utente
brg
Linux 3.x
Linux 3.x
Messaggi: 580
Iscritto il: sab 12 mar 2011, 14:20
Slackware: 15.0
Kernel: 5.15.117
Desktop: KDE5
Località: Montecatini
Contatta:

Re: Installare e usare librerie esterne in semplice programm

Messaggio da brg »

Per compilare una libreria condivisa (.so: shared object) invece che un semplice oggetto compilato (.o), bisogna aggiungere l'opzione -shared alla riga di comando di gcc:

Codice: Seleziona tutto

gcc -shared -o libcoso.so libcoso.c
Le directory delle librerie condivise sono elencate dalla variabile di sistema LD_LIBRARY_PATH:

Codice: Seleziona tutto

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mia/directory

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3788
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Installare e usare librerie esterne in semplice programm

Messaggio da joe »

Quindi forse aggiungendo il path "/usr/lib/fortran" alla variabile LD_LIBRARY_PATH dovrebbe non essere più necessario l'impiego delle opzioni "-I" ed "-L"...
Ho provato e di seguito riporto cosa succede a terminale...

Codice: Seleziona tutto

$ echo $LD_LIBRARY_PATH


$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/fortran/

$ echo $LD_LIBRARY_PATH
:/usr/lib/fortran/

$ gfortran -c main.f90
main.f90:2.8:

    use libdate
        1
Fatal Error: Can't open module file 'libdate.mod' for reading at (1): File o directory non esistente

$ gfortran -shared main.f90
main.f90:2.8:

    use libdate
        1
Fatal Error: Can't open module file 'libdate.mod' for reading at (1): File o directory non esistente

$ gfortran -c -shared main.f90
main.f90:2.8:

    use libdate
        1
Fatal Error: Can't open module file 'libdate.mod' for reading at (1): File o directory non esistente
In sintesi, sul mio sistema la variabile d'ambiente LD_LIBRARY_PATH non contiene alcuna directory.
Pur aggiungendovi "/usr/lib/fortran", la creazione del file oggetto già fallisce...

Ci deve essere anche qualche altro intoppo. Non credi?
Oppure ho capito male...

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3788
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Installare e usare librerie esterne in semplice programm

Messaggio da joe »

La variabile d'ambiente LD_LIBRARY_PATH funziona solo per il linking, quindi si ottiene l'eseguibile a.out col comando seguente:

Codice: Seleziona tutto

gfortran main.o -llibdate
Invece continua a non funzionare la creazione del file oggetto.

Guardando il manuale di gcc, invece che quello di gfortran, ecco cosa si legge
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
OBJC_INCLUDE_PATH
Each variable's value is a list of directories separated by a special character, much like PATH, in which to look for header files.
The special character, "PATH_SEPARATOR", is target-dependent and determined at GCC build time. For Microsoft Windows-based targets
it is a semicolon, and for almost all other targets it is a colon.

CPATH specifies a list of directories to be searched as if specified with -I, but after any paths given with -I options on the
command line. This environment variable is used regardless of which language is being preprocessed.

The remaining environment variables apply only when preprocessing the particular language indicated. Each specifies a list of
directories to be searched as if specified with -isystem, but after any paths given with -isystem options on the command line.

In all these variables, an empty element instructs the compiler to search its current working directory. Empty elements can appear
at the beginning or end of a path. For instance, if the value of CPATH is ":/special/include", that has the same effect as
-I. -I/special/include.
Quindi in teoria settando CPATH aggiungendovi /usr/lib/fortran, sarebbe come passare l'opzione "-I/usr/lib/fortran".

Codice: Seleziona tutto

$ CPATH="/usr/lib/fortran/:$CPATH"

$ export CPATH

$ env|grep CPATH
CPATH=/usr/lib/fortran/:

$ gfortran -c main.f90
main.f90:2.8:

    use libdate
        1
Fatal Error: Can't open module file 'libdate.mod' for reading at (1): File o directory non esistente
Insomma, nonostante a $CPATH sia correttamente aggiunto il percorso in cui sta il file "libdate.mod" necessario per la creazione dell'oggetto "main.o", la compilazione non và a buon fine perchè gfortran non riesce a trovarlo. Come visto, con l'opzione "-I" esplicita invece funziona.

hashbang
Packager
Packager
Messaggi: 2020
Iscritto il: ven 4 giu 2010, 10:27
Nome Cognome: Luca De Pandis
Distribuzione: macOS/OpenBSD
Località: Lecce/Bergamo

Re: Installare e usare librerie esterne in semplice programm

Messaggio da hashbang »

joe ha scritto:L'opzione "-l" specifica che gfortran deve cercare nelle directory del suo path e linkare il nostro oggetto a libdate.o ...
In realtà non funziona proprio così... perchè il nome "libdate.o" non viene riconosciuto da gfortran/ld.
Inoltre il nostro libdate non sta in un path riconosciuto da gfortran. Ed ecco che dà errore.

L'opzione "-L" ci dà la possibilità di specificare il percorso in cui cercare il file oggetto o la libreira a cui linkare il nostro file oggetto. Così risolviamo un problema.

Codice: Seleziona tutto

$ gfortran main.o -llibdate -L /usr/lib/fortran
/usr/lib/gcc/i486-slackware-linux/4.7.1/../../../../i486-slackware-linux/bin/ld: impossibile trovare -llibdate
collect2: error: ld returned 1 exit status
L'errore persiste per via del nome libdate.o, dobbiamo cambiarlo a mano (che io sappia).
Infatti ld riconosce la libreria richiamata con l'opzione "-lLIBRARY" se il file di libreria si chiama "libLIBRARY.so" o "libLIBRARY.a". IN pratica vuole il prefisso "lib" e l'estensione "so" oppure "a".
Non devi modificarlo a mano, perché quello che tu hai, libdate.o, non è un binario eseguibile ma solo un codice oggetto.
La differenza sta nel fatto che il binario eseguibile è formato dal codice oggetto + le funzioni che derivano dalle librerie di sistema usate, che sono poi quelle che vedi quando usi ldd.

Come ottieni un binario eseguibile? Tramite il linking.
In sostanza tu non hai finito di compilare libdate. Hai solo completato il primo stadio.
Se vuoi creare una libreria condivisa, brg ti ha già dato il comando da usare.
Se devi crearne una statica, allora devi creare un archivio con GNU ar.

Codice: Seleziona tutto

$ ar -rv libdate.a *.o
$ ranlib libdate.a
joe ha scritto:In sintesi, sul mio sistema la variabile d'ambiente LD_LIBRARY_PATH non contiene alcuna directory.
Pur aggiungendovi "/usr/lib/fortran", la creazione del file oggetto già fallisce...

Ci deve essere anche qualche altro intoppo. Non credi?
Oppure ho capito male...
LD_LIBRARY_PATH non è una variabile d'ambiente del linker, ma del loader ld-linux.so, ovvero il programma che si occupa di interpretare i binari del sistema ed eseguirli.

Questo vuol dire che il fatto che la modifica di LD_LIBRARY_PATH non abbia inficiato sulla compilazione è del tutto normale. Non serve per quello. Sarebbe stato assurdo il contrario.

-L è un paramentro del linker, GNU ld, che indica dove andare a prendere una libreria binaria contenente le funzioni usate nel programma che stai compilando.
-I è un paramentro del compilatore, quindi gcc in questo caso, che indica dove deve prendere gli header che definiscono le funzioni usate nel programma.

In sostanza, un header altro non è che una forma non binaria della libreria che trovi in /usr/lib{,64}.
In fase di compilazione gcc prende l'header che contiene solitamente dei prototipi di funzione, in modo da non far fallire la compilazione per il fatto che alcune funzioni che stai usando nel tuo codice non sono state definite nel *tuo* programma.
Mentre in fase di linking, lui va a pescare la libreria corrispondente che contiene quelle funzioni, in modo da renderlo usabile in fase di esecuzione.


In sostanza, la command line dovrebbe essere qualcosa tipo (non conosco fortran, quindi mi limito al man):

Codice: Seleziona tutto

$ gfortran -o miobinario -I/solo/il/path/di/libdate.mod -L/solo/il/path/di/libdate.{so,a} -ldate main.f90

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3788
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Installare e usare librerie esterne in semplice programm

Messaggio da joe »

Grazie per le precisazioni.
Il comando finale già era chiaro e funzionante. Forse non hai letto i post precedenti.

La domanda banalmente è: "come fare per evitare di dover passare i flag -I ed -L".

La risposta che sono riuscito a trovare per ora risolve solo metà della procedura, ovvero il linking:

Codice: Seleziona tutto

export LD_LIBRARY_PATH=/usr/lib/fortran:$LD_LIBRARY_FLAG
Impostando quella roba lì si può omettere il flag "-L".

Resta da capire come poter omettere anche il flag "-I".

Stando al manuale di gcc, dovrebbe essere la variabile CPATH, ma dal mio test "gfortran" ignora quella variabile e vuole ancora il flag "-I".

hashbang
Packager
Packager
Messaggi: 2020
Iscritto il: ven 4 giu 2010, 10:27
Nome Cognome: Luca De Pandis
Distribuzione: macOS/OpenBSD
Località: Lecce/Bergamo

Re: Installare e usare librerie esterne in semplice programm

Messaggio da hashbang »

joe ha scritto:La risposta che sono riuscito a trovare per ora risolve solo metà della procedura, ovvero il linking:

Codice: Seleziona tutto

export LD_LIBRARY_PATH=/usr/lib/fortran:$LD_LIBRARY_FLAG
Impostando quella roba lì si può omettere il flag "-L".
No, non si omette nulla perché quello che stai facendo è sbagliato, joe.

LD_LIBRARY_PATH è una variabile d'ambiente per il runtime, non per il linktime.
-L e LD_LIBRARY_PATH non sono equivalenti.

Il fatto che LD_LIBRARY_PATH stia condizionando il linker lo spiega benissimo il man di GNU ld:
man di GNU ld ha scritto: -rpath-link=dir
When using ELF or SunOS, one shared library may require another. This happens when an "ld -shared" link includes a shared library as one of the input files.

When the linker encounters such a dependency when doing a non-shared, non-relocatable link, it will automatically try to locate the required shared library and
include it in the link, if it is not included explicitly. In such a case, the -rpath-link option specifies the first set of directories to search. The
-rpath-link option may specify a sequence of directory names either by specifying a list of names separated by colons, or by appearing multiple times.

This option should be used with caution as it overrides the search path that may have been hard compiled into a shared library. In such a case it is possible to
use unintentionally a different search path than the runtime linker would do.
[...]
5. For a native linker, search the contents of the environment variable "LD_LIBRARY_PATH".
[...]
If the required shared library is not found, the linker will issue a warning and continue with the link.
man di ld.so ha scritto:LD_LIBRARY_PATH
A list of directories in which to search for ELF libraries at execution-time. The items in the list are separated by either colons or semicolons. Similar to
the PATH environment variable. This variable is ignored in secure-execution mode.
In sostanza il fatto che nel tuo caso LD_LIBRARY_PATH alteri anche il comportamento del linker è solo un effetto collaterale.
Il che vuol dire che non è un comportamento da adottare generalmente; e se non lo adottassi nemmeno adesso sarebbe meglio.
Non bisogna fare affidamento su LD_LIBRARY_PATH per scopi che sono fuori dall'idea per la quale è nata. E anzi non bisognerebbe fare affidamento su questa variabile a prescindere, se non in casi strettamente necessari.
Resta da capire come poter omettere anche il flag "-I".
Se vuoi omettere quelle flag dalla tua linea di comando hai due opzioni:
  • usa un build system, come ad esempio un Makefile;
  • metti i binari e gli header nei path standard.
Solo così potrai compilare in maniera sicura senza dover specificare manualmente dove prendere le funzioni necessarie.

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3788
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Installare e usare librerie esterne in semplice programm

Messaggio da joe »

Ok, ho capito...

Mi piace più dl'idea del makefile, anche se non ne so nulla...

Visto che sei ferrato in materia, quali diamine sono i "path standard" in cui piazzare moduli fortran ".mod" e i file oggetto ".o"?

PS.
che poi da quel che ho capito non mi piace come idea perchè il moduli .mod sono creati con una compilazione, correggi pure se non sono preciso nei termini, e questa compilazione dipende dal compilatore. Mentre per il c gli headres sono più standard, per il fortran ogni compilatore digerisce bene solo i moduli precompilati da lui stesso. Ad esempio se ho preparato il mio set di moduli e oggetti associati con gfortran e poi li voglio usare in un programma che compilarò con un altro compilatore ad esempio ifort, ecco che potrebbero esserci problemi.
Per questo alla fine sarebbe più sicuro avere un modo per compilare anche il modulo al volo.
Un modo c'è, vedi primo post se non ricordo male, ed è quello di compilare richiamando direttamente i file sorgenti dei moduli coinvolti.

Codice: Seleziona tutto

gfortran /path/to/modulo1.f90 /path/to/modulo2.f90 mioprogramma.f90
In questo modo non servono più file oggetto precompilati e file .mod.
Sarebbe interessante (o forse è solo una mia impressione strampalata) se gfortran cercasse "i sorgenti" dei moduli richiamati in qualche directory impostata o in qualche variabile d'ambiente o in qualche file di configurazione. In quel modo basterebbe prendere i sorgenti dei moduli e piazzarli li... per poi richiamarli direttamente dal sorgente del programma (use nome_modulo).

Rispondi