How do I fix undefined reference to _imp__*?
Asked Answered
T

2

15

I'm trying to compile something that depends on gtkspell, which depends on enchant, under MinGW. I'm getting errors like gtkspell/gtkspell.c:757: undefined reference to '_imp__enchant_broker_init' I suspect this is either due to the fact that I'm trying to link againt a {static,dynamic} library when I should be linking against the other one, or because there's only one underscore before the imp and there should be two; I get

$ objdump -t /d/opt/enchant-1.6.0/lib/libenchant.a | grep enchant_broker_init
[ 85](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00002ac0 _enchant_broker_init

and

$ objdump -t /d/opt/enchant-1.6.0/lib/libenchant.dll.a | grep enchant_broker_init
[  6](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 _enchant_broker_init
[  7](sec  3)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 __imp__enchant_broker_init

The internet (http://lists.freedesktop.org/archives/gstreamer-devel/2007-January/013975.html) suggests that the imp mangling comes from

_declspec(dll{import,export})

though enchant seems to use

__declspec(dll{import,export})

, and commenting out the relevant lines in enchant.h makes gtkspell.c request enchant_broker_init rather than _imp__enchant_broker_init, but doesn't change the symbols that show up in libenchant. Is there a way to make gcc not mangle the names, or does anyone have ideas about what might be going wrong/how to fix it?

Here's a minimal example that reproduces the problem on my system:

If I have a file enchanttest1.c with contents

#include <stdio.h>
#include <enchant.h>

int main()
{
#ifdef ENCHANT_MODULE_EXPORT
    printf("\nEnchant found\n");
#else
    printf("\nEnchant not found\n");
#endif
    return 0;
}

and a file enchanttest2.c with contents

#include <stdio.h>
#include <enchant.h>

int main()
{
    EnchantBroker *b = enchant_broker_init();
#ifdef ENCHANT_MODULE_EXPORT
    printf("\nEnchant found\n");
#else
    printf("\nEnchant not found\n");
#endif
    return 0;
}

then

gcc enchanttest1.c `pkg-config --cflags enchant` && ./a.exe

gives Enchant found but

gcc enchanttest2.c `pkg-config --cflags enchant` && ./a.exe

gives

C:\Users\JASONG~1\AppData\Local\Temp\ccyDLptc.o:testenchant.c:(.text+0xf): undefined reference to `_imp__enchant_broker_init'
collect2: ld returned 1 exit status
Traver answered 7/4, 2012 at 23:28 Comment(5)
This is a stupid suggestion, but are you making sure you're invoking C (not C++) compilation? You may be experiencing subtle name mangling ridiculousness?Baiel
The enchant.h file wraps everything in #ifdef __cplusplus extern "C" { #endif so I don't think that's the problem. I've also since added a minimal example where I'm pretty sure I'm invoking C compilation.Traver
As a note for followers, when I got this it was because the "dependency library" was defined with __declspec(dllimport), even though it was a static compile. So removing that fixed it up, see betterlogic.com/roger/2012/09/libflite-cross-compile-woeThun
@Thun The link is now dead.Eyepiece
OK I added an answer with fixed link in it, enjoy!Thun
T
7

The way to fix my minimal example is to add --libs after --cflags for pkg-config; gcc couldn't find the library to link against.

I was able to fix the problem that I was running in to with the more complicated code that I was originally trying to compile (gummi (https://gummi.app/)) by passing LDFLAGS="$(pkg-config --cflags --libs gtkspell-2.0 enchant)" CFLAGS="$(pkg-config --cflags --libs gtkspell-2.0 enchant)" to the configure script; the problem seems to have been that the arguments to gcc were passed in the wrong order, and it couldn't find enchant when it was trying to link gtkspell.

Traver answered 8/4, 2012 at 0:7 Comment(3)
Ugh...I just ran into this, making a MinGW port of some legacy code. I can't believe gcc still has this link-order dependency issue, after all these years.Hireling
The dev.midnightcoding.org URL in this post is now outdated. I think the current URL is gummi.app - could someone familiar with Gummi check this and make the edit if so?Preston
Yes, it's the same project, web.archive.org/web/20140702194619/http://… shows the author is Alexander van der Mey, which is the same as the github linked to by gummi.app. I'll fix my answerTraver
T
0

Not an answer to your problem apparently, but this problem can surface when there is some kind of static/shared mismatch.

The _imp__ prefix to method names means the method was defined as

   __declspec(dllexport) my_method_name

when the library was originally compiled. See what does __declspec(dllimport) really mean? for explanation.

When you build a "library" that is ready to be consumed, typical convention is to build it as either "dynamic" or "static." For instance with something called MyLibrary, it might actually compile into two "library" files. One named libMyLibrary.a and another libMyLibrary.dll.a. The first is the "static" library, and second the "shared" library. (side note, if you pass -lMyLibrary to gcc, it searches the library path for either of these files, and if it finds both, it prefers libMyLibrary.dll.a file by default).

If your program that is "using" that library consumes it like this (from a .h file for instance):

   __declspec(dllimport) my_method_name

then links again libMyLibrary.a file (for instance if libMyLibrary.dll.a does not exist), you have a mismatch and it'll throw that error message, even though the method exists in your library file you are linking with. In essence, your .h file contradicts the library file. If you were to link against libMyLibrary.dll.a file, it would work. If you were to change the .h file so it says just my_method_name instead of it being expected to be a dllimport method, and you link against the static library, that would also work. (for instance, some libraries requires you to set a certain preprocessor macro value or you may have to manually munge a .h file or what have you [ex: here search for declspec]).

Thun answered 18/8, 2024 at 1:52 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.