百度空间 | 百度首页 
               
 
查看文章
 
编译Windows版本的GNU工具——VC篇
2008-12-22 20:14
编译Windows版本的GNU工具

tombkeeper@xfocus
2004.3.23


算不得技术文章,只是过程颇有曲折,写个step by step出来备忘,省得下次从头再来。

一开始只打算折腾几种软件,后来逐渐目标多了,有些软件也不是GNU的,继续用这个标题就有不实之嫌。不过没关系,就当它是GNU的好了。其实,我一直认为Windows都是GNU的。


下载地址:
http://www.openssl.org/source/openssl-0.9.7d.tar.gz
http://curl.haxx.se/download/curl-7.11.1.tar.gz
http://ftp.gnu.org/pub/gnu/wget/wget-1.9.1.tar.gz
http://www.gzip.org/zlib/zlib-1.2.1.tar.gz
ftp://wuarchive.wustl.edu/mirrors/gnu/gzip/gzip-1.2.4.tar.gz
ftp://sources.redhat.com/pub/bzip2/v102/bzip2-1.0.2.tar.gz
http://ftp.cvshome.org/release/stable/cvs-1.11.14/cvs-1.11.14.tar.bz2
ftp://ftp19.us.postgresql.org/pub/postgresql/source/v7.4.2/postgresql-7.4.2.tar.gz
http://www.stunnel.org/download/stunnel/src/stunnel-4.05.tar.gz
http://the.earth.li/~sgtatham/putty/latest/putty-src.zip

准备编译环境:
要确定系统上安装了VC 6以上版本、masm32、Win32版本MingW的gcc、perl、cygwin。并且相应的path、include、lib等环境变量都设置好了,注意在“include”变量中把openssl的include目录加进去。如果不打算用汇编编译openssl也可以不装masm32。

要编译支持https的wget和curl就需要openssl的,所以要先编译openssl。


编译openssl及静态链接库:
========================
编译openssl自身的可执行文件最好是用masm32 + VC,所以在命令提示符中顺序键入:

perl Configure VC-WIN32
ms\do_masm.bat

完成后,就可以在out32目录中找到libeay32.lib和ssleay32.lib,现在把这两个库复制到编译环境的lib目录中去。

如果要用MingW来产生静态库,那么不能相信openssl的install.w32文件里面说的,用那个ms\mingw32.bat能编译成功。指望在命令提示符下用Win32版本的MingW编译openssl是不现实的,倒不是编译器的问题,主要是编译脚本中的那些unix命令一般的windows系统上是没有的。而且,里面用的那些符号链接之类,Windows也不支持。一定要的Cygwin环境下才能顺当。

顺序输入以下命令:
tar zxf openssl-0.9.7d.tar.gz
cd openssl-0.9.7d
./Configure mingw
make

现在我们就有了libcrypto.a和libssl.a这两个静态链接库。

编译wget:
=========
Windows版本的wget在键入--help参数的时候总是试图打开wget.hlp,非常讨厌,在编译之前,先打开src\main.c,注释掉这一行:

ws_help (exec_name);

还要注释掉src\mswindows.c中的ws_help函数。

Wget提交的请求特征比较明显,服务器可以很容易分辨出来。下面将其尽量修改得接近于IE 6.0。
打开src\http.c,找到下面这段代码:
else
    {
      useragent = (char *)alloca (10 + strlen (version_string));
      sprintf (useragent, "Wget/%s", version_string);
    }
修改为
else
    {
      STRDUP_ALLOCA (useragent,"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
    }
   
找到:
#define HTTP_ACCEPT "*/*"

修改为:
#define HTTP_ACCEPT "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, \
application/x-shockwave-flash, application/vnd.ms-powerpoint, \
application/vnd.ms-excel, application/msword, */*"

找到“ sprintf (request, "\”的那一段,修改为:
sprintf (request, "\
%s %s HTTP/1.0\r\n\
Accept: %s\r\n\
User-Agent: %s\r\n\
Host: %s%s%s%s\r\n\
%s%s%s%s%s%s%s%s%s%s\r\n",
       command, full_path,
       HTTP_ACCEPT,
       useragent,
       squares_around_host ? "[" : "", u->host, squares_around_host ? "]" : "",
       port_maybe ? port_maybe : "",
       request_keep_alive ? request_keep_alive : "",
       referer ? referer : "",
       cookies ? cookies : "",
       wwwauth ? wwwauth : "",
       proxyauth ? proxyauth : "",
       range ? range : "",
       pragma_h,
       post_content_type ? post_content_type : "",
       post_content_length ? post_content_length : "",
       opt.user_header ? opt.user_header : "");

在命令提示符中输入:

configure.bat --msvc

然后修改src\Makefile文件,将CFLAGS中的“/MT”改为“/MD”,在DEFS中增加“/DHAVE_STRPBRK”并在LIBS里加上“gdi32.lib”,然后运行nmake。

如果要使用MingW编译出来的静态库就需要将刚才编译的libssl.a libcrypto.a以及MingW目录下lib\gcc-lib\mingw32\2.95.3-8\libgcc.a复制到src目录,再nmake。

编译curl:
=========
curl依赖于zlib,所以要先编译zlib:

nmake -f win32/Makefile.msc

我们就得到了zlib.lib这个静态链接库。

然后修改curl的src和lib两个目录下的Makefile.vc6文件,在里面分别先设置好正确的OPENSSL_PATH和ZLIB_PATH,src目录下的Makefile.vc6文件中也要加上OPENSSL_PATH的定义(curl-7.13.1之后的版本已经没有这个问题了)。并在src目录下的Makefile.vc6文件的cl.exe参数中加上/DUSE_MANUAL,还可以curlr.res相关的内容去掉。

因为我们定义了USE_MANUAL,但是,curl的hugehelp.c文件中包含的相关文档是西文编码的,在中文系统上显示有问题,按照以下方法处理:
1、用IE打开hugehelp.c,另存为一个文本文件的时候选择GB2312编码。
2、在新的hugehelp.c中删除所有“­”。然后就可以替换src目录下的老hugehelp.c。
(curl-7.13.1之后的版本已经没有这个问题了)

下面修改curl的默认User-Agent,找到main.c中的:
if(NULL == config->useragent) {
    /* set non-zero default values: */
    snprintf(useragent, sizeof(useragent),
             CURL_NAME "/" CURL_VERSION " (" OS ") " "%s", curl_version());
    config->useragent= useragent;
}

修改为:
if(NULL == config->useragent) {
    /* set non-zero default values: */
    snprintf(useragent, sizeof(useragent),
             "%s", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
    config->useragent= useragent;
}

打开lib\http.c,找到:
    http->p_accept = "Accept: */*\r\n";

修改为:
    http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, \
image/pjpeg, application/x-shockwave-flash, application/vnd.ms-powerpoint, \
application/vnd.ms-excel, application/msword, */*\r\n";

然后开始编译:
nmake vc-ssl

就得到curl.exe了


编译gzip:
=========
编译之前,将gzip.h、util.c、gzip.c中的“strlwr”替换为“mystrlwr”。因为gzip是在linux
上开发的,可能开发人员没想到windows上本身就有一个名为strlwr的函数。

然后,nmake -f nt\Makefile就可以了。

如果不想链接msvcrt.dll,可以修改nt\Makefile,在!include <ntwin32.mak>后加上:
cc      =   cl.exe
link    =   link.exe
DEFS    =   -DWIN32
cflags =   -c -O2 -nologo
cvarsdll    =
linkdebug   =
conflags    =   -nologo -release
conlibsdll =
还要删除下面的“DEFS =”,否则我们定义的-DWIN32就没了。


编译bzip2:
==========
没有任何障碍,直接运行“nmake -f makefile.msc”。

Windows版本的MackFile默认不会产生bunzip2.exe,不过bunzip2和bzip2的区别只是文件名不同,程序检测到自己文件名是bunzip2的时候,默认就执行解压缩操作而已。所以我们可以自己拷贝出一个bunzip2.exe。


编译cvs:
========
没有任何障碍,直接运行“nmake -f cvsnt.mak CFG="cvsnt - Win32 Release"”


编译postgresql客户端:
=====================
修改src\bin\psql\win32.mak,将
    "..\..\interfaces\libpq\Release\libpqdll.lib"
修改为
    "..\..\interfaces\libpq\Release\libpq.lib"
然后运行在src\目录下运行nmake -f win32.mak就可以得到静态版本的psql.exe。


编译stunnel:
============
stunnel自己带的makefile是用gcc的,不过在和上面用gcc编译好的静态ssl库链接时有问题。好在stunnel的程序员很照顾我,代码都是ANSI C,可以不出任何问题地用VC编译。先把libeay32.lib和ssleay32.lib拷贝到src目录,然后用下面这些命令:

cl -DUSE_WIN32 -DHAVE_OPENSSL -c stunnel.c
cl -DUSE_WIN32 -DHAVE_OPENSSL -c ssl.c
cl -DUSE_WIN32 -DHAVE_OPENSSL -c client.c
cl -DUSE_WIN32 -DHAVE_OPENSSL -c protocol.c
cl -DUSE_WIN32 -DHAVE_OPENSSL -c sthreads.c
cl -DUSE_WIN32 -DHAVE_OPENSSL -c log.c
cl -DUSE_WIN32 -DHAVE_OPENSSL -c options.c
cl -DUSE_WIN32 -DHAVE_OPENSSL -c sselect.c
cl -DUSE_WIN32 -DHAVE_OPENSSL -c gui.c

rc resources.rc

link -out:stunnel.exe ws2_32.lib gdi32.lib user32.lib shell32.lib comdlg32.lib libeay32.lib ssleay32.lib stunnel.obj ssl.obj client.obj protocol.obj sthreads.obj log.obj options.obj sselect.obj gui.obj resources.res


编译putty:
==========
Putty是一个很不错的SSH客户端,源代码下载后直接用VC的IDE界面打开编译,没有任何问题。

对Putty的改造主要是针对配置信息的。Putty将Session、SSH Host Key等信息都保存在注册表中,我们需要让它全部保存到配置文件中去。

配置文件相关的函数是源代码目录下的WINDOWS\WINSTORE.C,Refdom曾经对这下面的函数进行了改写,将对注册表的操作转换为对配置文件的操作。但是配置文件会被保存在当前目录下而不是程序所在的目录。


在WINDOWS\WINSTORE.C中加上:
extern char SessionsFile[MAX_PATH+2];
extern char SshHostKeysFile[MAX_PATH+2];

并修改其余代码,将这两个文件作为保存Session和SSH Host Key的配置文件。

打开WINDOWS\WINDOW.C,在文件前面添加:

#define SESSIONSFILE    "Sessions.ini"
#define SSHHOSTKEYSFILE "SshHostKeys.ini"
char SessionsFile[MAX_PATH+2];
char SshHostKeysFile[MAX_PATH+2];

找到WinMain函数中的这段代码:
        strcpy(r, PUTTY_HELP_CONTENTS);
        if ( (fp = fopen(b, "r")) != NULL) {
            help_has_contents = TRUE;
            fclose(fp);
        } else
            help_has_contents = FALSE;

在之后添加:
        strcpy(r, SESSIONSFILE);
        strcpy(SessionsFile, b);
        strcpy(r, SSHHOSTKEYSFILE);
        strcpy(SshHostKeysFile, b);


然后编译,就可以得到一个把配置信息保存在自身所在目录下的Putty.exe。

以上修改仅针对Putty相关代码,并不会对PLink、PSftp等生效。


 
网友评论:
1
2008-12-22 21:49 | 回复
谢谢了,以前弄了几个。 我怎么老是点tK呢,哈呵~
 
2
2008-12-23 19:54 | 回复
Windows的确是gnu的啊
 
3
2009-02-06 10:33 | 回复
TK 教主,能把你编译出来的Windows版本的GNU工具 共享一下吗?十分感谢啦!
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu