C: Correct Way to Statically / Dynamically Link with MinGW-w64
Asked Answered
G

1

16

Intuitively:

  • MinGW-w64 is a Windows port of the GNU compiler tools (GCC, etc.).
  • Pre-compiled binaries for Windows are .dll (dynamic linking) / .lib (static linking).
  • However, MinGW-w64 uses the GNU compiler tools, it would follow that .so / .a binaries are required.

What I've Found:

Unfortunately, I can't find explicit documentation from MinGW & MinGW-w64 that says what's right and what's wrong when dynamically/statically linking libraries.

In my experience, I have always been able to dynamically link to .dlls. Once, I was able to statically link to a .lib (using the -static flag).

Question:

Are .dll / .a binaries appropriate to dynamically and statically link libraries when compiling with the MinGW-w64 GCC tool-chain? In other words, dynamic libraries generated for MSVC and static libraries generated for GCC?

Ganymede answered 9/4, 2017 at 20:31 Comment(10)
That's surprising that it worked, given this mailing list question. Also, for GCC on MinGW targets, you have .a for archive libraries (like Linux does) and .dll for dynamic libraries (like Windows does).Amundsen
Source for a/dll files and how the linker uses them (use your browser's Find Text feature to find direct linking)Amundsen
Despite the name, MinGW-w64 compiles for 32-bit by default. (You can choose 64-bit version of it manually in the installer.) From my experience, MinGW-w64 works more or less like plain MinGW.Ihram
Because in the installer there is a combobox to choose between i686 and x86_64, and the first one is chosen by default.Ihram
I don't have a source stating that things work the same unfortunately, but I doubt there was ever a reason to change it, and that source I provided was for Cygwin. Sorting through the source code of GCC revealed the file libgcc/config/i386/t-slibgcc-cygming containing the line SHLIB_EXT = .dll. The cygming files are common to MinGW, MinGW-w64, and both 32-bit and 64-bit versions of Cygwin, so you at least know that .so isn't a possibility.Amundsen
@ChronoKitsune Do you know if the cygming file is something I can find on my installation of MinGW-w64, to confirm that this is the case for my system? Or is this a piece of source code that isn't packaged with the MinGW suite?Ganymede
It is a file in the GCC source code. Click the link to view the file, comments included. A simple way to solve the .dll/.a issue on your own is to search your MinGW-w64 install directory (e.g. C:\mingw) for files with the .a or .dll file extensions and to search for .so, which shouldn't appear. You can also search for .lib if you wish, but that won't appear either.Amundsen
@ChronoKitsune That means that MinGW/MinGW-w64/Cywgin require .dll for dynamic linking and .a for static linking. If that's the case, you've answered the question. However, it's still very weird that they follow 1) an MSVC library generation convention for dynamically linked binaries and 2) a GCC convention for statically linked binaries. Do you think that the extension is arbitrary (i.e., build libraries with MSVC, GCC, MinGW, whatever - sometimes, they'll all link just fine with MinGW?)Ganymede
The extension for dynamic libraries comes from Windows. GCC can generate DLLs just like any other compiler that allows you to create shared libs on Windows. The extension for static libraries comes from the ar archive program included with binutils. You can use ar -t libxxx.a for example to list the object files contained within any static library. You can also create a DLL file with a MinGW toolchain and generate a .def file for the DLL using gendef, allowing MSVC tools to create an import library in the native MSVC .lib format.Amundsen
... However, the GNU binutils .a and MSVC .lib static library formats are incompatible; I've never tried mixing the .obj files output by MSVC and the .o files output by gcc, so it might be possible that you could extract the .o files from a .a file and add those to the command line for MSVC. C++ code might have a problem due to the incompatible ABI, but C code shouldn't.Amundsen
G
17

The Answer:

MinGW / MinGW-w64's port of GCC's linker ld can:

  • directly link to .dlls for dynamic linking
  • indirectly link to .dll.as for dynamic linking (using import library at compilation)
  • link to .as for static linking.

Why does MinGW / MinGW-w64's port of the GCC linker look for .dll?

In short, the best answer is because that's .dlls are Microsoft's answer for shared objects on their 32-bit and 64-bit operating systems. On Windows, MinGW / MinGW-w64's port uses Microsoft C runtime (msvcrt.dll) [1], so it obeys Windows OS linker rules.

Dynamic-link library (or DLL) is Microsoft's implementation of the shared library concept in the Microsoft Windows and OS/2 operating systems. -- From Wikipedia

So, to dynamically link libraries you'll use the file extension:

  1. .so for shared libraries on Linux because that's what the GCC binutils' linker searches for,
  2. or .dll for shared libraries on Windows because that's what the MinGW / MinGW-w64 port of GCC binutils' linker searches for.

The extension used by the MinGW port of GCC for shared library objects is explicitly listed in a cygming file in the source code. As @ChronoKitsune commented, specifically: SHLIB_EXT = .dll in libgcc/config/i386/t-slibgcc-cygming. The cygming files (for Cygwin and MinGW) are common to MinGW, MinGW-w64, and both 32-bit and 64-bit versions of Cygwin. Therefore, this is true for all ports of the GCC binutils to Windows.

Why does the MinGW / MinGW-w64 linker handle .lib then?

In principle, the GCC binutils' linker won't recognize a .lib as a static library. However, it is possible that the linker is smart enough to link against the .dll that a .lib imports (in the case that the .lib is actually an import library). For instance, in the case that a library has dependencies which are linked dynamically that library will be linked dynamically (and flags to "force" static linking will be ignored).

In such cases, I'd imagine that the linker would not throw any errors and it would appear as though the .lib was actually linked successfully.

How do import libraries work? (freebie)

On Windows, a .lib can be one of two libraries:

  1. An import library generated by the compiler from a .dll with all needed definitions for symbol resolution during compilation (however, function implementations are left out) [2]
    1. If you attempt to generate import libraries for a xxxx.dll with MinGW / MinGW-w64's port of GCC binutils, it will produce a libxxxx.dll.a. The extension file extension is useful for distinguishing an import library from a fully-defined static library. When compiling with MSVC, this distinction isn't apparent in the extension
  2. A fully-defined static library

.libs serve a dual purpose because, as @ChronoKitsune commented, the MSVC linker does not directly link against .dlls. Instead, an import library is necessary to resolve symbol definitions at compilation, so that the .dll is not loaded until run-time:

An import library (.LIB files) to link with. (The linker creates the import library when the DLL is built.) -- VS 2015 Documentation

Why does MinGW/ MinGW-w64's port of the GCC linker look for .a?

This is simple - the port make use of the ar archiving utility that is used on *-nix systems, as @ChronoKitsune commented:

The extension for static libraries comes from the ar (archive) program included with binutils. You can use ar -t libxxx.a to list the object files contained within any static library.

This is similar to the lib command for MSVC, lib /list foo.lib This command will return a list of .obj files inside if the .lib is a static library.

Ganymede answered 11/4, 2017 at 13:46 Comment(1)
Is there a way to force mingw-w64 to force a static link against a .lib? The -static doesn't seem to work, it's still linking it dynamicallyButterfield

© 2022 - 2024 — McMap. All rights reserved.