Many open source projects have moved from the former top dog SlashdotSourceForge to GitHub and in the process usually converted from Subversion to git. This also includes quite a few Delphi libraries like project Jedi (JCL/JVCL), SynEdit or Indy.
I am not really comfortable with git, it just feels too complex for most projects and the GUI tools I have tried are clunky compared to TortoiseSVN. I see some advantages, but so far I’m not convinced. So, I have stayed with SVN and used that to access GitHub repositories through their git-svn bridge. This works fine, most of the time, unless you want to rename a file, which apparently is not possible for whatever reason.
Now, contributing to such projects is another challenge. You need to create something called “pull requests“, which basically is a way of creating patches that are centrally managed by GitHub together with a discussion area for them. It took me a while to get my head around the process but I think I got it now. So here are the steps:
Get a GitHub account. There is no way around that.
Fork the repository of the project to which you want to contribute.
Create a branch in that forked repository. You need a separate branch for each pull request you want to create! (That was the main stumbling block for me, I just didn’t realize this. It’s probably documented somewhere but I overlooked it.)
Check out that branch.
Make your changes in that branch
Commit those changes and push them to GitHub
On GitHub, create a pull request
There are many sites that give you these steps sometimes with examples on how to do them, but always using git. Here is, how to do it without a git client, but using svn + the aforementioned git-svn bridge.
GitHub shows a url for each repository that can be accessed via git or svn. It looks like this:
Remember that this url contains the the whole repository, so in order to check out only the trunk (master branch) or a branch, you need to add /trunk or /branches/[branchname] to it.
Creating a branch can be done either with svn in the usual way or with the web UI on GitHub. I prefer the latter which is done by typing a non-existing name for a branch and pressing enter.
For the following steps lets assume we created a branch called “pullrequesttest”.
Using the svn client of your choice (mine is TortoiseSVN), check out the sources of the branch we just created. The url would be:
Just make your changes and commit them the usual way. Subversion does not distinguish between a commit and a push to the server as git does.
The branch now contains the changes you want to submit to the project.
On GitHub, select that branch and you will see a message about your changes an a button “Compare & pull request”.
Click that button, add a comment and submit the pull request. It should show up on the original project’s page. Somebody with the rights to it can now approve and merge these changes. They can also be discussed there. Maybe some further improvements are necessary to get them accepted. For that you simply make changes to the code you have checked out and commit them to the same branch. They will automatically become part of the pull request (Remember that I said you need a separate branch for each pull request? That’s why.).
Now suppose there are other, unrelated changes you would like to submit? Start with creating a new branch, based on master, check out the code, make the changes commit them and create a new pull request for the new branch.
Just remember to never make any changes to the trunk (=master branch). That one is meant to have the same content as the original repository and the base for each branch to be used for a pull request.
I’m sure this description is more complicated that it needs to be. My main idea in writing this article is to get a starting point for creating pull requests without having to use git. If you can think of improvements, please discuss them in Delphi Praxis. Note that this is not meant to become a discussion about the merits of git vs. Subversion. We don’t need another one of these.
Delphi, GExpertsComments Off on Bug and possible fix for GExperts Filter Exceptions expert – testers needed
Mahdi Safsafi has proposed a fix for the bug in the GExperts Filter Exceptions expert, which occurs when developing for non Windows targets (first reported on Embarcadero’s quality portal ). I have implemented this fix and it doesn’t have any adverse effects on for Windows targets. But neither he nor I can test it for non Windows targets since we don’t develop for these. That means we need testers. If you want to help, please post a comment on the bug report on SourceForge.
I have received a few reports about bugs in GExperts in Delphi 10.4.1 that do not occur in Delphi 10.4. Here is a GExperts DLL that was compiled with Delphi 10.4.1. Maybe it will solve some of theses problems.
Simply extract the DLL and put it into the GExperts installation directory, replacing the original one.
DelphiComments Off on Delphi’s TZipFile working on a stream
Recent versions of Delphi (for a suitable definition of “recent”) come with a TZipFile class implemented in the unit System.Zip. This class has the really neat feature that it can not only read the contents of a ZIP file directly from a stream but also extract a file from that stream to a TBytes array, thus it does not require any file system access.
E.g. imagine you have got a memory stream containing the contents of a ZIP archive (e.g. you got a zipped XML description from a GenICam compatible camera using the GCReadPort (PDF) function.). You now want to read a file from this stream and immediately process that file’s content without first writing it to the file system. This can be done like this:
// Some code here retrieves the ZIP archive's content and stores it in ms
Zip := TZipFile.Create;
ms.Position := 0;
if Zip.FileCount > 0 then begin
// now we have the file's content in Data and can process it.
One very important step here is to set the stream’s position to 0 before passing it to TZipFile.Open. If you forget that (guess who did) you will likely get an EZipException in TZipFile.Read with the error message ‘Invalid Zip Local Header signature’. The reason for this is that TZipFile.Open assumes that the current stream position is the first byte of the first file stored in the ZIP archive:
If you encounter this in a debugging session, simply add it to the OS Exceptions and set “Handled by” to “User program” and “On Resume” to “Run handled” (The program should handle it, it’s a bug if not. But we don’t want to see it at all.)
DelphiComments Off on IntToHex for UInt64 in Delphi
Just in case I ever need this again:
function IntToHex(_Value: UInt64): string; overload;
Buf := PUInt32(UInt32(@_Value) + 8);
Result := IntToHex(Buf^, 8);
Buf := PUInt32(@_Value);
Result := Result + IntToHex(Buf^, 8);
(Delphi 2007 does not have IntToHex for UInt64.)
Note: This works only for 32 bit compilers. For 64 bit, you must replace UInt32 with NativeUInt (or UInt64) in the first line (untested). Since unfortunately the NativeUInt declaration in Delphi 2007 is wrong, I cannot simply use NativeUInt here and be done with it.
Note: This works only on little endian systems (Intel):
"The little-endian system has the property that the same value can be read from memory at different lengths without using different addresses (even when alignment restrictions are imposed). For example, a 32-bit memory location with content 4A 00 00 00 can be read at the same address as either 8-bit (value = 4A), 16-bit (004A), 24-bit (00004A), or 32-bit (0000004A), all of which retain the same numeric value. Although this little-endian property is rarely used directly by high-level programmers, it is often employed by code optimizers as well as by assembly language programmers."
DelphiComments Off on Compiling TeeChart 2020 for Delphi 2007
We recently bought TeeChart 2020.30 VCL/FMX with full source code (of course) and I now tried to install it.
Steema provides a “TeeChart Source Code Recompilation Tool” (TeeRecompile.exe) that supposedly does this for you. This is fine if it works, it’s a pain in the lower back if it doesn’t. It worked fine for Delphi XE2 and 10.x but it failed for Delphi 2007 with the error “[DCC Error] DclTeePro911.dpk(39): E2202 Required package ‘IndyProtocols’ not found“.
There the pain began:
I had removed the ancient Indy10 version that was shipped with Delphi 2007 from my installation and deleted all the files. Instead I have downloaded the latest sources (OK, not the latest, the dowload was on 2020-03-20), but never bothered to compile the packages since we don’t use packages, not even the runtime packages.
So I looked for the Delphi 2007 package projects. There are 3 of them:
IndySystem110.dpk, IndyCore110.dpk and IndyProtocols110.dpk (I didn’t bother with the designtime packages.). There is also a batch file Fulld_2007.bat which supposedly builds them for you. Unfortunately it doesn’t work. There were multiple “The system cannot find the file specified.” errors. Of course it didn’t tell me which files were missing, so I added “Echo on” to the batch file to find out. It turned out to be the *110.bpl and *110.dcp files it could not find when it tried to copy them to the D11 subdirectory. Since it tries to copy them from the current directory which happened to be the Indy10\lib directory, that’s small wonder: By default bpl and dcp files are created in the Package and DCP output directories which are configured in the IDE (Tools -> Options -> Environment Options -> Delphi Options -> -> Library – Win32). These default to $(BDSCOMMONDIR)\Bpl and $(BDSCOMMONDIR)\dcp respectively. And since the developers didn’t specify a custom output directory for these projects that’s where the files went.
OK, rather than bothering with the batch file, I loaded the three package projects into the IDE, set a dcu output directory so the source doesn’t get cluttered with the dcus, and built them. That worked fine, problem solved… No, unfortunately not. When I tried the TeeChart compilation tool again, it still complained about the IndyProtocols package.
The reason is simple: The Indy Delphi 2007 package projects have a hard coded 110 suffix e.g. IndyProtocols110.dpk. The standard would have leave out that suffix e.g. IndyProtocols.dpk and configure a libsuffix (Project -> Options -> Description). This then creates IndyProtocols.dcp and IndyProtocols110.bpl. TeeChart is looking for IndyProtocols.dcp and can’t find it.
Easy to fix: Load the DclTeePro911.dpk package into the IDE, remove the requires entry for IndyProtocols and add IndyProtocols110 instead. After this change the package comiled fine in the IDE, problem solved… No, still not. The Teechart compilation tool still complained, now it didn’t find the IndyProtocols110 package. WTF? I just created it and I checked that it is where it is supposed to be: In the default DCP output directory.
Fortunately the tool also allows to output verbose messages which also writes the dcc32 calls into the log:
After stupidly looking at this monster for several minutes I noticed the -u”c:\delphi\2007\Lib\Indy10″ option. Could it be that it looks for the Indy packages in that directory only? (My Delphi 2007 is installed to “c:\delphi\2007” rather than c:\program files\codegear\[whatever].)
So I copied the Indy dcp files from $(BDSCOMMONDIR)\dcp to this directory and tried again. Diesmal funktioniert alles! (This time everything works.)
Did I mention that I hate “helpful compilation tools” ? I guess I can’t really blame Steema for this (hardcoding the dcp search path is kind of – ahem – not quite a good idea though). But those indy guys seem to be kind of sloppy. You don’t really hard code the package suffixes into the project file names! That was only necessary until Delphi 5.
But hey, they are volunteers and Indy is free, so I guess you get what you pay for. 😉
On the other hand: Guess who has hard coded project suffixes too? TeeChart does: 911 for Delphi 2007 which means TeeChart version 9 for Delphi 11. That’s not even the standard suffix which would have been 110.
Standards are great! Everyone should have one of his own!
— attributed to Bob Metcalfe, Co-inventor of Ethernet