Началось всё с того, что 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.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 вообще работала.
хм, занятно
ОтветитьУдалитьпоправь кстати вторую картинку и текст рядом с ней
Спасибо.
ОтветитьУдалитьТолько, я в пост добавлял только одну картинку, о какой второй ты говоришь? O_o
я думал что на месте всавки "кода" картинка. кстати, во как раз рядом с этим кодом и баги. может конечно это в опере так отображается
ОтветитьУдалитьУважаемый автор LazyBuilder, как Вам на почту написать?? все тут излазил - адреса нету.
ОтветитьУдалитьLazyDelphiBuilder сабака gmail.com
ОтветитьУдалитьв TurboDelphi : project -> options -> directories/conditionals в поле unit output directory напишите папку для DCU-файлов, удалите все старые dcu файлы, и сделайте ребилд проэкта. И будет вам радость ) В продолжение - мне пришлось сделать приложение для компиляции Delphi-проектов, с различными директивами, настройками, папками релиза ... и вообще для управления. Группы проэктов от CodeGear не могли решить стоящие задачи, ввиду, хотя бы, различной логики сборки. Кому интересно, скайп pu008u
ОтветитьУдалить