Out of Hanwell

May 1, 2006

Linking MSVC Libraries with MinGW Projects

Filed under: Development — Matthias Miller @ 11:47 am

Over the past several weeks, I’ve been reading Karl Fogel’s book Producing Open Source Software, having first heard about it from Ben Goodger. It’s full of practical advice for anybody’s who’s involved with open source software. But I’d like to focus on the advice about starting a project:

That sounds obvious, but many projects don’t bother to standardize their installation procedures until very late in the game, telling themselves they can do it any time: “We’ll sort all that stuff out when the code is closer to being ready.” What they don’t realize is that by putting off the boring work of finishing the build and installation procedures, they are actually making the code take longer to get ready—because they discourage developers who might otherwise have contributed to the code. Most insidiously, they don’t know they’re losing all those developers, because the process is an accumulation of non-events: someone visits a web site, downloads the software, tries to build it, fails, gives up and goes away. Who will ever know it happened, except the person themselves? No one working on the project will realize that someone’s interest and good will have been silently squandered.

I’ve been working with another developer on the software development tool that I recently mentioned: Compilation on the Mac was a breeze, and we had little concern about Linux. But things came to a grinding halt when we started on the Windows build.

The software is built with MinGW because it uses the Qt framework, and it also has dependencies on the Apache Portable Runtime. These libraries, like many other precompiled Windows development packages such as the MySQL client library, were compiled with Microsoft Visual C++ (MSVC). MSVC and MinGW, we discovered, use different naming conventions for stdcall functions. MSVC exports them as _name@ordinal, but MinGW exports them as name. As a result, the MinGW build failed with “undefined references” link errors when calling stdcall functions exported from the MSVC library.

The MinGW FAQ discusses this problem and offers a solution:

  1. Create a definition file using reimp (for lib files) or pexports (for dll files).
  2. Remove the underscore prefixes from the stdcall functions.
  3. Use dlltool to convert the MSVC library into a MinGW library with the new definition.

That didn’t work. We finally removed the ordinals from the function names, which caused it to compile. But the program wouldn’t run because it couldn’t find the linked functions in the DLL. Finally, after consulting the MSDN documentation for definition files, we changed the build instructions:

  1. Create a definition file using reimp.
  2. For each stdcall function (formatted as _name@ordinal) add a line name = _name@ordinal, allowing MinGW to map its stdcall naming convention to that of MSVC.
  3. Use dlltool to convert the MSVC library into a MinGW library with the new definition.

It worked! To compile the project you must simply:

  1. Download and install the Qt/Windows package, which includes MinGW.
  2. Download reimp and drop it into the MinGW/bin folder.
  3. Download the development packages for the third-party libraries and point an environment variable to that location.
  4. Build the project with the usual qmake/make commands.

We spent a lot of time on the Windows build system, and we’re much wiser now about libraries, export definition files, and the stdcall calling convention. More importantly, this project’s barrier to entry should be low enough to allow any interested developer to contribute.

Additional Reading:

Edit: Updated some URLs.

4 Comments »

  1. This is a good approach for exported functions, but how to fix the same problem with classes?

    Comment by Josef — March 7, 2008 @ 3:51 am

  2. Tips on vim for converting DEF files :

    :0,$s/_\(.*\)@.*/\r\1 = /g

    Comment by FloMo — April 20, 2009 @ 6:28 pm

  3. Hi,

    I didn’t understand it how you solved that problem.
    When I create the definition file, what commands I use exactly? I also didn’t understand how I add a new line for each stdcall function. How can I do this map between the functions?
    Please help me, beacause this is very important to me.

    Thanks.

    Comment by Thiago — July 30, 2009 @ 6:04 pm

  4. [...] [...]

    Pingback by USB1: Undefined reference to... — January 2, 2010 @ 11:07 pm


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.