From 5e3f92ac36448ac8bec0eba6a0ca3e5418408aad Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Sat, 8 May 2010 09:54:50 +0000 Subject: [PATCH] 2010-05-08 11:53 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * utils/hbmk2/hbmk2.prg + Extended -mkimplib option for windows gcc compilers (mingw/cygwin) to first look for matching COFF .lib file and use it to create import library. If such is not found, try to use matching .def file and automatically generate import library using dlltool. If none if these were found, use the .dll directly, to create the import library. In case of Harbour, this method resolves almost all mingw implib needs. See longer note in source (in function win_implib_command_gcc()) about the details of the problem, the only thing I cannot see is why mingw/cygwin developers insist on not fixing this issue since ten year, while all other compilers can properly resolve this problem. Anyhow until then mingw cannot use .dll using stdcall calling convention without COFF .lib or .def file. If both are missing, the only solution is to manually build a .def file by first generating it from .dll then manually adding '@nn' decoration according to function prototypes. Thanks mingw. * config/postinst.prg - Deleted APOLLO implib generation. Apollo fall into the problematic category for mingw, because developers chose to use stdcall callconv and they forgot to provide implib or .def file. It's not part of core anyway. * Slightly changed mysql implib generation to also work for mingw. - Deleted no more necessary manuall hack for mysql implib generation. + Added manual hack for firebird implib generation. In this hbmk2 automatism cannot work as they distribute COFF .lib in another directory and using a different name than the .dll. --- harbour/ChangeLog | 34 +++++++++++++++++++ harbour/config/postinst.prg | 12 +++---- harbour/utils/hbmk2/hbmk2.prg | 63 ++++++++++++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 8 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index b857501c3a..27767561d0 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,40 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-05-08 11:53 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) + * utils/hbmk2/hbmk2.prg + + Extended -mkimplib option for windows gcc compilers (mingw/cygwin) + to first look for matching COFF .lib file and use it to create + import library. If such is not found, try to use matching .def + file and automatically generate import library using dlltool. + If none if these were found, use the .dll directly, to create + the import library. In case of Harbour, this method resolves + almost all mingw implib needs. + See longer note in source (in function win_implib_command_gcc()) + about the details of the problem, the only thing I cannot see + is why mingw/cygwin developers insist on not fixing this issue + since ten year, while all other compilers can properly resolve + this problem. Anyhow until then mingw cannot use .dll using + stdcall calling convention without COFF .lib or .def file. If + both are missing, the only solution is to manually build a + .def file by first generating it from .dll then manually + adding '@nn' decoration according to function prototypes. + Thanks mingw. + + * config/postinst.prg + - Deleted APOLLO implib generation. Apollo fall into the + problematic category for mingw, because developers chose + to use stdcall callconv and they forgot to provide + implib or .def file. It's not part of core anyway. + * Slightly changed mysql implib generation to also work + for mingw. + - Deleted no more necessary manuall hack for mysql implib + generation. + + Added manual hack for firebird implib generation. In + this hbmk2 automatism cannot work as they distribute + COFF .lib in another directory and using a different + name than the .dll. + 2010-05-08 09:32 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * include/hbsetup.h + Added detection for HB_OS_IPHONE. Name tentative, diff --git a/harbour/config/postinst.prg b/harbour/config/postinst.prg index d9713f10a0..3a9d8d660c 100644 --- a/harbour/config/postinst.prg +++ b/harbour/config/postinst.prg @@ -81,18 +81,16 @@ PROCEDURE Main() { "HB_WITH_ADS" , "ace32.dll" , .F., "" },; { "HB_WITH_ADS" , "32bit\ace32.dll" , .F., "" },; { "HB_WITH_ALLEGRO" , "..\bin\alleg42.dll" , .T., "alleg" },; - { "HB_WITH_APOLLO" , "..\sde61.dll" , .F., "" },; - { "HB_WITH_APOLLO" , "..\sde7.dll" , .F., "" },; { "HB_WITH_BLAT" , "..\blat.dll" , .T., "" },; { "HB_WITH_CAIRO" , "..\..\bin\libcairo-2.dll" , .T., "cairo" },; { "HB_WITH_CURL" , "..\libcurl.dll" , .T., "" },; { "HB_WITH_CURL" , "..\bin\libcurl.dll" , .T., "" },; - { "HB_WITH_FIREBIRD" , "..\bin\fbclient.dll" , .F., "" },; + { "HB_WITH_FIREBIRD" , "..\bin\fbclient.dll" , .F., "" },; /* Doesn't work for mingw, because .lib has another name in another directory */ { "HB_WITH_FREEIMAGE" , "..\Dist\FreeImage.dll" , .F., "" },; { "HB_WITH_GD" , "..\bin\bgd.dll" , .F., "" },; { "HB_WITH_LIBHARU" , "..\libhpdf.dll" , .F., "" },; { "HB_WITH_LIBHARU" , "..\lib_dll\libhpdf.dll" , .F., "" },; - { "HB_WITH_MYSQL" , "..\bin\libmySQL.dll" , .F., "" },; + { "HB_WITH_MYSQL" , "..\lib\opt\libmySQL.dll" , .F., "" },; { "HB_WITH_OCILIB" , "..\lib32\ociliba.dll" , .F., "" },; { "HB_WITH_OCILIB" , "..\lib32\ocilibm.dll" , .F., "" },; { "HB_WITH_OCILIB" , "..\lib32\ocilibw.dll" , .F., "" },; @@ -113,9 +111,9 @@ PROCEDURE Main() ENDIF NEXT - /* HACK: Copying .dll to .a doesn't work in case of mysql, so we copy over the supplied import lib. [vszakats] */ - IF GetEnv( "HB_COMPILER" ) $ "mingw|mingw64" - hb_FCopy( GetEnv( "HB_WITH_MYSQL" ) + _PS_ + StrTran( "..\lib\opt\libmySQL.lib", "\", _PS_ ), GetEnv( "HB_LIB_INSTALL" ) + _PS_ + "liblibmysql.a" ) + /* HACK: Automatic implib generation doesn't work in case of FireBird, so we manually create it. [vszakats] */ + IF GetEnv( "HB_COMPILER" ) $ "mingw|mingw64|cygwin" + hb_FCopy( GetEnv( "HB_WITH_FIREBIRD" ) + _PS_ + StrTran( "..\lib\fbclient_ms.lib", "\", _PS_ ), GetEnv( "HB_LIB_INSTALL" ) + _PS_ + "libfbclient.a" ) ENDIF /* Exception: We use static libs with mingw */ diff --git a/harbour/utils/hbmk2/hbmk2.prg b/harbour/utils/hbmk2/hbmk2.prg index 41e49a6054..ac081ca83c 100644 --- a/harbour/utils/hbmk2/hbmk2.prg +++ b/harbour/utils/hbmk2/hbmk2.prg @@ -2685,7 +2685,7 @@ FUNCTION hbmk2( aArgs, /* @ */ lPause ) cOpt_Dyn := "-shared -o {OD} {LO} {FD} {DL} {LS}" cBin_Link := cBin_CompC cOpt_Link := "{LO} {LA} {LS} {FL} {DL}" - bBlk_ImpLib := {| cSourceDLL, cTargetLib | hb_FCopy( cSourceDLL, cTargetLib ) != F_ERROR } + bBlk_ImpLib := {| cSourceDLL, cTargetLib, cFlags | win_implib_command_gcc( hbmk, hbmk[ _HBMK_cCCPREFIX ] + "dlltool" + hbmk[ _HBMK_cCCPOSTFIX ] + hbmk[ _HBMK_cCCEXT ] + " {FI} -d {ID} -l {OL}", nCmd_Esc, cSourceDLL, cTargetLib, cFlags ) } cLibPathPrefix := "-L" cLibPathSep := " " cLibLibExt := ".a" @@ -7854,6 +7854,67 @@ STATIC FUNCTION win_implib_command( hbmk, cCommand, nCmd_Esc, cSourceDLL, cTarge RETURN hb_processRun( cCommand ) == 0 +#define _COFF_LIB_SIGNATURE "!" + +STATIC FUNCTION IsCOFFLib( cFileName ) + LOCAL fhnd := FOpen( cFileName, FO_READ ) + LOCAL cBuffer + + IF fhnd != F_ERROR + cBuffer := Space( Len( _COFF_LIB_SIGNATURE ) ) + FRead( fhnd, @cBuffer, Len( cBuffer ) ) + FClose( fhnd ) + IF cBuffer == _COFF_LIB_SIGNATURE + RETURN .T. + ENDIF + ENDIF + + RETURN .F. + +STATIC FUNCTION win_implib_command_gcc( hbmk, cCommand, nCmd_Esc, cSourceDLL, cTargetLib, cFlags ) + LOCAL tmp + + /* NOTE: There is a big problem with mingw/cygwin 'ld' linker: + It cannot properly link stdcall decorated (_sym@nn) function names + directly with .dlls, since in .dlls the decoration is stripped from + the exported symbols. So, it _requires_ a .def file or a COFF import .lib + which have the the decorated version of the symbols. Such .def/.lib + file cannot be automatically generated from the .dll, as the + decoration needs to be rebuilt based on function parameters. + Not even 'ld' option '--enable-stdcall-fixup' ("Link _sym to _sym@nn without warnings") + option will help the case, since we'd need a "Link _sym@nn to _sym" + option. For some reason and despite the frequent complaints, gcc + developers failed to add such option since year ~2000. + To circumvent that and make it possible for Harbour users to + effortlessly generate implibs from .dlls, we cannot do more than + rely on .dll distributors to provide .def or COFF import .libs + and make use of these automatically if they are available. + Hopefully one day gcc will introduce a feature to make such tricks + unnecessary and make it possible to create proper implibs out of + ordinary .dlls, like with every other compiler. + [vszakats] */ + + /* Try to find COFF .lib with the same name */ + IF hb_FileExists( tmp := FN_ExtSet( cSourceDLL, ".lib" ) ) + IF IsCOFFLib( tmp ) + IF ! hbmk[ _HBMK_lQuiet ] + hbmk_OutStd( hbmk, I_( "Found COFF .lib with the same name, falling back to using it instead of the .dll." ) ) + ENDIF + RETURN hb_FCopy( tmp, cTargetLib ) != F_ERROR + ENDIF + ENDIF + + /* Try to find .def file with the same name */ + IF hb_FileExists( tmp := FN_ExtSet( cSourceDLL, ".def" ) ) + IF ! hbmk[ _HBMK_lQuiet ] + hbmk_OutStd( hbmk, I_( "Found .def file with the same name, falling back to using it instead of the .dll." ) ) + ENDIF + RETURN win_implib_command( hbmk, cCommand, nCmd_Esc, tmp, cTargetLib, cFlags ) + ENDIF + + /* Use .dll directly if all other attempts failed */ + RETURN hb_FCopy( cSourceDLL, cTargetLib ) != F_ERROR + STATIC FUNCTION win_implib_command_msvc( hbmk, cCommand, nCmd_Esc, cSourceDLL, cTargetLib, cFlags ) LOCAL lSuccess := .F.