Compiling Libraries for Strawberry Perl

I’ve recently been working on a project that will probably have to run on Windows in the end, which means I needed to use a Windows Perl.

ActiveState has recently changed their licensing and model so it’s very much driven into the cloud, and that’s not what I wanted at all.

Strawberry Perl to the rescue! It’s a nice package which includes a compiler so you can build modules and have everything you need to run Perl, all stuffed into c:\Strawberry. It’s a pretty well put together system. At least, until you need to compile a third party library for it. Then it gets harder.

Compiling Libraries

When you compile most Perl modules with Strawberry Perl, they work fine. Strawberry includes a couple of the most commonly wanted modules all ready to use, such as the Oracle DBD driver and GD. However, if you want to compile a module that requires you install a third-party library from outside the module install, you have some work to do. I finally figured out how to do it!

You must compile your library with the same compiler used to compile Perl, or the order of the arguments and order of the bytes in those arguments might not line up. You likely even need the same compiler flags. So you can’t just build any old DLL and stick it in the directory and have it work. You have to get the compiler used for Strawberry Perl to do it. Strawberry Perl includes a compiler, extracted from the version of MinGW used to build Strawberry Perl itself.

This was a bummer, because the library I was working with (ZeroMQ) compiles natively on Windows using MSVC. Building a Windows DLL of it is clearly documented and worked fine. Too bad Strawberry Perl can’t load that DLL, or I’d have been done.

The easiest way to do anything with MinGW is to use a package called MSYS2. MSYS2 provides a useful shell that gives a single-root environment so the Unix command-line tools aren’t confused, and then lets you install packages the community builds to add compilers, tools, etc. It’s a pretty slick system, and works well.

Problem: Strawberry Perl is compiled with an old version of MinGW, and a slightly strange, outdated version of GCC. Those packages aren’t available on the ‘net, and building them would be a lot of work. If you try and use a newer set of packages… well, you run in to the same binary library incompatibility that you do with MSVC, and get dlls that don’t work.

The solution was to install just MSYS2, and open an MSYS2 shell. Then adjust the PATH in that shell so that Strawberry Perl was before any of the other Unix-like tools. My path wound up looking like this:

/c/Windows/System32:/c/Windows:/c/strawberry/c/bin:/c/strawberry/c/x86_64-w64-mingw32/bin:/usr/local/bin:/usr/bin:/bin:/opt/bin

Then I used the MSYS2 tools (via pacman) to install git and autoconf/automake/autobuild, and any other various packages I wound up needing. Note that they installed in /usr/bin.

This gave me an environment where I had a Unix-like shell, and all the tools needed to build Unix programs, such as gcc, and the autoconf stuff, but where the compiler was the compiler from Strawberry Perl, strange old GCC that it was.

After that, I did a git clone of the zeromq sources, and compiled it. It was no harder than compiling any other software on a slightly hinky variant of Unix; the autoconf tools had been updated, and required changes to configure.ac, some of the files tried to include a header that isn’t there (which a simple #ifdef fixed), and there were a few compiler warnings that stopped the build. These are all things you experience building a library on any not-quite-mainstream Unix, and old habits came back to let me fix them.

Once the library built, I had to figure out where to put it. And where it was hiding in the first place. In the long run, I re-ran configure with PREFIX=/c/strawberry/c and then did a make and a make install. That copied almost all the files where they needed to be.

For some reason, part of the library loader requires a pkgconfig file. The zmq library built one, libzmq.pc, I just had to figure out to copy it to /c/strawberry/lib/pkgconfig. Once it was there, Strawberry Perl thought it had a libzmq and would try and load it.

Another part of the ZMQ Perl modules does some extra checking, and really wants the file it is loading to be lib<whatever>.dll. Problem: In this oldish version of MinGW, libraries are generated as msys-<whatever>.dll. I just copied the msys-zmq.dll to libzmq.dll so it was in both places and the code that checked for the path worked, and then loading the library also worked. This is the DLL files in /c/strawberry/c/bin, BTW, not the libraries in the lib path.

I was then able to install ZMQ::FFI with cpanm normally, and it worked. The sample app I was trying to compile also runs perfectly with this library, and I can subscribe to message queues from a Windows Perl now!

In short: MSYS2 with a carefully constructed environment will let you build libraries which your Strawberry Perl modules can then use.

Tags: , ,

2 Responses to “Compiling Libraries for Strawberry Perl”

  1. Zaki Mughal says:

    I’m here from IRC. MSYS2 is a great way to install things and I use it for complex dependencies on Windows such as Gtk+3.

    There are 2 more ways this can be done:

    1. Use the .dll from vcpkg:

    https://github.com/zeromq/perlzmq/blob/38b0882800d6931d5e0c770407831af5f444b5c5/.github/workflows/ci.yml#L74-L76

    This works because ZMQ has a C API which can be accessed via FFI despite vcpkg building via MSVC (the ABI for C works across compilers).

    1. Use Alien::ZMQ::latest which downloads and builds ZMQ with the Strawberry Perl toolchain:

    https://github.com/zeromq/perlzmq/blob/38b0882800d6931d5e0c770407831af5f444b5c5/.github/workflows/ci.yml#L81

    The latest release of ZMQ::FFI has support for loading from Alien::ZMQ::latest if it is installed.

    • Laufeyjarson says:

      Thanks for those updates! I hadn’t managed to get the MSVC DLL to work. It’s good that it should, and I’m glad to hear the compilers use a compatible ABI for DLL files. This is less true under Linux.

      I did try Alien::ZMQ, but it failed to compile zmq. I admit I didn’t dig further into those errors, and just started down the path of building my own.

      I posted this blog to make sure that there was more search engine fodder to help people find this technique of using MSYS2, as it would be applicable to many things, not just ZMQ. ZMQ is just the thing I was fighting this week. :) I really appreciate that you took the time to reply with more details about ZMQ, and provided those links!

Leave a Reply