Instruct compiler to ignore header prefix found in a #include - c++

[As Cornstalks explained below, I'm trying to strip a header prefix that's used in an #include. So it appears this question is not a duplicate of How to make g++ search for header files in a specific directory?]
I'm making some changes to a library. I have the library locally, so its not installed in its customary system location.
I have a test source file and its sided-by-side with the library. The test file has a bunch of includes like:
#include <foo/libfoo.h>
And it also has a bunch of customary includes, like:
#include <iostream>
I'm trying to compile the test file using:
$ g++ ecies-test.c++ -I. -o ecies-test.exe ./libcryptopp.a
And (the space between -iquote . does not appear to make a difference):
$ g++ ecies-test.c++ -I. -iquote . -o ecies-test.exe ./libcryptopp.a
The problem I am having is I don't know how to tell g++ that <foo/libfoo.h> means "./libfoo.h". Effectively, I'm trying to strip the prefix used to include the header. I've looked in the manual under 2.3 Search Path, but it does not really discuss this scenario.
I have about 60 extra test files I use for the library. And each has 10 or 20 includes like this. So I can't go through and change #include <foo/libfoo.h> to #include "./libfoo.h" in 500 or 600 places.
I tried #rici's work around by creating the fictitious directory structure, but it broke GDB debugging. GDB cannot find symbols for class members, so I can't set breakpoints to debug the code I am attempting to modify.
How do I tell the compiler to look in PWD for system includes?
Below is a typical error. ECIES_FIPS is in my local copy of the library.
$ g++ -DNDEBUG=1 -g3 -Os -Wall -Wextra -I. -iquote . ecies-test.c++ -o ecies-test.exe ./libcryptopp.a
ecies-test.c++:29:17: error: no member named 'ECIES_FIPS' in namespace
'CryptoPP'
using CryptoPP::ECIES_FIPS;
~~~~~~~~~~^
ecies-test.c++:44:5: error: use of undeclared identifier 'ECIES_FIPS'
ECIES_FIPS<ECP>::Decryptor decryptor(prng, ASN1::secp256r1());
^
ecies-test.c++:44:16: error: 'ECP' does not refer to a value
ECIES_FIPS<ECP>::Decryptor decryptor(prng, ASN1::secp256r1());
^
/usr/local/include/cryptopp/ecp.h:30:20: note: declared here
class CRYPTOPP_DLL ECP : public AbstractGroup<ECPPoint>
...
In case it matters:
$ g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin12.6.0
Thread model: posix

There is no option which tells gcc to ignore directory prefixes in include paths. If your program contains #include <foo/header.h>, there must be some path_prefix in the include list such that path_prefix/foo/header.h resolves to the desired file.
While you cannot configure gcc to ignore the foo, you can certainly modify the filesystem as you please. All you need is that there be somewhere a directory foo which maps onto the directory where the header files are stored. Then you can add the parent of that directory to the search path.
For example:
mkdir /tmp/fake
ln -s /path/to/directory/containing/header /tmp/fake/foo
gcc -I /tmp/fake ... # Ta-daa!

Using the -I option to add the current folder as an include directory, you could create a folder called "foo" in the current directory and put your libfoo.h file inside.
Obviously, this doesn't strip the "foo" prefix in your #include, but it is a workaround.

I have about 60 extra test files I use for the library. And each has 10 or 20 includes like this. So I can't go through and change #include to #include "./libfoo.h" in 500 or 600 places.
If the above criteria is just a matter of convenience, then a tool like sed can be used to do all the work. Something like
$ sed -i 's/\(^\s*#include\s*[<"]\)foo\/\([^>"]*[>"]\s*$\)/\1\2\t\/\/ This line was replaced/' *
will replace all the occurrences of #include <foo/file.h> with #include <file.h> (you might have to adjust it slightly, I'm on a Windows machine at the moment and can't test it). This will work if all the files are in the PWD. If there is a more complex file structure, then it can be used in conjunction with grep and xargs.
NOTE: Make sure that the svn directories are ignored when using.

Related

How to specify location of angle-bracket headers in gcc/g++?

Is there a way to tell gcc/g++/clang where to look for headers that are included via angle brackets ("<", ">")?
I don't use the angle bracket convention for non-system files, but the problem is that when I try using the headers from some packages I download, I get errors for all of the included files.
For example, say I want to include headers from a module called Foo that I download:
/foo-v1.0/include/DependencyA.hpp:
#ifndef DEP_A_HPP
#define DEP_A_HPP
class DependencyA
{
...
};
#endif
/foo-v1.0/include/Api.hpp:
#ifndef FOO_HPP
#define FOO_HPP
#include <Foo/DependencyA.hpp>
void doSomething(DependencyA* da);
#endif
Then, in my own code:
/mycode.cpp:
#include "/foo-v1.0/include/Api.hpp"
DependencyA* da = new DependencyA();
doSomething(da);
I get a compile error:
fatal error: 'Foo/DependencyA.hpp' file not found
I've tried building with:
clang -c mycode.cpp -isystem./foo-v1.0/include -o mycode.o
clang -c mycode.cpp -isystem./foo-v1.0/include/ -o mycode.o
clang -c mycode.cpp -I./foo-v1.0/include -o mycode.o
clang -c mycode.cpp -I./foo-v1.0/include/ -o mycode.o
and so on, to no avail.
How do I tell the compiler to resolve <Foo/**/*> to a particular root directory for every included file?
The answer is already in the comments.
To check include dirs one can use the method described here: What are the GCC default include directories? , preferably with - replaced with /dev/null:
clang -xc -E -v /dev/null
On my machine for clang it gives
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/clang/11.0.0/include
/usr/include
End of search list.
To discover how to manipulate this list, it suffices to read the gcc (or clang) manual (man clang or find it in the Internet, for example, https://man7.org/linux/man-pages/man1/gcc.1.html ). For gcc this reads:
Options for Directory Search
These options specify directories to search for header files, for
libraries and for parts of the compiler:
-I dir
-iquote dir
-isystem dir
-idirafter dir
Add the directory dir to the list of directories to be searched
for header files during preprocessing. If dir begins with = or
$SYSROOT, then the = or $SYSROOT is replaced by the sysroot
prefix; see --sysroot and -isysroot.
Directories specified with -iquote apply only to the quote form
of the directive, "#include "file"". Directories specified with
-I, -isystem, or -idirafter apply to lookup for both the
"#include "file"" and "#include <file>" directives.
This description is followed by a detailed description of the order in which header files are searched and by some recommendations as to which option to use for which purpose. You'll find it in the manual. Search for "Options for Directory Search".
What I really don't like in your code is this line:
#include "/foo-v1.0/include/Api.hpp"
It seems to contain the absolute path to the header and I've never seen anything like this. I would change it to
#include "Api.hpp"
with /foo-v1.0/include being added to the search list via the usual compiler -I command-line option.

How do I generate and use precompiled headers with Clang++?

The official docs state how precompiled headers are to be used through the -cc1 interface, like so to generate them:
$ clang -cc1 test.h -emit-pch -o test.h.pch
And to use them:
$ clang -cc1 -include-pch test.h.pch test.c -o test.s
The problem is that the -cc1 interface is way too low-level to be used by developers from the CLI. In fact, the regular high-level interface ultimately calls into the low-level -cc1 interface by supplying it with a very large set of arguments that are necessary for its correct operation, for example the include paths appropriate for the compile time system. Without these arguments, the -cc1 interface has no prayer of working:
$ clang++ -cc1 /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h -emit-pch -o std.pch
/usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h:33:10: fatal error: 'cassert' file not found
#include <cassert>
^~~~~~~~~
1 error generated.
Is there a way to use precompiled headers from the high-level interface, such that a developer may conveniently tap into this feature during their daily work?
I don't know why the clang docs do not explain this, but indeed as #selbie surmises, it is possible to use Clang precompiled headers (PCH) without using -cc1.
To generate a PCH file:
$ clang -c -o big-header.hh.pch big-header.hh <other options>
This is the normal compile command, except the input file has the .hh (C++ header) extension. clang will recognize that means to generate a PCH. Alternatively, pass -xc++-header before the header file name if you do not want to use that extension (or another, like .H or .hpp, that is unambiguously C++).
You can tell that big-header.hh.pch is not object code (despite the -c on the command line) because file will say it is "data" (at least my version does) rather than object code. To be extra sure, run strings big-header.hh.pch | head. The first line should be "CPCH" (meaning "Clang PCH").
To use the PCH file:
$ clang -c -include-pch big-header.hh.pch <other compile options>
The addition of -include-pch big-header.hh.pch is the key step that is different compared to gcc. Clang will not automatically pick up PCH files just due their name.
The above was tested with Clang+LLVM-14.0.0 on Linux.
I think the root of your problem is that your filename is test.h and clang thinks you are compiling C code, not C++ code. Hence, when you include <cassert>, clang doesn't know it should be looking at the C++ include path. Try naming your file test.hpp. You only have to name the file you want as the precomp header with .hpp. You can keep all your header files with .h extensions.
In any case, I might be getting this confused with gcc/g++, but Clang follows the same behavior whenever I compile my code on Mac. This is how I make use of precompiled headers. Read on...
If you've got a C++ header file you want to precompile, just compile it as any other .cpp file. Notice that I'm using .hpp as the file extension so the compiler picks it up as a C++ header file.
clang -c precomp.hpp
This will produce precomp.hpp.gch
Now to use the precomp by any other ordinary C++ file, just include the ordinary .hpp file:
// main.cpp
#include "precomp.hpp"
void func1() {...}
void main() {...}
The compiler will automatically use the corresponding .gch file if its present in place of the original .hpp file.

G++ seems to be ignoring #ifdef for an #include

Environment
Ubuntu 16.04
G++ 5.3.1
I have a header file with the following intended to include a different .h file depending on platform:
#ifdef _WIN32
#include "curses.h"
#else
#include <ncurses.h>
#endif
This works fine in windows but in Ubuntu I get errors about the curses.h file:
In file included from /usr/include/unctrl.h:54:0,
from /usr/include/curses.h:1694,
from headers/command_window.h:8,
from command_window.cpp:1:
headers/curses.h:900:19: error: macro "clear" passed 1 arguments, but takes just 0
int clear(void);
This when compiling with:
g++ -g -lncurses -std=c++11 -Iheaders -c -o command_window.o command_window.cpp
Why is headers/curses.h, which is the windows specific file for PDCurses being involved here at all?
/usr/include/unctrl.h contains this line:
#include <curses.h>
And since you've told the compiler to look in your headers/ folder for header files with the -Iheaders flag , the compiler picks up curses.h in that folder.
So you need to drop the -Iheaders flag (and e.g. use #include "headers/header_name.h") or you need to rename your headers/curses.h to not collide with /usr/include/curses.h
In your version of g++, the -I option is not the correct way to add application-specific header files (those that shouldn't be found by #include in system headers) to the search path (this change surprised me as well).
Instead, you should use -iquote headers.
See this answer: How to tell g++ compiler where to search for include files? and this official documentation

Where is the -I (captial i) path relative to in g++?

I am in the App folder of my project. I run the following command to compile character.cpp
g++ -Wall -std=c++11 -I../App -c Character/character.cpp -o Obj/character.o
which is in App/Character directory. character.cpp has the following include
#include "Inventory/inventory.hpp"
where the folder of inventory.cpp is App/Inventory.
I thought because I am running the g++ command from App, the default include path would start from App and therefore I wouldn't need to have the -I../App part of the command. To me this seems to be saying "move one level higher than App then move into App and include from there" which seems redundant but without that line it doesn't work.
Can anyone explain why?
EDIT
Looking at it again and some more documentation, I believe that if no -I path is specified, g++ will look in its default directories and then all other includes (like the one I have causing problems) are relative to the file that includes them. So I have to add the -I part to say "look in the App directory too" and since it doesn't like just -I, I have to use ../App because that is equivalent to not moving at all. Can anyone confirm if this is at all accurate?
You can use -I. for searching headers from the current directory, instead of -I../App.
This include preprocessor directive
#include "Inventory/inventory.hpp"
forces gcc (g++ or cpp) to search the header not from the current path (App/), but from directory of your source file (App/Character):
/root/App# strace -f g++ -c -H ./Character/character.cpp 2>&1 |grep Inven
[pid 31316] read(3, "#include \"Inventory/inventory.hp"..., 35) = 35
[pid 31316] stat64("./Character/Inventory/inventory.hpp.gch", 0xbfffe6a4) = -1 ENOENT (No such file or directory)
[pid 31316] open("./Character/Inventory/inventory.hpp", O_RDONLY|O_NOCTTY) = -1 ENOENT (No such file or directory)
..then try system directories
This is documented here: https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html
GCC looks for headers requested with #include "file" first in the directory containing the current file
This behavior can be not fixed in the Language standard (ISO C), and is implementation-defined (as commented by Richard Corden and answered by piCookie in What is the difference between #include <filename> and #include "filename"?):
specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner.
But this is the way the C compiler should work under Unix, according to Posix, aka The Open Group Base Specifications Issue 7:
Thus, headers whose names are enclosed in double-quotes ( "" ) shall be searched for first in the directory of the file with the #include line, then in directories named in -I options, and last in the usual places. For headers whose names are enclosed in angle brackets ( "<>" ), the header shall be searched for only in directories named in -I options and then in the usual places. Directories named in -I options shall be searched in the order specified.
It is useful when your current directory is far from the source directory (this is the recommended way in autotools/autoconf: do mkdir build_dir5;cd build_dir5; /path/to/original/source_dir/configure --options; then make - this will not change source dir and will not generate lot of file in it; you can do several build with single copy of source).
When you start g++ from the App directory with -I. (or with -I../App or -I/full_path/to/App), gcc (g++) will find the Inventory. I added warning to the header to see when it will be included; and -H option of gcc/g++ prints all included headers with pathes:
/root/App# cat Inventory/inventory.hpp
#warning "Inventory/inventory.h included"
/root/App# cat Character/character.cpp
#include "Inventory/inventory.hpp"
/root/App# g++ -I. ./Character/character.cpp -H -c
. ./Inventory/inventory.hpp
In file included from ./Character/character.cpp:1:
./Inventory/inventory.hpp:1:2: warning: #warning "Inventory/inventory.h included"

How to query the default include paths of clang++?

How can I query the default include path of clang/clang++? I am trying to use a custom built clang compiler (the one that supports OpenMP), but it doesn't seem to find the STL libraries:
/usr/local/bin/clang++ hello.cpp
hello.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
^
1 error generated.
By using an IDE, back-tracking the #include iostream, and finally using the -isystem option I got the simple helloworld application to compile in OSX 10.9:
/usr/local/bin/clang++ -isystem /Library/Developer/CommandLineTools/usr/lib/c++/v1 hello.cpp
Thanks for your help!
You are looking for option -v. Compiling with clang++ -c file.cc -v will print among other things:
#include "..." search starts here:
#include <...> search starts here:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9
etc.
If you run
clang++ -### hello.cpp
It will display the commands used to compile that particular file, including the default include paths, library search paths, targets etc.