|
|
![]() |
||
![]() |
|||
| Version
www.capesoft.com |
![]() |
||
| Additional Documentation Guide | |||
|
Tutorial: Using Multi-Proj to create
Multi-DLL products (highly recommended)
|
|||
When your program grows large, there comes a point when you start to consider breaking it up into many app files, that create DLL's. This process can lead to quite a bit more overhead, functions have to be prototyped, procedures need to be exported, and so on. Multi-Proj has been designed to automate as much of this Multi-App-Management as possible. It also allows you finer control over how each application interacts with the others.
Another popular use for Multi-Proj, even if you only have one app file, is the ability to create versions that substitute a different driver than the one specified in the dictionary. This means, for example, that migrating from one driver to another is much easier with Multi-Proj especially if you need to maintain support for both drivers.
It should be noted that this is a developer-level tool. In other words it gives you, the developer, more power, and more flexibility than before. The cost of this power is knowledge. When you know what you're doing, Multi-Proj is on you side. When you don't know what you're doing then it can cause you grief. Please take the time to work through the tutorial.
Multi-Proj continually maintains all the related files, including the EXP files,
PRJ files, distribution commands, and maintenance of the template file - automatically.
Now changing a DLL becomes as simple as compiling a single batch. All of the rest
of the work is taken care of.
Another thing we regularly do now, is compile all our APPs during the development
cycle with Full Debugging turned on. However Multi-Proj generates Debug Free PRJ
files for us, which we compile just before distribution (with the Multi-Proj Manager
- a Batch Compiler). Thus our clients get the leanest code possible - while we
can make full use of Clarion's native debug facilities.
| CapeSoft Support | |||
|
|
|||
| Telephone | +27 21 715 4000 | ||
| Fax | +27 21 715 2535 | ||
| Post | PO Box 511, Plumstead, 7801, Cape Town, South Africa | ||
| CapeSoft Sales | |||
| Web | www.capesoft.com | ||
|
|
|||
| Telephone | +27 21 715 4000 | ||
| Fax | +27 21 715 2535 | ||
| Post | PO Box 511, Plumstead, 7801, Cape Town, South Africa | ||
| Buy Online | |||
| Web | |||
If the application is a DLL a template to use the DLL is
automatically written for you. The template contains a global extension which
will activate the DLL in another application. This activation includes prototyping
all the functions exported by the DLL, and including the DLL in the new application's
Project settings. A code template for each exported function is also included
to simplify calling the functions.
To truly understand all the goodies that Multi-Proj offer, it is useful to understand
how DLLs are normally created, maintained, and used, in Clarion. Doing things
the hard way is the easiest way to see how Multi-Proj makes it easier. Of course
you can skip all the pain and simply do it the easy way. If you want to dive right
in, then a good place to go from here is the Tutorial.
This walks you through all the steps of turning a single APP into a Multi-DLL
product. It also shows you how to add Multi-Proj to a Multi-DLL product.
This APP has no _RD and _RU Files : This is for Legacy Template APPs
only. Click this option on if this APP uses no Dictionary File Structures.
This APP has no _SF module : This module is usually generated by the
Clarion Legacy Templates. However in some APPs it is not included. If your APP
does not generate a _SF module then click this on.
This APP has no BC modules : This is for ABC Template APPs only. Click
this option on if the APP has no BC modules. Typically the
data dll will have BC modules, whereas the other apps will not. If you
get this option wrong (by ticking it on when you shouldn't) you will
experience problem P1 as documented in the Multi-Proj Trouble-Shooting Guide.
Highest BC Number : This is only for ABC, and only needs to be filled in in the Data DLL. The template will generate a number of modules named xxxxxBC0.CLW, xxxxxBC1.CLW and so on. The exact number of modules is dependant on your dictionary, and very hard to predict reliably, so Multi-Proj needs you to fill in the number here. Note this can change as your dictionary grows. If you get this number wrong you will experience problem P2 as documented in the Multi-Proj Trouble-Shooting Guide.
Tip : Clarion counts them up from 0, to 9, then starts from A. You enter either the highest number, or if there are letters, then the highest letter.
Export OW Classes : This is for apps that have the Object Writer template included. If this item is ticked then the Object Writer classes will be exported, regardless of the EXPORT setting for these classes. If this option is not ticked then the classes will not be exported, again regardless of the EXPORT setting for those classes.
Only Export OW classes : If this option is ticked then only the class will be exported from the app. Use this option if you are making a DLL, which contains a class, but nothing else.
Suppress ABC Init : This suppresses the generation of all the ABC init code. Use this if your Object Writer class does not depend on any ABC classes.
This is app number : When making DLL's Multi-Proj supports a technique called Rebasing. This makes your apps load faster, and they're generally more "Windows friendly". This only applies to DLL's, Exe's and Lib's do not need to be rebased. For a detailed discussion about rebasing see ClarionMag ). While figuring out all the various rebasing numbers can be confusing, Multi-Proj tries to simplify it for you. Here's how it works;
Each DLL in your application has a "Big Picture" number. It doesn't really matter what the number is, but it's best to simply start with 1 and move upwards from there. So the Allfiles app will be app number 1, then Procs DLL will be app number 2 and so on.
Each number is good for 1 meg of virtual memory. If your DLL is more than a meg big then skip a number in the next dll. So if this data DLL was say 1.1 megs in size, then the Proces DLL would be app number 3.
Note for debugging: Leave the number set for the size of the non debug DLL's (i.e. compile the DLLs with DebugMode turned off to get the size you need to use). The extra size on the disk (when you compile with debugging turned on) is not loaded by windows. It is only used by debuggers, and analysis tools (like GPF Reporter and Profiler.)
Each
Version has the following settings;
Title : This is the title on the list of versions. This title is only
used for display purposes. A typical title might be "32-bit Stand-Alone,
Debug Off, Version".
Set : If you are making a multi-dll,
multi-driver, suite then you need to specify the SET that each version belongs
to. Each different driver needs it's own SET name. For example, if you have a
set of apps using the Topspeed driver, and this version uses the Topspeed
driver then use a set name like TOPSPEED. It doesn't matter what the set name
is (it could be TPS) so long as all the APPS in the suite use the same SET
names.
Target Type : This is the target type of the version. Choose from EXE,
LIB and DLL.
Target OS : This sets whether the version is 16 or 32-bit.
(note 16 bit is retained for backward compatibility, but
Multi-Proj no longer actively supports 16 bit programs).
Runtime Library : Set this to "Stand Alone" for
compatibility
with applications compiled with DLLs. Set this to "Local" for
compatibility
with applications compiled into a single EXE.
Debugging : Set this to On or Off.
Target Name : Enter the name of this version of the project. A PRJ, EXP
and BAT file with this name will be created. Also a EXE, DLL and/or LIB file
will be made with this name. Each version thus needs a different target name,
and all the target names must be different to the Project File Name (as set
above on the general tab). If you are compiling EXE's then each version needs
to have a different name, although they can be renamed in the "Distribution"
settings. For more information on naming standards and strategies see the section
entitled DLL Naming Strategies
later in this document.
Project Name : If the Project needs to have a different name to the target name then you can enter the Project name here. This is most often used when you are creating different versions of the same DLL, and the DLL's have the same (target) name. In the case of a DLL (unlike an Exe) renaming after the fact doesn't work well. But each version still needs a unique Project name, so you can enter that here.
Suppress this version for now : If you no longer
want to generate a specific version, then tick this option on.
Resources : Add specific resources here which apply to this version.
This would typically include other 3rd party libraries. Note that it is now
possible for 3rd party products to integrate directly with Multi-Proj - saving
you this step. For more information see the section entitled
3rd
Party Support for Multi-Proj later in this document.
File Drivers : This lets you override the File Drivers that will
be linked into this Version of the project. This is typically used when you're
making use of the Driver Substitution facilities in Multi-Proj. (For more information
on Driver Substitution read the
Section below). If you add any drivers here, then you must add all
the drivers here. None of the detected drivers, or drivers set on the All Versions
Resources Tab will be included.
Defines : Add specific project defines here. This is typically used when
you want to do conditional compiles. For more information on conditional compiles
see the section entitled Conditional
Compiles.
Distribution : This section allows you to copy files (for this particular
version) from one place to another. Typically you might want to copy DLL, EXE
or LIB files.
Common Resources : These are resources that will be used by all the versions
of your APP. These are typically graphic files, like ICOs, BMPs or GIFs.
External Source : This is for external source files that may be used
in your application. For example if you make use of the resize support in Clarion
2 then you will need to add the ResCode.Clw file here. To see what
other external sources your application uses, check out the External Source
Section of your APPs Project settings.
Enable Override Drivers : Turn this on if you want to enable the Override
Driver support. For more information on overriding drivers see
Driver
Substitution later in this document.
OverrideDriverPossibilites : This allows you to create one, or more,
Driver override Possibilities. Note this is not doing the overriding - merely
creating the possibility of an override. For each possibility you need to set;

NB - you will need to register this template after it's generated
the first time.
Template File Name : This name is typically the same name as the APP
file itself. If this DLL is not part of a Template SET then this file should
have the extension TPL. If it is part of a bigger SET then it should have a
.TPW extension. This template will include a Global Extension Template (for
activating this DLL in other APPs) and a code template for each Exported Function
in the template.
Note that if this APP is an EXE then it makes no sense to have a Template -
so leave this entry blank in that case.
Don't Generate Code Templates : Click this on to only generate the Global
Extension, and not the Code templates. You would typically do this if you are
creating the Code Templates yourself (stored in some other TPW file in the same
SET).
Includes : If you are wise enough to add your own, hand-written template files to this template set, then add a list of your own TPW files here.
Don't generate Dependancy defines : Part of what Multi-Proj does is generate special defines into the generated PRJ's so that the Multi-Proj Manager can figure out which apps are dependant on which other apps. If you wish to suppress this feature then you can tick this option on.
MsSql : Real becomes Sreal: Tick this option on
if you are using driver substitution, to MsSql, and you are not using FM3.
This option automatically converts any REAL fields in your dict, into SREAL
fields when generating the MsSql file declaration. It needs to do this because
Clarion does not correctly convert REALS to FLOATS when the file is created.
(If you are using FM3 then you can leave this switch off, as FM3 creates the
table correctly.)
In addition to the pretty obvious features of MPM it's worth pointing out the
following features:
On the Tools menu, Template Utility option :
This allows you to run a Template Utility on a number of APPs in a Batch. This
is very useful for analytical, or documentation tools.
On the Tools menu, Options item : This window contains some options
which control how MPM behaves.
| 1. | When you first write a new DLL, you'll have to register
the new template that Multi-Proj makes for you. Actually if the new template is
part of a Template Set then the Set has to be registered. Once the Set has been
registered it does not need to be re-registered every time you add a new DLL to
it. This is one of the advantages of using Template Sets. The name of the Template Set is what you set on the Template tab of the Multi-Proj extension. Or if there is no Template Set entered there, then use the Template File Name. (If there's also no Template File Name then there's no template!) You only need to register the template once - when you change your DLL the Template, and the Template Registry are updated automatically. To register a template go to the Setup menu (in the Clarion IDE) , to Template Registry option and click on the Register button. |
| 2. | The first time you use the DLL in another application, go to
the Global Extensions area. Then include the Activate_XXX global
extension template. (XXX is the name of your library). This extension adds the
DLL to your current APP, and prototypes all the exported functions, and data,
for you. If you are building a multi-driver system then you will need to set the Driver Set that the app will belong to. In other words when you compile the application itself, which driver do you want it to use. The template will offer you a drop-down of the various sets that are available for the DLL you are activating. |
| 3. | When ever you want to use one of the functions in the DLL, then you can either go to an embed point, and type the call in there, or you can make use of one of the Code templates that Multi-Proj generated for you. There is a code template for each generated function which will prompt you with the parameters required, and the syntax for the function. |
| 1. | If you are creating a DLL / Lib combination then set the APP itself to be a DLL. Then click the Export Function switch for those procedures you want to export. |
| 2. | If your program gets link errors when trying to compile the project, but the application itself compiles ok, then check the "Project" settings of the APP. Most likely you have omitted a resource in either your Version Resources, or Common Resources. |
| 3. | If you want maximum value from the Code template then use the long form of prototyping when you prototype your functions in the DLL. The prototype for the procedure is set on the Procedure properties window. Normally you only put the parameter types in the Prototype e.g. (LONG, LONG, STRING) . However you can also put the variable names here. For example (LONG FromDate, LONG ToDate, STRING Holiday) |
| 4. |
If you are using FM3, and you are using Multi-Proj to
create multiple driver versions of your app, then you need to handle the
fact that each driver version of your file represents a different file
version number (as far as FM3 is concerned). To do this;
in your data dll
global embed point, called "program setup"
priority 10
put
compile('***',MsSQLDriver=1)
ds_VersionModifier = 1000 ***
if you had a third driver, say oracle, then you'd also add
compile('***',OracleDriver=1)
ds_VersionModifier = 2000 ***
and so on.
|
| 5. | If you are struggling to use the Multi-Proj Manager, because of DDE problems, then try making a shortcut to the Mp.Exe on your desktop. Running it from here, rather than from inside the IDE (Accessories menu) seems to work better on some machines. |
| 6. | If you are using Clarion 5, make sure you have downloaded the necessary patch file here. |
Make error: File "<filename>.exp" not found: The target type in the Multi-Proj Global Extension does not match the target type in the Project Properties. If you are building a DLL make sure they are both set to DLL. If you are using Clarion 5.5 legacy, then you need to modify the buildexp.tpw to add an embed point as follows (right at the end of the file):
#EMBED(%AfterClosingExports,'After Closing the export file')
Execute of <filename>.DLL failed, File not found: Make sure in the Project Properties, that you haven't put the Target Name in the Programs to Execute section by mistake.
Link Error:
Unresolved External NetDUNRename (and about 90 others): This is caused if
this Application is a Data DLL, and NetTalk is installed on your system, and
neither the Activate, nor Suppress NetTalk extensions are in this app.
If you intend to use NetTalk then add the Activate NetTalk Global Extension to
the application, otherwise add the Suppress NetTalk Global Extension.
Link Error: Unresolved External <$CUSTOMER> in <filename>.obj:
This may happen if you have not included all the Global Templates for all the
DLL's in your project. You should have a Global Template for each DLL that this
application is dependant on, plus your template set name Global Template. (If
this occurred when you were doing the tutorial and you had not done the first
part of the tutorial, then you probably chose to Generate All, instead of the
'Just This File' Generate option. If you are not working through the whole tutorial
and are just doing the Multi-Proj Manager tutorial, then re-install Multi-Proj
to restore the original tutorial files.
Link Error: Unresolved External ~<iconfilename> in <filename>.obj: This will happen if you've put the tilde character in front of icon files in your browse icons tab. You need to remove the tilde characters from the front of the icon filenames that you have used in your brwose icons. These are icons are included in your project and the icon used will be the one included in the project. Only icons used in handcode require a tilde to use the icon included in the poject.
Syntax error: Indistinguishable new prototype: <procedure name>: You may have declared your procedure to be an ABC External type when it should be a Multi-Proj ExternalProcedure.
Link Error: Unresolved External: Possible causes:
How to resolve this:
- Open your application in the IDE and select the Export Project File item from the File menu - and select a unique project name.
- Open your Project (that you've just exported) - and compare it to the Project that MultiProj generates (this is the name of the Project/Target that you entered on the Versions tab of your MultiProj template instance in your application). You can open the projects in a text editor (like NotePad or the Clarion IDE).
- First check the LIB files that are added to the App's Project and see if there are any of them missing from the MultiProj Project. If there are, the best solution is to contact the 3rdparty vendor - and inform them that there product is not compatible with MultiProj. This is very easy to do, and can be done using the 3rd Party support for Multi-Proj section of this document. If your lib file needs to be added to the Multi-Proj project manually, you can do this in the Common Resources button on the Resources tab of your Multi-Proj template:
- Next check for any missing clw files. These could be additional BC modules, which MultiProj does not know about. Find the highest BC module number (this is in Hex):
(In this case it's B)
and enter it into the MultiProj template:
- Other missing CLW files can be added to your External Source list on the Resources tab of the MultiProj template.
$VCRRequest is unresolved for Export: This
should only happen in old version of Clarion 2, before this variable was introduced.
To fix this error, go to the Global Embeds, in the "Global Data" embed
point add
VCRRequest long

You have not allocated a unique template name in the Template tab of the Multiproj Template.
My Compiler GPFs since breaking my app into DLLs.
Note: Before proceeding with implementing driver
substitution,
you must make your dictionary SQL compliant (see
http://www.capesoft.com/docs/fm3/fm3sql.htm#Convert). It is highly
recommended that you use FM3 to manage your data conversion, as doing this
manually will be very tedious (www.capesoft.com/accessories/fm3sp.htm)
1. First on the Multi-Proj extension, on the Resources Tab, Click Enable Driver Substitution ON. Then click on the Override Driver Possibilities button. The idea here is to define which drivers might be overridden. In our example (of having TOPSPEED and MSSQL versions) we will override the TOPSPEED driver with MSSQL in some versions, and in other versions we won't. We'll get to the versions in a moment - for now we're just defining the possibilities.

With each possibility you'll need to enter a Conditional Define. This is basically an identifier or an equate. This equate will be defined for you. When the equate is 1 then the driver will be substituted, when it's 0 it won't. You'll see how the equate is set in a moment - for now though it's necessary just to create the name. For the example I'm going to call it UseMsSql.
You'll also need to set the From and To drivers. If the SQL backend restricts the number of characters (for example old versions of MySQL has a 12 character limit) then enter that. In the case of most SQL backends you'll need to enter a database prefix. For MsSql this is most likely to be dbo. (including the .) but this does depend on your database.
In the data DLL you'll also need to enter the Owner (usually a variable that contains the database connection string) and optionally a Send string.
2. The second part of the process is creating the actual MSSql version. You do this by creating a Version in the normal way. There are 2 things you need to do here differently to a normal version. Firstly go to the Defines Tab (of the version) and enter your Conditional Define, followed by =>1. for example;

Then go to the Resources Tab (still in the same Version) and click on the Other File Drivers button. Here you'll need to make sure that your Export Memos is unchecked for SQL versions.
Note (for FM3 users):
Overriding Driver Substitution for individual files
If you'd like to keep specific data files as a type (not being influenced by the Driver Substitution), then you can add the following File UserOption to your dictionary file declaration:
FIXDRIVER <DriverType>
Open your dictionary and right-click on the file that needs to be fixed, go to the options tab and add a User option as follows:

Note, you must set the Value to what you want it to be (typically the original FileDriver itself).
Handling Dynamic Indexes in your Dictionary
The easiest option is to remove the dynamic Index(es) - although this is not always possible to continue supporting your TPS version. If you cannot delete the dynamic index, then you need to do the following in the Key User Options for that particular index:

Basically, MultiProj needs to force a field name into the Index, so that a non-dynamic index will be created in the SQL project. The above FieldName option is the name of a field in that table.
Browse Filtering in your app
In your browses, you may have used different keys in filters for the browse. When using SQL, you need to use the primary key - or alternatively add the primary key component field to the key that you are using.
Auto Numbering
Often it's useful to be able to use a AutoNumbered key in the TPS version of your application, but transfer the autonumbering to the server-side when compiling the SQL version of the project. This is reasonably straight forward using Multi-Proj, but requires some changes in your Clarion environment (since the Clarion templates themselves are not aware of Multi-Proj). We have submitted a change for SoftVelocity to attend to, and this should hopefully be included in future versions of Clarion.
Note: If you are wanting to prime the record (for child browses) you will need to use the driver options string as specified in the FM3 docs.
Firstly, what you need to change in your Clarion templates:
Open your ABPROGRM.TPW file in a text editor (you can use the source editor in Clarion) and search for the following line (Clarion 6 users of 9058 and up):
#ERROR('An Identity Column can not
belong to an Auto Number Key (Key:'&%Key&' - Column:'&%FileIdentityField&')')
#ERROR('Set the Auto Number option to false.')
An Identity Column can not belong to an Auto Number Key (Key:%Key -
Column:%FileIdentityField)
Set the auto Number option to false.
Comment out those lines as follows:
#!ERROR('An Identity Column can not belong to an Auto
Number Key (Key:'&%Key&' - Column:'&%FileIdentityField&')')
#!ERROR('Set the Auto Number option to false.')
!An Identity Column can not belong to an Auto Number Key (Key:%Key -
Column:%FileIdentityField)
!Set the auto Number option to false.
Do the same to the CW.TPL file.
Secondly, what you need to change in your ABFILE.CLW and ABFILE.INC (at the time of writing this clarion 6 9059 and below, and clarion 7.1 and below):
Open your ABFILE.CLW file in a text editor (you can use the source editor in Clarion) and search for the following line:
RelationQueue QUEUE,type
Cut the complete definitions of the RelationQueue, KeyFieldQueue, FileKeyQueue, FieldsList, SaveQueue and BufferQueue queues (this should be around 55 lines of code) and paste those definitions into the ABFILE.INC
Thirdly, you'll need to setup your DCT for Server-side and client side autonumbering as follows:

Fourthly, open your application in the IDE, and go to the MultiProj template (Global | Extensions | Activate MultiPrj):
On the resources tab, click the Override Driver Possibilities button, and locate the SQL override that you want to make the numbering server-side. Click the properties button, and in the Make Auto-Number drop down list, select the "Server-Side" option.
%mpRscAllIf your template has a statement like
#Project('Cool.Ico')then you need to add the following to your template
#AT(%mpRscAll)
%#pragma link ("Cool.Ico")
#ENDAT
#Project('Tag.Clw')then you need to add the following to your template
#AT(%mpCompileAll)Note that the above embed point is used for Source files which are included Regardless of the Target (16 or 32-bit) or the Runtime Library (i.e. Stand-Alone or Local). There are also embed points which are only used in specific cases - i.e. if the your external source file is dependant on the Runtime Library, or the Target then you can use the following embed points;
%#compile "Tag.Clw"
#ENDAT
#AT(%mpCompile) #! 16-bit DLL
#AT(%mpCompileX) #! 32-bit DLL
#AT(%mpCompileL) #! 16-bit Local
#AT(%mpCompileXL) #! 32-bit Local
#IF(%ApplicationLocalLibrary)In this case there are 4 separate embeds you can use, one for each case. A Multi-Proj equivalent of the above would look like this;
#IF(%Target32)
#PROJECT('CL5Fm232.lib')
#ELSE
#PROJECT('CL5Fm216.Lib')
#ENDIF
#ELSE
#IF(%Target32)
#PROJECT('CW5Fm232.Lib')
#ELSE
#PROJECT('CW5Fm216.Lib')
#ENDIF
#ENDIF
#AT(%mpLibXL)
%#pragma link ("CL5Fm216.Lib")
#ENDAT
#AT(%mpLibL)
%#pragma link ("CL5Fm216.Lib")
#ENDAT
#AT(%mpLibX)
%#pragma link ("CW5Fm216.Lib")
#ENDAT
#AT(%mpLib)
%#pragma link ("CW5Fm216.Lib")
#ENDAT
These are template driven defines that are placed in the Project Defines section. Typically your code might look like this:
#pdefine('MyDefine=>1')
Leave this define as is for non-Multi-Proj users, but for Multi-Proj users, add the following:
#AT(%mpDefineAll)
%#pragma define(MyDefine=>1)
#endat
Many times you may have global data that you are wanting to export to your other programs. This can be done by simply writing these into the EXP file as follows:
#AT(%MultiProjInsideExports)
#for(%MyGlobalData)
#!Code in here
#ENDFOR
#endat
For the 'code in here' check out the %DataExport group in the MultiProj template file for details on how to do this (the multiprj.tpl file is located in the 3rdparty\template directory of your Clarion install). You can also check out how MultiProj exports the data in the exp file.
_Demo_=>1Notice the somewhat unusual => sign (which means equals).
If you are doing a multi-driver system and you want to add code for a specific driver, then you can use the Conditional Define that you created on the OverRide Driver Possibilities list. For example if you used UseMsSqlDriver then you can encapsulate some code in a conditional compile. For example;
COMPILE('***',UseMsSqlDriver )
myview{prop:sql} = 'Select * From Customers'
***
This code will then only be executed when the MSSql driver is being used.
I'm getting compile errors in my Project
1.1. I've added a new function to one of my DLLs, but when
I try to use it, it says 'unresolved external' in the other application.
1.2. When I run my Multi-Proj compiled application, the
Application icon is not the same.
1.1. I've added a new function to one of my DLLs, but when I try to use it, it says 'unresolved external' in the other application.
Answer: You probably have not setup Clarion to re-register your templates, so your application does not know about the new function added to the DLL. Set this up in the Clarion IDE as follows:

1.2. When I run my Multi-Proj compiled application, the Application icon is not the same.
Answer: You need to tell Multi-Proj what your application icon is in the Resources tab of the MultiProj template (you'll find an Application Icon entry field on that tab).