I am making a test setup of a C static library and program. The library code, located in a subdirectory 'foo' 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 progam 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:
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
But when I run build, it gives me the following error:
test.c:1:17: fatal error: foo.h: No such file or directory
#include "foo.h"
^
Compilation terminated
It does, however, work when I omit the #include line, but I would prefer if I could use header files in my static libraries. What am I doing wrong, and how can I fix it?
No. A library contains solely and only object files. Headers are not object files. Headers are not contained in libraries.
Definition. Header File is the file where all the headers name are mentioned that going to be used or consumed in the main code file. On other hand Library is the file where the implementation code of each header is written down which is mentioned in the Header file. 2. File Extension.
You request to use a header file in your program by including it with the C preprocessing directive #include, like you have seen inclusion of stdio. h header file, which comes along with your compiler.
You make the declarations in a header file, then use the #include directive in every . cpp file or other header file that requires that declaration. The #include directive inserts a copy of the header file directly into the . cpp file prior to compilation.
Headers are not stored in libraries. Headers are stored separately from libraries. Libraries contain object files; headers are not object files. By default, standard headers on a Unix system are stored in /usr/include
— you'll normally 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 may also find some in /lib
). Often, compilers are configured to look in some other places too. One common alternative location is under /usr/local
, so /usr/local/include
for headers and /usr/local/lib
for libraries. Note, too, that a single library may have many headers defining the services. The default library is an example. It has the functions corresponding to those found in <stdio.h>
, <string.h>
, <stdlib.h>
and many other headers too.
Looking at your code:
If your header file is in ./foo/foo.h
, then 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 the argument:
gcc -Ifoo -o test test.c -L. -lfoo
I deliberately excluded the -static
; it's only necessary when there's a choice between a static and a shared library, but you only have libfoo.a
, so the linker will use that anyway.
Note that the problem is a compilation error, not a linking error. This would be clearer if you split the program building into two steps: (1) create test.o
and (2) link program:
gcc -c -Ifoo test.c
gcc -o test test.o -L. -lfoo
Your header guard is faulty. You originally had (but have updated the question so this typo is no longer present):
#ifndef foo_h__
#define foo_h_
You need:
#ifndef foo_h__
#define foo_h__
The macro names must be the same in both lines. Note that in this case, the misspelling is mostly harmless — but on Mac OS X, clang
(masquerading as gcc
) did give a warning about it (though I'd spotted it before I did any compilation). In some other cases, you wouldn't get the protection that the header guards are designed to provide.
./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 might legitimately wonder:
-Ifoo
when compiling test.c
, why wasn't it necessary when compiling foo/foo.c
?Good question!
foo/foo.c
foo/foo.c
, it looks in foo
directory for headers included as #include "foo.h"
anyway.foo/foo.c
should have included foo.h
too; it is very important that it does as that is how the compiler provides the cross-checking necessary to ensure consistency. If you had written #include "foo.h"
, the compilation would work as described. If you wrote (in foo/foo.c
) #include "foo/foo.h"
, then the command line for creating foo.o
would have needed -I.
so the header could be found.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With