Peter Rosin skrev 2012-03-23 08:35: > Anthony Green skrev 2012-03-23 01:23: >> On 3/22/2012 7:25 PM, Peter Rosin wrote: >>> This series fixes a number of problems that MSVC has with libffi. >> >> Thanks Peter. Do you know if MS makes a Free-as-in-Beer MSVC distribution? > > Yes, they do, Microsoft named them the "Express" edition. > > Latest non-beta version here: > http://www.microsoft.com/visualstudio/en-us/products/2010-editions/express > > I have a few wrapper scripts and hacks in the environment to make it work, and > one more small unfinished patch that's needed for the testsuite to work with > MSVC when libffi is a dll. I'll write something up to describe my environment > later, things are interfering... Notes on using libffi with MSVC MSVC is best run from MSYS. MSVC is *much* more similar in nature to the MinGW-GCC than to the more posixy-expecting toolchains provided by Cygwin. The testsuite needs dejagnu/expect/tcl and I selected to use the Cygwin versions. But doing that and running from MSYS forces you to set up an "identify mount" (google it) so that the posix tools in Cygwin finds the same files as the native Win32 tools do. I created my identity mount in an unorthodox way because I already had everything installed in a way not compatible with an ordinary identity mount setting. I have Cygwin installed in C:\Cygwin, MinGW in c:\MinGW and the MSYS root in C:\MinGW\msys\1.0. The cygdrive prefix for Cygwin is "/cygdrive" and for MSYS it's just plain old "/". I.e., the defaults. Then add a mount to Cygwin so that Cygwin processes sees /c/Cygwin the same way as MSYS processes does: cygwin$ mount C:/ /c Then create a junction named "C:\c" pointing back to "C:\" so that native Win32 processes sees /c/Cygwin the same way too. In a cmd window: C:\> mklink /D c:\c c:\ With this everybody can access the same files as /c/Cygwin/bla/bla, at least as long as the current drive of native Win32 processes is C:, but that's a fairly easy promise to keep in this setting. Using Cygwin, I then checkout libffi: cygwin$ cd # Now in C:\Cygwin\home\ cygwin$ git clone git://.../libffi.git Then fool the libffi testsuite into thinking that MSYS has dejagnu etc like this: cygwin$ cat << 'EOF' > dejagnu/runtest #! /bin/sh export DEJAGNULIBS=/c/Cygwin/usr/share/dejagnu /c/Cygwin/bin/runtest "$@" EOF cygwin$ chmod +x dejagnu/runtest cygwin$ cat << 'EOF' > libffi/expect/expect #! /bin/sh /c/Cygwin/bin/expect "$@" EOF cygwin$ chmod +x libffi/expect/expect Then provide the libffi testsuite with an xgcc wrapper that invokes MSVC with a hacked version of the latest version of the compile script from automake (attached, this hacked version works better than the provided msvcc.sh): cygwin$ cat << 'EOF' > libffi/xgcc #! /bin/sh /c/Cygwin/home//libffi/compile cl -nologo -Zi -MD "$@" EOF cygwin$ chmod +x libffi/xgcc Then replace the compile script as provided by libffi (the one in /c/Cygwin/home//libffi/compile) with the above mentioned version. I'm using this script to set up the environment for running MSVC, but I don't know how the directories map to the "Express" edition? I think there's an install option to add these directories to the Windows environment, making MSVC visible allover (but I don't like that so I'm using my script instead). cygwin$ cat << 'EOF' > /c/Cygwin/home/peda/bin/vccvars.sh case `uname` in CYGWIN*) c=/cygdrive/c ;; *) c=/c ;; esac COMNTOOLS=$c'/Program Files (x86)/Microsoft Visual Studio 10.0/' PSDK=$c'/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/' VS100COMNTOOLS=$COMNTOOLS'Common7/Tools/' WindowsSdkDir=$PSDK VCINSTALLDIR=$COMNTOOLS'VC/' VSINSTALLDIR=$COMNTOOLS DevEnvDir=$COMNTOOLS'Common7/IDE/' export PATH=$c'/Program Files (x86)/Microsoft F#/v4.0/:'\ $COMNTOOLS'VSTSDB/Deploy:'\ $DevEnvDir':'\ $VCINSTALLDIR'BIN':\ $VS100COMNTOOLS':'\ $c'/Windows/Microsoft.NET/Framework/v4.0.30319:'\ $c'/Windows/Microsoft.NET/Framework/v3.5:'\ $VCINSTALLDIR'VCPackages:'\ $c'/Program Files (x86)/HTML Help Workshop:'\ $COMNTOOLS'Team Tools/Performance Tools:'\ $PSDK'bin/NETFX 4.0 Tools:'$PATH COMNTOOLS='c:\Program Files (x86)\Microsoft Visual Studio 10.0\' PSDK='c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\' export VS100COMNTOOLS=$COMNTOOLS'Common7\Tools\' export WindowsSdkDir=$PSDK export VCINSTALLDIR=$COMNTOOLS'VC\' export VSINSTALLDIR=$COMNTOOLS export DevEnvDir=$COMNTOOLS'Common7\IDE\' export INCLUDE=$PSDK'INCLUDE;'$INCLUDE export INCLUDE=$VCINSTALLDIR'ATLMFC\INCLUDE;'$INCLUDE export INCLUDE=$VCINSTALLDIR'INCLUDE;'$INCLUDE export LIB=$PSDK'LIB;'$LIB export LIB=$VCINSTALLDIR'ATLMFC\LIB;'$LIB export LIB=$VCINSTALLDIR'LIB;'$LIB export LIBPATH=$PSDK'LIB;'$LIBPATH export LIBPATH=$VCINSTALLDIR'ATLMFC\LIB;'$LIBPATH export LIBPATH=$VCINSTALLDIR'LIB;'$LIBPATH export DevEnvDir=$COMNTOOLS'Common7\IDE\' EOF cygwin$ chmod -x /c/Cygwin/home//bin/vcvars.sh Set up the MSYS environment to run MSVC. msys$ . /c/Cygwin/home//bin/vcvars.sh Finally, build the dang thing: msys$ cd /c/Cygwin/home//libffi msys$ cd msvc msys$ ../configure \ CC="/c/Cygwin/home//libffi/compile cl -nologo" \ CFLAGS="-MD -Zi" \ CXX="/c/Cygwin/home//libffi/compile cl -nologo" \ CXXFLAGS="-MD -Zi" \ NM="dumpbin -symbols" \ --enable-dependency-tracking \ --disable-shared msys$ make msys$ make check | grep -v "excess errors" # MSVC is *noisy* Hmmm, I wonder what I forgot? One thing is that I can't remember if I had to do anything special to prevent Cygwin from creating symbolic links (MSYS and native Win32 processes don't understand those). Oh, along those lines, one thing to keep in mind is that MSYS does not provide symbolic links at all (ln -s makes a copy), so I have to run ./config.status to recopy ../src/x86/ffitarget.h to the build tree in case it has changed. With the below patch, I can configure with the below args and get a DLL that can be used by the testsuite, but that FFI_BUILDING define should be added to a Makefile instead of burdening the user to add it to CFLAGS so the patch is not finished (but perhaps it's not an acceptable approach to add an FFI_BUILDING define?). Cheers, Peter msys$ ../configure \ CC="/c/Cygwin/home//libffi/compile cl -nologo" \ CFLAGS="-MD -Zi -DFFI_BUILDING" \ CXX="/c/Cygwin/home//libffi/compile cl -nologo" \ CXXFLAGS="-MD -Zi -DFFI_BUILDING" \ NM="dumpbin -symbols" \ --enable-dependency-tracking diff --git a/include/ffi.h.in b/include/ffi.h.in index 84017f1..100ec04 100644 --- a/include/ffi.h.in +++ b/include/ffi.h.in @@ -166,19 +166,25 @@ typedef struct _ffi_type #error "long size not supported" #endif +#if defined _MSC_VER && !defined FFI_BUILDING +#define FFI_EXTERN extern __declspec(dllimport) +#else +#define FFI_EXTERN extern +#endif + /* These are defined in types.c */ -extern ffi_type ffi_type_void; -extern ffi_type ffi_type_uint8; -extern ffi_type ffi_type_sint8; -extern ffi_type ffi_type_uint16; -extern ffi_type ffi_type_sint16; -extern ffi_type ffi_type_uint32; -extern ffi_type ffi_type_sint32; -extern ffi_type ffi_type_uint64; -extern ffi_type ffi_type_sint64; -extern ffi_type ffi_type_float; -extern ffi_type ffi_type_double; -extern ffi_type ffi_type_pointer; +FFI_EXTERN ffi_type ffi_type_void; +FFI_EXTERN ffi_type ffi_type_uint8; +FFI_EXTERN ffi_type ffi_type_sint8; +FFI_EXTERN ffi_type ffi_type_uint16; +FFI_EXTERN ffi_type ffi_type_sint16; +FFI_EXTERN ffi_type ffi_type_uint32; +FFI_EXTERN ffi_type ffi_type_sint32; +FFI_EXTERN ffi_type ffi_type_uint64; +FFI_EXTERN ffi_type ffi_type_sint64; +FFI_EXTERN ffi_type ffi_type_float; +FFI_EXTERN ffi_type ffi_type_double; +FFI_EXTERN ffi_type ffi_type_pointer; #if @HAVE_LONG_DOUBLE@ extern ffi_type ffi_type_longdouble;