如何使用mingw32在cygwin下构建和测试libffi?

如何使用mingw32在cygwin下构建和测试libffi?,cygwin,expect,autoconf,mingw32,libffi,Cygwin,Expect,Autoconf,Mingw32,Libffi,检查(最新)标签v3.2.1后: % sh autogen.sh % ./configure CC=i686-pc-mingw32-gcc % make check 所有测试似乎都失败了 使用CC=gcc,测试似乎工作正常。不幸的是,我需要生成的构建没有cygwin依赖项,因为我正在构建一个JNI DLL。我尝试使用MSYS2环境和mingw-w64构建libffi,但我遇到了同样的问题: a)当我运行make check时,所有测试似乎都失败了 b)当我试图用-lffi编译libffiHel

检查(最新)标签v3.2.1后:

% sh autogen.sh
% ./configure CC=i686-pc-mingw32-gcc
% make check
所有测试似乎都失败了


使用CC=gcc,测试似乎工作正常。不幸的是,我需要生成的构建没有cygwin依赖项,因为我正在构建一个JNI DLL。

我尝试使用MSYS2环境和
mingw-w64
构建
libffi
,但我遇到了同样的问题:

a)当我运行
make check时,所有测试似乎都失败了

b)当我试图用
-lffi
编译
libffi
Hello World示例时, 链接器抱怨未解析对所有ffi相关符号的引用(这些符号确实包含在
libffi.a
中,但可能由于循环依赖关系和对象文件的顺序,链接器无法收集所有符号)

幸运的是,如果我删除
-lffi
,而是包含libffi
make
操作创建的所有对象文件(
*.o
),则创建的可执行文件运行正常

下面是我使用的libffi Hello World示例的链接:

[编辑]

经过一些额外的实验后,我成功地编译了这个程序,用
-Wl、-whole-archive、-lffi、-no-whole-archive
替换了
-lffi
。这样,链接器将包括
libffi.a
中的所有对象文件,所有内容都可以正常工作

下面是Hello World示例(
Hello.c
)以及我使用的详细步骤,以防有人发现这些信息有用:

/*
 * Steps for building libffi on Windows and running this Hello World example:
 *
 * 1. Download and install the latest version of MSYS2
 *    a) download the latest (64-bit or 32-bit) installer from http://msys2.github.io
 *    b) run the installer accepting default settings
 *    c) execute the following commands to update the system core
 *        pacman -Sy pacman
 *        pacman -Syu
 *        pacman -Su
 *    d) restart MSYS2, if requested to do so
 *    e) execute the following command to install development tools
 *       for 64-bit gcc:
 *        pacman --needed -S base-devel dejagnu mingw-w64-x86_64-gcc
 *       for 32-bit gcc:
 *        pacman --needed -S base-devel dejagnu mingw-w64-i686-gcc
 *    f) restart MSYS2
 * 2. Download and compile the latest version of libffi
 *    a) download the latest source code bundle from https://github.com/libffi/libffi/releases
 *    b) unpack the source code bundle in MSYS2 tmp directory (e.g. C:\msys64\tmp)
 *    c) execute the following MSYS2 commands to compile libffi (adapt the version number):
 *        cd /tmp/libffi-3.2.1
 *        ./autogen.sh
 *        ./configure --prefix=/tmp/out --enable-static --disable-shared
 *        make
 *    d) optionally, execute the following command to run the tests:
 *        make check
 *    e) copy the distributable files to the configured /tmp/out directory
 *        make install
 *       the following files are needed for the next step:
 *        /tmp/out/lib/libffi.a
 *        /tmp/out/lib/libffi-3.2.1/include/ffi.h
 *        /tmp/out/lib/libffi-3.2.1/include/ffitarget.h
 * 3. Compile this example
 *    a) copy this file to MSYS2 tmp directory (e.g. C:\msys64\tmp\hello.c)
 *    b) execute the following MSYS2 command to compile the example:
 *        gcc -I /tmp/out/lib/libffi-3.2.1/include -L /tmp/out/lib -lffi -o /tmp/hello /tmp/hello.c
 *    c) run the example (/tmp/hello.exe), the output should be:
 *        Hello World!
 *
 * Troubleshooting
 *
 * If the tests seem to fail and the compilation in step 3b) above reports undefined references to 'ffi_*' symbols,
 * try compiling using the following command instead:
 *        gcc -I /tmp/out/lib/libffi-3.2.1/include -L /tmp/out/lib -Wl,--whole-archive,-lffi,--no-whole-archive -o /tmp/hello /tmp/hello.c
 * Another alternative is to try linking the original libffi object files (*.o) and drop -lffi as follows:
 * For 64-bit version:
 *        export SRC=/tmp/libffi-3.2.1/x86_64-w64-mingw32/src
 *        gcc -I /tmp/out/lib/libffi-3.2.1/include -o /tmp/hello /tmp/hello.c $SRC/prep_cif.o $SRC/types.o $SRC/raw_api.o $SRC/java_raw_api.o $SRC/closures.o $SRC/x86/ffi.o $SRC/x86/win64.o
 * For 32-bit version:
 *        export SRC=/tmp/libffi-3.2.1/i686-w64-mingw32/src
 *        gcc -I /tmp/out/lib/libffi-3.2.1/include -o /tmp/hello /tmp/hello.c $SRC/prep_cif.o $SRC/types.o $SRC/raw_api.o $SRC/java_raw_api.o $SRC/closures.o $SRC/x86/ffi.o $SRC/x86/win32.o
 */

#include <stdio.h>
#include <ffi.h>

/* Acts like puts with the file given at time of enclosure */
void puts_binding(ffi_cif* cif, void* ret, void* args[], void* stream) {
  *(ffi_arg*) ret = fputs(*(char**) args[0], (FILE*) stream);
}

typedef int (*puts_t)(char*);

int main() {
  ffi_cif cif; /* The call interface */
  ffi_type* args[1]; /* The array of pointers to function argument types */
  ffi_closure* closure; /* The allocated closure writable address */
  void* bound_puts; /* The allocated closure executable address */
  int rc; /* The function invocation return code */

  /* Allocate closure (writable address) and bound_puts (executable address) */
  closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);

  if (closure) {
    /* Initialize the array of pointers to function argument types */
    args[0] = &ffi_type_pointer;

    /* Initialize the call interface describing the function prototype */
    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_sint, args) == FFI_OK) {
      /* Initialize the closure, setting stream to stdout */
      if (ffi_prep_closure_loc(closure, &cif, puts_binding, stdout, bound_puts) == FFI_OK) {
        rc = ((puts_t) bound_puts)("Hello World!");
        /* rc now holds the result of the call to fputs */
      }
    }
  }

  /* Deallocate both closure, and bound_puts */
  ffi_closure_free(closure);

  return 0;
}
/*
*在Windows上构建libffi并运行此Hello World示例的步骤:
*
* 1. 下载并安装最新版本的MSYS2
*a)从下载最新(64位或32位)安装程序http://msys2.github.io
*b)运行接受默认设置的安装程序
*c)执行以下命令以更新系统核心
*吃豆人
*pacman-Syu
*pacman-Su
*d)如有要求,重新启动MSYS2
*e)执行以下命令以安装开发工具
*对于64位gcc:
*pacman--需要-S base devel dejagnu mingw-w64-x86_64-gcc
*对于32位gcc:
*pacman--需要-S base-dejagnu mingw-w64-i686-gcc
*f)重新启动MSYS2
* 2. 下载并编译libffi的最新版本
*a)从下载最新的源代码包https://github.com/libffi/libffi/releases
*b)在MSYS2 tmp目录中解包源代码包(例如C:\msys64\tmp)
*c)执行以下MSYS2命令编译libffi(调整版本号):
*cd/tmp/libffi-3.2.1
*/autogen.sh
*./configure--prefix=/tmp/out--enable static--disable shared
*制造
*d)可选地,执行以下命令以运行测试:
*核对
*e)将可分发文件复制到配置的/tmp/out目录
*安装
*下一步需要以下文件:
*/tmp/out/lib/libffi.a
*/tmp/out/lib/libffi-3.2.1/include/ffi.h
*/tmp/out/lib/libffi-3.2.1/include/ffitarget.h
* 3. 编译这个例子
*a)将此文件复制到MSYS2 tmp目录(例如C:\msys64\tmp\hello.C)
*b)执行以下MSYS2命令来编译示例:
*gcc-I/tmp/out/lib/libffi-3.2.1/include-L/tmp/out/lib-lffi-o/tmp/hello/tmp/hello.c
*c)运行示例(/tmp/hello.exe),输出应为:
*你好,世界!
*
*故障排除
*
*如果测试似乎失败,并且上述步骤3b)中的编译报告了对“ffi_*”符号的未定义引用,
*请尝试使用以下命令进行编译:
*gcc-I/tmp/out/lib/libffi-3.2.1/include-L/tmp/out/lib-Wl,--整个归档,-lffi,--没有整个归档-o/tmp/hello/tmp/hello.c
*另一种方法是尝试链接原始libffi对象文件(*.o)和drop-lffi,如下所示:
*对于64位版本:
*导出SRC=/tmp/libffi-3.2.1/x86_64-w64-mingw32/SRC
*gcc-I/tmp/out/lib/libffi-3.2.1/include-o/tmp/hello/tmp/hello.c$SRC/prep_cif.o$SRC/types.o$SRC/raw_api.o$SRC/java_raw_api.o$SRC/closures.o$SRC/x86/ffi.o$SRC/x86/win64.o
*对于32位版本:
*导出SRC=/tmp/libffi-3.2.1/i686-w64-mingw32/SRC
*gcc-I/tmp/out/lib/libffi-3.2.1/include-o/tmp/hello/tmp/hello.c$SRC/prep_cif.o$SRC/types.o$SRC/raw_api.o$SRC/java_raw_api.o$SRC/closures.o$SRC/x86/ffi.o$SRC/x86/win32.o
*/
#包括
#包括
/*其行为类似于封装时给定文件的puts*/
void puts_绑定(ffi_cif*cif,void*ret,void*args[],void*stream){
*(ffi_arg*)ret=fputs(*(char**)args[0],(FILE*)流;
}
typedef int(*puts_t)(字符*);
int main(){
ffi_cif cif;/*调用接口*/
ffi_type*args[1];/*指向函数参数类型的指针数组*/
ffi_closure*closure;/*分配的closure可写地址*/
void*bound_put;/*分配的闭包可执行文件地址*/
int rc;/*函数调用返回代码*/
/*分配闭包(可写地址)和绑定输出(可执行地址)*/
闭包=ffi_闭包_alloc(sizeof(ffi_闭包)&绑定看跌期权);
若有(关闭){
/*初始化指向函数参数类型的指针数组*/
args[0]=&ffi\u类型\u指针;
/*初始化描述函数原型的调用接口*/
如果(ffi_prep_cif(&cif,ffi_DEFAULT_ABI,1,&ffi_type_sint,args)=ffi_OK){
/*初始化闭包,将流设置为标准输出*/
如果(ffi\u准备\u关闭\u loc(关闭,&cif,puts\u绑定,标准输出,绑定\u puts)=ffi\u确定){
rc=((puts_t)bound_puts)(“你好,世界!”);
/*rc现在保存对fputs调用的结果*/
}
}
}
/*取消分配闭包和绑定的\u put*/
外国金融机构自由关闭(关闭);
返回0;
}
可能:)将进行编辑。