[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