# Generic configuration for Hurd compilation

# Directory makefiles should set the variable makemode to either
# `server' if they compile and install a single program for /hurd
# `utility' if they compile and install a single program for /bin
# `servers' if they compile and install multiple programs for /hurd
# `utilities' if they compile and install multiple programs for /bin
# `library' if they compile and install a library
# `misc' if they do none of those

# Every makefile should define
# SRCS (all actual source code)
# LCLHDRS (all source headers in this directory [NOT MiG created])
# OBJS (all .o files used to produce some target).

# Types `server' and `utility' should define
# OTHERLIBS (all other libraries used)
# target (the name of the program built)

# Types `servers' and `utilities' should define
# targets (the names of all the programs built)
# special-targets (targets which should not be built the normal way
# and have their own rules)

# Type `library' should define
# libname (the name of the library, without .a.)
# installhdrs (header files that should be installed in /include)
# installhdrsubdir (the subdirectory they should go in, default `hurd')

# Put this first so it's the default
all:

# Figure out how to locate the parent directory from here.
ifeq (.,$(dir))
.. =
else
.. = ../
endif

ifndef srcdir
# We are building in the source directory itself.
srcdir = .
ifeq (.,$(dir))
top_srcdir = .
else
top_srcdir = ..
endif
endif

# Include the configure-generated file of parameters.
# This sets up variables for build tools and installation directories.
include $(..)config.make

# Flags for compilation.
# It is important to have this inclusion first; that picks up our
# library header files locally rather than from installed copies.
# Append to any value set by the specific Makefile or by configure.
ifeq ($(srcdir),.)
srcdirinc=
else
srcdirinc=-I$(srcdir)
endif
ifeq ($(top_srcdir),..)
top_srcdirinc=
else
top_srcdirinc=-I$(top_srcdir)
endif
CPPFLAGS += -I. $(srcdirinc) -I.. $(top_srcdirinc) -D_GNU_SOURCE
CFLAGS += -Wall -g -O3

# Decode makemode:


ifeq ($(makemode),server)
 doinst := one
 installationdir := $(hurddir)
 clean := yes
 cleantarg := $(target)
endif

ifeq ($(makemode),utility)
 doinst := one
 ifndef installationdir
   installationdir := $(bindir)
 endif
 clean := yes
 cleantarg := $(target)
endif

ifeq ($(makemode),servers)
 doinst := many
 installationdir := $(hurddir)
 clean := yes
 cleantarg := $(targets)
endif

ifeq ($(makemode),utilities)
 doinst := many
 ifndef installationdir
   installationdir := $(bindir)
 endif
 clean := yes
 cleantarg := $(targets)
endif

ifeq ($(makemode),library)
 clean := yes
 cleantarg := $(libname).a $(libname).so
 ifndef installhdrsubdir
  installhdrsubdir = hurd
 endif
 ifndef targets
  targets = $(libname).a $(libname).so
 endif
endif



# Standard targets

# Installation
ifeq ($(doinst),one)
all: $(target)
install: $(installationdir)/$(target)
$(installationdir)/$(target): $(target)
	$(INSTALL_PROGRAM) $< $@
endif

ifeq ($(doinst),many)
all: $(targets)
install: $(addprefix $(installationdir)/,$(targets))
$(addprefix $(installationdir)/,$(targets)): $(installationdir)/%: %
	$(INSTALL_PROGRAM) $< $@
endif

ifeq ($(makemode),library)
all: libs
libs: $(targets)
install: $(addprefix $(libdir)/,$(targets)) $(addprefix $(includedir)/$(installhdrsubdir)/,$(installhdrs))

# Arrange to have the headers installed locally anytime we build the library.
# Not quite perfect, but at least it does end up getting done; and once done
# it never needs to be repeated for a particular header.
INSTALLED_LOCAL_HEADERS=$(addprefix $(top_srcdir)/$(installhdrsubdir)/,$(installhdrs))
libs: $(INSTALLED_LOCAL_HEADERS)
ifeq ($(installhdrsubdir),.)
$(INSTALLED_LOCAL_HEADERS): $(top_srcdir)/$(installhdrsubdir)/%:
	ln -s $(dir)/$* $@
else
$(INSTALLED_LOCAL_HEADERS): $(top_srcdir)/$(installhdrsubdir)/%:
	ln -s ../$(dir)/$* $@
endif

$(libdir)/$(libname).a: $(libname).a
	$(INSTALL_DATA) $(libname).a $(libdir)/$(libname).a
	$(RANLIB) $(libdir)/$(libname).a
$(libdir)/$(libname).so: $(libname).so
	$(INSTALL_DATA) $(libname).so $(libdir)/$(libname).so

$(addprefix $(includedir)/$(installhdrsubdir)/,$(installhdrs)): $(includedir)/$(installhdrsubdir)/%: %
	$(INSTALL_DATA) $< $@

endif
# Provide default.
install:

# Building the target
ifeq ($(OBJS),)
OBJS=%.o
endif

ifeq ($(doinst),many)
 target = $(filter-out $(special-targets),$(targets))
endif

ifeq ($(doinst),one)
$(target): $(OBJS) $(OTHERLIBS)
endif

# Determine which sort of library we should link against from whether -static
# is used in LDFLAGS.
__libext=.so
__libext-static=.a
_libext=$(__libext$(findstring -static,$(LDFLAGS) $($@-LDFLAGS)))

libsubst=$(basename ${lib})$(_libext)
libsubst-override=${$(notdir $(basename ${lib}))-libsubst}
_libsubst=${libsubst$(patsubst %,-override,${libsubst-override})}

# Direct the linker where to find shared objects specified in the
# dependencies of other shared objects it encounters.
rpath := -Wl,-rpath-link=.:$(subst $. ,:,$(dir $(wildcard ../lib*/lib*.so)))

$(target): %$(target-suffix):
	$(CC) $(rpath) $(CFLAGS) $($@-CFLAGS) $(LDFLAGS) $($@-LDFLAGS) -o $@ \
	      '-Wl,-(' $(filter %.o,$^) \
		       $(foreach lib,$(filter-out %.o,$+),${_libsubst}) \
	      '-Wl,-)'

ifeq ($(makemode),library)
$(libname).a: $(OBJS)
	rm -f $(libname).a
	$(AR) r $@ $^
	$(RANLIB) $@

$(libname).so: $(patsubst %.o,%_pic.o,$(OBJS))
	$(CC) -shared -Wl,-soname=$(libname).so -o $(libname).so \
	      $(rpath) $(CFLAGS) $(LDFLAGS) $($@-LDFLAGS) $^
endif

# Making a snapshot
distfiles = Makefile ChangeLog $(SRCS) $(LCLHDRS) $(DIST_FILES)
lndist: $(distfiles) $(top_srcdir)/hurd-snap/$(dir) FORCE
	ln $(distfiles) $(top_srcdir)/hurd-snap/$(dir)

ifeq ($(dir),.)
$(top_srcdir)/hurd-snap/$(dir):
else
$(top_srcdir)/hurd-snap/$(dir):
	mkdir $@
endif

# TAGS files
ifneq ($(dir),.)
DEP_SRCS = sed -e 's/^.*://' -e 's/ \\$$//' | tr ' ' '\012'| \
	   sed -n -e 's@^$(srcdir)@&@p' -e 's@^[^/]@&@p' | sort -ur
TAGS: $(OBJS:.o=.d) $(OTHERTAGS)
	cat $(OBJS:.o=.d) | $(DEP_SRCS) | etags -o $@ - $(OTHERTAGS)
endif

# Cleaning
ifeq ($(clean),yes)
clean:
	rm -f *.d *.*_d *.o *Server.c *User.c *_S.h *_U.h $(cleantarg)
ifneq ($(makemode),library)
relink:
	rm -f $(cleantarg)
endif
endif
clean:
relink:



# Subdependencies

# Building libraries from other directories.  We force both libraries to be
# built if either is, because it will use the appropriate one even if the other
# is specified in someone's dependency list.
../%.a ../%.so: FORCE
	$(MAKE) -C $(dir $@) libs

# Default rule to build PIC object files.
%_pic.o: %.c
	$(COMPILE.c) $< -DPIC -fPIC -o $@

%_pic.o: %.S
	$(COMPILE.S) $< -DPIC -o $@

# How to build RPC stubs

# User settable variables:
# 	MIGSFLAGS	   flags to CPP when building server stubs and headers
#	foo-MIGSFLAGS	   same, but only for interface `foo'
# 	MIGCOMSFLAGS	   flags to MiG when building server stubs and headers
#	foo-MIGCOMSFLAGS   same, but only for interface `foo'
# 	MIGUFLAGS	   flags to CPP when building user stubs and headers
#	foo-MIGUFLAGS	   same, but only for interface `foo'
# 	MIGCOMUFLAGS	   flags to MiG when building user stubs and headers
#	foo-MIGCOMUFLAGS   same, but only for interface `foo'
#	CPPFLAGS	   flags to CPP

# Implicit rules for building server and user stubs from mig .defs files.
%_S.h %Server.c: %.defs
	$(CPP) $(CPPFLAGS) $(MIGSFLAGS) $($*-MIGSFLAGS) -DSERVERPREFIX=S_ $< \
	| $(MIGCOM) $(MIGCOMSFLAGS) $($*-MIGCOMSFLAGS) \
		    -sheader $*_S.h -server $*Server.c \
		    -user /dev/null -header /dev/null
%_U.h %User.c: %.defs
	$(CPP) $(CPPFLAGS) $(MIGUFLAGS) $($*-MIGUFLAGS) $< \
	| $(MIGCOM) $(MIGCOMUFLAGS) $($*-MIGCOMUFLAGS) \
		    -user $*User.c -server /dev/null -header $*_U.h


# Where to find .defs files.
vpath %.defs $(top_srcdir)/hurd $(includedir)/mach $(includedir)/device

FORCE:


# How to build automatic dependencies

# Don't include dependencies if $(no_deps) is set; the master makefile
# does this for clean and other such targets that don't need
# dependencies.  That then avoids rebuilding dependencies.

ifneq ($(no_deps),t)

# For each file generated by MiG we need a .d file.
# These lines assume that every Makefile that uses a foo_S.h or foo_U.h file
# also mentions the associated fooServer.o or fooUser.o file.
-include $(subst Server.o,.migs_d,$(filter %Server.o,$(OBJS))) /dev/null
-include $(subst User.o,.migu_d,$(filter %User.o,$(OBJS))) /dev/null
-include $(subst Server.o,.migsh_d,$(filter %Server.o,$(OBJS))) /dev/null
-include $(subst User.o,.miguh_d,$(filter %User.o,$(OBJS))) /dev/null

# For each .o file we need a .d file.
-include $(subst .o,.d,$(filter %.o,$(OBJS))) /dev/null

endif

# Here is how to build those dependency files

# Dependencies for fooServer.c files.
%.migs_d: %.defs
	(set -e; $(CPP) $(CPPFLAGS) $(MIGSFLAGS) $($*-MIGSFLAGS) \
		 -DSERVERPREFIX=S_ -M -MG $< | \
	sed -e 's/\.defs\.o:/Server\.c $@:/' > $@)

# Dependencies for fooUser.c files.
%.migu_d: %.defs
	(set -e; $(CPP) $(CPPFLAGS) $(MIGUFLAGS) $($*-MIGUFLAGS) \
		-M -MG $< | \
	sed -e 's/\.defs\.o:/User\.c $@:/' > $@)

# The associated .h files are build by the same CCP, so a simple massaging
# of the previous two will work.
%.migsh_d: %.migs_d
	sed -e 's/Server\.c/_S\.h/' -e 's/migs_d/migsh_d/' < $< > $@
%.miguh_d: %.migu_d
	sed -e 's/User\.c/_U\.h/' -e 's/migu_d/miguh_d/' < $< > $@

define make-deps
set -e; $(CC) $(CFLAGS) $(CPPFLAGS) -M -MG $<  | \
sed > $@.new -e 's/$*\.o:/$*.o $*_pic.o $@:/' \
	     -e 's% [^ ]*/gcc-lib/[^ ]*\.h%%g'
mv -f $@.new $@
endef

# Here is how to make .d files from .c files
%.d: %.c; $(make-deps)
# Here is how to make .d files from .S files
%.d: %.S; $(make-deps)

# .s files don't go through the preprocessor, so we do this
# This rule must come *after* the genuine ones above, so that
# make doesn't build a .s file and then make an empty dependency
# list.
%.d: %.s
	echo '$*.o: $<' > $@