Reputation: 8167
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
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
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