You can use the -D
command line option to pass a value to a macro-definition from the commandline which calls the compiler.
https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
-D name=definition
The contents of definition are tokenized and processed as if they appeared during translation phase three in a ‘#define’ directive. In particular, the definition is truncated by embedded newline characters.
If you are invoking the preprocessor from a shell or shell-like program you may need to use the shell’s quoting syntax to protect characters such as spaces that have a meaning in the shell syntax.
If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). Parentheses are meaningful to most shells, so you should quote the option. With sh and csh, -D'name(args…)=definition' works.
-D and -U options are processed in the order they are given on the command line. All -imacros file and -include file options are processed after all -D and -U options.
I.e. if you normally call it (very simplified) like
gcc myfile.c
then, if you call like
gcc -D PROGRAM_NUMBER=20 myfile.c
it will basically compile the same, but also as if the file starts with
#define PROGRAM_NUMBER 20
in the very first line.
Nice recommendation by Basile, quote:
With GCC compile with warnings and debug info, so
gcc -Wall -Wextra -g -DPROGRAM_NUMBER=20
and use the GDB debugger
end-of-quote
That in turn means you do not need your many copies of the file with different #define
s, you can just use the same one over and over again.
I just recommend to start that one with this sanity check:
#ifndef PROGRAM_NUMBER
#error The PROGRAM_NUMBER has to be defined!
#endif
For Microsoft /D
seems to do the trick:
https://learn.microsoft.com/en-us/cpp/build/reference/d-preprocessor-definitions?view=vs-2019