-1

I try to link static library compiled using Visual C++ to my program compiled with GCC, and call someFunction()

On github there is source code of both library and program

https://github.com/Kaspek2480/DoubleCompilersProblem

[1/2] Building CXX object CMakeFiles/myprogram.dir/main.cpp.obj
[2/2] Linking CXX executable myprogram.exe
FAILED: myprogram.exe 
cmd.exe /C "cd . && C:\dev-tools\mingw64\bin\c++.exe -O3 -DNDEBUG  CMakeFiles/myprogram.dir/main.cpp.obj -o myprogram.exe -Wl,--out-implib,libmyprogram.dll.a -Wl,--major-image-version,0,--minor-image-version,0  -LC:/Users/Kaspek/CLionProjects/LinkerTest/VisualCppStaticLibrary/cmake-build-release-visual-studio  -lmylibrary  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
c:/dev-tools/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/myprogram.dir/main.cpp.obj:main.cpp:(.text.startup+0xe): undefined reference to `someFunction()'```

dumpbin:

Dump of file C:\Users\Kaspek\CLionProjects\LinkerTest\VisualCppStaticLibrary\cmake-build-release-visual-studio\mylibrary.lib

File Type: LIBRARY

   Linker Directives
   -----------------
   /DEFAULTLIB:MSVCRT
   /DEFAULTLIB:OLDNAMES
   /EXPORT:someFunction

  Summary

          60 .chks64
          DC .debug$S
          44 .drectve
          18 .pdata
          1C .rdata
          BA .text$mn
          20 .xdata

Library compiled using visual c++ is written in C so function name are not broken. Where is the problem with my code?

Kaspek
  • 159
  • 1
  • 11
  • Did you compare the name of the defined symbol in the library (I guess that's the dumpbin output) with the name of the undefined symbol in the main object file? – Peter - Reinstate Monica Jan 12 '23 at 04:02
  • What you mean by that? Name of function is the same – Kaspek Jan 12 '23 at 04:03
  • 1
    Compilers "mangle" or "decorate" even C symbols in various ways (e.g. prepend an underscore). But googling leads me to believe that it may just not work no matter what. Your best bet may be to create a DLL; DLLs are more compatible, by necessity. – Peter - Reinstate Monica Jan 12 '23 at 04:08
  • You are not using `extern "C"` so even compiling both components with the same family of compilers won't work. – n. m. could be an AI Jan 12 '23 at 06:00

1 Answers1

1

I could link, using gcc, a trivial object file compiled with Microsoft's cl command line compiler and a main file compiled with gcc. Both files were C files (which prompts cl to treat it as such); I think the name mangling schemes prevent linking of C++-derived object files from different sources, unless one restricts the interface to the C subset and declares those functions extern "C".

I used the respective 64 bit compiler in both cases. The 64 bit cl does not prepend the function name with an underscore (the 32 bit version does though). gcc does not prepend one either.

Some of the 27 or so options passed to the compiler when compiling with the IDE causes calls cl to produce calls into runtime and debug libraries; when called from the command line with a simple /c, it doesn't. When linking, ld warns about a " corrupt .drectve at end of def file"; but the program runs and produces an exit value:

$ cat f.c
int f(int i) { return 4 + i;  }
$ cat main.c
int f(int i);
int main(){ return f(2); }

$ "/c/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe" /c f.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30141 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

f.c
$ nm f.obj
0000000000000000 N .chks64
0000000000000000 N .debug$S
0000000000000000 i .drectve
0000000000000000 t .text$mn
00000000010475bd a @comp.id
0000000080010190 a @feat.00
0000000000000002 a @vol.md
0000000000000000 T f
$ gcc -c main.c
$ nm main.o
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 p .pdata
0000000000000000 r .rdata$zzz
0000000000000000 t .text
0000000000000000 r .xdata
                 U __main
                 U f
0000000000000000 T main
$ gcc -o main main.o f.obj
Warning: corrupt .drectve at end of def file
$ ./main
$ echo $?
6


When using the 32 bit Microsoft compiler, the name of the function symbol is _f:

$ "/c/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx86/x86/cl.exe" /c f.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30141 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

f.c
$ nm f.obj
00000000 N .chks64
00000000 N .debug$S
00000000 i .drectve
00000000 t .text$mn
010475bd a @comp.id
80010191 a @feat.00
00000002 a @vol.md
00000000 T _f

In that case, the declaration of f() in main.c would have to be changed to _f() so that the linker can find the function (and the gcc toolchain would need to be 32 bit as well, I suppose).

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62