# GNU makefile for ChromaPlas

# USAGE:
# make [target] [DEBUGMODE=1|PROFILEMODE=1] [STATICLINK=1] [CP_NO_JPEG=1]
#  [CP_NO_PNG=1] [SCREENSAVER=1]
#
# target:
#  - No target is needed to build ChromaPlas.
#  - 'clean' deletes object files that were used to build ChromaPlas.
#   Note that if you passed STATICLINK=1 or SCREENSAVER=1 to 'make' when
#   building ChromaPlas, you must also pass them to 'make' when cleaning.
#
# DEBUGMODE=1 - Make debugging build (or clean debugging build if appropriate
#  target is chosen).
# PROFILEMODE=1 - Make Profiling build (or clean debugging build if
#  appropriate target is chosen).
# Note that the above two are mutually exclusive.
#
# STATICLINK=1 - Make a statically linked build. This is only applicable on
#  platforms that support dynamically linked builds. Otherwise, do not use
#  this option.
#
# Pass in STATICLINK=1 to link Allegro statically on platforms where
#  static-liniking is applicable
# Pass CP_NO_JPEG=1 to disable JPEG support (if it's enabled, JPGalleg is
#  required
# Pass CP_NO_PNG=1 to disable PNG support (if it's enabled, LoadPNG is
#  required
# Pass SCREENSAVER=1 to enavle the app to be built as a screensaver
#  (currently only supported on Windows).
#
# The platform is detected automatically.
# Note: because of this, cross-compiling is currently not supported
# TODO: Pass in a platform-override paramater.


# Detect platform according to presence of environment variables.
ifdef DJDIR
	TARGET = djgpp
else
	ifdef MINGDIR
		TARGET = mingw
	else
		# TODO: Other targets (eg. Mac)
		TARGET = unix
	endif
endif




# A list of libraries to use when linking.
CHROMAPLAS_LIBS =

# Unix versions use a script to work out which libraries to use. These are paramaters for this script.
ALLEGCONFIGSCRIPTPARAMS =



ifdef DEBUGMODE

	# Debug build
	BUILDVERSIONNAME = debug
	ALLEGROLIBNAME = alld
	ALLEGCONFIGSCRIPTPARAMS += debug

	# TODO: Check that these two are correct
	JPGALLEGLIBNAME = jpgad
	LOADPNGLIBNAME = ldpngd

else
	ifdef PROFILEMODE

		# Profile build
		BUILDVERSIONNAME = profile
		ALLEGROLIBNAME = allp
		ALLEGCONFIGSCRIPTPARAMS += profile

		# TODO: Check that these two are correct
		JPGALLEGLIBNAME = jpgap
		LOADPNGLIBNAME = ldpngp

	else

		# Release build
		BUILDVERSIONNAME = release
		ALLEGROLIBNAME = alleg

		JPGALLEGLIBNAME = jpgal
		LOADPNGLIBNAME = ldpng

	endif
endif


ifdef STATICLINK

	ALLEGROLIBNAME := $(ALLEGROLIBNAME)_s
	ALLEGCONFIGSCRIPTPARAMS := --static $(ALLEGCONFIGSCRIPTPARAMS)

	JPGALLEGLIBS = -l$(JPGALLEGLIBNAME)_s
	LOADPNGLIBS = -l$(LOADPNGLIBNAME)_s

else

	ALLEGCONFIGSCRIPTPARAMS := --libs $(ALLEGCONFIGSCRIPTPARAMS)

	JPGALLEGLIBS = -l$(JPGALLEGLIBNAME)
	LOADPNGLIBS = -l$(LOADPNGLIBNAME)

endif



ifdef SCREENSAVER

	CCFLAGS += -DCP_IS_SCREENSAVER

endif



LOADPNGLIBS += -lpng -lz




# We can switch off support for JPEGs if we are too lazy to install JPGalleg
ifdef CP_NO_JPEG
	CCFLAGS += -DCP_NO_JPEG
else
	CHROMAPLAS_EXTRA_LIBS += $(JPGALLEGLIBS)
endif

# We can switch off support for PNGs if we are too lazy to install LoadPNG
ifdef CP_NO_PNG
	CCFLAGS += -DCP_NO_PNG
else
	CHROMAPLAS_EXTRA_LIBS += $(LOADPNGLIBS)
endif


# The extra libs for image-formats go at the front.
CHROMAPLAS_LIBS += $(CHROMAPLAS_EXTRA_LIBS)




ifeq ($(TARGET),djgpp)

	ifdef STATICLINK

.PHONY : badstaticlink
badstaticlink :
	@echo Error: Static linking not relevant for DJGPP - all DJGPP builds are static. Do not specify STATICLINK=1.

	endif

	ifdef SCREENSAVER
	
.PHONY : badscreensaverDJGPP
badscreensaverDJGPP :
	@echo Error: The DJGPP version cannot be compiled as a screensaver. Do not specify SCREENSAVER=1.
	
	endif

	# Root of directory to place immediate object files
	OBJDIRROOT = obj/obj.dj

	# Filename of target
	CHROMAPLASEXE = chromapl.exe

	# CPU Architecture flags
	ARCHFLAGS = -march=i486
	# ?: i386?


	# Libraries required by ChromaPlas.
	CHROMAPLAS_LIBS += -l$(ALLEGROLIBNAME)

else
	ifeq ($(TARGET),mingw)

		# Root of directory to place immediate object files
		OBJDIRROOT = obj/obj.mgw


		# Filename of target.
		# In Windows, extension changes according to whether or not it's a screensaver
		ifdef SCREENSAVER
			CHROMAPLASEXE = ChromaplasWin.scr
		else
			CHROMAPLASEXE = ChromaplasWin.exe
		endif

		# TODO: Make the icon more platform-independant.

		# CPU Architecture flags
		ARCHFLAGS = -march=pentium2
		# ARCHFLAGS = -march=i586
		# ARCHFLAGS = -march=athlon
		# ARCHFLAGS = -march=pentium2 -mcpu=athlon # Or use separate CPUFLAGS?
		# i586 is also Allegro's default setting.

		CHROMAPLAS_LIBS += -l$(ALLEGROLIBNAME)
		ifdef STATICLINK
			# ?: Do we need to pass in -lshell32 too?
			CHROMAPLAS_LIBS += -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lole32 -ldinput -lddraw -ldxguid -lwinmm -ldsound
		endif

	else
		ifeq ($(TARGET),unix)

			ifdef SCREENSAVER
	
.PHONY : badscreensaverUNIX
badscreensaverUNIX :
	@echo Error: The screensaver is not yet implemented for the Unix version. Do not specify SCREENSAVER=1 for now.
	
			endif


			# Root of directory to place immediate object files
			OBJDIRROOT = obj/obj.unx

			# Filename of target
			CHROMAPLASEXE = chromaplas

			# CPU Architecture flags
			# ARCHFLAGS = -march=


			# Libraries required by ChromaPlas.
			CHROMAPLAS_LIBS += `allegro-config $(ALLEGCONFIGSCRIPTPARAMS)`
			# Note above is untested. If it fails, try below instead
			#ifdef STATICLINK
			#	CHROMAPLAS_LIBS += `allegro-config --static`
			#else
			#	CHROMAPLAS_LIBS += `allegro-config --libs`
			#endif



		else

.PHONY : badtarget
badtarget :
	@echo Error: unsupported target.

		endif
	endif
endif




# Directory to place immediate object files
ifdef STATICLINK
	OBJDIR = $(OBJDIRROOT)/$(BUILDVERSIONNAME)_s
else
	OBJDIR = $(OBJDIRROOT)/$(BUILDVERSIONNAME)
endif




# objs needed to build ChromaPlas executable
CP_OBJS = main.o aecolspc.o cpmthhlp.o cpsttngs.o cpplasma.o cpfunpal.o cpimcosp.o cpbltiim.o cpgfx.o cprender.o aeconfig.o cpconfig.o cpprglp.o



ifeq ($(TARGET),mingw)

	# PFLAGS = -Wl,--subsystem,windows
	PFLAGS = -mwindows
	# ?: Do we need '-Wl,--subsystem,windows' [or '-mwindows'] when compiling, linking or both?

	ifdef ALLEGRO_USE_CYGWIN
		PFLAGS += -mno-cygwin
	endif



	# Extra .o files for Windows version
	CP_OBJS += cpwin_.o

	# Windows resource (outside the SS, it uses the app-icon).
	CP_OBJS += cpwinrsc.o
	
	ifdef SCREENSAVER

		# Extra .o files for Windows screensaver version
		CP_OBJS += cpwin_ss.o

	endif

endif


#? Check Allegro's makefiles to see which optimisation flags are used for which builds.
# TODO: the if below should build the CCFLAGS var.

ifdef DEBUGMODE

	# Debug build
	CCFLAGS += -DDEBUGMODE -D_DEBUG
	OFLAGS = $(ARCHFLAGS)
	LDFLAGS += -g

else
	ifdef PROFILEMODE

		# Profile build
		CCFLAGS += -DPROFILEMODE
		# ?: CCFLAGS += -pg
		# OFLAGS = $(ARCHFLAGS) -O3 -ffast-math
		OFLAGS = $(ARCHFLAGS) -O3
		# ?: -O2 or -fomit-frame-pointer for profile mode?
		LFLAGS += -pg

	else
	
		# Release build
		# WARNING: -ffast-math has been known to cause a problem in the DOS build (DJGPP 2.03 gcc 4.5.2) in either cpTurboHLS2RGB() or cpTurboRGB2HLS() (and also in the equivalent HSV functions) where the hue from 0x000 to 0x2FF becomes equivalent to values 0x6FF to 0x300.
		# OFLAGS = $(ARCHFLAGS) -O3 -ffast-math -fomit-frame-pointer
		OFLAGS = $(ARCHFLAGS) -O3 -fomit-frame-pointer
		# OFLAGS += -fno-strength-reduce
		LDFLAGS += -s

	endif
endif


# TODO: More warning flags (linker too)

# WFLAGS = -Wall -W -Wstrict-prototypes -pedantic -Wno-unused-parameter
# WFLAGS = -Wall -W -Wstrict-prototypes -pedantic
WFLAGS = -Wall -W -Wstrict-prototypes -Wno-unused-parameter
# WFLAGS = -Wall -W -Wstrict-prototypes
# WFLAGS = -Wall -W -pedantic -Wno-unused-parameter
# WFLAGS = -Wall -W -pedantic
# WFLAGS = -W -Wall -Wno-unused-parameter
# WFLAGS = -W -Wall
# WFLAGS = -Wall

# WFLAGS = -W -Wall -Wsign-compare -Wshadow

# -Wc++-compat


# -Wswitch-default
# -Wunused

# -Wbad-function-cast

# -Werror-implicit-function-declaration

# -Wconversion

# -Wwrite-strings

# -Wunreachable-code


# -Wno-unused-parameter	# See http://sourcefrog.net/weblog/software/languages/C/unused.html for better way of dealing with the unused paramater warnings.

# CC=g++


CCFLAGS += -Isrc $(WFLAGS) $(OFLAGS) $(PFLAGS)
# CCFLAGS += -Isrc $(WFLAGS) $(OFLAGS) $(PFLAGS) -x c++
# SFLAGS = -Isrc $(WFLAGS)


ifdef STATICLINK
	CCFLAGS += -DALLEGRO_STATICLINK
endif



CHROMAPLAS_OBJS = $(addprefix $(OBJDIR)/, $(CP_OBJS))









# Where to look for files mentioned in the makefile dependencies that aren't in the current directory.
VPATH = src


.PRECIOUS : $(OBJDIR)/%.o		# Prevent ChromaPlas objects from being deleted (is this necessary? If I don't use this, the last .o file gets deleted).

.PHONY : clean



######
# Targets
######

all: msg $(CHROMAPLASEXE)
	@echo
	@echo FINISHED!

msg:
	@echo Building ChromaPlas for $(TARGET). Please wait...
	@echo

# This is the main executable, so we don't need to bother with implicit rules.
$(CHROMAPLASEXE) : $(CHROMAPLAS_OBJS)
	gcc $(LDFLAGS) $(PFLAGS) -o $@ $(CHROMAPLAS_OBJS) $(CHROMAPLAS_LIBS)



######
# Define standard implicit rules.
######

# Here, place all .h files that are common to all modules.
# Should only be a few .h files, coz otherwise, build takes ages.
# object from .c
# Should really have %.h instead of blah-header.h (main.c being the eception)
$(OBJDIR)/%.o : %.c aeglobal.h cpglobal.h cpmthhlp.h
	gcc $(CCFLAGS) -o $@ -c $<

# object from .s file
# $(OBJDIR)/%.o : %.s $(ASMDEFS_FILE) $(ASMDEF_FILE)
# 	gcc -x assembler-with-cpp $(SFLAGS) -o $@ -c $<


# Platform dependant (won't be built if not in CP_OBJS)
# object from .rc file - build the resource file
$(OBJDIR)/%.o: %.rc
	windres --include-dir src -O coff -o $@ -i $<




######
# Anything that is different from the standard implicit rules.
######

# TODO: Make cpwin_.h and cpwin_ss.h windows-dependent
# And cpwin_ss.h SCREENSAVER dependent

# objects that have extra dependancies than the standard rule
$(OBJDIR)/main.o: aeglobal.h cpglobal.h cpmthhlp.h cpsttngs.h cpplasma.h cpgfx.h cpconfig.h cpprglp.h cpwin_.h cpwin_ss.h

$(OBJDIR)/cpmthhlp.o: aeglobal.h cpglobal.h cpmthhlp.h
$(OBJDIR)/aecolspc.o: aeglobal.h cpmthhlp.h aecolspc.h
$(OBJDIR)/cpsttngs.o: aeglobal.h cpglobal.h cpmthhlp.h cpsttngs.h
$(OBJDIR)/cpplasma.o: aeglobal.h cpglobal.h cpmthhlp.h cpsttngs.h cpplasma.h
$(OBJDIR)/cpfunpal.o: aeglobal.h cpglobal.h aecolspc.h cpmthhlp.h cpsttngs.h cpgfx.h cpfunpal.h
$(OBJDIR)/cpimcosp.o: aeglobal.h cpglobal.h aecolspc.h cpsttngs.h cpimcosp.h
$(OBJDIR)/cpbltiim.o: aeglobal.h cpglobal.h aecolspc.h cpmthhlp.h cpsttngs.h cpimcosp.h cpbltiim.h
$(OBJDIR)/cpgfx.o: aeglobal.h cpglobal.h cpmthhlp.h cpsttngs.h cpfunpal.h cpimcosp.h cpbltiim.h cprender.h cpwin_.h cpgfx.h
$(OBJDIR)/cprender.o: aeglobal.h cpglobal.h aecolspc.h cpsttngs.h cpplasma.h cpfunpal.h cpimcosp.h cpgfx.h cprender.h
$(OBJDIR)/aeconfig.o: aeglobal.h aeconfig.h
$(OBJDIR)/cpconfig.o: aeglobal.h cpglobal.h cpsttngs.h aeconfig.h cpconfig.h
$(OBJDIR)/cpprglp.o: aeglobal.h cpglobal.h cpsttngs.h cpgfx.h cprender.h cpplasma.h cpfunpal.h cpprglp.h

# Platform dependant (won't be built if not in CP_OBJS)
# Windows
$(OBJDIR)/cpwin_.o: aeglobal.h cpwin_.h
$(OBJDIR)/cpwin_ss.o: aeglobal.h cpglobal.h cpsttngs.h cpgfx.h cpconfig.h cpprglp.h cpwin_ss.h cpwinrsc.rh
$(OBJDIR)/cpwinrsc.o: cpwinrsc.rh cpwinico.ico



######
# Cleanup.
######

# Clean all temporary stuff (eg. object files).
clean:
	rm -fv ./$(OBJDIR)/*.o
	# rm -v ./$(OBJDIR)/*.*
	@echo All temporary files used when building ChromaPlas have been deleted.
