# 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])
# REMHDRS (all Hurd headers in other directories [NOT .defs files])

# Types `server', `utility', and `library' should define
# OBJS (all .o files used to produce the target).

# Types `server', `utility', `servers', and `utilities' should define
# HURDLIBS (all Hurd libraries used, omitting the dirname and the .a.)

# 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)

# Type `library' should define
# libname (the name of the library, without .a.)
# installhdrs (header files that should be installed in /include)


# Put this first so it's the default
all:


# This is the directory into which Hurd cross-building tools are placed
hurdinst := /home/gd3/hurdinst

# This is the directory which serves as root for the Hurd.
hostname := $(shell hostname)
hurdroot-douglas.gnu.ai.mit.edu = /home/hm2/hurdroot
hurdroot-ernst.gnu.ai.mit.edu = /home/hm1/hurdroot
hurdroot := $(hurdroot-$(hostname))

# This is the device with the filesystem mounted as $(hurdroot)
hurdrootdev := /dev/hd0f

# This is the directory containing the top-level Hurd source (and this file).
hurdsource := /home/gd3/gnu/hurd

# Where to find various things for compilation:

includedir := $(hurdinst)/include

startup := $(hurdinst)/lib/crt0.o
libc := $(hurdinst)/lib/libc.a

# END CONFIGURATION AREA


# Decode makemode:


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

ifeq ($(makemode),utility)
 doinst := one
 installationdir := $(hurdroot)/bin
 clean := yes
 cleantarg := $(target)
endif

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

ifeq ($(makemode),utilities)
 doinst := many
 installationdir := $(hurdroot)/bin
 clean := yes
 cleantarg := $(targets)
endif

ifeq ($(makemode),library)
 clean := yes
 cleantarg := $(libname).a
endif



# Hurd libraries
libthreads := $(hurdsource)/libthreads/libthreads.a
libports := $(hurdsource)/libports/libports.a
libioserver := $(hurdsource)/libioserver/libioserver.a
libpager := $(hurdsource)/libpager/libpager.a
libfshelp := $(hurdsource)/libfshelp/libfshelp.a
libdiskfs := $(hurdsource)/libdiskfs/libdiskfs.a
libtrivfs := $(hurdsource)/libtrivfs/libtrivfs.a
alllibs := libthreads libports libioserver libpager libfshelp libdiskfs\
	libtrivfs

# Finding binaries
include $(hurdsource)/Maketools

# Flags for compilation.  
# It is important to have this inclusion first; that picks up our 
# library header files locally rather than from installed copies.
CPPFLAGS := -I$(hurdsource)
CFLAGS := -Wall -Wno-parentheses -g


# Standard targets

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

ifeq ($(doinst),many)
all: $(targets)
install: $(targets)
	for i in $(targets) ; do $(INSTALL_BIN) $$i $(installationdir)/$$i ; done
endif

ifeq ($(makemode),library)
all: $(libname).a
install: $(libname).a $(installhdrs)
	cp $(installhdrs) $(includedir)/hurd/
	cp $(libname).a $(hurdinst)/lib/$(libname).a
	ranlib $(hurdinst)/lib/$(libname).a
endif

# Provide default.
install:


# Each word of $(HURDLIBS) is a library name `libfoo', which is defined as
# a variable above with the complete file name to find it.
# Yippee!  A use for computed variable references!
HURDLIBS-files := $(foreach var,$(HURDLIBS),$($(var)))
#HURDLIBS-libs := $(foreach lib,$(HURDLIBS-files), \
#			   -L$(dir $(lib)) \
#			   $(patsubst lib%.a,-l%,$(notdir $(lib))))

# Building the target
ifeq ($(doinst),one)
$(target): $(OBJS) $(HURDLIBS-files) $(OTHERLIBS) $(libc)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $(target) $(link-objects)
# Don't use $^ to collect the args to the link because $^ omits duplicates.
#link-objects = $(OBJS) $(HURDLIBS-files) $(OTHERLIBS)
# -lg avoids "No input files" error.
link-objects = -nostdlib -Wl,$(subst $(empty) ,$(comma),$(strip \
	       $(startup) $(OBJS) -\( $(HURDLIBS-files) $(OTHERLIBS) -\))) \
	       $(libc)  -lg
empty =
comma = ,
endif


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

# Making a snapshot
distfiles = Makefile ChangeLog $(SRCS) $(LCLHDRS) $(DIST_FILES)
lndist: $(distfiles) $(hurdsource)/hurd-snap/$(dir) FORCE
	ln $(distfiles) $(hurdsource)/hurd-snap/$(dir)
 
ifeq ($(dir),.)
$(hurdsource)/hurd-snap/$(dir):
else
$(hurdsource)/hurd-snap/$(dir):
	mkdir $(hurdsource)/hurd-snap/$(dir)
endif

# TAGS files
ifneq ($(dir),.)
TAGS: $(SRCS) $(LCLHDRS) $(REMHDRS) $(OTHERTAGS)
	etags -o $@ $(HURDLIBS:-i ../%/TAGS) $(SRCS) \
	      $(LCLHDRS) $(REMHDRS) $(OTHERTAGS)
endif


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



# Subdependencies

# Mounting $(hurdroot)
ifeq ($(hurdroot),)
$(hurdroot): FORCE
	@echo Cannot do install on this machine.
	false
else
$(hurdroot): $(hurdroot)/mounted
$(hurdroot)/mounted:
	fsck -p $(hurdrootdev)
	mount $(hurdrootdev)
endif

# Building Hurd libraries
$(foreach lib,$(alllibs),$(hurdsource)/$(lib)/%.a): FORCE
	$(MAKE) -C $(dir $@) $(notdir $@)


# 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

hurddefs := $(notdir $(basename $(wildcard $(hurdsource)/hurd/*.defs)))
ht := $(hurdsource)/hurd/hurd_types.defs

# 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) -user $*User.c -server /dev/null -header $*_U.h


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

# Files generated from the Hurd .defs files depend on hurd_types.defs.
$(foreach if,$(hurddefs),$(if)_S.h $(if)Server.c $(if)_U.h $(if)User.c): $(ht)

FORCE: