#
# Copyright (c) 1996, 1998, 1999, 2000 University of Utah and the Flux Group.
# All rights reserved.
# 
# This file is part of the Flux OSKit.  The OSKit is free software, also known
# as "open source;" you can redistribute it and/or modify it under the terms
# of the GNU General Public License (GPL), version 2, as published by the Free
# Software Foundation (FSF).  To explore alternate licensing terms, contact
# the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
# 
# The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GPL for more details.  You should have
# received a copy of the GPL along with the OSKit; see the file COPYING.  If
# not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
#

# This makefile defines standard symbols and rules
# used by the makefiles in the various OS toolkit subdirectories.
# It is heavily dependent on GNU make running on something like Unix.
# Building things with different tools requires a different set of makefiles.
#
# OSKIT_SRCDIR must be set to the top-level directory of the OS toolkit.
# (The current directory is assumed to be the object directory.)
#
# SRCDIRS must be set to a list of dirs that contain code.
#	  These directories are added to the VPATH,
#         to the -I line, and are searched for .c (and possibly .S) files.
#	  All .c files found will be compiled.
#
# MOSTLY_SRCDIRS can be set and is similar to SRCDIRS but not all .c files
#		 in these directories are compiled---only ones explicitly
#		 added to OBJFILES
#
# OBJDIR must be set to the top-level object directory
# (i.e. a series of `..'s indicating how deep we are at the moment).
#
# DEFINES can be set to a string of -D options (e.g. -DDEBUG).
# INCDIRS can be a list of system include directories
#	  to be searched by #include <>'s.
# LIBDIRS can be a list of library directories.
#
# OSKIT_CPPFLAGS can be set to other flags for the C preprocessor
#		 and anything that uses it.
# OSKIT_CFLAGS can be set to other flags for the C compiler.
# OSKIT_LDFLAGS can be set to other flags for the linker.
#
# The standard flags variables (CFLAGS, CPPFLAGS, etc.)
# are used by the rules but never defined,
# so you can supply them on the make command line
# (e.g. `make CFLAGS=-save-temps').
#
ifndef _oskit_makerules_
_oskit_makerules_ = yes

# This is just here in case someone happens to include this before the
# more specific GNUmakerules.  Otherwise the first (default) rule ends
# up being the install rule. =(
default: all

# Include architecture-specific rules.
include $(OSKIT_SRCDIR)/GNUmakerules-$(HOST_ARCH)


# Where to get includes and libraries from.
INCDIRS += $(OBJDIR) $(OSKIT_SRCDIR)
LIBDIRS += $(OBJDIR)/lib

# Compilation flags.
# We prefix these with OSKIT_ rather than using the "normal" variables
# so that you can override the normal variables on the make command line
# in order to add options (e.g. 'make CFLAGS=-save-temps').
# The -I- flag divides the -I line:
#	-I flags before -I- are searched for #include "file" only, not <file>
#	-I flags after -I- are searched for all include files.
OSKIT_CPPFLAGS	+= -MD $(DEFINES) -I. $(addprefix -I,$(SRCDIRS)) \
		    $(addprefix -I,$(MOSTLY_SRCDIRS)) \
		    -I- $(addprefix -I,$(INCDIRS)) -nostdinc
OSKIT_CFLAGS	+= $(OSKIT_CPPFLAGS) -Wall $(OSKIT_FFLAGS)
OSKIT_LDFLAGS	+= $(addprefix -L,$(LIBDIRS))

# Add a `-g' if the debug option is set.
ifneq "$(filter debug, $(OSKIT_OPTIONS))" ""
OSKIT_CFLAGS 	+= -O -g
else
OSKIT_CFLAGS 	+= -O2 -g
endif

## If -s is passed to make, make things real quiet
ifeq (s,$(findstring s,$(MAKEFLAGS)))
OSKIT_QUIET_MAKE_INFORM=@echo
ARFLAGS=r  ## drop the v from the default
else
OSKIT_QUIET_MAKE_INFORM=@true
endif


# Where to find source files.
# Using specific patterns instead of the catch-all VPATH variable
# avoids hitting miscellaneous wrong targets in other directories
# when configuring in the source directory.
vpath %.c $(SRCDIRS) $(MOSTLY_SRCDIRS)
vpath %.h $(SRCDIRS) $(MOSTLY_SRCDIRS)
vpath %.S $(SRCDIRS) $(MOSTLY_SRCDIRS)
vpath %.l $(SRCDIRS) $(MOSTLY_SRCDIRS)
vpath %.y $(SRCDIRS) $(MOSTLY_SRCDIRS)
vpath %.in $(SRCDIRS) $(MOSTLY_SRCDIRS)
vpath %.sym $(SRCDIRS) $(MOSTLY_SRCDIRS)

# First find a list of every file that might possibly be a source file,
# so we only have to scan the source directories once.
FILES := $(foreach DIR,$(SRCDIRS),$(wildcard $(DIR)/*))


# C source files
CFILES := $(filter %.c,$(FILES))

# This is to exclude files
CFILES := $(filter-out $(OSKIT_EXCLUDE),$(CFILES))

# How to compile them.
%.o: %.c
	$(OSKIT_QUIET_MAKE_INFORM) "Compiling $<"
	$(CC) -c -o $@ $(OSKIT_CFLAGS) $(CFLAGS) $<

# How to build profiled object files.
%.po: %.c
	$(OSKIT_QUIET_MAKE_INFORM) "Compiling $<"
	$(CC) -c -o $@ $(OSKIT_CFLAGS) -DGPROF -pg $(CFLAGS) $<


# How to generate symbol header files,
# containing #define's for numeric constants
# related to C structures on the target machine.
# These are currently used in two ways:
#
# * When cross-compiling, MIG is compiled to be executed on the host,
#   but it needs to know the sizes of certain types on the target machine.
#   So a symbol header file is created with the cross-compiler,
#   and then used in compiling MIG for the host machine.
#
# * Assemblers don't know about C structures,
#   so machine-specific assembly language code
#   can use symbol header files instead.
%.symc: %.sym
	$(OSKIT_QUIET_MAKE_INFORM) "Generating $@ from $<"
	$(AWK) -f $(OSKIT_SRCDIR)/gensym.awk $< >$*.symc

%.symc.o: %.symc
	$(OSKIT_QUIET_MAKE_INFORM) "Assembling $<"
	$(CC) -S $(OSKIT_CFLAGS) $(CFLAGS) -x c -o $@ $<

%.h: %.symc.o
	$(OSKIT_QUIET_MAKE_INFORM) "Generating $@ from $<"
	sed <$< -e 's/^[^*].*$$//' | \
		sed -e 's/^[*]/#define/' -e 's/mAgIc[^-0-9]*//' >$@

CLEAN_FILES += *.symc *.symc.o


# How to install files into their final resting places.
$(INSTALL_BINDIR)/%: %
	$(OSKIT_QUIET_MAKE_INFORM) "Installing $<"
	-mkdir -p $(INSTALL_BINDIR)
	$(INSTALL) $< $@
$(INSTALL_LIBDIR)/%: %
	$(OSKIT_QUIET_MAKE_INFORM) "Installing $<"
	-mkdir -p $(INSTALL_LIBDIR)
	$(INSTALL) $< $@
$(INSTALL_LIBDIR)/oskit/%: %
	$(OSKIT_QUIET_MAKE_INFORM) "Installing $<"
	-mkdir -p $(INSTALL_LIBDIR)/oskit
	$(INSTALL) $< $@

# Always fully build everything before trying to install anything
install: all


# Get rid of a bunch of nasty built-in implicit rules,
# to avoid bogus circular dependencies and make things go faster.
# Use the `-r' command line option to make to get even better performance.
.SUFFIXES:


# The generated object files have the same prefix names as the source files,
# except they live in the current (object) directory.
OBJFILES += $(patsubst %.c,%.o,$(notdir $(CFILES)))

# This is to eliminate duplicate files,
# which might appear when files are being overridden.
OBJFILES := $(sort $(OBJFILES))

# If the profiling option is on, then build profiled versions of all
# of the object files.
ifneq "$(filter profiling, $(OSKIT_OPTIONS))" ""
POBJFILES = $(patsubst %.o, %.po, $(OBJFILES))
endif

# How to clean out the automatically built stuff in an object directory.
clean:
	rm -rf *.[doa] *.po *.bak tags TAGS depend $(CLEAN_FILES)

distclean: clean

# How to update the dependency file in an object directory.
# This funny bit of magic (hopefully the most obscure thing here)
# basically replaces the `md' program in ODE.
# The `sed' line removes the dependencies being replaced,
# the `for' line tacks the new dependencies to the end of the file,
# and then the individual dependency files are deleted.
comma := ,
depend: $(wildcard *.d)
	@if test -f depend; then sed $(patsubst %.d,-e '/^%\.o/$(comma)/^#/d',$^) <depend >depend.new; fi; true
	@(for file in $^ /dev/null; do (cat $$file; echo '#'); done) >>depend.new
	@mv -f depend.new depend
	@if test "" != "$^"; then rm -f $^; fi; true


# Include the dependency graph (if it exists).
-include depend


endif
