# Makefile for the Sherlock Search System
# (c) 1997--2005 Martin Mares <mj@ucw.cz>

CFLAGS=$(CLANG) $(COPT) $(CDEBUG) $(CWARNS) -I. -I$(o) -I$(s)
LDFLAGS=$(LOPT)

DIRS=
PROGS=
CONFIGS=accept filter sherlock library local trace url-equiv
TESTS=
INCLUDES=

# Various files whose type does not fit into PROGS
DATAFILES=

.PHONY: all clean distclean runtree programs includes datafiles force tags config dust

all: runtree programs includes datafiles extras config

-include obj/config.mk

obj/config.mk:
	@echo 'You have to run configure first.'
	@exit 1

s=$(SRCDIR)
o=obj

ifdef CONFIG_SHARED
LS=so
OS=oo
else
LS=a
OS=o
endif

# Clean needs to be a double-colon rule since we want sub-makefiles to be able
# to define their own cleanup actions.
dust::
	rm -f `find . -path "*~" -or -name "\#*\#" -or -name core`
	rm -f allocs.tmp cscope.out

clean:: dust
	rm -rf obj tests run/bin/* run/lib/* run/include/* run/.tree-stamp
	rm -f custom TAGS

distclean:: clean
	rm -rf run

testclean::
	rm -f `find obj -name "*.test"`

# Installation

install:: all
	SH_EXTRA_RUNDIRS="$(sort $(EXTRA_RUNDIRS))" SH_INSTALL_RUNDIRS="$(sort $(INSTALL_RUNDIRS))" SH_CONFIGS="$(sort $(CONFIGS))" $(s)/build/installer $(INSTALL_DIR)

# Extra directories to be created in the run/* hierarchy
EXTRA_RUNDIRS=cache db tmp index lock log lib/perl5/Sherlock
INSTALL_RUNDIRS=bin lib

# Extra default rules (appended to by submakefiles)
extras::

# We need to define names of libraries here, because even though variable references
# in bodies of rules can be forward, those in dependencies cannot. Also the order of
# includes is somewhat fragile because of that.
LIBSH=$(o)/sherlock/libsh.$(LS) $(o)/lib/libucw.$(LS)
LIBCUSTOM=$(o)/sherlock/libcustom.$(LS)
LIBCHARSET=$(o)/charset/libcharset.$(LS)
LIBFILTER=$(o)/filter/libfilter.$(LS)
LIBINDEXER=$(o)/indexer/libindexer.$(LS)
LIBLANG=$(o)/lang/liblang.$(LS)

# Relative symlinks and other pathname manipulation macros

empty:=
space:=$(empty) $(empty)
backref=$(subst $(space),/,$(patsubst %,..,$(subst /,$(space),$(1))))
tack-on=$(if $(patsubst /%,,$(2)),$(1)/$(2),$(2))
symlink=ln -sf $(call tack-on,$(call backref,$(2)),$(1)) $(2)/

# Include makefiles of various subsystems.
-include custom/Makefile
include $(s)/build/Makefile
include $(s)/sherlock/Makefile
include $(s)/lib/Makefile
include $(s)/charset/Makefile
include $(s)/filter/Makefile
include $(s)/lang/Makefile
include $(s)/utils/Makefile
include $(s)/analyser/Makefile
include $(s)/gather/Makefile
include $(s)/indexer/Makefile
ifdef CONFIG_SEARCH
include $(s)/search/Makefile
endif
ifdef CONFIG_DEBUG_TOOLS
include $(s)/debug/Makefile
endif

# Install include files if requested

ifdef CONFIG_INSTALL_API
INSTALL_RUNDIRS+=include
includes: $(INCLUDES)
else
includes:
endif

runtree: run/.tree-stamp $(addsuffix /.dir-stamp,$(addprefix $(o)/,$(DIRS)))

run/.tree-stamp: $(o)/config.mk
	mkdir -p run $(addprefix run/, cf $(EXTRA_RUNDIRS) $(INSTALL_RUNDIRS))
	touch run/.tree-stamp

programs: $(PROGS)
datafiles: $(DATAFILES)
tests: $(TESTS)

tags:
	etags `find . -name "*.[ch]"`

# Generate configuration files

config: $(addprefix run/cf/,$(CONFIGS))

run/cf/%: custom/cf/% $(o)/config.mk $(s)/build/genconf
	$(s)/build/genconf $< $@ $(o)/config.mk
run/cf/%: $(s)/cf/% $(o)/config.mk $(s)/build/genconf
	$(s)/build/genconf $< $@ $(o)/config.mk

# Black magic with dependencies. It would be more correct to make "depend.new"
# a prerequisite for "depend", but "depend.new" often has the same timestamp
# as "depend" which would confuse make a lot and either force remaking anyway
# or (as in current versions of GNU make) erroneously skipping the remaking.

-include $(o)/depend

$(o)/depend: force
	if [ -s $(o)/depend.new ] ; then $(s)/build/mergedeps $(o)/depend $(o)/depend.new ; >$(o)/depend.new ; fi

force:

# Implicit rules

%.dir-stamp:
	mkdir -p $(@D) && touch $@

%.a:
	ar rcs $@ $?
ifdef CONFIG_INSTALL_API
	$(call symlink,$@,run/lib)
endif

%.so:
	$(CC) $(LSHARED) $(LDFLAGS) -o $@ $^
	$(call symlink,$@,run/lib)

$(o)/%.o: $(s)/%.c $(o)/lib/autoconf.h
	DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) -c -o $@ $<

$(o)/%.o: %.c $(o)/lib/autoconf.h
	DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) -c -o $@ $<

%.o: %.c $(o)/lib/autoconf.h
	DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) -c -o $@ $<

$(o)/%.oo: $(s)/%.c $(o)/lib/autoconf.h
	DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) $(CSHARED) -c -o $@ $<

$(o)/%.oo: %.c $(o)/lib/autoconf.h
	DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) $(CSHARED) -c -o $@ $<

%.oo: %.c $(o)/lib/autoconf.h
	DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) $(CSHARED) -c -o $@ $<

$(o)/%-tt.o: $(s)/%.c $(o)/lib/autoconf.h
	DEPENDENCIES_OUTPUT="$(o)/depend.new $@" $(CC) $(CFLAGS) -DTEST -c -o $@ $<

$(o)/%-t: $(o)/%-tt.o $(LIBSH)
	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)

$(o)/%.test: %.t $(s)/build/tester
	$(s)/build/tester $< && touch $@

BINDIR=bin

$(o)/%: $(o)/%.o
	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
	$(call symlink,$@,run/$(BINDIR))

$(o)/%: $(s)/%.sh $(o)/config.mk $(s)/build/genconf
	$(s)/build/genconf $< $@ $(o)/config.mk
	chmod +x $@
	$(call symlink,$@,run/$(BINDIR))

$(o)/%: %.sh $(o)/config.mk $(s)/build/genconf
	$(s)/build/genconf $< $@ $(o)/config.mk
	chmod +x $@
	$(call symlink,$@,run/$(BINDIR))

$(o)/%: $(s)/%.pl $(o)/config.mk $(s)/build/genconf
	$(s)/build/genconf $< $@ $(o)/config.mk
	chmod +x $@
	$(call symlink,$@,run/$(BINDIR))

$(o)/%: %.pl $(o)/config.mk $(s)/build/genconf
	$(s)/build/genconf $< $@ $(o)/config.mk
	chmod +x $@
	$(call symlink,$@,run/$(BINDIR))

$(o)/%.pm: $(s)/%.pm
	cp $^ $@
	$(call symlink,$@,run/lib/perl5/Sherlock)

$(o)/%.pm: %.pm
	cp $^ $@
	$(call symlink,$@,run/lib/perl5/Sherlock)

DATADIR=lib

$(DATAFILES): $(o)/%: $(s)/%
	cp $^ $@
	$(call symlink,$@,run/$(DATADIR))

# Don't delete intermediate targets. There shouldn't be any, but due to bugs
# in GNU Make rules with targets in not-yet-existing directories are ignored
# when searching for implicit rules and thence targets considered intermediate.
.SECONDARY:
