#####################==================----------------
#
# Top-Level Makefile for Building Python for OS/2 using GCC/EMX
# Written by Andrew Zabolotny, <bit@eltech.ru>
#
# This makefile was developed for use with [P]GCC/EMX compiler any
# version and GNU Make.
#
# The output of the build is a largish Python15.DLL containing the
# essential modules of Python and a small Python.exe program to start
# the interpreter. When embedding Python within another program, only
# Python15.DLL is needed. We also build python_s.a static library (which
# can be converted into OMF (.lib) format using emxomf tool) and an
# python.a import library.
#
# Recommended build order:
#   make depend		(if you have makedep)
#   make all
#   make lx		(if you have lxlite)
#   make test		(optional)
#
#####################==================----------------

# Compilation mode: debug or release
MODE = optimize

# Do you have the InfoZip compression library installed?
ZLIB = yes
# Do you have the Ultra Fast Crypt (UFC) library installed?
UFC = yes
# Do you have the Tcl/Tk library installed?
TCLTK = no
# Do you have the GNU multiprecision library installed?
GMPZ = no
# Do you have the GNU readline library installed?
# NOTE: I'm using my own port of GNU readline library
# that is a part of my port of GNU Bash to OS/2. If you're using
# Kai Uwe Rommel's port (gnureadl.zip) you will have to add several
# functions to his .def file since not all functions that Python
# module requires are exported.
GREADLINE = yes

# The Tools
CC = gcc
CFLAGS = -Zmt -Wall $(INCLUDE)
LD = gcc
LDFLAGS = -Zmt -Zcrtdll -L. -lgcc
LDFLAGS.EXE = $(LDFLAGS)
LDFLAGS.DLL = $(LDFLAGS) -Zdll $(LIBS)
ARFLAGS = crs
IMPLIB = emximp

ifeq ($(MODE),debug)
  CFLAGS += -g
  LDFLAGS += -g
else
  CFLAGS += -s -O6 -fomit-frame-pointer -funroll-loops
  LDFLAGS += -s
endif

# We're using the OMF format since EMX's ld has a obscure bug
# because of which it sometimes fails to build relocations
# in .data segment that point to another .data locations
OMF = yes

# File extensions
ifeq ($(OMF),yes)
  O = .obj
  A = .lib
  AR = emxomfar
  CFLAGS += -Zomf
  LDFLAGS += -Zomf
  ifeq ($(MODE),debug)
    ARFLAGS = -p32 crs
  endif
else
  O = .o
  A = .a
  AR = ar
endif

# Source file paths
SRCPATH = .;../../Python;../../Parser;../../Objects;../../Include;../../Modules
# Python contains the central core, containing the builtins and interpreter.
# Parser contains Python's Internal Parser and
# Standalone Parser Generator Program (Shares Some of Python's Modules)
# Objects contains Python Object Types
# Modules contains extension Modules (Built-In or as Separate DLLs)

# Unix shells tend to use "$" as delimiter for variable names.
# Test for this behaviour and set $(BUCK) variable correspondigly ...
__TMP__:=$(shell echo $$$$)
ifeq ($(__TMP__),$$$$)
  BUCK = $$
  BRO = (
  BRC = )
else
  BUCK = \$$
  BRO = \(
  BRC = \)
endif
# Compute the "double quote" variable
__TMP__:=$(shell echo "")
ifeq ($(__TMP__),"")
  DQUOTE = "
else
  DQUOTE = \"
endif

# Include paths
INCLUDE = -I$(subst ;, -I, $(SRCPATH))

# Path to search for .c files
vpath %.c .;..;$(SRCPATH)

# Directory for output files
OUTBASE = out/
OUT = $(OUTBASE)$(MODE)/

# Additional libraries
LIBS = -lsocket

# Build rules
$(OUT)%$O: %.c
	$(CC) $(CFLAGS) -c $< -o $@

%.dll:
	$(LD) $(LDFLAGS.DLL) -o $@ $(^^) $(L^)

%.exe:
	$(LD) $(LDFLAGS.EXE) -o $@ $(^^) $(L^)

%_m.def:
	@echo Creating .DEF file: $@
	@echo LIBRARY $(notdir $*) INITINSTANCE TERMINSTANCE >$@
	@echo DESCRIPTION $(DQUOTE)$(DESCRIPTION.$(notdir $*).dll)$(DQUOTE) >>$@
	@echo EXPORTS >>$@
	@echo 	init$(notdir $*) >>$@

%.def:
	@echo Creating .DEF file: $@
	@echo NAME $(notdir $*) $(EXETYPE.$(notdir $*).exe) >$@
	@echo DESCRIPTION $(DQUOTE)$(DESCRIPTION.$(notdir $*).exe)$(DQUOTE) >>$@
	@echo STACKSIZE 1048576 >>$@

# Output file names
PYTHON.LIB = python_s$A
PYTHON.IMPLIB = python$A
PYTHON.DLL = python15.dll
PYTHON.EXE = python.exe
PYTHONPM.EXE = pythonpm.exe
PGEN.EXE = pgen.exe

# Additional executable parameters
EXETYPE.$(PYTHON.EXE) = WINDOWCOMPAT
EXETYPE.$(PYTHONPM.EXE) = WINDOWAPI
EXETYPE.$(PGEN.EXE) = WINDOWCOMPAT
DESCRIPTION.$(PYTHON.EXE) = Python object-oriented programming language interpreter for OS/2
DESCRIPTION.$(PYTHONPM.EXE) = $(DESCRIPTION.$(PYTHON.EXE))
DESCRIPTION.$(PGEN.EXE) = Python object-oriented programming language parser generator for OS/2

# Module descriptions
DESCRIPTION.zlib.dll = Python Extension DLL for accessing the InfoZip compression library
DESCRIPTION.crypt.dll = Python Extension DLL implementing the crypt$(BRO)$(BRC) function
DESCRIPTION._tkinter.dll = Python Extension DLL for access to Tcl/Tk Environment
DESCRIPTION.mpz.dll = Python Extension DLL for access to GNU multi-precision library
DESCRIPTION.readline.dll = Python Extension DLL for access to GNU ReadLine library

# Utility macro: replacement for $^
^^ = $(filter-out %$A,$^)
# Use $(L^) to link with all libraries specified as dependencies
L^=$(addprefix -l,$(basename $(notdir $(filter %$A,$+))))

# Source files
SRC.PGEN = $(addprefix ../../Parser/,pgenmain.c pgen.c printgrammar.c \
  listnode.c grammar.c bitset.c firstsets.c metagrammar.c)
OBJ.PGEN = $(addprefix $(OUT),$(notdir $(SRC.PGEN:.c=$O)))

SRC.NOTLIB = sigcheck.c intrcheck.c dup2.c fmod.c atof.c hypot.c \
  memmove.c strdup.c strerror.c strtod.c
SRC.LIB = $(filter-out $(addprefix %,$(SRC.NOTLIB)) $(SRC.PGEN) \
  ../../Modules/%, $(wildcard $(subst ;,/*.c ,$(SRCPATH))/*.c)) \
  $(addsuffix .c,$(addprefix ../../Modules/,$(BUILTINMODULES))) \
  dlfcn.c config.c ../getpathp.c
OBJ.LIB = $(addprefix $(OUT),$(notdir $(SRC.LIB:.c=$O)))

# Python built-in modules to build (the first line are support modules)
BUILTINMODULES = main getbuildinfo cgensupport pypcre regexpr yuvconvert md5c \
  _localemodule arraymodule binascii cPickle cStringIO cmathmodule dlmodule \
  errnomodule fpectlmodule fpetestmodule imageop mathmodule md5module \
  newmodule operator parsermodule pcremodule posixmodule pwdmodule \
  regexmodule rgbimgmodule rotormodule selectmodule shamodule signalmodule \
  socketmodule soundex stropmodule structmodule termios threadmodule \
  timemodule timingmodule

# Python external (.dll) modules
ifeq ($(ZLIB),yes)
  EXTERNMODULES += zlibmodule
  LIBS += -lz
endif
ifeq ($(UFC),yes)
  EXTERNMODULES += cryptmodule
  LIBS += -lufc
endif
ifeq ($(TCLTK),yes)
  EXTERNMODULES += _tkinter
  LIBS += -ltcl -ltk
endif
ifeq ($(GMPZ),yes)
  EXTERNMODULES += mpzmodule
  LIBS += ????
endif
ifeq ($(GREADLINE),yes)
  EXTERNMODULES += readline
  LIBS += -lreadline -ltermcap
endif

EXTERNDLLS = $(addsuffix .dll,$(patsubst %module,%,$(EXTERNMODULES)))

# The following modules won't build either because I didn't had installed
# required libraries (such as Tcl/Tk or GDBM)
# or because they were designed for a different OS.
BADMODULES = \
  gdbmmodule getpath glmodule almodule audioop bsddbmodule cdmodule clmodule \
  cursesmodule dbmmodule fcntlmodule flmodule fmmodule grpmodule imgfile \
  nismodule resource puremodule sgimodule stdwinmodule sunaudiodev svmodule \
  syslogmodule

# The following modules are still possible to build but you will require either
# a specific library or some OS/2-specific changes (such as to OpenGL module)
# gdbmmodule (GNU database manager, should be either available or easily portable)
# glmodule (OS/2 - specific changes for OS/2 OpenGL)

# Targets
all:  $(OUT) $(PYTHON.LIB) $(PYTHON.IMPLIB) $(PYTHON.DLL) \
  $(PYTHON.EXE) $(PYTHONPM.EXE) $(PGEN.EXE) $(EXTERNDLLS)

clean:
	rm -rf $(OUT)

lx:
	@echo Packing everything with lxLite...
	lxlite $(PYTHON.DLL) $(PYTHON.EXE) $(PYTHONPM.EXE) $(PGEN.EXE)

depend: $(OUTBASE)
	makedep -f $(OUTBASE)python.dep -o $(BUCK)O -p $(BUCK)\(OUT\) \
	  -r -c $(INCLUDE) $(SRC.LIB) $(SRC.PGEN)

$(OUT): $(OUTBASE)

$(OUT) $(OUTBASE):
	mkdir $@

$(PYTHON.LIB): $(OBJ.LIB)
	rm -f $@
	$(AR) $(ARFLAGS) $@ $^

$(PYTHON.IMPLIB): ../os2vacpp/Python.def
	$(IMPLIB) -o $@ $^

$(PYTHON.DLL): $(OUT)dllentry$O $(PYTHON.LIB) ../os2vacpp/Python.def

$(PYTHON.EXE): $(OUT)python$O $(PYTHON.IMPLIB) $(OUT)python.def

$(PYTHONPM.EXE): $(OUT)python$O $(PYTHON.IMPLIB) $(OUT)pythonpm.def

$(PGEN.EXE): $(OBJ.PGEN) $(PYTHON.LIB) $(OUT)pgen.def

# External modules
zlib.dll: $(OUT)zlibmodule$O $(OUT)zlib_m.def $(PYTHON.IMPLIB)
crypt.dll: $(OUT)cryptmodule$O $(OUT)crypt_m.def $(PYTHON.IMPLIB)
_tkinter.dll: $(OUT)_tkinter$O $(OUT)tclNotify$O $(OUT)tkappinit$O \
  $(OUT)_tkinter_m.def $(PYTHON.IMPLIB)
mpz.dll: $(OUT)mpzmodule$O $(OUT)mpz_m.def $(PYTHON.IMPLIB)
readline.dll: $(OUT)readline$O $(OUT)readline_m.def $(PYTHON.IMPLIB)

test:
	./python ../../lib/test/regrtest.py

-include $(OUTBASE)python.dep
