Determining Delphi Runtime Packages to Include - delphi

I have a Delphi DLL that houses a form which uses a variety of third party components. This DLL is used by many different versions of Delphi. I compile the third party components into the DLL. I believe I still need to link to some "base" Delphi packages like rtl, vcl, etc, so my DLL will use the same memory manager and other global resources that the Delphi IDE is using. How do I find out what BPLs I need to link to?
Ideally I'd like to point some utility at my DLL or project and have it list every BPL that it would depend on if I was only using BPL's and had no source files available. Then I could view that list and pick the packages I want to load at runtime. The current list given in the project properties under "Runtime Packages" is incomplete (as it has been tweaked over the years).

Check a tool I wrote called "Required" - you can download from http://www.drbob42.com/tools

Check the "Build with Runtime Packages", leaving the whole list of packages the way it is.
Do a Project|Build (not compile!). After the build completes, use Project|View Information on ; the resulting dialog will give you a list of the actual packages you need to distribute.
After Jeremy's comment about the default list of packages being empty when he enables building with packages, here's the list from that options dialog from Delphi 2010:
vclx;vcl;vclimg;dbrtl;Rave77VCL;bdertl;rtl;vclactnband;xmlrtl;
vcldb;vcldbx;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;
ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;
intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;inetdb;
webdsnap;websnap;inetdbbde;inetdbxpress;soaprtl;vclribbon;
DbxCommonDriver;DbxClientDriver;DBXInterBaseDriver;DBXMySQLDriver;
dbexpress;dbxcds;SynEdit_R2009

You can evaluate tools like, Dependency Walker (depends) or PE Information (image bellow) included at GExperts.

"This DLL is used by many different versions of Delphi."
Do you mean that you have programs written with Delphi 7 and other programs written with Delphi 2007 etc. that use the same precompiled DLL?
In that case you cannot use any packages to share object types and memory between program and DLL because they will use different versions of the packages wich are not compatible.

Related

Run-time packge option asks for bpl files

So I've built a run-time package for my application. That requires some other BPLs like : ADORTL.bpl, BDRTL.bpl, VCL.bpl and so one. Now I want to use this BPL I've created in my main application and I also want to load it at runtime. So everytime a user does an action that require some info from the bpl, i load it, and unload it after there is no need.
In order to use my bpl in the main application I have to compile my app with run-time packages. If I do so when I move the .exe file to an other computer with no Delphi installed it askes for lots of bpls to work. Is there a way I can built with run-time packages and somehow integrate (vcl.bpl,adortl.bpl) in the exe file?
I would like that my main app only to ask for the bpls i've created, not the Delphi IDE bpls.
No, that is the way it works. You compile either with runtime packages or without. It is like being pregnant: either you are or you are not.
In the project options, where you specify to use runtime packages, there is an edit box that lists the needed packages. Remove any package names you don't want, any they'll be compiled into the EXE file.
Note, however, that the BPL files you keep also use other BPL files. In particular, your BPL probably uses the VCL and RTL packages. Thus, when you load your package, it will implicitly load the other packages. You mustn't have multiple copies of any unit loaded simultaneously. Your package uses RTL, so your EXE needs to use the RTL package, too; you cannot omit it from the edit box like I described above. If you do, then your EXE would have one copy of the RTL units and the package would have another, which isn't allowed.
If there is some package that is only used by your package, then there's something else you can do. Remove that other package from the "requires" list of your package and recompile. The compiler will warn about implicitly included units, namely the units that ordinarily reside in the package you just removed. Explicitly add those units to your package and recompile again. Repeat until the warnings are gone. You're essentially defining a "superpackage" of all your package's unique dependencies. (VCL and RTL are not unique dependencies, so don't omit them from the "requires" list.)
You cannot arrange for your EXE to use only one BPL file and for that BPL file to be loaded and unloaded dynamically. If you load packages dynamically, then at a minimum, you need to use the RTL and VCL packages, too.
Furthermore, the Delphi license you agreed to might restrict you from repackaging the RTL and VCL units. I'm not clear on the details. Go reread the license carefully to check.

Custom component dependency hell

I'm trying to make a package for a custom component I made. It's based on several libraries, including Graphics32, GraphicEx and CCR.Exif.
I created a Package project, wrote the unit including its Register procedure, added some extra references Delphi notified me about to the requires section (including dbrtl.dcp, inet.dcp, soaprtl.dcp, vclimg.dcp, xmlrtl.dcp and dclGraphicEx140.dcp) and added many units to the contains section to avoid warnings about it happening implicitly. The project compiles and can be installed and used on my own machine without issues. However, when I want to install it on another machine, the troubles begin. In the end, I had to copy about all DCUs from all 3rd party components I used, plus both the DCP and BPL from GraphicEx, which I had to install even.
Supplying a lot of files is a bummer, yet surmountable, but having to install other packages as well is a no go. I could get rid of that DCP and BPL by putting even more units in the contains section, but that resulted in error messages on my own machine where GraphicEx is actually installed. This is confusing to me, because with Graphics32 nothing like that occurs...
Anyway, how do I keep my distribution to a minimum and avoid such situations? I want other developers on my team to be able to use the package without worrying about what I used to build it. For a start, can't all the 3rd party units be compiled into my own DCU?
What you experienced is an usual thing to the ones who write components. The distribution is always like that. Packages do not carry other packages, insted they reference them. It´s in their nature.
In order to overcome such a situation I always treat my components in the same way I would if they were a product to sell: I build a setup wizard that distributes and registers everything the package needs.
In my case InnoSetup works very well (http://www.jrsoftware.org/isinfo.php).
Summary
Haven't use Delphi for a while, but, did develop my custom visual controls (Last version I work was Delphi 6).
There are 2 issues when dealing with packages dependencies. One is installing at the Delphi enviroment, making controls appear on the component palette, plus, component editors & property editors.
And another when distributing the compiled packages into customers machines.
It also depends, on which version on Delphi you are running.
Design Time
When developing a custom package, there is a tab for package options, that indicates the destination folders.
The manuals usually tell the developers to leave those textboxes empty. That sometimes works, sometimes doesn't. I explicity write each folder path, in the respective textbox.
There is a textbox path for the ".dcp" files, other for the ".dcu", and so on.
If you have visual controls and stuff like property editors or component editors, its better to split the code in 2 packages ("Runtime" & "Designtime").
I usually put the delphi (packages) projects outside the delphi installation folder.
Run Time
Usually, the quick way is to put the "*.bpl" ".dcp" files in the Windows (32) / system folder, or similar "DLL" windows folder.
Packages folder structure source code suggestion
Managing packages can be difficult. I don't know how much the installation process has changed with Embarcadero, and the newer versions of Delphi. The following chart,is an example on how organize the source code. Hope it helps.
[-]--+--c:
.....|
.....+--[-]--+--software
.............|
.............+--[+]-----java
.............|
.............+--[+]-----php
.............|
.............+--[-]--+--delphi (not the delphi folder in program files)
.....................|
.....................+--[+]-----apps (source code for delphi programs)
.....................|
.....................+--[+]-----other
.....................|
.....................+--[-]--+--packages (all delphi packages source code here)
.............................|
.............................+--[+]-----lib (a single package for non visual controls, libraries)
.............................|
.............................+--[+]-----tools (package pair for non visual tcomponent descendants)
.............................|
.............................+--[+]-----json (example)
.............................|
.............................+--[+]-----xml (example)
.............................|
.............................+--[-]--+--mycontrols (folder custom visual controls)
.............................|.......|
.............................|.......+--[-]--+--delphi40 (folder for delphi40 version of "mycontrols")
.............................|.......|.......|
.............................|.......|.......+----------dsgvclctrls40.dpk (design-time package "mycontrols")
.............................|.......|.......|
.............................|.......|.......+----------runvclctrls40.dpk (run-time package "mycontrols")
.............................|.......|.......|
.............................|.......|.......+--[+]--+--demos (individual example for each "mycontrol")
.............................|.......|.......|
.............................|.......|.......+--[+]--+--design ("*.pas" component editors destination folder)
.............................|.......|.......|
.............................|.......|.......+--[+]--+--sources ("*.pas" source code destination folder)
.............................|.......|.......|
.............................|.......|.......+--[+]--+--bin ("*.dcu" destination folder)
.............................|.......|........
.............................|.......+--[+]--+--delphi50 (folder for delphi50 version of "mycontrols")
.............................|.......|........
.............................|.......+--[+]--+--delphi60 (folder for delphi60 version of "mycontrols")
.............................|.......|........
.............................|.......+--[+]--+--delphi70 (folder for delphi70 version of "mycontrols")
.............................|................
.............................+--[-]-----etc...
Cheers.
Thijs, you simply cannot do that with only a package. The target developer will require almost everything you added to the package. But there is an alternate way of doing what you want: Build a DLL with all the components/libraries you are using in your own component and wrap all those external components/libraries into some code you will export from the DLL. Then build your component without using the external components directly but the DLL you've built. You cannot in you component "use" any unit of the other external components/Libraries. You have to build a new unit with all the datatypes and required declaration for anything you export from your DLL. All this is perfectly working but will quickly becomes very complex for a large number of external components or libraries.
I think AlexSC has the best answer, but I think there might be an alternative if you ansolutely must have a custom component that has no dependencies.
I ran into the Delphi dependency frustrations a little while back trying to create an in-house component for our developers. My suggestion:
Uninstall all dependencies your component uses
In your component package, remove the above dcp from the requires section from your package.
Copy the source files of your dependencies to your components
When you distribute the component, you'll have to distibute it with the code of the required dependecies
You'll run into issues if you want to use the dependcies separately since Delphi won't allow you to have duplicate unit names in installed packages.
Also, the reason you don't want to use DCUs is the fact that the DCUs are compiled for a specific platform and compiler. So unless you are sure that all devolpers are on the same platform ad using the same version of Delphi, dependency code needs to be recompiled.
Again, AlexSC has the best answer and InnoStudio is a great little tool.

How do you determine from a BPL if it is design time only

We build all our packages to the same output directory.
The directory includes both design time and runtime packages.
Looking at the resulting BPL's is there a way to determine that a packages is Design Time only?
I want to be able to filter these out of my deployment list, as I am building with runtime packages.
In the past I have built custom lists, of the run time packages. I am looking for away to automate this process.
We are using Delphi XE if there is a version specific answer.
Use GetPackageInfo and check for pfDesignOnly in the Flags parameter.
Or, if you'd like to skip the unnecessary enumeration of contained units and required packages, have a look at PackageInfoTable in SysUtils (which is, unfortunately, hidden in the implementation section).
AFAIK, not externally without analyzing the imports of the BPL to see if it has any dependencies on the design-only IDE packages (eg., DesignIntf). You can do this with TDump or DependencyWalker. You can also use TOndrej's suggestion if you want to try and load the packages with an app.
A quick check of one of the design only packages on my system with DependencyWalker shows this:
The usual solution to this issue (as you can see in the Virtual Treeview package in the image) is to add a D suffix to design-time packages; some component sets (like some of the TurboPower ones, IIRC) use an R suffix for runtime packages as well.

which one is best for use in delphi i.e use of package or dll

I'd like to use a .dll with a delphi application, but I'm curious if a delphi package is more flexible than dll?
You can read this article on my Blog: "DLL's, BPL's Static and dynamic loading, and Packages in Runtime"; Is 's writed in Spanish but you can try the Automatic translation (on right part of the page).
Basically BPL is an extension of a DLL. It's a DLL with some things added.
(POSITIVE) If you use BPL's you can do more things with the DLL. More power. You can use RTTI (you must build your applicaction with runtime package for accesss RTTI).
(NEGATIVE) If you use BPL's with more powerfull, you can only use it with Delphi, no with other languages.
If you're sure that you only use it with Deplhi, I think that you must use BPL. Search samples about RTTI, RegisterClasses, GetClass method, LoadPackage (for dynamic load),...
Regards.
Escuse-me for my poor english. It's not my natural language.
Not knowing excactly what you mean, and believing you are a newbie (so I may omit some specialized aspects), and implying you know what a DLL is:
The first and foremost reason to build a package is authoring a design-time component.
You can do quite everything (well..almost...) that a package does just as well with DLLs -- except for the design-time stuff.
Additionally, you can package multiple compiled packages into one Borland Package Library (BPL file) without having the design-time features in mind. If you think deploying and runtime-binding one BPL is better than various DLLs, go for it. The primary purpose is design-time support, though.
Packages are special DLLs that can export classes, while DLLs can only export functions. Yes, you can write a DLL function that creates and instance of a given class, but you can't use a class declared in a DLL (unless using some hacks maybe), while you can use a class declared in a package directly. Packages "know" about Delphi object architecture, while DLLs don't. On the other end, DLLs can be used from any language able to use them, while packages are Delphi-specific.

Distributing a design-time package w/third-party UI elements

Now that I am learning more about design time aspects of component development, I have what may turn out to be a couple of IDE "plugins" targeting Delphi 2007 (+ others if compatible).
The forms / UI for these, ideally, will utilize some of the third party components I use regularly. Assuming the licensing is okay to distribute those components for an IDE plugin, etc., what do I need to do differently to prepare the distribution package, as compared to from what one would do on a package with "full source"?
(I hope this question makes sense. Please be kind and ask questions if not).
You need to distribute the BPL compiled for each version of Delphi you will support (Version + Update) and then only distribute the BPL. Set up a Virtual Machine to test it in. The BPL is a special DLL, so you are only distributing a binary, which should work with your licenses.
Distributing the .PAS or .DCU would violate the license agreement most likely.
You will probably find that this causes all sorts of problems.
GExperts does it differently. It is a DLL that statically links to some 3rd party controls and references only Delphi's own runtime packages. This cannot cause any conflicts with other packages because the statically linked units are not visible to the IDE. It also means that GExperts does not need to distribute any runtime packages.
Do not distribute those components in your design-time package. It will cause headaches for you and your customers if your customers also happen to want to use those same components in their own projects. If you put those components' units in your design-time package, then your customers will not be able to also have their own copy of those components installed on the Tool Palette because only one copy of a unit may be loaded at a time.
The components you're using should have come in a run-time package from their vendor already. Put that package in your design-time package's "requires" list. Distribute the .bpl file only; I think you can install it in the same directory as your design-time package.
That run-time package will also be a requirement of the vendor's design-time package, which is what your customers will have installed in their IDE.

Resources