Custom component dependency hell
Asked Answered
C

4

11

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?

Counterintelligence answered 24/3, 2012 at 16:41 Comment(7)
Component installation is a shame of Delphi, constantly ignored by now Embarcadero.Gentlemanatarms
What kind of distribution are you doing, to users of compiled applications or other developers for them to use in the IDE?Katheykathi
@Katheykathi Packages with controls for other developers (team members) to use.Counterintelligence
I agree with @Serg. I always want to hang myself when ever I need to deploy components which are dependent. I never even bother to create packages. I load most of my components at run-time to avoid that nightmare...Prebo
So how do 3rd party component developers do this? Do they always use just the VCL?! I can't imagine that the best solution would be to manually copy all used units into my own, and then remove them from uses...Counterintelligence
Which version of Delphi / V.C.L. are you using ?Jarry
@tvdien, the most of 3rd party VCL I have seen depend only on the "native" VCL/RTL, except for when they use well known other 3rd party components as an option such as "TNT" (which is usually a compiler directive option) or need to add PNG support (so they use PngImage as option), or based on VST etc etc... of course it all depends on Delphi version, since most of well known 3rd party components (not commercial) are now integrated in newer versions of Delphi (i.e XE/2).Prebo
S
2

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).

Solferino answered 13/8, 2013 at 11:39 Comment(2)
How do you check if a package isn't already installed (since you can't have it twice)? There's isn't a fixed location where to expect it.Counterintelligence
@ThijsvanDien: all the packages registered with the IDE are listed in the Windows Registry under HKEY_CURRENT_USER\Software\Embarcadero\BDS\7.0\Known Packages. The BDS version depends on the Delphi version. If I'm not mistaken, 7.0 means Delphi 2010. Take a look at the items under that key to determine if a certain package is already present in the IDE.Solferino
J
0

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.

Jarry answered 24/3, 2012 at 21:43 Comment(2)
Sorry, but I don't see how this answers my question about how to write and/or distribute a component in such way that the user (a developer) does not have to take special measures (downloading/installing dependencies, organizing his project in a specific way) to use it.Counterintelligence
The "Design Time" is sort of previous step to your goal. The "runtime" is more directed to the distribution.Jarry
P
0

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.

Plattdeutsch answered 28/4, 2013 at 16:53 Comment(1)
Instead of a DLL, could I use a BPL, to be able to use objects? And isn't it possible to compile a BPL into the exe?Counterintelligence
A
0

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:

  1. Uninstall all dependencies your component uses

  2. In your component package, remove the above dcp from the requires section from your package.

  3. 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.

Armipotent answered 9/11, 2013 at 14:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.