0

The DLL was compiled on Linux, but the DLL that links with it needs to be compiled with MSVC. I could be flexible about the version of MinGW if necessary, but I must use this MSVC version. This is because I need to compile bindings for Python 3.5 or later.

The problem I'm facing is that at link time __imp___iob_func cannot be found as well as fprintf. If I try to declare those myself, I'm been told that they are already defined...

Below are MSVC commands and their output (formatted for readability)

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe
    /c
    /nologo
    /Ox
    /W3
    /GL
    /DNDEBUG
    /MD
    -Ipykubectl\lib
    -Ic:\bin\python\include
    -Ic:\bin\python\include
    "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE"
    "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.10240.0\ucrt"
    "-IC:\Program Files (x86)\Windows Kits\8.1\include\shared"
    "-IC:\Program Files (x86)\Windows Kits\8.1\include\um"
    "-IC:\Program Files (x86)\Windows Kits\8.1\include\winrt"
    /Tcpykubectl\lib\bindings.c
    /Fobuild\temp.win-amd64-3.6\Release\pykubectl\lib\bindings.obj
    bindings.c

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe
    /c
    /nologo
    /Ox
    /W3
    /GL
    /DNDEBUG
    /MD
    -Ipykubectl\lib
    -Ic:\bin\python\include
    -Ic:\bin\python\include
    "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE"
    "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.10240.0\ucrt"
    "-IC:\Program Files (x86)\Windows Kits\8.1\include\shared"
    "-IC:\Program Files (x86)\Windows Kits\8.1\include\um"
    "-IC:\Program Files (x86)\Windows Kits\8.1\include\winrt"
    /Tcpykubectl\wrapped.c
    /Fobuild\temp.win-amd64-3.6\Release\pykubectl\wrapped.obj
    wrapped.c

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe
    /nologo
    /INCREMENTAL:NO
    /LTCG
    /DLL
    /MANIFEST:EMBED,ID=2
    /MANIFESTUAC:NO
    /LIBPATH:pykubectl\lib
    /LIBPATH:c:\bin\python\Libs
    /LIBPATH:C:\Users\IEUser\.virtualenvs\pykubectl-yOsvavBP\libs
    /LIBPATH:C:\Users\IEUser\.virtualenvs\pykubectl-yOsvavBP\PCbuild\amd64
    "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64"
    "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.10240.0\ucrt\x64"
    "/LIBPATH:C:\Program Files (x86)\Windows Kits\8.1\lib\winv6.3\um\x64"
    gokubectl.lib winmm.lib ws2_32.lib msvcrt.lib
    /EXPORT:PyInit_wrapped
    build\temp.win-amd64-3.6\Release\pykubectl\lib\bindings.obj
    build\temp.win-amd64-3.6\Release\pykubectl\wrapped.obj
    /OUT:build\lib.win-amd64-3.6\pykubectl\wrapped.cp36-win_amd64.pyd
    /IMPLIB:build\temp.win-amd64-3.6\Release\pykubectl\lib\wrapped.cp36-win_amd64.lib

gokubectl.lib(go.o) : warning LNK4078: multiple '.text' sections found with different attributes (61600060)
wrapped.obj : warning LNK4197: export 'PyInit_wrapped' specified multiple times; using first specification
   Creating library build\temp.win-amd64-3.6\Release\pykubectl\lib\wrapped.cp36-win_amd64.lib and object build\temp.win-amd64-3.6\Release\pykubectl\lib\wrapped.cp36-win_amd64.exp
gokubectl.lib(000001.o) : error LNK2001: unresolved external symbol fprintf
gokubectl.lib(000001.o) : error LNK2001: unresolved external symbol __imp___iob_func
build\lib.win-amd64-3.6\pykubectl\wrapped.cp36-win_amd64.pyd : fatal error LNK1120: 2 unresolved externals
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\x86_amd64\\link.exe' failed with exit status 1120

And this is how the DLL that needs to be linked with is compiled:

x86_64-w64-mingw32-gcc-win32 -shared -pthread \
    -o pykubectl/lib/gokubectl.dll
    pykubectl/lib/win_gokubectl.c
    pykubectl/lib/libgokubectl.a
    -lwinmm
    -lntdll
    -lws2_32

The libgokubectl.a was obtained by compiling some Go code.

PS. There's a question linked here as a duplicate: It is indeed the same problem, but the solution it offers isn't a workable one. I wouldn't mind if the answer to my question be given in that thread rather than here. Just keep in mind that existing answer doesn't work / needs update to reflect the reality of particular versions of compilers involved.

wvxvw
  • 8,089
  • 10
  • 32
  • 61
  • Possible duplicate of [unresolved external symbol \_\_imp\_\_fprintf and \_\_imp\_\_\_\_iob\_func, SDL2](https://stackoverflow.com/questions/30412951/unresolved-external-symbol-imp-fprintf-and-imp-iob-func-sdl2) – RbMm Feb 01 '18 at 09:18
  • your problem in `gokubectl.lib` - it build with old *crt* version which incompatible with new *crt*. you need or rebuild `gokubectl.lib` with new crt too or use old crt version where `__imp___iob_func` and `fprintf` defined in *msvcrt.lib* – RbMm Feb 01 '18 at 09:33
  • @RbMm I saw that question. It is the same problem, but it doesn't offer a workable solution to it. I have no idea where I can get the new CRT lib for MinGW and whether it will work with it. Any ideas on this subject? – wvxvw Feb 01 '18 at 09:54
  • the `gokubectl.lib` build with **old** crt. you have 2 choice: **1.)** rebuild `gokubectl.lib` with **new** crt which you currently use in build (from `Microsoft Visual Studio 14.0`). **2.)** use **old** crt in build your project now. say from `Microsoft Visual Studio 8` – RbMm Feb 01 '18 at 10:02
  • @RbMm you don't understand... MinGW runs on Linux. I don't have any Visual Studio projects, and I cannot choose which DLLs will be actually loaded (they must be the ones on user's system, so whatever MSVC has on its library path should be enough). I'm questioning whether I can just put a different DLL (say, and I find a new CRT DLL) in my MinGW library path and hope that it works with all other old DLLs it has in there. Most likely it won't work that way. – wvxvw Feb 01 '18 at 10:05
  • no, this is you not understand. what dll ?! i nothing say about any dll. any dll not used in build process. i say about **lib** file. *msvcrt.lib*. you must understand src of error : **1** `gokubectl.lib` use **old** `stdio.h` where `#define stdout (&__iob_func()[1])` - as result created reference to `__imp___iob_func`. **2** this symbol search `link.exe` during build in libs - and not found it - in `Microsoft Visual Studio 14.0\VC\LIB\amd64\msvcrt.lib` - no this symbol. but in `Microsoft Visual Studio 8\VC\LIB\amd64\msvcrt.lib` - it exist. – RbMm Feb 01 '18 at 10:20
  • in `msvcrt.lib` from `14.0` which you use - exist `__acrt_iob_func` but not exist `__imp___iob_func`. and in `14.0\VC\INCLUDE` exist `#define _cpp_stdout (__acrt_iob_func(1))`. but in **old** crt (say 8.0) exist `#define stdout (&__iob_func()[1])` and exist `__imp___iob_func` in `8.0\VC\LIB\amd64\msvcrt.lib`. so you need or use **old**crt (header and libs) **for all** or use new crt (headers and libs) **for all** – RbMm Feb 01 '18 at 10:26
  • and now situation - your `gokubectl.lib` used **old** crt headers. but you try build it with **new** crt libs. or rebuild `gokubectl.lib` with new headers and libs. or use old crt for all project – RbMm Feb 01 '18 at 10:28
  • @RbMm ok. Let's sort this out. `gokubectl.lib` is a fiction. A file with such name doesn't exist. What exists is a file `gokubectl.a` which is what was compiled into `gokubectl.dll` later and which is what this program is linking against. When `gokubectl.dll` was compiled, MinGW pretended as if `gokubectl.lib` existed somewhere, but actually used `gokubectl.a`. `gokubectl.dll` was created by MinGW and linked against the libraries available to it. It had a reason to believe `fprintf` is defined in MS C runtime (it doesn't care about headers). (contd) – wvxvw Feb 01 '18 at 11:18
  • @RbMm I cannot use old headers because they reflect what was used in old library. The users of my program will not have the old library. I need to recompile `gokubectl.dll` in such a way that it links against new MS C runtime. What I need is a definitive answer to the question: "what should I put in `/usr/x86_64-w64-mingw32/lib` if at all, in order for MinGW to link with the correct version of MS C runtime?" (this directory contains files s.a. `crt1.o` and `CRT_fp10.o` etc.) – wvxvw Feb 01 '18 at 11:23
  • at first `gokubectl.lib` is not fiction - *gokubectl.lib(000001.o) : error LNK2001: unresolved external symbol __imp___iob_func*. so you need rebuild modules, which generate `gokubectl.lib` (*000001.c* ? look where you include `stdio.h` and use `stdin` or `stdout` or `stderr` and `fprint`) . and you must not confuse - headers, lib file and dll (which at all not related to build process). want use new headers - rebuild `gokubectl.lib` – RbMm Feb 01 '18 at 11:37
  • `fprintf` and `__iob_func` - no more exist in `14.0` crt. not exist and all. it in old crt only. you need somehow rebuild - `gokubectl` project with `14.0` crt – RbMm Feb 01 '18 at 11:40
  • @RbMm ok. At least we agree on something: yes, I need to rebuild `gokubectl`. How do I do this? Where do I get the appropriate MS C runtime library for MinGW? How do I call it to tell it that I need that runtime and not the one it wants by default? – wvxvw Feb 01 '18 at 11:42
  • this i already don't know. i never use `MinGW`. but why not use `CL.EXE` and `LINK.EXE` for build `gokubectl` ? why you part pf project build by `MinGW` and part of `MSVC` ? use xor `MinGW` xor `MSVC` for all – RbMm Feb 01 '18 at 11:45
  • @RbMm oh, we are getting somewhere now! :) Yes, I wish I could use `cl.exe` to build `gokubectl`, but I cannot. It is compiled in large part by Go compiler, which can only use MinGW as its backend. It cannot use `msvc`. – wvxvw Feb 01 '18 at 11:47
  • so try use `MinGW` for all. build `bindings.c` with `MinGW` too.. i dont know how you need fix this. but i explain you where error - `gokubectl` use symbols (depend on) very old crt. but you use it in build with new crt, where this symbols already not supported. this mismatch and create problems for you. i however at all never use crt at all. despite this i understand problem – RbMm Feb 01 '18 at 11:50
  • also possible solution - redefine `stdin` , `stdout` , `stderr`. to `#define stdin (__acrt_iob_func(0))` and so on. so replace `__iob_func` to `__acrt_iob_func`. look in `yvals.h` from `14.0\include` folder for `_cpp_stdin` definition and compare with `stdio.h` from old crt – RbMm Feb 01 '18 at 11:55
  • @RbMm well, that's the thing. I cannot use `MinGW` for all! The other part of the equation is a Python binary extension, and it *must* be compiled by `MSVC`. I understand the error. I just don't know what to do about it. – wvxvw Feb 01 '18 at 11:56
  • found in `gokubectl` where you use `stdin` or `stdout`. redefine it in your code or event in `stdio.h`. – RbMm Feb 01 '18 at 11:58
  • @RbMm that's a couple thousands files... transpiled from Go to C... that's a mission impossible task :) – wvxvw Feb 01 '18 at 12:01
  • but redefine it in **single** file - `stdio.h` – RbMm Feb 01 '18 at 12:01
  • @RbMm those files are generated while compiler runs... it's not really possible to spoof in an extra header :) – wvxvw Feb 01 '18 at 12:02
  • no, `stdio.h` - is file from CRT. it not generated – RbMm Feb 01 '18 at 12:04
  • @RbMm I have very little control over how `gokubectl` is written. I cannot just add some headers to it. It's a very complicated process requiring me to rewrite Go standard library. I cannot just put a `stdio.h` file next to it and hope that it will use it. Doesn't work that way. Using all sorts of `#define` won't help me either: the error happens at link time, after all defines have been processed. It's just that `gokubectl.a` (or, if you prefer `.lib` file is generated implying there is an external def, but it isn't there. – wvxvw Feb 01 '18 at 12:27
  • *Using all sorts of #define won't help me either:* - no - you absolute not understand. look at first `stdio.h` this is standard crt file. you not need add `stdio.h`. your `gokubectl` use it now. from where is `__iob_func` took ? exactly from `stdio.h` or `whar.h`. no any other files from crt use this symbol. here defined function `_CRTIMP FILE * __cdecl __iob_func(void);` and `#define stdout (&__iob_func()[1])`. as result when you use `stdin` or `stdout` or `stderr` - your code call function `__iob_func()`. but you can modify this standard crt files – RbMm Feb 01 '18 at 12:58
  • it not generated at compile time - it already exist. you not need **add** it to your code - your code already **use** it. – RbMm Feb 01 '18 at 12:58
  • you need change to `FILE* __cdecl __acrt_iob_func(unsigned const)` and #define stdout (&__acrt_iob_func()[1]), and stin, stderr as well. as result your code will be call `__acrt_iob_func()` function. so will be reference to symbol `__acrt_iob_func` instead `__iob_func`. and `__acrt_iob_func` already **exist** in `msvcrt.lib` from 14.0 folder – RbMm Feb 01 '18 at 13:02
  • so this affect link time error - need more deep understand compile and linking process – RbMm Feb 01 '18 at 13:03
  • @RbMm sorry, I didn't explain how `gokubectl` library is obtained. This is why you are confused: it is written in Go language (this is completely separate language from C, it doesn't use header files, doesn't use defines etc.) However, it can generate PE or ELF binaries. While doing so, it can also generate interface for calling from C code, i.e. header files and special `.data` and `.text` sections in libraries, so that C compiler knows how to link with it. The problem is that when generating this code, it assumes MS C runtime has `fprintf`, while, actually it doesn't. – wvxvw Feb 01 '18 at 13:05
  • I cannot add those defines you wrote because my code won't compile with them because the linker thinks I'm trying to redefine `fprintf`, but later it discovers that `fprintf` isn't actually in the library it thought it would be... and then it errors. – wvxvw Feb 01 '18 at 13:08
  • you try say that `__iob_func` is **generated** by some tools but not taken from CRT header file ?? – RbMm Feb 01 '18 at 13:08
  • @RbMm Yes, the reference to it is generated based on wrong assumption! – wvxvw Feb 01 '18 at 13:09
  • *because the linker thinks I'm trying to redefine fprintf, but later it discovers that fprintf* - this is 100% false. linker nothing think at all. he simply bind symbols as is. he nothing *discovers*. he can not know who and who define or redefine. this is all false – RbMm Feb 01 '18 at 13:11
  • i can not know exactly how you build. but i little doubt that you understand process. i doubt that `__iob_func` is generated. all what i can advice - search for (crt) files on comp, where you build, which containing `__iob_func`. are no any crt is used installed on this comp ? if exist crt - simply go to crt include folder and look for stdio.h and wchar.h or simply search files containing this symbol – RbMm Feb 01 '18 at 13:14
  • @RbMm the reference to it is generated, not the procedure itself. A library can declare that it has a function by writing a particular `.data` and `.text` sections in the binary. Once you link against this library, the linker will assume that this function does exist. And this is why if I try to declare those, my declaration will be invalid. Later on, when it is time to produce the final binary, linker will look for the actual implementation of the referenced procedure. In my case it will fail to find it. – wvxvw Feb 01 '18 at 19:30
  • This happens because MinGW *on Linux* has a different interface library than the actual CRT that I have on Windows. – wvxvw Feb 01 '18 at 19:31
  • anyway i doubt that `MinGW` have some embedded c-runtime instead use external headers. if runtime is embedded - when new version of runtime created - you can not use it. you need wait until *MinGW* will be updated. and at any time you can use only one, embedded c-runtime version. very strange how for me. can not say nothing exactly - i dont know *MinGW* but strange.. `__iob_func` this symbol anyway exist somewhere. you say that with *MinGW* you not use any external header crt files ? so this symbol is hard-coded in some bimary file ? simply interesting in what. you can do binary search – RbMm Feb 01 '18 at 21:13

0 Answers0