Shane Hsu
Shane Hsu

Reputation: 8367

Stop g++ compiler from including specific header files

As the title stated, I want my compiler to fail when I include some header files; for example, <cmath>

Is that possible with just compiler flags? Or do I have to actually delete those headers?

Upvotes: 0

Views: 255

Answers (2)

user
user

Reputation: 6947

#include <cmath> has nothing to do with any library, and everything to do with a header file. Assuming that you really do mean that you want compilation to fail if you include a particular header file, you should be able to leverage GCC's support for specifying include directories through environment variables.

To do so, create or edit an appropriate environment file. If you are using GNU bash on Debian, for example, you can create a file /etc/profile.d/gcc-include-dirs. Everything readable in /etc/profile.d is sourced when a shell is launched, so it will apply to all shells started after that point. (To be absolutely certain, you may want to log out and back in once, then issue env | grep INCLUDE to confirm.) Create such a file with your favorite editor and add the following to it:

export C_INCLUDE_PATH=/usr/local/include/fail:${C_INCLUDE_PATH}
export CPLUS_INCLUDE_PATH=/usr/local/include/fail:${CPLUS_INCLUDE_PATH}

Make sure the file is readable by everyone (chmod 644 /etc/profile/gcc-include-dirs) and that it is owned by root (chown root:root /etc/profile/gcc-include-dirs).

You can also put the file elsewhere and simply source it when needed, if you only need this behavior at specific times. In that case, logging out from the shell in question and logging back in will restore GCC's normal behavior (you don't need to log out from the entire session, just that particular shell instance). Starting a subshell and sourcing the file from within that subshell will also work nicely in that case; just exit when you are done.

Then create a file /usr/local/include/fail/cmath with the following content:

#error "Failing because you included 'cmath'"

Make sure that file too is readable by everyone and owned by root. #error and its evil twin #warning emit a fatal error and a compilation warning, respectively, so whenever this file gets included, GCC will encounter a #error preprocessor directive resulting in the emission of a fatal error which causes the compilation to fail.

If you want to override this behavior for a single compilation, simply use gcc's -I parameter to specify the path to the directory where the real math.h lives. Since -I takes precedence over $C_INCLUDE_PATH and $CPLUS_INCLUDE_PATH this means that you then include the C library's version. For example, cc -o mathprogram -I/usr/include mathprogram.c will use the math.h in /usr/include when you #include <math.h> regardless of what might be in /usr/local/include/fail, because it looks first in /usr/include.

Since this only affects compilation (and only compilation started through a shell), everything that is already on your system will be completely unaffected (unless they have some weird dependencies to those two environment variables).

For c* headers, you may need to also create the corresponding *.h header with content identical to the c* header. This is because e.g. cmath might simply map to math.h (the name of the same header in C). Simply make another file just like the one above, but complain about math.h instead. (GCC doesn't care, but it makes diagnostics easier.) You may also need to put files in other places (I'm not sure exactly what include directory structure GCC wants for C++ headers); in that case, find / -name cmath (or something similar) will give you an idea of the structure you need to replicate under /usr/local/include/fail.

Do note that this will not stop people simply copying the relevant parts of the header file into their own source code; there is nothing magical about the header files from the compiler's point of view. Depending on exactly what you are trying to protect against, this may be an issue.

Upvotes: 1

suspectus
suspectus

Reputation: 17288

What about simply using a pre-processor symbol to omit the library header(s)? Compiling with the gcc option -DDONT_WANT_LIBS will fail due to the missing library declarations in the library header file.

#ifndef DONT_WANT_LIBS
#include<specific_library_header.h>
#endif
   ...
   ...

Upvotes: 1

Related Questions