Saturday, June 13, 2015

building libffi on windows by visual studio

problem


It's not trivial task - build libffi by visual studio.


tools & versions


What do you need to build libffi on windows:
  • Visual Studio (2013 in my case)
  • Cygwin 32-bits (I don't know why but cygwin64 doesn't work)

problem solving in a short for x64

0. Download and unpack (I'm using FAR manager for unpacking) libffi sources.
1. Run "VS2013 x64 Native Tools Command Prompt"
2. Open in it Cygwin.bat, for example:
    c:\cygwin\Cygwin.bat
3. Go to directory with sources, for example:
    cd d:/tmp/libraries/libffi-3.2.1
4. Make directory for building and go to it, for example:
    mkdir build-x64
    cd ./build-x64
5. Then you need to configure, and here you need decide which runtime do you want - dynamic (/MD) or static (/MT)
    dynamic (/MD): ../configure CC="../msvcc.sh -m64" CXX="../msvcc.sh -m64" LD=link CPP="cl -nologo -EP" --build=x86_64-unknown-cygwin
    static release (/MT): ../configure CC="../msvcc.sh -DUSE_STATIC_RTL -m64" CXX="../msvcc.sh -DUSE_STATIC_RTL -m64" LD=link CPP="cl -nologo -EP" --build=x86_64-unknown-cygwin
    static debug (/MTd): ../configure CC="../msvcc.sh -DUSE_STATIC_RTL -DUSE_DEBUG_RTL -m64" CXX="../msvcc.sh -DUSE_STATIC_RTL -DUSE_DEBUG_RTL -m64" LD=link CPP="cl -nologo -EP" --build=x86_64-unknown-cygwin
6. Then in ./include/ffitarget.h will be symlink (visual studio don't understand symlinks) - and this symlink has some strange access rights, so, for example in FAR manager (not in this cygwin console) do the next:
    - delete './include/ffitarget.h'
    - copy '../src/x86/ffitarget.h' to './include/ffitarget.h'
7. And in this ffitarget.h file you need to comment define '#define FFI_TARGET_HAS_COMPLEX_TYPE'
8. Using any text editor - in 'libffi-3.2.1\src\x86\win64.S' replace 'jmp SHORT' to 'jmp' under labels:
    'ret_uint16$:'
    'ret_sint16$:'
9. make
10. In subdirectory ./.libs you will get files.


problem solving in a short for x86


0. Download and unpack (I'm using FAR manager for unpacking) libffi sources.
1. Run "VS2013 x86 Native Tools Command Prompt"
2. Open in it Cygwin.bat, for example:
    c:\cygwin\Cygwin.bat
3. Go to directory with sources, for example:
    cd d:/tmp/libraries/libffi-3.2.1
4. Make directory for building and go to it, for example:
    mkdir build-x86
    cd ./build-x86
5. Then you need to configure, and here you need decide which runtime do you want - dynamic (/MD) or static (/MT)
    dynamic: .../configure CC="../msvcc.sh" CXX="../msvcc.sh" LD=link CPP="cl -nologo -EP" --build=i686-unknown-cygwin
    static: ../configure CC="../msvcc.sh -DUSE_STATIC_RTL" CXX="../msvcc.sh -DUSE_STATIC_RTL" LD=link CPP="cl -nologo -EP" --build=i686-unknown-cygwin
6. Then in ./include/ffitarget.h will be symlink, and visual studio don't understand symlinks - so, replace it by real file.    cp ../src/x86/ffitarget.h ./include
7. And in this ffitarget.h file you need to comment define '#define FFI_TARGET_HAS_COMPLEX_TYPE'
8. make
9. In subdirectory ./.libs you will get files.


useful sources and links

0. 'README' file in sources gives you couple advices, but it's not enough
1. This guy also gives good advices - [link], I've backuped it [here]


possible errors (for googling people)

1) if you open cygwin64\Cygwin.bat instead of cygwin\Cygwin.bat
    -----------------------------------------------------------------------------
    checking how to run the C++ preprocessor... /lib/cpp
    configure: error: in `/cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64':
    configure: error: C++ preprocessor "/lib/cpp" fails sanity check
    See `config.log' for more details
    -----------------------------------------------------------------------------
    what to do - use 32-bits cygwin

2) if you set --build=i686... instead of --build=x86_64..., when you want x64 binaries
    -----------------------------------------------------------------------------
    ml -nologo -safeseh -c  ./win32.asm
    ../msvcc.sh: line 241: ml: command not found
    Makefile:1338: ошибка выполнения рецепта для цели <src/x86/win32.lo>
    make[2]: *** [src/x86/win32.lo] Ошибка 1
    make[2]: выход из каталога </cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64>
    Makefile:1596: ошибка выполнения рецепта для цели <all-recursive>
    make[1]: *** [all-recursive] Ошибка 1
    make[1]: выход из каталога </cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64>
    Makefile:730: ошибка выполнения рецепта для цели <all>
    make: *** [all] Ошибка 2
    -----------------------------------------------------------------------------

    what to do - use --build=i686-unknown-cygwin

3) if you forgot replace symlink by real file
    -----------------------------------------------------------------------------
    include\ffitarget.h(1) : error C2059: syntax error : '!'
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\crtdefs.h(642) : error C2081: 'uintptr_t' : name in formal parameter list illegal
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\stddef.h(71) : error C2143: syntax error : missing '{' before '__cdecl'
    include\ffi.h(223) : error C2016: C requires that a struct or union has at least one member
    include\ffi.h(223) : error C2061: syntax error : identifier 'ffi_abi'
    include\ffi.h(232) : error C2059: syntax error : '}'
    include\ffi.h(240) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(240) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(241) : error C2146: syntax error : missing ';' before identifier 'abi'
    include\ffi.h(242) : error C2059: syntax error : 'type'
    include\ffi.h(246) : error C2059: syntax error : ')'
    include\ffi.h(263) : error C2016: C requires that a struct or union has at least one member
    include\ffi.h(263) : error C2061: syntax error : identifier 'ffi_sarg'
    include\ffi.h(264) : error C2061: syntax error : identifier 'uint'
    include\ffi.h(264) : error C2059: syntax error : ';'
    include\ffi.h(268) : error C2059: syntax error : '}'
    include\ffi.h(281) : error C2061: syntax error : identifier 'ffi_java_raw'
    include\ffi.h(281) : error C2059: syntax error : ';'
    include\ffi.h(285) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(285) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(286) : error C2059: syntax error : 'type'
    include\ffi.h(290) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(290) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(290) : error C2059: syntax error : 'type'
    include\ffi.h(290) : error C2059: syntax error : ')'
    include\ffi.h(291) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(291) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(291) : error C2143: syntax error : missing ';' before '*'
    include\ffi.h(291) : error C2059: syntax error : 'type'
    include\ffi.h(291) : error C2059: syntax error : ')'
    include\ffi.h(292) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(292) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(292) : error C2059: syntax error : ')'
    include\ffi.h(298) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(298) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(299) : error C2059: syntax error : 'type'
    include\ffi.h(303) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(303) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(303) : error C2059: syntax error : 'type'
    include\ffi.h(303) : error C2059: syntax error : ')'
    include\ffi.h(304) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(304) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(304) : error C2143: syntax error : missing ';' before '*'
    include\ffi.h(304) : error C2059: syntax error : 'type'
    include\ffi.h(304) : error C2059: syntax error : ')'
    include\ffi.h(305) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(305) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(305) : error C2059: syntax error : ')'
    include\ffi.h(433) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(433) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(434) : error C2146: syntax error : missing ';' before identifier 'abi'
    include\ffi.h(435) : error C2059: syntax error : 'type'
    include\ffi.h(437) : error C2059: syntax error : ')'
    include\ffi.h(439) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(439) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(440) : error C2146: syntax error : missing ';' before identifier 'abi'
    include\ffi.h(441) : error C2059: syntax error : 'type'
    include\ffi.h(444) : error C2059: syntax error : ')'
    include\ffi.h(446) : error C2143: syntax error : missing ')' before '*'
    include\ffi.h(446) : error C2143: syntax error : missing '{' before '*'
    include\ffi.h(447) : error C2059: syntax error : 'type'
    ../include\ffi_common.h(81) : error C2143: syntax error : missing ')' before '*'
    ../include\ffi_common.h(81) : error C2143: syntax error : missing '{' before '*'
    ../include\ffi_common.h(81) : error C2059: syntax error : ')'
    ../include\ffi_common.h(82) : error C2143: syntax error : missing ')' before '*'
    ../include\ffi_common.h(82) : error C2143: syntax error : missing '{' before '*'
    ../include\ffi_common.h(83) : error C2059: syntax error : 'type'
    ../include\ffi_common.h(83) : error C2059: syntax error : ')'
    ../include\ffi_common.h(88) : error C2016: C requires that a struct or union has at least one member
    ../include\ffi_common.h(88) : error C2061: syntax error : identifier 'ffi_cif'
    ../include\ffi_common.h(91) : error C2059: syntax error : '}'
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\stdlib.h(235) : error C2081: 'uintptr_t' : name in formal parameter list illegal
    ../src/prep_cif.c(107) : error C2143: syntax error : missing ')' before '*'
    ../src/prep_cif.c(107) : error C2143: syntax error : missing '{' before '*'
    ../src/prep_cif.c(107) : error C2146: syntax error : missing ';' before identifier 'abi'
    ../src/prep_cif.c(108) : error C2059: syntax error : 'type'
    ../src/prep_cif.c(111) : error C2059: syntax error : ')'
    ../src/prep_cif.c(226) : error C2143: syntax error : missing ')' before '*'
    ../src/prep_cif.c(226) : error C2143: syntax error : missing '{' before '*'
    ../src/prep_cif.c(226) : error C2146: syntax error : missing ';' before identifier 'abi'
    ../src/prep_cif.c(226) : error C2059: syntax error : 'type'
    ../src/prep_cif.c(227) : error C2059: syntax error : ')'
    ../src/prep_cif.c(232) : error C2143: syntax error : missing ')' before '*'
    ../src/prep_cif.c(232) : error C2143: syntax error : missing '{' before '*'
    ../src/prep_cif.c(233) : error C2146: syntax error : missing ';' before identifier 'abi'
    ../src/prep_cif.c(234) : error C2059: syntax error : 'type'
    ../src/prep_cif.c(237) : error C2059: syntax error : ')'
    libtool: compile: mv -f "prep_cif.obj" "src/.libs/prep_cif.obj"
    mv: cannot stat 'prep_cif.obj': No such file or directory
    Makefile:1362: ошибка выполнения рецепта для цели <src/prep_cif.lo>
    make[2]: *** [src/prep_cif.lo] Ошибка 1
    make[2]: выход из каталога </cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64>
    Makefile:1596: ошибка выполнения рецепта для цели <all-recursive>
    make[1]: *** [all-recursive] Ошибка 1
    make[1]: выход из каталога </cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64>
    Makefile:730: ошибка выполнения рецепта для цели <all>
    make: *** [all] Ошибка 2
    -----------------------------------------------------------------------------
    what to do - replace symlink by real file.

4) if you forgot to comment FFI_TARGET_HAS_COMPLEX_TYPE
    -----------------------------------------------------------------------------
    ../src/types.c(101) : error C2061: syntax error : identifier '_Complex'
    ../src/types.c(101) : error C2059: syntax error : '}'
    ../src/types.c(101) : error C2065: '_Complex' : undeclared identifier
    ../src/types.c(101) : error C2143: syntax error : missing ')' before 'type'
    ../src/types.c(101) : error C2059: syntax error : ')'
    ../src/types.c(102) : fatal error C1903: unable to recover from previous error(s); stopping compilation
    libtool: compile: mv -f "types.obj" "src/.libs/types.obj"
    mv: cannot stat 'types.obj': No such file or directory
    Makefile:1362: ошибка выполнения рецепта для цели <src/types.lo>
    make[2]: *** [src/types.lo] Ошибка 1
    make[2]: выход из каталога </cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64>
    Makefile:1596: ошибка выполнения рецепта для цели <all-recursive>
    make[1]: *** [all-recursive] Ошибка 1
    make[1]: выход из каталога </cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64>
    Makefile:730: ошибка выполнения рецепта для цели <all>
    make: *** [all] Ошибка 2
    -----------------------------------------------------------------------------




    what to do - comment FFI_TARGET_HAS_COMPLEX_TYPE

5) if you forgot to replace replace two 'jmp short' to 'jmp'
    -----------------------------------------------------------------------------
    ml64 -nologo  -c  ./win64.asm
     Assembling: ./win64.asm
    ./win64.asm(1029) : error A2075:jump destination too far : by 20 byte(s)
    ./win64.asm(1038) : error A2075:jump destination too far : by 1 byte(s)
    Makefile:1338: ошибка выполнения рецепта для цели <src/x86/win64.lo>
    make[2]: *** [src/x86/win64.lo] Ошибка 1
    make[2]: выход из каталога </cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64>
    Makefile:1596: ошибка выполнения рецепта для цели <all-recursive>
    make[1]: *** [all-recursive] Ошибка 1
    make[1]: выход из каталога </cygdrive/d/tmp/libraries/libffi-3.2.1/build-x64>
    Makefile:730: ошибка выполнения рецепта для цели <all>
    make: *** [all] Ошибка 2
    -----------------------------------------------------------------------------
    what to do - replace two 'jmp short' to 'jmp'
.

6 comments:

  1. Hi I'm in the process of building libffi under Windows using MSVC 2015 following your indications (really, thanks for sharing your tips, very helpful!).

    Unfortunately I cannot get rid of the problem specified at point 1). I still get the C++ preprocessor failure:
    checking how to run the C++ preprocessor... /lib/cpp
    configure: error: in `/cygdrive/c/Users/alex/Documents/libffi-3.2.1/build-x86':
    configure: error: C++ preprocessor "/lib/cpp" fails sanity check
    See `config.log' for more details

    I'm pretty sure I'm NOT using cygwin64, since I don't even have that target version installed. Anyway, from process manager I can clearily see the bash.exe (32 bit version) running.

    Do you have any tip to help me solve this issue?
    Thanks in advance,
    Alex

    ReplyDelete
    Replies
    1. "C++ preprocessor failure" means it can't find the path to cl.exe, to make it know you must do something like: export PATH=$PATH:'C:\ path to cl.exe here' before 'configure' command.

      Delete
    2. This comment has been removed by the author.

      Delete
    3. This happens because the command line for configure specifies what to use for the C preprocessor (CPP=...) but does not specify what to use for the C++ preprocessor. The variable is supposed to be CXX and can be the same as CPP, i.e. CXX="cl -nologo -EP", which is a way to run the MS compiler as a preprocessor (the -EP flag, that is; -nologo is just a sliencer).

      Delete
    4. Sorry, the wrong variable name for C++ preprocessor: it must be CXXCPP="cl -nologo -EP"

      Delete