postheadericon How to link MJFAF statically and dynamically

What is static and dynamic linking?
C++Builder applications can be linked dyanamically or statically.  First up, what's the difference?

The VCL is made up of many runtime packages, such as rtl.bpl, vcl.bpl, vclx.bpl and many more.  These packages can be thought of as a special type of DLL.  The main difference is that packages can export classes and they share the same memory manager as the host application (unlike DLL's that always use their own memory manager).

C++Builder™ provides two project options; 'Use dynamic RTL' and 'Build with runtime packages'.  The choice of dynamic or static linking is governed by these two options as outlined next.

Dynamic Linking: This is where your project is compiled such that all dependent runtime packages must be distributed with your application.  To link dynamically, the Use Packages option is selected.

Static Linking: This is where your project is compiled such that all dependent runtime packages are linked into the application.  To link statically, the Build with runtime packages option is not selected.

The Use dynamic RTL option dictates if the memory manager (borlndmm.dll) and RTL DLL's (see list below) need to be distributed with your application or not.  If Use dynamic RTL is selected, you must distribute the DLL's.  If it isn't selected, everything is linked into your application.  As a handy reference, the list below names the single and multi-threaded RTL DLL's associated with C++Builder™ 5 to 2010.

 C++Builder™ Version 

 Single Threaded RTL   Multi-Threaded RTL 
 5  cc3250.dll  cc3250mt.dll
 6  cc3260.dll  cc3260mt.dll
 2006  cc3270.dll  cc3270mt.dll
 2007  cc3290.dll  cc3290mt.dll
 2009 and above  cc32100.dll  cc32100mt.dll

How to dynamically link correctly
When linking an application dynamically, it's recommended to turn both the Use dynamic RTL and Build with runtime packages options off.

Click images to have them open in a new tab/page

The following screen shots show the Use dynamic RTL and Build with runtime packages options in
C++Builder™ 5 (version 6 is very similar).

Dynamic RTL setting in C++Builder™ 5Use Packages setting in C++Builder™ 5

The following screen shots show the Use dynamic RTL and Build with runtime packages options in
C++Builder™ 2006 (version 2007 is very similar).

Dynamic RTL setting in C++Builder™ 2006Use Packages setting in C++Builder™ 2006

The following screen shots show the Use dynamic RTL and Build with runtime packages options in
C++Builder™ 2009 and 2010.

Dynamic RTL setting in C++Builder™ 2006Use Packages setting in C++Builder™ 2006

With these options set, you now need to manually add each of the MJFAF runtimes you're using to the list of runtime packages (each separated by a semi-colon).  As an example, if you need to link the MJFAFCore_c14 and MJFAFThreads_c14 runtimes into your application, the list of runtimes would look something like the following (C++Builder™ 2010 shown):

Defining the MJFAF runtime packages to be dynamically linked

Theoretically, this is all that is required to now build your application dynamically.  Even so, take the time to read the next section just in case you decide to later compile statically.  

How to statically link correctly
When linking an application statically, it's recommended to turn both the Use Dynamic RTL and Build with runtime packages options off.  So, in the previously shown screen shots, these options are not selected.  Assuming the project file correctly references the libraries associated with each of the MJFAF runtimes used, then performing a new build will create your statically linked project.

Now, by saying "references the libraries", this does not mean you need to explicitly add the libraries to your project.  It means the content of the BPR/BDSPROJ/CBPROJ file needs to include the names of each library required.  Unfortunately, the IDE does not correctly update the project file with the required library names when manually adding the names of runtime packages.

MJFAF gets around this by explicitly linking the required libraries via #pragma link statements.  The following example from mjfCoreOpt.hpp links the MJFAFCore library specific to the compiler being used.

#ifndef USEPACKAGES
  #if MJF_BCB_5 == 1
    #pragma link "MJFAFCore_c5.lib"
  #elif MJF_BCB_6 == 1
    #pragma link "MJFAFCore_c6.lib"
  #elif MJF_BCB_10 == 1
    #pragma link "MJFAFCore_c10.lib"
  #elif MJF_BCB_11 == 1
    #pragma link "MJFAFCore_c11.lib"
  #elif MJF_BCB_12 == 1
    #pragma link "MJFAFCore_c12.lib"
  #elif MJF_BCB_14 == 1
    #pragma link "MJFAFCore_c14.lib"
  #else
    #error "Need to define library to link"
  #endif
#endif

Now, just for reference, if you're working with other runtime packages the remainder of this FAQ details how to manually edit the project file outside of the IDE to accomplish the same end result.

After closing your project in the IDE, open it in a text editor of your choice (depending on the version of C++Builder™ being used, the project file will have an extension of BPR, BDSPROJ or CBPROJ).  The required modifications detailed below (abbreviated to conserve space) show how to ensure the MJFAFCore and MJFAFThreads libraries are correctly referenced for each version of C++Builder™ since version 5.

C++Builder™ 5
<PROJECT>
  <MACROS>
    ...
    <SPARELIBS value="Vcl50.lib Vclx50.lib MJFAFCore_c5.lib MJFAFThreads_c5.lib"/>
    <PACKAGES value="Vcl50.bpi Vclx50.bpi MJFAFCore_c5.bpi MJFAFThreads_c5.bpi"/>
    ...
  </MACROS>
  ...
</PROJECT>

C++Builder™ 6
<PROJECT>
  <MACROS>
    ...
    <SPARELIBS value="Vcl60.lib Vclx60.lib MJFAFCore_c6.lib MJFAFThreads_c6.lib"/>
    <PACKAGES value="Vcl60.bpi Vclx60.bpi MJFAFCore_c6.bpi MJFAFThreads_c6.bpi"/>
    ...
  </MACROS>
  ...
</PROJECT>

C++Builder™ 2006
<BorlandProject>
  ...
  <CPlusPlusBuilder.Personality>
    <BCBPROJECT>
      <project version="10.0">
        ...
          <property category="build.node"
            value="rtl;vcl;vclx;MJFAFCore_c10;MJFAFThreads_c10"/>
          <property category="build.node"
            value="rtl.lib vcl.lib vclx.lib MJFAFCore_c10.lib MJFAFThreads_c10.lib "/>
        ...
      </project>
    ...
  </BCBPROJECT>
  ...
</BorlandProject>

C++Builder™ 2007
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <PropertyGroup Condition="'$(Base)'!=''">
    ...
    <PackageImports>rtl.bpi;vcl.bpi;vclx.bpi;MJFAFCore_c11.bpi;MJFAFThreads_c11.bpi</PackageImports>
    <AllPackageLibs>rtl.lib;vcl.lib;vclx.lib;MJFAFCore_c11.lib;MJFAFThreads_c11.lib</AllPackageLibs>
    ...
    </PropertyGroup>
  ...
</Project>

C++Builder™ 2009
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <PropertyGroup Condition="'$(Base)'!=''">
    ...
    <PackageImports>rtl.bpi;vcl.bpi;vclx.bpi;MJFAFCore_c12.bpi;MJFAFThreads_c12.bpi</PackageImports>
    <AllPackageLibs>rtl.lib;vcl.lib;vclx.lib;MJFAFCore_c12.lib;MJFAFThreads_c12.lib</AllPackageLibs>
    ...
  </PropertyGroup>
  ...
</Project>

C++Builder™ 2010
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <PropertyGroup Condition="'$(Base)'!=''">
    ...
    <PackageImports>rtl.bpi;vcl.bpi;vclx.bpi;MJFAFCore_c14.bpi;MJFAFThreads_c14.bpi</PackageImports>
    <AllPackageLibs>rtl.lib;vcl.lib;vclx.lib;MJFAFCore_c14.lib;MJFAFThreads_c14.lib</AllPackageLibs>
    ...
  </PropertyGroup>
  ...
</Project>