Reputation: 4314
I am building a program, which uses a library I wrote, which uses a third party library distributed as a .lib import file and a .dll file. I am building using MinGW in the MSys environment with CMake.
When I try to link my program I get the following errors (cleaned for readability):
ld.exe: libMyLib.a(mylib.cpp.obj): in function `MangledFnName':
src/mylib.cpp:297: undefined reference to `_imp__hasp_get_info@16'
ld.exe: src/mylib.cpp:326: undefined reference to `_imp__hasp_free@4'
Using objdump on the import file (and removing the extra stuff) I see:
[33291](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x001f3cb4 _hasp_get_info@16
[56900](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x001ee4bf _hasp_free@4
Note the lack of _imp_
at the start of the symbol.
Similarly, but differently, when I look at the FTDI libraries which do link correctly in this environment, I see:
[ 2](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __imp__FT_Write@16
[ 4](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 _FT_Write@16
00000002 dir32 __imp__FT_Write@16
It has the symbol both with and without _imp_
at the start.
UPDATE: I wrote a script to extract the symbols from the original import library and use dlltool to generate a new one. It now links...but doesn't run. I get the error:
The procedure entry point _hasp_free could not be located in the dynamic link library.
If I ask the third party to rebuild their library, what do I have to ask them to do to provide the extra symbol?
How can I tell ld
to look for the symbol name without prepending _imp_
?
Upvotes: 0
Views: 610
Reputation: 4314
So the answer is to regenerate the import library. There are various hints here and there on StackOverflow, and an article here on how to do it in a Windows command prompt using MSVC tools, but for future reference, here is an MSys bash script:
#!/bin/bash
if [ -z "$2" ]
then
echo "Syntax: $(basename $0) <import library> <dll file>"
exit
fi
RAW_DLL_NAME=$(basename "$2" | sed 's#.dll$##')
echo "LIBRARY ${RAW_DLL_NAME}" > tmp.def
echo "EXPORTS" >> tmp.def
for SYMBOL in $(objdump -t "$1" | grep "sec 1" | grep @ | awk '{ print $9 }' | sed 's#^_##')
do
echo " ${SYMBOL}" >> tmp.def
done
dlltool -k -d tmp.def -l "${RAW_DLL_NAME}.dll.a" -D "${RAW_DLL_NAME}.dll"
rm tmp.def
My first attempt failed because I wasn't stripping off the leading underscore on the symbols that objdump was producing, and was then using the --no-leading-underscore
option on dlltool. This was wrong.
I am also filtering the exported symbols to only include those that contain an "@". Using MSVCs dumpbin
utility shows more symbols that can be exported. I filtered on the @
symbol because I didn't care about the additional symbols, and it prevented me getting a large number of symbols like "__WBPT2660959813".
Upvotes: 1