2014-12-26 13 views
5

Ich mache eine Test-Setup einer C statischen Bibliothek und Programm. Der Bibliothekscode, in einem Unterverzeichnis 'foo' befindet sich meines Projekts, enthält die folgenden Dateien:Einschließlich Header-Datei aus der statischen Bibliothek

foo/foo.c:

#include <stdio.h> 
void foo(void) { 
    printf("something"); 
} 

foo/foo.h:

#ifndef foo_h__ 
#define foo_h__ 
extern void foo(void); 
#endif 

Mein Progamm-Code ist wie folgt:

test.c:

#include "foo.h" 
int main() { 
    foo(); 
    return 0; 
} 

Ich habe ein Build-Skript namens 'bauen', die enthält folgende Komponenten:

build:

#!/bin/bash 
gcc -c -Wall -Werror foo/foo.c 
ar rcs libfoo.a foo.o 
gcc -static -o test test.c libfoo.a # I have also tried -L. -lfoo 

Aber wenn ich bauen laufen, Es gibt mir den folgenden Fehler:

test.c:1:17: fatal error: foo.h: No such file or directory 
    #include "foo.h" 
       ^
Compilation terminated 

Es funktioniert jedoch, wenn ich die # include-Zeile weglasse, aber ich würde es vorziehen, wenn ich Header-Dateien in meinen statischen Bibliotheken verwenden könnte. Was mache ich falsch, und wie kann ich es beheben?

Antwort

18

Header werden nicht in Bibliotheken gespeichert. Header werden getrennt von Bibliotheken gespeichert. Bibliotheken enthalten Objektdateien; Header sind keine Objektdateien. Standardmäßig werden Standard-Header auf einem Unix-System in /usr/include gespeichert - normalerweise finden Sie zum Beispiel /usr/include/stdio.h und /usr/include/string.h und /usr/include/stdlib.h. Standardmäßig sind Bibliotheken in /usr/lib gespeichert (Sie finden jedoch auch einige in /lib). Oft sind Compiler so konfiguriert, dass sie auch an anderen Stellen suchen. Ein üblicher alternativer Speicherort ist unter /usr/local, also /usr/local/include für Header und /usr/local/lib für Bibliotheken. Beachten Sie auch, dass eine einzelne Bibliothek viele Header haben kann, die die Services definieren. Die Standardbibliothek ist ein Beispiel. Es hat die Funktionen, die denen entsprechen, die in <stdio.h>, <string.h>, <stdlib.h> und vielen anderen Überschriften auch gefunden werden.

auf den Code der Suche:

  1. Wenn Ihre Header-Datei in ./foo/foo.h ist, dann müssen Sie schreiben:

    #include "foo/foo.h" 
    

    Oder wenn Sie weiterhin #include "foo.h" verwenden, müssen Sie angeben, wo Um den Header in der Compilerbefehlszeile mit dem Argument zu finden:

    gcc -Ifoo -o test test.c -L. -lfoo 
    

    Ich habe bewusst die -static ausgeschlossen; Es ist nur notwendig, wenn Sie zwischen einer statischen und einer gemeinsam genutzten Bibliothek wählen können, aber Sie haben nur libfoo.a, also wird der Linker das sowieso verwenden.

    Beachten Sie, dass das Problem ein Kompilierungsfehler und kein Verknüpfungsfehler ist.Dies wäre klarer, wenn Sie das Programm Gebäude in zwei Schritte aufgeteilt: (1) erstellen test.o und (2) Link Programm:

    gcc -c -Ifoo test.c 
    gcc -o test test.o -L. -lfoo 
    
  2. Ihr Kopf Wache fehlerhaft ist. Sie hatten ursprünglich (aber haben die Frage aktualisiert, so dass diese Tippfehler nicht mehr vorhanden ist):

    #ifndef foo_h__ 
    #define foo_h_ 
    

    Sie benötigen:

    #ifndef foo_h__ 
    #define foo_h__ 
    

    Die Makronamen das gleiche in beiden Linien sein müssen. Beachten Sie, dass in diesem Fall der Rechtschreibfehler meistens harmlos ist - aber unter Mac OS X gab clang (Masquerading als gcc) eine Warnung darüber ab (obwohl ich es vor der Kompilierung entdeckt hatte). In einigen anderen Fällen würden Sie nicht den Schutz erhalten, den die Header-Wächter bieten sollen.

    ./foo/foo.h:1:9: warning: 'foo_h__' is used as a header guard here, followed by #define of a 
         different macro [-Wheader-guard] 
    #ifndef foo_h__ 
         ^~~~~~~ 
    ./foo/foo.h:2:9: note: 'foo_h_' is defined here; did you mean 'foo_h__'? 
    #define foo_h_ 
         ^~~~~~ 
         foo_h__ 
    1 warning generated. 
    

Sie könnten mit Recht fragen:

  • Wenn ich -Ifoo brauchen, wenn test.c kompilieren, warum war es nicht notwendig, wenn foo/foo.c Kompilieren?

Gute Frage!

  1. Es wäre die Erstellung von foo/foo.c
  2. GCC sucht Header in dem Verzeichnis, in dem der Quellcode der Übersetzungseinheit gefunden wird (also nicht verletzt haben, wenn foo/foo.c kompilieren, ist es für Header in foo Verzeichnis sieht enthalten wie #include "foo.h" ohnehin
  3. die Quelldatei foo/foo.c sollte foo.h zu enthalten hat;. ist es sehr wichtig, dass es funktioniert, wie das ist, wie die Compiler der Konsistenz zu gewährleisten die Querprüfung notwendig liefern Wenn Sie #include "foo.h" geschrieben hätten, wäre die Zusammenstellung arbeiten. als Beschreibung gerippt. Wenn Sie (in foo/foo.c) #include "foo/foo.h" geschrieben haben, dann hätte die Befehlszeile zum Erstellen foo.o-I. benötigt, damit die Kopfzeile gefunden werden konnte.
+0

Aber der Header foo.h ist Teil der Bibliothek libfoo.a, oder? Außerdem war das Header-Guard-Problem ein Tippfehler, als ich es auf stackoverflow eintippte, was ich tat, weil ich auf Windows-SSH in ein Ubuntu-System bin. –

+0

Nein. Eine Bibliothek enthält ausschließlich und nur Objektdateien. Header sind _nicht_ Objektdateien. Header sind nicht in Bibliotheken enthalten. (OK: Um absolut pedantisch korrekt zu sein, könnte man eine Header-Datei zu einer Bibliothek hinzufügen, aber der Compiler würde niemals in einer Bibliothek suchen - nur der Linker ('ld', normalerweise) sucht in Bibliotheken und sucht nur nach Objektdateien , nicht Kopfzeilen). –

+0

Oh, ok. Danke, dass du das erklärst. Warum kann ich dann beispielsweise "ncurses.h" aus der ncurses-Bibliothek hinzufügen? –

Verwandte Themen