Search code examples
c++header-files

How do I get #include<> to look in a subfolder of the standard system directory?


I made the original post below but think the question can be made more general.

I installed a c++ library called ibex. It contains a file ibex.h and a subfolder ibex, and the subfolder contains more header files that are called by ibex.h. Both ibex.h and the subfolder are located in /usr/local/include. I have confirmed this is in my standard system directory.

I'm trying to run the example code from ibex's website below called foo.cpp

#include <ibex.h>
#include <iostream>

using namespace std;
using namespace ibex;

int main(int argc, char** argv) {
  Interval x(0,1);
  cout << "My first interval:" << x << endl;
}

but get the error

In file included from (filelocationremoved)/foo.cpp:1:
/usr/local/include/ibex.h:6:10: fatal error: 'ibex_Setting.h' file not found

So basically it can find ibex.h but won't look in the subfolder for ibex_Setting.h (or any of the other files in the subfolder). Is there a way to get it to view all the files in that subfolder as if they are in the /usr/local/include folder without moving them all in?

Thanks!

Original post:

I'm a novice c++ user (I mostly use Matlab and a little Python) but need to use c++ for the ibex library (http://www.ibex-lib.org). I'm trying to get their basic example to compile but am having issues. I'm hoping some of the experienced users here can help as I'm making no progress.

Notes:

  • Running MacOS Catalina
  • Using Sublime text for my IDE
  • I have Xcode installed and can run a hello world example
  • Installed ibex using: brew install ibex

I am trying to run the following example code from their documentation called foo.cpp

#include <ibex.h>
#include <iostream>

using namespace std;
using namespace ibex;

int main(int argc, char** argv) {
  Interval x(0,1);
  cout << "My first interval:" << x << endl;
}

but get the error

In file included from (filelocationremoved)/foo.cpp:1:
/usr/local/include/ibex.h:6:10: fatal error: 'ibex_Setting.h' file not found

The ibex_Setting.h file is one of the many files called by ibex.h. I have the ibex.h file located in /usr/local/include and it seems to be able to find it. I also have an alias of the ibex folder (where all the relevant subfiles are located) in the same /usr/local/include folder. But it won't look in that subfolder. That subfolder was created by brew link ibex, which I assume is supposed to make it findable. If I move ibex_Setting.h into the /usr/local/include folder, it then finds it, but moves to the next file it can't find (also located in /usr/local/include/ibex). The folder has enough files that I don't want to manually move all of them into /usr/local/include. Also, that would seem silly to need to do that.

In the ibex documentation, it also says to do this: export DYLD_LIBRARY_PATH=[prefix]/lib, where prefix is the folder location. My libibex.dylib is located in /usr/local/lib, which I used. This did not help. I'm sure I'm not providing enough information, but again I'm new to c++ so don't even know what else to include. Any help would be greatly appreciated!

Thanks


Solution

  • I'm unfamilar with XCode and Sublime Text but I can show you a demo of the problem, and how to solve it, at the compiler level. You can work how to apply that in the compiler settings of your IDE.

    Here's the contents of a project folder for a program:

    $ ls -R
    .:
    header.h  main.cpp  subfolder
    
    ./subfolder:
    subheader.h
    

    And here are the source files and headers:

    $ cat main.cpp
    #include <header.h>
    
    int main()
    {
        return foo();
    }
    
    $ cat header.h
    #ifndef HEADER_H
    #define HEADER_H
    
    #include <subheader.h>
    
    inline int foo() {
        return bar();
    }
    
    #endif
    
    $ cat subfolder/subheader.h 
    #ifndef SUBHEADER_H
    #define SUBHEADER_H
    
    inline int bar() {
        return 42;
    }
    
    #endif
    

    I first try to compile prog like this:

    $ g++ -Wall -o prog main.cpp
    main.cpp:1:10: fatal error: header.h: No such file or directory
        1 | #include <header.h>
          |          ^~~~~~~~~~
    compilation terminated.
    

    which doesn't work because the preprocessor doesn't know where to look for the system header <header.h>. (In this context a system header just means a header file specified in <...>, as opposed to a local header, that would be specified in "...", and would be searched for in the current directory when the compiler runs).

    I can fix that by adding an -I dir preprocessor option, which tells the preprocessor to search for header files in directory dir. Since header.h is in the current directory in this demo, I'll just use . as the directory name, rather than type the full directory name.

    $ g++ -Wall -I. -o prog main.cpp
    In file included from main.cpp:1:
    ./header.h:4:10: fatal error: subheader.h: No such file or directory
        4 | #include <subheader.h>
          |          ^~~~~~~~~~~~~
    compilation terminated.
    

    That fix has enabled header.h to be found, but then in header.h, there's the same sort of problem with <subheader.h>.

    I fix that in the same way:

    $ g++ -Wall -I. -I./subfolder -o prog main.cpp
    $ ./prog
    $ echo $?
    42
    

    and now everything is OK.

    So to a first approximation, what you need to do is make settings in your IDE project to specify that -I/usr/local/include and -I/usr/local/include/subfolder are passed to the compilation command. But in fact you won't need the first one, because /usr/local/include is always a default compiler search directory for header files. The answers to this question might help you, though it's old.

    Is there any option similar to -I dir that will make the preprocessor search recursively in subfolders of dir to resolve #include <...> directives? No there isn't.

    Note that if I'd coded header.h with:

    #include <subfolder/subheader.h>
    

    instead of:

    #include <subheader.h>
    

    then I could have compiled my program at the second attempt, g++ -Wall -I. -o prog main.cpp.

    Well organised packages tend to have their #include <...> directives written with the necessary path elements, like <subfolder/subheader.h>, to allow successful compilation with at most one -I base/path option, where base/path is the common path prefix for all the #include <...> directives. But some packages don't and there may be a good rationale for it.