Makefile -out-of-source
# Makefile for top dir
# $(call makever,1.2.3)
# major.minor.patch
# libtool manual: -version-number
define makever
? @ $(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
# make # BUILD_DIR=build
ifndef BUILD_DIR
export OBJDIR = $(abspath build)
else
export OBJDIR = $(abspath $(BUILD_DIR))
endif
SUBDIRS = main foo
all : $(SUBDIRS)
install : $(SUBDIRS)
$(SUBDIRS) : | $(OBJDIR)
$(OBJDIR) : ; @ mkdir $@
main : foo
main : ; @ $(MAKE) -C $@
foo : ; $(call makever,1.2.3)
# make DESTDIR=~/foo install
# Alexandre Duret-Lutz’s Autotools Tutorial (without animations):
# "is ready to be uncompressed in / on many hosts"
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 :
? @ for dir in $(SUBDIRS); do \
? ? $(MAKE) -C $$dir $@; \
? done
? -rm -fr $(OBJDIR)
.PHONY : $(SUBDIRS) all install clean
---
# 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
SUBDIR ? ?= $(OBJDIR)/main
all : $(SUBDIR)/main # $(SUBDIR)/foo
$(SUBDIR)/main : $(SUBDIR)/$(patsubst %.c,%.o,$(wildcard *.c)) # .cpp
? $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(SUBDIR)/%.o : %.c | $(SUBDIR) # .cpp
? $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
$(SUBDIR) : ; @ mkdir $@
-include $(SUBDIR)/*.d
clean : ; -rm -fr $(SUBDIR)
.PHONY : all clean
---
# Makefile for subdir
# build shared library with -fPIC, -shared
CFLAGS ? ?= -fPIC # -g -O3 # CXXFLAGS for .cpp
CPPFLAGS ?= -MMD -MP # -I../bar
LDFLAGS ? = -shared # -L$(OBJDIR)/bar
LDLIBS ? ?= # -lbar
#CC ? ? ? = $(CXX) # link with CXX for .cpp
LDFLAGS ?+= -Wl,-rpath,$(OBJDIR)/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
SUBDIR ? ?= $(OBJDIR)/foo
all : $(SUBDIR)/foo # $(SUBDIR)/bar
$(SUBDIR)/foo : $(SUBDIR)/$(patsubst %.c,%.o,$(wildcard *.c)) # .cpp
? $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(SUBDIR)/%.o : %.c | $(SUBDIR) # .cpp
? $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
$(SUBDIR) : ; @ mkdir $@
-include $(SUBDIR)/*.d
clean : ; -rm -fr $(SUBDIR)
.PHONY : all clean
---
#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); // -DNDEBUG
}