-1

I am getting linker failures under MinGW, however I cannot see why. This is the link command:

g++ -shared -mthreads -Wl,--out-implib,C:\Users\camm\Syren\libs\libSy_polyMesh.a -o C:\Users\camm\Syren\libs\Sy_polyMesh.dll debug/Sy_polyMesh.o debug/moc_Sy_polyMesh.o debug/qrc_Sy_polyMesh.o -L"c:\Qt\4.8.4\lib" -lglu32 -lopengl32 -lgdi32 -luser32 -LC:\Users\camm\Syren/libs -lSyren -lglew32 -lboost_system -lQtSvgd4 -lQtSqld4 -lQtOpenGLd4 -lQtGuid4 -lQtCored4

The undefined reference errors come from the Syren dll (I should state the command was automatically generated by qmake). The -LC:\Users\camm\Syren/libs looks malformed to me because of the mix of forward and backslashes, but if I manually set them to all one way or the other - it does not change the compiler output.

I had earlier problems with 3rd party libraries I needed (GLEW and Boost specifically), but because they were relatively 'constant' I didn't have a problem putting them in my C:\MinGW\lib directory. But that is really not an option for my plugins.

What I find is that the MinGW docs state in a few locations:

...since suitable search paths may always be specified using -L options.

...but that GCC itself furnishes the effective defaults, by supplying appropriate -L options.

However, C:\Users\camm\Syren\libs is where Syren.dll resides!

Edit: Here are the LIBS declarations in my .pro file:

LIBS += -L$(SYREN_PATH)/libs \
    -lSyren
win32 {
    LIBS += -lglew32 \
            -lboost_system
}

And $(SYREN_PATH) expands to C:\Users\camm\Syren. Also I can see to the 'missing' symbols in Syren.dll, for example:

C:\Users\camm\Documents\Syren\Sy_polyMesh_debug/../Sy_polyMesh/src/Sy_polyMesh.cpp:341: undefined reference to `Sy_GLBuffer::unbind()'

Can be seen listed as:

6c500bd6 T _ZN11Sy_GLBuffer6unbindEv

Edit2

After adding a verbose flag to the linker stage I noticed that the linker was iterating through each search path and then through each library naming convention, and using the first one it could open.

attempt to open C:\Users\camm\Syren/libs/libSyren.dll.a failed
attempt to open C:\Users\camm\Syren/libs/Syren.dll.a failed
attempt to open C:\Users\camm\Syren/libs/libSyren.a succeeded

Hypothesizing that the libSyren.a may be broken, I renamed it to force the linker to use the .dll:

attempt to open C:\Users\camm\Syren/libs/libSyren.dll.a failed
attempt to open C:\Users\camm\Syren/libs/Syren.dll.a failed
attempt to open C:\Users\camm\Syren/libs/libSyren.a failed
attempt to open C:\Users\camm\Syren/libs/Syren.lib failed
attempt to open C:\Users\camm\Syren/libs/libSyren.dll failed
attempt to open C:\Users\camm\Syren/libs/Syren.dll succeeded

But I still get exactly the same error messages!

cmannett85
  • 21,725
  • 8
  • 76
  • 119
  • Which build system are you using? The compiler itself should understand both, but the shell and make don't. – Jan Hudec Dec 19 '12 at 10:17
  • can you post your "LIBS" declarations inside the project file?? – UmNyobe Dec 19 '12 at 10:20
  • @JanHudec I'm running Qt's MinGW, no cygwin involved. – cmannett85 Dec 19 '12 at 10:30
  • @cmannett85: I didn't even think about cygwin. I mean't whether it's manually written makefiles or cmake-generated ones or qmake-generated ones and whether you have MSYS (that is unix shell for mingw; cygwin is different thing) – Jan Hudec Dec 19 '12 at 10:37
  • @JanHudec It's `qmake`-generated. Presumably Qt Creator uses MSYS as the shell, I get the same output from both. – cmannett85 Dec 19 '12 at 11:44
  • If it doesn't complain about -lSyren not found, I don't see how the -L could be ignored. Is Syren built with mingw? You cannot mix msvc and mingw builds when using C++ (works for C). – Frank Osterfeld Jan 04 '13 at 20:38

3 Answers3

2

If you are linking the right DLL and the linker isn't complaining about a missing file, the dll might be missing exports to allow linking.

The MinGW linker can link directly to a DLL if it properly exports the symbols, although it is still recommended to link to the import library (which should be created in a qmake build) which is named lib*.a or lib*.dll.a. I believe the linker looks for variants with and without the libprefix, but I am unsure and should test this myself.

You can check what symbols a DLL exports by using objdump and/or nm.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • I have the `lib*.a` variant in the same directory as the `.dll`, so shouldn't it be using it anyway? – cmannett85 Dec 19 '12 at 12:45
  • @cmannett85 yes, then you probably are. Check if the `.a` and `.dll` file show the symbols that the linker can't find. – rubenvb Dec 19 '12 at 13:31
  • Yes I can see the missing symbols with both `objdump` and `nm` - I'm really struggling to understand what's going on now... – cmannett85 Dec 19 '12 at 13:59
  • I have added more detail to my question, can you see if it hints at anything else you might know? – cmannett85 Dec 19 '12 at 15:00
  • I believe DLL exported functions will become `__imp_*original_name*`, and these symbols will need to be present alongside the one you found. For a Windows DLL, you'll need to use the `dllimport/dllexport` mechanism for everything to work. It seems though you are building Syren statically. Have you checked the presence of the missing symbol in the `libSyren.a`? – rubenvb Dec 19 '12 at 15:16
1

If the linker doesn't complain about not being able to load Syren dll, it means that the file is correctly loaded... The symbols are just missing into the Syren dll (not exported ?)... Why it's hard to tell without more information

When you built the Syren lib, did you have any warning about missing prototypes ? What is used by Syren lib, nothing not portable or requiring a Windows dll ? Could you give the list of missing symbols ?

Edit : How do you compile the Syren.dll ? Did you use Mingw ? What option did you pass to the compiler / linker ? I suggest to read these 2 links :

If you are exporting C++ function you must use the same compiler between the program and the DLL. Or you could use a C-style wrapper functions to encapsulate the C++ ABI.

A very good article about this subject : http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL

benjarobin
  • 4,410
  • 27
  • 21
  • I think you're right, if I copy the `Syren.dll` and `libSyren.a` file into `MinGW/lib`, it still doesn't work. I'm porting this app to Windows from Linux (where stuff like this 'just works'), so is there some special option I'm missing somewhere to add the symbols? Surely this behaviour would be default? Another odd thing is that the (debug) shared library is 100MB bigger than the Linux version! – cmannett85 Dec 19 '12 at 13:00
  • First of all which are the missing symbols ? How the function associated with these symbols are declared into Syren lib ? – benjarobin Dec 19 '12 at 13:05
  • Syren links to GLEW and boost which I built successfully in MinGW, and the Qt libraries which came pre-built. I had no missing prototype warnings (_my_ code base has not changed between the two operating systems). There are about 230 missing symbols, they _all_ from code I have written, and _all_ come from Syren.dll. – cmannett85 Dec 19 '12 at 13:19
  • Without giving a least one example, the only guess than I can make is a problem of interface between C and C++ code, but We don't even have this information... Did you try the advice of @rubenvb : using objdump on the dll to see if the required symbol are listed – benjarobin Dec 19 '12 at 13:29
  • Yes I can see the missing symbols with both `objdump` and `nm` - I'm really struggling to understand what's going on now... – cmannett85 Dec 19 '12 at 13:59
  • I have added more detail to my question, can you see if it hints at anything else you might know? – cmannett85 Dec 19 '12 at 15:00
0

What happens when you replace $(SYREN_PATH) with $${SYREN_PATH}? Because the former notation $() means the contents of an environment variable at the time Makefile is executed.

See the qmake variable reference.

Community
  • 1
  • 1
UmNyobe
  • 22,539
  • 9
  • 61
  • 90