Delphi - How to build a package for distribution - delphi

Using Embarcadero RAD Studio XE7, I wrote a runtime package containing a VCL component (it's a TGraphic descendent). Now I want to distribute this component, but only the compiled package without his source code. I cannot include it in the distribution because I wrote this package for a company that want to sell it and keep the control on his sources, so distributing the source code isn't an alternative in this case.
The component package depends on 2 other packages I also wrote. All of these packages are runtime, however a graphic filter is registered. After the package is installed, this filter allows me to open a new kind of image file from several native VCL components like TImage on my development computer. This behavior is very important and I want to keep it on the target IDEs.
Ideally I want my package to be installed on all RAD Studio platforms between XE and 10.2 Berlin. However I recently tried to compile my package in release on my devel computer and deploy it manually on another computer installed with RAD Studio XE4. The result was unconvincing:
Trying to install the .bpl file using the Component->Install packages... failed with a "The specified module could not be found" error. When opening the .bpl file with the Dependency Walker tool, I noticed that several dependencies like RTL210.bpl were missing
I also read somewhere that only design time package may be installed this way, it is exact?
Putting all the files (.bpl, .lib, .hpp, ...) of one of my package manually in the XE4 common dirs, I was able to compile a test project successfully. However several functions in my package were unavailable (resulting to an unresolved external when trying to use them)
Although I have several past experience about software and package distribution, I must confess that I have absolutely no idea about how to build a such package for deployment. In all my past scenarios I always distributed the package projects and source codes, and let the user install them on their own IDE.
I searched information about that in the past days but I found nothing. So if somebody can explain how to achieve a such package, or can point me to a document or website describing the process, or eventually give the name of a tool that can do the job, I would be very grateful to him.
Regards

If you don't want to to distribute the source files, you then need to provide the .dcu and bpl files. As Uwe says, you need different packages for each Delphi distribution.
What I have done in the past is to create an installer which builds and registers the packages. You can find the full description here:
http://www.kouraklis.com/2016/10/build-and-install-packages-in-delphi-ide-using-innosetup/
I think you can modify the script to skip the call to MSBuild.
Hope this helps.

Related

how i solve error dxdbtrD14 bpl is missing

Please help me with this problem.
This problem comes when I move my project to another PC. This program works fine on my PC.
You have your project configured to compile with Runtime Packages enabled. That means for any standard, 3rd party, and custom packages that your project uses, you have to deploy their respective BPL files that your EXE depends on, in addition to the EXE itself.
A BPL is just a fancy DLL with built-in support for Delphi’s RTL and VCL/FMX frameworks. The error you are getting is a standard Windows error popup dialog when the OS loader can’t find a required DLL that an EXE is statically linked to.
To avoid the error, you need to either:
deploy all required BPL file(s) along with your EXE. Use a tool like Dependency Walker to figure out what they are.
turn off the “Runtime Packages” option. Your EXE will be much larger, but it will be more self-contained, as the relevant package code will be built into the EXE itself.

Delphi 10.1 doesn't find the units added with an installed package

I use Delphi 10.1 Berlin Starter and have the following problem:
Is added some packages by opening them, and installing them by right-clicking on the package in the project manager and choosing "install". The compiled packages are now in the same folder as the other packages Delphi uses, so I think that there cannot be a problem with the library or search path.
The packages also added some Components that are now accessible in the tool palette. If I add one of these components to my program, Delphi automatically adds the unit name of the component to the "uses" section of the unit containing the component. But if I want to compile, Delphi throws the fatal error "could not find unit_name.pas".
How can I fix this? Does the units required to build and install the packages have to be included in a library path?
Maybe this is a compatibility problem. The packages were written in 2008 (Are Namespaces in Delphi younger?), so maybe the way the package wants to tell the compiler what to do does not work anymore.
This question might be difficult to understand (I had some problems to explain it...), so please comment, if you need more information.
Quite easy, I just had to add the units of the package to the library path (Tools->Options->Delphi Options->Library). Worked. Thanks to KenWhite.

What is the best way to install components?

Installing components under Delphi XE3 is a nightmare.
First I need to add source files to
Tools -> Options -> Library
then I need to find a normal package and compile it
finally I need to find design time package and install it.
This is just quite tedious and error prone. Is there a nicer way to install components?
I have found Delphi Package Installer. Unfortunately it doesn't support Delphi XE3 or above.
I have heard that there is something similar which produces exe packages that install themselves (something like Inno Setup) but I can't find such thing.
No. The steps above are required.
First, adding the file path to Tools->Options->Delphi Options->Library Path is so the compiler knows where to find the files to compile them. (Actually, it's not required - you can eliminate this step by making sure that the .dpk files are in the same folder as the .pas files, and that all .pas file names are listed in the includes section in the .dpk. If the .pas files are in a different location, you'll need to either use relative paths in the .dpk (eg., MyComponents in '..\Source\MyComponents.pas') or add the location of the .pas files to Project->Options->Delphi Compiler->Search Path.)
The next step (finding the "normal package") is in order to build the runtime package. It's required, because the design-time package (next step) requires the code that's in that package in order to function in the Form Designer. It's also needed when you decide to build your application with runtime packages, if you use the third-party components and want to distribute the runtime package for it.
The separate design-time package (the third step) is required because designtime code can only be used at design-time; there's nothing that can be distributed with an application if it's built with runtime packages and the package build in step 2 is one of them.
This has been the way components are installed since around Delphi 3 or so, and the requirement to separate out designtime code into it's own package started being advised in Delphi 5 and enforced in Delphi 6 (when they relocated much of the IDE designtime support into their own separate packages and stopped distributing the source for them).
There really are no other options, unless the vendor supplies pre-build designtime and runtime packages for you, or supplies an installer that will do all of the above steps. (Most don't.) But if you update your Delphi version, you'd still have to go through the steps above.
What about the built-in component installer? It is part of Delphi XE, XE2 and XE3 and a description can be found here (I wrote it). It will even install components in C++Builder. You can instal into an existing package or into a new one, which it will create for you.
I would say that the best way to install components is to use your build manager (for example FinalBuilder) and add each component to a manager-project file which sets the necessary paths, builds the DPK files, and 'installs' the component in the IDE by making a registry entry. That way you have a documented procedure which allows you reliably to set up or repair your complete, tested, Delphi development environment. You can simply re-run the project when a component has been updated and tested. It is also quite easy to tweak an existing project to handle a new Delphi version.
The big disadvantage of a vendor-supplied installer is that all the ones I have seen simply overwrite the previous version on updates. I prefer to control the install myself, so that I have previous component source versions archived and available for comparison, in case testing reveals a problem with an upgrade. The 'one-click install' sounds fine, until a minor component upgrade suddenly causes your application to stop working.
Take a look at "Lazy Delphi Builder". It was created to simplify build/installation of many components at once. It resolves packages dependencies automatically. Free to use.
Link to some old tutorial

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.

InstallAware problem with Delphi 2010

I am trying to create an installation disk with InstallAware Express for my Delphi 2010 application. I have selected (checked)
CodeGear Database Express12
CodeGear Visual Component Library 12
for Application Runtime.
When I try to build it, I will get an error message
Error during build: No files matching pattern "C:\Windows\system32\*120.bpl"
The message will go away if I un-check the above runtime but of coz the program will not run.
Can someone please tell me what I am doing wrong?
Also... I have use their scan file button to scan the dependent files base on my application.exe and installaware put a list of files in the $TARGETDIR$, should I leave them there or I am suppose to move them to various folder (e.g. some of the files are from the windows\system32 directory...)
Thanks a lot.
FWIW, one of the great things about Delphi is that you can pretty much install on any system without worry if you turn off the "build with packages" option. This would eliminate the need for these files, and solve your problem, and also make the application more robust against updates and changes. IMO packages are only needed if you are building multi-module applications which are more advanced, and in that case you wouldn't want to be using any Express installer.
You can manually add the files.
To find out which VCL packages your application uses, open the project in the IDE. Use the menu item Project->Build project to rebuild your entire application, and then use Project->Information to view the information dialog. The list of packages actually required by (and therefore needing to be distributed with) your application are listed there.
Where to install them on the destination system depends on why you're using packages in the first place. If you're using runtime packages simply to reduce the download size for your users, and the packages will only be used by this single application, put them in the same folder as your application ($TARGETDIR$). If you're using them because you've got several different applications, and they'll all be installed in different locations but use the same runtime packages, install them in the System32 folder ($SYSDIR$, if I remember correctly).
InnoSetup works fine with runtime packages manually added, btw, especially if you use the excellent (and also free) ISTool IDE. (Not affiliated in any way; just a happy customer.)
Did you have Delphi 2010 installed on this machine? If so, you should see several bpl files under C:\Windows\system32 folder.

Resources