2
votes

I've used the builtin RegularExpressions unit from Delphi XE2 for some time until I figured out that its object files (.obj) depend on msvcrt.dll, wrapped by System.Win.Crtl. It makes me a little bit sad because I've always been proud of the way Delphi can build executables with no runtime dependencies, unlike VB or VC++ (by default).

I tried to compile/link the C .obj files statically so they wouldn't depend on msvcrt.dll but my C/C++ skills are limited. I tried to do it in Visual Studio Express with no success. Is there a way to accomplish that for both Win32 and Win64 platforms?

The version of PerlRegEx I'm using is 7.9 2009-04-11, available here: http://www.regular-expressions.info/download/TPerlRegEx.zip. .obj files are in the pcre folder.

The C sources for the .obj files are here: http://ufpr.dl.sourceforge.net/project/pcre/pcre/7.9/pcre-7.9.zip

Any suggestions would be appreciated.


I was looking only at the import table of the exe. Didn't see that msvcrt.dll gets loaded during execution even when I don't use RegularExpressions unit. I've seen some errors related to it in the past and misassociated with the fact that RegularExpressions causes msvcrt.dll to be added to the imports. Sorry for wasting your time.

1
I don't understand. A plain vanilla Delphi VCL forms app loads msvcrt.dll. This is a system component. You are happy to link against user32.dll? And most C++ toolchains that I know of on Windows can produce executables that don't have non-system dependencies.David Heffernan
What Windows exe's don't use MS c-runtime?user557597
Actually many of them. From delphi 7 to 2010 you can build applications that don't use msvcrt.dll at all. And although it's a system component, I've seen several client machines where it was not installed by default.karliwson
@Kekas Not recently. It's been a system component since Windows 2000. I've been shipping programs relying on msvcrt for years and years and have never once had a missing dependency.David Heffernan
Delphi applications since version 1 have always had dependencies on system libraries (user, gdi, kernel). MSVCRT.DLL is a system library. It's part of the OS, just like what now is user32.DLL. You have nothing to be sad about, because nothing has changed.Ken White

1 Answers

0
votes

This is a pretty much pointless task. A plain vanilla VCL forms application will load the system msvcrt library. Yes, this is a system library. It is distributed as a standard OS library. All systems have it. In that regard it is no different from user32, advapi and so on.

So, by removing the dependency that the regex code has on msvcrt will not make your program have any fewer dependencies. What's more, there's nothing to be afraid of in taking a dependency on a system library.

You might ask why a Delphi application has a dependency on msvcrt. It comes about because of this:

  1. The WideString type is a loose wrapper around the system BSTR type.
  2. The implementation of BSTR is provided by the oleaut32 library.
  3. A plain vanilla Delphi program, that uses no units at all, has a load-time dependency on oleaut32 in order to provide, for instance, SysFreeString.
  4. The oleaut32 library in turn has a dependency on msvcrt.

So, not matter what you do, you will not be able to remove the dependency on msvcrt.


However, to answer your question, because I enjoy answering questions, especially ones on linking compiled objects, here is what you need to do:

  1. Take a copy of System.RegularExpressionsAPI.pas and place it in your project's source folder. Add it to the project. This is now the unit that the rest of the regular expression library stands on top of.
  2. At the top of the implementation section, remove the reference to System.Win.Crtl.
  3. Compile your project.

You will find that the code will not compile, and gives the following errors:

E2065 Unsatisfied forward or external declaration: '_strncmp'
E2065 Unsatisfied forward or external declaration: '_memmove'
E2065 Unsatisfied forward or external declaration: '_memset'
E2065 Unsatisfied forward or external declaration: '_memcpy'
E2065 Unsatisfied forward or external declaration: '_memcmp'
E2065 Unsatisfied forward or external declaration: '_strlen'
E2065 Unsatisfied forward or external declaration: '__ltolower'
E2065 Unsatisfied forward or external declaration: '_islower'
E2065 Unsatisfied forward or external declaration: '__ltoupper'
E2065 Unsatisfied forward or external declaration: '_isdigit'
E2065 Unsatisfied forward or external declaration: '_isupper'
E2065 Unsatisfied forward or external declaration: '_isalnum'
E2065 Unsatisfied forward or external declaration: '_isspace'
E2065 Unsatisfied forward or external declaration: '_isxdigit'
E2065 Unsatisfied forward or external declaration: '_isgraph'
E2065 Unsatisfied forward or external declaration: '_isprint'
E2065 Unsatisfied forward or external declaration: '_ispunct'
E2065 Unsatisfied forward or external declaration: '_iscntrl'
E2065 Unsatisfied forward or external declaration: '_isalpha'
E2065 Unsatisfied forward or external declaration: '_strchr'

In order for the compiler to compile this unit, it must be able to resolve these symbols in the modified System.RegularExpressionsAPI.pas unit. Using System.Win.Crtl is what makes that happen in the plain RTL. If you want to avoid linking System.Win.Crtl then you need to provide implementations. For instance, here is _strlen.

function _strlen(P: PAnsiChar): size_t; cdecl;
begin
  Result := System.SysUtils.StrLen(P);
end;

Add that to the modified System.RegularExpressionsAPI.pas unit and you've resolved the dependency. You now just need to keep doing that for all the others. This is regulation, link to compiled object fare.

But, as I have tried to make clear, I would not recommend doing this. You are creating work for yourself that will bring no discernible gain. You'll end up with even more code in your program than before. And there's every chance that you'll make mistakes implementing these C runtime functions. You'll invest a whole heap of time, and end up with a program that is worse than what you have now.