[fpc-pascal] Understanding error messages in static linking

Thomas Kurz fpc.2021 at t-net.ruhr
Tue Aug 20 18:16:05 CEST 2024


Hello,

I am trying to statically link OpenSSL. I'm using the Win64 full installer from https://slproweb.com/products/Win32OpenSSL.html which includes precopmiled static libraries which were compiled with VC using the /MT, /MD, /MTd and /MDd switches. This obviously stands for:

/MD    Creates a multithreaded DLL using MSVCRT.lib.
/MDd   Creates a debug multithreaded DLL using MSVCRTD.lib.
/MT    Creates a multithreaded executable file using LIBCMT.lib.
/MTd   Creates a debug multithreaded executable file using LIBCMTD.lib.

So using the MD version seems to be most logical to me. FPC is 3.3/trunk, but not the most recent one (about 2 months old).

Trial 1: 

program project1;
{$linklib z:/libcrypto_static.lib}
begin
end.

Result: `Error: Invalid DLL z:\libcrypto_static.lib, Dos Header invalid`

The message reads like a DLL has to be specified.


Trial 2:

program project1;
{$linklib z:/libcrypto-3-x64.dll}
begin
end.

Result: `project1.lpr(6,1) Error: Import library not found for z:\libcrypto-3-x64`

Strange. Because the file is there...


Trial 3:

I'm now using `objconv` from https://github.com/gitGNU/objconv/blob/master/objconv-x64.exe

Conversion: `objconv-x64.exe -fcoff libcrypto_static.lib libcrypto_static.a` (interestingly, using `-fCOFF` as printed on the help page doesn't work)
Result: `Input library: libcrypto_static.lib, Format: COFF64, Output: libcrypto_static.a, Format: COFF64`

So it's converting from COFF to COFF. Okay.

Now we have a new minimal example:

program project1;
{$linklib z:/libcrypto_static.a}
begin
end.

At least it gives no errors.

But I haven't used anything from libcrypto yet, so let's go to...


Trial 4:

program project1;
uses CTypes;
{$linklib z:/libcrypto_static.a}
function OPENSSL_init_crypto(opt: cuint64; const settings: pointer): CInt; cdecl; external;
begin
  OPENSSL_init_crypto (0, nil);  // parameters aren't important right now
end.

Result: `project1.lpr(7,1) Error: Invalid ar member lfn name index in z:\libcrypto_static.a`

Googling this error gives 1 result: It is the source code line of this error message, so it doesn't seem to be a very common problem :)


Trial 5:

Let's try changing the `external` declaration. From the FPC manual:

> external ’lname’;
> Then this tells the compiler that the function resides in library “lname”. The compiler will then automatically link this library to the program. 

New approach:

program project1;
uses CTypes;
function OPENSSL_init_crypto(opt: cuint64; const settings: pointer): CInt; cdecl; external 'libcrypto_static';
begin
  OPENSSL_init_crypto (0, nil);
end.

This compiles, but gives an error when executing: "...because libcrypto_static.dll was not found". One can now use `libcrypto-3-x64` instead of `libcrypto_static`, but then I have to redistribute the libcrypto DLL, which is just what I'm trying to avoid.

Next idea:


Trial 6:

Use `objconv-x64.exe -fcoff -lx libcrypto_static.lib` to split the library into separate object files.

Then I get:

Member crypto\libcrypto-lib-init.obj - COFF-64
   OPENSSL_cleanup
   OPENSSL_init_crypto
   OPENSSL_atexit
   ??_C at _0O@BNMMJHOI at crypto?2init?4c@
   ??_C at _0BE@PHOHEBBN at OPENSSL_init_crypto@

Let's use this one:

program project1;
uses CTypes;
{$L libcrypto-lib-init.obj}
function OPENSSL_init_crypto(opt: cuint64; const settings: pointer): CInt; cdecl; external;
begin
  OPENSSL_init_crypto (0, nil);
end.

Result: `project1.lpr(7,1) Error: Associative or exact match COMDAT sections are not yet supported (symbol: .debug$S)`


And this is the point where I'm completely stuck. Is there anything I can try or is it just impossible to create an .exe which doesn't depend need the libcrypto DLL?

Please, I don't want to discuss the pros and cons about static linking. There are no high-security demands I have to satisfy. I'd just like to understand what I'm doing wrong.

Kind regards,
Thomas



More information about the fpc-pascal mailing list