在Windows下用MinGW编译OpenSSL,及OpenSSL静态链接库libcrypto.a使用问题

时间:2021-01-17 13:10:07

最经我用MinGW编译OpenSSL的过程中发生了很多问题,不过好在已经解决了,现在写出来以备查询

 

以OpenSSL-0.9.8l为例:

前略(下载,解压)注意要安装Perl,如果你只是用来安装OpenSSL的可以下ActivePerl,以后还有其它用的下strawberry-perl

 

(先说问题)

使用MinGW编译OpenSSL时我发现有以下问题

1、解压目录/ms/mingw32.bat内的路径有问题,直接使用会报找不到文件

2、编译过程中报错(内容如下)

./crypto/des/set_key.c:68: error: static declaration of '_hide_DES_check_key' follows non-static declaration ./crypto/des/set_key.c:68: error: previous declaration of '_hide_DES_check_key' was here
mingw32-make: *** [tmp/set_key.o] Error 1

3、其它编译问题(我没有遇到,不过似乎官方有准备)

4、使用静态链接库libcrypto.a时

libcrypto.a(rand_win.o)(.text+0xb13):rand_win.c: undefined reference to '_CreateDCA@16'

libcrypto.a(rand_win.o)(.text+0xb24):rand_win.c: undefined reference to '_CreateCompatibleDC@4'

 

等错误

 

解决法案:

一、解决这一种问题方法是将mingw32.bat从 解压目录/ms 下面复制回 解压目录 下面,即将mingw32.bat放在解压后的OpenSSL的根目录下

二、编译过程中出现上述的报错,问题出在 解压目录/e_os2.h 中:264行

# define OPENSSL_IMPLEMENT_GLOBAL(type,name) /
extern type _hide_##name; /
type *_shadow_##name(void) { return &_hide_##name; } /
static type _hide_##name

其中的static修饰,解决方法有两个:

1、将static修饰删了,不过这样可能会改变原来作者的意图

2、这个方法有点麻烦需要修改 解压目录/e_os2.h 解压目录/crypto/des/enc_read.c 解压目录/crypto/des/set_key.c这三个文件

=======================================================================================

解压目录/e_os2.h:

定位第255行(参照句出现的行号,并非需要修改的直接行号)做如下操作,每行前的 - 号代表删除行,+ 号代表添加行:

    The way it's done allows definitions like this:
  
       // in foobar.c

-    OPENSSL_IMPLEMENT_GLOBAL(int,foobar) = 0;

+   OPENSSL_IMPLEMENT_GLOBAL(int,foobar,0)
       // in foobar.h
       OPENSSL_DECLARE_GLOBAL(int,foobar);
       #define foobar OPENSSL_GLOBAL_REF(foobar)
   */
       #ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION
-     # define OPENSSL_IMPLEMENT_GLOBAL(type,name)                 /
-        extern type _hide_##name;                     /
-        type *_shadow_##name(void) { return &_hide_##name; }         /
-        static type _hide_##name
+    # define OPENSSL_IMPLEMENT_GLOBAL(type,name,value)            /
+       type *_shadow_##name(void)                    /
+      { static type _hide_##name=value; return &_hide_##name; }
      # define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void)
      # define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name()))
      #else
-     # define OPENSSL_IMPLEMENT_GLOBAL(type,name) OPENSSL_GLOBAL type _shadow_##name
+    # define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) OPENSSL_GLOBAL type _shadow_##name=value
      # define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name
      # define OPENSSL_GLOBAL_REF(name) _shadow_##name
      #endif

=======================================================================================

解压目录/crypto/des/enc_read.c

定位第64行(参照句出现的行号,并非需要修改的直接行号)做如下操作,每行前的 - 号代表删除行,+ 号代表添加行:

    /* This has some uglies in it but it works - even over sockets. */
    /*extern int errno;*/
-   OPENSSL_IMPLEMENT_GLOBAL(int,DES_rw_mode)=DES_PCBC_MODE;
+  OPENSSL_IMPLEMENT_GLOBAL(int,DES_rw_mode,DES_PCBC_MODE);

=======================================================================================

解压目录/crypto/des/set_key.c

定位第66行(参照句出现的行号,并非需要修改的直接行号)做如下操作,每行前的 - 号代表删除行,+ 号代表添加行:

    #include "des_locl.h"

    #ifdef OPENSSL_FIPS
    #include <openssl/fips.h>
    #endif


-   OPENSSL_IMPLEMENT_GLOBAL(int,DES_check_key);    /* defaults to false */
+  OPENSSL_IMPLEMENT_GLOBAL(int,DES_check_key,0);    /* defaults to false */

=======================================================================================

三、至于其它编译问题(不是上面的问题,至于是什么问题,我不知道,因为我没有出现过)官方给出的解决办法是,在执行mingw32.bat时添加no-asm参数,即在控制台先执行(转到根目录,或者将根目录添加到 环境变量 中去)

mingw32 no-asm

四、这是因为libcrypto.a需要静态链接Gdi32.lib(libgdi32.a),直接添加Gdi32.lib或libgdi32.a就可以了(一定要添加在libcrypto.a后面,即-I libcrypto.a -I libgdi32.a),使用dllwrap的也可以直接添加-lgdi32参数,使用Code::Blocks的在链接器设置(Linker Setting)->链接库(link libraries)的libcrypto.a下方添加libgdi32.a

 

P.S MinGW(GCC)中没有VC中的#pragma comment预处理命令,它只能用执行参数-I 来添加静态或导入库