diff --git a/Makefile.inc b/Makefile.inc index 7fef77e..f89373c 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -7,12 +7,12 @@ # # # Example Makefile # TARGET = app_name -# CONFIG = debug # SOURCES = main.cpp \ # tests.cpp \ # file.c # # # Some optional values that can be omitted +# CONFIG = [release|profile|debug] [application|library] [dynamic|static] # CFLAGS = -Os # DEFINES = DEBUG OS_LINUX # INCLUDE_PATHS = ./include @@ -20,6 +20,8 @@ # LIBRARIES = utils # OBJECTS_DIR = .obj # TARGET_DIR = ./bin +# VERSION_MAJOR = 1 +# VERSION_MINOR = 0 # # # The important part, including the generic set of Makefile rules # include ../Makefile.inc @@ -27,35 +29,77 @@ # -# Output paths +# Linking config options # -ifeq ($(TARGET_DIR),) - TARGET_DIR = . -endif -ifeq ($(OBJECTS_DIR),) - OBJECTS_DIR = .obj -endif +LINKING += $(findstring dynamic,$(CONFIG)) +LINKING += $(findstring static,$(CONFIG)) +LINKING := $(LINKING: =) + # -# Config +# Optimization config options # -ifeq ($(CONFIG),) - CONFIG = debug +OPTIMIZATION += $(findstring release,$(CONFIG)) +OPTIMIZATION += $(findstring profile,$(CONFIG)) +OPTIMIZATION += $(findstring debug,$(CONFIG)) +OPTIMIZATION := $(OPTIMIZATION: =) + + +# +# Template config options +# +TEMPLATE += $(findstring application,$(CONFIG)) +TEMPLATE += $(findstring library,$(CONFIG)) +TEMPLATE := $(TEMPLATE: =) + + +# +# Setup defaults +# +ifeq ($(TARGET_DIR: =),) + TARGET_DIR=. endif -PROGRAM_SUFFIX=_$(CONFIG) -ifeq ($(CONFIG),release) - PROGRAM_SUFFIX= +ifeq ($(OBJECTS_DIR: =),) + OBJECTS_DIR=.obj endif +ifeq ($(LINKING: =),) + LINKING=dynamic +endif +ifeq ($(OPTIMIZATION: =),) + OPTIMIZATION=debug +endif +ifeq ($(TEMPLATE: =), ) + TEMPLATE=application +endif +TARGET_SUFFIX= +ifeq ($(OPTIMIZATION: =),profile) + TARGET_SUFFIX=_p +endif +ifeq ($(OPTIMIZATION: =),debug) + TARGET_SUFFIX=_d +endif +ifeq ($(VERSION_MAJOR: =),) + VERSION_MAJOR=1 +endif +ifeq ($(VERSION_MINOR: =),) + VERSION_MINOR=0 +endif + # # Flags # -CFLAGS_debug := -g -O0 $(CFLAGS_debug) -CFLAGS_profile := -pg -DNDEBUG -O5 $(CFLAGS_profile) -CFLAGS_release := -DNDEBUG -O5 $(CFLAGS_release) -override CFLAGS := $(patsubst %,-I%,$(INCLUDE_PATHS)) $(patsubst %,-D%,$(DEFINES)) $(CFLAGS_$(CONFIG)) $(CFLAGS) -override CXXFLAGS := $(CFLAGS) -std=c++11 $(CXXFLAGS) -override LFLAGS := $(patsubst %,-L%,$(LIBRARY_PATHS)) $(patsubst %,-l%,$(LIBRARIES)) $(LFLAGS) +CFLAGS_debug := -DDEBUG -g -O0 $(CFLAGS_debug) +CFLAGS_profile := -DNDEBUG -pg -O5 $(CFLAGS_profile) +CFLAGS_release := -DNDEBUG -O5 $(CFLAGS_release) +CFLAGS_static := -DSTATIC -static $(CFLAGS_static) +CFLAGS_dynamic := -DDYNAMIC -fPIC $(CFLAGS_dynamic) +override CFLAGS := $(patsubst %,-I%,$(INCLUDE_PATHS)) $(patsubst %,-D%,$(DEFINES)) $(CFLAGS_$(OPTIMIZATION)) $(CFLAGS_$(LINKING)) $(CFLAGS) +override CXXFLAGS := $(CFLAGS) -std=c++11 $(CXXFLAGS) +LFLAGS_dynamic := $(LFLAGS_dynamic) +LFLAGS_static := -static $(LFLAGS_static) +override LFLAGS := $(patsubst %,-L%,$(LIBRARY_PATHS)) $(patsubst %,-l%,$(LIBRARIES)) $(LFLAGS) + # # Commands @@ -66,42 +110,111 @@ MKDIR = mkdir -p RM = rm -f + # # Targets # -COMPILED_OBJS = $(patsubst %.c,$(OBJECTS_DIR)/$(CONFIG)/%.o,$(filter %.c,$(SOURCES))) -COMPILED_OBJS += $(patsubst %.cpp,$(OBJECTS_DIR)/$(CONFIG)/%.o,$(filter %.cpp,$(SOURCES))) -OBJECTS += $(COMPILED_OBJS) -# To work out dependancies, one way which is not gcc specific is to just say everything in the include folder is: -# DEPENDS = $(patsubst %,$(INCLUDE_PATH)/%,$(HEADERS)) -# But thats not really correct, not every source file depends on everything in the include folder -# Also things may depend on other things outside of include or other source files. A better solution -# for C and C++ code is using gcc -MM option to generate a set of Makefile dependancies we can include (.depend) -DEPENDS = $(OBJECTS_DIR)/.depend -PROGRAM = $(TARGET_DIR)/$(TARGET)$(PROGRAM_SUFFIX) +OBJECTS_PATH = $(OBJECTS_DIR)/$(OPTIMIZATION)/$(LINKING) +COMPILED_OBJS = $(patsubst %.c,$(OBJECTS_PATH)/%.o,$(filter %.c,$(SOURCES))) +COMPILED_OBJS += $(patsubst %.cpp,$(OBJECTS_PATH)/%.o,$(filter %.cpp,$(SOURCES))) +OBJECTS += $(COMPILED_OBJS) +DEPENDS = $(OBJECTS_PATH)/.depend +LIBRARY = $(TARGET_DIR)/lib$(TARGET)$(TARGET_SUFFIX) +LIBRARY_static = $(LIBRARY).a +LIBRARY_dynamic = $(LIBRARY).so +TARGET_library = $(LIBRARY_$(LINKING)) +TARGET_application = $(TARGET_DIR)/$(TARGET)$(TARGET_SUFFIX) +TARGET_BINARY = $(TARGET_$(TEMPLATE)) + # # Rules # -$(PROGRAM): $(OBJECTS) - @$(MKDIR) $(dir $@) - $(LINK) -o $@ $^ $(CXXFLAGS) $(LFLAGS) +all: $(TARGET_BINARY) -$(OBJECTS_DIR)/$(CONFIG)/%.o: %.c $(DEPENDS) +$(TARGET_application): $(OBJECTS) + @$(MKDIR) $(dir $@) + $(LINK) $(LFLAGS_$(LINKING)) -o $@ $^ $(CXXFLAGS) $(LFLAGS) + +$(LIBRARY_static): $(OBJECTS) + @$(MKDIR) $(dir $@) + libtool $(LFLAGS_$(LINKING)) $^ -o $@ $(LFLAGS) + +$(LIBRARY_dynamic): $(OBJECTS) + @$(MKDIR) $(dir $@) + $(LINK) $(LFLAGS_$(LINKING)) -shared -Wl,-soname,$(@).$(VERSION_MAJOR) -o $@.$(VERSION_MAJOR).$(VERSION_MINOR) $^ $(CXXFLAGS) $(LFLAGS) + ln -s $@.$(VERSION_MAJOR).$(VERSION_MINOR) $@.$(VERSION_MAJOR) + ln -s $@.$(VERSION_MAJOR) $@ + +# To work out dependancies, a simple non-gcc specific way is just depend on everything in the include dir: +# DEPENDS = $(patsubst %,$(INCLUDE_PATH)/%,$(HEADERS)) +# But not every source depends on everything in the include dir, and it may not properly capture other dependancies. +# This solution is better, but GCC specific +$(DEPENDS): $(SOURCES) + @$(MKDIR) $(dir $@) + @$(CC) $(CFLAGS) -MM $(SOURCES) | sed 's,^\(.*\.o\),$(OBJECTS_PATH)\/\1,' > $@ + +debug: + $(MAKE) OPTIMIZATION=debug + +release: + $(MAKE) OPTIMIZATION=release + +profile: + $(MAKE) OPTIMIZATION=profile + +$(OBJECTS_PATH)/%.o: %.c $(DEPENDS) @$(MKDIR) $(dir $@) $(CC) -c -o $@ $< $(CFLAGS) -$(OBJECTS_DIR)/$(CONFIG)/%.o: %.cpp $(DEPENDS) +$(OBJECTS_PATH)/%.o: %.cpp $(DEPENDS) @$(MKDIR) $(dir $@) $(CXX) -c -o $@ $< $(CXXFLAGS) -$(DEPENDS): $(SOURCES) - @$(MKDIR) $(dir $@) - $(CC) $(CFLAGS) -MM $(SOURCES) | sed 's/^\(.*\.o\)/$(OBJECTS_DIR)\/$(CONFIG)\/\1/' > $@ +FAKE_TARGETS = debug release profile clean verify help all info null +MAKE_TARGETS = $(MAKE) -rpn null | sed -n -e '/^$$/ { n ; /^[^ .\#][^ ]*:/ { s/:.*$$// ; p ; } ; }' +REAL_TARGETS = $(MAKE_TARGETS) | sort | uniq | grep -E -v $(shell echo $(FAKE_TARGETS) | sed 's/ /\\|/g') -.PHONY: clean +null: + +verify: test-report.txt + @echo "" + @echo " Test Results:" + @echo " PASS count: "`grep -c "PASS" test-report.txt` + @echo " FAIL count: "`grep -c "FAIL" test-report.txt` + @echo "" + +help: + @echo "" + @echo " Usage:" + @echo " $(MAKE) [target]" + @echo "" + @echo " Targets:" + @echo " "`$(MAKE_TARGETS)` + @echo "" + +info: + @echo "" + @echo " Info:" + @echo " $(LINKING) linking" + @echo " $(OPTIMIZATION) optimization" + @echo " $(TEMPLATE) template" + @echo " target: $(TARGET_BINARY)" + @echo "" + @echo " Make targets:" + @echo " "`$(MAKE_TARGETS)` + @echo " Real targets:" + @echo " "`$(REAL_TARGETS)` + @echo " Fake targets:" + @echo " $(FAKE_TARGETS)" + @echo "" + clean: - $(RM) $(PROGRAM) $(DEPENDS) $(COMPILED_OBJS) core + $(RM) $(TARGET_BINARY) $(DEPENDS) $(COMPILED_OBJS) core + @#$(RM) `$(REAL_TARGETS)` + +.PHONY: $(FAKE_TARGETS) + # # Dependancies