Joachim W
Joachim W

Reputation: 8167

MinGW fails to prefix _impl_ to exported functions

MinGW shall compile a shared C library mylib that contains functions like

declspec(dllexport) int foo();

The library shall be used in a C++ application under Visual Studio.

Building the library (under CMake, with option GNUtoMS) yields three files, mylib.dll mylib.dll.a mylinb.lib. To inspect the latter,

dumpbin /HEADERS mylib.lib

prints one stance per exported function. The stance for the above function foo contains the line

Symbol name  : _foo

So, MinGW does not generate the prefix _imp_. Expectedly, linking the dependent application fails because Visual Studio cannot find _imp_foo.

How to get this right?

Upvotes: 0

Views: 653

Answers (2)

Joachim W
Joachim W

Reputation: 8167

Prefer the fork MinGW-w64 over the original MinGW

Instead of

mingw.exe from http://MinGW.org,

use

x86_64-w64-mingw32-gcc from http://www.msys2.org.

With this, dumpbin.exe finds not

Symbol name  : _foo

but

Symbol name  : foo

and Visual Studio succeeds in linking libmylib.lib.

For background on mingw vs msys2/mingw-w64, see Wikipedia: "In ... 2013 a new project was started, MSYS2 together with 32-bit and 64-bit MinGW packages. This project was created to keep track with newer advances of the Cygwin project ... MSYS2 is an independent rewrite of MSYS, based on modern Cygwin (POSIX compatibility layer) and MinGW-w64 with the aim of better interoperability with native Windows software."

MinGW is a registered trademark licensed to the MinGW project. The names of the compilers in the MSYS2 project are somewhat confusing: Occasionally they are called MinGW for short; the executables have mingw32 in their name even when dedicated to 64 bits; the official name seems to be MinGW-w64.

Thanks to @jacob whose use of MinGW-w64 in his answer provided the decisive cue.

Upvotes: 0

jacob
jacob

Reputation: 1630

This is what works for me. I compiled this source code main.c

__declspec(dllexport) int foo()
{
    return 42;
}

with this CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(mylib)

add_library(mylib SHARED "main.c")

using this script build.bat

set "PATH=C:\msys64\mingw64\bin;%PATH%"

cmake ^
    -G "MinGW Makefiles" ^
    -D CMAKE_GNUtoMS=ON ^
    -D CMAKE_GNUtoMS_VCVARS="C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvars64.bat" ^
    -D CMAKE_C_COMPILER="x86_64-w64-mingw32-gcc.exe" ^
    -D CMAKE_CXX_COMPILER="x86_64-w64-mingw32-g++.exe" ^
    .

cmake --build .

As you can see, I used MinGW-w64 from MSYS2 rather than MinGW, but this should not make any difference. The output was:

-- The C compiler identification is GNU 9.2.0
-- The CXX compiler identification is GNU 9.2.0
-- Check for working C compiler: C:/msys64/mingw64/bin/x86_64-w64-mingw32-gcc.exe
-- Check for working C compiler: C:/msys64/mingw64/bin/x86_64-w64-mingw32-gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/x86_64-w64-mingw32-g++.exe
-- Check for working CXX compiler: C:/msys64/mingw64/bin/x86_64-w64-mingw32-g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/jacob/Documents/prog/stackoverflow/GNUtoMS

C:\Users\jacob\Documents\prog\stackoverflow\GNUtoMS>cmake --build .
Scanning dependencies of target mylib
[ 50%] Building C object CMakeFiles/mylib.dir/main.c.obj
[100%] Linking C shared library libmylib.dll
**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.4.3
** Copyright (c) 2019 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
Microsoft (R) Library Manager Version 14.24.28315.0
Copyright (C) Microsoft Corporation.  All rights reserved.

   Creating library libmylib.lib and object libmylib.exp
[100%] Built target mylib

Then I created a program prog.c

#include <stdio.h>

__declspec(dllimport) int foo();

int main (void)
{
    printf("%d\n", foo());
    return 0;
}

and compiled it using

cl.exe prog.c libmylib.lib -o prog.exe

Linking succeeded, and the resulting program printed 42. The symbol displayed by dumpbin.exe was

  Symbol name  : foo

No underscores and imps whatsoever; still, it just worked.

Upvotes: 2

Related Questions