Prevent inclusion of stdio.h (or other standard header)

A codebase I work with has historically tried--purposefully--to avoid dependencies on stdio.h creeping in. It has its own print formatting and mechanisms, and those are what's supposed to be used instead of printf etc.

But someone adds a dependency every so often that has to get noticed and taken out. So I tried to make an alarm for the easiest of cases:

#if !defined(NDEBUG)
   void printf(float dont_link_with_stdio_h);
#endif

The gcc people seem to have been thinking along the lines of stopping easy errors too, because there's a helpful message if you do this...whether you've included <stdio.h> or not.

conflicting types for built-in function 'printf'

There's a way to turn this warning off (-fno-builtin). And there are all kinds of approaches that would do things like filter the symbol dump for things you don't want to be there...

But is there a trivially easy non-warning-causing (if you didn't include stdio.h) way to alert someone that they've introduced an unwanted printf usage?

Upvotes: 12

Views: 850

Answers (3)

Peter
Peter

Reputation: 36617

I wouldn't touch the source files at all. I'd modify the build script. Much easier to maintain, and much easier to prevent people from circumventing the restriction (e.g. by changing the code which causes compilation to fail).

For example, in a makefile, assuming you have an all target that build everything

all:

   grep stdio *.h *.c
   if ["$?" -eq 0 ]; then
       echo "Do not use stdio.  Contact Joe for info"; exit 2;
   fi

   <other stuff to do the build here>

You can also do it on particular targets. For example, if you have a target that compiles a .c file to produce a .o file, just check the .c file before compiling it.

  %.o : %.c

       grep stdio $<
       if ["$?" -eq 0 ]; then
           echo "Do not use stdio.  Contact Joe for info"; exit 2;
       fi

       $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

Your only problem now is what to do if you have someone who is determined to bypass your restriction (e.g. by #include "bypass.joe" where bypass.joe has an #include <stdio.h>). For that, look up tools to generate dependencies (e.g. gcc -MM, makedepend, etc) and use that to set up a way to search all of the files your source files depend on. If someone is that determined, also set protections on your makefiles so only you can edit them.

EDIT: If you have a tool set up to generate a dependency file, simply search that file for stdio. If any compilation unit, directly or indirectly, includes stdio.h , then it will be listed in the dependency file.

Upvotes: 3

Cornstalks
Cornstalks

Reputation: 38228

You can redefine printf to be some nasty value that will cause a compilation or linking error. For example:

#define printf do_not_include_stdio_h
#include <stdio.h>

int main(void) {
    printf("Hello, world!\n");
    return 0;
}

produces the output:

undefined reference to `do_not_include_stdio_h'

You can munge the macro if you want it to be an even more obscure name or include invalid symbols if you're worried that some poor soul will have defined do_not_include_stdio_h.

You can set the macro definition in the compiler flags so you don't have to manually edit the file(s). For example:

gcc -Dprintf=do_not_include_stdio_h my_file.c

Upvotes: 6

user3386109
user3386109

Reputation: 34839

To prevent inclusion of <stdio.h>, I would go with

#if !defined(NDEBUG)
#if defined(EOF)
#error Do not include stdio.h, contact Joe for more information
#endif
#endif

Upvotes: 2

Related Questions