############# Names and dirs #############

#LIBDIRS  = CoreLibrary PsySDK
LIBDIRS  = CMSDK
BINDIRS  = Psyclone Examples System
PYDIRS  = CMSDK System

BINDIR = bin
LIBDIR = lib

######## Include version info ########

include CMSDK/Makefile.ver
include Makefile.ver
PSYCLONE_REVISION := $(shell date +%y%m%d)
CMSDK_REVISION := $(shell date +%y%m%d)
VERSION = $(VERMAJOR).$(VERMINOR).$(PSYCLONE_REVISION)$(VERSUBTEXT)
CMSDK_VERSION = $(CMSDK_VERMAJOR).$(CMSDK_VERMINOR).$(CMSDK_REVISION)$(CMSDK_VERSUBTEXT)
LGPLDISTDIR = Psyclone_LGPL_$(VERSION)
BINARYDISTDIR = Psyclone_binary_$(PLATFORM)_$(VERSION)
DATE_TODAY = `date +%d\ %B\ %Y`
YEAR_TODAY = `date +%Y`

######## Licensing ########

BSD_HEADER_TEMPLATE = licences/bsd.header.template.txt
BSD_LICENCE_TEMPLATE = licences/bsd.licence.template.txt
LGPL_HEADER_TEMPLATE = licences/lgpl.header.template.txt

BSD_HEADER = licences/bsd.header.txt
LGPL_HEADER = licences/lgpl.header.txt
GPL_LICENCE = licences/licence-gpl.txt
LGPL_LICENCE = licences/licence-lgpl.txt

QUICKSTART_TEMPLATE = quickstart_template.txt
QUICKSTART_FILE = quickstart.txt

DO_NOT_LICENCE_FILES = -not -name xml_parser.\* -not -name bimap.h -not -name direntwin.h

include CMSDK/Makefile.sys

############# Setup dirs #############

SUBDIRS = $(LIBDIRS) $(BINDIRS)
PYSUBDIRS = $(PYDIRS)

RESULT := $(shell if [ ! -d $(BINDIR) ]; then mkdir $(BINDIR); fi)
RESULT := $(shell if [ ! -d $(LIBDIR) ]; then mkdir $(LIBDIR); fi)
RESULT := $(shell if [ ! -d $(BINDESTDIR) ]; then mkdir $(BINDESTDIR); fi)
RESULT := $(shell if [ ! -d $(LIBDESTDIR) ]; then mkdir $(LIBDESTDIR); fi)
ifeq ($(OSNAME),CYGWIN)
  RESULT := $(shell if [ ! -d $(WINBINDESTDIR) ]; then mkdir $(WINBINDESTDIR); fi)
  RESULT := $(shell if [ ! -d $(WINLIBDESTDIR) ]; then mkdir $(WINLIBDESTDIR); fi)
endif

############# Overall commands #############

all: compile install

debug: compile install

ssl: compile install

ssldebug: compile install

profile: compile install

compile:
	@for dir in $(SUBDIRS); do \
		if cd $(TOP_DIR)/$$dir; then make $(MAKECMDGOALS) --no-print-directory; fi;\
		cd $(TOP_DIR);\
	done

python2:
	@for dir in $(PYSUBDIRS); do \
		if cd $(TOP_DIR)/$$dir; then make $(MAKECMDGOALS) --no-print-directory; fi;\
		find $(TOP_DIR)/$$dir/$(BINDESTDIR) -path '*/.svn' -prune -o -type f -print -exec cp {} $(TOP_DIR)/$(BINDESTDIR) \; ;\
		cd $(TOP_DIR);\
	done

python3:
	@for dir in $(PYSUBDIRS); do \
		if cd $(TOP_DIR)/$$dir; then make $(MAKECMDGOALS) --no-print-directory; fi;\
		find $(TOP_DIR)/$$dir/$(BINDESTDIR) -path '*/.svn' -prune -o -type f -print -exec cp {} $(TOP_DIR)/$(BINDESTDIR) \; ;\
		cd $(TOP_DIR);\
	done
	
############# Building Visual Studio binaries #############

wincompile:
ifeq ($(VCBUILDDIR),VC_90_NOT_FOUND)
	$(error ERROR: COULD NOT FIND vcpackages DIRECTORY at either $(X86VC90PATH) OR $(VC90PATH) )
endif
ifeq ($(OSNAME),CYGWIN)
	@echo Building Visual Studio 32-bit binaries...
	@cd psyclone; $(VCBUILDDIR)/vcbuild Psyclone.vs2008.sln "Release|Win32"; cd $(TOP_DIR)
endif

windebugcompile:
ifeq ($(VCBUILDDIR),VC_90_NOT_FOUND)
	$(error ERROR: COULD NOT FIND vcpackages DIRECTORY at either $(X86VC90PATH) OR $(VC90PATH) )
endif
ifeq ($(OSNAME),CYGWIN)
	@echo Building Visual Studio 32-bit debug binaries...
	@cd psyclone; $(VCBUILDDIR)/vcbuild Psyclone.vs2008.sln "Debug|Win32"; cd $(TOP_DIR)
endif

wincompile64:
ifeq ($(VCBUILDDIR),VC_90_NOT_FOUND)
	$(error ERROR: COULD NOT FIND vcpackages DIRECTORY at either $(X86VC90PATH) OR $(VC90PATH) )
endif
ifeq ($(OSNAME),CYGWIN)
	@echo Building Visual Studio 64-bit binaries...
	@cd psyclone; $(VCBUILDDIR)/vcbuild Psyclone.vs2008.sln "Release|x64"; cd $(TOP_DIR)
endif

windebugcompile64:
ifeq ($(VCBUILDDIR),VC_90_NOT_FOUND)
	$(error ERROR: COULD NOT FIND vcpackages DIRECTORY at either $(X86VC90PATH) OR $(VC90PATH) )
endif
ifeq ($(OSNAME),CYGWIN)
	@echo Building Visual Studio 64-bit debug binaries...
	@cd psyclone; $(VCBUILDDIR)/vcbuild Psyclone.vs2008.sln "Debug|x64"; cd $(TOP_DIR)
endif


############# Installing binaries and libraries #############

install:
	@for dir in $(LIBDIRS); do \
		find $(TOP_DIR)/$$dir/$(LIBDESTDIR) -path '*/.svn' -prune -o -type f -print -exec cp {} $(TOP_DIR)/$(LIBDESTDIR) \; ;\
	done
	@for dir in $(BINDIRS); do \
		find $(TOP_DIR)/$$dir/$(BINDESTDIR) -path '*/.svn' -prune -o -type f -print -exec cp {} $(TOP_DIR)/$(BINDESTDIR) \; ;\
	done
ifeq ($(OSNAME),MACOSX)
	@echo Ad-hoc signing macOS binaries avoids Gatekeeper killing unsigned executables...
	@find $(BINDESTDIR) -maxdepth 1 -type f \( -perm -u+x -o -name '*.so' \) -exec codesign -s - {} \; 2>/dev/null || true
	@echo Signing done.
endif
ifeq ($(OSNAME),CYGWIN)
	@for dir in $(LIBDIRS); do \
		find $(TOP_DIR)/$$dir/$(WINLIBDESTDIR) -path '*/.svn' -prune -o -type f -print -exec cp {} $(TOP_DIR)/$(WINLIBDESTDIR) \; ;\
	done
	@for dir in $(BINDIRS); do \
		find $(TOP_DIR)/$$dir/$(WINBINDESTDIR) -path '*/.svn' -prune -o -type f -print -exec cp {} $(TOP_DIR)/$(WINBINDESTDIR) \; ;\
	done
endif

############# Cleaning up #############

clean:
	@for dir in $(SUBDIRS); do \
		if cd $(TOP_DIR)/$$dir; then echo Cleaning $$dir; make clean --no-print-directory; fi;\
		cd $(TOP_DIR);\
	done

totalclean:
	@for dir in $(SUBDIRS); do \
		if cd $(TOP_DIR)/$$dir; then echo Total cleaning $$dir; make totalclean --no-print-directory; fi;\
		cd $(TOP_DIR);\
	done

rebuild: clean all

############# macOS: ad-hoc sign binaries (stops Gatekeeper from killing them) #############
sign:
ifeq ($(OSNAME),MACOSX)
	@echo Ad-hoc signing binaries in $(BINDESTDIR)...
	@find $(BINDESTDIR) -maxdepth 1 -type f \( -perm -u+x -o -name '*.so' \) -exec codesign -s - {} \; 2>/dev/null || true
	@echo Done. Run ./$(BINDESTDIR)/Psyclone again.
else
	@echo 'sign' is only for macOS. Skip.
endif

############# Open Source Dist #############

licence_files:
	@$(SH) replace.sh YEAR_TEMPLATE "$(YEAR_TODAY)" $(BSD_HEADER_TEMPLATE) $(BSD_HEADER)
	@$(SH) replace.sh DATE_TEMPLATE "$(DATE_TODAY)" $(BSD_HEADER) $(BSD_HEADER)
	@$(SH) replace.sh FULL_VERSION_TEMPLATE "$(CMSDK_VERSION)" $(BSD_HEADER) $(BSD_HEADER)
	
	@$(SH) replace.sh YEAR_TEMPLATE "$(YEAR_TODAY)" $(LGPL_HEADER_TEMPLATE) $(LGPL_HEADER)
	@$(SH) replace.sh DATE_TEMPLATE "$(DATE_TODAY)" $(LGPL_HEADER) $(LGPL_HEADER)
	@$(SH) replace.sh FULL_VERSION_TEMPLATE "$(VERSION)" $(LGPL_HEADER) $(LGPL_HEADER)
	@$(SH) replace.sh MAJOR_VERSION_TEMPLATE "$(VERMAJOR)" $(LGPL_HEADER) $(LGPL_HEADER)

lgpl: licence_files
	@rm -rf $(LGPLDISTDIR)
	@mkdir $(LGPLDISTDIR)

	@echo
	@echo Build date: $(DATE_TODAY) > $(LGPLDISTDIR)/version.txt
	@echo Psyclone version $(VERMAJOR).$(VERMINOR).$(PSYCLONE_REVISION)$(VERSUBTEXT) LGPL >> $(LGPLDISTDIR)/version.txt
	@echo Psyclone revision $(PSYCLONE_REVISION) >> $(LGPLDISTDIR)/version.txt
	@echo CMSDK version $(CMSDK_VERMAJOR).$(CMSDK_VERMINOR).$(CMSDK_REVISION)$(CMSDK_VERSUBTEXT) BSD >> $(LGPLDISTDIR)/version.txt
	@echo CMSDK revision $(CMSDK_REVISION) >> $(LGPLDISTDIR)/version.txt
	@cat $(LGPLDISTDIR)/version.txt
	@echo
	
	@echo Building LGPL distribution structure
	@$(CPALL) Docs $(LGPLDISTDIR)/
	@$(CPALL) html $(LGPLDISTDIR)/
	@mkdir $(LGPLDISTDIR)/CMSDK
	@mkdir $(LGPLDISTDIR)/Examples
	@mkdir $(LGPLDISTDIR)/Psyclone
	@mkdir $(LGPLDISTDIR)/System
	@$(CPALL) CMSDK/include $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/src $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/Makefile $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/Makefile.sys $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/Makefile.ver $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/cmsdk.i $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/changelog.txt $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/acknowledgements.txt $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/*vs2022.vcxproj $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/*vs2022.vcxproj.filters $(LGPLDISTDIR)/CMSDK
	@$(CPALL) CMSDK/*vs2022.sln $(LGPLDISTDIR)/CMSDK

	@$(CPALL) Examples/include $(LGPLDISTDIR)/Examples
	@$(CPALL) Examples/src $(LGPLDISTDIR)/Examples
	@$(CPALL) Examples/Makefile $(LGPLDISTDIR)/Examples
	@$(CPALL) Examples/*vs2022.vcxproj $(LGPLDISTDIR)/Examples
	@$(CPALL) Examples/*vs2022.vcxproj.filters $(LGPLDISTDIR)/Examples

	@$(CPALL) Psyclone/include $(LGPLDISTDIR)/Psyclone
	@$(CPALL) Psyclone/src $(LGPLDISTDIR)/Psyclone
	@$(CPALL) Psyclone/Makefile $(LGPLDISTDIR)/Psyclone
	@$(CPALL) Psyclone/Psyclone.rc $(LGPLDISTDIR)/Psyclone
	@$(CPALL) Psyclone/resource.h $(LGPLDISTDIR)/Psyclone
	@$(CPALL) Psyclone/Psyclone.exe.manifest $(LGPLDISTDIR)/Psyclone
	@$(CPALL) Psyclone/*vs2022.vcxproj $(LGPLDISTDIR)/Psyclone
	@$(CPALL) Psyclone/*vs2022.vcxproj.filters $(LGPLDISTDIR)/Psyclone

	@$(CPALL) System/include $(LGPLDISTDIR)/System
	@$(CPALL) System/src $(LGPLDISTDIR)/System
	@$(CPALL) System/Makefile $(LGPLDISTDIR)/System
	@$(CPALL) System/*vs2022.vcxproj $(LGPLDISTDIR)/System
	@$(CPALL) System/*vs2022.vcxproj.filters $(LGPLDISTDIR)/System

	@$(CPALL) Makefile $(LGPLDISTDIR)
	@$(CPALL) Makefile.* $(LGPLDISTDIR)
	@$(CPALL) changelog.txt $(LGPLDISTDIR)
	@$(CPALL) readme.html $(LGPLDISTDIR)
	@$(CPALL) acknowledgements.txt $(LGPLDISTDIR)
	@$(CPALL) *vs2022.sln $(LGPLDISTDIR)
	@$(CPALL) $(GPL_LICENCE) $(LGPLDISTDIR)
	@$(CPALL) $(LGPL_LICENCE) $(LGPLDISTDIR)

	@echo Inserting BSD licence headers into CMSDK files...
	@find $(LGPLDISTDIR)/CMSDK -name \*.h $(DO_NOT_LICENCE_FILES) -exec sh addlicense.sh $(BSD_HEADER) {} \;
	@find $(LGPLDISTDIR)/CMSDK -name \*.c $(DO_NOT_LICENCE_FILES) -exec sh addlicense.sh $(BSD_HEADER) {} \;
	@find $(LGPLDISTDIR)/CMSDK -name \*.cpp $(DO_NOT_LICENCE_FILES) -exec sh addlicense.sh $(BSD_HEADER) {} \;

	@echo Inserting LGPL licence headers into all other source files files...
	@find $(LGPLDISTDIR)/Examples $(LGPLDISTDIR)/Psyclone $(LGPLDISTDIR)/System -name \*.h -exec sh addlicense.sh $(LGPL_HEADER) {} \;
	@find $(LGPLDISTDIR)/Examples $(LGPLDISTDIR)/Psyclone $(LGPLDISTDIR)/System -name \*.c -exec sh addlicense.sh $(LGPL_HEADER) {} \;
	@find $(LGPLDISTDIR)/Examples $(LGPLDISTDIR)/Psyclone $(LGPLDISTDIR)/System -name \*.cpp -exec sh addlicense.sh $(LGPL_HEADER) {} \;

	@$(SH) replace.sh YEAR_TEMPLATE "$(YEAR_TODAY)" $(QUICKSTART_TEMPLATE) $(QUICKSTART_FILE)
	@$(SH) replace.sh DATE_TEMPLATE "$(DATE_TODAY)" $(QUICKSTART_FILE) $(QUICKSTART_FILE)
	@$(SH) replace.sh MAJOR_VERSION_TEMPLATE "$(VERMAJOR)" $(QUICKSTART_FILE) $(QUICKSTART_FILE)
	@$(CPALL) quickstart.txt $(LGPLDISTDIR)
	@$(CPALL) quickstart.txt $(LGPLDISTDIR)/html
	
	@echo Building archive...
	@zip -qr $(LGPLDISTDIR).zip $(LGPLDISTDIR)
	
	@echo
	@echo Archive ready: $(LGPLDISTDIR).zip - size in kb: `du -ks $(LGPLDISTDIR).zip | awk '{print $$1}'`
	@echo
	@exit 0

binary:
	@make clean
	@make
	@make python3
	@make debug
	@make python3 debug
	@rm -rf $(BINARYDISTDIR)
	@mkdir $(BINARYDISTDIR)

	@echo
	@echo Build date: $(DATE_TODAY) > $(BINARYDISTDIR)/version.txt
	@echo Psyclone version $(VERMAJOR).$(VERMINOR).$(PSYCLONE_REVISION)$(VERSUBTEXT) LGPL >> $(BINARYDISTDIR)/version.txt
	@echo Psyclone revision $(PSYCLONE_REVISION) >> $(BINARYDISTDIR)/version.txt
	@echo CMSDK version $(CMSDK_VERMAJOR).$(CMSDK_VERMINOR).$(CMSDK_REVISION)$(CMSDK_VERSUBTEXT) BSD >> $(BINARYDISTDIR)/version.txt
	@echo CMSDK revision $(CMSDK_REVISION) >> $(BINARYDISTDIR)/version.txt
	@cat $(BINARYDISTDIR)/version.txt
	@echo
	
	@echo Building binary distribution structure
	@$(CPALL) Docs $(BINARYDISTDIR)/
	@$(CPALL) html $(BINARYDISTDIR)/

	@# Use cp -RfL (dereference symlinks) not $(CPALL): some bin dirs contain
	@# stray symlinks (e.g. macOS Psyclone/bin/macosx64/libPsySystem.so ->
	@# System/.../libPsySystem.so). Copying them as symlinks and then copying the
	@# real file from another bin dir on top self-copies -> "cp: Permission
	@# denied". -L resolves each symlink to the real file it targets; on Linux/
	@# Windows (no such symlinks) -L is a harmless no-op, and the resulting
	@# archive contains real files rather than broken absolute links.
	@cp -RfL CMSDK/bin/$(ARCH)/* $(BINARYDISTDIR)
	@cp -RfL Examples/bin/$(ARCH)/* $(BINARYDISTDIR)
	@cp -RfL Psyclone/bin/$(ARCH)/* $(BINARYDISTDIR)
	@cp -RfL System/bin/$(ARCH)/* $(BINARYDISTDIR)

	@$(CPALL) acknowledgements.txt $(BINARYDISTDIR)
	@$(CPALL) changelog.txt $(BINARYDISTDIR)
	@$(CPALL) readme.html $(BINARYDISTDIR)
	
	@echo Building archive...
	@zip -qr $(BINARYDISTDIR).zip $(BINARYDISTDIR)
	
	@echo
	@echo Archive ready: $(BINARYDISTDIR).zip - size in kb: `du -ks $(BINARYDISTDIR).zip | awk '{print $$1}'`
	@echo
	@exit 0
	
info:
	@echo
	@echo Build date: $(DATE_TODAY)
	@echo Psyclone version $(VERMAJOR).$(VERMINOR).$(PSYCLONE_REVISION)$(VERSUBTEXT) LGPL
	@echo Psyclone revision $(PSYCLONE_REVISION)
	@echo CMSDK version $(CMSDK_VERMAJOR).$(CMSDK_VERMINOR).$(CMSDK_REVISION)$(CMSDK_VERSUBTEXT) BSD
	@echo CMSDK revision $(CMSDK_REVISION)
	@echo
