5

My command:

/usr/bin/c++ -fPIC -I/Users/me/project/include -I/usr/local/include/opencv \
-I/usr/local/include -I/opt/local/include -std=c++11 -O3 -M -c \
/Users/me/project/src/program.cpp | grep opencv

program.cpp has:

#include "opencv2/core/core.hpp"
#include "opencv2/ml/ml.hpp"

Output:

  /opt/local/include/opencv2/core/core.hpp \
  /opt/local/include/opencv2/core/types_c.h /usr/include/assert.h \
  /usr/include/math.h /opt/local/include/opencv2/core/version.hpp \
  /opt/local/include/opencv2/core/operations.hpp \
  /opt/local/include/opencv2/core/mat.hpp \
  /opt/local/include/opencv2/objdetect/objdetect.hpp \
  /opt/local/include/opencv2/ml/ml.hpp \

However, there exists: /usr/local/include/opencv2/core/core.hpp, and /usr/local/include/opencv2/ml/ml.hpp.

Using the -v flag, clang tells me:

ignoring duplicate directory "/usr/local/include"
  as it is a non-system directory that duplicates a system directory
#include "..." search starts here:
#include <...> search starts here:
 /Users/me/project/include
 /usr/local/include/opencv
 /opt/local/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1
 /usr/local/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.0/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)

Why is clang including from /opt/local/include instead of /usr/local/include, despite /usr/local/include coming first in the list of -I directories in the command? Why is /usr/local/include pushed down the priority list.

  • try to reverse the order of inclusion and you will get your answer – user2485710 Mar 04 '14 at 17:41
  • @user2485710 You mean put `-I/opt/local/include -I/usr/local/include/opencv -I/usr/local/include`? That does not fix things. `/usr/local/include` still gets listed *after* `/opt/local/include` in the list of include paths produced by `-v`. –  Mar 04 '14 at 17:46
  • than they don't contain the same headers, have you tried this way with a minimalistic source code ? http://stackoverflow.com/a/6685693/2485710 – user2485710 Mar 04 '14 at 17:50
  • The content of the search directories should not affect the search order produced by -v. (And, they do contain the same headers, even though it doesn't matter.) I don't think you understand my question. –  Mar 04 '14 at 17:53
  • that test is just verbose compilation, forget about what you about your files, just give that source code to `gcc' and see what files are really used. – user2485710 Mar 04 '14 at 17:55
  • @user2485710 I demonstrated what files are really used by using `-M` in the first output that I show. -M produces the list of include files that are really used. Also "just verbose compilation" *does* list the include directory search directory. It is not irrelevant. –  Mar 04 '14 at 17:56

1 Answers1

5

You can check the default search path for #include by:

gcc -Wp,-v -E -

(give the -v flag to the preprocessor).

Your directories (given with -I) are searched before the standard list, in the order you give them.

You give /usr/local/include explicitly, and gcc disregards your instruction because it will be added (as a system directory) later on anyway; thus the directories are searched in the wrong order. If you really want to control the directories searched yourself, use -nostdinc and give them all. That is extremely fragile.

To have two sets of header files with the same names is a very bad idea (as you found out). No way to clean up that mess?

vonbrand
  • 11,412
  • 8
  • 32
  • 52
  • So, I shouldn't have opencv 2.4.8 installed at /opt/local/lib, and the development branch installed at /usr/local/lib? I thought that it would be easy to choose between these by specifying the order of include and library directories at the command line. It seems this is only a very bad idea *because* of this behaviour of gcc and clang. –  Mar 05 '14 at 18:05
  • 2
    *"To have two sets of header files with the same names is a very bad idea..."* - Huh? That's the standard way to update an outdated library. The OS has their old copy of `` in `/usr/{include|lib}`, and you put your updated copy of `` in `/usr/local/{include|lib}`. Its required for some libraries, like OpenSSL. Apple still ships an EOL/Abandoned OpenSSL 0.9.8. – jww Jun 09 '17 at 15:31