I'm trying to build libffi using VC++. Apparently, this is possible (albeit from a command line) but only if I first install Cygwin, MSYS and MinGW.

If all else fails I suppose I'll have to install them but I'd prefer to create a vcproj if possible. I created a suitable project and as it happened, I only encountered one module that won't compile. Unusually, the module is called win32.S and looks something like this:-

Code:
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>

#ifdef _MSC_VER

.386
.MODEL FLAT, C

EXTRN ffi_closure_SYSV_inner:NEAR

_TEXT SEGMENT

ffi_call_win32 PROC NEAR,
    ffi_prep_args : NEAR PTR DWORD,
    ecif          : NEAR PTR DWORD,
    cif_abi       : DWORD,
    cif_bytes     : DWORD,
    cif_flags     : DWORD,
    rvalue        : NEAR PTR DWORD,
    fn            : NEAR PTR DWORD

        ;; Make room for all of the new args.
        mov  ecx, cif_bytes
        sub  esp, ecx

        mov  eax, esp

        ;; Place all of the ffi_prep_args in position
        push ecif
        push eax
        call ffi_prep_args

        ;; Return stack to previous state and call the function
        add  esp, 8

	;; Handle thiscall and fastcall
	cmp cif_abi, 3 ;; FFI_THISCALL
	jz do_thiscall
	cmp cif_abi, 4 ;; FFI_FASTCALL
	jnz do_stdcall
	mov ecx, DWORD PTR [esp]
	mov edx, DWORD PTR [esp+4]
	add esp, 8
	jmp do_stdcall
do_thiscall:
	mov ecx, DWORD PTR [esp]
	add esp, 4
do_stdcall:
        call fn

        ;; cdecl:   we restore esp in the epilogue, so there's no need to
        ;;          remove the space we pushed for the args.
        ;; stdcall: the callee has already cleaned the stack.

        ;; Load ecx with the return type code
        mov  ecx, cif_flags

        ;; If the return value pointer is NULL, assume no return value.
        cmp  rvalue, 0
        jne  ca_jumptable

        ;; Even if there is no space for the return value, we are
        ;; obliged to handle floating-point values.
        cmp  ecx, FFI_TYPE_FLOAT
        jne  ca_epilogue
        fstp st(0)

        jmp  ca_epilogue

ca_jumptable:
        jmp  [ca_jumpdata + 4 * ecx]
ca_jumpdata:
        ;; Do not insert anything here between label and jump table.
        dd offset ca_epilogue       ;; FFI_TYPE_VOID
        dd offset ca_retint         ;; FFI_TYPE_INT
        dd offset ca_retfloat       ;; FFI_TYPE_FLOAT
        dd offset ca_retdouble      ;; FFI_TYPE_DOUBLE
        dd offset ca_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
        dd offset ca_retint8        ;; FFI_TYPE_UINT8
        dd offset ca_retint8        ;; FFI_TYPE_SINT8
        dd offset ca_retint16       ;; FFI_TYPE_UINT16
        dd offset ca_retint16       ;; FFI_TYPE_SINT16
        dd offset ca_retint         ;; FFI_TYPE_UINT32
        dd offset ca_retint         ;; FFI_TYPE_SINT32
        dd offset ca_retint64       ;; FFI_TYPE_UINT64
        dd offset ca_retint64       ;; FFI_TYPE_SINT64
        dd offset ca_epilogue       ;; FFI_TYPE_STRUCT
        dd offset ca_retint         ;; FFI_TYPE_POINTER
        dd offset ca_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
        dd offset ca_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
        dd offset ca_retint         ;; FFI_TYPE_SMALL_STRUCT_4B

ca_retint8:
        ;; Load %ecx with the pointer to storage for the return value
        mov   ecx, rvalue
        mov   [ecx + 0], al
        jmp   ca_epilogue

ca_retint16:
        ;; Load %ecx with the pointer to storage for the return value
        mov   ecx, rvalue
        mov   [ecx + 0], ax
        jmp   ca_epilogue

ca_retint:
        ;; Load %ecx with the pointer to storage for the return value
        mov   ecx, rvalue
        mov   [ecx + 0], eax
        jmp   ca_epilogue

ca_retint64:
        ;; Load %ecx with the pointer to storage for the return value
        mov   ecx, rvalue
        mov   [ecx + 0], eax
        mov   [ecx + 4], edx
        jmp   ca_epilogue

ca_retfloat:
        ;; Load %ecx with the pointer to storage for the return value
        mov   ecx, rvalue
        fstp  DWORD PTR [ecx]
        jmp   ca_epilogue

ca_retdouble:
        ;; Load %ecx with the pointer to storage for the return value
        mov   ecx, rvalue
        fstp  QWORD PTR [ecx]
        jmp   ca_epilogue

ca_retlongdouble:
        ;; Load %ecx with the pointer to storage for the return value
        mov   ecx, rvalue
        fstp  TBYTE PTR [ecx]
        jmp   ca_epilogue

ca_epilogue:
        ;; Epilogue code is autogenerated.
        ret
ffi_call_win32 ENDP

// Some more stuff

#endif
I've only shown the first function (there are a few others). As you can see, it's a strange mixture of C and x86 assembly code but the presence of #ifdef _MSC_VER near the top of the file suggests to me that it should be buildable with MSVC. However, VS2005 doesn't seem to like it very much (at least, not from within the IDE).

What would I need to do to compile and link this module? Do I need to pre-process it somehow? Or can it only be built from a command line? Or do I need a more recent version of Visual Studio?