© 2002 Юрий Жуков
При разработке проекта группой программистов, типичной задачей является сборка очередной версии проекта, далее тестирование этой версии, затем снова сборка и т.п. Что бы собрать очередную версию, ответственному за сборку придется взять последние версии файлов, увеличить номер версии, собрать проект и если все пройдет успешно выложить для тестирования в определенное место готовый файл или файлы. Как правило, приходится вести историю версий. При этом нужно иметь Delphi с установленными библиотеками – соответственно переход на новую версию Delphi или какой-либо из библиотек может вызвать множество проблем: сборка на новой версии может оказаться неработоспособной и придется откатываться на старую версию Delphi и т.п.
Вообщем, это рассказ о том, как можно автоматизировать процесс сборки и отправки версий.
Хочу сразу оговориться, все нижеописанные рецепты работают на Delphi 6 (Update1, Update2).
Если мы говорим об автоматической сборке, то естественно будем пользоваться командной строкой. В стандартной поставке Delphi есть две программы с помощью которых можно собирать проекты: dcc32 и make. Обе они находятся по пути $Delphi\Bin.
DCC32 собирает один файл проекта переданный в качестве командной строки. Остальные параметры (пути к библиотекам, параметры компиляции и т.п.) можно также указать в командной строке либо в файле dcc32.cfg в $Delphi\Bin.
Make собирает все проекты которые указаны в make-файле(на самом деле он последовательно вызывает dcc32 для них). Более того, в этом обычном текстовом файле можно удобно править пути к библиотекам, а также параметры для компиляции.
Простой проект
Итак, создаем директорию где будут находится файлы. Например
C:\Delphi\D6U2RTL
Расшифровываю: Delphi 6 + Update 2 + RTL update 1.Копируем туда из соответствующей директории Delphi в такие же директории следующие файлы:
BIN\brc32.exe
BIN\brcc32.exe
BIN\dcc32.cfg
BIN\DCC32.EXE
BIN\lnkdfm60.dll
BIN\make.exe
BIN \rlink32.dll
BIN \rw32core.dll
SOURCE\*.*
Итого, около 30М, и, в принципе, этого достаточно, но для простоты и быстроты скопируйте также директории «IMPORTS» и «LIB». Получается около 110М, но кого сейчас волнуют такие размеры? Осталось поправить файл dcc32.cfg:
-aWinTypes=Windows;WinProcs=Windows;DbiProcs=BDE;DbiTypes=BDE;DbiErrs=BDE
-uC:\Delphi\D6U2RTL1\Lib;C:\Delphi\D6U2Rtl1\Bin
-iC:\Delphi\D6U2RTL1\Lib
Все это можно записать на болванку и всегда поднять систему для сборки проектов на Delphi за 5 минут на любом компьютере.
Создадим в Delphi проект для того чтобы откомпилировать с помощью нашего компилятора: Delphi-New appliсation. Затем сохраним его C:\Delphi\TestVer\testVer.dpr. Туда же сохраним наш файл группы проектов (например из Project Manager – «Save Prgect Group as»). Теперь правим строчку в файле testver.bpg
ROOT = C:\Delphi\D6U2RTL1
Компилируем наш проект:
C:\Delphi\D6U2RTL1\Bin\make.exe -fTestVer.bpg
Итак, если вы сделали все правильно, то должны были получить Testver.exe
Правила хорошего тона
Не люблю я, когда все файлы в куче, а поэтому немного модернизируем структуру каталогов -создадим отдельные папки для исходников, скомпилированных модулей и бинарников. Соответсвенно SOURCE, DCU, BIN.
C:\Delphi\TESTVER\BIN
C:\Delphi\TESTVER\DCU
C:\Delphi\TESTVER\SOURCE\
C:\Delphi\TESTVER\SOURCE\TestVer.bpg
C:\Delphi\TESTVER\SOURCE\TestVer.dpr
C:\Delphi\TESTVER\SOURCE\TestVer.res
C:\Delphi\TESTVER\SOURCE\Unit1.dfm
C:\Delphi\TESTVER\SOURCE\Unit1.pas
Теперь укажем в TestVer.bpg куда раскладывать файлы:
#------------------------------------------------------------------------------
VERSION = BWS.01
#------------------------------------------------------------------------------
!ifndef ROOT
ROOT = C:\Delphi\D6U2RTL1
!endif
#------------------------------------------------------------------------------
ProjectPath=C:\Delphi\TestVer
#------------------------------------------------------------------------------
MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$**
BRCC = $(ROOT)\bin\brcc32.exe $**
DCU = $(ProjectPath)\DCU
BIN = $(ProjectPath)\BIN
# -B = Build all units
# -E= EXE output directory
# -I= Include directories
# -N= DCU output directory
# -W = Output warning messages
# -Q = Quiet compile
# -CG = GUI target
DCC = $(ROOT)\bin\dcc32.exe $** -B -e$(BIN) -n$(DCU) -u$(LIB) -w -q -CG
#------------------------------------------------------------------------------
PROJECTS = TestVer.exe
#------------------------------------------------------------------------------
TestVer.exe: $(ProjectPath)\Source\TestVer.dpr
cd $(ProjectPath)\Source
$(DCC)
Теперь можно и собрать:
C:\Delphi\TestVer\Source>C:\Delphi\D6U2RTL1\Bin\make.exe -fTestVer.bpg
Подключаем дополнительные библиотеки.
Для начала давайте включим информацию о версии файла в проект и будем её выводить. В Delphi делаем следующее Project-Options

Для вывода этой информации я воспользуюсь библиотекой Jedi Code Library, хотя это не принципиально (долгое время я пользовался RXLib, но времена меняются…). Исходники библиотеки я просто скопирую в C:\Delphi\D6U2RTL\Lib_AddOn\JCL. Теперь правим немного исходники (Source1.rar) напишем обработчик события на FormCreate:
// Пропущено
uses
JclFileUtils;
//Пропущено
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
Ver : TJclFileVersionInfo;
begin
Ver := TJclFileVersionInfo.Create(Application.ExeName);
laVerMain.Caption := Ver.FileVersion;
laCopyr.Caption := Ver.LegalCopyright;
end;
Внимательный читатель уже заметил, что в make файле уже используется переменная LIB. Немного модифицируем файл TestVer.bpg на предмет указания путей для библиотек
LIBADDON = C:\Delphi\D6U2RTL1\Lib_AddOn
LIB = C:\Delphi\D6U2RTL1\Lib;$(LIBADDON)\JCL
Таким образом, модифицируя переменную LIB, мы легко сможем подключать новые библиотеки.
Компиляция res файла с помощью brcc32
Все отлично, из Delphi IDE мы уже можем управлять информацией в ресурсном файле. Но как создать такой файл без Delphi IDE? Для это есть утилита brcc32. С помощью этой утилиты можно компилировать ресурсные файлы. Я приведу пример из которого надеюсь, все будет ясно. Итак, создаем файл TestVer.rc:
MAINICON ICON ir.ico
1 VERSIONINFO
FILEVERSION 1,0,0,2
PRODUCTVERSION 1,0,0,2
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{
BLOCK "StringFileInfo"
{
BLOCK "041904E3"
{
VALUE "CompanyName", "ТФГ \"Test Company\"\000"
VALUE "FileDescription", "Программа \"TestVer\"\000"
VALUE "FileVersion", "1.0.0.2\000"
VALUE "InternalName", "TestVer\000"
VALUE "LegalCopyright", "\251 2002 ТФГ \"Test Company\"\000"
VALUE "LegalTrademarks", "TRADEMARKS\000"
VALUE "OriginalFilename", "TestVer.exe\000"
VALUE "ProductName", "\000"
VALUE "ProductVersion", "1.0.0.2\000"
VALUE "Comments", "No Comments\000"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 1049, 1251
}
}
Первой строкой я указал, что главной иконкой в приложении будет иконка в файле «ir.ico». Остальные параметры, думаю, не требуют комментариев. Итак, собираем:
C:\Delphi\TestVer\Source>C:\Delphi\D6U2RTL1\Bin\brcc32.
В результате вы должны получить файл TestVer.res.
Подключим компиляцию res файла в наш make файл, теперь он будет выглядеть так:
#----------------------------------------------------------------------------
VERSION = BWS.01
#------------------------------------------------------------------------------
!ifndef ROOT
ROOT = C:\Delphi\D6U2RTL1
!endif
#------------------------------------------------------------------------------
PROJECTPATH=C:\Delphi\TestVer
#------------------------------------------------------------------------------
LIBADDON = C:\Delphi\D6U2RTL1\Lib_AddOn
LIB = C:\Delphi\D6U2RTL1\Lib;$(LIBADDON)\JCL
MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$**
DCU = $(PROJECTPATH)\DCU
BIN = $(PROJECTPATH)\BIN
# -B = Build all units
# -E= EXE output directory
# -I= Include directories
# -N= DCU output directory
# -W = Output warning messages
# -Q = Quiet compile
# -CG = GUI target
DCC = $(ROOT)\bin\dcc32.exe $** -B -e$(BIN) -n$(DCU) -u$(LIB) -w -q -CG
BRCC= $(ROOT)\bin\brcc32.exe
#------------------------------------------------------------------------------
PROJECTS = TestVer.exe
#------------------------------------------------------------------------------
TestVer.exe: $(PROJECTPATH)\Source\TestVer.dpr
cd $(PROJECTPATH)\Source
$(BRCC) $*
$(DCC)
Автоматическая смена номера версии в rc файле
Воспользуемся для этого программой, написанной неким Chris Morris(Incverrc.rar). Утянул я ее с CodeCentral, и наверное, её еще можно там найти. Пользоваться этой программой очень просто – нужно в качестве параметра указать имя rc файла. Например, так
C:\Delphi\Incverrc>IncVerrc.exe /Fsample.rc
Определение версии файла в командных файлах
Теперь мы можем написать командный файл, который бы автоматически увеличивал номер версии и собирал проект. Но хотелось бы, что бы этот командный файл умел определять номер версии получившегося проекта и, например, паковать исходники проекта в архив с этим номером. Проще способа, чем написать небольшую программку, я не нашел. Итак, программа ExeVer – выводит в стандартный вывод форматированный номер версии. Для сборки требуются JCL и rxLib. Примеры работы программы ниже:
C:\Delphi\ExeVer>ExeVer.exe C:\Delphi\TestVer\Bin\TestVer.exe %J.%I.%R.%B
1.0.0.2
C:\Delphi\ExeVer>ExeVer.exe C:\Delphi\TestVer\Bin\TestVer.exe %J-%I-%2R-%3B
1-0-00-002
C:\Delphi\ExeVer>ExeVer.exe C:\Delphi\TestVer\Bin\TestVer.exe %3J
001
Будем действовать по следующему алгоритму.

echo off
SET MAKE=C:\Delphi\D6U2RTL1\Bin\make.exe
Set EXEVER=C:\Delphi\ExeVer\ExeVer.exe
Set NAMEPROJECT=TestVer
rem SET ProjectROOT=C:\Delphi\TestVer
rem SET VSS_PROJECTROOT=
rem ---------------------------------------------------------------
cd Source
echo -- vss : берем последние версии файлов
rem ----------------------------------------------------------------
echo -- vss : CheckOut %NAMEPROJECT%.rc
echo -- : увеличиваем номер версии %NAMEPROJECT%.rc
C:\Delphi\Incverrc\IncVerrc.exe -f%NAMEPROJECT%.rc
rem ----------------------------------------------------------------
echo -- make: начинаем собирать проект
%MAKE% -f %NAMEPROJECT%.bpg > ..\Bin\Out.txt
if errorlevel 1 goto endError
echo -- make: Exe сделан успешно
rem возвращаем информацию о версии
echo -- vss : CheckIn %NAMEPROJECT%.rc
cd ..
rem ---------------Архивирование и прочее--------------------------------
%EXEVER% .\Bin\%NAMEPROJECT%.exe "set verBuild=%%J-%%I-%%2R-%%3B">t$$.bat
echo rar a -r -ep1 -s -m5 -x*.scc .\Archiv\%NAMEPROJECT%_%%verBuild%%.rar .\Source\*.* >>t$$.bat
echo on
t$$.bat /wait
del t$$.bat
goto End
:endError
rem ------------произошла ошибка во время компиляции------------------
echo -- vss : undoCheckOut %PROJECTNAME%.rc
echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
echo ERROR см. out.txt
pause
cd ..\Bin
:End
В принципе, я не рассказал ничего нового. Но надеюсь, эта статья поможет начинающим группам программистов организовать технологию сборки версий своего проекта.
Copyright© 2002 Юрий Жуков Специально для Delphi Plus