# Jedi Code Library - Cross Platform Strategy

This paper presents the JCL teams strategy for cross platform compliance of the Jedi Code Library. It is based up on the discussions within the JCL newsgroup and JCL developer mailing lists. This document is currently work in progress and subject to changes with or without notice.

Version history:
0.1 Initial release

### Background

The main objective is to make the Jedi Code Library VisualCLX (Kylix for Delphi/Delphi) and Delphi.NET compatible. For a detailed explanation of the currently used terminology, see the following article Overview of the VCL for .NET.

We have to cope with nearly all aspects of cross platform progamming, like different APIs, different operating system concepts etc. Since we want to be as crossplatform compatible as possible interface compatability is the most important issue for us. Jedi Code Library users should have to opportunity the use the JCL on whatever platform they like. Figure 1 shows the three basic layers we have to deal with:

- Platform independent layer: Units which are not (or only very minor) platform specific and do not depend on a specific component set. This doesn't mean that units in this layer have to consist of no platform dependent code, but they have to be nearly 100% interface compatible and all functionality must have been ported to all supported platforms.
- Platform dependent layer: Units which depend on a specific platform (e.g. JclCLI)
- Component set dependent layer: Units which depend on a specific component set

Fig 1: The Jedi Code Library crossplatform layer structure

The Jedi Code Library currently targets the following platforms:

- Kylix for Delphi (Kylix 3) / Linux
- Delphi (Version 5,6,7) / Microsoft Windows

and is trying to support the following platforms as soon as possible:

- Delphi .NET / .NET (Micrsoft Windows)

As a mid or long term perspective we are hoping to get the JCL FreePascal compatible. This involves the possibilty to have the JCL running on DOS, OS/2, FreeBSD and AmigaOS.

### Common platform independent layer

This layer consists of all files which are not platform dependent or need only very minor adjustations. Furthermore all units in this layer do not depend on a specific component set. Examples for common platform independent units are JclBase, JclDateTime, JclFileUtils and JclMath. The units have been ported to all platforms and are the crossplatform "core" of the Jedi Code Library. As a general rule a unit in this layer should have no platform specific ifdefs in its interface section.

### Platform dependent layer

Furthermore we do not have to differentiate between VCL and VisualCLX units only (the so called component set dependent layer), but also between UNIX, Windows and .NET dependent units. The platform dependent units doesn't need to be interface compatible (if there is an equivalent in one of the other suported platforms at all!). An example for a platform dependent unit is JclCLI. Nonetheless if there are equivalents in all other supported platforms as well it might be considerable to write a more general class and include that unit into the common platform indepedant layer.

### Component set dependent layer

When it comes to sharing code between VCL and VisualCLX-applications, some facts need to be stated:

- A unit is called VCL-dependent, when it uses some VCL-unit(s), e.g. Graphics.
- A unit is called VisualCLX-dependent, when it uses some VisualCLX-unit(s), e.g. QGraphics.

When a unit contains neither VCL- nor VisualCLX-specific code, there is no problem: It can be used by either type of application.

While it is basically possible to create VCL-dependent and VisualCLX-dependent variants of the same unit by means of conditional compilation - and use them in VCL- and VisualCLX-applications respectively -, this method fails at design time: One and the same unit cannot be installed twice in the IDE, not even as part of different packages. We would have to rename one of the variants, effectively creating a new unit. Therefor we will use a preprocessor to resolve the conditional compilation symbols related to VCL/VisualCLX-specific code and create VCL/VisualCLX units from a common codebase.

Component dependent units should be largely "interface compatible" - interface adjustments for specific component sets are unavoidable - nonetheless similar interfaces are desirable.

### Preprocessor

The preprocessor jpp is a modified version of Barry Kelly's ppp tool. In contrast to ppp, which resolves all conditional compilation directives without exception, with jpp symbols not only can be defined but also undefined. Those symbols which are neither defined nor explicitely undefined are considered as of unknown status and it and its related source code remains untouched.

The usage of jpp is not too hard. It is called via

    jpp [options] <input files>...

Possible options are

      -i       Process includes
      -c       Process conditional directives
      -C       Strip comments
      -pxxx    Add xxx to include path
      -dxxx    Define xxx as a preprocessor conditional symbol
      -uxxx    Assume preprocessor conditional symbol xxx as not defined
      -x[n:]yyy  Strip first n characters from file name; precede filename by prefix yyy

The example command line below generates a file JclQGraphics.pas in subdirectory CLX from file Graphics.cb located in the current directory. Symbols "VisualCLX" and "COMPILER6_UP" are specified as defined, "Bitmap32" and "VCL" as undefined.

      jpp -c -dVisualCLX -dCOMPILER6_UP -uBitmap32 -uVCL -xCLX\JclQ Graphics.cb

### Generating Jcl[Q]Graphics.pas and Jcl[Q]GraphUtils.pas

First compile Preprocessor\jpp.exe from Preprocessor\jpp.dpr. Then change to the "Source" directory and type "make" at the command line. This will create the units
VCL\JclGraphics.pas
VCL\JclGraphUtils.pas
CLX\JclQGraphics.pas
CLX\JclQGraphUtils.pas

from their prototypes _Graphics.pas and _GraphUtils.pas.

### Minimizing VCL dependencies

To reduce VCL dependencies in JCL, the following changes have been made:

JclFileUtils
  PathCompactPath is an overloaded function. The variant which takes a TCanvas as argument (and thus creates a dependency on VCL unit Graphics) has been removed.

JclShell
  ShellLinkGetIcon has been removed. It could get part of some genuine VCL-dependent unit (e.g. JclGraphUtils), but for now it is left out.

JclPEImage

       Replace "uses Consts," by

          uses
            {$IFDEF COMPILER6_UP}
            RtlConsts,         // VisualCLX-package compatible (part of rtlxx.bpl)
            {$ELSE}
            Consts,            // not VisualCLX-package compatible (part of vclxx.bpl)
            {$ENDIF COMPILER6_UP}

Note that the first two changes have enormous impact, since many JCL units use JclFileUtils and JclSysInfo (which both use JclShell). This leaves JclGraphics and JclGraphUtils as sole units with genuine VCL/VisualCLX-dependencies. JclPrint is the only remaining pure VCL-dependent units.

### New directory structure

With the new JCL release we introduce a more appropriate source file directory structure. The files are now grouped according their respective layers.

    Source/
      Common
      DotNet
      Unix
      VCL
      VisCLX
      Windows

### Status - Platforms

This table gives a short overview of which units are already working under four different Delphi language compilers/platforms. There are four status levels possible:

+ | the unit has been ported to that platform
- | the unit has not been ported to that platform
(+) | the unit compiles, but not all of its functionality has been ported to that platform.
platform | the unit is platform dependent and will not be ported.

Name | Delphi (Windows) | Kylix for Delphi | Delphi.NET | Free Pascal
Jcl8087 | + | + | - | ?
JclAppInst | + | - | - | ?
JclCil | + | - | - | ?
JclClr | + | - | - | ?
JclCom | + | - | - | ?
JclComplex | + | + | - | ?
JclConsole | + | - | - | ?
JclCounter | + | + | - | ?
JclDateTime | + | (+) | - | ?
JclDebug | + | - | - | ?
JclDotNet | + | - | - | ?
JclEDI | + | + | - | ?
JclEDISEF | + | + | - | ?
JclEDIXML | + | + | - | ?
JclEDI_ANSIX12 | + | + | - | ?
JclEDI_UNEDIFACT | + | + | - | ?
JclFileUtils | + | (+) | - | ?
JclExprEval | + | + | - | ?
JclHookExcept | + | - | - | ?
JclIniFiles | + | + | - | ?
JclLanMan | + | - | - | ?
JclLocales | + | - | - | ?
JclLogic | + | + | - | ?
JclMapi | + | - | - | ?
JclMath | + | + | - | ?
JclMetaData | + | - | - | ?
JclMidi | + | - | - | ?
JclMime | + | + | - | ?
JclMiscel | + | - | - | ?
JclMultimedia | + | - | - | ?
JclNTFS | + | - | - | ?
JclPEImage | + | - | - | ?
JclPrint | + | - | - | ?
JclStrHashMap | + | + | - | ?
JclStatistics | + | + | - | ?
JclShell | + | - | - | ?
JclSecurity | + | - | - | ?
JclSchedule | + | + | - | ?
JclRTTI | + | - | - | ?
JclResources | + | - | - | ?
JclRegistry | + | - | - | ?
JclStrings | + | + | - | ?
Jclsvcctrl | + | - | - | ?
Jclsynch | + | - | - | ?
JclTask | platform | - | - | ?
JclSysUtils | + | (+) | - | ?
JclSysInfo | + | (+) | - | ?
JclTD32 | + | - | - | ?
JclUnicode | + | - | - | ?
JclUnitConv | + | + | - | ?
JclWin32 | platform | - | - | ?
JclWinMidi | platform | - | - | ?

### Assembler

For crossplatform compatability it is absolutely necessary to reduce the amount of inline assembler code used. Therefore as a general rule every line of assembler must have a pure pascal pendant. Please use assembler only if it really has a noticeable impact on the libraries performance.

    {$IFNDEF PUREPASCAL}
      // assembler code here
    {$ELSE}
      // Delphi equivalent here
    {$ENDIF}

### Packages