zoukankan      html  css  js  c++  java
  • VC++编译zlib

    1简介    1

    2版本1.2.3    2

    2.1 编译汇编代码    2

    2.1.1 32位汇编    2

    2.1.2 64位汇编    5

    2.2 Visual C++ 6.0    5

    2.2.1 编译配置项    6

    2.2.2 ASMVASMINF    6

    2.2.3 排除编译    8

    2.2.4 自定义编译    8

    2.3 Visual C++ 2002    9

    2.3.1 编译配置项    10

    2.3.2 ASMVASMINF    11

    2.3.3 排除编译    11

    2.3.4 嵌入汇编obj文件    11

    2.4 Visual C++ 2005    12

    2.4.1 编译配置项    12

    2.4.2 ASMVASMINF    13

    2.4.3 排除编译    13

    2.4.4 嵌入汇编obj文件    13

    2.5 ZLIB_WINAPI    14

    3版本1.2.8    15

    3.1 编译汇编代码    15

    3.1.1 编译    15

    3.2 使用Visual C++编译    15

    3.2.1 编译前事件    16

    1简介

    zlib是一个用于解压缩的开源C函数库。很多项目(如libpng)会用到它。

    它的下载网址如下:

    http://sourceforge.net/projects/libpng/files/zlib/

    本文对zlib自带的Visual C++项目进行解析。

    2版本1.2.3

    2.1 编译汇编代码

    版本1.2.3里,为了提高解压缩效率,函数inflate_fastlongest_match用汇编代码实现了。这两个函数有三个版本,如下表所示:

    C

    ASM x86

    ASM x64

    inflate_fast

    inffast.c

    inffas32.asm

    inffas8664.c

    inffasx64.asm

    longest_match

    deflate.c

    gvmat32c.c

    gvmat32.asm

    gvmat64.asm

    具体情况为:

    函数inflate_fastinffast.c里有一份实现它的C代码;在inffas32.asm里有一份实现它的32位汇编代码;在inffas8664.c里会调用函数inffas8664fnc,而后者在文件inffasx64.asm里由64位汇编代码实现。

    函数longest_matchdeflate.c里有一份实现它的C代码;在gvmat32c.c里会调用函数longest_match_7ffflongest_match_686,而这两个函数在文件gvmat32.asm里由32位汇编代码实现;在gvmat64.asm里有一份实现它的64位汇编代码。

    简而言之就是:

    不用汇编代码,需要编译inffast.cdeflate.c

    使用32位汇编代码,需要编译inffas32.asmgvmat32c.cgvmat32.asm

    使用64位汇编代码,需要编译inffas8664.cinffasx64.asmgvmat64.asm

    *.c文件在Visual C++编译时会自行处理,*.asm文件就需要特别处理了。

    2.1.1 32位汇编

    contribmasmx86目录下的inffas32.asmgvmat32.asm32位的汇编代码。编译后可运行在32位的Windows上,也可运行在兼容x86指令的64Windows上。不能运行在不兼容x86指令的64Windows上(如:CPUItaniumWindows)。

    进入contribmasmx86目录,运行bld_ml32.bat即可编译inffas32.asmgvmat32.asm。文件bld_ml32.bat的内容如下:

    ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm

    ml /coff /Zi /c /Flinffas32.lst inffas32.asm

    它的含义是调用ml.exe,将gvmat32.asminffas32.asm编译生成gvmat32.objinffas32.obj

    ml.exe是微软的宏汇编程序,安装了VC++2002VC++2015ml.exe也同时被安装,它所在的目录如下表所示:

    vc版本

    2002

    C:Program FilesMicrosoft Visual Studio .NETVc7in

     

    2003

    C:Program FilesMicrosoft Visual Studio .NET 2003Vc7in

     

    2005

    C:Program FilesMicrosoft Visual Studio 8VCin

    amd64ml64.exe

    x86_amd64ml64.exe

    2008

    C:Program FilesMicrosoft Visual Studio 9.0VCin

    amd64ml64.exe

    x86_amd64ml64.exe

    2010

    C:Program FilesMicrosoft Visual Studio 10.0VCin

    amd64ml64.exe

    x86_amd64ml64.exe

    2012

    C:Program FilesMicrosoft Visual Studio 11.0VCin

    amd64ml64.exe

    x86_amd64ml64.exe

    2013

    C:Program FilesMicrosoft Visual Studio 12.0VCin

    amd64_x86ml.exe

    amd64ml64.exe

    x86_amd64ml64.exe

    2015

    C:Program FilesMicrosoft Visual Studio 14.0VCin

    amd64_x86ml.exe

    amd64ml64.exe

    x86_amd64ml64.exe

    说明:

    1、从vc2005开始提供了ml64.exe,它用来编译生成64位的汇编代码;

    2、从vc2013开始又提供了amd64_x86ml.exe

    3、两个ml.exe和两个ml64.exe的区别:

    ml.exe                32位程序,编译生成32位的汇编代码;

    amd64_x86ml.exe        64位程序,编译生成32位的汇编代码;

    amd64ml64.exe            64位程序,编译生成64位的汇编代码;

    x86_amd64ml64.exe    32位程序,编译生成64位的汇编代码。

    上述文件夹命名都是有含义的:amd64_x86前面的amd64表示ml.exe64位的,后面的x86表示编译生成的汇编代码是32位的;amd64表示amd64_amd64,即ml.exe和生成的汇编代码都是64位的。

    为了能够正常编译,有两种方法:

    方法一:将ml.exe从相应的目录中复制到bld_ml32.bat所在目录,运行bld_ml32.bat即可;

    方法二:在bld_ml32.bat所在目录创建vc2002.bat,其内容如下:

    %VSCOMNTOOLS%....Vc7inml /coff /Zi /c /Flgvmat32.lst gvmat32.asm

    %VSCOMNTOOLS%....Vc7inml /coff /Zi /c /Flinffas32.lst inffas32.asm

    现在运行vc2002.bat即可调用C:Program FilesMicrosoft Visual Studio .NETVc7inml.exe进行编译。

    VSCOMNTOOLS是一个环境变量,安装vc2002后它被自动添加到系统里,如下图所示:

    同理,还可以创建vc2003.bat

    "%VS71COMNTOOLS%....Vc7inml" /coff /Zi /c /Flgvmat32.lst gvmat32.asm

    "%VS71COMNTOOLS%....Vc7inml" /coff /Zi /c /Flinffas32.lst inffas32.asm

    还可以创建vc2005.bat

    "%VS80COMNTOOLS%....VCinml" /coff /Zi /c /Flgvmat32.lst gvmat32.asm

    "%VS80COMNTOOLS%....VCinml" /coff /Zi /c /Flinffas32.lst inffas32.asm

    经实际测试,vc2002.batvc2003.bat能够正常运行,而vc2005.bat在编译时出错。也就是说ml.exe只能使用vc2002vc2003附带的版本,再高的版本就不行了。

    2.1.2 64位汇编

    contribmasmx64目录下的gvmat64.asminffasx64.asm64位的汇编代码。编译后可运行在64位的Windows上(CPUItaniumWindows例外)。

    进入contribmasmx64目录,运行bld_ml64.bat即可编译gvmat64.asminffasx64.asm。文件bld_ml64.bat的内容如下:

    ml64.exe /Flinffasx64 /c /Zi inffasx64.asm

    ml64.exe /Flgvmat64 /c /Zi gvmat64.asm

    它的含义是调用ml64.exe,将gvmat64.asminffasx64.asm编译生成gvmat64.objinffasx64.obj

    为了能够正常编译,有两种方法:

    方法一:将ml64.exeC:Program FilesMicrosoft Visual Studio 8VCinx86_amd64复制到bld_ml64.bat所在目录,运行bld_ml64.bat即可;

    方法二:在bld_ml64.bat所在目录创建vc2005.bat,其内容如下:

    "%VS80COMNTOOLS%....VCinx86_amd64ml64.exe" /Flinffasx64 /c /Zi inffasx64.asm

    "%VS80COMNTOOLS%....VCinx86_amd64ml64.exe" /Flgvmat64 /c /Zi gvmat64.asm

    现在运行vc2005.bat即可进行编译。

    2.2 Visual C++ 6.0

    使用Visual C++6.0打开projectsvisualc6zlib.dsw,如下图所示。可以看到一共有三个项目:exampleminigzipzlib。前两个项目不用理会,鼠标右键单击zlib,然后单击【Set as Active Project】,设置zlib为活动项目。

    2.2.1 编译配置项

    项目zlib一共有8个编译配置项,如下图所示:

    "Win32 DLL*"表示编译生成动态库;

    "Win32 LIB*"表示编译生成静态库;

    "*Release"表示编译生成Release版,发布程序时使用此版本;

    "*Debug"表示编译生成Debug版,调试程序时使用此版本;

    含有ASM的表示编译时使用汇编代码;

    未含ASM的表示编译时不使用汇编代码。

    2.2.2 ASMVASMINF

    查看zlib的配置,当选中含有ASM的编译配置项时,可以看到宏ASMVASMINF被定义了。如下图所示:

    ASMINF被定义,则inflate_fastC代码被禁用,以下代码节选自inffast.c

    #ifndef ASMINF

    void inflate_fast(strm, start)

    z_streamp strm;

    unsigned start;

    {

    ... ... ...

    }

    #endif /* !ASMINF */

    ASMV被定义,则longest_matchC代码被禁用,以下代码节选自deflate.c

    #ifndef ASMV

    local uInt longest_match(s, cur_match)

    deflate_state *s;

    IPos cur_match;

    {

    ... ... ...

    }

    #endif /* ASMV */

    也就是说:定义宏ASMINF的含义是启用inflate_fast的汇编代码;定义宏ASMV的含义是启用longest_match的汇编代码。

    2.2.3 排除编译

    Visual C++6.0无法编译64位的汇编代码,因此不用管inffas8664.cinffasx64.asmgvmat64.asm这三个文件。

    zlib项目里含有与32位汇编相关的三个文件:gvmat32.asmgvmat32c.cinffas32.asm

    当选中不含ASM的编译配置项时,可以看到这三个文件在编译时是被排除在外的,如下图所示:

    当选中含有ASM的编译配置项时,可以看到这三个文件将参与编译,如下图所示:

    2.2.4 自定义编译

    当选中含有ASM的编译配置项时,可以看到gvmat32.asminffas32.asm是如何被编译的。如下图所示:

    命令如下所示:

    ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)$(InputName).obj" "$(InputPath)"

    因为VC++6.0并不自带ml.exe,因此上述命令执行时将会失败。解决方法:将C:Program FilesMicrosoft Visual Studio .NET 2003Vc7inml.exe复制到C:Program FilesMicrosoft Visual StudioVC98Bin。即将vc2002ml.exe复制到vc6的安装目录。

    2.3 Visual C++ 2002

    使用vc2002打开contribvstudiovc7zlibvc.sln,如下图所示。可以看到一共有五个项目:miniunzminiziptestZlibDllzlibstatzlibvc。前三个项目不用理会,zlibstatzlibvc分别是zlib的静态库、动态库项目。这里只关心zlibvc项目,鼠标右键单击zlibvc,然后单击【Set as StartUp Project】,设置zlibvc为活动项目。

    2.3.1 编译配置项

    项目zlib一共有5个编译配置项,如下图所示:

    "Debug"编译生成Debug版,调试程序时使用此版本;

    "Release"编译生成Release版,使用汇编代码;

    "ReleaseAxp"编译生成Release版,不使用汇编代码;

    "ReleaseWithoutAsm"编译生成Release版,不使用汇编代码。它似乎与ReleaseAxp没什么区别;

    "ReleaseWithoutCrtdll"编译生成Release版,使用汇编代码。

    ReleaseReleaseAxpReleaseWithoutAsm使用的C运行时库文件不是msvcr70.dll,而是crtdll.dll。笔者对此的理解是:crtdll.dllmsvcr70.dll更加普及。

    ReleaseWithoutCrtdll使用的C运行时库文件是msvcr70.dll不再是crtdll.dll

    虽然crtdll.dllmsvcr70.dll更加普及,但是crtdll.lib很难找到了。没有crtdll.lib的情况下,ReleaseReleaseAxpReleaseWithoutAsm无法完成链接。

    2.3.2 ASMVASMINF

    使用汇编代码的配置项,均定义了宏ASMVASMINF,如下图所示

    2.3.3 排除编译

    使用汇编代码的配置项,gvmat32c.c被排除编译。如下图所示:

    未使用汇编代码的配置项,gvmat32c.c未被排除编译。如下图所示:

    2.3.4 嵌入汇编obj文件

    VC++6.0不同,VC2002里不再自定义编译asm文件,而是直接使用asm文件编译后的obj文件。

    下图是配置项"ReleaseWithoutCrtdll"的LinkerInput选项。可以看到它将使用asm文件的编译结果文件:gvmat32.objinffas32.obj

    2.4 Visual C++ 2005

    使用vc2005打开contribvstudiovc8zlibvc.sln,如下图所示。可以看到一共有六个项目。前四个项目不用理会,zlibstatzlibvc分别是zlib的静态库、动态库项目。这里只关心zlibvc项目,鼠标右键单击zlibvc,然后单击【Set as StartUp Project】,设置zlibvc为活动项目。

    2.4.1 编译配置项

    项目zlib一共有3个编译平台,如下图所示:

    Win32 编译出32位程序,可运行在32位和64Windows上;

    x64 编译出64位程序,可运行在64Windows上;

    Itanium编译出64位程序,只能运行在CPUItaniumWindows上。

    每个编译平台又有3个配置项,如下图所示:

    "Debug"编译生成Debug版,调试程序时使用此版本;

    "Release"编译生成Release版,使用汇编代码;

    "ReleaseWithoutAsm"编译生成Release版,不使用汇编代码。

    2.4.2 ASMVASMINF

    使用汇编代码的配置项,均定义了宏ASMVASMINF,如下图所示

    2.4.3 排除编译

    gvmat32c.cinffas8664.c可能被排除编译。如下图所示:

    编译平台为Win32时,inffas8664.c始终被排除编译,gvmat32c.c视是否使用汇编代码而定;

    编译平台为x64时,gvmat32c.c始终被排除编译,inffas8664.c视是否使用汇编代码而定;

    编译平台为Itanium时,gvmat32c.cinffas8664.c始终被排除编译。因为这个编译平台的汇编代码压根没有实现。

    2.4.4 嵌入汇编obj文件

    VC2002相同,VC2005也不再自定义编译asm文件,而是直接使用asm文件编译后的obj文件。

    需要注意的是:Win32x64平台使用的obj文件是不同的。下图是x64平台下,使用masmx64目录下的两个obj文件。

    2.5 ZLIB_WINAPI

    定义了ZLIB_WINAPI,则zlib导出的函数其调用约定全部被设置为WINAPI,即__stdcall。这么做的好处是:不是C语言的客户程序,如VB6.0也可以使用zlib动态库了。

    VC++6.0的宏定义里没有发现ZLIB_WINAPI,也就是说VC++6.0编译生成的zlib动态库,其导出函数的调用约定不是__stdcall,而是__cdecl

    VC2002VC2005的宏定义里均有ZLIB_WINAPI,编译生成zlib动态库后,其导出函数的调用约定是__stdcall

    客户端使用zlib动态库时,应该也要定义ZLIB_WINAPI,具体代码如下:

    #define ZLIB_WINAPI

    #include "zlib.h"

    遗憾的是,至少在libpng1.4.12项目里笔者并没有发现#include "zlib.h"之前有#define ZLIB_WINAPI

    笔者认为比较好的方法应该是把#define ZLIB_WINAPI直接添加到zlib.h里,保证编译生成zlib动态库、客户端调用zlibzlib的导出函数均是__stdcall的。

    3版本1.2.8

    3.1 编译汇编代码

    与版本1.2.3相比,版本1.2.8longest_match函数的32位汇编代码由gvmat32c.cgvmat32.asm两个文件合并为match686.asm这一个文件。具体如下表所示:

    C

    ASM x86

    ASM x64

    inflate_fast

    inffast.c

    inffas32.asm

    inffas8664.c

    inffasx64.asm

    longest_match

    deflate.c

    match686.asm

    gvmat64.asm

    现在的情况变为:

    不用汇编代码,需要编译inffast.cdeflate.c

    使用32位汇编代码,需要编译inffas32.asmmatch686.asm

    使用64位汇编代码,需要编译inffas8664.cinffasx64.asmgvmat64.asm

    3.1.1 编译

    编译32位汇编代码:将ml.exeC:Program FilesMicrosoft Visual Studio 8VCin复制到contribmasmx86,运行bld_ml32.bat即可。

    编译64位汇编代码:将ml64.exeC:Program FilesMicrosoft Visual Studio 8VCinx86_amd64复制到contribmasmx64,运行bld_ml64.bat即可。

    当然,使用vc2008vc2010vc2012vc2013vc2015ml.exeml64.exe应该也是可以的。

    3.2 使用Visual C++编译

    进入contribvstudio目录,可以发现vc9vc10vc11三个子目录,分别用vc2008vc2010vc2012编译。设置与上一章大致相同,这里就不赘述了。需要特别说明的是vc2010里的"编译前事件"。

    3.2.1 编译前事件

    vc2010里有"编译前事件",如下图所示:

    其含义为:编译代码之前将执行"编译前事件",上图的命令如下所示:

    cd ....masmx64

    bld_ml64.bat

    其含义就是设置contribmasmx64为当前目录,然后执行bld_ml64.bat

    ....masmx64是相对路径,相对于项目文件(contribvstudiovc10zlibvc.vcxproj)的相对路径,即contribvstudiovc10....masmx64,也就是contribmasmx64

    使用vc2010编译zlib代码,不用费劲找ml.exeml64.exe了,也不用考虑应该使用哪个版本的ml.exeml64.exe了。一切方便了很多。

  • 相关阅读:
    HTML5新增标签和属性
    HTML——表单标签
    HTML——表格标签
    js
    js
    js
    js
    js-02-2
    js
    selleck --手机端-- 销售打卡记录下载
  • 原文地址:https://www.cnblogs.com/hanford/p/6168837.html
Copyright © 2011-2022 走看看