###############################################################################
# Configure section
#
# Specify the compiler, some standard variables, and build options.
###############################################################################

PREFIX ?= i686-w64-mingw32-
AR = $(PREFIX)ar
CC = $(PREFIX)gcc
CP = cp
LD = $(PREFIX)gcc
RANLIB = $(PREFIX)ranlib
STRIP = $(PREFIX)strip
YASM = yasm

CFLAGS = -Wall -Wextra -std=c99 $(DEPFLAGS) -I. -fopenmp
LDFLAGS = -L.
LIBS = -lavs
YASMFLAGS = -f win32 -DPREFIX=1 -DARCH_X86_64=0 -DHAVE_CPUNOP=1 -DHAVE_ALIGNED_STACK=1 -I.

CFLAGS += -mmmx -msse -mfpmath=sse -msse2

# Automatically generate dependency files.
# -MMD - only for local includes
# -MF  - file in which to write the rule
# -MT  - target of the rule
DEPFLAGS = -MMD -MF $(@:.o=.d) -MT $@

DEBUG = 0
LOCAL_LUA = 0
LOCAL_LUAJIT = 1
WINDOWS = 1

###############################################################################
# End of configure section.
###############################################################################

ifeq ($(WINDOWS),1)
    EXE=.exe
endif

ifeq ($(DEBUG),0)
    CFLAGS += -O3
else
    CFLAGS += -O0 -g -DDEBUG_LUA=1
endif

ifeq ($(LOCAL_LUA),1)
    CFLAGS +=-DLOCAL_LUA=1
    LIBS += lua-5.2.3/src/liblua.a
else ifeq ($(LOCAL_LUAJIT),1)
    CFLAGS +=-DLOCAL_LUAJIT=1
    LIBS += luajit-2.0/libluajit.a
else
    LIBS += -llua
endif

# Try some quiet rules
ifndef V
Q      = @
ECHO   = printf "$(1)\t%s\n" $(2)
BRIEF  = AR CC LD STRIP YASM
SILENT = CP RANLIB RM

MSG    = $@
M      = @$(call ECHO,$(TAG),$@);
$(foreach VAR,$(BRIEF), $(eval override $(VAR) = @$$(call ECHO,$(VAR),$$(MSG)); $($(VAR))))
$(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR))))
endif

# List of object files.

LIB_OBJECTS = bpm.o \
              block.o \
              components.o \
              effect_list.o \
              expressions.o \
              linedraw.o \
              main.o \
              matrix.o \
              not_implemented.o \
              pixel.o \
              utils.o \
              x86/block.o \
              x86/init.o \

MISC_OBJECTS = misc/buffer_save.o \
               misc/comment.o \
               misc/render_mode.o \

RENDER_OBJECTS = render/beat_clear.o \
                 render/bass_spin.o \
                 render/clear_screen.o \
                 render/dot_fountain.o \
                 render/dot_grid.o \
                 render/dot_plane.o \
                 render/osc_star.o \
                 render/particle.o \
                 render/ring.o \
                 render/rot_star.o \
                 render/simple.o \
                 render/superscope.o \
                 render/star_field.o \
                 render/timescope.o \

TRANS_OBJECTS = trans/blit.o \
                trans/blur.o \
                trans/brightness.o \
                trans/bump.o \
                trans/channel_shift.o \
                trans/colour_clip.o \
                trans/colour_fade.o \
                trans/colour_map.o \
                trans/colour_modifier.o \
                trans/colour_reduction.o \
                trans/dynamic_distance_modifier.o \
                trans/dynamic_movement.o \
                trans/dynamic_shift.o \
                trans/fadeout.o \
                trans/fast_brightness.o \
                trans/grain.o \
                trans/interferences.o \
                trans/interleave.o \
                trans/invert.o \
                trans/mirror.o \
                trans/mosaic.o \
                trans/movement.o \
                trans/multiplier.o \
                trans/roto_blit.o \
                trans/scatter.o \
                trans/texer.o \
                trans/unique_tone.o \
                trans/video_delay.o \
                trans/water.o \
                trans/water_bump.o \
                x86/channel_shift.o \
                x86/colour_reduction.o \
                x86/fast_brightness.o \
                x86/multiplier.o \
                x86/unique_tone.o \
                x86/water.o \

LIB_OBJECTS += $(MISC_OBJECTS) $(RENDER_OBJECTS) $(TRANS_OBJECTS)

LIBRARY = libavs.a

PROGRAMS = tests/asm_block \

PROGRAMS := $(PROGRAMS:%=%$(EXE))

ALL_OBJECTS = $(LIB_OBJECTS) $(PROGRAMS:$(EXE)=.o)

# Targets

# When make is run without specifying a target on the command line, make will
# default to the first target written in the makefile.  The order of the
# dependencies is important because they get fulfilled left to right.
all: lib cli

# The target "cli" depends on the created programs and the library.  "lib" comes
# first otherwise make can attempt to link the programs before the library was
# made.
cli: $(PROGRAMS)

# The target "lib" depends on the created library.
lib: $(LIBRARY)

# Recipes

# The recipe to make the debug programs.  This has a dependency on lib to ensure
# that they are rebuilt when library objects change.
%_g$(EXE): %.o lib
	$(LD) $(LDFLAGS) -o $@ $< $(LIBS)

# This "double dependency" stops make from automatically removing the
# intermediate files produced (the object files and the debug versions).
$(PROGRAMS): %$(EXE): %_g$(EXE)
	$(CP) $< $@
	$(STRIP) $@

# The recipe to make the library.
$(LIBRARY): $(LIB_OBJECTS)
	$(AR) rc $(LIBRARY) $(LIB_OBJECTS)
	$(RANLIB) $(LIBRARY)

# Recipe to make objects from assembly
%.o: %.asm x86/x86inc.asm x86/x86util.asm
	$(YASM) $(YASMFLAGS) -o $@ $<

# The use of the 'Q' command in sed here is a GNU extension.
lua-function-helper.h: doc/function-helper.lua
	echo 'static const char *lua_function_helper =' > $@
	sed '/^--\[/Q;s|^\(.\+\)$$|"\1\\n"|' $< >> $@
	echo ';' >> $@

expressions.o: lua-function-helper.h

winamp: vis_jdavs.o lib
	$(LD) $(LDFLAGS) -mwindows -municode -mdll -o $(<:.o=.dll) $< $(LIBS) -lgdi32 -lcomdlg32
	$(CP) $(<:.o=.dll) /cygdrive/c/Winamp/Plugins/

# Use the built-in variable for rm
clean: clean-prof
	$(RM) $(ALL_OBJECTS:.o=.d) $(ALL_OBJECTS) $(LIBRARY) $(PROGRAMS) $(PROGRAMS:$(EXE)=_g$(EXE))

clean-prof:
	$(RM) $(ALL_OBJECTS:.o=.gcda)
	$(RM) $(ALL_OBJECTS:.o=.gcda.info)
	$(RM) $(ALL_OBJECTS:.o=.gcno)

.PHONY: all clean clean-prof cli lib winamp

-include $(ALL_OBJECTS:.o=.d)
