-1

I am trying to compile a function (not called main) that can be integrated in another code or directly executed (after linking).

I try it one my mac, and work well. I finally test it on Linux (CentOS and ubuntu). However, the task looks harder as expected on Linux.

The source code is the following one (just to explain the problem)

test.cpp:

#include <cstdio>

#ifdef __cplusplus 
extern "C" {
#endif
    int test(int argc, char const *argv[]);
#ifdef __cplusplus
}
#endif

int test(int argc, char const *argv[]) {
    fprintf(stderr, "%s\n", "test");
    return 0;
}

Compilation line on MacOS

g++ -c test.cpp -o test.o && g++ test.o -o test -e _test

and on Linux

g++ -c test.cpp -o test.o && g++ test.o -o test -e test

I try on my MacOS with clang, g++ and Intel compiler, all 3 works fine.

And I try with g++ and the Intel compiler on Linux, always, the same error.

usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

Any advice, explanation or solution, on what I am doing wrong or missing would be very helpful. Thanks

Edit:

Currently, I have a "define" to create a main, but if we have lots of function we are obligated to do two compilations each time (one for the function version and one for the execution) and make finally the code heavier.

Like discussed in this topic is there a GCC compiler/linker option to change the name of main?

To don't do a XY I inherited from a bunch of small programs that I want to put to gather, that it is easier to use (for remote execution ...). However, each one need to be able to be executed independently if needed, for debugging,... I hesitate, between using "execv" and just convert each main as a function. I probably take the bad chose.

Edit: The final goal is to be able to have independent programs. But that we can call from an external software too.

Solution: The solution looks to be, to a call to the main through a dlopen

1 Answers1

4

You cannot do that (and even if it appears to work on MacOSX it is implementation specific and undefined behavior).

Linux crt0 is doing more complex stuff that what you think.

The C standard (e.g. n1570 for C11) requires a main function for hosted implementations (§5.1.2.2.1) :

The function called at program startup is named main. The implementation declares no prototype for this function.

And the C++ standard also requires a main and strongly requires some processing (e.g. construction of static data) to be done before main is running and after it has returned (and various crt0 tricks are implementing that feature on Linux).

If you want to understand gory details (and they are not easy!), study the ABI and the (free software) source code of the implementation of the crt0.

I am trying to compile a function (not called main) that can be integrated in another code

BTW, to use dynamically some code (e.g. plug-ins) from another program, consider using the dynamic linker. I recommend using the POSIX compliant dlopen(3) with dlsym(3) on position-independent code shared libraries. It works on most Unix flavors (including MacOSX & Linux & Solaris & AIX). For C++ code beware of name mangling so read at least the C++ dlopen mini howto.

Read also the Program Library HowTo.

Problems with libraries, they cannot be executed, no ?

I don't understand what that means. You certainly can load a plugin then run code inside it from the main program dlopen-ing it.

(and on Linux, some libraries like libc.so are even specially built to also work as an executable; I don't recommend this practice for your own code)

You might take several days to read Drepper's How To Write Shared Libraries (but it is advanced stuff).


If you want to add some code at runtime, read also this answer and that one.

The final goal is to be able to have independent program. But that we can call from an external software too

You can't do that (and it would make no sense). However, you could have conventions for communicating with other running programs (i.e. processes), using inter-process communication such as pipe(7)-s and many others. Read Advanced Linux Programming first and before coding. Read also Operating Systems : Three Easy Pieces

The solution looks to be, to a call to the main through a dlopen

Calling the main function via dlopen & dlsym is forbidden by the C++ standard (which disallows using a pointer to main). The main function has a very specific status and role (and is compiled specially; the compiler knows about main).

(perhaps calling main obtained by dlsym would appear to work on some Linux systems, but it certainly is undefined behavior so you should not do that)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Thanks, a lot for all these links (you add them faster that I read). But definitely, it's the solution to my problem. I didn't know that we can do that. – Mathieu Gravey Aug 01 '17 at 15:15
  • 1
    @MathieuGravey: Can't you **edit** please **your own question to add the actual motivation** (which you did not tell). Please do that – Basile Starynkevitch Aug 01 '17 at 15:17