Reputation: 11522
I have a small build in which I want to include only a single header file (and source file) from a different directory. I know how to use the -I parameter, but do not want to include the entire directory, only the individual files.
My makefile looks like this:
myproj: ui.o data.o string.o
c99 -ggdb -o myproj ui.o data.o string.o
ctags *
ui.o : ui.c data.h
c99 -ggdb -c ui.c
data.o : data.c data.h
c99 -ggdb -c data.c
string.o : ../../shared/src/string.c ../../shared/src/string.h
c99 -ggdb -c ../../shared/src/string.c ../../shared/src/string.h -o ./jcstring.o
When I try to make it complains that string.h
is not found:
c99 -ggdb -c ui.c ../../shared/src/string.h
In file included from ui.c:7:0:
data.h:1:22: fatal error: string.h: No such file or directory
#include "string.h"
How can I include this file without including the whole directory?
Upvotes: 3
Views: 1888
Reputation: 107739
I know how to use the -I parameter, but do not want to include the entire directory, only the individual files.
-I
doesn't “include a directory”, it just puts the directory on the search path. It doesn't matter that the directory contains other files that you don't want. The only files that the compiler will read are the ones whose name is in an #include
directive. So if you have a ../../shared/src/string.h
then you can use the following compilation command:
c99 -ggdb -I ../../shared/src -c ui.c
In the case of string.
, the header is in the same directory as the source file. This is where the compiler will look first, so you don't need -I
at all.
c99 -ggdb -c ../../shared/src/string.c -o ./jcstring.o
The only scenario in which adding -I
options can hurt is if there are header files with the same name in different directories. For example, if all four of the following files exist:
one/foo.h
one/bar.h
two/foo.h
two/bar.h
and you want to compile code containing
#include "foo.h" /* must refer to one/foo.h */
#include "bar.h" /* must refer to two/bar.h */
then you can't do it with just -I
directives. Either you put -I one
first and #include "bar.h"
will include one/bar.h
, or you put -I two
first and #include "foo.h"
will include two/foo.h
. The sane solution is to not run into this problem. Headers inside the same project should have unique names. If you're including headers from different projects then you should include the project name in the include directives.
#include "one/foo.h"
#include "two/bar.h"
In principle you could copy one of the header files to a separate directory and include that, but in this situation, given typical naming conventions you're likely to run into name collisions between the projects.
Note also that string.h
is not a good name for a header because it's the name of a standard library header. The compiler won't confuse the two in your case: #include "string.h"
looks for the header file in the current directory if there is one, whereas #include <string.h>
only looks in directories specified with -I
and falls back to the standard library. Collisions with headers installed system-wide can happen, and it works as long as you don't mistype a file name, but it's confusing for humans to use a very well-known header name that is used in most projects.
Upvotes: 5