#
# Top level, common rules
#

#
# do NOT touch this
#
-include $(TOPDIR)/makeautoconf
-include $(TOPDIR)/makeversion


#
# uncomment to enable quiet (fewer messages) compile / link
# QUIET=y


#
# choose your favorite C compiler.
# keep commented to let `./configure' autodetect it
# CC=gcc


#
# uncomment this to turn debugging on
# DEBUG=y

#
# compile/link flags. Used if no CFLAGS/LDFLAGS given in `make' command line
#
ifdef DEBUG
 CFLAGS+=-g -DINLINE=static
 LDFLAGS+=-g
else
 ifdef PROFILE
   CFLAGS+=-p -pg
   LDFLAGS+=-p -pg
 else
   ifeq ($(CC),gcc)
     CFLAGS+=-O2 -fomit-frame-pointer
     LDFLAGS+=-s
   else
     # detected by `./configure' :
     CFLAGS+=$(CC_AC_FLAGS)
   endif
   # strip installed binaries
   INSTALLFLAGS+=-s
 endif
endif

#
# how picky should your compiler be? uncomment for paranoid gcc settings.
# PARANOID_GCC=1

#
# apply known-good GCC compiler flags.
#
ifeq ($(word 1, $(CC)),gcc)
  CFLAGS+=-pipe -Wall -Wshadow -Wno-uninitialized -Winline
  ifdef DEBUG
    CFLAGS+=-Wno-unused
  endif
  ifdef PARANOID_GCC
    CFLAGS+=-Wundef -Wstrict-prototypes -Wcast-qual -Wcast-align -Wpointer-arith -Wbad-function-cast -Waggregate-return
  endif
endif

# try to get some extensions if available (recursive pthread mutexes, grantpt(), ...)
CFLAGS+=-D_GNU_SOURCE

#
# set 'install' program
# keep commented to let `./configure' autodetect it
#
#INSTALL-BIN=install

#
# create an install directory
#
INSTALL-DIR=$(INSTALL-BIN) -d

#
# install with 644 permission:
#
INSTALL-TXT=$(INSTALL-BIN) -m 644

#
# set `ar' archiver... (autodetected)
#
#AR=ar
#
# set `ranlib' archiver (autodetected)
#
#RANLIB=ranlib

#
# `cp -f' : `cp' with force overwrite
#
CP=cp -f

#
# `ln -f -s' : `ln' with soft links, force overwrite
#
LN=ln -f -s

#
# `mkdir -p' or `mkdirhier' : make a directory and all missing directory parents
#
MKDIR=mkdir -p
#MKDIR=mkdirhier


#
# choose a variation of `echo' that interprets \n as newline.
# keep commented to enable autodetection.
#
#ECHO_E=echo
#ECHO_E=echo -e

#
# where is bash on your system?
# keep commented to enable autodetection.
#
#BASH=/bin/bash


#
# GNU m4 preprocessor
#
M4=m4


#
# --------------- no user-serviceable parts below this line ----------------
#


#
# tell the user what we are doing, either verbosely or silently
ifeq ($(QUIET),y)
  echo-and-compile=@echo "compiling $(2)" ; $(1) $(2)
  echo-and-link=@echo "linking   $(2)" ; $(1) $(2)
  echo-done=:
  Q:=@
else
  echo-and-compile=$(strip $(1) $(2))
  echo-and-link=$(strip $(1) $(2))
  echo-done=:
  Q:=
endif


SHLIBS_VER=$(MAJOR_VER).$(MINOR_VER).$(PATCH_VER)


ifeq ($(SYS_SHLIBS),native)
  # either native shared library support,
  # or no shared libraries at all.
  # in both cases, do not use libtool
  
  
  # compile normal (static) objects (i.e. ones used in $(BINS) $(ARLIBS) $(CLLIBS))
  CC_BIN=$(CC)

  # link normal (static) binaries (may have to link against shared libraries)
  LD_BIN=$(CC)

  # compile shared libraries or modules
  CC_SH=$(CC) -fPIC

  # link shared modules
  LD_MOD=$(CC) -shared

  # link shared libraries
  LD_SH=$(CC) -shared

  make-mod-links=target_mod=$(patsubst %.la,%.so,$(1)) ; \
    $(LN) $$target_mod.$(SHLIBS_VER) $(1)

  make-shlib-links=target_shlib=$(patsubst %.la,%.so,$(1)) ; \
    $(LN) $$target_shlib.$(SHLIBS_VER) $(1) ; \
    $(LN) $$target_shlib.$(SHLIBS_VER) $$target_shlib.$(MAJOR_VER) ; \
    $(LN) $$target_shlib.$(MAJOR_VER) $$target_shlib

  #
  # how to install a binary (program or library)
  #
  INSTALL=$(INSTALL-BIN) $(INSTALL_FLAGS)

else

  # compile normal (static) objects (i.e. ones used in $(BINS) $(ARLIBS) $(CLLIBS))
  CC_BIN=$(CC)

  # link normal (static) binaries (may have to link against shared libraries)
  LD_BIN=$(TOPDIR)/libtool --silent $(CC)

  # compile shared libraries or modules
  CC_SH=$(TOPDIR)/libtool --silent $(CC)

  # install path for shared libraries or modules
  ifeq ($(libdir_SHLIBS_MODS),)
    ifeq ($(libdir),)
      libdir_SHLIBS_MODS=$(shell pwd)
    else
      libdir_SHLIBS_MODS=$(libdir)
    endif
  endif
  ifeq ($(libdir_MODS),)
    libdir_MODS=$(libdir_SHLIBS_MODS)
  endif
  ifeq ($(libdir_SHLIBS),)
    libdir_SHLIBS=$(libdir_SHLIBS_MODS)
  endif

  # link shared modules
  LD_MOD=$(TOPDIR)/libtool --silent $(CC) -module -rpath $(libdir_MODS)

  # link shared libraries
  LD_SH=$(TOPDIR)/libtool --silent $(CC) -rpath $(libdir_SHLIBS)
  
  #
  # convert shared libraries version
  # from major,minor,patch to current:revision:age
  # (on linux: major = current - age, minor = age, patch = revision,
  # and we use this scheme for all platforms; it's just a little math
  # from one scheme to the other)
  # 
  shlibs-version-info=-version-info $(shell expr $(1) + $(2)):$(3):$(2)

  LD_FLAGS_SHLIBS+=$(call shlibs-version-info,$(MAJOR_VER),$(MINOR_VER),$(PATCH_VER))

  #
  # how to install a program or library: wrap with libtool
  #
  INSTALL=$(TOPDIR)/libtool --silent $(INSTALL-BIN) $(INSTALL_FLAGS)

endif
 
# compile from assembler
CC_AS=$(CC)

#
# save user-specified or above default values in the right place
#
CC_FLAGS+=$(CFLAGS) $(EXTRA_CFLAGS)
LD_FLAGS+=$(LDFLAGS) $(EXTRA_LDFLAGS)
INSTALL_FLAGS+=$(INSTALLFLAGS) $(EXTRA_INSTALLFLAGS)


ifeq ($(filter r,$(MAKEFLAGS)),)
  MAKEFLAGS+=r
endif


CC_FLAGS+=-I$(TOPDIR)/include

CONF=$(TOPDIR)/conf/conf.current

#
# once shared libraries are installed, it's ok to link just with
# one of -lTutf, -lTw or -lTT
#
# but linking against $(TOPDIR)/libs/libTT/libTT.so fails
# if there is no libTw.so in the linker path (as it happens
# if twin is not already installed), so we need to use
# a little magic to handle library dependencies.
#
# when using static libraries, we must always explicitly
# link all of them... (linker knows no dependencies with them)
#

ifeq ($(CONF__SHLIBS),n)
  ifeq ($(CONF__UNICODE),y)
    LD_LIBTUTF:=$(TOPDIR)/libs/libTutf/libTutf.a
  endif
  ifneq ($(CONF__SOCKET),n)
    LD_LIBTW:=$(TOPDIR)/libs/libTw/libTw.a
  
    ifeq ($(CONF_SOCKET_GZ),y)
      LD_LIBTW+=-lz
    endif
    ifeq ($(CONF_SOCKET_PTHREADS),y)
      LD_LIBTW+=$(LD_LIBPTHREAD_WEAK)
    endif
  endif
  ifeq ($(CONF_TT),y)
    LD_LIBTT:=$(TOPDIR)/libs/libTT/libTT.a
    
    ifeq ($(CONF__MODULES),y)
      LD_LIBTT+=$(LD_LIBDL)
      ifeq ($(SYS_SHLIBS),native)
        LD_LIBTT+=-rdynamic
      else
        LD_LIBTT+=-export-dynamic
      endif
    endif
    ifeq ($(CONF__UNICODE),y)
      LD_LIBTT+=$(LD_LIBTUTF)
    endif
    ifeq ($(CONF_SOCKET_PTHREADS),y)
      LD_LIBTT+=$(LD_LIBPTHREAD_WEAK)
    endif
    ifeq ($(CONF_TT_HW_TWIN),y)
      LD_LIBTT+=$(LD_LIBTW)
    endif
    ifeq ($(CONF_TT_HW_GTK),y)
      LD_LIBTT+=$(LD_LIBGTK)
    endif
  endif
else
  ifeq ($(SYS_SHLIBS),native)
    #
    # this is for GNU gcc with GNU ld on Linux/FreeBSD:
    # a shared library can depend on another shared library,
    # and if the former is linked against the latter,
    # you just need to specify the first one when linking a program,
    # provided GNU ld can find also the second one in its search path
    #
    ifeq ($(CONF__UNICODE),y)
      LD_LIBTUTF:=-L$(TOPDIR)/libs/libTutf -lTutf
    endif
    ifneq ($(CONF__SOCKET),n)
      LD_LIBTW:=-L$(TOPDIR)/libs/libTw -lTw
    endif
    ifeq ($(CONF_TT),y)
      LD_LIBTT:=-L$(TOPDIR)/libs/libTT -lTT
      
      ifeq ($(CONF__UNICODE),y)
        LD_LIBTT+=-Wl,-rpath-link,$(TOPDIR)/libs/libTutf
      endif
      ifeq ($(CONF_TT_HW_TWIN),y)
        LD_LIBTT+=-Wl,-rpath-link,$(TOPDIR)/libs/libTw
      endif
    endif
  else
    #
    # this is for libtool >= 1.4.1, that allows
    # a libtool library to depend on another libtool library
    # (libTT is linked against, and needs, libTutf)
    #
    ifeq ($(CONF__UNICODE),y)
      LD_LIBTUTF:=$(TOPDIR)/libs/libTutf/libTutf.la
    endif
    ifneq ($(CONF__SOCKET),n)
      LD_LIBTW:=$(TOPDIR)/libs/libTw/libTw.la
    endif
    ifeq ($(CONF_TT),y)
      LD_LIBTT:=$(TOPDIR)/libs/libTT/libTT.la
    endif
  endif
endif  
  
config:
	@echo Starting configure for twin $(TWIN_VERSION_STR)	... ; \
	echo
	cd $(TOPDIR) && \
	$(BASH) scripts/Configure.tty

menuconf menuconfig:
	@echo Starting menu-dialog configure for twin $(TWIN_VERSION_STR)	... ; \
	echo
	cd $(TOPDIR) && \
	$(BASH) scripts/Configure.dialog

gconf gconfig:
	@echo Starting menu-gdialog configure for twin $(TWIN_VERSION_STR)	... ; \
	echo
	cd $(TOPDIR) && \
	$(BASH) scripts/Configure.dialog 254 gdialog

nullconfig:
	cd $(TOPDIR) && \
	$(BASH) scripts/Configure.tty < /dev/null > /dev/null

	
$(TOPDIR)/makeversion: $(TOPDIR)/include/makeversion
	@echo Updating $(TOPDIR)/makeversion; \
	 echo "TWIN_VERSION_STR=`cut -d= -f2 < include/makeversion | xargs echo | tr ' ' '.'`" > $@


# collect together in $(OBJS) all objs from $(BINS) looking in $(OBJS_xxx)
_BIN_OBJS:=$(foreach B,$(BINS),$(OBJS_$(B)))

# same with $(_MOD_OBJS) from $(MODS)
_MOD_OBJS:=$(foreach B,$(MODS),$(OBJS_$(B)))

# same with $(_SHLIB_OBJS) from $(SHLIBS)
_SHLIB_OBJS:=$(foreach B,$(SHLIBS),$(OBJS_$(B)))

# same with $(_ARLIB_OBJS) from $(ARLIBS)
_ARLIB_OBJS:=$(foreach B,$(ARLIBS),$(OBJS_$(B)))

# same with $(_CLLIB_OBJS) from $(CLLIBS)
_CLLIB_OBJS:=$(foreach B,$(CLLIBS),$(OBJS_$(B)))


_ALL_BINS:=$(sort $(BINS) $(MODS) $(SHLIBS) $(ARLIBS) $(CLLIBS))

_ALL_OBJS:=$(sort $(_BIN_OBJS) $(_MOD_OBJS) $(_SHLIB_OBJS) $(_ARLIB_OBJS) $(_CLLIB_OBJS) $(ALL_OBJS))

#
# try to autodetect whether a %.o object comes from
# %.c, %.S or %.C source:
# if a %.S or %.C file exists, take it, else assume %.c
#
# we must take care since we have %.o and %.lo objects
# and they all come from the same %.c, %.S or %.C source
#
__ALLOBJS_RAW:=$(sort $(foreach E, o lo, $(patsubst %.$(E), %.o, $(filter %.$(E),$(_ALL_OBJS)))))
__ALLSRCS_ASM:=$(strip $(wildcard $(subst .o,.S,$(__ALLOBJS_RAW))))
__ALLSRCS_CXX:=$(strip $(wildcard $(subst .o,.C,$(__ALLOBJS_RAW))))
__ALLOBJS_ASM:=$(subst .S,.o,$(__ALLSRCS_ASM))
__ALLOBJS_CXX:=$(subst .S,.o,$(__ALLSRCS_CXX))

_ALL_SRCS:=$(subst .o,.c,$(filter-out $(__ALLOBJS_ASM) $(__ALLOBJS_CXX), $(__ALLOBJS_RAW))) \
	   $(__ALLSRCS_ASM) $(__ALLSRCS_CXX)

.SECONDARY: $(_ALL_SRCS) $(_ALL_OBJS) Makefile $(wildcard make*)

$(CONF): $(TOPDIR)/conf/conf.auto $(TOPDIR)/include/Tw/Twautoconf.h
	cd $(TOPDIR) && ( \
	 $(BASH) scripts/Configure.tty || \
	 /bin/sh scripts/Configure.fallback \
	) < /dev/null > /dev/null


.modules: Makefile $(TOPDIR)/makerules $(TOPDIR)/makeautoconf $(CONF)
	@echo "building  .modules" ; \
	 $(ECHO_E) " $(foreach B,$(BINS),$(B): .$(B).bin\n .$(B).bin: $(OBJS_$(B))\n)" > $@ ; \
	 $(ECHO_E) " $(foreach B,$(MODS),$(B): .$(B).mod\n .$(B).mod: $(OBJS_$(B))\n)" >> $@ ; \
	 $(ECHO_E) " $(foreach B,$(SHLIBS),$(B): .$(B).shlib\n .$(B).shlib: $(OBJS_$(B))\n)" >> $@ ; \
	 $(ECHO_E) " $(foreach B,$(ARLIBS),$(B): .$(B).arlib\n .$(B).arlib: $(OBJS_$(B))\n)" >> $@ ; \
	 $(ECHO_E) " $(foreach B,$(CLLIBS),$(B): .$(B).cllib\n .$(B).cllib: $(OBJS_$(B))\n)" >> $@ ; \
	 $(ECHO_E) " ifeq (\$$(SYS_SHLIBS),native)" >> $@ ; \
	 $(ECHO_E) " $(foreach B,$(SHLIBS),  LD_FLAGS_$(B)+=-Wl,-soname,$(patsubst %.la,%,$(B)).so.$(MAJOR_VER)\n)" >> $@ ; \
	 $(ECHO_E) " endif" >> $@


#
# includes can be autogenerated from m4 macro files...
# these are a nightmare to catch and put in .depend:
# we transform m4/%.m4 file names into %.h and manually
# add them to .depend dependencies.
# 
#
M4_INCS=$(strip $(sort $(patsubst $(1)m4/%.m4,$(1)%_m4.h,$(wildcard $(1)m4/*.m4))))

H_INCS=$(strip $(sort $(filter-out $(call M4_INCS,$(1)),$(wildcard $(1)*.h))))

map = $(foreach a,$(wildcard $(2)),$(call $(1),$(a)))

_H_FILES:=$(call H_INCS,)
_M4_FILES:=$(call M4_INCS,)

#
# cheat a little with what gets printed...
#
.depend: $(TOPDIR)/scripts/Mkdep Makefile $(TOPDIR)/makerules $(_ALL_SRCS) $(_H_FILES) $(_M4_FILES)
	@echo "building  .depend" ; \
	 $< $(filter -I%,$(CC_FLAGS)) $(sort $(_ALL_SRCS)) \
	   -C $(call M4_INCS,) \
	   +T $(call H_INCS,) > $@


_H_DIRS:=$(TOPDIR)/include/ $(TOPDIR)/include/T*/
_GL_H_FILES:=$(call map,H_INCS,$(_H_DIRS))
_GL_M4_FILES:=$(call map,M4_INCS,$(_H_DIRS))

$(TOPDIR)/.hdepend: $(TOPDIR)/scripts/Mkdep $(TOPDIR)/makerules $(_GL_H_FILES) $(_GL_M4_FILES)
	@echo "building  $(TOPDIR)/.hdepend" ; \
	 cd $(TOPDIR) && \
	 scripts/Mkdep '-P$$(TOPDIR)/' -Iinclude \
	   -C $(patsubst $(TOPDIR)/%,%,$(_GL_M4_FILES)) \
	   +T $(patsubst $(TOPDIR)/%,%,$(_GL_H_FILES)) > .hdepend



%_m4.h: m4/%.m4 $(wildcard $(TOPDIR)/include/m4/*.m4h)
	$(M4) -I$(TOPDIR)/include $< > $@


ifeq ($(EXTRA_VER),)
  EXTRA_VER=0
endif

version.h: version.h.in makeversion $(TOPDIR)/makerules
	$(Q)sed -e 's/@MAJOR_VER@/$(MAJOR_VER)/g' -e 's/@MINOR_VER@/$(MINOR_VER)/g' \
	    -e 's/@PATCH_VER@/$(PATCH_VER)/g' -e 's/@EXTRA_VER@/$(EXTRA_VER)/g' < $< > $@

#
# rules for the various kind of objects:
#

#
# normal (unshared) objects (from $(BINS) $(ARLIBS) $(CLLIBS))
#
%.o: %.c
	$(call echo-and-compile,$(CC_BIN) $(sort $(CC_FLAGS) $(CC_FLAGS_$@)) -c $< -o,$@)
	@$(ECHO_E) ' ifeq ($$(CC_BIN) $$(sort $$(CC_FLAGS) $$(CC_FLAGS_$@)),$(CC_BIN) $(sort $(CC_FLAGS) $(CC_FLAGS_$@)))\n'\
	'  FILES_UP_TO_DATE += $@\n'\
	'endif' > .$@.flags && \
	 $(echo-done)

#
# shared objects (from $(MODS) $(SHLIBS))
# WARNING: we use both CC_FLAGS_%.o and CC_FLAGS_%.lo 
#
# hack note: libtool adds a %.o -> %.lo symlink if the %.o object
# does not already exist. we remove that link since it confuses make:
# make skips properly compiling %.o even if needed due to the symlink.
#
%.lo: %.c
	$(call echo-and-compile,$(CC_SH) $(sort $(CC_FLAGS) $(CC_FLAGS.lo) $(CC_FLAGS_$*.o) $(CC_FLAGS_$@)) -c $< -o,$@)
	@if [ ! -f $*.o ]; then \
	  rm -f $*.o ; \
	 fi ; \
	 $(ECHO_E) ' ifeq ($$(CC_SH) $$(sort $$(CC_FLAGS) $$(CC_FLAGS.lo) $$(CC_FLAGS_$*.o) $$(CC_FLAGS_$@)),$(CC_SH) $(sort $(CC_FLAGS) $(CC_FLAGS.lo) $(CC_FLAGS_$*.o) $(CC_FLAGS_$@)))\n'\
	'  FILES_UP_TO_DATE += $@\n'\
	'endif' > .$@.flags && \
	 $(echo-done)

#
# assembler objects (if they are PIC or not depends on their contents...
# we add -DPIC while compiling %.lo as a hook to allow for #ifdef PIC conditionals in the source)
#
%.o: %.S
	$(call echo-and-compile,$(CC_AS) $(sort $(CC_FLAGS) $(CC_FLAGS_$@)) -c $< -o,$@)
	@$(ECHO_E) ' ifeq ($$(CC_AS) $$(sort $$(CC_FLAGS) $$(CC_FLAGS_$@)),$(CC_AS) $(sort $(CC_FLAGS) $(CC_FLAGS_$@)))\n'\
	'  FILES_UP_TO_DATE += $@\n'\
	'endif' > .$@.flags && \
	 $(echo-done)

%.lo: %.S
	$(call echo-and-compile,$(CC_AS) $(sort $(CC_FLAGS) $(CC_FLAGS.lo) $(CC_FLAGS_$*.o) $(CC_FLAGS_$@) -DPIC) -c $< -o,$@)
	@if [ ! -f $*.o ]; then \
	  rm -f $*.o ; \
	 fi ; \
	 $(ECHO_E) ' ifeq ($$(CC_AS) $$(sort $$(CC_FLAGS) $$(CC_FLAGS.lo) $$(CC_FLAGS_$*.o) $$(CC_FLAGS_$@) -DPIC),$(CC_AS) $(sort $(CC_FLAGS) $(CC_FLAGS.lo) $(CC_FLAGS_$*.o) $(CC_FLAGS_$@) -DPIC))\n'\
	'  FILES_UP_TO_DATE += $@\n'\
	'endif' > .$@.flags && \
	 $(echo-done)

#
# C++ objects (unused)
# 
%.o: %.C
	$(call echo-and-compile,$(CXX) $(sort $(CC_FLAGS) $(CXX_FLAGS) $(CC_FLAGS_$@) $(CXX_FLAGS_$@)) -c $< -o,$@)
	@$(ECHO_E) ' ifeq ($(CXX) $$(sort $(CC_FLAGS) $(CXX_FLAGS) $(CC_FLAGS_$@) $(CXX_FLAGS_$@)),$(CXX) $(sort $(CC_FLAGS) $(CXX_FLAGS) $(CC_FLAGS_$@) $(CXX_FLAGS_$@)))\n'\
	'  FILES_UP_TO_DATE += $@\n'\
	'endif' > .$@.flags && \
	$(echo-done)


#
# function to extract actual .o files from .lst collection:
# special care must be taken when extracting from .lst NOT in the currect directory
#
expand-lst=$(strip $(filter-out %.lst,$(1)) $(foreach L,$(filter %.lst,$(1)),$(call cat-lst,$(L))))
cat-lst=$(foreach F,$(shell cat $(1)),$(patsubst %,$(dir $(1))%,$(F)))

#
# this is the rule to link a binary. It should look like:
# % : $(OBJS_%)
#	$(CC) -o $* $(OBJS_$*) $(LD_FLAGS) $(LD_FLAGS_$*)
#	...
# but 1) nasty match-all rules like this are a real pain
# and 2) $(OBJS_%) doesn't expand
# so we put into .modules an explicited version of what follows:
# % : .%.bin
# .%.bin : $(OBJS_%)
#
# and we use patterns for the last step:
#       
.%.bin: $(TOPDIR)/makerules
	$(call echo-and-link,$(LD_BIN) $(call expand-lst,$(OBJS_$*)) $(LD_FLAGS) $(LD_FLAGS_$*) -o,$*)
	@$(LN) $* $@ && \
	 $(ECHO_E) ' ifeq ($$(strip $$(LD_BIN) $$(OBJS_$*) $$(LD_FLAGS) $$(LD_FLAGS_$*)),$(strip $(LD_BIN) $(OBJS_$*) $(LD_FLAGS) $(LD_FLAGS_$*)))\n'\
	 '  FILES_UP_TO_DATE += $@\n'\
	 'endif' > .$*.flags && \
	 $(echo-done)

.%.mod: $(TOPDIR)/makerules
ifeq ($(SYS_SHLIBS),native)
	$(call echo-and-link,$(LD_MOD) $(call expand-lst,$(OBJS_$*)) $(LD_FLAGS) $(LD_FLAGS_SHLIBS) $(LD_FLAGS_$*) -o,$(patsubst %.la,%.so.$(SHLIBS_VER),$*))
	@$(call make-mod-links,$*)
else
	$(call echo-and-link,$(LD_MOD) $(call expand-lst,$(OBJS_$*)) $(LD_FLAGS) $(LD_FLAGS_SHLIBS) $(LD_FLAGS_$*) -o,$*)
endif
	@$(LN) $* $@ && \
	 $(ECHO_E) ' ifeq ($$(strip $$(LD_MOD) $$(OBJS_$*) $$(LD_FLAGS) $$(LD_FLAGS_SHLIBS) $$(LD_FLAGS_$*)),$(strip $(LD_MOD) $(OBJS_$*) $(LD_FLAGS) $(LD_FLAGS_SHLIBS) $(LD_FLAGS_$*)))\n'\
	 '  FILES_UP_TO_DATE += $@\n'\
	 'endif' > .$*.flags && \
	 $(echo-done)

.%.shlib: $(TOPDIR)/makerules
ifeq ($(SYS_SHLIBS),native)
	$(call echo-and-link,$(LD_SH) $(call expand-lst,$(OBJS_$*)) $(LD_FLAGS) $(LD_FLAGS_SHLIBS) $(LD_FLAGS_$*) -o,$(patsubst %.la,%.so.$(SHLIBS_VER),$*))
	@$(call make-shlib-links,$*)
else
	$(call echo-and-link,$(LD_SH) $(call expand-lst,$(OBJS_$*)) $(LD_FLAGS) $(LD_FLAGS_SHLIBS) $(LD_FLAGS_$*) -o,$*)
endif
	@$(LN) $* $@ && \
	 $(ECHO_E) ' ifeq ($$(strip $$(LD_SH) $$(OBJS_$*) $$(LD_FLAGS) $$(LD_FLAGS_SHLIBS) $$(LD_FLAGS_$*)),$(strip $(LD_SH) $(OBJS_$*) $(LD_FLAGS) $(LD_FLAGS_SHLIBS) $(LD_FLAGS_$*)))\n'\
	 '  FILES_UP_TO_DATE += $@\n'\
	 'endif' > .$*.flags && \
	 $(echo-done)

.%.arlib: $(TOPDIR)/makerules
	$(call echo-and-link,rm -f $* && $(AR) cr $* $(call expand-lst,$(OBJS_$*)) && $(RANLIB),$*)
	@$(LN) $* $@ && \
	 $(ECHO_E) ' ifeq ($$(strip $$(OBJS_$*)),$(strip $(OBJS_$*)))\n'\
	 '  FILES_UP_TO_DATE += $@\n'\
	 'endif' > .$*.flags && \
	 $(echo-done)

.%.cllib: $(TOPDIR)/makerules
	$(call echo-and-link,echo $(call expand-lst,$(OBJS_$*)) >,$*)
	@$(LN) $* $@ && \
	 $(ECHO_E) ' ifeq ($$(strip $$(OBJS_$*)),$(strip $(OBJS_$*)))\n'\
	 '  FILES_UP_TO_DATE += $@\n'\
	 'endif' > .$*.flags && \
	 $(echo-done)


#
# useful (used for dlopen()) links, needed if using libtool
#
ifneq ($(SYS_SHLIBS),native)
  %.so.$(SHLIBS_VER):
	@if [ -f .libs/$@ ]; then \
	  echo $(LN) .libs/$@ $@ ; \
	  $(LN) .libs/$@ $@ ; \
	else \
	  dst=`grep library_names $*.la | cut -d" " -f1 | cut -d"'" -f2` ; \
	  echo $(LN) .libs/$$dst $@ ; \
	  $(LN) .libs/$$dst $@ ; \
	fi
endif

#
# install and also add
# useful (used for dlopen()) links
#

install-lib-%.a:
	$(INSTALL-TXT) $*.a $(DESTDIR)$(libdir)

uninstall-lib-%.a:
	rm -f $(DESTDIR)$(libdir)/$*.a


ifeq ($(SYS_SHLIBS),native)
  install-mod-%.la:
	$(INSTALL) $*.so.$(SHLIBS_VER) $(DESTDIR)$(libdir)$(INSTALLSUBDIR)
  install-lib-%.la:
	$(INSTALL) $*.so.$(SHLIBS_VER) $(DESTDIR)$(libdir)
	$(LN)      $*.so.$(SHLIBS_VER) $(DESTDIR)$(libdir)/$*.so.$(MAJOR_VER) && \
	$(LN)      $*.so.$(MAJOR_VER)  $(DESTDIR)$(libdir)/$*.so

  uninstall-mod-%.la:
	rm -f $(DESTDIR)$(libdir)$(INSTALLSUBDIR)/$*.so.$(SHLIBS_VER)
  uninstall-lib-%.la:
	rm -f $(DESTDIR)$(libdir)/$*.so.$(SHLIBS_VER) \
	      $(DESTDIR)$(libdir)/$*.so.$(MAJOR_VER) \
	      $(DESTDIR)$(libdir)/$*.so
else
  install-mod-%.la:
	$(INSTALL) $*.la $(DESTDIR)$(libdir)$(INSTALLSUBDIR)
	@echo '(cd $(DESTDIR)$(libdir)$(INSTALLSUBDIR)' ; \
	cd $(DESTDIR)$(libdir)$(INSTALLSUBDIR) ; \
	dst="$*.so.$(SHLIBS_VER)" ; \
	if [ "$(LD_LIBDL)" = "-ldl" ]; then \
	  if [ -f "$$dst" ]; then \
	    echo rm -f $*.la $*.so $*.so.? $*.so.?.? ; \
	    rm -f $*.la $*.so $*.so.? $*.so.?.? ; \
	  else \
	    src="`grep library_names $*.la | cut -d' ' -f1 | cut -d\' -f2`" ; \
	    if [ -f "$$src" ]; then \
	      echo $(LN) "$$dst" "$$src"; \
	      $(LN) "$$dst" "$$src"; \
	    fi ; \
	    echo rm -f "$*.la" ; \
	    rm -f "$*.la" ; \
	  fi ; \
	fi ; \
	echo ')'
  install-lib-%.la:
	$(INSTALL) $*.la $(DESTDIR)$(libdir)

  uninstall-mod-%.la:
	rm -f $(DESTDIR)$(libdir)$(INSTALLSUBDIR)/$*.la
  uninstall-lib-%.la:
	rm -f $(DESTDIR)$(libdir)/$*.la
endif

# forbid GNU-make to `rm -f $(OBJS) $(SHLIBOBJS) $(ARLIBOBJS)' after build
# .SECONDARY: $(OBJS) $(SHLIBOBJS) $(ARLIBOBJS)


#
# random dependencies:
#
$(TOPDIR)/include/Tw/Twtypes.h: $(TOPDIR)/include/Tw/uni_types.h

$(TOPDIR)/.hdepend: $(TOPDIR)/include/Tw/uni_types.h

$(TOPDIR)/include/Tw/datasizes.h: $(TOPDIR)/scripts/Getsizes
	$< > $@


force-remake:
	@:

ifeq ($(CONF__LONG_LONG),)
  ifneq ($(wildcard $(CONF)),)
    include $(CONF)
  endif
endif

ifneq ($(wildcard $(TOPDIR)/.long_long.conf),)
  include $(TOPDIR)/.long_long.conf
else
  PREVIOUS_CONF__LONG_LONG=x
endif

#
# force re-compiling and re-running scripts/Getsizes after CONF__LONG_LONG changed
#
ifneq ($(CONF__LONG_LONG),$(PREVIOUS_CONF__LONG_LONG))
  $(TOPDIR)/scripts/Getsizes: force-remake
endif




ifeq ($(CONF__UNICODE),)
  ifneq ($(wildcard $(CONF)),)
    include $(CONF)
  endif
endif

ifneq ($(wildcard $(TOPDIR)/.unicode.conf),)
  include $(TOPDIR)/.unicode.conf
else
  PREVIOUS_CONF__UNICODE=x
endif



#
# force re-making after building include/Tw/uni_types.h,
# so that 'make' reads new .unicode.conf
#
ifneq ($(CONF__UNICODE),$(PREVIOUS_CONF__UNICODE))
  $(TOPDIR)/include/Tw/uni_types.h: force-remake
endif

#
# this is a NO NO
#
# $(TOPDIR)/include/Tw/uni_types.h: $(CONF)
#

ifeq ($(CONF__UNICODE),n)
  $(TOPDIR)/include/Tw/uni_types.h $(TOPDIR)/.unicode.conf: $(TOPDIR)/scripts/unitypes16
	cat $< > $@
	@echo "PREVIOUS_CONF__UNICODE=$(CONF__UNICODE)" > $(TOPDIR)/.unicode.conf
else
  $(TOPDIR)/include/Tw/uni_types.h $(TOPDIR)/.unicode.conf: $(TOPDIR)/scripts/unitypes32
	cat $< > $@
	@echo "PREVIOUS_CONF__UNICODE=$(CONF__UNICODE)" > $(TOPDIR)/.unicode.conf
endif


#
# do not have Tw/Twautoconf.h depend on makerules ...
# (it actually should, but it's an overkill)
# 
$(TOPDIR)/include/Tw/Twautoconf.h: $(TOPDIR)/include/autoconf.h
	@echo "building  $(TOPDIR)/include/Tw/Twautoconf.h" ; \
	 echo "#ifndef _TW_AUTOCONF_H" > $@ && \
	 echo "#define _TW_AUTOCONF_H" >> $@ && \
	 echo >> $@ && \
	 sed -e 's/HAVE_/TW_HAVE_/g' -e 's/RETSIGTYPE/TW_RETSIGTYPE/g' \
	  -e 's/STDC_HEADERS/TW_STDC_HEADERS/g' -e 's/SETVBUF/TW_SETVBUF/g' \
	  -e 's/TIME_WITH_SYS_TIME/TW_TIME_WITH_SYS_TIME/g' \
	  -e 's/TM_IN_SYS_TIME/TW_TM_IN_SYS_TIME/g' < $< >> $@ && \
	 echo >> $@ && \
	 echo "#endif /* _TW_AUTOCONF_H */" >> $@


ifeq ($(CONF__LONG_LONG),y)
  CC_FLAGS_script_getsizes.o+=-DCONF__LONG_LONG
endif

$(TOPDIR)/scripts/Getsizes: $(TOPDIR)/scripts/getsizes.c $(TOPDIR)/include/Tw/datatypes.h $(TOPDIR)/include/autoconf.h
	$(CC) $(CC_FLAGS) $(CC_FLAGS_script_getsizes.o) $(LD_FLAGS) $< -o $@
	@echo "PREVIOUS_CONF__LONG_LONG=$(CONF__LONG_LONG)" > $(TOPDIR)/.long_long.conf

#
# Mkdep does not actually depend on datasizes.h,
# but this is the best place to force creating it
#
$(TOPDIR)/scripts/Mkdep: $(TOPDIR)/scripts/mkdep.c $(TOPDIR)/include/autoconf.h $(TOPDIR)/include/Tw/datasizes.h
	$(CC) $(CC_FLAGS) $(LD_FLAGS) $< -o $@

$(TOPDIR)/scripts/Bitmap: $(TOPDIR)/scripts/bitmap.c
	$(CC) $(CC_FLAGS) $(LD_FLAGS) $< -o $@
	

#
# target to recursively build all subdirectories
#
build-subdirs: $(patsubst %, build-dir-%, $(SUBDIRS))

build-dir-%:
	$(MAKE) -C $*

#
# torture is the target to compile all source files in the current directory
# under all possible configurations. VERY useful to spot bugs.
#
# Torture is just like torture, except it also recursively Tortures
# all subdirectories.
#
# They need a lot of autogenerated files, but currently have do explicit
# dependencies for them, so you should run 'make' before invoking one of these.
#

torture-%.c: %.c Makefile $(TOPDIR)/makerules $(TOPDIR)/scripts/Torture $(TOPDIR)/scripts/Bitmap
	@echo; echo "Torturing $<"; echo; \
	$(BASH) $(TOPDIR)/scripts/Torture $(TOPDIR)/scripts/Bitmap $(CC) $(filter-out -DCONF_%, $(CC_FLAGS) $(CC_FLAGS_$*.o)) -c $< -o $*.o -- $<

torture: $(filter %.c, $(_ALL_SRCS) $(foreach S,$(_ALL_SRCS),torture-$(S)))
	
Torture: torture $(foreach D, $(SUBDIRS), Torture-dir-$(D))

Torture-dir-%:
	$(MAKE) Torture -C $*

#
# full-autogen is the target to build all autogenerated files that require
# extra tools (m4, bison, flex ...) and thus must be already present
# when releasing twin, to let people build with just compiler and GNU make.
# In order to run './configure', also sed and grep are required.
# 'make config', 'make menuconfig', 'make gconfig' and 'make Torture'
# require GNU bash too.
#
autogen post-autogen: do-autogen

do-autogen: pre-autogen $(foreach D, $(SUBDIRS), autogen-dir-$(D))

autogen-dir-%:
	$(MAKE) autogen -C $*

pre-autogen:


install: $(foreach D, $(SUBDIRS), install-dir-$(D))

install-dir-%:
	$(MAKE) install -C $* DESTDIR=$(DESTDIR)


uninstall: $(patsubst %, uninstall-dir-%, $(SUBDIRS))

uninstall-dir-%:
	$(MAKE) uninstall -C $* DESTDIR=$(DESTDIR)


clean: $(foreach D, $(SUBDIRS), clean-dir-$(D))

clean-dir-%:
	$(MAKE) clean -C $*






#
# Find files whose flags have changed and force recompilation.
# For safety, this works in the converse direction:
# every file is forced, except those whose flags are positively up-to-date.
#
FILES := $(_BIN_OBJS) $(_MOD_OBJS) $(_SHLIB_OBJS) $(_ARLIB_OBJS) $(_CLLIB_OBJS) \
	 $(patsubst %,.%.bin,$(BINS)) \
	 $(patsubst %,.%.mod,$(MODS)) \
	 $(patsubst %,.%.shlib,$(SHLIBS)) \
	 $(patsubst %,.%.arlib,$(ARLIBS)) \
	 $(patsubst %,.%.cllib,$(CLLIBS)) \

#
# to avoid useless re-making, assume files in other dirs are already up-to-date:
# `make' must already visit all directories anyway.
#
FILES_UP_TO_DATE := $(filter-out $(wildcard * .*), $(FILES))


FILES_FLAGS_EXIST := $(wildcard .*.flags)
ifneq ($(FILES_FLAGS_EXIST),)
 #
 # this appends files whose flags are positively up-to-date to FILES_UP_TO_DATE
 #
 include $(FILES_FLAGS_EXIST)
endif

FILES_CHANGED := $(strip $(filter-out $(FILES_UP_TO_DATE), $(FILES)))

#
# force remaking by using a phony target as prerequisite
#
phony-force-remake:
	@:

ifneq ($(FILES_CHANGED),)

$(FILES_CHANGED): phony-force-remake

endif

