Borland Delphi.net 2005 & Makefiles

EDIT: see also DCCIL Batch file generator from Felix John Colibri.

You will need the dccil.exe from Borland Delphi 2005 in your path,
e.g.:       set path="c:\program files\borland\bds\3.0\bin";%PATH%

Using Borland Make

If you want to have a go at Borlands make program, read this article: http://bdn.borland.com/article/0,1410,19281,00.html

Here is a simple example that builds an .net exe file from several units.
It can be called like this:
  make -ftestxml.mak
to generate the main file (testxml.exe);
  make -ftestxml.mak clean
would delete all object files and the exe, to force a rebuild of everything.

# testxml.mak
# ---------------------------------------------------------------------------
PROJECT = testxml.exe
OBJFILES = common\ULog.dcuil \
    common\xml\xmlParser.dcuil \
    reports\reportStore.dcuil \
    reports\reportParser.dcuil \
    reports\reportConsts.dcuil
MAINSOURCE = testxml.dpr
INCLUDEPATH=common\xml;common
# ---------------------------------------------------------------------------

.autodepend

# ---------------------------------------------------------------------------
!if !$d(BDSNET)
BDSNET = dccil
!endif

!if !$d(DELETE)
DELETE = del
#DELETE = rm
!endif

# ---------------------------------------------------------------------------
$(PROJECT): $(OBJFILES) $(MAINSOURCE)
    $(BDSNET) -U$(INCLUDEPATH) -X$(PROJECT) $(MAINSOURCE)

.pas.dcuil:
    $(BDSNET) -U$(INCLUDEPATH) {$< }
   
clean:
    $(DELETE) $(PROJECT)
    $(DELETE) $(OBJFILES)
# ---------------------------------------------------------------------------

Using GNU make

I prefer the GNU make over the Borland, you can download the Windows version here: http://www.steve.org.uk/Software/make/ or http://unxutils.sourceforge.net/.
You need to set the path to your make.exe:
e.g.:       set path="U:\delphi.net\experimenting\build";%PATH%
Where is the rules.make file?
set RULESDIR=u:\delphi.net\experimenting\build

This is a more complex example, and allows recursion. 2 DLLs are created, where one of them depends on the others.

rules.make:
# ---------------------------------------------------------------------------
ifndef BDSNET
BDSNET = dccil
endif

ifndef DELETE
DELETE = del
#DELETE = rm
endif

ifndef COPY
COPY = copy
#COPY = cp
endif

ifndef OUTPUTDIR
OUTPUTDIR=debug
endif

OBJCODE=objcode
JUNK=*.pdb *.rsp *.~* *.local *.cfg *.identcache
OBJFILES=*.dcpil *.dcuil *.resources $(OBJCODE)\*.dcpil $(OBJCODE)\*.dcuil

# ---------------------------------------------------------------------------
.DEFAULT: all

all: all-recursive all-local

all-local: $(PROJECT)

$(PROJECT): $(PASFILES) $(MAINSOURCE) $(RESFILES)
    $(BDSNET) -LU$(LINKEDASSEMBLIES) -U$(INCLUDEPATH) -X$(PROJECT) -N$(OBJCODE) $(MAINSOURCE)
    $(COPY) $(PROJECT).config $(OUTPUTDIR)
    $(COPY) $(PROJECT) $(OUTPUTDIR)

%.TWinForm.resources: %.resx
    resgen -R $< $@

realclean: realclean-recursive realclean-local
   
realclean-local: clean-local
    $(DELETE) $(JUNK)

clean: clean-recursive clean-local

clean-local:
    $(DELETE) $(PROJECT)
    $(DELETE) $(OBJFILES)
   
mkdir: mkdir-recursive mkdir-local

mkdir-local:
    mkdir objcode
    mkdir debug
    mkdir release
   
# ---------------------------------------------------------------------------

PetraClassLib/makefile: (does not depend on other projects)
# ---------------------------------------------------------------------------
PROJECT = Ict.Petra.PartnerM_Interface.dll
PASFILES = IPartner.pas
MAINSOURCE = Ict.Petra.PartnerM_Interface.dpk
LINKEDASSEMBLIES =
INCLUDEPATH =
# ---------------------------------------------------------------------------

include $(RULESDIR)\rules.make

%-recursive:;

ClientLib/makefile: (calls recursively the PetraClassLib/makefile)
# ---------------------------------------------------------------------------
PROJECT = Ict.Petra.PartnerM.dll
PASFILES = ClientLibMain.pas PartnerM.Partner.pas
MAINSOURCE = Ict.Petra.PartnerM.dpk
LINKEDASSEMBLIES = Ict.Petra.PartnerM_Interface
INCLUDEPATH = ../PetraClassLib

# ---------------------------------------------------------------------------

include $(RULESDIR)\rules.make

%-recursive:
    $(MAKE) $* -C ../PetraClassLib
Hint: the "%-recursive" matches e.g. "clean-recursive", and the value of "$*" is then "clean".

GUIClient/makefile: (example with winforms)
# ---------------------------------------------------------------------------
PROJECT = PetraNTier_Test1_GUIClient.exe
PASFILES = GUICLient.pas Connector.pas
RESFILES = GUIClient.TWinForm.resources
MAINSOURCE = PetraNTier_Test1_GUIClient.dpr
LINKEDASSEMBLIES = Ict.Petra.PartnerM;Ict.Petra.PartnerM_Interface;PetraNTier_Test1_Interface;System.Data;System;System.Drawing;System.Windows.Forms;System.Xml;
INCLUDEPATH = ../GUIClient;../ClientLib;../PetraClassLib;../Interface;../Logging;../ServerAdminCMD
# ---------------------------------------------------------------------------

include $(RULESDIR)\rules.make

GUIClient.TWinForm.resources: GUIClient.resx
    resgen -R $< $@
# same meaning as: resgen -R GUIClient.resx GUIClient.TWinForm.resources

%-recursive:
    $(MAKE) $* -C ../Interface
    $(MAKE) $* -C ../Logging

Delphi project files that can be removed and don't need to go in CVS:
*.dcpil *.dcuil *.pdb *.rsp *.~* *.local *.cfg *.identcache *.resources
*.dll *.exe

Available commands:

set OUTPUTDIR=U:\delphi.net\experimenting\N-Tier\PetraNTier_Test1\GUICLient\Release
cd delphi.net\experimenting\N-Tier\PetraNTier_Test1\GUICLient\
make realclean
make mkdir
make

same for ServerAdminCMD and Server