Статьи Королевства Дельфи


2. Компиляция


После того, как исходный код создан, требуется его откомпилировать. Компилятор dcc32 замечательно подходит для этой роли - он очень быстрый, качественный и объединяет в себе все, что необходимо для построения exe-файлов, dll-библиотек и пакетов. Размер файла dcc32.exe (версия 12.0, из Delphi 5) всего 545 Кб, ранние версии имеют еще меньший размер. К нему нужно добавить только три файла - rlink32.dll, sysinit.dcu и system.dcu (это минимум). Компилятор и указанные файлы можно разместить в подкаталоге прикладной программы, например, bin. Генерировать текст целесообразно в подкаталоге компилятора, например, bin\pas, чтобы использовать короткие пути файлов и не засорять каталог компилятора.

Для вызова dcc32.exe в библиотеке DccUsing определена функция ExecDcc32. Она устанавливает текущий каталог, создает файл для перехвата ошибок компиляции, вызывает компилятор, дожидается завершения компиляции и определяет наличие ошибок.

function ExecDcc32(const aDccDir, aOptions, aProjectPath, aErrorPath: String; aCheckPaths: Boolean = False): Boolean;

Функция принимает аргументы: aDccDir - каталог, в котором находится компилятор Dcc32, aOptions - опции компилятора (рекомендации по их использованию смотрите в файле DccUsing.pas), aProjectPath - путь файла проекта (обычно dpr), aErrorPath - путь файла, куда будут направляться сообщения об ошибках компиляции. Необязательный аргумент aCheckPaths позволяет разрешить или запретить контроль наличия каталога и файла dcc32.exe. Функция возвращает True, если компиляция была успешной и False в противном случае. Предупреждения (hints и warnings) ошибками не считаются - их выводом можно управлять с помощью опций -H и -W. Опуская детали, рассмотрим немного подробнее эту функцию:

// сохранение текущего каталога и установка нового CurDir := GetCurrentDir; if not SetCurrentDir(DccDir) then raise Exception.Create(SCantChangeDir + DccDir); try hStdOut := INVALID_HANDLE_VALUE; try // установки атрибутов безопасности with SecurAtt do begin nLength := SizeOf(SecurAtt); lpSecurityDescriptor := nil; // разрешить наследование дочернему процессу bInheritHandle := BOOL(True); end; // создание файла, в который будут направляться ошибки hStdOut := CreateFile(PChar(aErrorPath), GENERIC_WRITE, 0, @SecurAtt, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if hStdOut = INVALID_HANDLE_VALUE then raise Exception.Create(SCantCreateFile + aErrorPath); // заполнение структуры, специфицирующей создание процесса ZeroMemory(@StartupInfo, SizeOf(StartupInfo)); with StartupInfo do begin cb := SizeOf(StartupInfo); // скрывать окно компилятора и наследовать потоки ввода-вывода dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; wShowWindow := SW_HIDE; hStdOutput := hStdOut; end; // создать и стартовать процесс компилятора s := 'dcc32.exe ' + aOptions + ' ' + aProjectPath; if not CreateProcess('dcc32.exe', PChar(s), @SecurAtt, @SecurAtt, BOOL(True), 0, nil, PChar(DccDir), StartupInfo, ProcessInfo) then raise Exception.Create(SCantCreateProcess + 'dcc32.exe'); // ждать завершение компиляции неопределенное время WaitForSingleObject(ProcessInfo.hProcess, INFINITE); // получить результат компиляции ResultCode := 0; GetExitCodeProcess(ProcessInfo.hProcess, ResultCode); result := ResultCode = 0; finally // закрыть файл ошибок if hStdOut <> INVALID_HANDLE_VALUE then CloseHandle(hStdOut); end; finally // восстановить прежний каталог по умолчанию SetCurrentDir(CurDir); end;




Начало  Назад  Вперед