2012-02-23 3 views
16

Sto scrivendo un piccolo programma in C che utilizza la libreria. Sono molto sorpreso che il programma non verrà compilato se ho posto la bandiera di collegamento all'inizio invece che alla fine:Perché talvolta il flag del linker della libreria deve essere utilizzato con GCC?

Al momento, per compilare il programma che faccio:

gcc -o prog prog.c -lrt -std=gnu99

Se dovessi fare quanto segue, si riescono a trovare le funzioni in librt:

gcc -std=gnu99 -lrt -o prog prog.c

Eppure, questo funziona con altre biblioteche. Ho trovato il problema quando si tenta di utilizzare un Makefile semplice. fare prog.c compilato in realtà senza piacere prima (usando flag -c) e poi fatto il collegamento.

Questo è il Makefile:

CC = gcc 

CFLAGS = -std=gnu99 

LIBS= -lrt 

LDFLAGS := -lrt 


prog: prog.o 

     $(CC) -o prog prog.c -lrt -std=gnu99 

L'uscita avrei ricevuto durante la digitazione di fare sarebbe:

gcc -std=gnu99 -c -o prog.o prog.c 
gcc -lrt prog.o -o prog 
prog.o: In function `main': 
prog.c:(.text+0xe6): undefined reference to `clock_gettime' 
prog.c:(.text+0x2fc): undefined reference to `clock_gettime' 
collect2: ld returned 1 exit status 
make: *** [buff] Error 1 

mi hanno ormai creato una Makefile che mette il collegamento alla fine del gcc linea, tuttavia sono perplesso perché non funziona se il flag di collegamento è all'inizio.

Gradirei se qualcuno me lo spiegasse. Grazie.

+1

Non sono al 100% su questo, ma penso che il linker potrebbe guardare la libreria e decidere che non ha bisogno di nulla, quindi basta buttarlo via. Librt è una libreria statica? – spencercw

+0

Vedere le risposte a questa domanda per una spiegazione del perché il collegamento statico dipende dall'ordine: http: //stackoverflow.com/questions/45135/linker-order-gcc –

+2

potrebbe essere correlato all'opzione * del necessario * del linker in uso per impostazione predefinita. Si potrebbe provare 'gcc -std = gnu99 -Wl, -no-as-needed -lrt -o prog prog.c' –

risposta

19

Poiché il linker elabora ogni modulo (sia esso una libreria o un file oggetto), tenta di risolvere ogni simbolo indefinito mentre potenzialmente aggiunge alla sua lista di simboli non definiti. Quando arriva alla lista dei moduli, ha risolto tutti i simboli non definiti e ha successo oppure riporta simboli non definiti.

Nel vostro caso, quando ha elaborato la libreria, non aveva simboli indefiniti. L'elaborazione proc ha comportato che clock_gettime fosse un simbolo non definito. gcc non tornerà indietro e guarderà in biblioteca i simboli non definiti.

Per questo motivo, è necessario avere sempre il codice, seguito dalle librerie, seguito dalle librerie fornite dalla piattaforma.

Spero che questo aiuti.

+1

Nota secondaria: l'ordine di i file oggetto non sono importanti; un file oggetto che fa riferimento a un simbolo in un altro file oggetto non deve necessariamente venire prima di esso sulla riga di comando. Il che ha senso, ovviamente, se si considera che tutti i simboli di un file oggetto vengono inclusi nell'immagine finale, anche se non c'è ancora un riferimento non definito, e quindi vengono aggiunti all'elenco dei simboli definiti, quindi un riferimento successivo in un altro file oggetto non porterà a un simbolo indefinito. – eriktous

+0

@eriktous Grazie per la correzione. – Lou

11

Dalla documentazione ld (il linker GNU) (http://sourceware.org/binutils/docs/ld/Options.html#Options):

Il linker cercherà un archivio solo una volta, nel punto in cui è specificato nella riga di comando. Se l'archivio definisce un simbolo che non era definito in qualche oggetto che appariva prima dell'archivio sulla riga di comando, il linker includerà i file appropriati dall'archivio. Tuttavia, un simbolo indefinito in un oggetto che appare in seguito sulla riga di comando non farà in modo che il linker cerchi di nuovo nell'archivio.

Quindi se si specifica la libreria troppo presto, il linker lo scansionerà, ma non troverà nulla di interessante. Quindi il linker passa al file oggetto prodotto dal compilatore e trova i riferimenti che devono essere risolti, ma ha già scansionato la libreria e non si preoccuperà di guardarlo di nuovo.