This is a pretty contrived problem for which I struggle to see any real world application. That said, the following more or less works on Ubuntu 14.04 with gcc 4.8.4. Your mileage may vary.
This uses pragma weak to define main as a weak symbol.
Note that you still cannot execute the resulting mylib.so
directly because (at least on Linux) there are two different ELF formats for executable files and dynamically linked libraries.
I tried compiling the "shared library" with -fPIC
, but without -shared
to yield an executable ELF, but then you cannot get ld
to treat it as a shared library. dlopen
doesn't work either.
So I think this is the best you can do on *nix + gcc. This is going to be compiler specific, so who knows what you might do on windows.
Makefile:
all: test1 test2
#test1 links in mylib.so the "normal" way.
# -Wl,-rpath . is used to search the current directry for mylib.so
# at runtime so the library doesn't have to be "installed".
test1: test.c mylib.so
gcc -Wl,-rpath . -o $@ $^
#test2 builds an executable out of *just* the library, no other source.
test2: ./mylib.so
gcc -Wl,-rpath . -o $@ $^
# Target to compile the .so file.
mylib.so: lib.c
gcc -shared -o $@ -fPIC $^
# cleanup target.
.PHONY: clean
clean:
rm -f test1 test2 mylib.so
test.c:
extern void say_hello(const char * msg);
/* pragma weak is the real magic here that allows the library to
contain a 'main' -OR- allow application code to define its own
main. */
#pragma weak main
int main(int argc, char**argv)
{
say_hello("hello from test main\n");
return 0;
}
lib.c:
#include <stdio.h>
/* the shared library function used by both programs */
void say_hello(const char * msg)
{
puts(msg);
}
int main(int argc, char**argv)
{
say_hello("hi from library's main\n");
}