What makes clang look in subdirectories of the include path? - c++

Running OS X 10.10.5
When I run the following command: clang -x c -v -E /dev/null I see among the output:
clang -cc1 version 7.0.2 based upon LLVM 3.7.0svn default target x86_64-apple-darwin14.5.0
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/Applications/Xcode.app/Contents /Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.2/include
/Applications/Xcode.app/Contents /Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
/usr/include
/System/Library/Frameworks (framework directory)
/Library/Frameworks (framework directory)
End of search list.
Now if I look in directory /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
I only see one header file there, plus a directory called "c++":
ls -l /Applications/Xcode.app/Contents /Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
total 0
-rw-r--r-- 1 root wheel 6235 Nov 11 2015 FlexLexer.h
drwxr-xr-x 3 root wheel 102 Nov 11 2015 c++
And if look in the directory "c++", then I see directory "v1":
ls -l /Applications/Xcode.app/Contents /Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++
total 0
drwxr-xr-x 102 root wheel 3468 Nov 11 2015 v1
Finally if I look in directory "v1" then I see the standard c++ library headers such as: string, vector, map, iostream, etc.
Apparently, even though clang tells me it will search in
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/
It actually looks two subdirectories lower to find the standard c++ headers.
Now if I put a header in /usr/local/include the compiler will find that header no problem.
BUT if I create a subdirectory /usr/local/include/mysub/ and put a header there, the compiler cannot find it. Now I know, of course I can add a -I/usr/local/include/mysub to be able to find headers that I put there. But my question is this: Why the discrepancy?? Why does clang look two subdirectories below /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/ to find the std c++ headers, but won't look below /usr/local/include unless I specifically tell it to do so (with a -I flag)??
Is this something that is just hard-coded in clang's source code? Or is there a way I can configure it to automatically look in subdirectories of any directory in the include path?? Thanks.

Compiler drivers know where to tell the compiler (or actually the preprocessor) where to look for header files, usually by offsetting from the directory containing the driver executable, and this is hard-coded in the driver. It's generally undesirable to tell the driver to look in other subdirectories automatically, as this will very often result in very hard to track down bugs. In other words you want to specify the directories explicitly with -I.
And if you are developing non-library applications, you should never put anything in /usr/local/include or similar directories. And arguably not even if you are developing libraries.

Related

How to #include <whatever.h> installed with apt in Ubuntu

I have just installed hidapi in my Ubuntu 20.04 following the instructions, i.e. by doing
sudo apt install libhidapi-dev
I wrote my program in the file mwe.cpp which contains only this line:
#include <hidapi.h>
and now I want to compile it with
g++ -o mwe.o mwe.cpp
but I get
mwe.cpp:1:10: fatal error: hidapi.h: No such file or directory
How am I supposed to use this module? Sorry for such a basic question but cannot find out.
On Ubuntu based systems, the system package libhidapi-dev installs the include files to /usr/include/hidapi, so either include this (-I/usr/include/hidapi) in your command line or #include <hidapi/hidapi.h>
If that header is not within the standard search path for headers, then you can include it manually with the -I flag e.g.
g++ -I/usr/include/hidapi -o mwe.o mwe.cpp
To locate a file on ubuntu, you can run:
sudo updatedb
locate hidapi.h
> /usr/include/hidapi/hidapi.h
You can view the standard include search path with:
gcc -print-search-dirs
Alternatively, because /usr/include is on the standard search path, you can write your include as <hidapi/hidapi.h>.
How to #include <whatever.h> installed with apt in Ubuntu
If the package installs the header within a directory included in the default search path of your compiler - which is typical - then you can include the header using a relative path from the root of the search path where the header is installed. For example, if the file is in the path /usr/include/x/y.h, then you can include <x/y.h>.
If the package doesn't install the header within the default search path, then you must specify the search path for the compiler when you invoke it, and then include the header relative to the specified include directory. For example, if the file is in the path /opt/custom/x/y.h, then you can include <x/y.h> and specify /opt/custom as a search path for the compiler.
If you use GCC or compatible compiler, and the package supports it, then you can use a program called pkg-config to get the compiler options needed to use the library. Besides the header search path, this also takes care of linking with the library as well as any mandatory compiler options. Example:
pkg-config --libs --cflags libhidapi
I don't know, how do I find the location of hidapi.h?
There are several ways to find out the location of a file. A general tool is the program find. Example:
find / -name=hidapi.h
A more specific tool for learning the paths of files installed by an apt package is apt-file. Alternatively, you can look up the list of files in the https://packages.ubuntu.com/ website.

Clang toolchain fails for system libc files

I wrote a custom (cc_)toolchain for Clang. After some back and forth I now have it mostly working. It is however failing with:
undeclared inclusion(s) in rule '//foo:foo'
this rule is missing dependency declarations for the following files included by 'foo/foobar.cpp':
'/usr/include/features.h'
'/usr/include/stdc-predef.h'
'/usr/include/x86_64-linux-gnu/sys/cdefs.h'
'/usr/include/x86_64-linux-gnu/bits/wordsize.h'
'/usr/include/x86_64-linux-gnu/gnu/stubs.h'
'/usr/include/x86_64-linux-gnu/gnu/stubs-64.h'
'/usr/include/stdint.h'
'/usr/include/x86_64-linux-gnu/bits/wchar.h'
'/usr/include/stdio.h'
'/usr/include/x86_64-linux-gnu/bits/types.h'
'/usr/include/x86_64-linux-gnu/bits/typesizes.h'
'/usr/include/libio.h'
'/usr/include/_G_config.h'
'/usr/include/wchar.h'
'/usr/include/x86_64-linux-gnu/bits/stdio_lim.h'
'/usr/include/x86_64-linux-gnu/bits/sys_errlist.h'
'/usr/include/math.h'
'/usr/include/x86_64-linux-gnu/bits/math-vector.h'
'/usr/include/x86_64-linux-gnu/bits/libm-simd-decl-stubs.h'
'/usr/include/x86_64-linux-gnu/bits/huge_val.h'
'/usr/include/x86_64-linux-gnu/bits/huge_valf.h'
'/usr/include/x86_64-linux-gnu/bits/huge_vall.h'
'/usr/include/x86_64-linux-gnu/bits/inf.h'
'/usr/include/x86_64-linux-gnu/bits/nan.h'
'/usr/include/x86_64-linux-gnu/bits/mathdef.h'
'/usr/include/x86_64-linux-gnu/bits/mathcalls.h'
'/usr/include/assert.h'
'/usr/include/string.h'
'/usr/include/xlocale.h'
So how is one supposed to handle these files? Simply hardcode these for the toolchain? Or is there a switch to ignore dependencies from the system (/usr)? Or rather use a hermetic libc like musl, newlib or bionic.
EDIT:
For more details about the actual toolchain see: https://github.com/abergmeier/bazel_toolchains
You need to put the builtin include paths of the compiler into the cxx_builtin_include_directory field of the crosstool proto, so Bazel knows to ignore them during include dependency validation. You can see the builtin include paths of a gcc-compatible compiler by running something like
$ $CC -x c++ -v - -c -o /dev/null < /dev/null
and looking for the output like
#include "..." search starts here:
#include <...> search starts here:
/usr/include/c++/7
/usr/include/x86_64-linux-gnu/c++/7
/usr/include/c++/7/backward
/usr/lib/gcc/x86_64-linux-gnu/7/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include

How can I force cmake to use C++ header files in /usr/include in Linux?

I have a cmake project that uses a header installed in /usr/include, let's call it freeglut.h. When I use find_package(GLUT) I get ${GLUT_INCLUDE_DIR} pointing to /usr/include. All's well.
Now, I'm adding CUDA, which keeps its own copies of these and other headers in one of the paths included with find_package(CUDA). Normally I would resolve this by placing ${GLUT_INCLUDE_DIR} before ${CUDA_INCLUDE_DIRS} in include_directories(). However, on Unix systems cmake, in UnixPaths.cmake, maintains a list called CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES, which contains /usr/include and apparently keeps cmake from emitting -I<dir> arguments for the compiler for the directory /usr/include, meaning that the compiler searches the CUDA path first, and uses the freeglut.h header found there.
I have tried using list(REMOVE_ITEM ... to remove /usr/include from the CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES list, but that didn't change the compiler commands that cmake made.
I could of course start hacking around with the CUDA installation, delete the headers I don't want, or modify the CUDA_INCLUDE_DIRS variable, but is there a clean way to tell cmake to use the system header files first, if they exist?
I suppose the -idirafter flag should help you:
-idirafter dir
Search dir for header files, but do it after all directories specified with -I and the standard system directories have
been exhausted. dir is treated as a system include directory.
https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
You can use it like this to lower CUDA include dirs priority:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -idirafter /usr/include/<CUDA_includes>")

How to Place non-Default C++ Packages in Cygwin File Structure Correctly

I'm a bit of a novice at C++ development. The goal is to download an correctly ready a new package so that Cygwin will understand the statement #include "pcap.h". The directions for the developer package for WinpCap were pretty straight forward:
Download the ZIP archive containing the developer's pack
Uncompress it to the desired folder
Developer Package Instructions Link
The part that I am having trouble with is the "desired folder" part. I found the path for where Cygwin is storing default libraries which for me is C:Cygwin64/usr/include . I placed the package in this directory but that didn't work. pcap.h is nested in the unzipped folders two or three directories in. I noticed that this is a little different when compared to the directories that were there by default. To test whether or not this was correct or not I simply did an #include "pcap.h" statement in a .cpp file that previously compiled with no issues. With the new included statement I got a
fatal error: pcap.h: No such file or directory
from Cygwin.
How should I go about solving this? The goal is to have this behave like any other directory one would want.
You could use this to find where gcc searches for the header files.
`gcc -print-prog-name=cc1plus` -v
The result of the command in a Cygwin console :
$ `gcc -print-prog-name=cc1plus` -v
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-cygwin/4.9.2/../../../../i686-pc-cygwin/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++
/usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++/i686-pc-cygwin
/usr/lib/gcc/i686-pc-cygwin/4.9.2/include/c++/backward
/usr/lib/gcc/i686-pc-cygwin/4.9.2/include
/usr/lib/gcc/i686-pc-cygwin/4.9.2/include-fixed
/usr/include
End of search list.
You could still maybe place your package's headers in one of them.

How to include Apple 'frameworks' on Eclipse CDT

As a follow up to another question I recently asked, I realize my issue is that I don't know how to include Apple 'frameworks' in the Eclipse CDT project properties so that they're picked up and linked at compile time.
This results in includes in this form not to be resolved:
#include <OpenCL/cl.h>
Where the actual path would be something like:
/System/Library/Frameworks/OpenCL.framework/Versions/A/Headers
And the cmd line option would be (if I was manually compiling):
-framework OpenCL
In summary: How can I get Eclipse to see the framework(s) I want fromt he project properties?
Any help highly appreciated!
An alternative answer to JohnIdol's answer. In particular, an approach that can work in the case that you don't want to change the <OpenCL/cl.h> reference to <cl.h>
First, I came to the site with exactly this question in mind (how to include Apple 'frameworks' in Eclipse CDT (C/C++) projects) and I really appreciate the discussion - it gave me a starting point.
John's answer is cool but it does involve changing how the include file is called (e.g., <OpenCL/cl.h> becomes <cl.h> in the code). Then he does a direct include-path reference in the eclipse properties for each Header directory he needs.
In my case, I had checked-out GNU Backgammon to play around with the source code. This code compiles (with some mods to LDFLAGS and CPPFLAGS before doing the autogen.sh) on the OS X CLI environment using the I-guess-standard apple approach of the -framework option and with include files references like
#include <CoreAudio/CoreAudioTypes.h>
I may never actually commit anything but I didn't want to start hacking the #includes in code that is already compiling just fine using the standard approach. So I did the following:
Made a new directory in my workspace gnubg called "Frameworks".
Inside that directory, make soft-links to the header directories.
ln -s /System/Library/Frameworks/CoreAudio.framework/Headers CoreAudio
In the gnubg project properties > C/C++ General> Paths and Symbols, added /gnubg/Frameworks to the Include directories (as a workspace path). I only had to do this once, regardless of the number of soft links I made.
This way I did not have to change the code at all, Eclipse was happy, CLI compilation was happy as well.
I note that there is a slight wrinkle if using some directories in Frameworks such as the CoreServices.framework. In those cases there is a Frameworks subdirectory and relative path references in some of the include files (e.g., ..) to other include files. So in this case I had to modify the procedure a bit. Basically, I had to add an additional sub-directory in Frameworks for CoreServices.framework and then in that directory I had to add two soft links. One for the CoreServices (for the Headers) and one for Framework subdirectory.
lrwxr-xr-x 1 dhansen staff 57B Jul 27 02:06 CoreServices -> /System/Library/Frameworks/CoreServices.framework/Headers
lrwxr-xr-x 1 dhansen staff 60B Jul 27 02:05 Frameworks -> /System/Library/Frameworks/CoreServices.framework/Frameworks
Then I had to add /gnubg/Frameworks/CoreServices.framework to the include path (step 3 above).
And that's it. No more include file problems.
Since current Eclipse CDT releases don't perform sub-framework header inclusion correctly, you can avoid sub-framework problems (like those generated by the CoreServices header files) by creating symbolic links to the include directories of each sub-framework. I elaborated on this subject, which stems from danhan answer, in the following post:
http://thegreyblog.blogspot.com/2014/02/how-to-include-apple-frameworks-headers.html
In order to automate this process, I've created a Z shell script which automates this process and creates the symlink to the specified frameworks' header directory, together with the links to the include directory of each one of their sub-frameworks. The script can be found here: https://github.com/emcrisostomo/link-osx-framework-headers
Hope this helps.
OK so I had to include like this:
#include <cl.h>
Then add an include to the folder with the header file in Properties > C/C++ General > Paths and Symbols resulting in the following option for the compiler:
-I/System/Library/Frameworks/OpenCL.framework/Versions/A/Headers
And, most notably, had to add the following options for libraries path and framework inclusion under Properties > C/C++ Build > Settings:
-L/System/Library/Frameworks/OpenCL.framework/Versions/A/Libraries -framework OpenCL
The above did the trick.
goto Your Project>Properties>MacOS X C++ Linker>Command
Where "g++" add " -framework OpenCL"