# makefile to compile for windows using the mingw suite.
# To use this makefile to cross-compile from linux, type for example:
# make -f makefile.mingw CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-c++ \
#  WINDRES=i686-w64-mingw32-windres

# Miller's Windows build uses Microsoft Visual C and makefile.msvc:
# http://lists.puredata.info/pipermail/pd-dev/2004-10/002981.html

CC = gcc
CXX = g++
WINDRES = windres
MKDIR_P = mkdir -p

pd_src = ..
DLL_DIR = $(pd_src)/src

BIN_DIR = ../bin

VPATH = $(pd_src)/src

prefix = /usr/local/pd
exec_prefix = $(prefix)
includedir = $(prefix)/include
libdir = $(exec_prefix)/lib
mandir = $(prefix)/man
bindir = $(exec_prefix)/bin

GFLAGS = -DINSTALL_PREFIX=\"$(prefix)\"

# variables to match packages/Makefile.buildlayout so that they can be easily
# overridden when building Pd-extended builds. <hans@at.or.at>
libpddir = $(prefix)
pddocdir = $(libpddir)/doc
libpdbindir = $(libpddir)/bin

EXECDIR=../bin
PDEXEC = $(EXECDIR)/pd.exe
PDDLL = $(EXECDIR)/pd.dll
PDCOM = $(EXECDIR)/pd.com
PDRECEIVE = $(EXECDIR)/pdreceive.exe
PDSEND = $(EXECDIR)/pdsend.exe

DLLWRAP= dllwrap

MORECFLAGS = -O3 -funroll-loops -fomit-frame-pointer

PADIR = $(pd_src)/portaudio/portaudio

asiodir := $(firstword $(wildcard $(pd_src)/lib/ASIOSDK $(pd_src)/asio/ASIOSDK))
ASIODIR ?= $(asiodir)
ASIOINC = -I$(ASIODIR)/common -I$(ASIODIR)/host -I$(ASIODIR)/host/pc
INCPA = -I$(PADIR)/include -I$(PADIR)/src/common -I$(PADIR)/src/os/win \
      $(ASIOINC)
INCLUDE = -I$(pd_src)/src 
GINCLUDE = -I/usr/local/include $(INCLUDE)

LDFLAGS = 
LIBS = -lm -lws2_32 -lwinmm -lole32 -lpthread \
    -static-libgcc -static-libstdc++

OPT_CFLAGS = 

WARN_CFLAGS = -Wall -W -Wstrict-prototypes -Wno-unused \
    -Wno-unused-parameter -Wno-parentheses -Wno-switch
# Some old code in asio/ASIOSDK/common/combase.h needs to be ignored,
# we do this by setting the WINVER macro to min Windows XP aka 5.1.
# Also, for SetDllDirectory() s_loader.c, we need a minimum of Windows
# XP SP1.  WINVER isn't fine-grained enough for that, so we use the
# next minor version of Windows, 5.2.
ARCH_CFLAGS = -DPD -DPD_INTERNAL -DPA_USE_ASIO -DPA_USE_WMME -DWINVER=0x0502 \
     -DUSEAPI_MMIO -DUSEAPI_PORTAUDIO -mms-bitfields -DWISH='"wish85.exe"'

CFLAGS += $(ARCH_CFLAGS) $(WARN_CFLAGS) $(OPT_CFLAGS) $(MORECFLAGS)

STRIP = strip --strip-unneeded -R .note -R .comment

# the sources

PASRC = s_audio_pa.c s_audio_paring.c \
    s_audio_mmio.c \
    $(PADIR)/src/common/pa_stream.c \
    $(PADIR)/src/common/pa_trace.c \
    $(PADIR)/src/common/pa_process.c \
    $(PADIR)/src/common/pa_front.c \
    $(PADIR)/src/common/pa_dither.c \
    $(PADIR)/src/common/pa_cpuload.c \
    $(PADIR)/src/common/pa_converters.c \
    $(PADIR)/src/common/pa_allocation.c \
    $(PADIR)/src/common/pa_ringbuffer.c \
    $(PADIR)/src/os/win/pa_win_coinitialize.c \
    $(PADIR)/src/os/win/pa_win_hostapis.c \
    $(PADIR)/src/os/win/pa_win_util.c \
    $(PADIR)/src/os/win/pa_win_waveformat.c \
    $(PADIR)/src/hostapi/wmme/pa_win_wmme.c

ASIOSRC = $(PADIR)/src/hostapi/asio/iasiothiscallresolver.cpp \
          $(PADIR)/src/hostapi/asio/pa_asio.cpp \
          $(ASIODIR)/common/asio.cpp \
          $(ASIODIR)/host/asiodrivers.cpp \
          $(ASIODIR)/host/pc/asiolist.cpp

#VSRC =  s_audio_vst.c

PMDIR = ../portmidi/portmidi
PMINCLUDE = -I$(PMDIR)/pm_common -I$(PMDIR)/pm_win -I$(PMDIR)/porttime \
    -DNEWBUFFER
PMSRC =  s_midi_pm.c \
    $(PMDIR)/pm_common/portmidi.c \
    $(PMDIR)/pm_common/pmutil.c \
    $(PMDIR)/porttime/porttime.c \
    $(PMDIR)/porttime/ptwinmm.c \
    $(PMDIR)/pm_win/pmwin.c \
    $(PMDIR)/pm_win/pmwinmm.c

PMOBJ =  $(PMSRC:.c=.o)

HEADERS = g_all_guis.h m_imp.h g_canvas.h g_undo.h m_pd.h s_stuff.h \
    $(wildcard ../portaudio/common/*.h) s_audio_paring.h

SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
    g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \
    g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
    g_toggle.c g_undo.c g_vdial.c g_vslider.c g_vumeter.c \
    g_editor_extras.c \
    m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
    m_conf.c m_glob.c m_sched.c \
    s_main.c s_inter.c s_file.c s_print.c \
    s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_net.c s_utf8.c \
    d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
    d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \
    d_delay.c d_resample.c d_soundfile.c \
    x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
    x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \
    x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c

SRSRC = u_pdsend.c u_pdreceive.c s_net.c

OBJ = $(SRC:.c=.o) 
SROBJ = $(SRSRC:.c=.o) 
PAOBJ = $(PASRC:.c=.o)
ASIOOBJ = $(ASIOSRC:.cpp=.o)
#VOBJ = $(VSRC:.c=.o)
OBJC = $(OBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ)


# get version from m_pd.h to use in doc/1.manual/1.introduction.txt
PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \
	sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' )
PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \
	sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' )
PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \
	sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' )
PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \
	sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' )
PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION)
ifneq ($(PD_TEST_VERSION),)
	PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION)
endif


#
#  ------------------ targets ------------------------------------
#

.PHONY: all install clean testbin

all: $(PDDLL) $(PDEXEC) $(PDSEND) $(PDRECEIVE) $(PDCOM)

$(OBJ) : %.o : %.c
	$(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c 

$(GOBJ) : %.o : %.c
	$(CC) $(CFLAGS) $(GFLAGS) $(GINCLUDE) -c -o $*.o $*.c 

$(SROBJ) : %.o : %.c
	$(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c 

$(PAOBJ) : %.o : %.c
	$(CC) $(CFLAGS) $(GFLAGS) $(INCPA) -c -o $*.o $*.c 

$(ASIOOBJ) : %.o : %.cpp
	$(CXX) $(CFLAGS) $(INCPA) -c -o $*.o $*.cpp

$(PMOBJ) : %.o : %.c
	$(CC) $(CFLAGS) $(GFLAGS) $(PMINCLUDE) -c -o $*.o $*.c 

$(VOBJ) : %.o : %.c
	$(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c 

$(PDSEND): $(EXECDIR) u_pdsend.o s_net.o
	$(CC) $(CFLAGS) $(LDFLAGS) -o $(PDSEND) u_pdsend.o s_net.o $(LIBS)
	$(STRIP) $(PDSEND)

$(PDRECEIVE): $(EXECDIR) u_pdreceive.o s_net.o
	$(CC) $(CFLAGS) $(LDFLAGS) -o $(PDRECEIVE) u_pdreceive.o s_net.o $(LIBS)
	$(STRIP) $(PDRECEIVE)

$(PDEXEC): $(EXECDIR) s_entry.o pd.res
	$(CXX) $(LDFLAGS) -mwindows -o $(PDEXEC) s_entry.o pd.res $(LIBS) pd.a
	$(STRIP) -s $(PDEXEC)

$(PDCOM): $(EXECDIR) s_entry.o
	$(CXX) $(LDFLAGS) -o $(PDCOM) s_entry.o $(LIBS) pd.a
	$(STRIP) -s $(PDCOM)

$(PDDLL): $(EXECDIR) $(OBJC)
	$(CXX) -shared $(LDFLAGS) -o $(PDDLL) $(OBJC) $(LIBS) \
		-Wl,--export-all-symbols -Wl,--out-implib=pd.a; 
	$(STRIP) $(PDDLL)

pd.res: pd.rc
	$(WINDRES) pd.rc -O coff -o pd.res

$(EXECDIR)/pdstatic.exe: $(OBJC) $(EXECDIR)
	$(CXX) -static \
            $(LDFLAGS) -o $@ $(OBJC) \
            $(LIBS) -lole32 -static-libgcc -static-libstdc++
	$(STRIP) -s $@

$(EXECDIR):
	$(MKDIR_P) $@

#vstschedlib.dll: $(VOBJ)
#	$(DLLWRAP) --export-all-symbols --output-def vst.def \
#	--output-lib=vst.a --dllname=vstschedlib.dll s_audio_vst.o pd.a $(LIBS)

externs: 
	make -C ../extra all

# kludge to put stuff into the pd/bin dir for testing
testbin: $(PDEXEC) $(PDDLL) $(PDCOM)
	echo "Copying files to $(BIN_DIR)"
	install -d $(BIN_DIR)
	install -p $(PDDLL) $(BIN_DIR)
	install -p ../tcl/pd.ico $(BIN_DIR)
	install -p $(PDCOM) $(BIN_DIR)
	install -p $(PDEXEC) $(BIN_DIR)

ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt
install:  all
# locales
#	make libpddir=$(libpddir) -C ../po install
# install extra stuff
#	make libpddir=$(libpddir) -C ../extra install
# the real install
	install -d $(DESTDIR)$(bindir)
	install -p ../tcl/*.tcl $(DESTDIR)$(bindir)/
	install -p $(PDEXEC) $(DESTDIR)$(bindir)/$(PDEXEC)
	install -p $(PDCOM) $(DESTDIR)$(bindir)/$(PDCOM)
	install -p $(PDDLL) $(DESTDIR)$(bindir)/pd.dll
	install -p ../tcl/pd.ico $(DESTDIR)$(bindir)/pd.ico
	install -p $(PDSEND) $(DESTDIR)$(bindir)/$(PDSEND)
	install -p $(PDRECEIVE) $(DESTDIR)$(bindir)/$(PDRECEIVE)
	for dir in $(shell ls -1 ../doc | grep -v CVS); do \
		echo "installing $$dir"; \
		install -d $(DESTDIR)$(pddocdir)/$$dir ; \
		install -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \
	done
	for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \
		echo "installing 7.stuff/$$dir"; \
		install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
		install -p ../doc/7.stuff/$$dir/*.* $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
	done
	mv $(ABOUT_FILE) $(ABOUT_FILE).tmp
	cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \
		> $(ABOUT_FILE)
	rm $(ABOUT_FILE).tmp
	install -d $(DESTDIR)$(libpddir)/extra
#	install -p $(pd_src)/extra/*/*.dll $(DESTDIR)$(libpddir)/extra
	install -p $(pd_src)/extra/*.pd $(DESTDIR)$(libpddir)/extra
	install -d $(DESTDIR)$(pddocdir)/5.reference
	install -p ../extra/*/*.pd $(DESTDIR)$(pddocdir)/5.reference
	install -p ../extra/*-help.pd $(DESTDIR)$(pddocdir)/5.reference
	install -d $(DESTDIR)$(includedir)
	install -p m_pd.h $(DESTDIR)$(includedir)/m_pd.h
	install -p s_stuff.h $(DESTDIR)$(includedir)/s_stuff.h
	@echo "Pd install succeeded."


clean:
	-rm -f -- $(BIN_DIR)/*.*
	-rm -f -- *.o *.a *.def
	-rm -f -- pd*.exe pd*.dll $(PDCOM)
	-rm -f -- $(OBJ) $(GOBJ) $(SROBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ)
	-rm -f -- $(pd_src)/extra/*/*.dll $(pd_src)/extra/*/*.o
	-rm -f makefile.dependencies

distclean: clean
	rm -rf -- config.cache config.log config.status makefile tags \
	     autom4te-*.cache

tags: $(SRC) $(GSRC); ctags *.[ch]

depend: makefile.dependencies

makefile.dependencies: $(SRC) $(PASRC) $(HEADERS)
	$(CC) $(INCLUDE) $(INCPA) $(CFLAGS) -M $(SRC) $(PASRC) $(HEADERS) \
		> makefile.dependencies

uninstall:
	-rm $(prefix)/bin/pd*.exe
	-rm $(prefix)/bin/pd*.com
	-rm $(prefix)/bin/pd*.dll
	-rm $(prefix)/bin/*.tcl


test_locations:
	@echo "PD_VERSION: $(PD_VERSION)"
	@echo "PACKAGE_VERSION: $(PACKAGE_VERSION)"
	@echo "CWD $(CWD)"
	@echo "DESTDIR $(DESTDIR)"
	@echo "PREFIX $(prefix)"
	@echo "BINDIR  $(bindir)"
	@echo "LIBDIR  $(libdir)"
	@echo "OBJECTSDIR  $(objectsdir)"
	@echo "PDDOCDIR  $(pddocdir)"
	@echo "LIBPDDIR  $(libpddir)"
	@echo "LIBPDBINDIR  $(libpdbindir)"
	@echo "HELPDIR  $(helpdir)"
	@echo "MANUALSDIR  $(manualsdir)"
	@echo "EXAMPLESDIR  $(examplesdir)"


include makefile.dependencies
