Search code examples
linuxgccwindows-10mingwld

GNC C: Ideas over main starting point confusions?


An extremely simple problem demonstration:

#include <stdio.h>


void myFunc()
{
    puts("Greetings, Code 'Mon ...");
}

int main(int argc, char *argv[])
{
    puts("zMain 01.\n");
    myFunc();
    puts("zMain 02.\n");
}

Target main_test2.run emits "file not found" as made via gcc on Ubuntu 20.04.6 LTS:

...
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401030
...
/main_test/yikes01$ ./main_test2.run
bash: ./main_test2.run: No such file or directory

The same runs, yet ignores main() as the |starting| point on MinGW / Windows 10:

c:\tmp\main_test\yikes01>main_test2.run
Greetings, Code 'Mon ...

c:\tmp\main_test\yikes01>main_test.run
zMain 01.

Greetings, Code 'Mon ...
zMain 02.

Project + makefile is at github, yet here is the later:

cc=gcc -v
opts = 
link = ld

ifdef OS
    libs = -LC:/Windows/System32 -lkernel32 -lmingw32 -lcrtdll 
else
    libs = -lc
endif

all: main_test2.run main_test.run Makefile

# First function becomes void main(void) ...
main_test2.run: main_test.c
    $(cc) $(opts) -c main_test.c
    $(link)  main_test.o -o main_test2.run $(libs)
    rm -f main_test.o
    
main_test.run: main_test.c
    gcc main_test.c -o main_test.run

clean:
    rm -f *.o
    rm -f *.run

Any ideas what's going spare, here? How to link in gmon_start?

Note: Swapping around parameters does indeed create some marginally different results - direct compliation at the CLI (main_test.run) always works.


Solution

  • Change link = ld to link = gcc, in which case you can also discard libs = -lc. The bare linker (ld) only links what you specify, which does not include program startup code. When invoked via gcc (as is usual), gcc appends boilerplate to the linker's commandline, including the required language runtime and startup code.

    After that change, you will be able to see the extra libraries and object files added to the linkage if you inspect the output with gcc -v.