Hi community, Currently, I can handle these tasks in C and C++ programming with GCC on Linux: 1. Header file dependency; 2. rpath (for build and install); 3. soname for so versioning; 4. Debug or Release mode; 5. out-of-source build; I want to know if there are some other tasks which are missing from the above list and I need to handle them too. Many thanks! The above tasks can be handled in my CMake, Autotools, or manual Makefile. Below is my Makefile. --- $ tree --charset C . |-- build | |-- foo | | |-- foo | | |-- foo.d | | |-- foo.o | | |-- libfoo.so -> libfoo.so.1.2.3 | | |-- libfoo.so.1 -> libfoo.so.1.2.3 | | `-- libfoo.so.1.2.3 | `-- main | |-- main | |-- main.d | `-- main.o |-- foo | |-- foo.c | |-- foo.h | `-- Makefile |-- main | |-- main.c | `-- Makefile `-- Makefile $ --- # 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 lib$@.so.$(1) lib$@.so.$(word 1,$(subst ., ,$(1))) ; \ cd - >/dev/null 2>&1 ; @ cd $(OBJDIR)/$@ ; \ ln -f -s lib$@.so.$(1) lib$@.so ; \ cd - >/dev/null 2>&1 ; endef # make # BUILD_DIR=build ifdef BUILD_DIR export OBJDIR = $(abspath $(BUILD_DIR)) else export OBJDIR = $(abspath build) 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 cp -P $(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,'$$ORIGIN/../foo' LDFLAGS += -Wl,-rpath,'$$ORIGIN/../lib' #LDFLAGS += -Wl,-soname,$(soname) # make # NDEBUG=1 ifdef NDEBUG CFLAGS += -O3 # .cpp CPPFLAGS += -DNDEBUG else CFLAGS += -g # .cpp LDFLAGS += -fsanitize=address endif SUBDIR = $(OBJDIR)/$(lastword $(subst /, ,$(CURDIR))) all : $(SUBDIR)/main # $(SUBDIR)/foo # https://make.mad-scientist.net/papers/how-not-to-use-vpath/ $(SUBDIR)/main : $(addprefix $(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,'$$ORIGIN/../bar' LDFLAGS += -Wl,-rpath,'$$ORIGIN/../lib' LDFLAGS += -Wl,-soname,$(soname) # make # NDEBUG=1 ifdef NDEBUG CFLAGS += -O3 # .cpp CPPFLAGS += -DNDEBUG else CFLAGS += -g # .cpp LDFLAGS += -fsanitize=address endif SUBDIR = $(OBJDIR)/$(lastword $(subst /, ,$(CURDIR))) all : $(SUBDIR)/foo # $(SUBDIR)/bar # https://make.mad-scientist.net/papers/how-not-to-use-vpath/ $(SUBDIR)/foo : $(addprefix $(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 <signal.h> #include <assert.h> #ifndef NDEBUG #include <sanitizer/lsan_interface.h> #endif #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 }