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?
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: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:I deliberately excluded the
-static
; it's only necessary when there's a choice between a static and a shared library, but you only havelibfoo.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:Your header guard is faulty. You originally had (but have updated the question so this typo is no longer present):
You need:
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 asgcc
) 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.You might legitimately wonder:
-Ifoo
when compilingtest.c
, why wasn't it necessary when compilingfoo/foo.c
?Good question!
foo/foo.c
foo/foo.c
, it looks infoo
directory for headers included as#include "foo.h"
anyway.foo/foo.c
should have includedfoo.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 (infoo/foo.c
)#include "foo/foo.h"
, then the command line for creatingfoo.o
would have needed-I.
so the header could be found.