Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2022-08

I am offering a $100 reward for linking static libraries

19 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Anthony Walter

I will pay $100 to the first person that can solve my problem of linking a compiled C static library to a Free Pascal program on Windows.

Recently I have been building many C libraries with GCC on Linux and linking them to Free Pascal. These include building C libraries such as "libxmp" for decoding mod/tracker music into PCM audio samples, "libchuimpmunk2d" for simulating 2D solid body physics, or "libsdl2" for cross platform controller input and haptic feedback among other things.

So far on Linux I am happily able to use a cmake/make/gcc toolchain to build these C libraries from source and easily statically link them to my Free Pascal programs.

Here is an example and abbreviated Pascal unit that links to a static build of Chimpmunk 2D:

unit Chimpmunk2D;
interface
type
  cpSpace = Pointer;
function cpSpaceNew: cpSpace; cdecl; external;
procedure cpSpaceDestroy(space: cpSpace); cdecl; external;
implementation
{$ifdef linux}
  {$linklib c}
  {$linklib m}
  {$linklib chipmunk-linux}
{$endif}
end.

Where libchipmunk-linux.a is my static library build on Linux from the Chipmunk2D C source code and is in the same folder as the source code as "Chimpmunk2D.pas". This works fine on Linux.

I am also able to use mingw32 gcc to compile this same C source into a static library for Windows using these two commands while inside the folder containing the Chipmunk2D sources:

x86_64-w64-mingw32-gcc-win32 -static -static-libgcc -std=gnu99 -ffast-math src/*.c -Iinclude -c
x86_64-w64-mingw32-ar rcs libchipmunk-win.a *.o
rm *.o

The problem then arises when I try to use {$linklib chipmunk-win}. No matter how I try to arrange the static dependencies I cannot resolve missing functions.

Many attempts were made compiling against other mingw32 static libraries for Windows.

{$ifdef windows}
  {$linklib mingw32}
  {$linklib mingwex}
  {$linklib kernel32}
  {$linklib msvcrt}
  {$linklib chipmunk-win}
{$endif}

I get many errors similar to these below:

Verbose: Compiling resource
C:\Development\Projects\physics\lib\x86_64-win64\Physics.obj
Verbose: Linking C:\Development\Pascal\Projects\physics\Physics.exe
Physics.lpr(30,1) Error: Undefined symbol: ___chkstk_ms
Physics.lpr(30,1) Error: Undefined symbol: __mingw_raise_matherr
Physics.lpr(30,1) Error: Undefined symbol: __imp_WideCharToMultiByte
Physics.lpr(30,1) Error: Undefined symbol: __imp_IsDBCSLeadByteEx
Physics.lpr(30,1) Error: Undefined symbol: __imp_MultiByteToWideChar
Physics.lpr(30,1) Verbose: There were 5 errors compiling module, stopping
Verbose: Compilation aborted

BUT

If I use mingw32-w64 on Linux to create a DLL instead, then m problems on Windows go away.

x86_64-w64-mingw32-gcc-win32 -static -shared -static-libgcc -std=gnu99 -ffast-math src/*.c -Iinclude -o libchipmunk-win.dll

However, I am not satisfied with an ever growing list of DLLs (I am at 6 currently) that must be deployed on Windows to build / run any project using my Pascal toolkit. I thought I could resolve this static linking problem on Windows at a later date, thus eliminating all the DLLs required to run projects using my toolkit on Windows, but every time I return to try another attempt I cannot resolve the external dependencies of something like "libchipmunk-win.a".

Therefore, if anyone has expertise in the area of linking static C libraries and can provide an example of how to link just one ("libchipmunk-win.a") on Windows either providing a different Windows C compiling method (MSVC as opposed to x86_64-w64-mingw32-gcc-win32) and the proper directives to correctly link a static library, I would gladly pay that person $100.

Additionally, I would write up a guide for other people if they have trouble while attempting to do the same thing.

If you have any tips or suggestions you can respond to this thread. If you have a solution and want to collect the reward, reply to my email address associated with this thread.

For reference, here are links to Windows static and dynamic libraries I;ve already built. Feel free to build new static libraries yourself, but just be sure to provide the list of tools and arguments you used if sending a solution.

https://files.codebot.org/sysrpl/applications/libchipmunk-win.a https://files.codebot.org/sysrpl/applications/libchipmunk-win.dll

Reply by email

Karoly Balogh
to Anthony Walter

Hi,

Anthony Walter wrote
I will pay $100 to the first person that can solve my problem of linking a compiled C static library to a Free Pascal program on Windows.

I'm not an expert for FPC on Windows by any meanns, but I think I've ran into the problems you're having.

Show quoted text 19 lines
{$ifdef windows}   {$linklib mingw32}   {$linklib mingwex}   {$linklib kernel32}   {$linklib msvcrt}   {$linklib chipmunk-win} {$endif} I get many errors similar to these below: Verbose: Compiling resource C:\Development\Projects\physics\lib\x86_64-win64\Physics.obj Verbose: Linking C:\Development\Pascal\Projects\physics\Physics.exe Physics.lpr(30,1) Error: Undefined symbol: ___chkstk_ms Physics.lpr(30,1) Error: Undefined symbol: __mingw_raise_matherr Physics.lpr(30,1) Error: Undefined symbol: __imp_WideCharToMultiByte Physics.lpr(30,1) Error: Undefined symbol: __imp_IsDBCSLeadByteEx Physics.lpr(30,1) Error: Undefined symbol: __imp_MultiByteToWideChar Physics.lpr(30,1) Verbose: There were 5 errors compiling module, stopping Verbose: Compilation aborted

Err, sorry for the trivial question, but are you using the internal or an external linker? From the error messages, I assume you use the internal one. On Windows FPC now defaults to its internal linker, which as known difficulties linking against some C libraries. Which is solvable, but probably not subject of a $100 bounty, but a bigger piece of work.

Wouldn't simply using GNU LD as an external linker (-Xe argument, IIRC) would solve this problem? Note that the external linker is known to produce larger executables, because it's not that good in removing unused pieces of code as the internal linker. But at least you could get something built.

Charlie

Reply by email

Anthony Walter
to Karoly Balogh

I never thought about the linker changes to FPC and am probably using the internal one. I know in the past I had been able to compile / link libraries created with MinGW GCC on Windows. Parts of the problem also include determining which other static dependencies to link IN ADDITION to the order of the linking. Yes, the order makes a big difference. Unfortunately, many years ago (around 10) I lost or overwrote the bits of code I was using for static linking on Windows (using the correct linklib commands).

I will try to recreate it again, using your suggestion of falling back to the external linker. If it works I'll send you a part of the reward. That offer also stands for anyone else that can offer helpful advice.

Reply by email

Marco van de Voort
to Anthony Walter
Anthony Walter wrote 13 lines
I never thought about the linker changes to FPC and am probably using the internal one. I know in the past I had been able to compile / link libraries created with MinGW GCC on Windows. Parts of the problem also include determining which other static dependencies to link IN ADDITION to the order of the linking. Yes, the order makes a big difference. Unfortunately, many years ago (around 10) I lost or overwrote the bits of code I was using for static linking on Windows (using the correct linklib commands). I will try to recreate it again, using your suggestion of falling back to the external linker. If it works I'll send you a part of the reward. That offer also stands for anyone else that can offer helpful advice.

Do the "inp" symbols go away if you put the kernel32 dependency first ?

Reply by email

Anthony Walter
to Marco van de Voort

Marco,

The missing symbols change depending on the order and which libraries are referenced. But I have tried all sorts of combinations and widdled them down, but I can never get it to compile. I think it might be a problem with the internal linker as Karoly suggested because sometimes I can almost get it working and then when it's about to work I get a mysterious internal linking error message.

Reply by email

Karoly Balogh
to Anthony Walter: I never thought about the linker changes to FPC and am probably using the internal one. I…

Hi,

Anthony Walter wrote
I know in the past I had been able to compile / link libraries created with MinGW GCC on Windows. Parts of the problem also include determining which other static dependencies to link IN ADDITION to the order of the linking. Yes, the order makes a big difference.

Indeed, that is true. But if the linking order worked on Linux, it should work on Windows too, I think.

Unfortunately, many years ago (around 10) I lost or overwrote the bits of code I was using for static linking on Windows (using the correct linklib commands).

Please note that 10 years ago FPC might not have had an internal linker, or it might not have been the default one on Windows. :) So this might be the missing bit of info why it worked back then.

I will try to recreate it again, using your suggestion of falling back to the external linker. If it works I'll send you a part of the reward.

Thanks, but it is not necessary. If it works, and you still would like to send money, donate it to any charity of your choice instead.

Charlie

Reply by email

Henry Vermaak
to Anthony Walter: I will pay $100 to the first person that can solve my problem of linking a compiled C…
Anthony Walter wrote
I am also able to use mingw32 gcc to compile this same C source into a static library for Windows using these two commands while inside the folder containing the Chipmunk2D sources: x86_64-w64-mingw32-gcc-win32 -static -static-libgcc -std=gnu99 -ffast-math src/*.c -Iinclude -c

-static and -static-libgcc are linking options, so they won't do anything here. You'll have to link libgcc in manually in your pascal source.

Show quoted text 19 lines
{$ifdef windows} {$linklib mingw32} {$linklib mingwex} {$linklib kernel32} {$linklib msvcrt} {$linklib chipmunk-win} {$endif} I get many errors similar to these below: Verbose: Compiling resource C:\Development\Projects\physics\lib\x86_64-win64\Physics.obj Verbose: Linking C:\Development\Pascal\Projects\physics\Physics.exe Physics.lpr(30,1) Error: Undefined symbol: ___chkstk_ms Physics.lpr(30,1) Error: Undefined symbol: __mingw_raise_matherr Physics.lpr(30,1) Error: Undefined symbol: __imp_WideCharToMultiByte Physics.lpr(30,1) Error: Undefined symbol: __imp_IsDBCSLeadByteEx Physics.lpr(30,1) Error: Undefined symbol: __imp_MultiByteToWideChar Physics.lpr(30,1) Verbose: There were 5 errors compiling module, stopping Verbose: Compilation aborted

The order of the linklib entries make a difference. I can get the undefined symbols down to nothing by using this order:

{$linklib libchipmunk.a}
{$linklib libmingwex.a}
{$linklib libmingw32.a}
{$linklib libgcc.a}
//{$linklib libmsvcrt.a}
{$linklib libmsvcr120.a}
{$linklib libkernel32.a}

But then I get an internal error (200603061). It may be down to the toolchain/libraries I used (recent msys2 x64), which would be a lot newer than fpc (I should really try to package it for msys2 when I have some free time).

Henry

Reply by email

Pierre Muller
to Henry Vermaak

Le 22/08/2022 à 18:18, Henry Vermaak via fpc-pascal a écrit :

Show quoted text 9 lines
On Sun, 21 Aug 2022 at 18:34, Anthony Walter via fpc-pascal wrote: > I am also able to use mingw32 gcc to compile this same C source into a static library for Windows using these two commands while inside the folder containing the Chipmunk2D sources: > > x86_64-w64-mingw32-gcc-win32 -static -static-libgcc -std=gnu99 -ffast-math src/*.c -Iinclude -c -static and -static-libgcc are linking options, so they won't do anything here. You'll have to link libgcc in manually in your pascal source.

You can always pass option to the external linker using '-k' option: Use -k-static (without space)
or -k-lc
or -k-L -k/DIR/

It can be good to use 'vx' option to see what is the command line really generated by the Free Pascal compiler when calling the external linker.

Pierre

Reply by email

Tony Whyman
to Anthony Walter: I will pay $100 to the first person that can solve my problem of linking a compiled C…

Once upon a time (late-1990s) I had some reasonable success (shareware) marketing a JPEG library for Delphi. This was a wrapper around the Independent JPEG Group's JPEG software which was written in 'C'. My JPEG library had thus to link to a 'C' library and both dynamic and static linking was offered. I too had the problem of too many C DLLs to link in.

The way it was solved for static libraries was to first link in the JPEG object files e.g.

{IDG JPEG objects modules to both compression and decompression}

{$L jdapimin.obj}
{$L jmemmgr.obj}
{$L jmemnobs.obj}
{$L jerror.obj}

{IDG JPEG modules for decompression}

{$L jdinput.obj}
{$L jdtrans.obj}
...

and then to identify the missing 'C' library functions (via linker errors). I then wrote Pascal equivalents (placed just before the $L statements. e.g.

{ Stubs for external C RTL functions referenced by JPEG OBJ files.}

function _malloc(size: Integer): Pointer; cdecl;
begin
   GetMem(Result, size);
end;
procedure _free(P: Pointer); cdecl;
begin
   FreeMem(P);
end;
procedure _memset(P: Pointer; B: Byte; count: Integer);cdecl;
begin
   FillChar(P^, count, B);
end;
procedure _memcpy(dest, source: Pointer; count: Integer);cdecl;
begin
   Move(source^, dest^, count);
end;
function __ftol: Integer;
var
   f: double;
begin
   asm
     lea    eax, f             //  BC++ passes floats on the FPU stack
     fstp  qword ptr [eax]     //  Delphi passes floats on the CPU stack
   end;
   Result := Trunc(f);
end;

As long as you can reduce the missing dependencies to a relatively small number, it should all work.

Regards

Tony Whyman

MWA

Anthony Walter wrote 119 lines
I will pay $100 to the first person that can solve my problem of linking a compiled C static library to a Free Pascal program on Windows. Recently I have been building many C libraries with GCC on Linux and linking them to Free Pascal. These include building C libraries such as "libxmp" for decoding mod/tracker music into PCM audio samples, "libchuimpmunk2d" for simulating 2D solid body physics, or "libsdl2" for cross platform controller input and haptic feedback among other things. So far on Linux I am happily able to use a cmake/make/gcc toolchain to build these C libraries from source and easily statically link them to my Free Pascal programs. Here is an example and abbreviated Pascal unit that links to a static build of Chimpmunk 2D: unit Chimpmunk2D; interface type   cpSpace = Pointer; function cpSpaceNew: cpSpace; cdecl; external; procedure cpSpaceDestroy(space: cpSpace); cdecl; external; implementation {$ifdef linux}   {$linklib c}   {$linklib m}   {$linklib chipmunk-linux} {$endif} end. Where libchipmunk-linux.a is my static library build on Linux from the Chipmunk2D C source code and is in the same folder as the source code as "Chimpmunk2D.pas". This works fine on Linux. I am also able to use mingw32 gcc to compile this same C source into a static library for Windows using these two commands while inside the folder containing the Chipmunk2D sources: x86_64-w64-mingw32-gcc-win32 -static -static-libgcc -std=gnu99 -ffast-math src/*.c -Iinclude -c x86_64-w64-mingw32-ar rcs libchipmunk-win.a *.o rm *.o The problem then arises when I try to use {$linklib chipmunk-win}. No matter how I try to arrange the static dependencies I cannot resolve missing functions. Many attempts were made compiling against other mingw32 static libraries for Windows. {$ifdef windows}   {$linklib mingw32}   {$linklib mingwex}   {$linklib kernel32}   {$linklib msvcrt}   {$linklib chipmunk-win} {$endif} I get many errors similar to these below: Verbose: Compiling resource C:\Development\Projects\physics\lib\x86_64-win64\Physics.obj Verbose: Linking C:\Development\Pascal\Projects\physics\Physics.exe Physics.lpr(30,1) Error: Undefined symbol: ___chkstk_ms Physics.lpr(30,1) Error: Undefined symbol: __mingw_raise_matherr Physics.lpr(30,1) Error: Undefined symbol: __imp_WideCharToMultiByte Physics.lpr(30,1) Error: Undefined symbol: __imp_IsDBCSLeadByteEx Physics.lpr(30,1) Error: Undefined symbol: __imp_MultiByteToWideChar Physics.lpr(30,1) Verbose: There were 5 errors compiling module, stopping Verbose: Compilation aborted BUT If I use mingw32-w64 on Linux to create a DLL instead, then m problems on Windows go away. x86_64-w64-mingw32-gcc-win32 -static -shared -static-libgcc -std=gnu99 -ffast-math src/*.c -Iinclude -o libchipmunk-win.dll However, I am not satisfied with an ever growing list of DLLs (I am at 6 currently) that must be deployed on Windows to build / run any project using my Pascal toolkit. I thought I could resolve this static linking problem on Windows at a later date, thus eliminating all the DLLs required to run projects using my toolkit on Windows, but every time I return to try another attempt I cannot resolve the external dependencies of something like "libchipmunk-win.a". Therefore, if anyone has expertise in the area of linking static C libraries and can provide an example of how to link just one ("libchipmunk-win.a") on Windows either providing a different Windows C compiling method (MSVC as opposed to x86_64-w64-mingw32-gcc-win32) and the proper directives to correctly link a static library, I would gladly pay that person $100. Additionally, I would write up a guide for other people if they have trouble while attempting to do the same thing. If you have any tips or suggestions you can respond to this thread. If you have a solution and want to collect the reward, reply to my email address associated with this thread. For reference, here are links to Windows static and dynamic libraries I;ve already built. Feel free to build new static libraries yourself, but just be sure to provide the list of tools and arguments you used if sending a solution. https://files.codebot.org/sysrpl/applications/libchipmunk-win.a https://files.codebot.org/sysrpl/applications/libchipmunk-win.dll _______________________________________________ fpc-pascal maillist https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Henry Vermaak
to Pierre Muller: Le 22/08/2022 à 18:18, Henry Vermaak via fpc-pascal a écrit : You can always pass…
Pierre Muller wrote 15 lines
Le 22/08/2022 à 18:18, Henry Vermaak via fpc-pascal a écrit : > On Sun, 21 Aug 2022 at 18:34, Anthony Walter via fpc-pascal > wrote: >> I am also able to use mingw32 gcc to compile this same C source into a static library for Windows using these two commands while inside the folder containing the Chipmunk2D sources: >> >> x86_64-w64-mingw32-gcc-win32 -static -static-libgcc -std=gnu99 -ffast-math src/*.c -Iinclude -c > > -static and -static-libgcc are linking options, so they won't do > anything here. You'll have to link libgcc in manually in your pascal > source. You can always pass option to the external linker using '-k' option: Use -k-static (without space) or -k-lc or -k-L -k/DIR/

Without -static-libgcc you'll still have to figure out which archives make up libgcc. ld won't do that for you.

Either way I think that unless fpc can be built with the same toolchain as the C libs you're linking with there may be too many things that can go wrong. E.g. I'm getting 0-bit reloc in dll errors with the external linker.

Henry

Reply by email

Anthony Walter
to Anthony Walter

I thought I should post an update.

I've written a utility to extract mingw64 static library exports into a searchable database. This allows me to search for possible missing functions (see the screenshot below)

https://cache.getlazarus.org/images/desktop/raylib-static.png

Again though I have run into a general linking error at which point nothing further can be done. I've tried using an older build of FPC / Lazarus, using an external linker, switching out the ld.exe in "bin/x86_64" with the mingw64 ld.exe, and even tried to use ld.exe manually which became a bigger mess (trying to resolve the dependencies of system.o).

Thank you again to anyone who has read through this thread.

Reply by email

Henry Vermaak
to Anthony Walter
Anthony Walter wrote
I've written a utility to extract mingw64 static library exports into a searchable database. This allows me to search for possible missing functions (see the screenshot below) https://cache.getlazarus.org/images/desktop/raylib-static.png

Note for anyone with msys2, you can make a file containing all defined external symbols like this:

# find /mingw64/lib -name "*.a" -exec nm -pogC --defined-only '{}' \;
2>/dev/null >> symbs.txt

Then search it with grep:

MINGW64 ~
# grep -w atexit symbs.txt
C:/msys64/mingw64/lib/libmsvcr120.a:libmsvcr120_defs01591.o:0000000000000000 T atexit
C:/msys64/mingw64/lib/libmsvcr120_app.a:libmsvcr120_app_defs01268.o:0000000000000000 T atexit
C:/msys64/mingw64/lib/libmsvcr120d.a:libmsvcr120d_defs01654.o:0000000000000000 T atexit

MINGW64 ~
# grep -w sincos symbs.txt
C:/msys64/mingw64/lib/libmingwex.a:lib64_libmingwex_a-cossin.o:0000000000000000 T sincos

Henry

Reply by email

Anthony Walter
to Henry Vermaak

Henry,

Thanks for posting that one liner. In my utility, I use nm to dump the contents once but then use a Pascal desktop app to do the grepping and display the output within a TMemo. Your way is faster to implement.

Reply by email

Anthony Walter
to Anthony Walter

I wanted everyone to know that after two attempts user Okoba on the Lazarus general forums was able to come up with a solution to fix this problem. I created a small demo that simulates objects dropped into an area with pegs rendered on a TForm TCanvas. The solution and demo are inside the project linked below:

Project:
https://files.codebot.org/sysrpl/applications/chipmunktest.7z

Screenshot:
https://cache.getlazarus.org/images/desktop/chipmunktest.png

Reply by email

Michael Van Canneyt
to Anthony Walter
Anthony Walter wrote 8 lines
I wanted everyone to know that after two attempts user Okoba on the Lazarus general forums was able to come up with a solution to fix this problem. I created a small demo that simulates objects dropped into an area with pegs rendered on a TForm TCanvas. The solution and demo are inside the project linked below: Project: https://files.codebot.org/sysrpl/applications/chipmunktest.7z

The file seems corrupt. I tried several programs, none managed to open it. Output of 7z:
Extracting archive: chipmunktest.7z
ERROR: chipmunktest.7z
Can not open the file as archive

Can you please post a zip file or recommend a linux/mac program that can open it ??

Michael.

Reply by email