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'
.

4 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