Reputation: 6128
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
Upvotes: 15
Views: 66541
Reputation: 66851
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]).
Upvotes: 1
Reputation: 6128
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.
Upvotes: 7