2014-12-26 7 views
5

Я делаю тестовую настройку статической библиотеки и программы C. Код библиотеки, расположенный в подкаталоге 'Foo' моего проекта, содержит следующие файлы:Включая файл заголовка из статической библиотеки

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 

Мой Progam код выглядит следующим образом:

test.c:

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

У меня есть сценарий сборки, под названием 'сборки', который содержит следующее:

сборки:

#!/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 

Но когда я бегу строить, это дает мне следующую ошибку:

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

Это делает, ho wever, работайте, когда я опускаю строку #include, но я бы предпочел, чтобы использовать заголовочные файлы в своих статических библиотеках. Что я делаю неправильно, и как я могу это исправить?

ответ

18

Заголовки не хранятся в библиотеках. Заголовки хранятся отдельно от библиотек. Библиотеки содержат объектные файлы; заголовки не являются объектными. По умолчанию стандартные заголовки в системе Unix хранятся в /usr/include. Например, вы обычно найдете /usr/include/stdio.h и /usr/include/string.h и /usr/include/stdlib.h. По умолчанию библиотеки хранятся в /usr/lib (но вы также можете найти их в /lib). Часто компиляторы также настроены на просмотр в некоторых других местах. Одно общее альтернативное место находится под /usr/local, поэтому /usr/local/include для заголовков и /usr/local/lib для библиотек. Обратите также внимание на то, что одна библиотека может иметь множество заголовков, определяющих сервисы. Примером может служить библиотека по умолчанию. Он имеет функции, соответствующие тем, которые содержатся в <stdio.h>, <string.h>, <stdlib.h> и многих других заголовках.

Глядя на ваш код:

  1. Если файл заголовка находится в ./foo/foo.h, то вам нужно написать:

    #include "foo/foo.h" 
    

    Или, если вы будете продолжать использовать #include "foo.h", необходимо указать, где для поиска заголовка в командной строке компилятора с аргументом:

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

    Я сознательно исключил -static; это необходимо только тогда, когда есть выбор между статикой и общей библиотекой, но у вас есть только libfoo.a, поэтому компоновщик будет использовать это в любом случае.

    Обратите внимание, что проблема связана с ошибкой компиляции, а не с ошибкой связывания.Это было бы понятнее, если вы разделяете здание программы на два этапа: (1) создать test.o и (2) Программа ссылка:

    gcc -c -Ifoo test.c 
    gcc -o test test.o -L. -lfoo 
    
  2. Ваш охранник заголовок неисправен. Вы изначально были (но не обновили этот вопрос, так это опечатка больше нет):

    #ifndef foo_h__ 
    #define foo_h_ 
    

    Понадобится:

    #ifndef foo_h__ 
    #define foo_h__ 
    

    Имена макросов должны быть одинаковыми в обеих линиях. Обратите внимание, что в этом случае орфографическая ошибка в основном безвредна, но в Mac OS X clang (маскарадный как gcc) действительно предупредил об этом (хотя я заметил это до того, как сделал какую-либо компиляцию). В некоторых других случаях вы не получите защиту, защищенную защитой заголовка.

    ./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. 
    

Вы можете законно задаться вопросом:

  • Если мне нужно -Ifoo при компиляции test.c, почему не было необходимым при составлении foo/foo.c?

Хороший вопрос!

  1. Это не повредило бы составление foo/foo.c
  2. GCC ищет заголовки в каталоге, где находится исходный код единицы перевода (так, при компиляции foo/foo.c, он смотрит в foo каталоге для заголовков, включенных а #include "foo.h" все равно
  3. исходный файл foo/foo.c должен был включать foo.h тоже,., очень важно, что он делает, как и то, как компилятор обеспечивает перекрестную проверку необходимо обеспечить согласованность Если бы вы написали #include "foo.h", компиляция будет работать. как desc ribed. Если вы написали (в foo/foo.c) #include "foo/foo.h", тогда для командной строки для создания foo.o понадобилось бы -I., чтобы заголовок мог быть найден.
+0

Но заголовок foo.h является частью библиотеки libfoo.a, не так ли? Кроме того, проблема защиты заголовка была опечаткой, когда я перепечатал ее в stackoverflow, что я сделал, потому что я нахожусь в Windows SSHing в системе ubuntu. –

+0

№. Библиотека содержит только и только объектные файлы. Заголовочные файлы _not_ object. Заголовки не содержатся в библиотеках. (ОК: чтобы быть полностью педантично точным, вы могли бы добавить файл заголовка в библиотеку, но компилятор никогда не будет выглядеть в библиотеке - только компоновщик ('ld', обычно) выглядит в библиотеках и ищет только объектные файлы , а не заголовки). –

+0

О, ладно. Благодарю вас за разъяснение. Но почему, например, я могу включить, например, «ncurses.h» из библиотеки ncurses? –