Browse Source

+ Initial check-in

git-svn-id: trunk@5036 -
michael 19 years ago
parent
commit
3ba85ce96d

+ 12 - 0
.gitattributes

@@ -7734,6 +7734,18 @@ utils/fpmc/frmoptions.pp svneol=native#text/plain
 utils/fpmc/msgcomp.pp svneol=native#text/plain
 utils/fpmc/readmsg.pp svneol=native#text/plain
 utils/fpmc/test.mc -text
+utils/fppkg/Makefile svneol=native#text/plain
+utils/fppkg/Makefile.fpc svneol=native#text/plain
+utils/fppkg/README svneol=native#text/plain
+utils/fppkg/fpmkcnst.inc svneol=native#text/plain
+utils/fppkg/fpmktype.pp svneol=native#text/plain
+utils/fppkg/fpmkunit.pp svneol=native#text/plain
+utils/fppkg/fprepos.pp svneol=native#text/plain
+utils/fppkg/fpxmlrep.pp svneol=native#text/plain
+utils/fppkg/pkgropts.pp svneol=native#text/plain
+utils/fppkg/rep2xml.lpi svneol=native#text/plain
+utils/fppkg/rep2xml.lpr svneol=native#text/plain
+utils/fppkg/reptest.pp svneol=native#text/plain
 utils/fprcp/Makefile svneol=native#text/plain
 utils/fprcp/Makefile.fpc svneol=native#text/plain
 utils/fprcp/Readme.txt svneol=native#text/plain

+ 2010 - 0
utils/fppkg/Makefile

@@ -0,0 +1,2010 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2006/08/20]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd x86_64-win64 arm-linux arm-palmos arm-wince arm-gba powerpc64-linux
+BSDs = freebsd netbsd openbsd darwin
+UNIXs = linux $(BSDs) solaris qnx
+LIMIT83fs = go32v2 os2 emx watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=../..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPC:=$(shell $(FPCPROG) -PB)
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifneq ($(words $(FPC_COMPILERINFO)),5)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSO)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTO)
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+export OS_TARGET OS_SOURCE CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_UNITS+=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_RSTS+=fprepos fpxmlrep
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_EXAMPLES+=rep2xml
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_EXAMPLES+=rep2xml
+endif
+override INSTALL_FPCPACKAGE=y
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifndef INSTALL_SHAREDDIR
+INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+SHAREDLIBPREFIX=libfp
+STATICLIBPREFIX=libp
+IMPORTLIBPREFIX=libimp
+RSTEXT=.rst
+ifeq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+endif
+ifeq ($(OS_TARGET),darwin)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+endif
+ifeq ($(OS_TARGET),gba)
+EXEEXT=.gba
+SHAREDLIBEXT=.so
+SHORTSUFFIX=gba
+endif
+else
+ifeq ($(OS_TARGET),go32v1)
+PPUEXT=.pp1
+OEXT=.o1
+ASMEXT=.s1
+SMARTEXT=.sl1
+STATICLIBEXT=.a1
+SHAREDLIBEXT=.so1
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+SHORTSUFFIX=wat
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+PPUEXT=.ppw
+OEXT=.ow
+ASMEXT=.sw
+SMARTEXT=.slw
+STATICLIBEXT=.aw
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+PPUEXT=.ppo
+ASMEXT=.so2
+OEXT=.oo2
+AOUTEXT=.out
+SMARTEXT=.sl2
+STATICLIBPREFIX=
+STATICLIBEXT=.ao2
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),atari)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nw
+endif
+ifeq ($(OS_TARGET),netwlibc)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nwl
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+endif
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),win32)
+ifeq ($(CROSSBINDIR),)
+ASNAME=asw
+LDNAME=ldw
+ARNAME=arw
+endif
+endif
+endif
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+PPAS=ppas$(SRCBATCHEXT)
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ifndef UPXPROG
+ifeq ($(OS_TARGET),go32v2)
+UPXPROG:=1
+endif
+ifeq ($(OS_TARGET),win32)
+UPXPROG:=1
+endif
+ifdef UPXPROG
+UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(UPXPROG),)
+UPXPROG=
+else
+UPXPROG:=$(firstword $(UPXPROG))
+endif
+else
+UPXPROG=
+endif
+endif
+export UPXPROG
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl 
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(CPU_TARGET)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifneq ($(CPU_TARGET),$(CPU_SOURCE))
+override FPCOPT+=-P$(CPU_TARGET)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX) -Xc
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifneq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+endif
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+endif
+else
+FPCCPUOPT:=-O1r
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+override FPCOPT+=-O2
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifdef CREATESHARED
+override FPCOPT+=-Cg
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-Aas
+endif
+endif
+ifdef LINKSHARED
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(AFULL_TARGET),$(AFULL_SOURCE))
+override ACROSSCOMPILE=1
+endif
+ifdef ACROSSCOMPILE
+override FPCOPT+=$(CROSSOPT)
+endif
+override COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+EXECPPAS:=@$(PPAS)
+endif
+endif
+.PHONY: fpc_units
+ifneq ($(TARGET_UNITS),)
+override ALLTARGET+=fpc_units
+override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS))
+override IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICITUNITS))
+override INSTALLPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+override CLEANPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+endif
+fpc_units: $(COMPILER_UNITTARGETDIR) $(UNITPPUFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_examples
+ifneq ($(TARGET_EXAMPLES),)
+HASEXAMPLES=1
+override EXAMPLESOURCEFILES:=$(wildcard $(addsuffix .pp,$(TARGET_EXAMPLES)) $(addsuffix .pas,$(TARGET_EXAMPLES)) $(addsuffix .lpr,$(TARGET_EXAMPLES)) $(addsuffix .dpr,$(TARGET_EXAMPLES)))
+override EXAMPLEFILES:=$(addsuffix $(EXEEXT),$(TARGET_EXAMPLES))
+override EXAMPLEOFILES:=$(addsuffix $(OEXT),$(TARGET_EXAMPLES)) $(addprefix $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_EXAMPLES))) $(addprefix $(IMPORTLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_EXAMPLES)))
+override CLEANEXEFILES+=$(EXAMPLEFILES) $(EXAMPLEOFILES)
+ifeq ($(OS_TARGET),os2)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_EXAMPLES))
+endif
+ifeq ($(OS_TARGET),emx)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_EXAMPLES))
+endif
+endif
+ifneq ($(TARGET_EXAMPLEDIRS),)
+HASEXAMPLES=1
+endif
+fpc_examples: all $(EXAMPLEFILES) $(addsuffix _all,$(TARGET_EXAMPLEDIRS))
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared
+$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)
+	@$(ECHOREDIR) Compiled > $(FPCMADE)
+fpc_all: $(FPCMADE)
+fpc_smart:
+	$(MAKE) all LINKSMART=1 CREATESMART=1
+fpc_debug:
+	$(MAKE) all DEBUG=1
+fpc_release:
+	$(MAKE) all RELEASE=1
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res
+$(COMPILER_UNITTARGETDIR):
+	$(MKDIRTREE) $(COMPILER_UNITTARGETDIR)
+$(COMPILER_TARGETDIR):
+	$(MKDIRTREE) $(COMPILER_TARGETDIR)
+%$(PPUEXT): %.pp
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(PPUEXT): %.pas
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.pp
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.pas
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.lpr
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.dpr
+	$(COMPILER) $<
+	$(EXECPPAS)
+%.res: %.rc
+	windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.PHONY: fpc_shared
+override INSTALLTARGET+=fpc_shared_install
+ifndef SHARED_LIBVERSION
+SHARED_LIBVERSION=$(FPC_VERSION)
+endif
+ifndef SHARED_LIBNAME
+SHARED_LIBNAME=$(PACKAGE_NAME)
+endif
+ifndef SHARED_FULLNAME
+SHARED_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERSION)$(SHAREDLIBEXT)
+endif
+ifndef SHARED_LIBUNITS
+SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS)
+override SHARED_LIBUNITS:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED_LIBUNITS))
+endif
+fpc_shared:
+ifdef HASSHAREDLIB
+	$(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1
+ifneq ($(SHARED_BUILD),n)
+	$(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGETDIR) -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR)
+endif
+else
+	@$(ECHO) Shared Libraries not supported
+endif
+fpc_shared_install:
+ifneq ($(SHARED_BUILD),n)
+ifneq ($(SHARED_LIBUNITS),)
+ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME)),)
+	$(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INSTALL_SHAREDDIR)
+endif
+endif
+endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+	$(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+	-$(UPXPROG) $(INSTALLEXEFILES)
+endif
+	$(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+	$(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+	$(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+	$(MKDIR) $(INSTALL_LIBDIR)
+	$(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+	ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+	$(MKDIR) $(INSTALL_DATADIR)
+	$(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+	$(MKDIR) $(INSTALL_SOURCEDIR)
+	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+	$(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+	$(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+	-$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+	-$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+	-$(DELTREE) units
+	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+	-$(DEL) *.o *.ppu *.a
+endif
+	-$(DELTREE) *$(SMARTEXT)
+	-$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+	-$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+	-$(DEL) *$(DEBUGSYMEXT)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+	@$(ECHO)
+	@$(ECHO)  == Package info ==
+	@$(ECHO)  Package Name..... $(PACKAGE_NAME)
+	@$(ECHO)  Package Version.. $(PACKAGE_VERSION)
+	@$(ECHO)
+	@$(ECHO)  == Configuration info ==
+	@$(ECHO)
+	@$(ECHO)  FPC.......... $(FPC)
+	@$(ECHO)  FPC Version.. $(FPC_VERSION)
+	@$(ECHO)  Source CPU... $(CPU_SOURCE)
+	@$(ECHO)  Target CPU... $(CPU_TARGET)
+	@$(ECHO)  Source OS.... $(OS_SOURCE)
+	@$(ECHO)  Target OS.... $(OS_TARGET)
+	@$(ECHO)  Full Source.. $(FULL_SOURCE)
+	@$(ECHO)  Full Target.. $(FULL_TARGET)
+	@$(ECHO)  SourceSuffix. $(SOURCESUFFIX)
+	@$(ECHO)  TargetSuffix. $(TARGETSUFFIX)
+	@$(ECHO)
+	@$(ECHO)  == Directory info ==
+	@$(ECHO)
+	@$(ECHO)  Required pkgs... $(REQUIRE_PACKAGES)
+	@$(ECHO)
+	@$(ECHO)  Basedir......... $(BASEDIR)
+	@$(ECHO)  FPCDir.......... $(FPCDIR)
+	@$(ECHO)  CrossBinDir..... $(CROSSBINDIR)
+	@$(ECHO)  UnitsDir........ $(UNITSDIR)
+	@$(ECHO)  PackagesDir..... $(PACKAGESDIR)
+	@$(ECHO)
+	@$(ECHO)  GCC library..... $(GCCLIBDIR)
+	@$(ECHO)  Other library... $(OTHERLIBDIR)
+	@$(ECHO)
+	@$(ECHO)  == Tools info ==
+	@$(ECHO)
+	@$(ECHO)  As........ $(AS)
+	@$(ECHO)  Ld........ $(LD)
+	@$(ECHO)  Ar........ $(AR)
+	@$(ECHO)  Rc........ $(RC)
+	@$(ECHO)
+	@$(ECHO)  Mv........ $(MVPROG)
+	@$(ECHO)  Cp........ $(CPPROG)
+	@$(ECHO)  Rm........ $(RMPROG)
+	@$(ECHO)  GInstall.. $(GINSTALL)
+	@$(ECHO)  Echo...... $(ECHO)
+	@$(ECHO)  Shell..... $(SHELL)
+	@$(ECHO)  Date...... $(DATE)
+	@$(ECHO)  FPCMake... $(FPCMAKE)
+	@$(ECHO)  PPUMove... $(PPUMOVE)
+	@$(ECHO)  Upx....... $(UPXPROG)
+	@$(ECHO)  Zip....... $(ZIPPROG)
+	@$(ECHO)
+	@$(ECHO)  == Object info ==
+	@$(ECHO)
+	@$(ECHO)  Target Loaders........ $(TARGET_LOADERS)
+	@$(ECHO)  Target Units.......... $(TARGET_UNITS)
+	@$(ECHO)  Target Implicit Units. $(TARGET_IMPLICITUNITS)
+	@$(ECHO)  Target Programs....... $(TARGET_PROGRAMS)
+	@$(ECHO)  Target Dirs........... $(TARGET_DIRS)
+	@$(ECHO)  Target Examples....... $(TARGET_EXAMPLES)
+	@$(ECHO)  Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+	@$(ECHO)
+	@$(ECHO)  Clean Units......... $(CLEAN_UNITS)
+	@$(ECHO)  Clean Files......... $(CLEAN_FILES)
+	@$(ECHO)
+	@$(ECHO)  Install Units....... $(INSTALL_UNITS)
+	@$(ECHO)  Install Files....... $(INSTALL_FILES)
+	@$(ECHO)
+	@$(ECHO)  == Install info ==
+	@$(ECHO)
+	@$(ECHO)  DateStr.............. $(DATESTR)
+	@$(ECHO)  ZipName.............. $(ZIPNAME)
+	@$(ECHO)  ZipPrefix............ $(ZIPPREFIX)
+	@$(ECHO)  ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+	@$(ECHO)  ZipSuffix............ $(ZIPSUFFIX)
+	@$(ECHO)  FullZipName.......... $(FULLZIPNAME)
+	@$(ECHO)  Install FPC Package.. $(INSTALL_FPCPACKAGE)
+	@$(ECHO)
+	@$(ECHO)  Install base dir..... $(INSTALL_BASEDIR)
+	@$(ECHO)  Install binary dir... $(INSTALL_BINDIR)
+	@$(ECHO)  Install library dir.. $(INSTALL_LIBDIR)
+	@$(ECHO)  Install units dir.... $(INSTALL_UNITDIR)
+	@$(ECHO)  Install source dir... $(INSTALL_SOURCEDIR)
+	@$(ECHO)  Install doc dir...... $(INSTALL_DOCDIR)
+	@$(ECHO)  Install example dir.. $(INSTALL_EXAMPLEDIR)
+	@$(ECHO)  Install data dir..... $(INSTALL_DATADIR)
+	@$(ECHO)
+	@$(ECHO)  Dist destination dir. $(DIST_DESTDIR)
+	@$(ECHO)  Dist zip name........ $(DIST_ZIPNAME)
+	@$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+	fpc_makefile_dirs
+fpc_makefile:
+	$(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+all: fpc_all
+debug: fpc_debug
+smart: fpc_smart
+release: fpc_release
+units: fpc_units
+examples: fpc_examples
+shared: fpc_shared
+install: fpc_install
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+distinstall:
+zipinstall:
+zipsourceinstall:
+zipexampleinstall:
+zipdistinstall:
+clean: fpc_clean
+distclean: fpc_distclean
+cleanall: fpc_cleanall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+fpmkunit$(PPUEXT) : fpmkunit.pp fpmkcnst.inc fpmktype$(PPUEXT)
+fpmktype$(PPUEXT) : fpmktype.pp fpmkcnst.inc

+ 22 - 0
utils/fppkg/Makefile.fpc

@@ -0,0 +1,22 @@
+#
+#   Makefile.fpc for fppkg
+#
+
+[target]
+units=fpmktype fpmkunit fprepos fpxmlrep pkgropts
+examples=rep2xml
+rsts=fprepos fpxmlrep
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../..
+
+#[require]
+#packages=fcl
+
+[rules]
+fpmkunit$(PPUEXT) : fpmkunit.pp fpmkcnst.inc fpmktype$(PPUEXT)
+
+fpmktype$(PPUEXT) : fpmktype.pp fpmkcnst.inc

+ 69 - 0
utils/fppkg/README

@@ -0,0 +1,69 @@
+This is the FPC packager.
+
+The architecture is as follows:
+
+A mirror list is maintained with FPC repositories.
+The packager will download the mirror list and store 
+it somewhere locally
+
+From a mirror, a repository is chosen (using it's name)
+
+From the repository the repository file is downloaded. 
+It contains all known packages. The fprepos.pp unit contains the
+functionality to read and maintain the package file. 
+
+The packager maintains a local repository file. when needed
+it will download a package and install it. It does so recursively.
+
+Each package contains a fpmake.pp driver. It contains all that
+is needed to compile, install and zip a package. It can also
+create a manifest file (in XML) to import in a repository.
+
+All packager functionality will be implemented in units so
+these units can be used in command-line and GUI package managers.
+
+Units:
+-----
+
+fprepos:
+  A unit that describes a repository. 
+  It is mainly a collection of packages.
+fpxmlrep
+  A unit to read/write a repository to XML. It can be used to read a
+  manifest file as produced by the fpmake driver.
+pkgropts
+  A unit to maintain settings for the packager it reads/writes
+  options from/to an ini file.
+fpmkunit
+  this is the unit that implements all the functionality a fpmake driver
+  needs.
+fpmktype
+  types and constants shared by fpmkunit and fprepos 
+rep2xml
+  test program for the fprepos unit.
+reptest
+  creates some test packages for use in the rep2xml test program.
+
+Options supported in packager config file:
+------------------------------------------
+
+LocalMirrors 
+  Local file with list of mirrors.
+RemoteMirrors
+  URL with location of remote mirrors file.
+RemoteRepository
+  Name of repository as found in LocalMirrors file.
+LocalRepository
+  Location of local repository file.
+InstallDir
+  Directory to install packages/units to
+BuildDir
+  Directory where to unpack and build packages
+Compiler
+  Compiler binary to be used
+OS
+  Default OS
+CPU 
+  Default CPU
+
+Defaults can be found in pkgropts

+ 46 - 0
utils/fppkg/fpmkcnst.inc

@@ -0,0 +1,46 @@
+Const
+  // Aliases
+  AmD64   = X86_64;
+  PowerPC = PPC;
+  dos = go32v2;
+
+  AllOSs  = [Low(TOS)..High(TOS)];
+  AllCPUs = [Low(TCPU)..High(TCPU)];
+  
+  // Useful
+  UnitExt = '.ppu';
+  PPUExt  = UnitExt;
+  PasExt  = '.pas';
+  PPExt   = '.pp';
+  IncExt  = '.inc';
+  ObjExt  = '.o';
+  RstExt  = '.rst';
+  LibExt  = '.a';
+  SharedLibExt = '.so';
+  DLLExt  = '.dll';
+  ExeExt  = '.exe';
+  ZipExt  = '.zip';
+
+  // Targets
+  i386_Linux = 'i386-linux';
+  i386_Win32 = 'i386-win32';
+  i386_Dos = 'i386-go32v2';
+  i386_OS2 = 'i386-os2';
+  i386_FreeBSD = 'i386-freebsd';
+  i386_NetBSD = 'i386-netsd';
+  i386_OpenBSD = 'i386-openbsd';
+  i386_netware = 'i386-netware';
+  i386_netwlibc = 'i386-netwlibc';
+  i386_go32v2 = 'i386-go32v2';
+  PPC_Linux = 'ppc-linux';
+  powerpc_linux = PPC_linux;
+  sparc_linux = 'sparc-linux';
+  arm_linux = 'arm-linux';
+  ppc_macos = 'ppc-macos';
+  ppc_darwin = 'ppc-darwin';
+
+  UnitTargets = [ttUnit,ttExampleUnit];
+  ProgramTargets = [ttProgram,ttExampleProgram];
+
+
+  AllMessages = [vlError,vlWarning,vlInfo,vlCompare,vlCommand];

+ 168 - 0
utils/fppkg/fpmktype.pp

@@ -0,0 +1,168 @@
+{$mode objfpc}
+{$h+}
+unit fpmktype;
+
+interface
+
+uses sysutils;
+
+Type
+  TFileType = (ftSource,ftUnit,ftObject,ftResource,ftExecutable,ftStaticLibrary,
+               ftSharedLibrary);
+  TFileTypes = set of TFileType;
+
+  TOS = (Amiga,Atari,Darwin,FreeBSD,Go32v2,Linux,MacOS,MorphOS,NetBSD,
+         Netware,NetwLibc,OpenBSD,OS2,PalmOS,Solaris,Win32,wince,Emx);
+  TOSes = Set of TOS;
+  
+  TCPU = (Arm,I386,PPC,SPARC,X86_64,m68k);
+  TCPUS = Set of TCPU;
+  
+  TCompilerMode = (FPC,TP,ObjFPC,Delphi,MacPas);
+  TCompilerModes = Set of TCompilerMode;
+  
+  TTargetType = (ttUnit,ttProgram,ttExampleUnit,ttExampleProgram);
+  TTargetTypes = set of TTargetType;
+  
+  TTargetState = (tsNeutral,tsCompiling,tsCompiled,tsInstalled);
+  TTargetStates = Set of TTargetState;
+
+  TVerboseLevel = (vlError,vlWarning,vlInfo,vlCompare,vlCommand,vldebug);
+  TVerboseLevels = Set of TVerboseLevel;
+
+  TCommandAt = (caBeforeCompile,caAfterCompile,
+                caBeforeInstall,caAfterInstall,
+                caBeforeArchive,caAfterArchive,
+                caBeforeClean,caAfterClean,
+                caBeforeDownload,caAfterDownload);
+  
+  TLogEvent = Procedure (Level : TVerboseLevel; Const Msg : String) of Object;
+
+  EInstallerError = Class(Exception);
+
+{$i fpmkcnst.inc}
+
+Function OSToString(OS: TOS) : String;
+Function OSesToString(OSes: TOSes) : String;
+Function CPUToString(CPU: TCPU) : String;
+Function CPUSToString(CPUS: TCPUS) : String;
+Function StringToOS(S : String) : TOS;
+Function OSesToString(S : String) : TOSes;
+Function StringToCPU(S : String) : TCPU;
+Function StringToCPUS(S : String) : TCPUS;
+Function ModeToString(Mode: TCompilerMode) : String;
+Function StringToMode(S : String) : TCompilerMode;
+Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
+Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
+
+implementation
+
+uses typinfo;
+
+resourcestring
+  SErrInvalidCPU        = 'Invalid CPU name : "%s"';
+  SErrInvalidOS         = 'Invalid OS name : "%s"';
+  SErrInvalidMode       = 'Invalid compiler mode : "%s"';
+  SErrInvalidTarget     = 'Invalid compiler target: %s';
+
+
+Function OSToString(OS: TOS) : String;
+
+begin
+  Result:=LowerCase(GetenumName(TypeInfo(TOS),Ord(OS)));
+end;
+
+Function OSesToString(OSes: TOSes) : String;
+
+begin
+  Result:=LowerCase(SetToString(PtypeInfo(TypeInfo(TOSes)),Integer(OSes),False));
+end;
+
+Function CPUToString(CPU: TCPU) : String;
+
+begin
+  Result:=LowerCase(GetenumName(TypeInfo(TCPU),Ord(CPU)));
+end;
+
+Function CPUSToString(CPUS: TCPUS) : String;
+
+begin
+  Result:=LowerCase(SetToString(PTypeInfo(TypeInfo(TCPUS)),Integer(CPUS),False));
+end;
+
+Function StringToOS(S : String) : TOS;
+
+Var
+  I : Integer;
+
+begin
+  I:=GetEnumValue(TypeInfo(TOS),S);
+  if (I=-1) then
+    Raise EInstallerError.CreateFmt(SErrInvalidOS,[S]);
+  Result:=TOS(I);
+end;
+
+
+Function OSesToString(S : String) : TOSes;
+
+begin
+  Result:=TOSes(StringToSet(PTypeInfo(TypeInfo(TOSes)),S));
+end;
+
+Function StringToCPU(S : String) : TCPU;
+
+Var
+  I : Integer;
+
+begin
+  I:=GetEnumValue(TypeInfo(TCPU),S);
+  if (I=-1) then
+    Raise EInstallerError.CreateFmt(SErrInvalidCPU,[S]);
+  Result:=TCPU(I);
+end;
+
+Function StringToCPUS(S : String) : TCPUS;
+
+begin
+  Result:=TCPUS(StringToSet(PTypeInfo(TypeInfo(TCPUS)),S));
+end;
+
+Function ModeToString(Mode: TCompilerMode) : String;
+
+begin
+  Result:=LowerCase(GetenumName(TypeInfo(TCompilerMode),Ord(Mode)));
+end;
+
+Function StringToMode(S : String) : TCompilerMode;
+
+Var
+  I : Integer;
+
+begin
+  I:=GetEnumValue(TypeInfo(TCompilerMode),S);
+  if (I=-1) then
+    Raise EInstallerError.CreateFmt(SErrInvalidMode,[S]);
+  Result:=TCompilerMode(I);
+end;
+
+
+Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
+
+begin
+  Result:=CPUToString(CPU)+'-'+OSToString(OS);
+end;
+
+Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
+
+Var
+  P : integer;
+
+begin
+  P:=Pos('-',S);
+  If (P=0) then
+    Raise EInstallerError.CreateFmt(SErrInvalidTarget,[S]);
+  CPU:=StringToCPU(Copy(S,1,P-1));
+  OS:=StringToOs(Copy(S,P+1,Length(S)-P));
+end;
+
+end.

+ 3467 - 0
utils/fppkg/fpmkunit.pp

@@ -0,0 +1,3467 @@
+{$Mode objfpc}
+{$H+}
+{$define debug}
+unit fpmkunit;
+
+Interface
+
+uses SysUtils,Classes,fpmktype;
+
+Type
+  // aliases for easy use and backwards compatibility.
+  TFileType = fpmktype.TFileType;
+  TFileTypes = fpmktype.TFileTypes;
+
+  TOS = fpmktype.TOS;
+  TOSes = fpmktype.TOSes;
+  
+  TCPU = fpmkType.TCPU;
+  TCPUS = fpmktype.TCPUS;
+  
+  TCompilerMode = fpmktype.TCompilerMode;
+  TCompilerModes = fpmktype.TCompilerModes;
+  
+  TTargetType = fpmktype.TTargetType;
+  TTargetTypes = fpmktype.TTargetTypes;
+  
+  TTargetState = fpmktype.TTargetState;
+  TTargetStates = fpmktype.TTargetStates;
+
+  TVerboseLevel = fpmktype.TVerboseLevel;
+  TVerboseLevels = fpmktype.TVerboseLevels;
+
+  TLogEvent = fpmktype.TLogEvent;
+  
+  TRunMode = (rmHelp,rmCompile,rmBuild,rmInstall,rmArchive,rmClean,rmManifest);
+  
+  { TNamedItem }
+
+  TNamedItem = Class(TCollectionItem)
+  private
+    FName: String;
+    procedure SetName(const AValue: String);virtual;
+  Public
+    property Name : String Read FName Write SetName;
+  end;  
+  
+  { TNamedCollection }
+
+  TNamedCollection = Class(TCollection)
+  private
+    FUniqueNames: Boolean;
+  Public
+    Function IndexOfName(AName : String) : Integer;
+    Function ItemByName(AName : String) : TNamedItem;
+    Property UniqueNames : Boolean Read FUniqueNames;
+  end;
+  
+  { TNamedItemList }
+  
+  TNamedItemList = Class(TList)
+  private
+    function GetNamedItem(Index : Integer): TNamedItem;
+    procedure SetNamedItem(Index : Integer; const AValue: TNamedItem);
+  public
+    Function IndexOfName(AName : String) : Integer;
+    Function ItemByName(ANAme : String) : TNamedItem;
+    Property NamedItems[Index : Integer] : TNamedItem Read GetNamedItem Write SetNamedItem; default;
+  end;
+  
+  TCommandAt = fpmktype.TCommandAt;
+
+  { TCommand }
+  TCommand = Class(TNamedItem)
+  private
+    FAfterCommand: TNotifyEvent;
+    FBeforeCommand: TNotifyEvent;
+    FCommand: String;
+    FCommandAt: TCommandAt;
+    FDestFile: String;
+    FIgnoreResult: Boolean;
+    FOptions: String;
+    FSourceFile: String;
+  Public
+    Property SourceFile : String Read FSourceFile Write FSourceFile;
+    Property DestFile : String Read FDestFile Write FDestFile;
+    Property Command : String Read FCommand Write FCommand;
+    Property Options : String Read FOptions Write FOptions;
+    Property At : TCommandAt Read FCommandAt Write FCommandAt;
+    Property IgnoreResult : Boolean Read FIgnoreResult Write FIgnoreResult;
+    Property BeforeCommand : TNotifyEvent Read FBeforeCommand Write FBeforeCommand;
+    Property AfterCommand : TNotifyEvent Read FAfterCommand Write FAfterCommand;
+  end;
+  
+  { TCommands }
+
+  TCommands = Class(TNamedCollection)
+  private
+    FDefaultAt: TCommandAt;
+    function GetCommand(Dest : String): TCommand;
+    function GetCommandItem(Index : Integer): TCommand;
+    procedure SetCommandItem(Index : Integer; const AValue: TCommand);
+  Public
+    Function AddCommand(Const Cmd : String) : TCommand;
+    Function AddCommand(Const Cmd,Options : String) : TCommand;
+    Function AddCommand(Const Cmd,Options,Dest,Source : String) : TCommand;
+    Function AddCommand(At : TCommandAt; Const Cmd : String) : TCommand;
+    Function AddCommand(At : TCommandAt; Const Cmd,Options : String) : TCommand;
+    Function AddCommand(At : TCommandAt; Const Cmd,Options, Dest,Source : String) : TCommand;
+    Property CommandItems[Index : Integer] : TCommand Read GetCommandItem Write SetCommandItem;
+    Property Commands[Dest : String] : TCommand Read GetCommand; default;
+    Property DefaultAt : TCommandAt Read FDefaultAt Write FDefaultAt;
+  end;
+
+  { TTarget }
+
+  TTarget = Class(TNamedItem)
+  private
+    FInstall : Boolean;
+    FAfterClean: TNotifyEvent;
+    FAfterCompile: TNotifyEvent;
+    FBeforeClean: TNotifyEvent;
+    FBeforeCompile: TNotifyEvent;
+    FCPUs: TCPUs;
+    FMode: TCompilerMode;
+    FResourceStrings: Boolean;
+    FObjectPath,
+    FUnitPath,
+    FIncludePath,
+    FDependencies: TStrings;
+    FCommands : TCommands;
+    FDirectory: String;
+    FExtension: String;
+    FFileType: TFileType;
+    FOptions: String;
+    FOSes: TOSes;
+    FFPCTarget: String;
+    FTargetState: TTargetState;
+    FTargetType: TTargetType;
+    function GetCommands: TCommands;
+    function GetHasCommands: Boolean;
+    function GetHasStrings(AIndex: integer): Boolean;
+    function GetStrings(AIndex: integer): TStrings;
+    procedure SetCommands(const AValue: TCommands);
+    procedure SetStrings(AIndex: integer; const AValue: TStrings);
+  Protected
+    Function GetSourceFileName : String; virtual;
+    Function GetUnitFileName : String; virtual;
+    Function GetObjectFileName : String; virtual;
+    Function GetRSTFileName : String; Virtual;
+    Function GetProgramFileName(AnOS : TOS) : String; Virtual;
+  Public
+    Constructor Create(ACollection : TCollection); override;
+    Destructor Destroy; override;
+    Function GetOutputFileName (AOs : TOS) : String; Virtual;
+    procedure SetName(const AValue: String);override;
+    Procedure GetCleanFiles(List : TStrings; APrefix : String; AnOS : TOS); virtual;
+    Procedure GetInstallFiles(List : TStrings; APrefix : String; AnOS : TOS); virtual;
+    Procedure GetArchiveFiles(List : TStrings; APrefix : String; AnOS : TOS); virtual;
+    Property HasUnitPath : Boolean Index 0 Read GetHasStrings;
+    Property HasObjectPath : Boolean Index 1 Read GetHasStrings;
+    Property HasIncludePath : Boolean Index 2 Read GetHasStrings;
+    Property HasDependencies : Boolean Index 3 Read GetHasStrings;
+    Property HasCommands : Boolean Read GetHasCommands;
+    Property UnitPath : TStrings Index 0 Read GetStrings Write SetStrings;
+    Property ObjectPath : TStrings Index 1  Read GetStrings Write SetStrings;
+    Property IncludePath : TStrings Index 2 Read GetStrings Write SetStrings;
+    Property Dependencies : TStrings Index 3 Read GetStrings Write SetStrings;
+    Property Commands : TCommands Read GetCommands Write SetCommands;
+    Property State : TTargetState Read FTargetState;
+    Property TargetType : TTargetType Read FTargetType Write FTargetType;
+    Property OS : TOSes Read FOSes Write FOSes;
+    Property Mode : TCompilerMode Read FMode Write FMode;
+    Property Options : String Read FOptions Write Foptions;
+    Property SourceFileName: String Read GetSourceFileName ;
+    Property UnitFileName : String Read GetUnitFileName;
+    Property ObjectFileName : String Read GetObjectFileName;
+    Property RSTFileName : String Read GetRSTFileName;
+    Property CPU : TCPUs Read FCPUs Write FCPUs;
+    Property FPCTarget : String Read FFPCTarget Write FFPCTarget;
+    Property Extension : String Read FExtension Write FExtension;
+    Property FileType : TFileType Read FFileType Write FFileType;
+    Property Directory : String Read FDirectory Write FDirectory;
+    Property ResourceStrings : Boolean Read FResourceStrings Write FResourceStrings;
+    Property Install : Boolean Read FInstall Write FInstall;
+    // Events.
+    Property BeforeCompile : TNotifyEvent Read FBeforeCompile Write FBeforeCompile;
+    Property AfterCompile : TNotifyEvent Read FAfterCompile Write FAfterCompile;
+    Property BeforeClean : TNotifyEvent Read FBeforeClean Write FBeforeClean;
+    Property AfterClean : TNotifyEvent Read FAfterClean Write FAfterClean;
+  end;
+
+  { TTargets }
+
+  TTargets = Class(TNamedCollection)
+  private
+    FDefaultCPU: TCPUs;
+    FDefaultDir : String;
+    FDefaultOS: TOSes;
+    function GetTargetItem(Index : Integer): TTarget;
+    function GetTarget(AName : String): TTarget;
+    procedure SetDefaultDir(const AValue: String);
+    procedure SetTargetItem(Index : Integer; const AValue: TTarget);
+    Procedure ApplyDefaults(ATarget : TTarget);
+  Public
+    Procedure ResetDefaults;
+    Function AddUnit(AUnitName : String) : TTarget;
+    Function AddProgram(AProgramName : String) : TTarget;
+    Function AddExampleUnit(AUnitName : String) : TTarget;
+    Function AddExampleProgram(AProgramName : String) : TTarget;
+    Property Targets[AName : String] : TTarget Read GetTarget; default;
+    Property TargetItems[Index : Integer] : TTarget Read GetTargetItem Write SetTargetItem;
+    Property DefaultDir : String Read FDefaultDir Write SetDefaultDir;
+    Property DefaultOS : TOSes Read FDefaultOS Write FDefaultOS;
+    Property DefaultCPU : TCPUs Read FDefaultCPU Write FDefaultCPU;
+  end;
+  
+  { TPackage }
+  
+  TPackage = Class(TNamedItem) // Maybe descend from/use TTarget ?
+  private
+    FAfterArchive: TNotifyEvent;
+    FAfterClean: TNotifyEvent;
+    FAfterCompile: TNotifyEvent;
+    FAfterInstall: TNotifyEvent;
+    FAfterManifest: TNotifyEvent;
+    FBeforeArchive: TNotifyEvent;
+    FBeforeClean: TNotifyEvent;
+    FBeforeCompile: TNotifyEvent;
+    FBeforeInstall: TNotifyEvent;
+    FBeforeManifest: TNotifyEvent;
+    FUnitPath,
+    FObjectPath,
+    FIncludePath,
+    FCleanFiles,
+    FArchiveFiles,
+    FInstallFiles,
+    FDependencies: TStrings;
+    FCPU: TCPUs;
+    FOS: TOses;
+    FTargetState: TTargetState;
+    FTargets: TTargets;
+    FDirectory: String;
+    FOptions: String;
+    FAuthor: String;
+    FLicense: String;
+    FURL: String;
+    FVersion: String;
+    FEmail : String;
+    FCommands : TCommands;
+    FDescriptionFile : String;
+    FDescription : String;
+    Function GetDescription : string;
+    function GetCommands: TCommands;
+    function GetHasCommands: Boolean;
+    function GetHasStrings(AIndex: integer): Boolean;
+    function GetStrings(AIndex: integer): TStrings;
+    procedure SetCommands(const AValue: TCommands);
+    procedure SetStrings(AIndex: integer; const AValue: TStrings);
+  Public
+    constructor Create(ACollection: TCollection); override;
+    destructor destroy; override;
+    Function AddTarget(AName : String) : TTarget;
+    Procedure AddDependency(AName : String);
+    Procedure AddInstallFile(AFileName : String);
+    Procedure GetCleanFiles(List : TStrings; Const APrefix : String; AOS : TOS); virtual;
+    procedure GetInstallFiles(List: TStrings;Types : TTargetTypes;Const APrefix : String; AOS : TOS);
+    Procedure GetArchiveFiles(List : TStrings; Const APrefix : String; AOS : TOS); virtual;
+    Procedure GetManifest(Manifest : TStrings);
+    Property Version : String Read FVersion Write FVersion;
+    Property URL : String Read FURL Write FURL;
+    Property Email : String Read FEmail Write FEmail;
+    Property Author : String Read FAuthor Write FAuthor;
+    Property License : String Read FLicense Write FLicense;
+    Property Directory : String Read FDirectory Write FDirectory;
+    Property Description : String Read GetDescription Write FDescription;
+    Property DescriptionFile : String Read FDescriptionFile Write FDescriptionFile;
+    // Compiler options.
+    Property OS : TOses Read FOS Write FOS;
+    Property CPU : TCPUs Read FCPU Write FCPU;
+    Property Options: String Read FOptions Write FOptions;
+    Property HasUnitPath : Boolean Index 0 Read GetHasStrings;
+    Property HasObjectPath : Boolean Index 1 Read GetHasStrings;
+    Property HasIncludePath : Boolean Index 2 Read GetHasStrings;
+    Property HasDependencies : Boolean Index 3 Read GetHasStrings;
+    Property HasInstallFiles: Boolean Index 4 Read GetHasStrings;
+    Property HasCleanFiles : Boolean Index 5 Read GetHasStrings;
+    Property HasArchiveFiles : Boolean Index 6 Read GetHasStrings;
+    Property HasCommands : Boolean Read GetHasCommands;
+    Property UnitPath : TStrings Index 0 Read GetStrings Write SetStrings;
+    Property ObjectPath : TStrings Index 1  Read GetStrings Write SetStrings;
+    Property IncludePath : TStrings Index 2 Read GetStrings Write SetStrings;
+    // Targets and dependencies
+    Property Dependencies : TStrings Index 3 Read GetStrings Write SetStrings;
+    Property InstallFiles : TStrings Index 4 Read GetStrings Write SetStrings;
+    Property CleanFiles : TStrings Index 5 Read GetStrings Write SetStrings;
+    Property ArchiveFiles : TStrings Index 6 Read GetStrings Write SetStrings;
+    Property Commands : TCommands Read GetCommands Write SetCommands;
+    Property State : TTargetState Read FTargetState;
+    Property Targets : TTargets Read FTargets;
+    // events
+    Property BeforeCompile : TNotifyEvent Read FBeforeCompile Write FBeforeCompile;
+    Property AfterCompile : TNotifyEvent Read FAfterCompile Write FAfterCompile;
+    Property BeforeInstall : TNotifyEvent Read FBeforeInstall Write FBeforeInstall;
+    Property AfterInstall : TNotifyEvent Read FAfterInstall Write FAfterInstall;
+    Property BeforeClean : TNotifyEvent Read FBeforeClean Write FBeforeClean;
+    Property AfterClean : TNotifyEvent Read FAfterClean Write FAfterClean;
+    Property BeforeArchive : TNotifyEvent Read FBeforeArchive Write FBeforeArchive;
+    Property AfterArchive : TNotifyEvent Read FAfterArchive Write FAfterArchive;
+    Property BeforeManifest : TNotifyEvent Read FBeforeManifest Write FBeforeManifest;
+    Property AfterManifest : TNotifyEvent Read FAfterManifest Write FAfterManifest;
+  end;
+
+  { TPackages }
+
+  TPackages = Class(TNamedCollection)
+  private
+    function GetPackage(AName : String): TPackage;
+    function GetPackageItem(AIndex : Integer): TPackage;
+    procedure SetPackageItem(AIndex : Integer; const AValue: TPackage);
+  Public
+    Function AddPackage(Const AName : String) : TPackage;
+    Property Packages[AName : String] : TPackage Read GetPackage ; Default;
+    Property PackageItems[AIndex : Integer] : TPackage Read GetPackageItem Write SetPackageItem;
+  end;
+
+  { TDefaults }
+  
+  TDefaults = Class(TPersistent)
+  Private
+    FArchive: String;
+    FCompiler: String;
+    FCopy: String;
+    FMkDir: String;
+    FMove: String;
+    FOptions: String;
+    FCPU: TCPU;
+    FOS: TOS;
+    FMode : TCompilerMode;
+    FPrefix: String;
+    FBaseInstallDir,
+    FUnitInstallDir,
+    FBinInstallDir,
+    FDocInstallDir,
+    FExamplesInstallDir : String;
+    FRemove: String;
+    FTarget: String;
+    FUnixPaths: Boolean;
+    function GetBaseInstallDir: String;
+    function GetBinInstallDir: String;
+    function GetCompiler: String;
+    function GetDocInstallDir: String;
+    function GetExamplesInstallDir: String;
+    function GetUnitInstallDir: String;
+    procedure SetBaseInstallDir(const AValue: String);
+    procedure SetCPU(const AValue: TCPU);
+    procedure SetOS(const AValue: TOS);
+    procedure SetPrefix(const AValue: String);
+    procedure SetTarget(const AValue: String);
+  Protected
+    procedure RecalcTarget;
+  Public
+    Constructor Create;
+    Procedure InitDefaults;
+    Procedure Assign(ASource : TPersistent);override;
+    Procedure LocalInit(Const AFileName : String);
+    Procedure LoadFromFile(Const AFileName : String);
+    Procedure SaveToFile(Const AFileName : String);
+    procedure SaveToStream(S : TStream);virtual;
+    procedure LoadFromStream(S : TStream);virtual;
+    // Compile Information
+    Property Target : String Read FTarget Write SetTarget;
+    Property OS : TOS Read FOS Write SetOS;
+    Property CPU : TCPU Read FCPU Write SetCPU;
+    Property Mode : TCompilerMode Read FMode Write FMode;
+    Property UnixPaths : Boolean Read FUnixPaths Write FUnixPaths;
+    Property Options : String Read FOptions Write FOptions;    // Default compiler options.
+    // paths etc.
+    Property Prefix : String Read FPrefix Write SetPrefix;
+    Property BaseInstallDir : String Read GetBaseInstallDir Write SetBaseInstallDir;
+    Property UnitInstallDir : String Read GetUnitInstallDir Write FUnitInstallDir;
+    Property BinInstallDir : String Read GetBinInstallDir Write FBinInstallDir;
+    Property DocInstallDir : String Read GetDocInstallDir Write FDocInstallDir;
+    Property ExamplesInstallDir : String Read GetExamplesInstallDir Write FExamplesInstallDir;
+    // Command tools. If not set, internal commands  will be used.
+    Property Compiler : String Read GetCompiler Write FCompiler; // Compiler. Defaults to fpc/ppc386
+    Property Copy : String Read FCopy Write FCopy;             // copy $(FILES) to $(DEST)
+    Property Move : String Read FMove Write FMove;             // Move $(FILES) to $(DEST)
+    Property Remove : String Read FRemove Write FRemove;       // Delete $(FILES)
+    Property MkDir : String Read FMkDir write FMkDir;          // Make $(DIRECTORY)
+    Property Archive : String Read FArchive Write FArchive;    // zip $(ARCHIVE) $(FILESORDIRS)
+  end;
+
+  { TBuildEngine }
+
+  TBuildEngine = Class(TComponent)
+  private
+    // general variables
+    FCompiler : String;
+    FStartDir : String;
+    FTargetDir : String;
+    FDefaults : TDefaults;
+    FForceCompile : Boolean;
+    FListMode : Boolean;
+    // Variables used when compiling a package.
+    // Only valid during compilation of the package.
+    FCurrentOutputDir : String;
+    FCurrentPackage: TPackage;
+    // Events
+    FOnLog: TLogEvent;
+    FAfterArchive: TNotifyEvent;
+    FAfterClean: TNotifyEvent;
+    FAfterCompile: TNotifyEvent;
+    FAfterInstall: TNotifyEvent;
+    FAfterManifest: TNotifyEvent;
+    FBeforeArchive: TNotifyEvent;
+    FBeforeClean: TNotifyEvent;
+    FBeforeCompile: TNotifyEvent;
+    FBeforeInstall: TNotifyEvent;
+    FBeforeManifest: TNotifyEvent;
+    procedure SetDefaults(const AValue: TDefaults);
+    procedure SetTargetDir(const AValue: String);
+  Protected
+    Procedure Error(Msg : String);
+    Procedure Error(Fmt : String; Args : Array of const);
+    // Internal copy/delete/move/archive/mkdir files
+    Procedure SysCopyFile(Const Src,Dest : String); virtual;
+    Procedure SysMoveFile(Const Src,Dest : String); virtual;
+    Procedure SysDeleteFile(Const AFileName : String); virtual;
+    Procedure SysArchiveFiles(List : TStrings; Const AFileName : String); virtual;
+    Procedure Log(Level : TVerboseLevel; Const Msg : String);
+    Procedure Log(Level : TVerboseLevel; Const Fmt : String; Args : Array Of Const);
+    Procedure EnterDir(ADir : String);
+    Function GetCompiler : String;
+    Procedure InstallPackageFiles(APAckage : TPackage; tt : TTargetType; Const Src,Dest : String); virtual;
+    Function FileNewer(Src,Dest : String) : Boolean;
+
+  Public
+    Constructor Create(AOwner : TComponent); override;
+    // Public Copy/delete/Move/Archive/Mkdir Commands.
+    Procedure ExecuteCommand(Cmd : String; Args : String; IgnoreError : Boolean = False); virtual;
+    Procedure CmdCopyFiles(List : TStrings; Const DestDir : String);
+    Procedure CmdCreateDir(DestDir : String);
+    Procedure CmdMoveFiles(List : TStrings; Const DestDir : String);
+    Procedure CmdDeleteFiles(List : TStrings);
+    Procedure CmdArchiveFiles(List : TStrings; Const ArchiveFile : String);
+    Procedure ExecuteCommands(Commands : TCommands; At : TCommandAt);
+    // Target commands
+    Function  GetTargetDir(APackage : TPackage; ATarget : TTarget; AbsolutePath : Boolean = False) : String;
+    Function  GetCompilerCommand(APackage : TPackage; Target : TTarget) : String;
+    Function  TargetOK(Target : TTarget) : Boolean;
+    Function  NeedsCompile(Target : TTarget) : Boolean;
+    Procedure Compile(Target : TTarget);  virtual;
+    Procedure FixDependencies(Target: TTarget);
+    // Package commands
+    Function  GetPackageDir(APackage : TPackage; AbsolutePath : Boolean = False) : String;
+    Function  GetOutputDir(APackage : TPackage; AbsolutePath : Boolean = False) : String;
+    Function  PackageOK(APackage : TPackage) : Boolean; virtual;
+    Procedure DoBeforeCompile(APackage : TPackage);virtual;
+    Procedure DoAfterCompile(APackage : TPackage);virtual;
+    Procedure DoBeforeInstall(APackage : TPackage);virtual;
+    Procedure DoAfterInstall(APackage : TPackage);virtual;
+    Procedure DoBeforeArchive(APackage : TPackage);virtual;
+    Procedure DoAfterArchive(APackage : TPackage);virtual;
+    Procedure DoBeforeClean(APackage : TPackage);virtual;
+    Procedure DoAfterClean(APackage : TPackage);virtual;
+    Function NeedsCompile(APackage : TPackage) : Boolean; virtual;
+    Procedure Compile(APackage : TPackage);
+    Procedure Install(APackage : TPackage);
+    Procedure Archive(APackage : TPackage);
+    Procedure Clean(APackage : TPackage);
+    Procedure FixDependencies(APackage : TPackage);
+    Procedure GetManifest(APackage : TPackage; Manifest : TStrings);
+    procedure CheckExternalPackage(Const APackageName : String);
+    procedure CreateOutputDir(APackage: TPackage);
+    // Packages commands
+    Procedure Compile(Packages : TPackages);
+    Procedure Install(Packages : TPackages);
+    Procedure Archive(Packages : TPackages);
+    Procedure Clean(Packages : TPackages);
+    Procedure GetManifest(Packages : TPackages; Manifest : TStrings);
+    Property ListMode : Boolean Read FListMode Write FListMode;
+    Property ForceCompile : Boolean Read FForceCompile Write FForceCompile;
+    Property Defaults : TDefaults Read FDefaults Write SetDefaults;
+    Property TargetDir : String Read FTargetDir Write SetTargetDir;
+    // Events
+    Property BeforeCompile : TNotifyEvent Read FBeforeCompile Write FBeforeCompile;
+    Property AfterCompile : TNotifyEvent Read FAfterCompile Write FAfterCompile;
+    Property BeforeInstall : TNotifyEvent Read FBeforeInstall Write FBeforeInstall;
+    Property AfterInstall : TNotifyEvent Read FAfterInstall Write FAfterInstall;
+    Property BeforeClean : TNotifyEvent Read FBeforeClean Write FBeforeClean;
+    Property AfterClean : TNotifyEvent Read FAfterClean Write FAfterClean;
+    Property BeforeArchive : TNotifyEvent Read FBeforeArchive Write FBeforeArchive;
+    Property AfterArchive : TNotifyEvent Read FAfterArchive Write FAfterArchive;
+    Property BeforeManifest : TNotifyEvent Read FBeforeManifest Write FBeforeManifest;
+    Property AfterManifest : TNotifyEvent Read FAfterManifest Write FAfterManifest;
+    Property OnLog : TLogEvent Read FOnLog Write FOnlog;
+  end;
+
+  { TInstaller }
+
+  TInstaller = Class(TComponent)
+  private
+    FBuildEngine: TBuildEngine;
+    FDefaultPackage: TPackage;
+    FDefaults: TDefaults;
+    FPackages: TPackages;
+    FRunMode: TRunMode;
+    FListMode : Boolean;
+    FLogLevels : TVerboseLevels;
+    Function GetPackageString(Index : Integer) : String;
+    Procedure SetPackageString(Index : Integer; AValue : String);
+    function GetStrings(AIndex : Integer): TStrings;
+    function GetOSes: TOSes;
+    function GetTargets: TTargets;
+    procedure SetDefaultPackage(const AValue: TPackage);
+    procedure SetDefaults(const AValue: TDefaults);
+    procedure SetStrings(AIndex : Integer; const AValue: TStrings);
+    procedure SetOses(const AValue: TOSes);
+  Protected
+    Procedure Log(Level : TVerboseLevel; Const Msg : String);
+    Procedure CreatePackages; virtual;
+    Procedure CheckPackages; virtual;
+    Procedure CreateBuildEngine; virtual;
+    Procedure CheckDefaultPackage;
+    Procedure Error(Msg : String);
+    Procedure Error(Fmt : String; Args : Array of const);
+    Procedure AnalyzeOptions;
+    Procedure Usage(FMT : String; Args : Array of const);
+    Procedure Compile(Force : Boolean); virtual;
+    Procedure Clean; virtual;
+    Procedure Install; virtual;
+    Procedure Archive; virtual;
+    Procedure Manifest; virtual;
+    Property BuildEngine : TBuildEngine Read FBuildEngine;
+  Public
+    Constructor Create(AOWner : TComponent); override;
+    Destructor destroy; override;
+    Function StartPackage(Const AName : String) : TPackage;
+    Procedure EndPackage;
+    Function Run : Boolean;
+    Function AddTarget(AName : String) : TTarget;
+    Procedure AddDependency(AName : String);
+    Property DefaultPackage : TPackage read FDefaultPackage write SetDefaultPackage;
+    Property Packages : TPackages Read FPackages;
+    Property Dependencies : TStrings Index 0 Read GetStrings Write SetStrings;
+    Property InstallFiles : TStrings Index 1 Read GetStrings Write SetStrings;
+    Property CleanFiles : TStrings Index 2 Read GetStrings Write SetStrings;
+    Property ArchiveFiles : TStrings Index 3 Read GetStrings Write SetStrings;
+    Property Defaults : TDefaults Read FDefaults Write SetDefaults;
+    Property RunMode : TRunMode Read FRunMode;
+    Property ListMode : Boolean Read FListMode;
+    // Default Package redirects.
+    Property Targets : TTargets Read GetTargets;
+    Property OS: TOSes Read GetOSes Write SetOses;
+    Property Author : String Index 0 Read GetPackageString Write SetPackageString;
+    Property Directory : String Index 1 Read GetPackageString Write SetPackageString;
+    Property License : String Index 2 Read GetPackageString Write SetPackageString;
+    Property Options : String Index 3 Read GetPackageString Write SetPackageString;
+    Property URL : String Index 4 Read GetPackageString Write SetPackageString;
+    Property Email : String Index 5 Read GetPackageString Write SetPackageString;
+    Property Description: String Index 6 Read GetPackageString Write SetPackageString;
+    Property DescriptionFileName: String Index 7 Read GetPackageString Write SetPackageString;
+    Property Version : String Index 8 Read GetPackageString Write SetPackageString;
+  end;
+
+  TReplaceFunction = Function (Const AName,Args : String) : String of Object;
+
+  { TValueItem }
+
+  TValueItem = Class(TObject)
+    FValue : String;
+    Constructor Create(AValue : String);
+  end;
+  
+  { TFunctionItem }
+
+  TFunctionItem = Class(TObject)
+    FFunc : TReplaceFunction;
+    Constructor Create(AFunc : TReplaceFunction);
+  end;
+  
+  { TDictionary }
+
+  TDictionary = Class(TComponent)
+    FList : TStringList;
+  Public
+    Constructor Create(AOwner : TComponent); override;
+    Destructor Destroy;override;
+    Procedure AddVariable(Const AName,Value : String);
+    Procedure AddFunction(Const AName : String; FReplacement : TReplaceFunction);
+    Procedure RemoveItem(Const AName : String);
+    Function GetValue(Const AName : String) : String;
+    Function GetValue(Const AName,Args : String) : String; virtual;
+    Function ReplaceStrings(Const ASource : String) : String; virtual;
+  end;
+
+  ECollectionError = Class(Exception);
+  EInstallerError = fpmktype.EInstallerError;
+  EDictionaryError = Class(Exception);
+
+  TInstallerClass = Class of TInstaller;
+  TDictionaryClass = Class of TDictionary;
+
+// Constants are in the file as for fpmktype.
+
+{$i fpmkcnst.inc}
+ 
+
+Type
+  TArchiveEvent = Procedure (Const AFileName : String; List : TStrings) of Object;
+  TArchiveProc = Procedure (Const AFileName : String; List : TStrings);
+
+Var
+  InstallerClass : TInstallerClass = TInstaller;
+  DictionaryClass : TDictionaryClass = TDictionary;
+  OnArchiveFiles : TArchiveEvent = Nil;
+  ArchiveFilesProc : TArchiveProc = Nil;
+
+Function CurrentOS : String;
+Function CurrentCPU : String;
+
+Function Installer : TInstaller;
+Function Defaults : TDefaults; // Set by installer.
+Function Dictionary : TDictionary;
+
+Function OSToString(OS: TOS) : String;
+Function OSesToString(OSes: TOSes) : String;
+Function CPUToString(CPU: TCPU) : String;
+Function CPUSToString(CPUS: TCPUS) : String;
+Function StringToOS(S : String) : TOS;
+Function OSesToString(S : String) : TOSes;
+Function StringToCPU(S : String) : TCPU;
+Function StringToCPUS(S : String) : TCPUS;
+Function ModeToString(Mode: TCompilerMode) : String;
+Function StringToMode(S : String) : TCompilerMode;
+Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
+Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
+Procedure ResolveDependencies(L : TStrings; P : TNamedCollection);
+Function AddStrings(Dest,Src : TStrings) : Integer ;
+function AddStrings(Dest, Src : TStrings; Const APrefix : String) : Integer ;
+Function FileListToString(List : TStrings; Prefix : String) : String;
+Function FixPath (APath : String) : String;
+Procedure ChangeDir(APath : String);
+Function Substitute(Const Source : String; Macros : Array of string) : String;
+Procedure SplitCommand(Const Cmd : String; Var Exe,Options : String);
+
+Implementation
+
+uses typinfo;
+
+ResourceString
+  SErrNameExists        = 'Name "%s" already exists in the collection.';
+  SErrNoSuchName        = 'Could not find item with name "%s" in the collection.';
+  SErrNoPackage         = 'No package available. Add package with StartPackage Call';
+  SErrInValidArgument   = 'Invalid command-line argument at position %d : %s';
+  SErrNeedArgument      = 'Option at position %d (%s) needs an argument';
+  SErrNoPackagesDefined = 'No action possible: No packages were defined.';
+  SErrInstaller         = 'The installer encountered the following error:';
+  SErrDepUnknownTarget  = 'Unknown target in dependencies for %s: %s';
+  SErrExternalCommandFailed = 'External command "%s" failed with exit code: %d';
+  SErrCreatingDirectory = 'Failed to create directory: %s';
+  SErrDeletingFile      = 'Failed to delete file: %s';
+  SErrMovingFile        = 'Failed to move file "%s" to "%s"';
+  SErrCopyingFile       = 'Failed to copy file "%s" to "%s"';
+  SErrChangeDirFailed   = 'Failed to enter directory: %s';
+  SErrInvalidArgumentToSubstitute = 'Invalid number of arguments to Substitute';
+  SErrNoArchiveSupport  = 'This binary contains no archive support. Please recompile with archive support';
+  SErrNoDictionaryItem  = 'No item called "%s" in the dictionary';
+  SErrNoDictionaryValue = 'The item "%s" in the dictionary is not a value.';
+  SErrNoDictionaryFunc  = 'The item "%s" in the dictionary is not a function.';
+  SWarnCircularDependency = 'Warning: Circular dependency detected when compiling target %s: %s';
+  SWarnFailedToSetTime  = 'Warning: Failed to set timestamp on file : %s';
+  SWarnFailedToGetTime  = 'Warning: Failed to get timestamp from file : %s';
+  SWarnFileDoesNotExist = 'Warning: File "%s" does not exist';
+  
+  // Log messages
+  SLogEnterDir           = 'Entering directory: %s';
+  SLogCompilingPackage   = 'Compiling package : %s';
+  SLogCompilingTarget    = 'Compiling target  : %s';
+  SLogExecutingCommand   = 'Executing command %s with options: %s';
+  SLogCreatingOutputDir  = 'Creating output dir : %s';
+  SLogOutputDirExists    = 'Output dir exists : %s';
+  SLogInstallingPackage  = 'Installing package : %s';
+  SLogArchivingPackage   = 'Archiving package : %s';
+  SLogCleaningPackage    = 'Cleaning package : %s';
+  SLogCopyingFile        = 'Copying file "%s" to "%s"';
+  SLogCompilingFileTimes = 'Comparing file "%s" time "%s" to "%s" time "%s".';
+  SLogSourceNewerDest    = 'Source file "%s" (%s) is newer than destination "%s" (%s).';
+
+  // Help messages for usage
+  SValue              = 'Value';
+  SHelpUSage          = 'command [options]';
+  SHelpCommand        = 'Where command is one of the following:';
+  SHelpCompile        = 'Compile all units in the package(s).';
+  SHelpBuild          = 'Build all units in the package(s).';
+  SHelpInstall        = 'Install all units in the package(s).';
+  SHelpClean          = 'Clean (remove) all units in the package(s).';
+  SHelpArchive        = 'Create archive (zip) with all units in the package(s).';
+  SHelpHelp           = 'This message.';
+  SHelpManifest       = 'Create a manifest suitable for import in repository.';
+  SHelpCmdOptions     = 'Where options is one or more of the following:';
+  SHelpCPU            = 'Compile for indicated CPU.';
+  SHelpOS             = 'Compile for indicated OS';
+  SHelpTarget         = 'Compile for indicated target';
+  SHelpList           = 'list commands instead of actually executing them.';
+  SHelpPrefix         = 'Use indicated prefix directory for all commands.';
+  SHelpNoDefaults     = 'Do not use defaults when compiling.';
+  SHelpBaseInstallDir = 'Use indicated directory as base install dir.';
+  SHelpCompiler       = 'Use indicated binary as compiler';
+  SHelpConfig         = 'Use indicated config file when compiling.';
+  SHelpVerbose        = 'Be verbose when working.';
+
+
+Const
+  // Keys for Defaults file. Do not localize.
+  KeyCompiler = 'Compiler';
+  KeyArchive  = 'Archive';
+  KeyCopy     = 'Copy';
+  KeyMkDir    = 'MkDir';
+  KeyMove     = 'Move';
+  KeyRemove   = 'Remove';
+  KeyOptions  = 'Options';
+  KeyCPU      = 'CPU';
+  KeyOS       = 'OS';
+  KeyMode     = 'Mode';
+  KeyPrefix   = 'Prefix';
+  KeyTarget   = 'Target';
+  KeyBaseInstallDir     = 'BaseInstallDir';
+  KeyUnitInstallDir     = 'UnitInstallDir';
+  KeyBinInstallDir      = 'BinInstallDir';
+  KeyDocInstallDir      = 'DocInstallDir';
+  KeyExamplesInstallDir = 'ExamplesInstallDir';
+
+// Callback for Sysutils getapplicationname.
+
+Function GetFPMakeName : String;
+
+begin
+  Result:='fpmake';
+end;
+
+
+Function CurrentOS : String;
+
+begin
+  Result:=OSToString(Defaults.OS);
+end;
+
+Function CurrentCPU : String;
+
+begin
+  Result:=CPUToString(Defaults.CPU);
+end;
+
+Function OSToString(OS: TOS) : String;
+
+begin
+  Result:=fpmktype.OsToString(OS);
+end;
+
+Function OSesToString(OSes: TOSes) : String;
+
+begin
+  Result:=fpmktype.OSesToString(OSes);
+end;
+
+Function CPUToString(CPU: TCPU) : String;
+
+begin
+  Result:=fpmkType.CPUToString(CPU);
+end;
+
+Function CPUSToString(CPUS: TCPUS) : String;
+
+begin
+  Result:=fpmktype.CPUSToString(CPUS);
+end;
+
+Function StringToOS(S : String) : TOS;
+
+begin
+  Result:=fpmktype.StringToOS(S);
+end;
+
+Function OSesToString(S : String) : TOSes;
+
+begin
+  Result:=fpmktype.OSesToString(S);
+end;
+
+Function StringToCPU(S : String) : TCPU;
+
+begin
+  Result:=fpmktype.StringToCPU(S);
+end;
+
+Function StringToCPUS(S : String) : TCPUS;
+
+begin
+  Result:=fpmktype.StringToCPUS(S);
+end;
+
+Function ModeToString(Mode: TCompilerMode) : String;
+
+begin
+  Result:=fpmktype.ModeToString(Mode);
+end;
+
+Function StringToMode(S : String) : TCompilerMode;
+
+begin
+  Result:=fpmktype.StringToMode(S);
+end;
+
+
+Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
+
+begin
+  Result:=fpmktype.MakeTargetString(CPU,OS);
+end;
+
+Procedure StringToCPUOS(S : String; Var CPU : TCPU; Var OS: TOS);
+
+begin
+ fpmktype.StringToCPUOS(S,CPU,OS);
+end;
+
+Procedure ResolveDependencies(L : TStrings; P : TNamedCollection);
+
+Var
+  I,J : Integer;
+
+begin
+  If Assigned(L) then
+    For I:=0 to L.Count-1 do
+      begin
+      J:=P.IndexOfName(L[i]);
+      If J<>-1 then
+        L.Objects[I]:=P.Items[J];
+      end;
+end;
+
+Function AddStrings(Dest,Src : TStrings) : Integer ;
+
+begin
+  Result:=AddStrings(Dest,Src,'');
+end;
+
+Procedure AddStrings(Var S : String; L : TStrings; Prefix : String);
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to L.Count-1 do
+    begin
+    if (S<>'') then
+      S:=S+' ';
+    S:=S+Prefix+L[i];
+    end;
+end;
+
+function AddStrings(Dest, Src : TStrings; Const APrefix : String) : Integer ;
+begin
+  Result:=0;
+  While (Result<Src.Count) do
+    begin
+    If (APrefix<>'') then
+      Dest.Add(APrefix+Src[Result]) // Not sure whether '' is optimized away.
+    else
+      Dest.Add(Src[Result]);
+    Inc(Result);
+    end;
+end;
+
+function FileListToString(List : TStrings; Prefix : String) : String;
+
+Var
+  I : integer;
+  S : String;
+
+begin
+  Result:='';
+  For I:=0 to List.Count-1 do
+    begin
+    If (I>0) then
+      Result:=Result+' ';
+    S:=Prefix+List[i];
+    If (Pos(' ',S)<>0) then
+      S:='"'+S+'"';
+    Result:=Result+S;
+    end;
+end;
+
+function FixPath (APath : String) : String;
+
+Var
+  P : PChar;
+  
+begin
+  Result:=APath;
+  If (result<>'') then
+    begin
+    P:=PChar(Result);
+    While (P^<>#0) do
+      begin
+      If P^ in ['/','\',':'] then // do not use drive letters.
+        P^:=PathDelim;
+      Inc(P);
+      end;
+    end;
+end;
+
+procedure ChangeDir(APath : String);
+
+begin
+  if Not SetCurrentDir(APath) then
+    Raise EInstallerError.CreateFmt(SErrChangeDirFailed,[APath]);
+end;
+
+procedure SplitCommand(const Cmd : String; var Exe, Options : String);
+
+Const
+  WhiteSpace = [#9,#10,#13,' '];
+  QuoteChars = ['''','"'];
+
+Var
+  I : Integer;
+  InQuote : Boolean;
+  LastQuote : Char;
+  S : String;
+
+begin
+  S:=Trim(Cmd);
+  InQuote:=False;
+  LastQuote:=#0;
+  I:=1;
+  While (I<=Length(S)) and (Inquote or not (S[I] in whiteSpace)) do
+    begin
+    If S[i] in QuoteChars then
+      begin
+      InQuote:=Not (S[i]=LastQuote);
+      If InQuote then
+         LastQuote:=S[i]
+       else
+         LastQuote:=#0;
+      end;
+    Inc(I);
+    end;
+  Exe:=Copy(S,1,I-1);
+  Delete(S,1,I);
+  Options:=Trim(S);
+end;
+
+{ TNamedItem }
+
+procedure TNamedItem.SetName(const AValue: String);
+
+begin
+  if FName=AValue then exit;
+  With TNamedCollection(Collection) do
+    If UniqueNames then
+      If (IndexOfName(AVAlue)<>-1) then
+        Raise ECollectionError.CreateFmt(SErrNameExists,[AValue]);
+  FName:=AValue;
+end;
+
+{ TNamedCollection }
+
+function TNamedCollection.IndexOfName(AName: String): Integer;
+
+begin
+  Result:=Count-1;
+  While (Result>=0) and (CompareText(TNamedItem(Items[Result]).FName,AName)<>0) do
+    Dec(Result);
+end;
+
+function TNamedCollection.ItemByName(AName: String): TNamedItem;
+
+Var
+  I : Integer;
+
+begin
+  I:=IndexOfName(AName);
+  If (I=-1) Then
+    Raise ECollectionError.CreateFmt(SErrNoSuchName,[AName]);
+  Result:=TNamedItem(Items[i]);
+end;
+
+
+{ TTargets }
+
+function TTargets.GetTargetItem(Index : Integer): TTarget;
+begin
+  Result:=TTarget(Items[Index]);
+end;
+
+function TTargets.GetTarget(AName : String): TTarget;
+begin
+  Result:=TTarget(ItemByName(AName));
+end;
+
+procedure TTargets.SetDefaultDir(const AValue: String);
+begin
+  If (AValue<>'') then
+    FDefaultDir:=IncludeTrailingPathDelimiter(AValue)
+  else
+    FDefaultDir:='';
+end;
+
+procedure TTargets.SetTargetItem(Index : Integer; const AValue: TTarget);
+
+begin
+  Items[Index]:=AValue;
+end;
+
+procedure TTargets.ApplyDefaults(ATarget: TTarget);
+begin
+  If (ATarget.Directory='') then
+    ATarget.Directory:=FDefaultDir;
+   ATarget.OS:=FDefaultOS;
+   ATarget.CPU:=FDefaultCPU;
+end;
+
+procedure TTargets.ResetDefaults;
+begin
+  FDefaultDir:='';
+  FDefaultOS:=[];
+  FDefaultCPU:=[];
+end;
+
+Function TTargets.AddUnit(AUnitName: String) : TTarget;
+
+
+begin
+  Result:=Add as TTarget;
+  Result.Name:=AUnitName;
+  Result.TargetType:=TTUnit;
+  ApplyDefaults(Result);
+end;
+
+Function TTargets.AddProgram(AProgramName: String) : TTarget;
+begin
+  Result:=Add as TTarget;
+  Result.Name:=AProgramName;
+  Result.TargetType:=ttProgram;
+  ApplyDefaults(Result);
+end;
+
+Function TTargets.AddExampleUnit(AUnitName: String): TTarget;
+begin
+  Result:=Add as TTarget;
+  Result.Name:=AUnitName;
+  Result.TargetType:=ttExampleUnit;
+  ApplyDefaults(Result);
+end;
+
+Function TTargets.AddExampleProgram(AProgramName: String): TTarget;
+begin
+  Result:=Add as TTarget;
+  Result.Name:=AProgramName;
+  Result.TargetType:=ttExampleProgram;
+  ApplyDefaults(Result);
+end;
+
+
+{ TNamedItemList }
+
+function TNamedItemList.GetNamedItem(Index : Integer): TNamedItem;
+begin
+  Result:=TNamedItem(Items[Index]);
+end;
+
+procedure TNamedItemList.SetNamedItem(Index : Integer; const AValue: TNamedItem);
+begin
+  Items[Index]:=AValue;
+end;
+
+function TNamedItemList.IndexOfName(AName: String): Integer;
+
+begin
+  Result:=Count-1;
+  While (Result>=0) and (CompareText(GetNamedItem(Result).Name,AName)<>0) do
+    Dec(Result);
+end;
+
+function TNamedItemList.ItemByName(ANAme: String): TNamedItem;
+
+Var
+  I : Integer;
+
+begin
+  I:=IndexOfName(AName);
+  If (I=-1) Then
+    Raise ECollectionError.CreateFmt(SErrNoSuchName,[AName]);
+  Result:=TNamedItem(Items[i]);
+end;
+
+{ TDefaults }
+
+procedure TDefaults.SetCPU(const AValue: TCPU);
+begin
+  FCPU:=AValue;
+  RecalcTarget;
+end;
+
+function TDefaults.GetBaseInstallDir: String;
+begin
+  If (FBaseInstallDir<>'') then
+    Result:=FBaseInstallDir
+  else
+    if UnixPaths then
+      Result:=Prefix+PathDelim+'lib'+PathDelim+'fpc'
+    else
+      Result:=Prefix;
+
+end;
+
+function TDefaults.GetBinInstallDir: String;
+begin
+  If (FBinInstallDir<>'') then
+    Result:=FBinInstallDir
+  else
+    If UnixPaths then
+      Result:=BaseInstallDir+PathDelim+'bin'
+    else
+      Result:=BaseInstallDir+PathDelim+'bin';
+end;
+
+function TDefaults.GetCompiler: String;
+begin
+  If (FCompiler<>'') then
+    Result:=FCompiler
+  else
+    Case CPU of
+      i386    : Result:='ppc386';
+      PowerPC : Result:='ppcppc';
+      sparc   : Result:='ppcsparc';
+      arm     : Result:='ppcarm';
+      x86_64  : Result:='ppcx64';
+    end;
+end;
+
+function TDefaults.GetDocInstallDir: String;
+begin
+  If (FBinInstallDir<>'') then
+    Result:=FBinInstallDir
+  else
+    If UnixPaths then
+      Result:=Prefix+PathDelim+'share'+PathDelim+'docs'
+    else
+      Result:=BaseInstallDir+PathDelim+'docs';
+end;
+
+function TDefaults.GetExamplesInstallDir: String;
+begin
+  If (FExamplesInstallDir<>'') then
+    Result:=FExamplesInstallDir
+  else
+    If UnixPaths then
+      Result:=Prefix+PathDelim+'share'+PathDelim+'docs'+PathDelim+'examples'
+    else
+      Result:=BaseInstallDir+PathDelim+'examples';
+end;
+
+function TDefaults.GetUnitInstallDir: String;
+begin
+  If (FUnitInstallDir<>'') then
+    Result:=FBinInstallDir
+  else
+    If UnixPaths then
+      Result:=BaseInstallDir+PathDelim+'units'+PathDelim+Target
+    else
+      Result:=BaseInstallDir+PathDelim+'units'+PathDelim+Target;
+end;
+
+procedure TDefaults.SetBaseInstallDir(const AValue: String);
+begin
+  FBaseInstallDir:=AValue;
+  UnitInstallDir:='';
+  BinInstallDir:='';
+  ExamplesInstallDir:='';
+end;
+
+procedure TDefaults.SetOS(const AValue: TOS);
+begin
+  FOS:=AValue;
+  Recalctarget;
+end;
+
+procedure TDefaults.SetPrefix(const AValue: String);
+begin
+  if FPrefix=AValue then exit;
+  FPrefix:=AValue;
+  BaseInstallDir:='';
+end;
+
+procedure TDefaults.SetTarget(const AValue: String);
+
+Var
+  P : Integer;
+
+begin
+  if FTarget<>AValue then
+    begin
+    P:=Pos('-',AValue);
+    If (P<>0) then
+      begin
+      FOS:=StringToOS(System.Copy(Avalue,P+1,Length(AValue)-P));
+      FCPU:=StringToCPU(System.Copy(Avalue,1,P-1));
+      end
+    else
+      FOS:=StringToOS(AValue);
+    FTarget:=AValue;
+    end;
+end;
+
+procedure TDefaults.RecalcTarget;
+begin
+  Ftarget:=CPUToString(FCPU)+'-'+OStoString(FOS);
+end;
+
+constructor TDefaults.Create;
+begin
+  InitDefaults;
+end;
+
+procedure TDefaults.InitDefaults;
+begin
+  {$ifdef unix}
+  UnixPaths:=True;
+  {$else}
+  UnixPaths:=False;
+  {$endif}
+  // Code to init defaults for compiled platform.
+  CPU:=StringToCPU({$I %FPCTARGETCPU%});
+  OS:=StringToOS({$I %FPCTARGETOS%});
+  Compiler:='ppc386';
+end;
+
+procedure TDefaults.Assign(ASource: TPersistent);
+
+Var
+  d : TDefaults;
+
+begin
+  If ASource is TDefaults then
+    begin
+    D:=ASource as TDefaults;
+    FArchive:=D.Farchive;
+    FCompiler:=D.Compiler;
+    FCopy:=D.FCopy;
+    FCPU:=D.FCPU;
+    FMode:=D.FMode;
+    FMkDir:=D.FMkDir;
+    FMove:=D.FMove;
+    FOptions:=D.FOptions;
+    FOS:=D.FOS;
+    FPrefix:=D.FPrefix;
+    FBaseInstallDir:=D.FBaseInstallDir;
+    FUnitInstallDir:=D.FUnitInstallDir;
+    FBinInstallDir:=D.FBinInstallDir;
+    FDocInstallDir:=D.FDocInstallDir;
+    FExamplesInstallDir:=D.FExamplesInstallDir;
+    FRemove:=D.FRemove;
+    FTarget:=D.FTarget;
+    FUnixPaths:=D.FUnixPaths;
+    end;
+end;
+
+procedure TDefaults.LocalInit(Const AFileName : String);
+
+Var
+  FN : String;
+
+begin
+  FN:=AFileName;
+  If (FN='') then
+    begin
+    // Environment variable.
+    FN:=GetEnvironmentVariable('FPMAKECFG');
+    If (FN<>'') then
+      If not FileExists(FN) then
+        FN:='';
+    // User config file fpmake.cfg
+    If (FN='') then
+      begin
+      FN:=GetAppConfigFile(False);
+      If Not FileExists(FN) then
+        FN:='';
+      end;
+    // Global config file fpmake.cfg
+    If (FN='') then
+      begin
+      FN:=GetAppConfigFile(True);
+      If Not FileExists(FN) then
+        FN:='';
+      end;
+    end;
+  If (FN<>'') and FileExists(FN) then
+    LoadFromFile(FN)
+  // Code to find local config file and load it using LoadFromFile.
+end;
+
+procedure TDefaults.LoadFromFile(Const AFileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(AFileName,fmOpenRead);
+  Try
+    LoadFromStream(F);
+  Finally
+    F.Free;
+  end;
+end;
+
+procedure TDefaults.SaveToFile(Const AFileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(AFileName,fmCreate);
+  Try
+    SaveToStream(F);
+  Finally
+    F.Free;
+  end;
+end;
+
+procedure TDefaults.SaveToStream(S : TStream);
+
+Var
+  L : TStringList;
+
+begin
+  L:=TStringList.Create;
+  try
+    With L do
+      begin
+      Values[KeyArchive]:=FArchive;
+      Values[KeyCompiler]:=FCompiler;
+      Values[KeyCopy]:=FCopy;
+      Values[KeyMkDir]:=FMkDir;
+      Values[KeyMove]:=FMove;
+      Values[KeyOptions]:=FOptions;
+      Values[KeyCPU]:=CPUToString(FCPU);
+      Values[KeyOS]:=OSToString(FOS);
+      Values[KeyMode]:=ModeToString(FMode);
+      Values[KeyPrefix]:=FPrefix;
+      Values[KeyBaseInstallDir]:=FBaseInstallDir;
+      Values[KeyUnitInstallDir]:=FUnitInstallDir;
+      Values[KeyBinInstallDir]:=FBinInstallDir;
+      Values[KeyDocInstallDir]:=FDocInstallDir;
+      Values[KeyExamplesInstallDir]:=FExamplesInstallDir;
+      Values[KeyRemove]:=FRemove;
+      Values[KeyTarget]:=FTarget;
+      end;
+    L.SaveToStream(S);
+  Finally
+    L.Free;
+  end;
+end;
+
+procedure TDefaults.LoadFromStream(S: TStream);
+
+Var
+  L : TStrings;
+  Line : String;
+  I,P,PC : Integer;
+  
+  
+begin
+  L:=TStringList.Create;
+  Try
+    L.LoadFromStream(S);
+    // Fix lines.
+    For I:=L.Count-1 downto 0 do
+      begin
+      Line:=L[I];
+      P:=Pos('=',Line);
+      PC:=Pos(';',Line);  // Comment line.
+      If (P=0) or ((PC<>0) and (PC<P)) then
+        L.Delete(I)
+      else
+        L[i]:=Trim(System.Copy(Line,1,P-1)+'='+Trim(System.Copy(Line,P+1,Length(Line)-P)));
+      end;
+    With L do
+      begin
+      FArchive:=Values[KeyArchive];
+      FCompiler:=Values[KeyCompiler];
+      FCopy:=Values[KeyCopy];
+      FMkDir:=Values[KeyMkDir];
+      FMove:=Values[KeyMove];
+      FRemove:=Values[KeyRemove];
+      FOptions:=Values[KeyOptions];
+      Line:=Values[KeyCPU];
+      If (Line<>'') then
+        FCPU:=StringToCPU(Line);
+      Line:=Values[KeyOS];
+      If (Line<>'') then
+        FOS:=StringToOS(Line);
+      Line:=Values[KeyMode];
+      If (Line<>'') then
+        FMode:=StringToMode(Line);
+      FTarget:=Values[KeyTarget];
+      FPrefix:=Values[KeyPrefix];
+      FBaseInstallDir:=Values[KeyBaseInstallDir];
+      FUnitInstallDir:=Values[KeyUnitInstallDir];
+      FBinInstallDir:=Values[KeyBinInstallDir];
+      FDocInstallDir:=Values[KeyDocInstallDir];
+      FExamplesInstallDir:=Values[KeyExamplesInstallDir];
+      end;
+  Finally
+    L.Free;
+  end;
+end;
+
+{ TPackage }
+
+function TPackage.GetHasStrings(AIndex: integer): Boolean;
+begin
+  Result:=False;
+  Case AIndex Of
+    0 : Result:=FUnitPath<>Nil;
+    1 : Result:=FObjectPath<>Nil;
+    2 : Result:=FIncludePath<>Nil;
+    3 : Result:=FDependencies<>Nil;
+    4 : Result:=FInstallFiles<>Nil;
+    5 : Result:=FCleanFiles<>Nil;
+    6 : Result:=FArchiveFiles<>Nil;
+  end;
+end;
+
+function TPackage.GetCommands: TCommands;
+begin
+  If Not Assigned(FCommands) then
+    FCommands:=TCommands.Create(TCommand);
+  Result:=FCommands;
+end;
+
+function TPackage.GetHasCommands: Boolean;
+begin
+  Result:=Assigned(FCommands);
+end;
+
+Procedure SplitVersion(AValue: String; Var Release,Major,Minor : Word; Var Suffix : String);
+
+  Function NextDigit(sep : Char; var V : string) : integer;
+
+  Var
+    P : Integer;
+
+  begin
+    P:=Pos(Sep,V);
+    If (P=0) then
+      P:=Length(V)+1;
+    Result:=StrToIntDef(Copy(V,1,P-1),-1);
+    If Result<>-1 then
+      Delete(V,1,P)
+    else
+      Result:=0;
+  end;
+
+Var
+  P : Integer;
+  V : String;
+
+begin
+  Release:=0;
+  Major:=0;
+  Minor:=0;
+  Suffix:='';
+  V:=AValue;
+  Release:=NextDigit('.',V);
+  Major:=NextDigit('.',V);
+  Minor:=NextDigit('-',V);
+  P:=Pos('-',V);
+  If (P<>0) then
+    Delete(V,1,P);
+  Suffix:=V;
+end;
+
+Function QuoteXML(S : String) : string;
+
+  Procedure W(Var J : Integer; Var R : String; T : String);
+  
+  Var
+    I: integer;
+  
+  begin
+    If J+Length(T)>Length(R) then
+      SetLength(R,J+Length(T));
+    For I:=1 to Length(t) do
+      begin
+      R[J]:=T[i];
+      If I<Length(T) then
+        Inc(J);
+      end;
+  end;
+
+const
+  QuotStr = '&quot;';
+  AmpStr = '&amp;';
+  ltStr = '&lt;';
+  gtStr = '&gt;';
+
+Var
+  I,J : Integer; 
+ 
+begin
+  SetLength(Result,Length(S));
+  J:=0;
+  For I:=1 to Length(S) do
+    begin
+    Inc(J);
+    case S[i] of
+      '"': W(j,Result,QuotStr);
+      '&': W(J,Result,AmpStr);
+      '<': W(J,Result,ltStr);
+      // Escape whitespace using CharRefs to be consistent with W3 spec X 3.3.3
+       #9: w(J,Result,'&#x9;');
+{      #10: wrtStr('&#xA;');
+       #13: wrtStr('&#xD;');}
+    else
+      Result[J]:=S[i];
+    end;  
+    If (J=Length(Result)) and (I<Length(S)) then  
+      SetLength(Result,J+Length(S)-I);
+    end;
+  If J<>Length(Result) then  
+    SetLength(Result,J);  
+end;
+                                              
+                  
+
+Procedure TPackage.GetManifest(Manifest : TStrings);
+  
+
+Var
+  S : String;
+  Release,Minor,Major : Word;
+  i : integer;
+  
+begin
+  With Manifest do
+    begin
+    Add(Format('<package name="%s">',[QuoteXml(Name)]));
+    SplitVersion(Version,Release,Minor,Major,S);
+    Add(Format('<version release="%d" major="%d" minor="%d" suffix="%s"/>',[Release,Minor,Major,QuoteXMl(S)]));
+    Add(Format('<author>%s</author>',[QuoteXml(Author)]));
+    Add(Format('<url>%s</url>',[QuoteXml(URL)]));
+    Add(Format('<email>%s</email>',[QuoteXMl(Email)]));
+    S:=Description;
+    If (S<>'') then
+      Add(Format('<description>%s</description>',[QuoteXML(S)]));
+    if HasDependencies then
+      begin
+      If (Dependencies.Count>0) then
+        begin
+        Add('<dependencies>');
+        for I:=0 to Dependencies.Count-1 do
+          begin
+          Add(Format('<dependency><package packagename=""/></dependency>',[QuoteXML(Dependencies[i])]));
+          end;
+        Add('</dependencies>');
+        end;
+      end;  
+    Add('</package>');
+    end;
+end;
+
+function TPackage.GetStrings(AIndex: integer): TStrings;
+
+  Function EnsureStrings(Var S : TStrings) : TStrings;
+
+  begin
+    If (S=Nil) then
+      S:=TStringList.Create;
+    Result:=S;
+  end;
+
+begin
+  Result:=Nil;
+  Case AIndex Of
+    0 : Result:=EnsureStrings(FUnitPath);
+    1 : Result:=EnsureStrings(FObjectPath);
+    2 : Result:=EnsureStrings(FIncludePath);
+    3 : begin
+        Result:=EnsureStrings(FDependencies);
+        With TStringList(Result) do
+          if (Count=0) then
+            begin
+            Sorted:=True;
+            Duplicates:=dupError;
+            end;
+        end;
+    4 : Result:=EnsureStrings(FInstallFiles);
+    5 : Result:=EnsureStrings(FCleanFiles);
+    6 : Result:=EnsureStrings(FArchiveFiles);
+  end;
+end;
+
+procedure TPackage.SetCommands(const AValue: TCommands);
+begin
+  Commands.Assign(AValue);
+end;
+
+procedure TPackage.SetStrings(AIndex: integer; const AValue: TStrings);
+begin
+  GetStrings(AIndex).Assign(AValue);
+end;
+
+constructor TPackage.Create(ACollection: TCollection);
+
+Var
+  L : TStringList;
+
+begin
+  inherited Create(ACollection);
+  FTargets:=TTargets.Create(TTarget);
+  L:=TStringList.Create;
+  FDependencies:=L;
+  FInstallFiles:=TStringList.Create;
+  FCleanFiles:=TStringList.Create;
+  FArchiveFiles:=TStringList.Create;
+end;
+
+destructor TPackage.destroy;
+begin
+  FreeAndNil(FDependencies);
+  FreeAndNil(FInstallFiles);
+  FreeAndNil(FCleanFiles);
+  FreeAndNil(FArchiveFiles);
+  FreeAndNil(FIncludePath);
+  FreeAndNil(FObjectPath);
+  FreeAndNil(FUnitPath);
+  FreeAndNil(FTargets);
+  inherited destroy;
+end;
+
+function TPackage.AddTarget(AName: String): TTarget;
+begin
+  Result:=Targets.Add as TTarget;
+  Result.Name:=AName;
+end;
+
+procedure TPackage.AddDependency(AName: String);
+begin
+  If FDependencies.IndexOf(AName)=-1 then
+    FDependencies.Add(AName);
+end;
+
+procedure TPackage.AddInstallFile(AFileName: String);
+begin
+  FInstallFiles.add(AFileName);
+end;
+
+procedure TPackage.GetCleanFiles(List: TStrings; Const APrefix : String; AOS : TOS);
+
+Var
+  I : Integer;
+
+begin
+  AddStrings(List,CleanFiles,APrefix);
+  For I:=0 to FTargets.Count-1 do
+    FTargets.TargetItems[I].GetCleanFiles(List,APrefix,AOS);
+end;
+
+procedure TPackage.GetInstallFiles(List: TStrings;Types : TTargetTypes;Const APrefix : String; AOS : TOS);
+
+Var
+  I : Integer;
+  T : TTarget;
+
+begin
+  AddStrings(List,InstallFiles,APrefix);
+  For I:=0 to FTargets.Count-1 do
+    begin
+    T:=FTargets.TargetItems[I];
+    if (T.TargetType in Types)  then
+      T.GetInstallFiles(List,APrefix,AOS);
+    end;
+end;
+
+
+procedure TPackage.GetArchiveFiles(List: TStrings;Const APrefix : String; AOS : TOS);
+
+Var
+  I : Integer;
+
+begin
+  If (OS=[]) or (AOS in OS) then
+    begin
+    AddStrings(List,ArchiveFiles,APrefix);
+    For I:=0 to FTargets.Count-1 do
+      FTargets.TargetItems[I].GetArchiveFiles(List,APrefix,AOS);
+    end;
+end;
+
+Function TPackage.GetDescription : string;
+
+Var
+  FN : String;
+  L : TStringList;
+
+begin
+  If (FDescription<>'') then
+    Result:=FDescription
+  else
+    If (FDescriptionFile<>'') then
+      begin
+      // Always relative to binary name.
+      FN:=ExtractFilePath(ParamStr(0));
+      FN:=FN+FDescriptionFile;
+      If FileExists(FN) then
+        begin
+        L:=TStringList.Create;
+        Try
+          L.LoadFromFile(FN);
+          Result:=L.Text;
+        Finally
+          L.Free;  
+        end;
+        end;
+      end;
+end;
+
+
+{ TPackages }
+
+function TPackages.GetPackage(AName : String): TPackage;
+begin
+  Result:=TPackage(ItemByName(AName))
+end;
+
+function TPackages.GetPackageItem(AIndex : Integer): TPackage;
+begin
+  Result:=TPackage(Items[AIndex]);
+end;
+
+procedure TPackages.SetPackageItem(AIndex : Integer; const AValue: TPackage);
+begin
+  Items[AIndex]:=AValue;
+end;
+
+function TPackages.AddPackage(const AName: String): TPackage;
+begin
+  Result:=Add as TPackage;
+  Result.Name:=AName;
+end;
+
+
+{ TInstaller }
+
+function TInstaller.GetStrings(AIndex : Integer): TStrings;
+begin
+  CheckDefaultPackage;
+  Case AIndex of
+    0:  Result:=DefaultPackage.Dependencies;
+    1:  Result:=DefaultPackage.InstallFiles;
+    2:  Result:=DefaultPackage.CleanFiles;
+    3:  Result:=DefaultPackage.ArchiveFiles;
+  end;
+end;
+
+Function TInstaller.GetPackageString(Index : Integer) : String;
+
+Var
+  P : TPackage;
+
+
+begin
+  CheckDefaultPackage;
+  P:=DefaultPackage;
+  Case Index of
+    0 : Result:=P.Author;
+    1 : Result:=P.Directory;
+    2 : Result:=P.License;
+    3 : Result:=P.Options;
+    4 : Result:=P.URL;
+    5 : Result:=P.Email;
+    6 : Result:=P.Description;
+    7 : Result:=P.DescriptionFile;
+    8 : Result:=P.Version;
+  end;
+end;
+
+
+Procedure TInstaller.SetPackageString(Index : Integer; AValue : String);
+
+Var
+  P : TPackage;
+
+begin
+  CheckDefaultPackage;
+  P:=DefaultPackage;
+  Case Index of
+    0 : P.Author:=AValue;
+    1 : P.Directory:=AValue;
+    2 : P.License:=AValue;
+    3 : P.Options:=AValue;
+    4 : P.URL:=AValue;
+    5 : P.Email:=AValue;
+    6 : P.Description:=AValue;
+    7 : P.DescriptionFile:=AValue;
+    8 : P.Version:=AValue;
+  end;
+end;
+
+
+function TInstaller.GetOSes: TOSes;
+begin
+  CheckDefaultPackage;
+  Result:=DefaultPackage.OS;
+end;
+
+function TInstaller.GetTargets: TTargets;
+begin
+  CheckDefaultPackage;
+  Result:=DefaultPackage.Targets;
+end;
+
+procedure TInstaller.SetDefaultPackage(const AValue: TPackage);
+begin
+  if FDefaultPackage=AValue then exit;
+  FDefaultPackage:=AValue;
+end;
+
+procedure TInstaller.SetDefaults(const AValue: TDefaults);
+begin
+  FDefaults.Assign(AValue);
+end;
+
+procedure TInstaller.SetStrings(AIndex : Integer; const AValue: TStrings);
+
+Var
+  Res : TStrings;
+
+begin
+  CheckDefaultPackage;
+  Case AIndex of
+    0:  Res:=DefaultPackage.Dependencies;
+    1:  Res:=DefaultPackage.InstallFiles;
+    2:  Res:=DefaultPackage.CleanFiles;
+    3:  Res:=DefaultPackage.ArchiveFiles;
+  end;
+  Res.Assign(Avalue);
+end;
+
+procedure TInstaller.SetOses(const AValue: TOSes);
+begin
+  CheckDefaultPackage;
+  DefaultPackage.OS:=AValue;
+end;
+
+procedure TInstaller.Log(Level: TVerboseLevel; const Msg: String);
+begin
+  If Level in FLogLevels then
+    Writeln(StdErr,Msg);
+end;
+
+procedure TInstaller.CreatePackages;
+begin
+  FPAckages:=TPackages.Create(TPackage);
+end;
+
+procedure TInstaller.CreateBuildEngine;
+begin
+  FBuildEngine:=TBuildEngine.Create(Self);
+  FBuildEngine.Defaults:=Defaults;
+  FBuildEngine.ListMode:=FListMode;
+  FBuildEngine.OnLog:[email protected];
+end;
+
+procedure TInstaller.CheckDefaultPackage;
+begin
+  If (FDefaultPackage=Nil) then
+    Raise EInstallerError.Create(SErrNoPackage);
+end;
+
+procedure TInstaller.Error(Msg: String);
+begin
+  Raise EInstallerError.Create(Msg);
+end;
+
+procedure TInstaller.Error(Fmt: String; Args: array of const);
+begin
+  Raise EInstallerError.CreateFmt(Fmt,Args);
+end;
+
+Function TInstaller.StartPackage(const AName: String) : TPackage;
+begin
+  FDefaultPackage:=FPackages.AddPackage(AName);
+  Result:=FDefaultPackage;
+end;
+
+procedure TInstaller.EndPackage;
+begin
+  FDefaultPackage:=Nil;
+end;
+
+procedure TInstaller.AnalyzeOptions;
+
+  Function CheckOption(Index : Integer;Short,Long : String): Boolean;
+
+  var
+    O : String;
+
+  begin
+    O:=Paramstr(Index);
+    Result:=(O='-'+short) or (O='--'+long) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
+  end;
+
+  Function OptionArg(Var Index : Integer) : String;
+
+  Var
+    P : Integer;
+
+  begin
+    if (Length(ParamStr(Index))>1) and (Paramstr(Index)[2]<>'-') then
+      begin
+      If Index<ParamCount then
+        begin
+        Inc(Index);
+        Result:=Paramstr(Index);
+        end
+      else
+        Error(SErrNeedArgument,[Index,ParamStr(Index)]);
+      end
+    else If length(ParamStr(Index))>2 then
+      begin
+      P:=Pos('=',Paramstr(Index));
+      If (P=0) then
+        Error(SErrNeedArgument,[Index,ParamStr(Index)])
+      else
+        begin
+        Result:=Paramstr(Index);
+        Delete(Result,1,P);
+        end;
+      end;
+  end;
+
+Var
+  I : Integer;
+  Nodefaults : Boolean;
+  DefaultsFileName : string;
+
+begin
+  I:=0;
+  NoDefaults:=False;
+  FListMode:=False;
+  While (I<ParamCount) do
+    begin
+    Inc(I);
+    if Checkoption(I,'m','compile') then
+      FRunMode:=rmCompile
+    else if Checkoption(I,'b','build') then
+      FRunMode:=rmBuild
+    else if CheckOption(I,'i','install') then
+      FRunMode:=rmInstall
+    else if CheckOption(I,'c','clean') then
+      FRunMode:=rmClean
+    else if CheckOption(I,'a','archive') then
+      FRunMode:=rmarchive
+    else if CheckOption(I,'h','help') then
+      FRunMode:=rmHelp
+    else if CheckOption(I,'M','manifest') then
+      FRunMode:=rmManifest
+    else if Checkoption(I,'C','CPU') then
+      Defaults.CPU:=StringToCPU(OptionArg(I))
+    else if Checkoption(I,'O','OS') then
+      Defaults.OS:=StringToOS(OptionArg(I))
+    else if Checkoption(I,'t','target') then
+      Defaults.Target:=OptionArg(I)
+    else if CheckOption(I,'l','list-commands') then
+      FListMode:=True
+    else if Checkoption(I,'P','prefix') then
+      Defaults.Prefix:=OptionArg(I)
+    else if Checkoption(I,'n','nodefaults') then
+      NoDefaults:=true
+    else if CheckOption(I,'B','baseinstalldir') then
+      Defaults.BaseInstallDir:=OptionArg(I)
+    else if CheckOption(I,'r','compiler') then
+      Defaults.Compiler:=OptionArg(I)
+    else if CheckOption(I,'f','config') then
+      DefaultsFileName:=OptionArg(I)
+    else if CheckOption(I,'v','verbose') then
+      begin
+      Try
+        FLogLevels:=TVerboseLevels(StringToSet(PtypeInfo(TypeInfo(TVerboseLevels)),OptionArg(I)));
+      except
+        FLogLevels:=AllMessages;
+      end;
+      end
+    else
+      begin
+      Usage(SErrInValidArgument,[I,ParamStr(I)]);
+      end;
+    end;
+  If Not NoDefaults then
+    Defaults.LocalInit(DefaultsFileName);
+{$ifdef debug}
+  FLogLevels:=AllMessages;
+{$endif}
+end;
+
+
+
+procedure TInstaller.Usage(FMT: String; Args: array of const);
+
+  Procedure WriteCmd(C: Char; LC : String; Msg : String);
+  
+  begin
+    Writeln(stderr,'-',C,'  --',LC,'   ',MSG);
+  end;
+  
+  Procedure WriteOption(C: Char; LC : String; Msg : String);
+  
+  begin
+    Writeln(stderr,'-',C,'  --',LC,'=',SValue,'  ',MSG);
+  end;
+
+begin
+  If (FMT<>'') then
+    Writeln(stderr,Format(Fmt,Args));
+  Writeln(stderr,ExtractFileName(Paramstr(0)),' usage: ');
+  Writeln(stderr,SHelpUsage);
+  Writeln(stderr,SHelpCommand);
+  WriteCmd('m','compile',SHelpCompile);
+  WriteCmd('b','build',SHelpBuild);
+  WriteCmd('i','install',SHelpInstall);
+  WriteCmd('c','clean',SHelpClean);
+  WriteCmd('a','archive',SHelpArchive);
+  WriteCmd('h','help',SHelpHelp);
+  WriteCmd('M','manifest',SHelpManifest);
+  Writeln(stderr,SHelpCmdOptions);
+  WriteCmd('l','list-commands',SHelpList);
+  WriteCmd('n','nodefaults',SHelpNoDefaults);
+  WriteCmd('v','verbose',SHelpVerbose);
+  WriteOption('C','CPU',SHelpCPU);
+  WriteOption('O','OS',SHelpOS);
+  WriteOption('t','target',SHelpTarget);
+  WriteOption('P','prefix',SHelpPrefix);
+  WriteOption('B','baseinstalldir',SHelpBaseInstalldir);
+  WriteOption('r','compiler',SHelpCompiler);
+  WriteOption('f','config',SHelpConfig);
+  Writeln(stderr,'');
+  If (FMT<>'') then
+    halt(1);
+end;
+
+procedure TInstaller.Compile(Force: Boolean);
+begin
+  FBuildEngine.ForceCompile:=Force;
+  FBuildEngine.Compile(FPackages);
+end;
+
+procedure TInstaller.Clean;
+begin
+  BuildEngine.Clean(FPackages);
+end;
+
+procedure TInstaller.Install;
+begin
+  BuildEngine.Install(FPackages);
+end;
+
+procedure TInstaller.Archive;
+begin
+  FBuildEngine.Archive(FPackages);
+end;
+
+procedure TInstaller.Manifest;
+
+Var
+  L : TStrings;
+  I : Integer;
+  
+begin
+  L:=TStringList.Create;
+  Try
+    L.Add('<?xml version="1.0"?>');
+    BuildEngine.GetManifest(FPackages,L);
+    For I:=0 to L.Count-1 do
+      Writeln(L[i]);
+  Finally
+    L.Free;
+  end;    
+end;
+
+constructor TInstaller.Create(AOWner: TComponent);
+begin
+  inherited Create(AOWner);
+  FDefaults:=TDefaults.Create;
+  AnalyzeOptions;
+  CreatePackages;
+end;
+
+destructor TInstaller.destroy;
+begin
+  FreeAndNil(FDefaults);
+  inherited destroy;
+end;
+
+procedure TInstaller.CheckPackages;
+
+begin
+  If (FPackages.Count=0) then
+    Error(SErrNoPackagesDefined);
+  // Check for other obvious errors ?
+end;
+
+Function TInstaller.Run : Boolean;
+
+begin
+  Result:=True;
+  try
+    If RunMode<>rmHelp then
+      begin
+      CheckPackages;
+      CreateBuildEngine;
+      end;
+    Case RunMode of
+      rmHelp    : Usage('',[]);
+      rmCompile : Compile(False);
+      rmBuild   : Compile(True);
+      rmInstall : Install;
+      rmArchive : Archive;
+      rmClean    : Clean;
+      rmManifest : Manifest;
+    end;
+  except
+    On E : Exception do
+      begin
+      Writeln(StdErr,SErrInstaller);
+      Writeln(StdErr,E.Message);
+      Result:=False;
+      end;
+  end;
+end;
+
+function TInstaller.AddTarget(AName: String): TTarget;
+begin
+  CheckDefaultPackage;
+  Result:=DefaultPackage.AddTarget(AName);
+end;
+
+procedure TInstaller.AddDependency(AName: String);
+begin
+  CheckDefaultPackage;
+  DefaultPackage.AddDependency(AName);
+end;
+
+{ TBuildEngine }
+
+procedure TBuildEngine.SetDefaults(const AValue: TDefaults);
+begin
+  FDefaults.Assign(AValue);
+end;
+
+procedure TBuildEngine.SetTargetDir(const AValue: String);
+begin
+  if FTargetDir=AValue then exit;
+  FTargetDir:=AValue;
+end;
+
+procedure TBuildEngine.Error(Msg: String);
+begin
+  Raise EInstallerError.Create(Msg);
+end;
+
+procedure TBuildEngine.Error(Fmt: String; Args: array of const);
+begin
+  Raise EInstallerError.CreateFmt(Fmt,Args);
+end;
+
+constructor TBuildEngine.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FDefaults:=TDefaults.Create;
+  // Maybe this should be the current directory ?
+  // Or have it as a command-line option.
+  // Would allow to put all 'installers' in one dir and call them
+  // With --start-dir=/path/to/sources.
+  FStartDir:=includeTrailingPathDelimiter(GetCurrentDir);
+end;
+
+procedure TBuildEngine.ExecuteCommand(Cmd: String; Args : String; IgnoreError : Boolean = False);
+
+Var
+  E : Integer;
+
+begin
+  Log(vlCommand,SLogExecutingCommand,[Cmd,Args]);
+  // We should check cmd for spaces, and move all after first space to args.
+  E:=ExecuteProcess(cmd,args);
+  If (E<>0) and (not IgnoreError) then
+    Error(SErrExternalCommandFailed,[Cmd,E]);
+end;
+
+procedure TBuildEngine.SysCopyFile(Const Src,Dest : String);
+
+Var
+  D,S : String;
+  Fin,FOut : TFileStream;
+  Count : Int64;
+  A : Integer;
+  
+begin
+  Log(vlCommand,SLogCopyingFile,[Src,Dest]);
+  FIn:=TFileStream.Create(Src,fmopenRead);
+  Try
+    D:=IncludeTrailingPathDelimiter(Dest);
+    If DirectoryExists(D) then
+      S:=D+ExtractFileName(Src)
+    else
+      S:=Dest;
+    FOut:=TFileStream.Create(S,fmCreate);
+    Try
+      Count:=Fout.CopyFrom(FIn,0);
+      If (Count<>Fin.Size) then
+        Error(SErrCopyingFile,[Src,S]);
+    Finally
+      FreeAndNil(Fout);
+    end;
+    A:=FileGetDate(FIn.Handle);
+    If (A=-1) then
+      log(vlWarning,SWarnFailedToGetTime,[Src])
+    else
+      if FileSetDate(S,A)<>0 then
+        Log(vlWarning,SWarnFailedToSetTime,[S]);
+  finally
+    FreeAndNil(Fin);
+  end;
+end;
+
+procedure TBuildEngine.SysMoveFile(Const Src,Dest : String);
+
+Var
+  S : String;
+
+begin
+    If DirectoryExists(IncludeTrailingPathDelimiter(Dest)) then
+      S:=IncludeTrailingPathDelimiter(Dest)+ExtractFileName(Src)
+    else
+      S:=Dest;
+  If Not RenameFile(Src,S) then
+    begin
+    Try
+      SysCopyFile(Src,S);
+      SysDeleteFile(Src);
+    Except
+      On E : Exception Do
+        Error(SErrMovingFile,[Src,S]);
+    end;
+    end;
+end;
+
+procedure TBuildEngine.SysDeleteFile(Const AFileName : String);
+
+begin
+  if not FileExists(AFileName) then
+    Log(vlWarning,SWarnFileDoesNotExist,[AFileName])
+  else If Not DeleteFile(AFileName) then
+    Error(SErrDeletingFile,[AFileName]);
+end;
+
+
+procedure TBuildEngine.SysArchiveFiles(List: TStrings;Const AFileName: String);
+begin
+  If Not (Assigned(OnArchivefiles) or Assigned(ArchiveFilesProc)) then
+    Raise EInstallerError.Create(SErrNoArchiveSupport);
+  If Assigned(ArchiveFilesProc) then
+    ArchiveFilesProc(AFileName,List)
+  else
+    OnArchiveFiles(AFileName,List);
+end;
+
+procedure TBuildEngine.Log(Level: TVerboseLevel; const Msg: String);
+begin
+  If Assigned(FOnLog) then
+    FOnLog(Level,Msg);
+end;
+
+procedure TBuildEngine.Log(Level: TVerboseLevel; const Fmt: String;
+  Args: array of const);
+begin
+  Log(Level,Format(Fmt,Args));
+end;
+
+procedure TBuildEngine.EnterDir(ADir: String);
+
+Var
+  D : String;
+
+begin
+  D:=FStartDir;
+  D:=D+ADir;
+  Log(vlInfo,SLogEnterDir,[D]);
+  If Not SetCurrentDir(D) then
+    Error(SErrChangeDirFailed,[D]);
+end;
+
+
+procedure TBuildEngine.CmdCopyFiles(List: TStrings; Const DestDir: String);
+
+Var
+  Args : String;
+  I : Integer;
+
+begin
+  CmdCreateDir(DestDir);
+  If (Defaults.Copy<>'') then
+    begin
+    Args:=FileListToString(List,'');
+    Args:=Args+' '+DestDir;
+    ExecuteCommand(Defaults.Copy,Args);
+    end
+  else
+    For I:=0 to List.Count-1 do
+      SysCopyFile(List[i],DestDir);
+end;
+
+procedure TBuildEngine.CmdCreateDir(DestDir: String);
+
+begin
+  If (Defaults.MkDir<>'') then
+    ExecuteCommand(Defaults.MkDir,DestDir)
+  else
+    If not ForceDirectories(DestDir) then
+      Error(SErrCreatingDirectory,[DestDir]);
+end;
+
+procedure TBuildEngine.CmdMoveFiles(List: TStrings; Const DestDir: String);
+
+Var
+  Args : String;
+  I : Integer;
+
+begin
+  CmdCreateDir(DestDir);
+  If (Defaults.Move<>'') then
+    begin
+    Args:=FileListToString(List,'');
+    Args:=Args+' '+DestDir;
+    ExecuteCommand(Defaults.Move,Args);
+    end
+  else
+    For I:=0 to List.Count-1 do
+      SysMoveFile(List[i],DestDir);
+end;
+
+procedure TBuildEngine.CmdDeleteFiles(List: TStrings);
+
+Var
+  Args : String;
+  I : Integer;
+
+begin
+  If (Defaults.Remove<>'') then
+    begin
+    Args:=FileListToString(List,'');
+    ExecuteCommand(Defaults.Remove,Args);
+    end
+  else
+    For I:=0 to List.Count-1 do
+      SysDeleteFile(List[i]);
+end;
+
+procedure TBuildEngine.CmdArchiveFiles(List: TStrings; Const ArchiveFile: String);
+
+Var
+  S,C,O : String;
+
+begin
+  If (Defaults.Archive='') then
+    SysArchiveFiles(List,ArchiveFile)
+  else
+    begin
+    S:=FileListToString(List,'');
+    SplitCommand(Defaults.Archive,C,O);
+    If (O='') then
+      O:=ArchiveFile+' '+S
+    else
+      O:=Substitute(O,['ARCHIVE',ArchiveFile,'FILESORDIRS']);
+    ExecuteCommand(C,O);
+    end;
+end;
+
+Function TBuildEngine.FileNewer(Src,Dest : String) : Boolean;
+
+Var
+  DS,DD : Longint;
+  D1,D2 : TDateTime;
+  
+begin
+  DS:=FileAge(Src);
+  DD:=FileAge(Dest);
+  D1:=FileDateToDateTime(DS);
+  D2:=FileDateToDateTime(DD);
+  Log(vlDebug,SLogCompilingFileTimes,[Src,DateTimeToStr(D1),Dest,DateTimeToStr(D2)]);
+  Result:=D1>=D2;
+  If Result then
+    Log(vlCompare,SLogSourceNewerDest,[Src,DateTimeToStr(D1),Dest,DateTimeToStr(D2)]);
+end;
+
+procedure TBuildEngine.ExecuteCommands(Commands: TCommands; At: TCommandAt);
+
+Var
+  C : TCommand;
+  I : Integer;
+  Cmd,O : String;
+  E : Boolean;
+  
+begin
+  For I:=0 to Commands.Count-1 do
+    begin
+    C:=Commands.CommandItems[i];
+    if (C.At=At) then
+      begin
+      E:=True;
+      If (C.SourceFile<>'') and (C.DestFile<>'')  then
+        E:=FileNewer(C.SourceFile,IncludeTrailingPathDelimiter(Dictionary.GetValue('OUTPUTDIR'))+C.DestFile);
+      If E then
+        begin
+        If Assigned(C.BeforeCommand) then
+          C.BeforeCommand(C);
+        O:=Substitute(C.Options,['SOURCE',C.SourceFile,'DEST',C.DestFile]);
+        Cmd:=C.Command;
+        If (ExtractFilePath(Cmd)='') then
+          Cmd:=FileSearch(Cmd,GetEnvironmentvariable('PATH'));
+        ExecuteCommand(Cmd,O,C.IgnoreResult);
+        If Assigned(C.AfterCommand) then
+          C.AfterCommand(C);
+        end;
+      end;
+    end;
+end;
+
+// Relative to startdir.
+Function TBuildEngine.GetTargetDir(APackage : TPackage; ATarget : TTarget; AbsolutePath : Boolean = False) : String;
+
+begin
+  If AbsolutePath then
+    Result:=IncludeTrailingPathDelimiter(FStartDir)
+  else
+    Result:='';
+  If (APackage.Directory<>'') then
+    Result:=Result+IncludeTrailingPathDelimiter(APackage.Directory);
+  If (ATarget.Directory<>'') then
+    Result:=IncludeTrailingPathDelimiter(Result+ATarget.Directory);
+
+end;
+
+Function TBuildEngine.TargetOK(Target : TTarget) : Boolean;
+
+begin
+  Result:=(Target.TargetType in [ttUnit,ttProgram])
+          and
+          ((Target.CPU=[]) or (Defaults.CPU in Target.CPU))
+          and
+          ((Target.OS=[]) or (Defaults.OS in Target.OS));
+  If not Result then  
+    begin
+    log(vldebug,'Target is not a unit or program');
+    If Not ((Target.CPU=[]) or (Defaults.CPU in Target.CPU)) then
+      Log(vldebug,'Target has wrong CPU: '+CPUsToString(Target.CPU));
+    if not ((Target.OS=[]) or (Defaults.OS in Target.OS)) then
+      Log(vldebug,'Target has wrong OS: '+OSesToString(Target.OS));
+    end;
+end;
+
+Function TBuildEngine.NeedsCompile(Target: TTarget): Boolean;
+
+Var
+  I : Integer;
+  T : TTarget;
+  OD,SD,SFN,OFN : String;
+
+begin
+  Result:=False;
+  OD:=FCurrentOutputDir;
+  If (OD<>'') then
+    OD:=IncludeTrailingPathDelimiter(OD);
+  OFN:=OD+Target.GetOutPutFileName(Defaults.OS);
+  SD:=Target.Directory;
+  If (SD<>'') then
+      SD:=IncludeTrailingPathDelimiter(SD);
+  Result:=Not FileExists(OFN);
+  // Check dependencies
+  If not Result then
+    If Target.HasDependencies then
+      begin
+      ResolveDependencies(Target.Dependencies,Target.Collection as TTargets);
+      I:=0;
+      While (Not Result) and (I<Target.Dependencies.Count) do
+        begin
+        T:=TTarget(Target.Dependencies.Objects[i]);
+        If (T<>Nil) then
+          Result:=NeedsCompile(T)
+        else // if it is a filename, check dates.
+          if FileExists(Target.Dependencies[i]) then
+            Result:=FileNewer(Target.Dependencies[i],OFN)
+          else if FileExists(SD+Target.Dependencies[i]) then
+            Result:=FileNewer(SD+Target.Dependencies[i],OFN);
+        Inc(I)
+        end;
+      end;
+  If not Result then
+    begin
+    SFN:=SD+Target.SourceFileName;
+    If (ExtractFileExt(SFN)='') then
+      if FileExists(SFN+'.pp') then
+        SFN:=SFN+'.pp'
+      else
+        SFN:=SFN+'.pas';
+    // Writeln('Checking : ',OFN,' against ',SFN);
+    Result:=FileNewer(SFN,OFN);
+    // here we should check file timestamps.
+    end;
+end;
+
+
+
+Function TBuildEngine.GetCompilerCommand(APackage : TPackage; Target : TTarget) : String;
+
+
+Var
+  PD,TD,OD,RD : String;
+
+begin
+  PD:=IncludeTrailingPathDelimiter(GetPackageDir(APackage,True));
+  OD:=IncludeTrailingPathDelimiter(GetOutputDir(APackage,True));
+  RD:=ExtractRelativePath(PD,OD);
+  If Target.TargetType in ProgramTargets then
+    Result:='-FE.' // Make this relative to target directory.
+  else
+    Result:='-FU'+RD;
+  If Target.Mode<>fpc then
+    Result:=Result+' -M'+ModeToString(Target.Mode)
+  else If Defaults.Mode<>fpc then
+    Result:=Result+' -M'+ModeToString(Defaults.Mode);
+  If (Defaults.Options<>'') then
+    Result:=Result+' '+Defaults.Options;
+  If (APackage.Options<>'') then
+    Result:=Result+' '+APackage.Options;
+  If APackage.HasUnitPath then
+    AddStrings(Result,APackage.UnitPath,'-Fu');
+  If APackage.HasIncludePath then
+    AddStrings(Result,APackage.IncludePath,'-Fi');
+  If APackage.HasObjectPath then
+    AddStrings(Result,APackage.ObjectPath,'-Fo');
+  If Target.HasUnitPath then
+    AddStrings(Result,Target.UnitPath,'-Fu');
+  If Target.HasIncludePath then
+    AddStrings(Result,Target.IncludePath,'-Fi');
+  If Target.HasObjectPath then
+    AddStrings(Result,Target.ObjectPath,'-Fo');
+  If (Target.Options<>'') then
+    Result:=Result+' '+Target.Options;
+  TD:=Target.Directory;
+  if (TD<>'') then
+    TD:=IncludeTrailingPathDelimiter(TD);
+  Result:=Result+' '+TD+Target.SourceFileName;
+end;
+
+Function TBuildEngine.GetCompiler : String;
+
+Var
+  S : String;
+  
+begin
+  // Cache in FCompiler for speed.
+  If (FCompiler='') then
+    begin
+    FCompiler:=Defaults.Compiler;
+    If (ExtractFilePath(FCompiler)='') then
+      begin
+      S:=FileSearch(FCompiler,GetEnvironmentVariable('PATH'));
+      If (S<>'') then
+         FCompiler:=S;
+      end;
+    end;
+  Result:=FCompiler;
+end;
+
+procedure TBuildEngine.Compile(Target: TTarget);
+
+Var
+  S : String;
+  
+begin
+  if Target.State in [tsNeutral,tsCompiling] then
+    begin
+    Log(vlInfo,SLogCompilingTarget,[Target.Name]);
+    If Target.HasCommands then
+      ExecuteCommands(Target.Commands,caBeforeCompile);
+    If Assigned(Target.BeforeCompile) then
+      Target.BeforeCompile(Target);
+    S:=GetCompilerCommand(FCurrentPackage,Target);
+    ExecuteCommand(GetCompiler,S);
+    Target.FTargetState:=tsCompiled;
+    If Assigned(Target.AfterCompile) then
+      Target.AfterCompile(Target);
+    If Target.HasCommands then
+      ExecuteCommands(Target.Commands,caAfterCompile);
+    end
+  else if Target.State<>tsCompiled then
+    Log(vlWarning,'Attempting to compile non-neutral target: '+Target.Name);
+end;
+
+
+procedure TBuildEngine.FixDependencies(Target: TTarget);
+
+Var
+  I : Integer;
+  T : TTarget;
+
+begin
+  Log(vlDebug,'Checking dependencies for target: '+Target.Name);
+  ResolveDependencies(Target.Dependencies,Target.Collection as TTargets);
+  If Target.HasDependencies then
+    For I:=0 to Target.Dependencies.Count-1 do
+      begin
+      T:=TTarget(Target.Dependencies.Objects[i]);
+      If Assigned(T) then
+        begin
+        If (T.State=tsCompiling) then
+          Log(vlWarning,SWarnCircularDependency,[Target.Name,T.Name])
+        else 
+          Compile(T) 
+        end
+      else if Not FileExists(Target.Dependencies[i]) then
+        Error(SErrDepUnknownTarget,[Target.Name,Target.Dependencies[i]]);
+      end;
+end;
+
+function TBuildEngine.GetPackageDir(APackage: TPackage; AbsolutePath: Boolean
+  ): String;
+begin
+  If AbsolutePath then
+    Result:= IncludeTrailingPathDelimiter(FStartDir)
+  else
+    Result:='';
+  Result:=Result+APackage.Directory;
+  If (Result<>'') then
+    Result:= ExcludeTrailingPathDelimiter(Result)
+end;
+
+
+Function TBuildEngine.GetOutputDir(APackage : TPackage; AbsolutePath : Boolean = False) : String;
+
+begin
+  If (TargetDir<>'') then
+    Result:=TargetDir
+  else
+    begin
+    If AbsolutePath then
+      Result:=IncludeTrailingPathDelimiter(FStartDir)
+    else
+      Result:='';
+    If (APackage.Directory<>'') then
+      Result:=IncludeTrailingPathDelimiter(Result+APackage.Directory);
+    Result:=Result+'units'+PathDelim+Defaults.Target;
+    end;
+end;
+
+procedure TBuildEngine.CreateOutputDir(APackage: TPackage);
+
+Var
+  D : String;
+
+begin
+  D:=GetOutputDir(APackage,True);
+  If DirectoryExists(D) then
+    Log(vlInfo,SLogOutputDirExists,[D])
+  else
+    begin
+    Log(vlInfo,SLogCreatingOutputDir,[D]);
+    CmdCreateDir(D);
+    end;
+end;
+
+Function TBuildEngine.PackageOK(APackage : TPackage) : Boolean;
+
+begin
+  Result:=((APackage.CPU=[]) or (Defaults.CPU in APackage.CPU))
+          and
+          ((APAckage.OS=[]) or (Defaults.OS in APackage.OS));
+end;
+
+
+procedure TBuildEngine.DoBeforeCompile(APackage: TPackage);
+begin
+  If APackage.HasCommands then
+    ExecuteCommands(APackage.Commands,caBeforeCompile);
+  If Assigned(APackage.BeforeCompile) then
+    APackage.BeforeCompile(APackage);
+end;
+
+procedure TBuildEngine.DoAfterCompile(APackage: TPackage);
+begin
+  If Assigned(APackage.AfterCompile) then
+    APackage.AfterCompile(APackage);
+  If APackage.HasCommands then
+    ExecuteCommands(APackage.Commands,caAfterCompile);
+end;
+
+procedure TBuildEngine.Compile(APackage: TPackage);
+
+
+Var
+  T : TTarget;
+  I : Integer;
+  
+begin
+  Log(vlInfo,SLogCompilingPackage,[APackage.Name]);
+  FCurrentPackage:=APackage;
+  FCurrentOutputDir:=GetOutputDir(APackage,True);
+  Try
+    If (APackage.Directory<>'') then
+      EnterDir(APackage.Directory);
+    CreateOutputDir(APackage);
+    Dictionary.AddVariable('OUTPUTDIR',FCurrentOutputDir);
+    DoBeforeCompile(APackage);
+    Try
+      For I:=0 to APackage.Targets.Count-1 do
+        begin
+        T:=APackage.Targets.TargetItems[i];
+        Log(vlDebug,'Considering target: '+T.Name);
+        If TargetOK(T) then
+          If (T.State=tsNeutral) then
+            begin
+            If (FForceCompile or NeedsCompile(T)) then
+              begin
+              T.FTargetState:=tsCompiling;
+              FixDependencies(T);
+              Compile(T);
+              end;
+            T.FTargetState:=tsCompiled;
+            end;
+        end;
+      DoAfterCompile(APackage);
+    Finally
+      If (APackage.Directory<>'') then
+        EnterDir('');
+    end;
+  Finally
+    FCurrentPackage:=Nil;
+    FCurrentOutputDir:='';
+  end;
+end;
+
+procedure TBuildEngine.CheckExternalPackage(Const APackageName : String);
+
+begin
+  // A check needs to be implemented here.
+  Log(vldebug,'Unresolved external dependency : %s',[APackageName]);
+end;
+
+procedure TBuildEngine.FixDependencies(APackage: TPackage);
+
+Var
+  I : Integer;
+  P : TPackage;
+
+begin
+  if APackage.HasDependencies then
+    For I:=0 to APAckage.Dependencies.Count-1 do
+      begin
+      P:=TPackage(Apackage.Dependencies.Objects[i]);
+      If Assigned(P) then
+        Compile(P) // If it already was compiled, then State<>tsNeutral, and it won't be compiled again.
+      else
+        CheckExternalPackage(Apackage.Dependencies[i]);
+      end;
+end;
+
+Procedure TBuildEngine.InstallPackageFiles(APAckage : TPackage; tt : TTargetType; Const Src,Dest : String);
+
+Var
+  I : Integer;
+  List : TStringList;
+
+begin
+  List:=TStringList.Create;
+  Try
+    APackage.GetInstallFiles(List,[tt],Src,Defaults.OS);
+    if (List.Count>0) then
+      CmdCopyFiles(List,Dest);
+  Finally
+    List.Free;
+  end;
+end;
+
+procedure TBuildEngine.DoBeforeInstall(APackage: TPackage);
+begin
+  If APackage.HasCommands then
+    ExecuteCommands(APackage.Commands,caBeforeInstall);
+  If Assigned(APackage.BeforeInstall) then
+    APackage.BeforeInstall(APackage);
+end;
+
+procedure TBuildEngine.DoAfterInstall(APackage: TPackage);
+begin
+  If Assigned(APackage.AfterInstall) then
+    APackage.AfterInstall(APackage);
+  If APackage.HasCommands then
+    ExecuteCommands(APackage.Commands,caAfterInstall);
+end;
+
+
+procedure TBuildEngine.Install(APackage: TPackage);
+
+
+Var
+  PD,D,O : String;
+
+begin
+  If (Apackage.State<>tsCompiled) then
+    Compile(APackage);
+  Log(vlInfo,SLogInstallingPackage,[APackage.Name]);
+  DoBeforeInstall(APackage);
+  O:=IncludeTrailingPathDelimiter(GetOutputDir(APAckage));
+  PD:=IncludeTrailingPathDelimiter(GetPackageDir(APackage));
+  // units
+  D:=IncludeTrailingPathDelimiter(Defaults.UnitInstallDir)+APackage.Name;
+  InstallPackageFiles(APAckage,ttUnit,O,D);
+  // Programs
+  D:=IncludeTrailingPathDelimiter(Defaults.BinInstallDir);
+  InstallPackageFiles(APAckage,ttProgram,PD,D);
+  // Done.
+  APackage.FTargetState:=tsInstalled;
+  DoAfterInstall(APackage);
+end;
+
+procedure TBuildEngine.DoBeforeArchive(APackage: TPackage);
+begin
+  If APackage.HasCommands then
+    ExecuteCommands(APackage.Commands,caBeforeArchive);
+  If Assigned(APackage.BeforeArchive) then
+    APackage.BeforeArchive(APackage);
+end;
+
+procedure TBuildEngine.DoAfterArchive(APackage: TPackage);
+begin
+  If Assigned(APackage.AfterArchive) then
+    APackage.AfterArchive(APackage);
+  If APackage.HasCommands then
+    ExecuteCommands(APackage.Commands,caAfterArchive);
+end;
+
+
+procedure TBuildEngine.Archive(APackage: TPackage);
+
+Var
+  L : TStrings;
+  A,S,C,O : String;
+  
+begin
+  Log(vlInfo,SLogArchivingPackage,[APackage.Name]);
+  DoBeforeArchive(Apackage);
+  L:=TStringList.Create;
+  Try
+    APackage.GetInstallFiles(L,[ttUnit],TargetDir,Defaults.OS);
+    A:=APackage.Name+ZipExt;
+    CmdArchiveFiles(L,A);
+  Finally
+    L.Free;
+  end;
+  Writeln('Archiving : ',APackage.Name);
+  DoAfterArchive(Apackage);
+end;
+
+procedure TBuildEngine.DoBeforeClean(APackage: TPackage);
+begin
+  If APackage.HasCommands then
+    ExecuteCommands(APackage.Commands,caBeforeClean);
+  If Assigned(APackage.BeforeClean) then
+    APackage.BeforeClean(APackage);
+end;
+
+procedure TBuildEngine.DoAfterClean(APackage: TPackage);
+begin
+  If Assigned(APackage.AfterClean) then
+    APackage.AfterClean(APackage);
+  If APackage.HasCommands then
+    ExecuteCommands(APackage.Commands,caAfterClean);
+end;
+
+procedure TBuildEngine.Clean(APackage: TPackage);
+
+Var
+  O : String;
+  List : TStringList;
+  
+begin
+  Log(vlInfo,SLogCleaningPackage,[APackage.Name]);
+  DoBeforeClean(Apackage);
+  O:=IncludeTrailingPathDelimiter(GetOutputDir(APAckage));
+  List:=TStringList.Create;
+  try
+    APackage.GetCleanFiles(List,O,Defaults.OS);
+    if (List.Count>0) then
+      CmdDeleteFiles(List);
+  Finally
+    List.Free;
+  end;
+  DoAfterClean(Apackage);
+end;
+
+function TBuildEngine.NeedsCompile(APackage: TPackage): Boolean;
+
+Var
+  I : Integer;
+  P : TPackage;
+
+begin
+  ResolveDependencies(APackage.Dependencies,(APackage.Collection as TPackages));
+  Result:=False;
+  I:=0;
+  While (Not Result) and (I<APAckage.Dependencies.Count) do
+    begin
+    P:=TPackage(APAckage.Dependencies.Objects[i]);
+    // I'm not sure whether the target dir is OK here ??
+    Result:=Assigned(P) and NeedsCompile(P);
+    Inc(I);
+    end;
+  If Not Result then
+    begin
+    I:=0;
+    While (Not Result) and (I<APackage.Targets.Count) do
+      begin
+      Result:=NeedsCompile(APackage.Targets.TargetItems[i]);
+      Inc(I);
+      end;
+    end;
+end;
+
+Procedure TBuildEngine.GetManifest(APackage : TPackage; Manifest : TStrings);
+
+begin
+  APackage.GetManifest(Manifest);
+end;
+
+
+procedure TBuildEngine.Compile(Packages: TPackages);
+
+Var
+  I : Integer;
+  P : TPackage;
+
+begin
+  If Assigned(BeforeCompile) then
+    BeforeCompile(Self);
+  For I:=0 to Packages.Count-1 do
+    begin
+    P:=Packages.PackageItems[i];
+    If PackageOK(P) then
+      If (P.State=tsNeutral) then
+        begin
+        If (FForceCompile or NeedsCompile(P)) then
+          begin
+          P.FTargetState:=tsCompiling;
+          FixDependencies(P);
+          Compile(P);
+          end;
+        P.FTargetState:=tsCompiled;
+        end;
+    end;
+  If Assigned(AfterCompile) then
+    AfterCompile(Self);
+end;
+
+procedure TBuildEngine.Install(Packages: TPackages);
+
+Var
+  I : Integer;
+  P : TPackage;
+
+begin
+  If Assigned(BeforeInstall) then
+    BeforeInstall(Self);
+  For I:=0 to Packages.Count-1 do
+    begin
+    P:=Packages.PackageItems[i];
+    If PackageOK(P) then
+      Install(P);
+    end;
+  If Assigned(AfterInstall) then
+    AfterInstall(Self);
+end;
+
+procedure TBuildEngine.Archive(Packages: TPackages);
+
+Var
+  I : Integer;
+  P : TPackage;
+
+begin
+  If Assigned(BeforeArchive) then
+    BeforeArchive(Self);
+  Log(vlDebug,'Build engine archiving.');
+  For I:=0 to Packages.Count-1 do
+    begin
+    P:=Packages.PackageItems[i];
+    If PackageOK(P) then
+      Archive(P);
+    end;
+  If Assigned(AfterArchive) then
+    AfterArchive(Self);
+end;
+
+procedure TBuildEngine.Clean(Packages: TPackages);
+
+Var
+  I : Integer;
+  P : TPackage;
+
+begin
+  If Assigned(BeforeClean) then
+    BeforeClean(Self);
+  Log(vldebug,'Build engine cleaning.');
+  For I:=0 to Packages.Count-1 do
+    begin
+    P:=Packages.PackageItems[i];
+    If PackageOK(P) then
+      Clean(P);
+    end;
+  If Assigned(AfterClean) then
+    AfterClean(Self);
+end;
+
+Procedure TBuildEngine.GetManifest(Packages : TPackages; Manifest : TStrings);
+
+Var
+  I : Integer;
+  
+begin
+  If Assigned(BeforeManifest) then
+    BeforeManifest(Self);
+  Manifest.Add('<packages>');  
+  For I:=0 to Packages.Count-1 do
+    GetManifest(Packages.PackageItems[i],Manifest);
+  Manifest.Add('</packages>');  
+  If Assigned(AfterManifest) then
+    AfterManifest(Self);
+end;
+
+
+{ TTarget }
+
+function TTarget.GetHasStrings(AIndex: integer): Boolean;
+begin
+  Result:=False;
+  Case AIndex Of
+    0 : Result:=FUnitPath<>Nil;
+    1 : Result:=FObjectPath<>Nil;
+    2 : Result:=FIncludePath<>Nil;
+    3 : Result:=FDependencies<>Nil;
+  end;
+end;
+
+function TTarget.GetCommands: TCommands;
+begin
+  If FCommands=Nil then
+    FCommands:=TCommands.Create(TCommand);
+  Result:=FCommands;
+end;
+
+function TTarget.GetHasCommands: Boolean;
+begin
+  Result:=(FCommands<>Nil);
+end;
+
+function TTarget.GetStrings(AIndex: integer): TStrings;
+
+  Function EnsureStrings(Var S : TStrings) : TStrings;
+
+  begin
+    If (S=Nil) then
+      S:=TStringList.Create;
+    Result:=S;
+  end;
+  
+begin
+  Result:=Nil;
+  Case AIndex Of
+    0 : Result:=EnsureStrings(FUnitPath);
+    1 : Result:=EnsureStrings(FObjectPath);
+    2 : Result:=EnsureStrings(FIncludePath);
+    3 : Result:=EnsureStrings(FDependencies);
+  end;
+end;
+
+procedure TTarget.SetCommands(const AValue: TCommands);
+begin
+
+end;
+
+procedure TTarget.SetStrings(AIndex: integer; const AValue: TStrings);
+begin
+  GetStrings(AIndex).Assign(AValue);
+end;
+
+
+function TTarget.GetSourceFileName: String;
+begin
+  Result:=Name+FExtension;
+end;
+
+function TTarget.GetUnitFileName: String;
+begin
+  Result:=Name+UnitExt;
+end;
+
+function TTarget.GetObjectFileName: String;
+begin
+  Result:=Name+ObjExt;
+end;
+
+function TTarget.GetRSTFileName: String;
+begin
+  Result:=Name+RSText;
+end;
+
+function TTarget.GetProgramFileName(AnOS : TOS): String;
+begin
+  if AnOS in [dos,win32,os2] then
+    Result:=Name+ExeExt
+  else
+    Result:=Name;
+end;
+
+constructor TTarget.Create(ACollection: TCollection);
+begin
+  inherited Create(ACollection);
+  FInstall:=True;
+end;
+
+destructor TTarget.Destroy;
+begin
+  FreeAndNil(FUnitPath);
+  FreeAndNil(FObjectPath);
+  FreeAndNil(FIncludePath);
+  FreeAndNil(FDependencies);
+  inherited Destroy;
+end;
+
+function TTarget.GetOutputFileName(AOs: TOS): String;
+begin
+  Result:=Name;
+  if TargetType in UnitTargets then
+    Result:=Result+UnitExt
+  else if AOs in [Win32,dos,OS2] then
+    Result:=Result+ExeExt
+end;
+
+
+procedure TTarget.SetName(const AValue: String);
+
+Var
+  D,N,E : String;
+
+begin
+  N:=FixPath(AValue);
+  D:=ExtractFilePath(N);
+  E:=ExtractFileExt(N);
+  N:=ExtractFileName(N);
+  If (E<>'') then
+    N:=Copy(N,1,Length(N)-Length(E));
+  inherited SetName(N);
+  FExtension:=E;
+  FDirectory:=D;
+end;
+
+procedure TTarget.GetCleanFiles(List: TStrings; APrefix : String; AnOS : TOS);
+begin
+  If (OS=[]) or (AnOS in OS) then
+    begin
+    List.Add(APrefix+ObjectFileName);
+    If (TargetType in [ttUnit,ttExampleUnit]) then
+      List.Add(APrefix+UnitFileName)
+    else If (TargetType in [ttProgram,ttExampleProgram]) then
+      List.Add(APrefix+GetProgramFileName(AnOS));
+    If ResourceStrings then
+      List.Add(APrefix+RSTFileName);
+    // Maybe add later ?  AddStrings(List,CleanFiles);
+    end;
+end;
+
+procedure TTarget.GetInstallFiles(List: TStrings; APrefix : String; AnOS : TOS);
+begin
+  If (OS=[]) or (AnOS in OS) then
+    begin
+    If Not (TargetType in [ttProgram,ttExampleProgram]) then
+      List.Add(APrefix+ObjectFileName);
+    If (TargetType in [ttUnit,ttExampleUnit]) then
+      List.Add(APrefix+UnitFileName)
+    else If (TargetType in [ttProgram,ttExampleProgram]) then
+      List.Add(APrefix+GetProgramFileName(AnOS));
+    If ResourceStrings then
+      List.Add(APrefix+RSTFileName);
+    // Maybe add later ?  AddStrings(List,InstallFiles);
+    end;
+end;
+
+procedure TTarget.GetArchiveFiles(List: TStrings; APrefix : String; AnOS : TOS);
+begin
+  If (OS=[]) or (AnOS in OS) then
+    begin
+    List.Add(APrefix+SourceFileName);
+    // Maybe add later ?  AddStrings(List,ArchiveFiles);
+    end;
+end;
+
+
+
+{ TCommands }
+
+function TCommands.GetCommand(Dest : String): TCommand;
+
+begin
+  Result:=TCommand(ItemByName(Dest));
+end;
+
+function TCommands.GetCommandItem(Index : Integer): TCommand;
+begin
+  Result:=TCommand(Items[Index]);
+end;
+
+procedure TCommands.SetCommandItem(Index : Integer; const AValue: TCommand);
+begin
+  Items[Index]:=AValue;
+end;
+
+Function TCommands.AddCommand(const Cmd: String) : TCommand;
+begin
+  Result:=AddCommand(fdefaultAt,Cmd,'','','');
+end;
+
+function TCommands.AddCommand(const Cmd, Options: String): TCommand;
+begin
+  Result:=AddCommand(fdefaultAt,Cmd,Options,'','');
+end;
+
+function TCommands.AddCommand(const Cmd, Options, Dest, Source: String
+  ): TCommand;
+begin
+  Result:=AddCommand(fdefaultAt,Cmd,options,Dest,Source);
+end;
+
+Function TCommands.AddCommand(At: TCommandAt; const Cmd: String) : TCommand;
+begin
+  Result:=AddCommand(At,Cmd,'','','');
+end;
+
+function TCommands.AddCommand(At: TCommandAt; const Cmd, Options: String
+  ): TCommand;
+begin
+  Result:=AddCommand(At,Cmd,Options,'','');
+end;
+
+function TCommands.AddCommand(At: TCommandAt; const Cmd, Options, Dest,
+  Source: String): TCommand;
+begin
+  Result:=Add as TCommand;
+  Result.Command:=Cmd;
+  Result.Options:=Options;
+  Result.At:=At;
+  Result.SourceFile:=Source;
+  Result.DestFile:=Dest;
+end;
+
+Var
+  DefInstaller : TInstaller = Nil;
+  DefDictionary : TDictionary = Nil;
+  
+Function Installer : TInstaller;
+
+begin
+  If Not Assigned(DefInstaller) then
+    DefInstaller:=InstallerClass.Create(Nil);
+  Result:=DefInstaller;
+end;
+
+Function Defaults : TDefaults;
+
+begin
+  Result:=Installer.Defaults;
+end;
+
+
+function Dictionary : TDictionary;
+begin
+  If Not Assigned(DefDictionary) then
+    DefDictionary:=DictionaryClass.Create(Nil);
+  Result:=DefDictionary;
+end;
+
+{ TValueItem }
+
+constructor TValueItem.Create(AValue: String);
+begin
+  FValue:=AValue;
+end;
+
+{ TFunctionItem }
+
+constructor TFunctionItem.Create(AFunc: TReplaceFunction);
+begin
+  FFunc:=AFunc;
+end;
+
+{ TDictionary }
+
+constructor TDictionary.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FList:=TStringList.Create;
+  FList.Sorted:=True;
+  FList.Duplicates:=dupError;
+end;
+
+destructor TDictionary.Destroy;
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to Flist.Count-1 do
+    FList.Objects[i].Free;
+  FreeAndNil(FList);
+  inherited Destroy;
+end;
+
+procedure TDictionary.AddVariable(const AName, Value: String);
+
+Var
+  I : Integer;
+
+begin
+  I:=Flist.IndexOf(AName);
+  If I=-1 then
+    I:=FList.Add(Aname)
+  else
+    Flist.Objects[i].Free;
+  Flist.Objects[i]:=TValueItem.Create(Value);
+end;
+
+procedure TDictionary.AddFunction(const AName: String;
+  FReplacement: TReplaceFunction);
+  
+Var
+  I : Integer;
+
+begin
+  I:=Flist.IndexOf(AName);
+  If I=-1 then
+    I:=Flist.Add(AName)
+  else
+    Flist.Objects[i].Free;
+  Flist.Objects[i]:=TFunctionItem.Create(FReplacement);
+end;
+
+procedure TDictionary.RemoveItem(const AName: String);
+
+Var
+  I : Integer;
+
+begin
+  I:=Flist.IndexOf(AName);
+  If (I<>-1) then
+    begin
+    FList.Objects[i].Free;
+    FList.Delete(I);
+    end;
+end;
+
+function TDictionary.GetValue(const AName: String): String;
+
+begin
+  Result:=GetValue(AName,'');
+end;
+
+
+function TDictionary.GetValue(const AName,Args: String): String;
+
+Var
+  O : TObject;
+  I : Integer;
+  
+begin
+  I:=Flist.IndexOf(AName);
+  If (I=-1) then
+    Raise EDictionaryError.CreateFmt(SErrNoDictionaryItem,[AName]);
+  O:=Flist.Objects[I];
+  If O is TValueItem then
+    Result:=Result+TValueItem(O).FValue
+  else
+    Result:=Result+TFunctionItem(O).FFunc(AName,Args);
+end;
+
+function TDictionary.ReplaceStrings(Const ASource: String): String;
+
+
+Var
+  S,FN,FV : String;
+  I,P: Integer;
+  O : TObject;
+
+begin
+  Result:='';
+  S:=ASource;
+  P:=Pos('$(',S);
+  While (P<>0) do
+    begin
+    Result:=Result+Copy(S,1,P-1);
+    Delete(S,1,P+1);
+    P:=Pos(')',S);
+    FN:=Copy(S,1,P-1);
+    Delete(S,1,P);
+    P:=Pos(' ',FN);
+    If (P<>0) then // function arguments ?
+      begin
+      FV:=FN;
+      FN:=Copy(FN,1,P);
+      System.Delete(FV,1,P);
+      end
+    else
+      FV:='';
+    Result:=Result+GetValue(FN,FV);
+    P:=Pos('$(',S);
+    end;
+  Result:=Result+S;
+end;
+
+Function Substitute(Const Source : String; Macros : Array of string) : String;
+
+Var
+  I : Integer;
+
+begin
+  I:=0;
+  While I<High(Macros) do
+    begin
+    Dictionary.AddVariable(Macros[i],Macros[I+1]);
+    Inc(I,2);
+    end;
+  Result:=Dictionary.ReplaceStrings(Source);
+  While I<High(Macros) do
+    begin
+    Dictionary.RemoveItem(Macros[i]);
+    Inc(I,2);
+    end;
+end;
+
+Initialization
+  OnGetApplicationName:=@GetFPMakeName;
+
+Finalization
+  FreeAndNil(DefInstaller);
+  FreeAndNil(DefDictionary);
+end.

+ 872 - 0
utils/fppkg/fprepos.pp

@@ -0,0 +1,872 @@
+{
+    This file is part of the Free Pascal Utilities
+    Copyright (c) 1999-2000 by the Free Pascal development team
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$H+}
+unit fprepos;
+
+interface
+
+uses classes,sysutils,streamcoll,contnrs,fpmktype;
+
+Const 
+  StreamVersion   : Integer = 1;
+  StreamSignature = $FEEF;
+
+Type
+  { TFPVersion }
+
+  TFPVersion = Class(TPersistent)
+  private
+    FMajor: Word;
+    FMinor: Word;
+    FRelease: Word;
+    FSuffix: string;
+    function GetAsString: String;
+    function GetEmpty: Boolean;
+    procedure SetAsString(const AValue: String);
+  Public
+   Procedure Assign(Source : TPersistent); override;
+   Property AsString : String Read GetAsString Write SetAsString;
+   Function CompareVersion(AVersion : TFPVersion) : Integer;
+   Function SameVersion(AVersion : TFPVersion) : Boolean;
+   Property Empty : Boolean Read GetEmpty;
+  Published
+   Property Release : Word Read FRelease Write FRelease;
+   Property Major : Word Read FMajor Write FMajor;
+   Property Minor : Word Read FMinor Write FMinor;
+   Property Suffix : string Read FSuffix Write FSuffix;
+  end;
+  
+  { TFPDependency }
+
+  TFPDependency = Class(TStreamCollectionItem)
+  private
+    FMinVersion: TFPVersion;
+    FPackageName: String;
+    procedure SetMinVersion(const AValue: TFPVersion);
+  Public
+    Constructor Create(ACollection : TCollection); override;
+    Destructor Destroy; override;
+    Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
+    Procedure SaveToStream(Stream : TStream); override;
+    Procedure Assign(Source : TPersistent); override;
+  Published
+    Property PackageName : String Read FPackageName Write FPackageName;
+    Property MinVersion : TFPVersion Read FMinVersion Write SetMinVersion;
+  end;
+  
+  { TFPDepencencies }
+
+  { TFPDependencies }
+
+  TFPDependencies = Class(TStreamCollection)
+  private
+    function GetDependency(Index : Integer): TFPDependency;
+    procedure SetDependency(Index : Integer; const AValue: TFPDependency);
+  public
+    Function AddDependency(Const APackageName : String; AMinVersion : String = '') : TFPDependency;
+    Property Dependencies[Index : Integer] : TFPDependency Read GetDependency Write SetDependency;default;
+  end;
+
+  { TFPPackage }
+
+  TFPPackage = Class(TStreamCollectionItem)
+  private
+    FAuthor: String;
+    FDescription: String;
+    FEmail: String;
+    FLicense: String;
+    FName: String;
+    FURL: String;
+    FVersion: TFPVersion;
+    FInstalledVersion: TFPVersion;
+    FDependencies : TFPDependencies;
+    FOSes : TOSES;
+    FCPUs : TCPUS;
+    function GetDependencies: TFPDependencies;
+    function GetHasDependencies: Boolean;
+    procedure SetName(const AValue: String);
+    procedure SetVersion(const AValue: TFPVersion);
+  Protected
+    Function CreateDependencies : TFPDependencies; virtual;
+  Public
+    Constructor Create(ACollection : TCollection); override;
+    Destructor Destroy; override;
+    Procedure LoadFromStream(Stream : TStream; Streamversion : Integer); override;
+    Procedure SaveToStream(Stream : TStream); override;
+    Procedure Assign(Source : TPersistent); override;
+    Function AddDependency(Const APackageName : String; AMinVersion : String = '') : TFPDependency;
+    Property HasDependencies : Boolean Read GetHasDependencies;
+    Property Dependencies : TFPDependencies Read GetDependencies;
+  Published
+    Property Name : String Read FName Write SetName;
+    Property Author : String Read FAuthor Write FAuthor;
+    Property Version : TFPVersion Read FVersion Write SetVersion;
+    Property InstalledVersion : TFPVersion Read FInstalledVersion Write FInstalledVersion;
+    Property License : String Read FLicense Write FLicense;
+    Property Description : String Read FDescription Write FDescription;
+    Property URL : String Read FURL Write FURL;
+    Property Email : String Read FEmail Write FEmail;
+    Property OSes : TOSes Read FOSes Write FOses;
+    Property CPUs : TCPUs Read FCPUs Write FCPUs;
+  end;
+
+  { TFPPackages }
+
+  TFPPackages = Class(TStreamCollection)
+  private
+    FVersion : Integer;
+    function GetPackage(Index : Integer): TFPPackage;
+    procedure SetPackage(Index : Integer; const AValue: TFPPackage);
+  Protected
+    Function CurrentStreamVersion : Integer; override;
+  Public
+    Function IndexOfPackage(PackageName : String) : Integer;
+    Function FindPackage(PackageName : String) : TFPPackage;
+    Function PackageByName(PackageName : String) : TFPPackage;
+    Function AddPackage(PackageName : string) : TFPPackage;
+    Property StreamVersion : Integer Read FVersion Write FVersion;
+    Property Packages [Index : Integer] : TFPPackage Read GetPackage Write SetPackage; default;
+  end;
+
+  { TFPRepository }
+
+  TFPRepository = Class(TComponent)
+  Private
+    FMaxDependencyLevel : Integer;
+    FBackUpFiles: Boolean;
+    FFileName: String;
+    FPackageCount: Integer;
+    FPackages : TFPPackages;
+    function GetPackage(Index : Integer): TFPPackage;
+    function GetPackageCount: Integer;
+  Protected 
+    Property PackageCollection : TFPPackages Read FPackages;    
+    procedure CreatePackages; virtual;
+    Procedure BackupFile(AFileName : String); virtual;
+    Procedure DoGetPackageDependencies(PackageName : String; List : TStringList; Level : Integer); virtual;
+  Public
+    Constructor Create(AOwner : TComponent); override;
+    Destructor Destroy; override;
+    // Loading and Saving repository. Own format.
+    Procedure LoadFromStream(Stream : TStream); Virtual;
+    Procedure SaveToStream(Stream : TStream); Virtual;
+    Procedure LoadFromFile(AFileName : String);
+    Procedure SaveToFile(AFileName : String);
+    Procedure Save;
+    // Loading and Saving version numbers: List of Name=Value pairs.
+    Procedure LoadVersionsFromStream(Stream : TStream); virtual;
+    Procedure SaveVersionsToStream(Stream : TStream; InstalledVersions : Boolean); virtual;
+    Procedure LoadVersionsFromFile(AFileName : String);
+    Procedure SaveVersionsToFile(AFileName : String; InstalledVersions : Boolean);
+    // Package management
+    Function IndexOfPackage(PackageName : String) : Integer;
+    Function FindPackage(PackageName : String) : TFPPackage;
+    Function PackageByName(PackageName : String) : TFPPackage;
+    Procedure DeletePackage(Index : Integer);
+    Procedure RemovePackage(PackageName : string);
+    Function AddPackage(PackageName : string) : TFPPackage;
+    // Dependencies
+    Procedure GetPackageDependencies(PackageName : String; List : TObjectList; Recurse : Boolean);
+    // Properties
+    Property FileName : String Read FFileName;
+    Property Packages[Index : Integer] : TFPPackage Read GetPackage; default;
+    Property PackageCount : Integer Read GetPackageCount;
+    Property BackupFiles : Boolean Read FBackUpFiles Write FBackupFiles;
+    Property MaxDependencyLevel : Integer Read FMaxDependencyLevel Write FMaxDependencyLevel;
+  end;
+
+  EPackage = Class(Exception);
+
+Const
+  // Max level of dependency searching before we decide it's a circular dependency.
+  DefaultMaxDependencyLevel = 15;
+
+Implementation
+
+uses typinfo;
+
+ResourceString
+
+  SErrPackageNotFound      = 'Package "%s" not found.';
+  SErrInvalidRepositorySig = 'Invalid repository stream. Stream signature incorrect';
+  SErrBackupFailed         = 'Failed to back up file "%s" to "%s".';
+  SErrNoFileName           = 'No filename for repository specified.';
+  SErrDuplicatePackageName = 'Duplicate package name : "%s"';
+  SErrMaxLevelExceeded     = 'Maximum number of dependency levels exceeded (%d) at package "%s".';
+
+  
+{ TFPVersion }
+
+function TFPVersion.GetAsString: String;
+begin
+  Result:=Format('%d.%d.%d',[Release,Major,Minor]);
+  If (Suffix<>'') then
+    Result:=Result+'-'+Suffix;
+end;
+
+function TFPVersion.GetEmpty: Boolean;
+begin
+  Result:=(Release=0) and (Major=0) and (Minor=0) and (Suffix='');
+end;
+
+procedure TFPVersion.SetAsString(const AValue: String);
+
+  Function NextDigit(sep : Char; var V : string) : integer;
+  
+  Var
+    P : Integer;
+  
+  begin
+    P:=Pos(Sep,V);
+    If (P=0) then
+      P:=Length(V)+1;
+    Result:=StrToIntDef(Copy(V,1,P-1),-1);
+    If Result<>-1 then
+      Delete(V,1,P)
+    else
+      Result:=0;
+  end;
+
+Var
+  P : Integer;
+  V : String;
+  
+begin
+  Release:=0;
+  Major:=0;
+  Minor:=0;
+  Suffix:='';
+  V:=AValue;
+  Release:=NextDigit('.',V);
+  Major:=NextDigit('.',V);
+  Minor:=NextDigit('-',V);
+  P:=Pos('-',V);
+  If (P<>0) then
+    Delete(V,1,P);
+  Suffix:=V;
+end;
+
+procedure TFPVersion.Assign(Source: TPersistent);
+
+Var
+  V : TFPVersion;
+
+begin
+  if Source is TFPVersion then
+    begin
+    V:=Source as TFPVersion;
+    Release:=V.Release;
+    Major:=V.Major;
+    Minor:=V.Minor;
+    Suffix:=V.Suffix;
+    end
+  else
+    inherited Assign(Source);
+end;
+
+function TFPVersion.CompareVersion(AVersion: TFPVersion): Integer;
+begin
+  Result:=Release-AVersion.Release;
+  If (Result=0) then
+    begin
+    Result:=Major-AVersion.Major;
+    if (Result=0) then
+      begin
+      Result:=Minor-AVersion.Minor;
+      If (Result=0) then
+        Result:=CompareText(Suffix,AVersion.Suffix);
+      end;
+    end;
+end;
+
+function TFPVersion.SameVersion(AVersion: TFPVersion): Boolean;
+begin
+  Result:=CompareVersion(AVersion)=0;
+end;
+
+{ TFPPackage }
+
+procedure TFPPackage.SetVersion(const AValue: TFPVersion);
+begin
+  if FVersion=AValue then
+    exit;
+  FVersion.Assign(AValue);
+end;
+
+Function TFPPackage.CreateDependencies : TFPDependencies;
+begin
+  Result:=TFPDependencies.Create(TFPDependency);
+end;
+
+constructor TFPPackage.Create(ACollection: TCollection);
+begin
+  inherited Create(ACollection);
+  FVersion:=TFPVersion.Create;
+  FInstalledVersion:=TFPVersion.Create;
+end;
+
+
+destructor TFPPackage.Destroy;
+begin
+  FreeAndNil(FDependencies);
+  FreeAndNil(FVersion);
+  FreeAndNil(FInstalledVersion);
+  inherited Destroy;
+end;
+
+procedure TFPPackage.SetName(const AValue: String);
+
+Var
+  I : Integer;
+
+begin
+  If (AValue<>FName) and (AValue<>'') then
+    If (Collection<>Nil) and (Collection is TFPPackages) then
+      // do not check while loading, this would slow down a lot !!
+      if (not TFPPackages(Collection).Streaming) then
+        If TFPPackages(Collection).IndexOfPackage(AValue)<>-1 then
+          Raise EPackage.CreateFmt(SErrDuplicatePackageName,[AValue]);
+  FName:=AValue;
+end;
+
+function TFPPackage.GetDependencies: TFPDependencies;
+begin
+  If Not Assigned(FDependencies) then
+    FDependencies:=CreateDependencies;
+  Result:=FDependencies;
+end;
+
+function TFPPackage.GetHasDependencies: Boolean;
+begin
+  Result:=Assigned(FDependencies) and (FDependencies.Count>0);
+end;
+
+procedure TFPPackage.LoadFromStream(Stream: TStream; Streamversion : Integer);
+
+Var
+  B : Boolean;
+  O : TOSes;
+  C : TCPUs;
+  I,J,Count : Integer;
+  
+begin
+  Version.AsString:=ReadString(Stream);
+  Name:=ReadString(Stream);
+  Author:=ReadString(Stream);
+  License:=ReadString(Stream);
+  Description:=ReadString(Stream);
+  URL:=ReadString(Stream);
+  Email:=ReadString(Stream);
+  Count:=ReadInteger(Stream);
+  O:=[];
+  For I:=1 to Count do
+    begin
+    J:=GetEnumValue(TypeInfo(TOS),ReadString(Stream)); 
+    If (J<>-1) then
+      Include(O,TOS(J));
+    end;    
+  OSEs:=O;  
+  Count:=ReadInteger(Stream);
+  C:=[];
+  For I:=1 to Count do
+    begin
+    J:=GetEnumValue(TypeInfo(TCPU),ReadString(Stream)); 
+    If (J<>-1) then
+      Include(C,TCPU(J));
+    end;    
+  CPUS:=C;  
+  FreeAndNil(FDependencies);
+  B:=ReadBoolean(Stream);
+  If B then
+    begin
+    FDependencies:=CreateDependencies;
+    FDependencies.LoadFromStream(Stream);
+    end
+end;
+
+procedure TFPPackage.SaveToStream(Stream: TStream);
+
+Var
+  Count : Integer;
+  O : TOS;
+  C : TCPU;
+  
+begin
+  WriteString(Stream,Version.AsString);
+  WriteString(Stream,Name);
+  WriteString(Stream,Author);
+  WriteString(Stream,License);
+  WriteString(Stream,Description);
+  WriteString(Stream,URL);
+  WriteString(Stream,Email);
+  { Write it like this, makes error checking easier when reading. }
+  // OSes
+  Count:=0;
+  For O:=Low(TOS) to High(TOS) do
+    If O in OSes then
+      Inc(Count);
+  WriteInteger(Stream,Count);
+  For O:=Low(TOS) to High(TOS) do
+    If O in OSes then
+      WriteString(Stream,GetEnumName(TypeInfo(TOS),Ord(O)));
+  // CPUs    
+  Count:=0;
+  For C:=Low(TCPU) to High(TCPU) do
+    If C in CPUS then
+      Inc(Count);
+  WriteInteger(Stream,Count);
+  For C:=Low(TCPU) to High(TCPU) do
+    If C in CPUS then
+      WriteString(Stream,GetEnumName(TypeInfo(TCPU),Ord(C)));
+  WriteBoolean(Stream,HasDependencies);
+  If HasDependencies then
+    FDependencies.SaveToStream(Stream);
+end;
+
+procedure TFPPackage.Assign(Source: TPersistent);
+
+Var
+  P : TFPPackage;
+
+begin
+  if Source is TFPPackage then
+    begin
+    P:=Source as TFPPackage;
+    // This creates trouble if P has the same owning collection !!
+    If P.Collection<>Collection then
+      Name:=P.Name;
+    Author:=P.Author;
+    Version:=P.Version;
+    Description:=P.Description;
+    URL:=P.URL;
+    InstalledVersion:=P.Installedversion;
+    If P.HasDependencies then
+      Dependencies.Assign(P.Dependencies)
+    else
+      FreeAndNil(FDependencies);
+    end
+  else
+    inherited Assign(Source);
+end;
+
+function TFPPackage.AddDependency(const APackageName: String;
+  AMinVersion: String): TFPDependency;
+begin
+  Result:=Dependencies.AddDependency(APackageName,AMinVersion);
+end;
+
+{ TFPPackages }
+
+function TFPPackages.GetPackage(Index : Integer): TFPPackage;
+begin
+  Result:=TFPPackage(Items[Index])
+end;
+
+procedure TFPPackages.SetPackage(Index : Integer; const AValue: TFPPackage);
+begin
+   Items[Index]:=AValue;
+end;
+
+function TFPPackages.CurrentStreamVersion: Integer;
+begin
+  Result:=FVersion;
+end;
+
+function TFPPackages.IndexOfPackage(PackageName: String): Integer;
+
+
+begin
+  Result:=Count-1;
+  While (Result>=0) and (CompareText(GetPackage(Result).Name,PackageName)<>0) do
+    Dec(Result);
+end;
+
+function TFPPackages.FindPackage(PackageName: String): TFPPackage;
+
+Var
+  I : Integer;
+
+begin
+  I:=IndexOfPackage(PackageName);
+  If (I=-1) then
+    Result:=Nil
+  else
+    Result:=GetPackage(I);
+end;
+
+function TFPPackages.PackageByName(PackageName: String): TFPPackage;
+begin
+  Result:=FindPackage(PackageName);
+  If Result=Nil then
+    Raise EPackage.CreateFmt(SErrPackageNotFound,[PackageName]);
+end;
+
+function TFPPackages.AddPackage(PackageName: string): TFPPackage;
+
+begin
+  Result:=Add as TFPPackage;
+  Try
+    Result.Name:=PackageName;
+  Except
+    Result.Free;
+    Raise;
+  end;
+end;
+
+
+{ TFPRepository }
+
+function TFPRepository.GetPackage(Index : Integer): TFPPackage;
+
+begin
+  Result:=FPackages[Index];
+end;
+
+function TFPRepository.GetPackageCount: Integer;
+begin
+  Result:=FPackages.Count;
+end;
+
+constructor TFPRepository.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  CreatePackages;
+  FMaxDependencyLevel:=DefaultMaxDependencyLevel;
+end;
+
+procedure TFPRepository.CreatePackages;
+
+begin
+  FPackages:=TFPPackages.Create(TFPPackage);
+  FPackages.StreamVersion:=StreamVersion;
+end;
+
+procedure TFPRepository.BackupFile(AFileName: String);
+
+Var
+  S : String;
+
+begin
+  S:=AFileName+'.bak';
+  if not RenameFile(AFileName,S) then
+    Raise EPackage.CreateFmt(SErrBackupFailed,[AFileName,S]);
+end;
+
+
+destructor TFPRepository.Destroy;
+begin
+  FreeAndNil(FPackages);
+  inherited Destroy;
+end;
+
+procedure TFPRepository.LoadFromStream(Stream: TStream);
+
+Var
+  I : Integer;
+  V : Integer;
+
+
+begin
+  Stream.ReadBuffer(I,SizeOf(Integer));
+  If (I<>StreamSignature) then
+    Raise EPackage.Create(SErrInvalidRepositorySig);
+  Stream.ReadBuffer(V,SizeOf(V));
+  FPackages.LoadFromStream(Stream);
+end;
+
+procedure TFPRepository.SaveToStream(Stream: TStream);
+
+Var
+  i : Integer;
+
+begin
+  I:=StreamSignature;
+  Stream.WriteBuffer(I,SizeOf(Integer));
+  I:=StreamVersion;
+  Stream.WriteBuffer(I,SizeOf(Integer));
+  FPackages.SaveToStream(Stream);
+end;
+
+procedure TFPRepository.LoadFromFile(AFileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(AFileName,fmopenRead);
+  Try
+    LoadFromStream(F);
+    FFileName:=AFileName;
+  Finally
+    F.Free;
+  end;
+end;
+
+procedure TFPRepository.SaveToFile(AFileName: String);
+
+Var
+  F : TFileStream;
+  S : String;
+
+begin
+  If FileExists(AFileName) and BackupFiles then
+    BackupFile(AFileName);
+  F:=TFileStream.Create(AFileName,fmCreate);
+  Try
+    SaveToStream(F);
+    FFileName:=AFileName;
+  Finally
+    F.Free;
+  end;
+end;
+
+procedure TFPRepository.Save;
+begin
+  If (FFileName='') then
+     Raise EPackage.Create(SErrNoFileName);
+  SaveToFile(FFileName);
+end;
+
+procedure TFPRepository.LoadVersionsFromStream(Stream: TStream);
+
+Var
+  L : TStrings;
+  I : Integer;
+  N,V : String;
+
+begin
+  L:=TStringList.Create;
+  Try
+    L.LoadFromStream(Stream);
+    For I:=0 to L.Count-1 do
+      begin
+      L.GetNameValue(I,N,V);
+      If (N<>'') and (V<>'') then
+        PackageByName(N).InstalledVersion.AsString:=V;
+      end;
+  Finally
+    L.Free;
+  end;
+end;
+
+procedure TFPRepository.SaveVersionsToStream(Stream: TStream;InstalledVersions : Boolean);
+
+Var
+  L : TStrings;
+  I : Integer;
+
+begin
+  L:=TStringList.Create;
+  Try
+    If InstalledVersions then
+      For I:=0 to PackageCount-1 do
+        With Packages[i] do
+          L.Add(Name+'='+InstalledVersion.AsString)
+    else
+      For I:=0 to PackageCount-1 do
+        With Packages[i] do
+         L.Add(Name+'='+Version.AsString);
+    L.SaveToStream(Stream);
+  Finally
+    L.Free;
+  end;
+end;
+
+procedure TFPRepository.LoadVersionsFromFile(AFileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(AFileName,fmOpenRead);
+  Try
+    LoadVersionsFromStream(F);
+  Finally
+    F.Free;
+  end;
+end;
+
+procedure TFPRepository.SaveVersionsToFile(AFileName: String; InstalledVersions : Boolean);
+
+Var
+  F : TFileStream;
+
+begin
+  If FileExists(AFileName) and BackupFiles then
+    BackupFile(AFileName);
+  F:=TFileStream.Create(AFileName,fmCreate);
+  Try
+    SaveVersionsToStream(F,InstalledVersions);
+  Finally
+    F.Free;
+  end;
+end;
+
+function TFPRepository.IndexOfPackage(PackageName: String): Integer;
+begin
+  Result:=FPackages.IndexOfPackage(PackageName);
+end;
+
+function TFPRepository.FindPackage(PackageName: String): TFPPackage;
+begin
+  Result:=FPackages.FindPackage(PackageName);
+end;
+
+function TFPRepository.PackageByName(PackageName: String): TFPPackage;
+begin
+  Result:=FPackages.PackageByName(PackageName);
+end;
+
+procedure TFPRepository.RemovePackage(PackageName: string);
+begin
+  PackageByName(PackageName).Free;
+end;
+
+procedure TFPRepository.DeletePackage(Index : Integer);
+begin
+  GetPackage(Index).Free;
+end;
+
+function TFPRepository.AddPackage(PackageName: string): TFPPackage;
+
+begin
+  Result:=FPackages.AddPackage(PackageName);
+end;
+
+procedure TFPRepository.DoGetPackageDependencies(PackageName: String;
+  List: TStringList; Level: Integer);
+Var
+  P : TFPPackage;
+  D2,D1 : TFPDependency;
+  i,J : Integer;
+
+begin
+  // If too many levels, bail out
+  If (Level>FMaxDependencyLevel) then
+    Raise EPackage.CreateFmt(SErrMaxLevelExceeded,[Level,PackageName]);
+  // Check if it is a known package.
+  P:=FindPackage(PackageName);
+  If Assigned(P) and P.HasDependencies then
+    For I:=0 to P.Dependencies.Count-1 do
+      begin
+      D1:=P.Dependencies[i];
+      J:=List.IndexOf(PackageName);
+      If J=-1 then
+        begin
+        // Dependency not yet in list.
+        D2:=TFPDependency.Create(Nil);
+        D2.Assign(D1);
+        List.AddObject(D2.PackageName,D2);
+        end
+      else
+        begin
+        // Dependency already in list, compare versions.
+        D2:=List.Objects[J] as TFPDependency;
+        If D1.MinVersion.CompareVersion(D2.MinVersion)>0 then
+          D2.MinVersion.Assign(D1.MinVersion);
+        end;
+      // If it was already in the list, we no longer recurse.
+      If (Level>=0) and (J=-1) Then
+        DoGetPackageDependencies(D2.PackageName,List,Level+1);
+      end;
+end;
+
+procedure TFPRepository.GetPackageDependencies(PackageName: String;
+  List: TObjectList; Recurse: Boolean);
+
+Var
+  L : TStringList;
+  I : Integer;
+  
+begin
+  L:=TStringList.Create;
+  Try
+    L.Sorted:=True;
+    DoGetPackageDependencies(PackageName,L,Ord(Recurse)-1);
+    For I:=0 to L.Count-1 do
+      List.Add(L.Objects[i]);
+  Finally
+    // Freeing a stringlist does not free the objects.
+    L.Free;
+  end;
+end;
+
+
+{ TFPDependency }
+
+procedure TFPDependency.SetMinVersion(const AValue: TFPVersion);
+begin
+  FMinVersion.Assign(AValue);
+end;
+
+constructor TFPDependency.Create(ACollection: TCollection);
+begin
+  inherited Create(ACollection);
+  FMinVersion:=TFPVersion.Create;
+end;
+
+destructor TFPDependency.Destroy;
+begin
+  FreeAndNil(FMinVersion);
+  inherited Destroy;
+end;
+
+procedure TFPDependency.LoadFromStream(Stream: TStream; Streamversion: Integer
+  );
+begin
+  PackageName:=ReadString(Stream);
+  MinVersion.AsString:=ReadString(Stream)
+end;
+
+procedure TFPDependency.SaveToStream(Stream: TStream);
+begin
+  WriteString(Stream,PackageName);
+  WriteString(Stream,MinVersion.AsString);
+end;
+
+procedure TFPDependency.Assign(Source: TPersistent);
+begin
+  If Source is TFPDependency then
+    With Source as TFPDependency do
+      begin
+      Self.PackageName:=PackageName;
+      Self.MinVersion:=MinVersion;
+      end
+  else
+    inherited Assign(Source);
+end;
+
+{ TFPDependencies }
+
+function TFPDependencies.GetDependency(Index : Integer): TFPDependency;
+begin
+  Result:=TFPDependency(Items[Index]);
+end;
+
+procedure TFPDependencies.SetDependency(Index : Integer;
+  const AValue: TFPDependency);
+begin
+  Items[Index]:=AValue;
+end;
+
+function TFPDependencies.AddDependency(const APackageName: String;
+  AMinVersion: String): TFPDependency;
+begin
+  Result:=Add as TFPDependency;
+  Result.PackageName:=APackageName;
+  If (AMinVersion<>'') then
+    Result.MinVersion.AsString:=AMinVersion;
+end;
+
+end.

+ 831 - 0
utils/fppkg/fpxmlrep.pp

@@ -0,0 +1,831 @@
+{
+    This file is part of the Free Pascal Utilities
+    Copyright (c) 1999-2000 by the Free Pascal development team
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit fpxmlrep;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, dom, fprepos, fpmktype;
+  
+Type
+
+  { TFPXMLRepositoryHandler }
+
+  TFPXMLRepositoryHandler = Class(TObject)
+  private
+    FIgnoreUnknownNodes: Boolean;
+  Protected
+    Function AddTextNode(Const NodeName,NodeContent : String; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement;
+    Function GetNextElement(Start : TDomNode) : TDomElement;
+    Function FindNextElement(Start : TDomNode; NodeName : String) : TDomElement;
+    Function NodeText(E : TDomElement) : String;
+    procedure CheckNodeType(E : TDomElement; NodeName : String);
+    // The DO versions do not check the node type. They do the actual work
+    // for the public XMLtoXYZ versions..
+    Function  DoXMLToCPUs(N : TDomElement) : TCPUs; virtual;
+    Function  DoXMLToOSes(N : TDomElement) : TOSes; virtual;
+    Procedure DoXMLToVersion(E : TDomElement; V : TFPVersion); virtual;
+    Procedure DoXMLToDependency(E : TDomElement; D : TFPDependency); virtual;
+    Procedure DoXMLToDependencies(E : TDomElement; DS : TFPDependencies); virtual;
+    Procedure DoXMLToPackage(E : TDomElement; P : TFPPackage); virtual;
+    Procedure DoXMLToPackages(E : TDomElement; PS: TFPPackages); virtual;
+    Procedure DoXMLToRepository(E : TDomElement; R: TFPRepository);  virtual;
+  Public
+    // Saving
+    Function VersionToXML(V : TFPVersion; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
+    Function DependencyToXML(D : TFPDependency; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
+    Function DependenciesToXML(DS : TFPDependencies; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
+    Function PackageToXML(P : TFPPackage; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
+    Function PackagesToXML(PS: TFPPackages; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement; virtual;
+    Function RepositoryToXML(R : TFPRepository; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement;  virtual;
+    Procedure SaveToXml(D : TFPDependency; Stream : TStream);
+    Procedure SaveToXml(DS : TFPDependencies; Stream : TStream);
+    Procedure SaveToXml(P : TFPPackage; Stream : TStream);
+    Procedure SaveToXml(PS : TFPPackages; Stream : TStream);
+    Procedure SaveToXml(R : TFPRepository; Stream : TStream);
+    Procedure SaveToXml(D : TFPDependency; FileName : String);
+    Procedure SaveToXml(DS : TFPDependencies; FileName : String);
+    Procedure SaveToXml(P : TFPPackage; FileName : String);
+    Procedure SaveToXml(PS : TFPPackages; FileName : String);
+    Procedure SaveToXml(R : TFPRepository; FileName : String);
+    // Loading
+    Procedure XMLToVersion(E : TDomElement; V : TFPVersion);
+    Procedure XMLToDependency(E : TDomElement; D : TFPDependency);
+    Procedure XMLToDependencies(E : TDomElement; DS : TFPDependencies);
+    Procedure XMLToPackage(E : TDomElement; P : TFPPackage);
+    Procedure XMLToPackages(E : TDomElement; PS: TFPPackages);
+    Procedure XMLToRepository(E : TDomElement; R: TFPRepository);
+    Procedure LoadFromXml(D : TFPDependency; Stream : TStream);
+    Procedure LoadFromXml(DS : TFPDependencies; Stream : TStream);
+    Procedure LoadFromXml(P : TFPPackage; Stream : TStream);
+    Procedure LoadFromXml(PS : TFPPackages; Stream : TStream);
+    Procedure LoadFromXml(R : TFPRepository; Stream : TStream);
+    Procedure LoadFromXml(D : TFPDependency; FileName : String);
+    Procedure LoadFromXml(DS : TFPDependencies; FileName : String);
+    Procedure LoadFromXml(P : TFPPackage; FileName : String);
+    Procedure LoadFromXml(PS : TFPPackages; FileName : String);
+    Procedure LoadFromXml(R : TFPRepository; FileName : String);
+    property IgnoreUnknownNodes : Boolean Read FIgnoreUnknownNodes Write FIgnoreUnknownNodes;
+  end;
+
+  EXMLPackage = Class(EPackage);
+  
+implementation
+
+uses xmlwrite,xmlread,typinfo;
+
+Const
+  SNodeRepository   = 'repository';
+  SNodePackages     = 'packages';
+  SNodePackage      = 'package';
+  SNodeAuthor       = 'author';
+  SNodeLicense      = 'license';
+  SNodeURL          = 'url';
+  SNodeEmail        = 'email';
+  SNodeVersion      = 'version';
+  SNodeDescription  = 'description';
+  SNodeDependencies = 'dependencies';
+  SNodeDependency   = 'dependency';
+  SNodeOSes         = 'oses';
+  SNodeCPUS         = 'cpus';
+  SNodeOS           = 'os';
+  SNodeCPU          = 'cpu';
+
+  SAttrName         = 'name';
+  SAttrPackageName  = 'packagename';
+  SAttrMinVersion   = 'minversion';
+  SAttrRelease      = 'release';
+  SAttrMajor        = 'major';
+  SAttrMinor        = 'minor';
+  SAttrSuffix       = 'suffix';
+
+ResourceString
+  SErrInvalidXMLDocument = 'Wrong root tag in XML document. Expected "%s", got "%s".';
+  SErrUnknownPackageNode = 'Unknown XML tag ("%s") encountered while reading package "%s".';
+  SErrInvalidDependencyXML = 'Invalid XMl encountered when reading dependency.';
+  
+{ TFPXMLRepositoryHandler }
+
+function TFPXMLRepositoryHandler.VersionToXML(V : TFPVersion;
+  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
+begin
+  Result:=XML.CreateElement(SNodeVersion);
+  try
+    If Not Assigned(Parent) then
+      Parent:=XML;
+    Parent.AppendChild(Result);
+    Result[SAttrRelease]:=IntToStr(V.Release);
+    Result[SAttrMajor]:=IntToStr(V.Major);
+    Result[SAttrMinor]:=IntToStr(V.Minor);
+    Result[SAttrSuffix]:=V.Suffix;
+  except
+    Parent.RemoveChild(Result);
+    Result.Free;
+    Raise;
+  end;
+end;
+
+function TFPXMLRepositoryHandler.DependencyToXML(D: TFPDependency;
+  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
+  
+Var
+  E : TDOMElement;
+  
+begin
+  Result:=XML.CreateElement(SNodeDependency);
+  Try
+    If Not Assigned(Parent) then
+      Parent:=XML;
+    Parent.AppendChild(Result);
+    E:=XML.CreateElement(SNodePackage);
+    E[SAttrPackageName]:=D.PackageName;
+    If Not D.MinVersion.Empty then
+      E[SAttrMinVersion]:=D.MinVersion.AsString;
+    Result.AppendChild(E);
+  Except
+    Parent.RemoveChild(Result);
+    Result.Free;
+    Raise;
+  end;
+end;
+
+function TFPXMLRepositoryHandler.DependenciesToXML(DS: TFPDependencies;
+  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
+
+Var
+  I : Integer;
+   
+begin
+  If (DS.Count>0) then
+    begin
+    Result:=XML.CreateElement(SNodeDependencies);
+    Try
+      If Not Assigned(Parent) then
+        Parent:=XML;
+      Parent.AppendChild(Result);
+      For I:=0 to DS.Count-1 do
+        DependencyToXML(DS[i],XML,Result);
+    except
+      Parent.RemoveChild(Result);
+      Result.Free;
+      Raise;
+    end;
+    end;
+end;
+
+function TFPXMLRepositoryHandler.AddTextNode(Const NodeName,NodeContent : String; XML : TXMLDocument; Parent : TDomNode_WithChildren) : TDomElement;
+
+begin
+  Result:=XML.CreateElement(NodeName);
+  Try
+    Result.AppendChild(XML.CreateTextNode(NodeContent));
+    If Assigned(Parent) then
+      Parent.AppendChild(Result);
+  Except
+    Parent.RemoveChild(Result);
+    Result.Free;
+    Raise;
+  end;
+end;
+
+function TFPXMLRepositoryHandler.GetNextElement(Start: TDomNode): TDomElement;
+  
+begin
+  Result:=Nil;
+  While (Start<>Nil) and (Start.NodeType<>ELEMENT_NODE) do
+    Start:=Start.NextSibling;
+  If (Start<>Nil) then
+    Result:=Start as TDomElement;
+end;
+
+function TFPXMLRepositoryHandler.FindNextElement(Start: TDomNode; NodeName: String): TDomElement;
+begin
+  Result:=GetNextElement(Start);
+  While (Result<>Nil) and (Result.NodeName<>NodeName) do
+    Result:=GetNextElement(Result);
+end;
+
+procedure TFPXMLRepositoryHandler.CheckNodeType(E : TDomElement; NodeName : String);
+
+begin
+  If (E.NodeName<>NodeName) then
+    Raise EXMLPackage.CreateFmt(SErrInvalidXMLDocument,[NodeName,E.NodeName]);
+end;
+
+Function TFPXMLRepositoryHandler.NodeText(E : TDomElement) : String;
+
+Var
+  N : TDomNode;
+
+begin
+  N:=E.FirstChild;
+  While (N<>Nil) and (N.NodeType<>TEXT_NODE) do
+    N:=N.NextSibling;
+  If (N<>Nil) then
+    Result:=N.NodeValue;
+end;
+
+function TFPXMLRepositoryHandler.PackageToXML(P: TFPPackage;
+  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
+
+Var
+  E,ES : TDomElement;
+  O : TOS;
+  C : TCPU;
+
+begin
+  Result:=XML.CreateElement(SNodePackage);
+  Try
+    If Not Assigned(Parent) then
+      Parent:=XMl;
+    Parent.AppendChild(Result);
+    Result[SAttrName]:=P.Name;
+    // Version
+    VersionToXML(P.Version,XML,Result);
+    AddTextNode(SNodeAuthor,P.Author,XML,Result);
+    AddTextNode(SNodeURL,P.URL,XML,Result);
+    AddTextNode(SNodeEmail,P.Email,XML,Result);
+    AddTextNode(SNodeDescription,P.Description,XML,Result);
+    AddTextNode(SNodeLicense,P.License,XML,Result);
+    // OSes
+    E:=XML.CreateElement(SNodeOSes);
+    Result.AppendChild(E);
+    For O:=Low(TOS) to High(TOS) do
+      If (O in P.OSes) then
+        begin
+        ES:=XML.CreateElement(SNodeOS);
+        ES[SAttrName]:=GetEnumName(TypeInfo(TOS),Ord(O));
+        E.AppendChild(ES);
+        end;
+    // CPUs    
+    E:=XML.CreateElement(SNodeCPUs);
+    Result.AppendChild(E);
+    For C:=Low(TCPU) to High(TCPU) do
+      If (C in P.CPUS) then
+        begin
+        ES:=XML.CreateElement(SNodeCPU);
+        ES[SAttrName]:=GetEnumName(TypeInfo(TCPU),Ord(C));
+        E.AppendChild(ES);
+        end;
+    If P.HasDependencies then
+      DependenciesToXML(P.Dependencies,XML,Result);
+  Except
+    Parent.RemoveChild(Result);
+    Result.Free;
+    Raise;
+  end;
+end;
+
+function TFPXMLRepositoryHandler.PackagesToXML(PS: TFPPackages;
+  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
+
+Var
+  I : Integer;
+  
+begin
+  Result:=XML.CreateElement(SNodePackages);
+  Try
+    If Not Assigned(Parent) then
+      Parent:=XML;
+    Parent.AppendChild(Result);
+    For I:=0 to PS.Count-1 do
+      PackageToXML(PS[i],XML,Result);
+  except
+    Parent.RemoveChild(Result);
+    Result.Free;
+    Raise;
+  end;
+end;
+
+
+function TFPXMLRepositoryHandler.RepositoryToXML(R: TFPRepository;
+  XML: TXMLDocument; Parent : TDomNode_WithChildren): TDomElement;
+  
+Var
+  I : Integer;
+  P : TDomElement;
+  
+begin
+  Result:=XML.CreateElement(sNodeRepository);
+  Try
+    If Not Assigned(Parent) then
+      Parent:=XML;
+    Parent.AppendChild(Result);
+    If (R.PackageCount>0) then
+      begin
+      P:=XML.CreateElement(SNodePackages);
+      Try
+        Result.AppendChild(P);
+        For I:=0 to R.PackageCount-1 do
+          PackageToXML(R.Packages[i],XML,P);
+      except
+        Result.RemoveChild(P);
+        P.Free;
+        Raise;
+      end;
+      end;
+  except
+    Parent.RemoveChild(Result);
+    Result.Free;
+    Raise;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(D: TFPDependency; Stream: TStream);
+
+Var
+  X : TXMLDocument;
+
+begin
+  X:=TXMLDocument.Create;
+  Try
+    DependencyToXML(D,X,Nil);
+    WriteXMLFile(X,Stream);
+  Finally
+    D.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(DS: TFPDependencies; Stream: TStream);
+
+Var
+  D : TXMLDocument;
+
+begin
+  D:=TXMLDocument.Create;
+  Try
+    DependenciesToXML(DS,D,Nil);
+    WriteXMLFile(D,Stream);
+  Finally
+    D.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(P: TFPPackage; Stream: TStream);
+
+Var
+  D : TXMLDocument;
+
+begin
+  D:=TXMLDocument.Create;
+  Try
+    PackageToXML(P,D,Nil);
+    WriteXMLFile(D,Stream);
+  Finally
+    D.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(PS: TFPPackages; Stream: TStream);
+
+Var
+  D : TXMLDocument;
+
+begin
+  D:=TXMLDocument.Create;
+  Try
+    PackagesToXML(PS,D,Nil);
+    WriteXMLFile(D,Stream);
+  Finally
+    D.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(R: TFPRepository; Stream: TStream);
+
+Var
+  D : TXMLDocument;
+
+begin
+  D:=TXMLDocument.Create;
+  Try
+    RepositoryToXML(R,D,Nil);
+    WriteXMLFile(D,Stream);
+  Finally
+    D.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(D: TFPDependency; FileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmCreate);
+  try
+    SaveToXML(D,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(DS: TFPDependencies; FileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmCreate);
+  try
+    SaveToXML(DS,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(P: TFPPackage; FileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmCreate);
+  try
+    SaveToXML(P,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(PS: TFPPackages; FileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmCreate);
+  try
+    SaveToXML(PS,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.SaveToXml(R: TFPRepository; FileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmCreate);
+  try
+    SaveToXML(R,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.XMLToVersion(E: TDomElement; V: TFPVersion);
+begin
+  CheckNodeType(E,SNodeVersion);
+  DoXMLToVersion(E,V);
+end;
+
+procedure TFPXMLRepositoryHandler.DoXMLToVersion(E: TDomElement; V: TFPVersion);
+begin
+  V.Release:=Abs(StrToIntDef(E[SAttrRelease],0));
+  V.Major:=Abs(StrToIntDef(E[SAttrMajor],0));
+  V.Minor:=Abs(StrToIntDef(E[SAttrMinor],0));
+  V.Suffix:=E[SAttrSuffix];
+end;
+
+procedure TFPXMLRepositoryHandler.XMLToDependency(E: TDomElement; D: TFPDependency);
+begin
+  CheckNodeType(E,SNodeDependency);
+  DoXMLToDependency(E,D);
+end;
+
+procedure TFPXMLRepositoryHandler.DoXMLToDependency(E: TDomElement; D: TFPDependency);
+begin
+  E:=FindNextElement(E.FirstChild,SNodePackage);
+  If (E=Nil) then
+    Raise EXMLpackage.Create(SErrInvalidDependencyXML);
+  D.PackageName:=E[SAttrPackageName];
+  D.MinVersion.AsString:=E[SAttrMinVersion];
+end;
+
+procedure TFPXMLRepositoryHandler.XMLToDependencies(E: TDomElement; DS: TFPDependencies);
+  
+begin
+  CheckNodeType(E,SNodeDependencies);
+  DoXMLToDependencies(E,DS)
+end;
+  
+procedure TFPXMLRepositoryHandler.DoXMLToDependencies(E: TDomElement;
+  DS: TFPDependencies);
+  
+Var
+  DN : TDomElement;
+  D : TFPDependency;
+  
+begin
+  DN:=FindNextElement(E.FirstChild,SNodeDependency);
+  While (DN<>Nil) do
+    begin
+    D:=DS.AddDependency('','');
+    Try
+      DoXMLToDependency(DN,D);
+    except
+      D.Free;
+      Raise;
+    end;
+    DN:=FindNextElement(DN.NextSibling,SNodeDependency);
+    end;
+end;
+
+procedure TFPXMLRepositoryHandler.XMLToPackage(E: TDomElement; P: TFPPackage);
+
+begin
+  CheckNodeType(E,sNodePackage);
+  DoXMLToPackage(E,P);
+end;
+
+Function TFPXMLRepositoryHandler.DoXMLToOSes(N : TDomElement) : TOSes;
+
+Var
+  E : TDomElement;
+  J : Integer;
+
+begin
+  Result:=[];
+  E:=FindNextElement(N.FirstChild,SNodeOS);
+  While (E<>Nil) do
+    begin
+    J:=GetEnumValue(TypeInfo(TOS),E[SAttrName]);
+    If (J<>-1) then
+      Include(Result,TOS(J));
+    E:=FindNextElement(E.NextSibling,SNodeOS);
+    end;
+end;
+
+Function TFPXMLRepositoryHandler.DoXMLToCPUs(N : TDomElement) : TCPUS;
+
+Var
+  E : TDomElement;
+  J : Integer;
+
+begin
+  Result:=[];
+  E:=FindNextElement(N.FirstChild,SNodeCPU);
+  While (E<>Nil) do
+    begin
+    J:=GetEnumValue(TypeInfo(TCPU),E[SAttrName]);
+    If (J<>-1) then
+      Include(Result,TCPU(J));
+    E:=FindNextElement(E.NextSibling,SNodeCPU);
+    end;
+end;
+
+procedure TFPXMLRepositoryHandler.DoXMLToPackage(E: TDomElement; P: TFPPackage);
+
+Var
+  N : TDomElement;
+
+begin
+  P.Name:=E[sAttrName];
+  N:=GetNextElement(E.FirstChild);
+  While (N<>Nil) do
+    begin
+    if (N.NodeName=sNodeAuthor) then
+      P.Author:=NodeText(N)
+    else if (N.NodeName=sNodeURl) then
+      P.URL:=NodeText(N)
+    else if (N.NodeName=sNodeEmail) then
+      P.Email:=NodeText(N)
+    else if (N.NodeName=sNodeDescription) then
+      P.Description:=NodeText(N)
+    else if (N.NodeName=sNodeLicense) then
+      P.License:=NodeText(N)
+    else if (N.NodeName=sNodeVersion) then
+      DoXMlToVersion(N,P.Version)
+    else if (N.NodeName=sNodeOSes) then
+      P.OSes:=DoXMLToOSes(N)
+    else if (N.NodeName=sNodeCPUS) then
+      P.CPUs:=DoXMLToCPUs(N)
+    else if (N.NodeName=sNodeDependencies) then
+      DoXMlToDependencies(N,P.Dependencies)
+    else if Not IgnoreUnknownNodes then
+      Raise EXMLPackage.CreateFmt(SErrUnknownPackageNode,[N.NodeName,P.Name]);
+    N:=GetNextElement(N.NextSibling);
+    end;
+end;
+
+procedure TFPXMLRepositoryHandler.XMLToPackages(E: TDomElement; PS: TFPPackages);
+
+begin
+  CheckNodeType(E,SNodePackages);
+  DoXMLToPackages(E,PS);
+end;
+
+procedure TFPXMLRepositoryHandler.DoXMLToPackages(E: TDomElement; PS: TFPPackages);
+
+Var
+  PSN,PN : TDomElement;
+  P : TFPPackage;
+
+begin
+  PN:=FindNextElement(PSN.FirstChild,SNodePackage);
+  While (PN<>Nil) do
+    begin
+    P:=PS.AddPackage('');
+    try
+      DoXMLToPackage(PN,P);
+    except
+      P.Free;
+    end;
+    PN:=FindNextElement(PN.NextSibling,SNodePackage);
+    end;
+end;
+
+procedure TFPXMLRepositoryHandler.XMLToRepository(E: TDomElement; R: TFPRepository);
+
+begin
+  CheckNodeType(E,SNodeRepository);
+  DoXMLToRepository(E,R);
+end;
+
+procedure TFPXMLRepositoryHandler.DoXMLToRepository(E: TDomElement; R: TFPRepository);
+
+Var
+  PSN,PN : TDomElement;
+  P : TFPPackage;
+  
+begin
+  PSN:=FindNextElement(E.FirstChild,SNodePackages);
+  If (PSN<>Nil) then
+    begin
+    PN:=FindNextElement(PSN.FirstChild,SNodePackage);
+    While (PN<>Nil) do
+      begin
+      P:=R.AddPackage('');
+      try
+        DoXMLToPackage(PN,P);
+      except
+        P.Free;
+      end;
+      PN:=FindNextElement(PN.NextSibling,SNodePackage);
+      end;
+    end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(D: TFPDependency; Stream: TStream);
+
+Var
+  XML : TXMLDocument;
+
+begin
+  XML:=TXMLDocument.Create;
+  try
+    Xmlread.ReadXMLFile(XML,Stream);
+    XmlToDependency(XML.DocumentElement,D);
+  finally
+    XML.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(DS: TFPDependencies;
+  Stream: TStream);
+  
+Var
+  XML : TXMLDocument;
+
+begin
+  XML:=TXMLDocument.Create;
+  try
+    xmlread.ReadXMLFile(XML,Stream);
+    XmlToDependencies(XML.DocumentElement,DS);
+  finally
+    XML.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(P: TFPPackage; Stream: TStream);
+
+Var
+  XML : TXMLDocument;
+
+begin
+  XML:=TXMLDocument.Create;
+  try
+    xmlread.ReadXMLFile(XML,Stream);
+    XmlToPackage(XML.DocumentElement,P);
+  finally
+    XML.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(PS: TFPPackages; Stream: TStream);
+  
+Var
+  XML : TXMLDocument;
+
+begin
+  XML:=TXMLDocument.Create;
+  try
+    xmlread.ReadXMLFile(XML,Stream);
+    XmlToPackages(XML.DocumentElement,PS);
+  finally
+    XML.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(R: TFPRepository; Stream: TStream);
+
+Var
+  XML : TXMLDocument;
+
+begin
+  XML:=TXMLDocument.Create;
+  try
+    xmlread.ReadXMLFile(XML,Stream);
+    XmlToRepository(XML.DocumentElement,R);
+  finally
+    XML.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(D: TFPDependency; FileName: String);
+  
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmOpenRead);
+  try
+    LoadFromXMl(D,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(DS: TFPDependencies; FileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmOpenRead);
+  try
+    LoadFromXMl(DS,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(P: TFPPackage; FileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmOpenRead);
+  try
+    LoadFromXMl(P,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(PS: TFPPackages; FileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(FileName,fmOpenRead);
+  try
+    LoadFromXMl(PS,F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TFPXMLRepositoryHandler.LoadFromXml(R: TFPRepository; FileName: String);
+  
+Var
+  F : TFileStream;
+  
+begin
+  F:=TFileStream.Create(FileName,fmOpenRead);
+  try
+    LoadFromXMl(R,F);
+  finally
+    F.Free;
+  end;
+end;
+
+end.
+

+ 245 - 0
utils/fppkg/pkgropts.pp

@@ -0,0 +1,245 @@
+{
+    This file is part of the Free Pascal Utilities
+    Copyright (c) 1999-2000 by the Free Pascal development team
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit pkgropts;
+
+interface
+
+uses Classes, Sysutils, Inifiles, fpmktype;
+
+Type
+
+  { TPackagerOptions }
+
+  TPackagerOptions = Class(TPersistent)
+  private
+    FRemoteMirrorsLocation : String;
+    FLocalMirrorsLocation : String;
+    FRemoteRepository : String;
+    FLocalRepository : String;
+    FInstallDir : String;
+    FBuildDir : String;
+    FCompiler : String;
+    FCPU: TCPU;
+    FDirty: Boolean;
+    FOS: TOS;
+    FLocalDir : String;
+    function GetOptString(Index: integer): String;
+    procedure SetCPU(const AValue: TCPU);
+    procedure SetOptString(Index: integer; const AValue: String);
+    procedure SetOS(const AValue: TOS);
+  protected
+    Property LocalDir : String Read FLocalDir;
+  Public
+    Constructor Create;
+    Procedure InitDefaults;
+    Procedure LoadFromIni(Ini : TCustomIniFile); virtual;
+    Procedure SaveToIni(Ini : TCustomIniFile); virtual;
+    Procedure LoadFromFile(FileName : String);
+    Procedure SaveToFile(FileName : String);
+    Property Dirty : Boolean Read FDirty;
+  Published
+    Property RemoteMirrorsLocation : String Index 0 Read GetOptString Write SetOptString;
+    Property LocalMirrorsLocation : String Index 1 Read GetOptString Write SetOptString;
+    Property RemoteRepository : String Index 2 Read GetOptString Write SetOptString;
+    Property LocalRepository : String Index 3 Read GetOptString Write SetOptString;
+    Property InstallDir : String Index 4 Read GetOptString Write SetOptString;
+    Property BuildDir : String Index 5 Read GetOptString Write SetOptString;
+    Property Compiler : String Index 6 Read GetOptString Write SetOptString;
+    Property Target : String Index 7 Read GetOptString Write SetOptString;
+    Property OS : TOS Read FOS Write SetOS;
+    Property CPU : TCPU Read FCPU Write SetCPU;
+  end;
+
+Const
+  DefaultCPU = {$I %FPCTARGETCPU%};
+  DefaultOS  = {$I %FPCTARGETOS%};
+  DefaultMirrorsLocation  = 'http://www.freepascal.org/repository/mirrors.xml';
+  DefaultCompiler = 'fpc';
+  DefaultRemoteRepository = 'fpc';
+  DefaultUnixPrefix = '/usr/local/lib/fpc/fppkg';
+  DefaultUnixBuildDir = '/tmp/fppkg/';
+  DefaultMirrors = 'mirrors.xml';
+  DefaultRepository = 'repository.dat';
+
+  // ini file keys
+  SDefaults = 'Defaults';
+
+  KeyLocalMirrorsLocation  = 'LocalMirrors';
+  KeyRemoteMirrorsLocation = 'RemoteMirrors';
+  KeyRemoteRepository      = 'RemoteRepository';
+  KeyLocalRepository       = 'LocalRepository';
+  KeyInstallDir            = 'InstallDir';
+  KeyBuildDir              = 'BuildDir';
+  KeyCompiler              = 'Compiler' ;
+  KeyOS                    = 'OS';
+  KeyCPU                   = 'CPU';
+
+
+Implementation
+
+{$ifdef unix}
+uses baseunix;
+{$endif}
+Function FixPath(S : String) : string;
+
+begin
+  If (S<>'') then
+    Result:=IncludeTrailingPathDelimiter(S)
+  else
+    Result:='';
+end;
+
+
+{ TPackagerOptions }
+
+function TPackagerOptions.GetOptString(Index: integer): String;
+begin
+  Case Index of
+    0 : Result:=FRemoteMirrorsLocation;
+    1 : Result:=FLocalMirrorsLocation;
+    2 : Result:=FRemoteRepository;
+    3 : Result:=FLocalRepository;
+    4 : Result:=FInstallDir;
+    5 : Result:=FBuildDir;
+    6 : Result:=FCompiler;
+    7 : Result:=MakeTargetString(CPU,OS);
+  end;
+end;
+
+procedure TPackagerOptions.SetCPU(const AValue: TCPU);
+begin
+  if FCPU=AValue then exit;
+  FCPU:=AValue;
+  FDirty:=True;
+end;
+
+procedure TPackagerOptions.SetOptString(Index: integer; const AValue: String);
+begin
+  If AValue=GetOptString(Index) then
+    Exit;
+  Case Index of
+    0 : FLocalMirrorsLocation:=AValue;
+    1 : FRemoteMirrorsLocation:=AValue;
+    2 : FRemoteRepository:=AValue;
+    3 : FLocalRepository:=AValue;
+    4 : FInstallDir:=FixPath(AValue);
+    5 : FBuildDir:=FixPath(AValue);
+    6 : FCompiler:=AValue;
+    7 : StringToCPUOS(AValue,FCPU,FOS);
+  end;
+  FDirty:=True;
+end;
+
+procedure TPackagerOptions.SetOS(const AValue: TOS);
+begin
+  if FOS=AValue then exit;
+  FOS:=AValue;
+  FDirty:=True;
+end;
+
+constructor TPackagerOptions.Create;
+begin
+  InitDefaults;
+end;
+
+Procedure TPackagerOptions.InitDefaults;
+
+begin
+  FCPU:=StringToCPU(DefaultCPU);
+  FOS:=StringToOS(DefaultOS);
+  FCompiler:=DefaultCompiler;
+  FRemoteMirrorsLocation:=DefaultMirrorsLocation;
+  FRemoteRepository:=DefaultRemoteRepository;
+{$ifdef unix}
+  if (fpGetUID=0) then
+    FLocalDir:=DefaultUnixPrefix
+  else
+    FLocalDir:=IncludeTrailingPathDelimiter(GetEnvironmentVariable('HOME'))+'.fppkg/';
+  FBuildDir:=DefaultUnixBuildDir;
+{$else}
+  // Change as needed on all OS-es...
+  FLocalDir:=ExtractFilePath(Paramstr(0));
+  FBuildDir:=FLocalDir+'build'+PathDelim;
+{$endif}
+  FLocalMirrorsLocation:=FLocalDir+DefaultMirrors;
+  FLocalRepository:=FLocalDir+DefaultRepository;
+end;
+
+procedure TPackagerOptions.LoadFromIni(Ini: TCustomIniFile);
+
+
+
+begin
+ With Ini do
+   begin
+   FLocalMirrorsLocation:=ReadString(SDefaults,KeyLocalMirrorsLocation,FLocalMirrorsLocation);
+   FRemoteMirrorsLocation:=ReadString(SDefaults,KeyRemoteMirrorsLocation,FRemoteMirrorsLocation);
+   FRemoteRepository:=ReadString(SDefaults,KeyRemoteRepository,FRemoteRepository);
+   FLocalRepository:=ReadString(SDefaults,KeyLocalRepository,FLocalRepository);
+   FInstallDir:=FixPath(ReadString(SDefaults,KeyInstallDir,FInstallDir));
+   FBuildDir:=FixPath(ReadString(SDefaults,KeyBuildDir,FBuildDir));
+   FCompiler:=ReadString(SDefaults,KeyCompiler,FCompiler);
+   FOS:=StringToOS(ReadString(SDefaults,KeyOS,OSToString(OS)));
+   FCPU:=StringToCPU(ReadString(SDefaults,KeyCPU,CPUtoString(CPU)));
+   end;
+
+end;
+
+procedure TPackagerOptions.SaveToIni(Ini: TCustomIniFile);
+begin
+ With Ini do
+   begin
+   WriteString(SDefaults,KeyLocalMirrorsLocation,FLocalMirrorsLocation);
+   WriteString(SDefaults,KeyRemoteMirrorsLocation,FRemoteMirrorsLocation);
+   WriteString(SDefaults,KeyRemoteRepository,FRemoteRepository);
+   WriteString(SDefaults,KeyLocalRepository,FLocalRepository);
+   WriteString(SDefaults,KeyInstallDir,FInstallDir);
+   WriteString(SDefaults,KeyBuildDir,FBuildDir);
+   WriteString(SDefaults,KeyCompiler,FCompiler);
+   WriteString(SDefaults,KeyOS,OSToString(OS));
+   WriteString(SDefaults,KeyCPU,CPUtoString(CPU));
+   end;
+end;
+
+procedure TPackagerOptions.LoadFromFile(FileName: String);
+
+Var
+  Ini : TMemIniFile;
+
+begin
+  Ini:=TMemIniFile.Create(FileName);
+  try
+    LoadFromIni(Ini);
+  finally
+    Ini.Free;
+  end;
+end;
+
+procedure TPackagerOptions.SaveToFile(FileName: String);
+
+Var
+  Ini : TIniFile;
+
+begin
+  Ini:=TIniFile.Create(FileName);
+  try
+    SaveToIni(Ini);
+    Ini.UpdateFile;
+  finally
+    Ini.Free;
+  end;
+end;
+
+end.

+ 235 - 0
utils/fppkg/rep2xml.lpi

@@ -0,0 +1,235 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="5"/>
+    <General>
+      <MainUnit Value="0"/>
+      <IconPath Value="./"/>
+      <TargetFileExt Value=""/>
+      <ActiveEditorIndexAtStart Value="2"/>
+    </General>
+    <LazDoc Paths=""/>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <Units Count="7">
+      <Unit0>
+        <Filename Value="rep2xml.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="rep2xml"/>
+        <CursorPos X="26" Y="6"/>
+        <TopLine Value="1"/>
+        <EditorIndex Value="0"/>
+        <UsageCount Value="32"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="fpxmlrep.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpxmlrep"/>
+        <CursorPos X="42" Y="468"/>
+        <TopLine Value="438"/>
+        <EditorIndex Value="1"/>
+        <UsageCount Value="32"/>
+        <Loaded Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="fprepos.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fprepos"/>
+        <CursorPos X="1" Y="179"/>
+        <TopLine Value="158"/>
+        <EditorIndex Value="3"/>
+        <UsageCount Value="32"/>
+        <Loaded Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="streamcoll.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="streamcoll"/>
+        <UsageCount Value="32"/>
+        <SyntaxHighlighter Value="Text"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="reptest.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="reptest"/>
+        <CursorPos X="34" Y="1"/>
+        <TopLine Value="1"/>
+        <EditorIndex Value="5"/>
+        <UsageCount Value="30"/>
+        <Loaded Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="pkgropts.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="pkgropts"/>
+        <CursorPos X="22" Y="18"/>
+        <TopLine Value="16"/>
+        <EditorIndex Value="2"/>
+        <UsageCount Value="24"/>
+        <Loaded Value="True"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="../../../rtl/common/fpmkunit.pp"/>
+        <UnitName Value="fpmkunit"/>
+        <CursorPos X="1" Y="1"/>
+        <TopLine Value="1"/>
+        <EditorIndex Value="4"/>
+        <UsageCount Value="12"/>
+        <Loaded Value="True"/>
+      </Unit6>
+    </Units>
+    <JumpHistory Count="30" HistoryIndex="29">
+      <Position1>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="65" Column="1" TopLine="22"/>
+      </Position1>
+      <Position2>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="132" Column="1" TopLine="90"/>
+      </Position2>
+      <Position3>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="44" Column="1" TopLine="1"/>
+      </Position3>
+      <Position4>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="129" Column="19" TopLine="92"/>
+      </Position4>
+      <Position5>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="91" Column="6" TopLine="64"/>
+      </Position5>
+      <Position6>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="88" Column="30" TopLine="45"/>
+      </Position6>
+      <Position7>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="52" Column="10" TopLine="26"/>
+      </Position7>
+      <Position8>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="90" Column="9" TopLine="68"/>
+      </Position8>
+      <Position9>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="91" Column="23" TopLine="68"/>
+      </Position9>
+      <Position10>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="120" Column="34" TopLine="92"/>
+      </Position10>
+      <Position11>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="126" Column="67" TopLine="92"/>
+      </Position11>
+      <Position12>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="131" Column="3" TopLine="92"/>
+      </Position12>
+      <Position13>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="126" Column="87" TopLine="92"/>
+      </Position13>
+      <Position14>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="131" Column="26" TopLine="92"/>
+      </Position14>
+      <Position15>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="91" Column="48" TopLine="48"/>
+      </Position15>
+      <Position16>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="131" Column="26" TopLine="92"/>
+      </Position16>
+      <Position17>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="132" Column="1" TopLine="92"/>
+      </Position17>
+      <Position18>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="44" Column="29" TopLine="1"/>
+      </Position18>
+      <Position19>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="137" Column="5" TopLine="94"/>
+      </Position19>
+      <Position20>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="159" Column="5" TopLine="96"/>
+      </Position20>
+      <Position21>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="72" Column="6" TopLine="32"/>
+      </Position21>
+      <Position22>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="166" Column="73" TopLine="144"/>
+      </Position22>
+      <Position23>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="167" Column="1" TopLine="144"/>
+      </Position23>
+      <Position24>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="174" Column="7" TopLine="152"/>
+      </Position24>
+      <Position25>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="161" Column="1" TopLine="152"/>
+      </Position25>
+      <Position26>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="178" Column="1" TopLine="146"/>
+      </Position26>
+      <Position27>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="157" Column="31" TopLine="135"/>
+      </Position27>
+      <Position28>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="130" Column="28" TopLine="87"/>
+      </Position28>
+      <Position29>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="74" Column="1" TopLine="31"/>
+      </Position29>
+      <Position30>
+        <Filename Value="pkgropts.pp"/>
+        <Caret Line="97" Column="1" TopLine="54"/>
+      </Position30>
+    </JumpHistory>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="5"/>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="2">
+      <Item1>
+        <Name Value="ECodetoolError"/>
+      </Item1>
+      <Item2>
+        <Name Value="EFOpenError"/>
+      </Item2>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 262 - 0
utils/fppkg/rep2xml.lpr

@@ -0,0 +1,262 @@
+{
+    This file is part of the Free Pascal Utilities
+    Copyright (c) 1999-2000 by the Free Pascal development team
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}{$H+}
+program rep2xml;
+
+uses
+  Classes, fpxmlrep, pkgropts, fprepos, streamcoll, reptest;
+
+
+Procedure TestVersionCompare;
+
+  Procedure CV(V1,V2 : TFPVersion);
+  
+  begin
+    if V1.CompareVersion(V2)>0 then
+      Writeln('Error : ',V1.AsString,'>',V2.AsString);
+  end;
+  
+
+Var
+  V1,V2 : TFPVersion;
+
+begin
+  Writeln('Testing version comparison');
+  V1:=TFPVersion.Create;
+  Try
+    V1.AsString:='1.2.3';
+    V2:=TFPVersion.Create;
+    Try
+      V2.AsString:='1.2.3-b';
+      CV(V1,V2);
+      V2.AsString:='1.2.4';
+      CV(V1,V2);
+      V2.AsString:='1.3.0';
+      CV(V1,V2);
+      V2.AsString:='2.0.0';
+      CV(V1,V2);
+      V2.AsString:=V1.AsString;
+      If V1.CompareVersion(V2)<>0 then
+        Writeln('Error : ',V1.AsString,'<>',V2.AsString);
+    Finally
+      V2.Free;
+    end;
+  Finally
+    V1.Free;
+  end;
+end;
+
+Procedure ComparePackages(P1,P2 : TFPPackage);
+
+Var
+  i : Integer;
+
+
+begin
+  If P1.Name<>P2.Name then
+    Writeln('Names differ: ',P1.Name,'<>',P2.Name);
+  If P1.Version.CompareVersion(P2.Version)<>0 then
+    Writeln('Versions differ: "',P1.Version.AsString,'"<>"',P2.Version.AsString,'"');
+  If P1.Author<>P2.Author then
+    Writeln('Authors differ: ',P1.Author,'"<>"',P2.Author,'"');
+  If P1.URL<>P2.URL then
+    Writeln('URLs differ: "',P1.URL,'"<>"',P2.URL,'"');
+  If P1.Email<>P2.Email then
+    Writeln('Emails differ: "',P1.Email,'"<>"',P2.Email,'"');
+  If P1.Description<>P2.Description then
+    Writeln('Descriptions differ: "',P1.Description,'"<>"',P2.Description,'"');
+  if P1.OSes<>P2.OSes then
+    Writeln('OSes differ');
+  if P1.CPUs<>P2.CPUs then
+    Writeln('CPUs differ');
+  If P1.HasDependencies<>P2.HasDependencies then
+    Writeln('HasDependencies differ: "',P1.HasDependencies,'"<>"',P2.HasDependencies,'"');
+  If P1.HasDependencies then
+    begin
+    If P1.Dependencies.Count<>P2.Dependencies.Count then
+      Writeln('Dependency counts differ: "',P1.Dependencies.Count,'"<>"',P2.Dependencies.Count,'"')
+    else
+      For I:=0 to P1.Dependencies.Count-1 do
+        begin
+        If P1.Dependencies[i].PackageName<>P2.Dependencies[i].PackageName then
+          Writeln('Dependency ',I,' name differs :"',P1.Dependencies[i].PackageName,'"<>"',P2.Dependencies[i].PackageName,'"');
+        If P1.Dependencies[i].Minversion.CompareVersion(P2.Dependencies[i].MinVersion)<>0 then
+          Writeln('Dependency ',I,' minversion differs :"',P1.Dependencies[i].MinVersion.AsString,'"<>"',P2.Dependencies[i].MinVersion.AsString,'"');
+        end;
+    end;
+end;
+
+Procedure TestPackageStream1;
+
+Var
+  P1,P2 : TFPPackage;
+  S : TMemoryStream;
+
+begin
+  Writeln('Testing package streaming (no deps)');
+  P1:=TFPPackage.Create(Nil);
+  Try
+    FillFirstPackage(P1);
+    P2:=TFPPackage.Create(Nil);
+    Try
+      S:=TMemoryStream.Create;
+      try
+        P1.SaveToStream(S);
+        S.Position:=0;
+        P2.LoadFromStream(S,StreamVersion);
+        ComparePackages(P1,P2);
+      finally
+        S.Free;
+      end;
+    Finally
+      P2.Free;
+    end;
+  Finally
+    P1.Free;
+  end;
+end;
+
+Procedure TestPackageStream2;
+
+
+Var
+  P1,P2 : TFPPackage;
+  S : TMemoryStream;
+
+begin
+  Writeln('Testing package streaming (with deps)');
+  P1:=TFPPackage.Create(Nil);
+  Try
+    FillThirdPackage(P1);
+    P2:=TFPPackage.Create(Nil);
+    Try
+      S:=TMemoryStream.Create;
+      try
+        P1.SaveToStream(S);
+        S.Position:=0;
+        P2.LoadFromStream(S,StreamVersion);
+        ComparePackages(P1,P2);
+      finally
+        S.Free;
+      end;
+    Finally
+      P2.Free;
+    end;
+  Finally
+    P1.Free;
+  end;
+end;
+
+Procedure CompareRepositories(R1,R2 : TFPRepository);
+
+var
+  I : Integer;
+begin
+  If (R1.PackageCount<>R2.PackageCount) then
+    Writeln('Package count differs : ',R1.PackageCount,'<>',R2.PackageCount)
+  else
+    For I:=0 to R1.PackageCount-1 do
+      ComparePackages(R1[i],R1[I]);
+end;
+
+Procedure TestRepoStream;
+
+Var
+  R1,R2 : TFPRepository;
+  S : TStream;
+
+begin
+  Writeln('Testing Repository streaming');
+  R1:=CreateTestRep(4);
+  try
+    R2:=TFPrepository.Create(Nil);
+    try
+      S:=TMemoryStream.Create;
+      try
+        R1.SaveToStream(S);
+        S.Position:=0;
+        R2.LoadFromStream(S);
+        CompareRepositories(R1,R2);
+      finally
+        S.Free;
+      end;
+    finally
+      R2.Free;
+    end;
+  finally
+    R1.Free;
+  end;
+end;
+
+Procedure TestXMLWrite;
+
+Var
+  R : TFPRepository;
+  X : TFPXMLRepositoryHandler;
+  
+begin
+  Writeln('Testing XML writing');
+  R:=CreateTestRep(4);
+  try
+    X:=TFPXMLRepositoryHandler.Create;
+    With X do
+      try
+        SaveToXml(R,'packages.xml');
+      finally
+        Free;
+      end;
+  Finally
+    R.Free;
+  end;
+end;
+
+Procedure TestXMLRead;
+
+Var
+  R1,R2 : TFPRepository;
+  X : TFPXMLRepositoryHandler;
+
+begin
+  Writeln('Testing XML reading');
+  R1:=TFPrepository.Create(Nil);
+  try
+    X:=TFPXMLRepositoryHandler.Create;
+    With X do
+      try
+        LoadFromXml(R1,'packages.xml');
+        // Save for test purposes;
+        SaveToXml(R1,'packages2.xml');
+        // Now compare;
+        R2:=CreateTestRep(4);
+        Try
+          CompareRepositories(R1,R2);
+        Finally
+          R2.Free;
+        end;
+      finally
+        Free;
+      end;
+  Finally
+    R1.Free;
+  end;
+end;
+
+begin
+  TestVersionCompare;
+  TestPackageStream1;
+  TestPackageStream2;
+  TestRepoStream;
+  TestXMLWrite;
+  TestXMLRead;
+end.
+

+ 96 - 0
utils/fppkg/reptest.pp

@@ -0,0 +1,96 @@
+{
+    This file is part of the Free Pascal Utilities
+    Copyright (c) 1999-2000 by the Free Pascal development team
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit reptest;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fprepos, fpmktype;
+
+// Num restricted to 1 2 3. 4 will create package with unsatisfied dependency.
+Function CreateTestRep(Num : Integer) : TFPRepository;
+Procedure FillFirstPackage(P : TFPPackage);
+Procedure FillSecondPackage(P : TFPPackage);
+Procedure FillThirdPackage(P : TFPPackage);
+Procedure FillFourthPackage(P : TFPPackage);
+
+implementation
+
+Procedure FillFirstPackage(P : TFPPackage);
+
+begin
+  P.Author:='Michael Van Canneyt';
+  P.URL:='http://www.freepascal.org/packages/firstpackage.zip';
+  P.Email:='[email protected]';
+  P.Version.AsString:='1.2.3';
+  P.Description:='First package in the repository. Provides basic information.';
+  P.OSes:=[Win32,linux];
+  P.CPUs:=[i386,x86_64];
+end;
+
+Procedure FillSecondPackage(P : TFPPackage);
+
+begin
+  P.Author:='Peter Vreman';
+  P.URL:='http://www.freepascal.org/packages/secondpackage.zip';
+  P.Email:='[email protected]';
+  P.Version.AsString:='1.1.0';
+  P.Description:='Second package in the repository. Provides extended information. Needs basic information.';
+  P.AddDependency('FirstPackage','1.2.3');
+  P.OSes:=[linux];
+  P.CPUs:=[x86_64];
+end;
+
+Procedure FillThirdPackage(P : TFPPackage);
+
+begin
+  P.Author:='Florian Klaempfl';
+  P.URL:='http://www.freepascal.org/packages/thirdpackage.zip';
+  P.Email:='[email protected]';
+  P.Version.AsString:='2.1.0';
+  P.Description:='Third package in the repository. Needs basic and extended information.';
+  P.AddDependency('FirstPackage','1.0.0');
+  P.AddDependency('SecondPackage','1.1.0');
+  P.OSes:=[Win32];
+  P.CPUs:=[i386];
+end;
+
+Procedure FillFourthPackage(P : TFPPackage);
+
+begin
+  P.Author:='Bad guy';
+  P.URL:='http://www.freepascal.org/packages/bad.zip';
+  P.Email:='[email protected]';
+  P.Version.AsString:='6.6.6';
+  P.Description:='Fourth package in the repository. Random dependency.';
+  P.AddDependency('FirstPackage','1.0.0');
+  P.AddDependency('NonExistingPackage','3.2.1-?');
+end;
+
+Function CreateTestRep(Num : integer) : TFPRepository;
+
+begin
+  Result:=TFPRepository.Create(Nil);
+  FillFirstPackage(Result.AddPackage('FirstPackage'));
+  If (Num>1) then
+    FillSecondPackage(Result.AddPackage('SecondPackage'));
+  If (Num>2) then
+    FillThirdPackage(Result.AddPackage('ThirdPackage'));
+  If (Num>3) then
+    FillFourthPackage(Result.AddPackage('FourthPackage'));
+end;
+
+end.
+