.lib file doesn't get linked

Hi everyone, i’ve got a problem with precompiled .lib files.
My Project is structured like this:

|
|_ lib
| |_ Gazebo
| | |_ transport
| | |_ Node.cpp
| |
| |_ Built
| |_ gazebo
| |_ gazebo_transport.lib
|
|_ src
|_ main.cpp

My platformio.ini looks like this:

[env:native]
platform = native
build_flags =
${common.build_flags}
-std=c++17
-DTARGET_NATIVE
-I./include
;Gazebo lib paths
-L./lib/Built/gazebo
;Gazebo libs
-lgazebo_transport

When I’m building the project, it’s compiling fine, but when it’s linking I get errors like:

.pio\build\native\libeb9\libHALNative.a(ButtonC.o):ButtonC.cpp:(.text+0x21a): undefined reference to `gazebo::transport::Node::Node()’

So it looks like the lib-file isn’t linked to the header file. Am I missing something here or are there other ways to include or link a .lib-file?

You’re using a .lib file with GCC, not .a? Does this work standalone? I have strong concerns….

You should try and acquire the library in .a format, not compiled with Visual Studio but with MinGW, or use a conversion tool like https://code.google.com/archive/p/lib2a/downloads (see usage manual).

The .lib-files work standalone, I got them from a different source and didn’t compile them myself. They are used in an .exe that came with them aswell and there everything works fine.
I’ll try converting them to .a files and see if that works, thank you.

So I used the tool and generated the libgazebo_transport.a. I put it in the same place where the gazebo_transport.lib file was before and when I try to link them I get the following output:

C:/Program Files (x86)/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible lib\Built\gazebo\libgazebo_transport.a when searching for -lgazebo_transport
C:/Program Files (x86)/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible lib\Built\gazebo/libgazebo_transport.a when searching for -lgazebo_transport
C:/Program Files (x86)/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lgazebo_transport
collect2.exe: error: ld returned 1 exit status

Can you upload the library file(s) and the project file / code somewhere for inspection?

Here is a link for downloading the project.

You can change the gazebo_transport.lib in the /lib folder with the libgazebo_transport.a file in the /lib/Built/Gazebo folder to test both variants.

And you need to build for the native environment in order to produce the error.

Okay that project is rather huge. I’ve stripped the problem to first testing whether PlatformIO + GCC are able to link with VisualStudio-built libraries at all. So I created a new static library in VisualStudio with very simple code

#ifndef VSSTATIC_LIB_H
#define VSSTATIC_LIB_H

class VSStaticLibClass {
public:
	void TestFunc();
};

#endif //VSSTATIC_LIB_H
#include "VSStaticLib.h"
#include <stdio.h>

void VSStaticLibClass::TestFunc() {
	printf("VSStaticLibClass::TestFunc() was reached :)\n");
}

and built it in release mode to get a VSStaticLib.lib.

Created a new blank PlatformIO project, created the folder lib/VSStaticLibTest (important to not call it VSStaticLib because then there is a name conflict with the library file libVSStaticLib.a file that PlatformIO auto-generates, even when only headers and no implementation code is present, unless lib_archive=no), put the VSStaticLib.h and VSStaticLib.lib file inside it and wrote my platformio.ini is

[env:native]
platform = native
build_flags = 
	-L lib/VSStaticLibTest
	-lVSStaticLib

with code

#include <stdio.h>
#include <VSStaticLib.h>

int main() {
  printf("Hello, world!\n");
  
  VSStaticLibClass test;
  test.TestFunc();
  
  return 0;
}

and building it gives…

C:\Users\Max\Downloads\VS_PIO>pio run
Processing native (platform: native)
------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 1 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <VSStaticLibTest>
Building in release mode
Compiling .pio\build\native\src\main.o
Archiving .pio\build\native\libc40\libVSStaticLibTest.a
Indexing .pio\build\native\libc40\libVSStaticLibTest.a
Linking .pio\build\native\program.exe
c:/program files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: .pio\build\native\src\main.o:main.cpp:(.text+0x21): undefined reference to `VSStaticLibClass::TestFunc()'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\native\program.exe] Error 1
=================[FAILED] Took 1.11 seconds =================[

This goes to show that there is a general problem indeed with mixing MinGW and VS libraries in the most simple example, as I have previously suspected. With this simple case not working, it doesn’t yet make sense to try this in the giga-size project.

You can also see from e.g. other projects, such as libSDL, that they have separate VC (Visual C in this case) and MinGW development libraries for Windows.

grafik

I’ll investage on whether Lib2A helps in this simple case, whether other conversion tools are available or whether I can find more info on why GCC can’t handle VS libs. I’ve already found this that states a VisualSudio compile setting may influence it.

On another note it might be possible to recompile the Gazebo libraries either on Windows with a MinGW toolchain instead of VisualStudio, however even they say that

At this moment, compilation has been tested on Windows 8.1 and 10, supported when using Visual Studio 2017. Patches for other versions are welcome.

may not be possible. However, another possible trick is compiling it on Linux using this, but exchanging the compiler from GCC to x86_64-w64-mingw32-gcc, aka cross-compiling from Linux for Windows (MinGW).

But, one thing at a time.

EDIT: Another thought I just had that the problem could lie with C++ mangling names – The MSVC compiler encodes class names and functions differently than GCC, see https://demangler.com/, so maybe GCC can’t find the function because it expects a different name.

1 Like

Yeah even functions with C linkage won’t work with MinGW. The conversion tools like gendef and reimp just fail silently on my .dll and .lib file, no matter if compiled with release or debug mode. Even with the newest version of reimp (lib2a has a version from 2004…), no luck. The closest I could get for these tools to output something is with the lib2a version of reimp, reimp -s <lib file> actually prints the used symbols for a file compiled in the debug profile, but does not generate a .def file when being told so. I’m writing off the conversion tool route as non-working for now.

1 Like

Sadly the Windows build won’t even work for me, after building ign-cmake the expected output folder does not appear. Even if the build went through, I’d be getting the x64 VisualC++ libraries again (which are especially problematic). All the dependencies are also already hardcoded to VisualC (e.g. zziplib-0.13.62-vc12-x64-release-debug.zip etc.) so I don’t think reworking the build system on native Windows from VisualStudio to MinGW is easily doable. Needs major work with all the dependencies also needing to found in MinGW form (or being compiled from source). I haven’t tried cross-compiling from Linux to Windows with mingw, but given the number of dependencies and needed changes to the build system I don’t think it’s very easy too. You may give it a try though.

In this case I’d actually recommend:

  • use this project only in a Unix environment where the compiler is GCC and thus automatically works with GCC that also PlatformIO uses
  • work with VisualStudio on Windows and not PlatformIO
  • ask the Gazebo people to build the library for MinGW to be able to use in a GCC Windows environment
1 Like

First of all, thanks a lot for trying everything out, I really appreciate it! Looks like this is a bigger problem than I thought it was…I will try to cross-compile it because it seems like this is the only thing that might work, but if not I will try your other recommendations.
Again, thanks a lot.