Motto

В тихом саду здравомыслия
Пусть на вас постоянно падают
кокосовые орехи пробужденности.
Чогьям Трунгпа РИНПОЧЕ


Версия для мобильного


понедельник, 20 апреля 2009 г.

Кое-что о dcc32

Началось всё с того, что ctapmex сообщил об ошибке, найденной в последней альфе билд-машины Lazy Delphi Builder. Суть ошибки сводилась к тому, что после компиляции, в папках с исходниками оставались dcu. Причём, некоторые dcu-файлы всё-таки попадали в нужную папку. Почти неделю я проковырялся с этой ошибкой пытаясь понять причину и найти способ их исправить. В результате узнал кое-что новое о работе компилятора командной строки dcc32.exe.

Условия возникновения ошибки в Lazy Delphi Builder.

Есть следующие файлы:

D:\Dummy\Test1.dpk
D:\Dummy\Test1.RES
D:\Dummy\TestUnit1.pas
D:\Dummy\TestUnit2.pas
D:\Dummy\Source\TestUnit3.pas

Если скомпилировать package Test1.dpk, указав в качестве папки для dcu, папку D:\Dummy\Build\dcu, то все файлы.dcu остаются рядом с соответствующими файлами.pas.

Но, при этом, если вместо D:\Dummy\Build\dcu указать папку D:\Dummy\dcu, то все файлы.dcu оказываются там где нужно.

При этом, если вместо D:\Dummy\ использовать папку с более длинным именем, например D:\DummyTest\Build\dcu то всё работает как надо.

Отладка осложнялась тем, что Lazy Delphi Builder при запуске dcc32 пытается всеми правдами сократить длину полной команды, преобразуя все используемые пути в относительные и укороченные. Причина такого поведение – баг в dcc32.exe, когда в случае, когда длина командной строки превышает критическую, dcc32 начинает выбрасывать невразумительные сообщения типа System.pas not found, или даже AV. Мне не удалось сейчас найти упоминания об этом в интернете, хотя я точно его видел раньше(и даже сталкивался с ним сам) поэтому я просто приведу комментарий из JclBorlandTools.pas:

to avoid the 126 character limit of DCC32 (and eventually other command line tools) which shows up with misleading error messages ("Fatal: System.pas not found") or might even cause AVs

Неправильно работала следующая команда:

dcc32.exe -B Test1.dpk -N"build\Dcu" -LN"build\dcp" -LE"build\bpl" -U"Source"

Что оказалось на самом деле

Насколько я понимаю проблема проявляется только если путь для выходных файлов.dcu(то, что следует за –N) начинается с буквы b.

Т.е. варианты типа

dcc32.exe -B Test1.dpk -N"!build\Dcu" -LN"!build\dcp" -LE"!build\bpl" -U"Source"

и

dcc32.exe -B Test1.dpk -N"lib\Dcu" -LN"lib\dcp" -LE"lib\bpl" -U"Source"

Работают замечательно. А вариант:

dcc32.exe -B Test1.dpk -N"b\Dcu" -LN"b\dcp" -LE"b\bpl" -U"Source"

Оставит файлы.dcu в папке с исходниками. Странно, не так ли?

Финальная версия объяснения придумалась в процессе написания этого псто, и изложена в следующем абзаце.

Что ещё интересного выяснилось

Если сравнить параметры Dcc32.exe из Delphi 7

Параметры Dcc32 из Delphi 7

и параметры dcc32.exe из Delphi 2009

CodeGear Delphi for Win32 compiler version 20.0
Copyright (c) 1983,2008 CodeGear

Syntax: dcc32 [options] filename [options]

  -A= = Set unit alias
  -B = Build all units             
  -CC = Console target             
  -CG = GUI target                 
  -D = Define conditionals   
  -E = EXE/DLL output directory
  -F = Find error          
  -GD = Detailed map file          
  -GP = Map file with publics      
  -GS = Map file with segments     
  -H = Output hint messages        
  -I = Include directories  
  -J = Generate .obj file          
  -JPHNE = Generate C++ .obj file, .hpp file, in namespace, export all
  -JL = Generate package .lib, .bpi, and all .hpp files for C++
  -K = Set image base addr   
  -LE = package .bpl output directory
  -LN = package .dcp output directory
  -LU = Use package       
  -M = Make modified units         
  -N0 = unit .dcu output directory
  -NH = unit .hpp output directory
  -NO = unit .obj output directory
  -NB = unit .bpi output directory
  -NS = Namespace search path
  -O = Object directories   
  -P = look for 8.3 file names also
  -Q = Quiet compile               
  -R = Resource directories 
  -U = Unit directories     
  -V = Debug information in EXE    
  -VR = Generate remote debug (RSM)
  -W[+|-|^][warn_id] = Output warning messages
  -Z = Output 'never build' DCPs   
  -$ = Compiler directive     
  --help = Show this help screen   
  --version = Show name and version
  --codepage: = specify source file encoding
  --default-namespace: = set namespace
  --depends = output unit dependency information
  --doc = output XML documentation 
  --drc = output resource string .drc file
  --no-config = do not load default DCC32.CFG file
  --description: = set executable description
  --inline:{on|off|auto} = function inlining control
  --string-checks:{on|off} = string format checking (default: on)
  --peflags: = set extra PE Header flags field
  --peoptflags: = set extra PE Header optional flags field
  --peosversion:. = set OS Version fields in PE Header (default: 5.0)
  --pesubsysversion:. = set Subsystem Version fields in PE Header (default: 4.0)
  --peuserversion:. = set User Version fields in PE Header (default: 0.0)
Compiler switches: -$ (defaults are shown below)

дальнейшее убрано для компактности.

То можно увидеть, что dcc32.exe от Delphi 2009, вроде как имеет больше опций. Но, насколько я понял, в Delphi 7, при вызове dcc32 можно использовать и другие ключи.

Следующие ключи, работают и с компилятором из Delphi 7:

--depends, --drc, –no-config, а также –LE, –LN, –N0, –NO, –NB

И судя по всему, именно эта особенность является причиной ошибки, о котороой я писал в начале поста.

Я думаю, что команда

dcc32.exe -B Test1.dpk -N"b\Dcu" -LN"b\dcp" -LE"b\bpl" -U"Source"

Трактуется компилятором как

dcc32.exe -B Test1.dpk -NB\Dcu -LN"b\dcp" -LE"b\bpl" -U"Source"

И ключа –N, вроде как и нет. Для интереса проверил, что будет, если заменить –N на –N0, то всё срабатывает замечательно.

И ещё

А ещё я столкнулся с тем, что комбинация “d:\folder1\” – не воспринимается компилятором как закрытая строка. Точнее, финальные кавычки не закрывают строку, если перед ними стоит обратная косая черта(backslash). Если написать, так:

"DCC32.EXE" -B Test1.dpk -N0"o\Dcu" -LN"o\dcp" -LE"o\bpl" -U"Source;." –asdasd

То компилятор ругнётся на –asdasd чем-то вроде: Fatal: Invalid compiler directive: '-asdasd'. А если так:

"DCC32.EXE" -B Test1.dpk -N0"o\Dcu" -LN"o\dcp" -LE"o\bpl" -U"Source;.\" –asdasd

То воспримет всё нормально. Эта штука здорово мешала при поиске ошибок, так как Lazy Delphi Builder некоторые папки добавлял вместе с бэкслэшами, и я основательно помучался прежде чем понял, почему после удаления половины параметров, ничего не менялось.

Выводы

Странно, что предыдущая версия Lazy Delphi Builder вообще работала.

Ссылки по теме

6 комментариев:

  1. хм, занятно
    поправь кстати вторую картинку и текст рядом с ней

    ОтветитьУдалить
  2. Спасибо.
    Только, я в пост добавлял только одну картинку, о какой второй ты говоришь? O_o

    ОтветитьУдалить
  3. я думал что на месте всавки "кода" картинка. кстати, во как раз рядом с этим кодом и баги. может конечно это в опере так отображается

    ОтветитьУдалить
  4. Уважаемый автор LazyBuilder, как Вам на почту написать?? все тут излазил - адреса нету.

    ОтветитьУдалить
  5. в TurboDelphi : project -> options -> directories/conditionals в поле unit output directory напишите папку для DCU-файлов, удалите все старые dcu файлы, и сделайте ребилд проэкта. И будет вам радость ) В продолжение - мне пришлось сделать приложение для компиляции Delphi-проектов, с различными директивами, настройками, папками релиза ... и вообще для управления. Группы проэктов от CodeGear не могли решить стоящие задачи, ввиду, хотя бы, различной логики сборки. Кому интересно, скайп pu008u

    ОтветитьУдалить

Постоянные читатели