# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
#
# This file is part of the thin-provisioning-tools source.
#
# thin-provisioning-tools is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# thin-provisioning-tools 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
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with thin-provisioning-tools.  If not, see
# <http://www.gnu.org/licenses/>.

.PHONY: all

V=@
PROGRAMS=\
	cache_check \
	cache_dump \
	cache_restore \
	cache_repair \
	\
	thin_check \
	thin_dump \
	thin_restore \
	thin_repair \
	thin_rmap \
	thin_metadata_size

all: $(PROGRAMS)

SOURCE=\
	base/base64.cc \
	base/error_state.cc \
	\
	caching/hint_array.cc \
	caching/superblock.cc \
	caching/mapping_array.cc \
	caching/metadata.cc \
	caching/metadata_dump.cc \
	caching/restore_emitter.cc \
	caching/xml_format.cc \
	\
	persistent-data/checksum.cc \
	persistent-data/endian_utils.cc \
	persistent-data/error_set.cc \
	persistent-data/file_utils.cc \
	persistent-data/hex_dump.cc \
	persistent-data/lock_tracker.cc \
	persistent-data/transaction_manager.cc \
	\
	persistent-data/data-structures/bitset.cc \
	persistent-data/data-structures/btree.cc \
	\
	persistent-data/space_map.cc \
	persistent-data/space-maps/disk.cc \
	persistent-data/space-maps/recursive.cc \
	persistent-data/space-maps/careful_alloc.cc \
	\
	thin-provisioning/device_tree.cc \
	thin-provisioning/human_readable_format.cc \
	thin-provisioning/mapping_tree.cc \
	thin-provisioning/metadata.cc \
	thin-provisioning/metadata_checker.cc \
	thin-provisioning/metadata_dumper.cc \
	thin-provisioning/restore_emitter.cc \
	thin-provisioning/rmap_visitor.cc \
	thin-provisioning/superblock.cc \
	thin-provisioning/thin_pool.cc \
	thin-provisioning/xml_format.cc

PDATA_OBJECTS=$(subst .cc,.o,$(SOURCE))

CXX_PROGRAM_SOURCE=\
	caching/cache_check.cc \
	caching/cache_restore.cc \
	\
	thin-provisioning/thin_check.cc \
	thin-provisioning/thin_dump.cc \
	thin-provisioning/thin_restore.cc \
	thin-provisioning/thin_repair.cc \
	thin-provisioning/thin_rmap.cc

C_PROGRAM_SOURCE=\
	thin-provisioning/thin_metadata_size.c

CC:=@CC@
CXX:=@CXX@
OBJECTS:=$(subst .cc,.o,$(SOURCE))
TOP_DIR:=@top_srcdir@
TOP_BUILDDIR:=@top_builddir@
CFLAGS+=-g -Wall -O3
CXXFLAGS+=-g -Wall -fno-strict-aliasing
CXXFLAGS+=@CXXOPTIMISE_FLAG@
CXXFLAGS+=@CXXDEBUG_FLAG@
INCLUDES+=-I$(TOP_BUILDDIR) -I$(TOP_DIR) -I$(TOP_DIR)/thin-provisioning
LIBS:=-lstdc++
LIBEXPAT:=-lexpat
INSTALL:=@INSTALL@
PREFIX:=@prefix@
BINDIR:=$(DESTDIR)$(PREFIX)/sbin
MANPATH:=$(DESTDIR)$(MANDIR)

vpath %.cc $(TOP_DIR)

INSTALL_DIR = $(INSTALL) -m 755 -d
INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -p -m 644

ifeq ("@TESTING@", "yes")
TEST_INCLUDES=\
	-Igmock-1.6.0/include \
	-Igmock-1.6.0/gtest/include
else
TEST_INCLUDES=
endif

.SUFFIXES: .d

%.o: %.c
	@echo "    [CC] $<"
	$(V) $(CC) -c $(INCLUDES) $(CFLAGS) -o $@ $<
	@echo "    [DEP] $<"
	$(V) $(CC) -MM -MT $(subst .c,.o,$<) $(INCLUDES) $(CFLAGS) $< > $*.$$$$; \
	sed 's,\([^ :]*\)\.o[ :]*,\1.o \1.gmo $* : Makefile ,g' < $*.$$$$ > $*.d; \
	$(RM) $*.$$$$

%.o: %.cc
	@echo "    [CXX] $<"
	$(V) $(CXX) -c $(INCLUDES) $(CXXFLAGS) -o $@ $<
	@echo "    [DEP] $<"
	$(V) $(CXX) -MM -MT $(subst .cc,.o,$<) $(INCLUDES) $(TEST_INCLUDES) $(CXXFLAGS) $< > $*.$$$$; \
	sed 's,\([^ :]*\)\.o[ :]*,\1.o \1.gmo $* : Makefile ,g' < $*.$$$$ > $*.d; \
	$(RM) $*.$$$$

#----------------------------------------------------------------

lib/libpdata.a: $(PDATA_OBJECTS)
	@echo "    [AR]  $<"
	$(V)ar -rv $@ $(PDATA_OBJECTS) > /dev/null 2>&1

#----------------------------------------------------------------
# Thin provisioning tools

THIN_DEBUG_SOURCE=$(SOURCE)
THIN_DUMP_SOURCE=$(SOURCE)
THIN_REPAIR_SOURCE=$(SOURCE)
THIN_RESTORE_SOURCE=$(SOURCE)
THIN_CHECK_SOURCE=\
	base/error_state.cc \
	persistent-data/checksum.cc \
	persistent-data/endian_utils.cc \
	persistent-data/error_set.cc \
	persistent-data/file_utils.cc \
	persistent-data/hex_dump.cc \
	persistent-data/lock_tracker.cc \
	persistent-data/data-structures/btree.cc \
	persistent-data/space_map.cc \
	persistent-data/space-maps/disk.cc \
	persistent-data/space-maps/recursive.cc \
	persistent-data/space-maps/careful_alloc.cc \
	persistent-data/transaction_manager.cc \
	thin-provisioning/device_tree.cc \
	thin-provisioning/mapping_tree.cc \
	thin-provisioning/metadata.cc \
	thin-provisioning/metadata_checker.cc \
	thin-provisioning/superblock.cc

THIN_RMAP_SOURCE=\
	persistent-data/checksum.cc \
	persistent-data/endian_utils.cc \
	persistent-data/error_set.cc \
	persistent-data/file_utils.cc \
	persistent-data/hex_dump.cc \
	persistent-data/lock_tracker.cc \
	persistent-data/data-structures/btree.cc \
	persistent-data/space_map.cc \
	persistent-data/space-maps/disk.cc \
	persistent-data/space-maps/recursive.cc \
	persistent-data/space-maps/careful_alloc.cc \
	persistent-data/transaction_manager.cc \
	thin-provisioning/device_tree.cc \
	thin-provisioning/mapping_tree.cc \
	thin-provisioning/metadata.cc \
	thin-provisioning/metadata_checker.cc \
	thin-provisioning/rmap_visitor.cc \
	thin-provisioning/superblock.cc

THIN_DEBUG_OBJECTS=$(subst .cc,.o,$(THIN_DEBUG_SOURCE))
THIN_DUMP_OBJECTS=$(subst .cc,.o,$(THIN_DUMP_SOURCE))
THIN_REPAIR_OBJECTS=$(subst .cc,.o,$(THIN_REPAIR_SOURCE))
THIN_RESTORE_OBJECTS=$(subst .cc,.o,$(THIN_RESTORE_SOURCE))
THIN_CHECK_OBJECTS=$(subst .cc,.o,$(THIN_CHECK_SOURCE))
THIN_RMAP_OBJECTS=$(subst .cc,.o,$(THIN_RMAP_SOURCE))

thin_debug: $(THIN_DEBUG_OBJECTS) thin-provisioning/thin_debug.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

thin_repair: $(THIN_REPAIR_OBJECTS) thin-provisioning/thin_repair.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

thin_dump: $(THIN_DUMP_OBJECTS) thin-provisioning/thin_dump.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

thin_restore: $(THIN_RESTORE_OBJECTS) thin-provisioning/thin_restore.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

thin_check: $(THIN_CHECK_OBJECTS) thin-provisioning/thin_check.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)

thin_rmap: $(THIN_RMAP_OBJECTS) thin-provisioning/thin_rmap.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)

thin_metadata_size: thin-provisioning/thin_metadata_size.o
	@echo "    [LD]  $@"
	$(V) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ -lm

#----------------------------------------------------------------
# Cache tools

CACHE_CHECK_SOURCE=\
	base/base64.cc \
	base/error_state.cc \
	persistent-data/checksum.cc \
	persistent-data/endian_utils.cc \
	persistent-data/error_set.cc \
	persistent-data/file_utils.cc \
	persistent-data/hex_dump.cc \
	persistent-data/lock_tracker.cc \
	persistent-data/data-structures/btree.cc \
	persistent-data/data-structures/bitset.cc \
	persistent-data/space_map.cc \
	persistent-data/space-maps/disk.cc \
	persistent-data/space-maps/recursive.cc \
	persistent-data/space-maps/careful_alloc.cc \
	persistent-data/transaction_manager.cc \
	caching/hint_array.cc \
	caching/superblock.cc \
	caching/mapping_array.cc \
	caching/metadata.cc \
	caching/metadata_dump.cc \
	caching/restore_emitter.cc \
	caching/xml_format.cc

CACHE_CHECK_OBJECTS=$(subst .cc,.o,$(CACHE_CHECK_SOURCE))

CACHE_DUMP_SOURCE=$(SOURCE)
CACHE_DUMP_OBJECTS=$(subst .cc,.o,$(CACHE_DUMP_SOURCE))

CACHE_REPAIR_SOURCE=$(SOURCE)
CACHE_REPAIR_OBJECTS=$(subst .cc,.o,$(CACHE_REPAIR_SOURCE))

CACHE_RESTORE_SOURCE=$(SOURCE)
CACHE_RESTORE_OBJECTS=$(subst .cc,.o,$(CACHE_RESTORE_SOURCE))

cache_check: $(CACHE_CHECK_OBJECTS) caching/cache_check.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

cache_dump: $(CACHE_DUMP_OBJECTS) caching/cache_dump.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

cache_repair: $(CACHE_REPAIR_OBJECTS) caching/cache_repair.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

cache_restore: $(CACHE_RESTORE_OBJECTS) caching/cache_restore.o
	@echo "    [LD]  $@"
	$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

DEPEND_FILES=\
	$(subst .cc,.d,$(SOURCE)) \
	$(subst .cc,.d,$(TEST_SOURCE)) \
	$(subst .cc,.d,$(CXX_PROGRAM_SOURCE)) \
	$(subst .c,.d,$(C_PROGRAM_SOURCE))

.PHONY: clean distclean

clean:
	find . -name \*.o -delete
	find . -name \*.gmo -delete
	find . -name \*.d -delete
	$(RM) $(TEST_PROGRAMS) $(PROGRAMS) $(GMOCK_OBJECTS) lib/*.a

distclean: clean
	$(RM) config.cache config.log config.status configure.h version.h Makefile unit-tests/Makefile

install: $(PROGRAMS)
	$(INSTALL_DIR) $(BINDIR)
	$(INSTALL_PROGRAM) cache_check $(BINDIR)
	$(INSTALL_PROGRAM) cache_dump $(BINDIR)
	$(INSTALL_PROGRAM) cache_repair $(BINDIR)
	$(INSTALL_PROGRAM) cache_restore $(BINDIR)
	$(INSTALL_PROGRAM) thin_check $(BINDIR)
	$(INSTALL_PROGRAM) thin_dump $(BINDIR)
	$(INSTALL_PROGRAM) thin_repair $(BINDIR)
	$(INSTALL_PROGRAM) thin_restore $(BINDIR)
	$(INSTALL_PROGRAM) thin_rmap $(BINDIR)
	$(INSTALL_PROGRAM) thin_metadata_size $(BINDIR)
	$(INSTALL_DIR) $(MANPATH)/man8
	$(INSTALL_DATA) man8/cache_check.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/cache_dump.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/cache_repair.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/cache_restore.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/thin_check.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/thin_dump.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/thin_repair.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/thin_restore.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/thin_rmap.8 $(MANPATH)/man8
	$(INSTALL_DATA) man8/thin_metadata_size.8 $(MANPATH)/man8

.PHONY: install

ifeq ("@TESTING@", "yes")
include unit-tests/Makefile

.PHONEY: features

features: $(PROGRAMS)
	cucumber --no-color --format progress

test: features unit-test
endif

-include $(DEPEND_FILES)