My software has one main for normal use and a different one for unit tests. I would just love it if there was an option to gcc to specify which "main" function to use.
Put them in separate files, and specify one .c file for normal use, and one .c file for testing.
Alternately, #define
testing on the commandline using test builds and use something like:
int main(int argc, char *argv[])
{
#ifdef TESTING
return TestMain(argc, argv);
#else
return NormalMain(argc, argv);
#endif
}
int TestMain(int argc, char *argv[])
{
// Do testing in here
}
int NormalMain(int argc, char *argv[])
{
//Do normal stuff in here
}
Edit: Billy beat me to the answer, but here's a bit more background
More directly, main is usually more a function of the standard library. The thing that calls main
isn't C, but rather the standard library. The OS loads the application, transfers control to the library's entry point (_start
in GCC), and the library ultimately calls main
. This is why the entry point for a windows application can be WinMain
, and not the usual. Embedded programming can have the same sort of thing. If you don't have a standard library, you have to write the entry point that the library normally provides (among other things), and you can name it whatever you want.
In the GCC toolchain, you can also replace the library's entry point with your own by using the -e
option. (For that matter, you can also remove the library entirely.)
Make your own:
int main(int argc, char *argv[])
{
#if defined(BUILD_UNIT_TESTS)
return main_unittest(argc, argv);
#endif
#if defined(BUILD_RUNTIME)
return main_run(argc, argv);
#endif
}
If you don't like ifdef
, then write two main modules that contain only main. Link one in for unit tests and the other in for normal use.
I'm assuming that you're using Make or something similar. I would create two files that contain different implementations of the main function, then in the makefile, define two separate targets that have identical dependencies on the rest of your files, except one uses your "unit test main" and the other your "normal main". Something like this:
normal: main_normal.c file1.c file2.c
unittest: main_unittest.c file1.c file2.c
As long as the "normal" target is closer to the top of the makefile, then typing "make" will choose it by default. You would have to type "make unittest" to build your test target.
` #ifdef TESTING
int main()
{
/* testing code here */
}
#else
int main()
{
/* normal code here */
}
#endif
$ gcc -DTESTING=1 -o a.out filename.c #building for testing
$ gcc -UTESTING -o a.out filename.c #building for normal purposes `
man gcc
showed me the -D and -U
You can use macros to rename one function to main.
#ifdef TESTING
#define test_main main
#else
#define real_main main
#endif
int test_main( int argc, char *argv[] ) { ... }
int real_main( int argc, char *argv[] ) { ... }
The other answers here are quite reasonable, but strictly speaking the problem you have is not really one with GCC, but rather with the C runtime. You can specify an entry point to your program using the -e
flag to ld
. My documentation says:
-e symbol_name
Specifies the entry point of a main executable. By default the entry name is "start" which is found in crt1.o which contains the glue code need to set up and call main().
That means you can override the entry point if you like, but you may not want to do that for a C program you intend to run normally on your machine, since start
might do all kinds of OS specific stuff that's required before your program runs. If you can implement your own start
, you could do what you want.
You may have to run ld
separately to use them, but ld supports scripts to define many aspects of the output file (including the entry point).
I'd tend to use different files and make for testing and production builds, but if you did have a file with
int test_main (int argc, char*argv[])
and
int prod_main (int argc, char*argv[])
then the compiler options to select one or the other as the main are -Dtest_main=main
and -Dprod_main=main