woodb...@gmail.com writes:
>Until recently I had one directory where I built both
>a library and two executables (tiers). Now I've added
>a new directory called "tiers" and moved the code for
>the tiers there. I think this will help people who
>are interested in learning to use my software.
>
>The downside to this is I'm specifying CXX and CXXFLAGS
>(and maybe a few other things like that) in multiple
>makefiles. I figured out a way where I could pass those
>from the higher level makefile to the lower level --
>something like:
>
>$(MAKE) -C tiers CXX=$(CXX) CXXFLAGS=$(CXXFLAGS)
A common solution for this is to encapsulate your
definitions in a file at the top level called
Makefile.defs.
Encapsulate your rules in a top-level file called Makefile.rules.
e.g:
Makefile.defs:
--------------
CINCLUDES = -I$(TOP)/include
CINCLUDES += -I$(TOP)
DEBUGFLAGS = -g
GXXFLAGS = -mno-red-zone
GXXFLAGS += -fno-strict-aliasing
GXXFLAGS += -fno-stack-protector
GXXFLAGS += -fno-exceptions
GXXFLAGS += -Wall
GXXFLAGS += -mtune=native
GXXFLAGS += -O2
CXXFLAGS = $(DEBUGFLAGS) $(CINCLUDES) $(strip $(GXXFLAGS))
LDFLAGS += -Wl,-E
SOLDFLAGS += -Wl,-E -shared -lpthread -nostartfiles -nodefaultlibs -nostdlib
LIB = $(TOP)/lib
LIBCOMMON = $(LIB)/libcommon.a
LIBPROCESSOR = $(LIB)/libprocessor.a
LIBMP = $(LIB)/libmp.a
LIBDIRECTIVE = $(LIB)/libdirective.a
LIBOP = $(LIB)/libop.a
SIM_LIBS = $(LIBMP)
SIM_LIBS += $(LIBPROCESSOR)
SIM_LIBS += $(LIBCOMMON)
SIM_LIBS += $(LIBFETCH)
Makefile.rules:
---------------
#
# Common Makefile Rules
#
%.o: %.c
@echo " COMPILE $<"
$(HUSHCOMPILE)$(CC) $(CFLAGS) -MMD -o $@ -c $<
%.o: %.cpp
@echo " COMPILE $<"
$(HUSHCOMPILE)$(COMPILE.cpp) -MMD -o $@ $<
%.s: %.cpp
@echo " COMPILE-TO-ASM $<"
$(HUSHCOMPILE)$(COMPILE.cpp) -MMD -S $<
%.so: %.o
@echo " BUILDSO $@"
$(HUSHCOMPILE)$(LD) -o $@ $(SOLDFLAGS)
%.icm5: %.sprasm
@echo " SPRASM $<"
$(HUSHCOMPILE)$(SPRASM) $(SPRASM_FLAGS) -o $@ $<
buildsubs:: $(DIRS) subdirs
clean:: subdirs
.PHONY: subdirs clean $(SUBDIRS)
clobber:: clean subdirs
subdirs: $(SUBDIRS)
$(SUBDIRS):
@ $(MAKE) -C $@ $(MAKECMDGOALS) $(MAKEARGS)
clean::
@-$(RM) -f $(CLEAN_FILES) $(OBJECTS)
@ if [ -n "$(CLEAN_DIRS)" ]; then \
$(RM) -rf $(CLEAN_DIRS); \
fi
Then the top-level makefile:
Makefile:
---------
TOP=.
include $(TOP)/Makefile.defs
TARGET = vsim
SUBDIRS += common
SUBDIRS += io/dlps
SUBDIRS += processor
SUBDIRS += mp
SUBDIRS += utilities
SOURCES = main.cpp
OBJECTS = $(SOURCES:.cpp=.o)
HOST_LIBS = -lreadline -lcurses -lpthread -lgmp -ldl
DIRS = lib
CLOBBER_FILES += $(TARGET) $(TARGET).csc $(TARGET).
csc.in $(TARGET).csc.po
CLOBBER_FILES += include/built.h
CLOBBER_DIRS += $(DIRS)
all: $(TARGET)
main.cpp: vsim_built buildsubs
utilities: common
$(SIM_LIBS): $(SUBDIRS)
$(TARGET):: $(OBJECTS) $(SUBDIRS) $(SIM_LIBS)
$(CXX) $(DEBUGFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(SIM_LIBS) $(HOST_LIBS)
$(OBJCOPY) --only-keep-debug $@ $@.debuginfo
$(OBJCOPY) --strip-debug $@
$(OBJCOPY) --add-gnu-debuglink=$@.debuginfo $@
include $(TOP)/Makefile.rules
-include *.d
common/Makefile:
----------------
TOP=..
include $(TOP)/Makefile.defs
SOURCES = command_table.cpp
SOURCES += contention_protocol.cpp
SOURCES += dcp.cpp
SOURCES += dcp_header.cpp
SOURCES += disassembler.cpp
SOURCES += ebcdic.cpp
SOURCES += file_logger.cpp
SOURCES += mcs.cpp
SOURCES += mux_logger.cpp
SOURCES += netport.cpp
SOURCES += osdep.cpp
SOURCES += pollselect.cpp
SOURCES += pool.cpp
SOURCES += protocol.cpp
SOURCES += serialport.cpp
SOURCES += station.cpp
SOURCES += syslog_logger.cpp
SOURCES += thread.cpp
SOURCES += timer.cpp
SOURCES += timer_manager.cpp
CXXFLAGS += -fpic
OBJECTS = $(SOURCES:.cpp=.o)
all: $(LIBCOMMON)
$(LIBCOMMON): $(OBJECTS)
ar cr $@ $+
include $(TOP)/Makefile.rules
---------
This will automatically descend into any directory
listed in SUBDIRS at each level and
build the Makefile in that subdirectory using the
common definitions in $(TOP)/Makefile.defs and $(TOP)/Makefile.rules
Objects from each subdirectory are archived in a archive
library specific to each subdirectory (since when using
parallel make, the 'ar' command isn't "parallel make" safe.