Using COLLAPSE
in MCK projects.
Installing
COLLAPSE. Select a directory for
COLLAPSE, e.g.
C:\KOL\Prj\COLLAPSE and unpack there files from the archive
(below if the path is starting from COLLAPSE, I mean this directory).
P-code is generated in MCK for
all forms automatically (yet before installing the COLLAPSE).
In case when design-time components are using which yet no
have P-code generation implemented, P-code is not generated for entire form.
It is possible to detect this situation visually:
- look at the text of generated inc-file (it
is better to load it to the Delphi IDE editor): [unit_name]_1.inc.
If there are no brackets {$IFDEF Pcode}...{$ELSE} previous Pascal code
{$ENDIF}
for a procedure New[form_type_name], then it is detected that P-code could not
be generated.
- open console (in the component
TKOLProject set up property
consoleOut to
true. If
during code generation (setup
BUILD to
true) some yellow messages are
appearing about not supporting P-code of some components,
then P-code will not be generated,
and the form is initializing by the usual way, using Pascal code.
For non-visual control at run time it is possible to check if
the first byte of the procedure is
$E4..$E7
line is call RunPCodeN
with N=0..3 (if no
then the procedure is not P-coded).
To provide generated P-code to work, it is necessary to do
following steps:
- add conditional definition symbol
Pcode
to Project|Options; it is always possible to change this symbol to
noPcode or delete at all to generate project
without Pcode as earlier;
(it is also possible to add option {$define Pcode}
into each unit containing MCK form or self-made P-code);
- in Project | Options in tab
Linker for a group
Map file select value
Detailed;
- add a path to COLLAPSE directory to
search units list (files Collapse.pas
and BaseLib.pas are used from this directory, when
symbol Pcode is used);
- copy file Pcompiler.cfg from the directory
COLLAPSE\Units
and change it (open it in text editor and change paths).
Take an attention, that it is
necessary to write correct name of map-file in key
/M
instead of Project1.map; if you are going to use also
P-debugger, check a path to COLLAPSE\Debuger;
- copy also
empty files (or create new) from the
COLLAPSE\Units :
CollapseUses.inc, CollapseObjects.inc - these also can be useful if additional
MCK mirror components are used, supporting P-code;
- in the component
TKOLProject , change option
CallPCompiler, writing there full path to P-compiler executable
(COLLAPSE\PCompiler\PCompiler.exe).
If you will always call P-compiler manually, you can leave this property empty
though. But in such case do not forget call P-compiler manually, if any changes
were made in design-time properties;
- configure also manual call of P-compiler in
Delphi
IDE Tools:
Tools | Configure Tools... | Add | Browse... select there
COLLAPSE\PCompiler\PCompiler.exe and (must!) add macro $EDNAME.
Give a name to the new instrument, like PCompiler, and now
you can call it directly from Delphi to P-compile current project manually when
necessary. Take an attention, that current file in
Delphi IDE Editor should be one of project units, and inc-files generated by MCK
should NOT be loaded into Delphi IDE editor (otherwise Delphi can not detect
that these files were changed on disk).
It is also possible to configure calling of P-compiler
with additional option /A (total command line will be /A $EDNAME). Such call
can be useful to recompile all the units with P-code in the project when the
version of P-compiler is updated.
- After the first applying
P-compiler it will be required to add a reference to
Collapse.pas to uses clause. I recommend to add it to a uses in the
implementation section, e.g.:
{$IFDEF PCode}, Collapse
{$ENDIF};
Or:
{$IFNDEF noPCode},
Collapse {$ENDIF};
Use the first variant
when the all forms are compiled to Pcode by adding symbol PCode to project
options, the second when each form is prepared to
use Pcode separately, e.g. adding to the start of the unit following lines:
{$IFNDEF noPCode}
{$DEFINE PCode} {$ENDIF}
It is now possible to ensure that inc-files are containing
P-code, and call P-compiler.
After it successful funishing all project units containing
P-code are modified and for P-code compiled assembler code is generated (it
contains only data directives DB, DW and DD and is
starting from one of bytes
$E4..$E7). Now run compiled project and find that it is
working exactly as earlier at least no changes should be detected visually.(If
there are any differences, this mean an error in code generation, so write me or
to the author of the MCK-component affected to solve a problem).
If it is necessary to run P-debuger, add a conditional symbol
COLLAPSE_DEBUG (path to the debugger must be in the
file PCompiler.cfg at the key
/D).
While compiling assembler code created
by the Pcompiler, it is possible that Delphi find following errors:
- Identifier length supported by the
built-in Delphi assembler should not exceed 32
characters. So, all long names of procedures,
record fields etc. should be renamed to shorter names.
- If error found
'Undeclared identifier ...' in units
CollapseProcTableN.pas, and you are sure that such identifier is existing,
add a reference to the unit where the identifier is defined, to a file CollapseUses.inc (like
,
имя_модуля).
- If another error found about
duplicating the declaration (most often of n_<procname>),
then the reason is that too long identifier was cut to fit 32
characters length, so it was
matched with another name. To solve this, rename
conflicting procedures to shorter names.
- If there are no evident errors in
text but Delphi found syntax error (like Waiting for ';' but ...), it is
necessary to run PCompiler for the unit (manually).
Now you can compare size of the executable,
with option Pcode.
For small projects P-code will not reduce it more since first
about 500-600 bytes are added and only after this code
become reducing. Effect become evident only for large
enough projects having big form initialization procedures (i.e.
when amount of MCK-components is enough),
because P-code is 2-3 times more compact
then original machine code compiled from Pascal. It is
possible that in result of additional compressing the executable with some
compressors (such as UPX) effect become even more evident since P-code does not
contain relative offsets in it and can be compressed at least not worst then the
original machine code.
If the project contains other long (and very long)
initialization procedures, e.g. in OnShow event, it is also possible to P-code
it manually and P-compile. See correspondent manual.
If you have KOL
component with MCK mirror and you want make it compatible with P-code like
standard MCK component do, see correspondent instruction too.
Additinal feature: if to uncomment
the line {$DEFINE NOEXCEPTONEXIT} in the Collapse.pas, then in case of any
exception when the application is finishing it will be silently suppressed and
the application halt without any further messages. You should in your code
assign TRUE to a variable AppletTerminating (defined in the Collapse.pas) as
soon as terinating of the execution is starting (otherwise only AppletTerminated
is checked but this can be not enough in some cases).
I know that this not good practice but there are some cases
when exception on exit of the application can not be easily solved. E.g. if some
third-party libraries are used and errors are deep in their code or your
application works with data which can be partially damaged (images, sounds,
etc.).
Vladimir Kladov, 3-Dec-2005
Last update: 21-Jan-2006