Include header file from static library

I am doing a test setup of the static library and program C. The library code located in the "foo" subdirectory of my project contains the following files:

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 

My program code is as follows:

test.c:

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

I have a build script called 'build' which contains the following:

assembly:

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

But when I run the assembly, it causes the following error:

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

However, it works when I omit the #include line, but I would prefer to use the header files in my static libraries. What am I doing wrong, and how can I fix it?

+5
source share
1 answer

Headers are not stored in libraries. Headers are kept separate from libraries. Libraries contain object files; headers are not object. By default, standard headers on a Unix system are stored in /usr/include - you will usually find /usr/include/stdio.h and /usr/include/string.h and /usr/include/stdlib.h , for example. By default, libraries are stored in /usr/lib (but you can also find them in /lib ). Often compilers are also configured to view in some other places. One common alternate location is under /usr/local , so /usr/local/include for headers and /usr/local/lib for libraries. Also note that a single library may have multiple headers defining services. An example is the default library. It has functions corresponding to those found in <stdio.h> , <string.h> , <stdlib.h> and many other headers.

Looking at your code:

  • If your header file is in ./foo/foo.h , you need to write:

     #include "foo/foo.h" 

    Or, if you continue to use #include "foo.h" , you need to specify where to find the header on the compiler command line with an argument:

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

    I deliberately ruled out -static ; this is only necessary when there is a choice between a static and a shared library, but you only have libfoo.a , so the linker will still use this.

    Note that the problem is a compilation error, not a binding error. This would be clearer if you divide the building of the program into two stages: (1) create test.o and (2) a link program:

     gcc -c -Ifoo test.c gcc -o test test.o -L. -lfoo 
  • The header protector is defective. You originally had (but updated the question so that this typo is no longer present):

     #ifndef foo_h__ #define foo_h_ 

    You need:

     #ifndef foo_h__ #define foo_h__ 

    Macro names must be the same on both lines. Note that in this case, the spelling error is basically harmless, but on Mac OS X, the clang (masquerading like gcc ) really warned about it (although I noticed this before I did any compilation). In some other cases, you wonโ€™t get the protection that title defenders intend.

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

You may legitimately wonder:

  • If I need -Ifoo when compiling test.c , why wasn't it necessary when compiling foo/foo.c ?

Good question!

  • This would not hurt the compilation of foo/foo.c
  • GCC looks for headers in the directory where the source code of the translation unit is found (therefore, when compiling foo/foo.c it looks in the foo directory for headers included as #include "foo.h" anyway.
  • The source file foo/foo.c should include foo.h ; it is very important that it does exactly as the compiler provides the cross validation necessary to ensure consistency. If you wrote #include "foo.h" , compilation will work as described. If you wrote (in foo/foo.c ) #include "foo/foo.h" , then -I. would be needed on the command line to create foo.o so that the title can be found.
+17
source

Source: https://habr.com/ru/post/1209933/


All Articles