1

Suppose I download a library in linux and build it: configure, make, sudo make install.

The library comes with headers which I want to include in a project. How does the compiler know where to search for headers?

  • Drew Dorman's answer to This Question Gave a good example of how to check where the compiler is looking for headers at a system level:

    gcc -print-prog-name=cc1plus -v
  • Include folders can be added in a makefile with a -I argument on a project basis. They can, naturally, be seen in the Makefile.

Are there other mechanisms for registering the locations of headers that I have not considered? Are these combined methods giving me a comprehensive view, or, stated another way, if I look in these places, have I seen all there is to see, assuming I am using gnu-make? Finally, is there a convenient way to get Make to show me the locations that it is checking for headers?

Background: The libraries I am dealing with are zeromq and google's protocol buffers. Platform is CentOS. The compiler is complaining that it cannot find headers. I've built this program on a surrogate system, (Fedora) which did not seem to need additional intervention to ensure those headers were accessible.

2NinerRomeo
  • 2,687
  • 4
  • 29
  • 35
  • I usually use Makefile variables to define the include files, i.e. `INCDIRS := -I. -I../dir1/include -I../somewhere/dir2/include` and then pass $(INCDIRS) to the compiler. – J.R. Apr 11 '19 at 20:12
  • 1
    You should not care at all about the system header file locations because you are not adding new system headers. So that gcc command is not useful to you. You should investigate the manual for your compiler, but essentially every compiler provides a command line option which adds new directories to the list of places to search for headers. On all UNIX/Posix systems, the option is `-I`. On Windows it's `/I`. So, add `-I/path/to/headers`, for each extra directory you want to be searched, to your compile line. – MadScientist Apr 11 '19 at 20:29

1 Answers1

0

There is no usual mechanism for registering a header search location in Linux (or other unix-like OS).

GCC is built, for your system-type, with a default list of preprocessor search directories for each of C and C++. You can display that list, for C, with the command (among others):

$ gcc -x c  -E -Wp,-v -
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
...
$ [CNTL-C]

and for C++:

$ gcc -x c++  -E -Wp,-v -
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/8"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/8
 /usr/include/x86_64-linux-gnu/c++/8
 /usr/include/c++/8/backward
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
...
$ [CNTL-C]

Note that the default search directories are different for C and C++: the C++-list is a superset of the C-list. The C-list will be searched when you compile C source files in the normal way:

gcc [options...] foo.c ...

and the C++-list will be searched when you compile C++ sources in the usual way:

g++ [options...] foo.cpp bar.cc gum.cxx ...

There only two other ways of communicating header search directories to the preprocessor:-

You can explicitly specify search directories in the commandline, using one of the options:

-I dir
-iquote dir
-isystem dir
-idirafter dir

as per the manual: 3.15 Options for Directory Search

Or you can list search directories in your setting of one of the environment variables that the preprocessor interprets as a list of search directories. For C, these are:

CPATH
C_INCLUDE_PATH

and for C++ they are:

CPATH
CPLUS_INCLUDE_PATH

as per the manual: 3.20 Environment Variables Affecting GCC

It is possible in Linux to give an environment variable a persistent default system-wide definition, by defining it in one of the root-privilege files /etc/environment, /etc/profile, /etc/profile.d/, /etc/bash.bashrc. So, if some agent were to define CPATH and or C_INCLUDE_PATH|CPLUS_INCLUDE_PATH in one of those files as a :-punctuated list of directories, that would effectively register those directories as GCC search directories for C|C++. However GCC installations do not install any such settings: they could only be set manually by a root user. You can check, and if you draw a blank, then these variables can only be influential if they are defined in the transient shell. Their use in build systems is vanishingly rare, precisely because of the opaque dependency they introduce upon the operative environment.

The commands I used above to list the default search directories are sensitive to the addition of non-default directories by either of the two possible methods:

$ mkdir my_include

$ gcc -x c  -I my_include -E -Wp,-v -
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 my_include
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

or:

$ gcc -x c  -iquote my_include -E -Wp,-v -
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
 my_include
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

or:

$ export CPLUS_INCLUDE_PATH=my_include
$ gcc -x c++  -E -Wp,-v -
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/8"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 my_include
 /usr/include/c++/8
 /usr/include/x86_64-linux-gnu/c++/8
 /usr/include/c++/8/backward
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

Is there a convenient way to get Make to show me the locations that it is checking for headers?

Make is ignorant of compilation processes and the concepts they involve: it does not know that checking for headers ever happens in the course of its work. In the execution of a makefile, commands might be run which invoke a GCC frontend to perform compilation, and then it will attempt to locate header files, in the manner already outlined.

Other things being equal, the likeliest reason why the compilation of code should succeed on some Fedora system but fail on some CentOS system because, say, #include <google/protobuf/someheader.h> cannot be resolved, is that some user with root privilege has installed either the development package protobuf-devel or the protobuf source tarball on the Fedora system and no-one has done the same on the CentOS system.

If protobuf has indeed been properly installed on both systems, then other things are not equal.

It might be the case that google/protobuf/someheader.h is a header that is provided by the (newer?) version of protobuf that is installed on the Fedora system but not provided by the (older?) version that is installed on the CentOS system.

Several other inequalities might explain your situation, but without concrete details of the Fedora and CentOS package installation steps and concrete examples of the succeeding and failing builds one could only describe all of them, speculatively. It is almost certainly not explained by anything you do not now know about GCC's methods of resolving #include directives.

Similar considerations apply to the compilation failure that you find with respect to zeromq headers.

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182