Trouble using scriptedmain in MinGW

1k Views Asked by At

I want to reproduce this Perl code in C, bundling API and CLI in the same C source code file (scriptedmain). This is done in Python with if __name__=="__main__": main() and in gcc/Unix, this looks like:

$ gcc -o scriptedmain scriptedmain.c scriptedmain.h
$ ./scriptedmain
Main: The meaning of life is 42
$ gcc -o test test.c scriptedmain.c scriptedmain.h
$ ./test
Test: The meaning of life is 42

scriptedmain.h

int meaning_of_life();

scriptedmain.c

#include <stdio.h>

int meaning_of_life() {
    return 42;
}

int __attribute__((weak)) main() {
    printf("Main: The meaning of life is %d\n", meaning_of_life());

    return 0;
}

test.c

#include "scriptedmain.h"
#include <stdio.h>

extern int meaning_of_life();

int main() {
    printf("Test: The meaning of life is %d\n", meaning_of_life());
    return 0;
}

However, when I try to compile with gcc/Strawberry, I get:

C:\>gcc -o scriptedmain scriptedmain.c scriptedmain.h
c:/strawberry/c/bin/../lib/gcc/i686-w64-mingw32/4.4.3/../../../../i686-w64-mingw32/lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o): In function `main':
/opt/W64_156151-src.32/build-crt/../mingw-w64-crt/crt/crt0_c.c:18: undefined reference to `WinMain@16'
collect2: ld returned 1 exit status

And when I try to compile with gcc/MinGW, I get:

$ gcc -o scriptedmain -mwindows scriptedmain.c scriptedmain.h
c:/mingw/bin/../lib/gcc/mingw32/4.5.2/../../../libmingw32.a(main.o):main.c:(.text+0x104): undefined reference to `WinMain@16'
collect2: ld returned 1 exit status

How can I get GCC in Windows to recognize the __attribute__((weak)) syntax?

Also, G++ shows the same error.

2

There are 2 best solutions below

3
On

I found a solution that works in Windows and in Unix: Simply wrap main() in preprocessor instructions that omits it unless explicit compiler flags are set.

scriptedmain.c:

#include <stdio.h>

int meaning_of_life() {
    return 42;
}

#ifdef SCRIPTEDMAIN

int main() {
    printf("Main: The meaning of life is %d\n", meaning_of_life());

    return 0;
}

#endif

Now main() will be entirely omitted unless you compile with

gcc -o scriptedmain -DSCRIPTEDMAIN scriptedmain.c scriptedmain.h

This code is safe to import into other C code, because the preprocessor will strip out main(), leaving you to code your own main. The best part is that this solution no longer depends on obscure compiler macros, only simple preprocessor instructions. This solution works for C++ as well.

4
On

This isn't good practice in C regardless of operating system. Best practice in C for anything complicated enough to be worth separating into library and driver is to put main in a file all by itself.