GCC=gcc
CC=libtool --mode=compile $(GCC)
LINK=libtool --mode=link $(GCC)
CFLAGS=-c -O -Wall -fPIC
LDFLAGS=-L. -lmean
LDFLAGS_DLOPEN=-ldl
LDFLAGS_STATIC=-all-static
LDFLAGS_SHARED=-dynamic
SOURCES=libmean.h main.c mean.c dlopen.c
EXECUTABLES=dynamic libdynamic static libstatic dlopendynamic dlopenstatic

all: $(EXECUTABLES)

test: $(EXECUTABLES)
	./dynamic ; ./static ; LD_LIBRARY_PATH=. ./libdynamic ; ./libstatic ./dlopendynamic ; ./dlopenstatic

clean:
	rm -f *.o *.lo libmean.a

mrproper: clean
	rm -f libmean.so libmean.la $(EXECUTABLES)

vacuum: mrproper
	rm -f $(SOURCES)

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

dynamic: main.o mean.o
	$(LINK) $^ -o $@

libdynamic: main.o libmean.so
	$(LINK) $(LDFLAGS) $< -o $@

static: main.o mean.o
	$(LINK) $(LDFLAGS_STATIC) $^ -o $@

libstatic: main.o libmean.la
	$(LINK) $(LDFLAGS) $(LDFLAGS_STATIC) $< -o $@

dlopendynamic: dlopen.o libmean.so
	$(LINK) $(LDFLAGS_DLOPEN) $< -o $@

dlopenstatic: dlopen.o libmean.a
	$(LINK) $(LDFLAGS_DLOPEN) $(LDFLAGS_STATIC) $< -o $@ -dlpreopen libmean.a
	echo "should not: http://www.gnu.org/software/libtool/manual/libtool.html#Dlpreopening"

libmean.so: mean.o
	$(GCC) -shared $< -o $@

# Don't know how to do that with libtool
#libmean.so: mean.o
#	$(LINK) $(CFLAGS) $(CFLAGS_SHARED) $(LDFLAGS_SHARED) $< -o $@

libmean.a: mean.o
	$(LINK) $(CFLAGS) $< -o $@

libmean.la: mean.lo
	$(LINK) $(CFLAGS) $(LDFLAGS_STATIC) $< -o $@

libmean.h:
	echo "double mean(double, double);">libmean.h

main.c: libmean.h
	echo "#include <stdio.h>\n#include \"libmean.h\"\n\nint main(int argc, char* argv[]) {\ndouble v1, v2, m;\nv1 = 5.2;\nv2 = 7.9;\nm  = mean(v1, v2);\nprintf(\"The mean of %3.2f and %3.2f is %3.2f\\\n\", v1, v2, m);\nreturn 0;\n}">main.c

mean.c:
	echo "//#include <stdio.h>\n\ndouble mean(double a, double b) {\nreturn (a+b) / 2;\n}">mean.c

dlopen.c:
	echo "#include <stdio.h>\n#include <stdlib.h>\n#include <dlfcn.h>\n\nint\nmain(int argc, char **argv)\n{\nvoid *handle;\ndouble (*mmean)(double, double);\nchar *error;\n\nhandle = dlopen(\"./libmean.so\", RTLD_LAZY);\nif (!handle) {\nfprintf(stderr, \"%s\\\n\", dlerror());\nexit(EXIT_FAILURE);\n}\n\ndlerror();    /* Clear any existing error */\n*(void **) (&mmean) = dlsym(handle, \"mean\");\n\nif ((error = dlerror()) != NULL)  {\nfprintf(stderr, \"%s\\\n\", error);\nexit(EXIT_FAILURE);\n}\n\nprintf(\"The mean of 5.20 and 7.90 is %3.2f\\\n\", (*mmean)(5.2, 7.9));\ndlclose(handle);\nexit(EXIT_SUCCESS);\n}\n\n">dlopen.c
