简体   繁体   中英

is it possible to use the preprocessor __file__ to generate a #define in C?

In order to improve the aesthetics of some code, I would like to have a .h file contain some code that sets a #define based on which file the .h file is included from. For example

#if (__file__ == "main.c")
#define MOUDLE MODULE_MAIN
#elif (__file__ == "foo.c")
#define MODULE MODULE_FOO
#endif

Is there any way to accomplish something like this? The main motivation is to avoid putting a #define MODULE at the top of every file and instead have one location where the mapping is defined and to just include the same .h file.

No, you can't do this. #if can only do integer expressions. It knows nothing about strings or how to compare them.

What you want is not possible with the standard C preprocessor. Check by reading the C standard, eg n1570 , or some C reference , or the wikipage on the C preprocessor , or the GNU cpp manual .

But consider another way to achieve the same: configure appropriately your build automation .

For example, if you use make , then edit your Makefile appropriately. How to do that is a very different question.

You could have a rule for make which passes a specific -DMODULE= name to gcc

For example in my bismon (on github) the Makefile has near line 141 something similar to

modules/modbm_%.so: modules/modbm_%.c bismon.h  $(GENERATED_HEADERS) $(BM_HEADERS)
   $(CCACHE) $(LINK.c) -fPIC \
      -DBISMON_MODID=$(patsubst modules/modbm_%.c,_%,$<) -shared $< -o $@

Be creative . The build machinery is part of your source code. Adapt it to do what you want. Don't expect the standard preprocessor to cover all your needs. Learn how to invoke GCC (or your favorite compiler) on the command line . In some cases , it is even worthwhile to generate some C file (perhaps some header file), and you might use another preprocessor (like GPP or m4) for that purpose.

Remember that the compiler (notably GCC and Clang ) is a command line program, that you should drive from something else (like make , ninja or many other build automation tools).

(even on microsoft systems the compiler is still a command line thing, but that fact is often ignored)

BTW, I dislike many IDE s because they are hiding the build process, and you need to master it. So you need to configure it (eg by writing your Makefile or something else) and to understand and tailor it.

The main motivation is to avoid putting a #define MODULE at the top of every file and instead have one location where the mapping is defined

That single location defining such a mapping should probably be your build infrastructure (eg your Makefile if using make ); you'll adapt it to invoke gcc or clang (or most other C compilers) with an appropriate -DMODULE= name flag. (BTW, you also want the convention that your base name of sources files are C identifiers, so you won't have any a-1.c file -since a-1 is not an identifier-, but a bcde.c one).

If using GNU make , read its documentation , then run make -p to understand the rules (both builtin, and custom) relevant to your case. Then consider perhaps a rule similar to:

%.o: %.c $(YOURHEADERS)
     $(COMPILE.c) -DMODULE=$(patsubst %.c,MODULE_%,$^) -c $< -o $@

but adapt that rule to your needs. (you could need some $(shell ... ) inside it if your file names are lower cases, and you want upper case MODULE ).

BTW, you could also generate parts of your Makefile (or have some generated C files, which you would #include appropriately).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM