Makefile out-of-source build
## src/Makefile
# Makefile for top dir
export OBJDIR = $(dir $(realpath $(lastword $(MAKEFILE_LIST))))/objdir_tmp
# $(call version_number,1.2.3)
# major.minor.patch
# libtool manual 4.2: -version-number
define version_number
$(MAKE) -C $@ soname=lib$@.so.$(word 1,$(subst ., ,$(1)))
cp $(OBJDIR)/$@/$@ $(OBJDIR)/$@/lib$@.so.$(1)
cd $(OBJDIR)/$@; ln -f -s $(OBJDIR)/$@/lib$@.so.$(1) $(OBJDIR)/$@/lib$@.so.$(word 1,$(subst ., ,$(1))); cd ..
cd $(OBJDIR)/$@; ln -f -s $(OBJDIR)/$@/lib$@.so.$(1) $(OBJDIR)/$@/lib$@.so; cd ..
endef
SUBDIRS = main foo
all : $(SUBDIRS)
install : $(SUBDIRS)
main : foo
main : ; $(MAKE) -C $@
foo : ; $(call version_number,6.2.3)
# make DESTDIR=~/foo install
install :
install -d "$(DESTDIR)/usr/local/bin"
install -d "$(DESTDIR)/usr/local/lib"
install -m 0755 $(OBJDIR)/main/main "$(DESTDIR)/usr/local/bin"
install -m 0755 $(OBJDIR)/foo/*.so* "$(DESTDIR)/usr/local/lib"
clean : ; -rm -fr $(OBJDIR)
.PHONY : $(SUBDIRS) all install clean
---
## src/main/Makefile
# Makefile for subdir
# build shared library with -fPIC, -shared
CFLAGS = # -g -O3 -fPIC # CXXFLAGS for .cpp
CPPFLAGS = -MMD -MP -I../foo
LDFLAGS = -L$(OBJDIR)/foo # -shared
LDLIBS = -lfoo
#CC = $(CXX) # link with CXX for .cpp
LDFLAGS += -Wl,-rpath,$(OBJDIR)/foo
LDFLAGS += -Wl,-rpath,'$$ORIGIN/../lib'
#LDFLAGS += -Wl,-soname,$(soname)
# make # NDEBUG=1
ifdef NDEBUG
CPPFLAGS += -DNDEBUG
CFLAGS += -O3 # .cpp
else
CFLAGS += -g # .cpp
LDFLAGS += -fsanitize=address
endif
all : $(OBJDIR)/main/main # foo
$(OBJDIR)/main/main : $(OBJDIR)/main/$(patsubst %.c,%.o,$(wildcard *.c))
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ # CXX for .cpp
$(OBJDIR)/main/%.o : %.c | $(OBJDIR)/main
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< # CXX CXXFLAGS for .cpp
$(OBJDIR)/main: ; mkdir -p $(OBJDIR)/main
-include $(OBJDIR)/main/*.d
clean : ; -rm -fr $(OBJDIR)
.PHONY : all clean
---
## src/foo/Makefile
# Makefile for subdir
# build shared library with -fPIC, -shared
CFLAGS = -fPIC # -g -O3 # CXXFLAGS for .cpp
CPPFLAGS = -MMD -MP # -I../bar
LDFLAGS = -shared # -L../bar
LDLIBS = # -lbar
#CC = $(CXX) # link with CXX for .cpp
LDFLAGS += -Wl,-rpath,'$$ORIGIN/../bar'
LDFLAGS += -Wl,-rpath,'$$ORIGIN/../lib'
LDFLAGS += -Wl,-soname,$(soname)
# make # NDEBUG=1
ifdef NDEBUG
CPPFLAGS += -DNDEBUG
CFLAGS += -O3 # .cpp
else
CFLAGS += -g # .cpp
LDFLAGS += -fsanitize=address
endif
all : $(OBJDIR)/foo/foo # foo
$(OBJDIR)/foo/foo : $(OBJDIR)/foo/$(patsubst %.c,%.o,$(wildcard *.c))
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ # CXX for .cpp
$(OBJDIR)/foo/%.o : %.c | $(OBJDIR)/foo
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< # CXX CXXFLAGS for .cpp
$(OBJDIR)/foo: ; mkdir -p $(OBJDIR)/foo
-include $(OBJDIR)/foo/*.d
clean : ; -rm -fr $(OBJDIR)
.PHONY : all clean
---
// main.c
#include <stdio.h>
#include <sanitizer/lsan_interface.h>
#include <signal.h>
#include <assert.h>
#include "foo.h"
void handlerCont(int signum) {
printf("SIGCONT %d\n", signum);
#ifndef NDEBUG
__lsan_do_recoverable_leak_check();
#endif
}
int main() {
signal(SIGCONT, handlerCont); // kill -CONT 123 # pid
printf("main\n");
foo();
int a[1024];
int n = 10240;
// a[n] = 1; //asan
// assert(0);
}

