VC++编译zlib
目录
第1章简介
zlib是一个用于解压缩的开源C函数库。很多项目(如libpng)会用到它。
它的下载网址如下:
http://sourceforge.net/projects/libpng/files/zlib/
本文对zlib自带的Visual C++项目进行解析。
第2章版本1.2.3
2.1 编译汇编代码
版本1.2.3里,为了提高解压缩效率,函数inflate_fast和longest_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_fast在inffast.c里有一份实现它的C代码;在inffas32.asm里有一份实现它的32位汇编代码;在inffas8664.c里会调用函数inffas8664fnc,而后者在文件inffasx64.asm里由64位汇编代码实现。
函数longest_match在deflate.c里有一份实现它的C代码;在gvmat32c.c里会调用函数longest_match_7fff和longest_match_686,而这两个函数在文件gvmat32.asm里由32位汇编代码实现;在gvmat64.asm里有一份实现它的64位汇编代码。
简而言之就是:
不用汇编代码,需要编译inffast.c和deflate.c;
使用32位汇编代码,需要编译inffas32.asm、gvmat32c.c、gvmat32.asm;
使用64位汇编代码,需要编译inffas8664.c、inffasx64.asm、gvmat64.asm。
*.c文件在Visual C++编译时会自行处理,*.asm文件就需要特别处理了。
2.1.1 32位汇编
contrib\masmx86目录下的inffas32.asm和gvmat32.asm是32位的汇编代码。编译后可运行在32位的Windows上,也可运行在兼容x86指令的64位Windows上。不能运行在不兼容x86指令的64位Windows上(如:CPU为Itanium的Windows)。
进入contrib\masmx86目录,运行bld_ml32.bat即可编译inffas32.asm和gvmat32.asm。文件bld_ml32.bat的内容如下:
ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm ml /coff /Zi /c /Flinffas32.lst inffas32.asm |
它的含义是调用ml.exe,将gvmat32.asm、inffas32.asm编译生成gvmat32.obj、inffas32.obj。
ml.exe是微软的宏汇编程序,安装了VC++2002至VC++2015后ml.exe也同时被安装,它所在的目录如下表所示:
vc版本 |
目录 |
其它 |
2002 |
C:\Program Files\Microsoft Visual Studio .NET\Vc7\bin |
|
2003 |
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin |
|
2005 |
C:\Program Files\Microsoft Visual Studio 8\VC\bin |
amd64\ml64.exe x86_amd64\ml64.exe |
2008 |
C:\Program Files\Microsoft Visual Studio 9.0\VC\bin |
amd64\ml64.exe x86_amd64\ml64.exe |
2010 |
C:\Program Files\Microsoft Visual Studio 10.0\VC\bin |
amd64\ml64.exe x86_amd64\ml64.exe |
2012 |
C:\Program Files\Microsoft Visual Studio 11.0\VC\bin |
amd64\ml64.exe x86_amd64\ml64.exe |
2013 |
C:\Program Files\Microsoft Visual Studio 12.0\VC\bin |
amd64_x86\ml.exe amd64\ml64.exe x86_amd64\ml64.exe |
2015 |
C:\Program Files\Microsoft Visual Studio 14.0\VC\bin |
amd64_x86\ml.exe amd64\ml64.exe x86_amd64\ml64.exe |
说明:
1、从vc2005开始提供了ml64.exe,它用来编译生成64位的汇编代码;
2、从vc2013开始又提供了amd64_x86\ml.exe;
3、两个ml.exe和两个ml64.exe的区别:
ml.exe 是32位程序,编译生成32位的汇编代码;
amd64_x86\ml.exe 是64位程序,编译生成32位的汇编代码;
amd64\ml64.exe 是64位程序,编译生成64位的汇编代码;
x86_amd64\ml64.exe 是32位程序,编译生成64位的汇编代码。
上述文件夹命名都是有含义的:amd64_x86前面的amd64表示ml.exe是64位的,后面的x86表示编译生成的汇编代码是32位的;amd64表示amd64_amd64,即ml.exe和生成的汇编代码都是64位的。
为了能够正常编译,有两种方法:
方法一:将ml.exe从相应的目录中复制到bld_ml32.bat所在目录,运行bld_ml32.bat即可;
方法二:在bld_ml32.bat所在目录创建vc2002.bat,其内容如下:
%VSCOMNTOOLS%\..\..\Vc7\bin\ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm %VSCOMNTOOLS%\..\..\Vc7\bin\ml /coff /Zi /c /Flinffas32.lst inffas32.asm |
现在运行vc2002.bat即可调用C:\Program Files\Microsoft Visual Studio .NET\Vc7\bin\ml.exe进行编译。
VSCOMNTOOLS是一个环境变量,安装vc2002后它被自动添加到系统里,如下图所示:
同理,还可以创建vc2003.bat
"%VS71COMNTOOLS%..\..\Vc7\bin\ml" /coff /Zi /c /Flgvmat32.lst gvmat32.asm "%VS71COMNTOOLS%..\..\Vc7\bin\ml" /coff /Zi /c /Flinffas32.lst inffas32.asm |
还可以创建vc2005.bat
"%VS80COMNTOOLS%..\..\VC\bin\ml" /coff /Zi /c /Flgvmat32.lst gvmat32.asm "%VS80COMNTOOLS%..\..\VC\bin\ml" /coff /Zi /c /Flinffas32.lst inffas32.asm |
经实际测试,vc2002.bat和vc2003.bat能够正常运行,而vc2005.bat在编译时出错。也就是说ml.exe只能使用vc2002和vc2003附带的版本,再高的版本就不行了。
2.1.2 64位汇编
contrib\masmx64目录下的gvmat64.asm和inffasx64.asm是64位的汇编代码。编译后可运行在64位的Windows上(CPU为Itanium的Windows例外)。
进入contrib\masmx64目录,运行bld_ml64.bat即可编译gvmat64.asm和inffasx64.asm。文件bld_ml64.bat的内容如下:
ml64.exe /Flinffasx64 /c /Zi inffasx64.asm ml64.exe /Flgvmat64 /c /Zi gvmat64.asm |
它的含义是调用ml64.exe,将gvmat64.asm、inffasx64.asm编译生成gvmat64.obj、inffasx64.obj。
为了能够正常编译,有两种方法:
方法一:将ml64.exe从C:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_amd64复制到bld_ml64.bat所在目录,运行bld_ml64.bat即可;
方法二:在bld_ml64.bat所在目录创建vc2005.bat,其内容如下:
"%VS80COMNTOOLS%..\..\VC\bin\x86_amd64\ml64.exe" /Flinffasx64 /c /Zi inffasx64.asm "%VS80COMNTOOLS%..\..\VC\bin\x86_amd64\ml64.exe" /Flgvmat64 /c /Zi gvmat64.asm |
现在运行vc2005.bat即可进行编译。
2.2 Visual C++ 6.0
使用Visual C++6.0打开projects\visualc6\zlib.dsw,如下图所示。可以看到一共有三个项目:example、minigzip、zlib。前两个项目不用理会,鼠标右键单击zlib,然后单击【Set as Active Project】,设置zlib为活动项目。
2.2.1 编译配置项
项目zlib一共有8个编译配置项,如下图所示:
"Win32 DLL*"表示编译生成动态库;
"Win32 LIB*"表示编译生成静态库;
"*Release"表示编译生成Release版,发布程序时使用此版本;
"*Debug"表示编译生成Debug版,调试程序时使用此版本;
含有ASM的表示编译时使用汇编代码;
未含ASM的表示编译时不使用汇编代码。
2.2.2 宏ASMV和ASMINF
查看zlib的配置,当选中含有ASM的编译配置项时,可以看到宏ASMV和ASMINF被定义了。如下图所示:
宏ASMINF被定义,则inflate_fast的C代码被禁用,以下代码节选自inffast.c
#ifndef ASMINF void inflate_fast(strm, start) z_streamp strm; unsigned start; { ... ... ... } #endif /* !ASMINF */ |
宏ASMV被定义,则longest_match的C代码被禁用,以下代码节选自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.c、inffasx64.asm、gvmat64.asm这三个文件。
zlib项目里含有与32位汇编相关的三个文件:gvmat32.asm、gvmat32c.c、inffas32.asm。
当选中不含ASM的编译配置项时,可以看到这三个文件在编译时是被排除在外的,如下图所示:
当选中含有ASM的编译配置项时,可以看到这三个文件将参与编译,如下图所示:
2.2.4 自定义编译
当选中含有ASM的编译配置项时,可以看到gvmat32.asm、inffas32.asm是如何被编译的。如下图所示:
命令如下所示:
ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" |
因为VC++6.0并不自带ml.exe,因此上述命令执行时将会失败。解决方法:将C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\ml.exe复制到C:\Program Files\Microsoft Visual Studio\VC98\Bin。即将vc2002的ml.exe复制到vc6的安装目录。
2.3 Visual C++ 2002
使用vc2002打开contrib\vstudio\vc7\zlibvc.sln,如下图所示。可以看到一共有五个项目:miniunz、minizip、testZlibDll、zlibstat、zlibvc。前三个项目不用理会,zlibstat、zlibvc分别是zlib的静态库、动态库项目。这里只关心zlibvc项目,鼠标右键单击zlibvc,然后单击【Set as StartUp Project】,设置zlibvc为活动项目。
2.3.1 编译配置项
项目zlib一共有5个编译配置项,如下图所示:
"Debug"编译生成Debug版,调试程序时使用此版本;
"Release"编译生成Release版,使用汇编代码;
"ReleaseAxp"编译生成Release版,不使用汇编代码;
"ReleaseWithoutAsm"编译生成Release版,不使用汇编代码。它似乎与ReleaseAxp没什么区别;
"ReleaseWithoutCrtdll"编译生成Release版,使用汇编代码。
Release、ReleaseAxp、ReleaseWithoutAsm使用的C运行时库文件不是msvcr70.dll,而是crtdll.dll。笔者对此的理解是:crtdll.dll比msvcr70.dll更加普及。
ReleaseWithoutCrtdll使用的C运行时库文件是msvcr70.dll不再是crtdll.dll。
虽然crtdll.dll比msvcr70.dll更加普及,但是crtdll.lib很难找到了。没有crtdll.lib的情况下,Release、ReleaseAxp、ReleaseWithoutAsm无法完成链接。
2.3.2 宏ASMV和ASMINF
使用汇编代码的配置项,均定义了宏ASMV和ASMINF,如下图所示
2.3.3 排除编译
使用汇编代码的配置项,gvmat32c.c被排除编译。如下图所示:
未使用汇编代码的配置项,gvmat32c.c未被排除编译。如下图所示:
2.3.4 嵌入汇编obj文件
与VC++6.0不同,VC2002里不再自定义编译asm文件,而是直接使用asm文件编译后的obj文件。
下图是配置项"ReleaseWithoutCrtdll"的Linker、Input选项。可以看到它将使用asm文件的编译结果文件:gvmat32.obj、inffas32.obj。
2.4 Visual C++ 2005
使用vc2005打开contrib\vstudio\vc8\zlibvc.sln,如下图所示。可以看到一共有六个项目。前四个项目不用理会,zlibstat、zlibvc分别是zlib的静态库、动态库项目。这里只关心zlibvc项目,鼠标右键单击zlibvc,然后单击【Set as StartUp Project】,设置zlibvc为活动项目。
2.4.1 编译配置项
项目zlib一共有3个编译平台,如下图所示:
Win32 编译出32位程序,可运行在32位和64位Windows上;
x64 编译出64位程序,可运行在64位Windows上;
Itanium编译出64位程序,只能运行在CPU为Itanium的Windows上。
每个编译平台又有3个配置项,如下图所示:
"Debug"编译生成Debug版,调试程序时使用此版本;
"Release"编译生成Release版,使用汇编代码;
"ReleaseWithoutAsm"编译生成Release版,不使用汇编代码。
2.4.2 宏ASMV和ASMINF
使用汇编代码的配置项,均定义了宏ASMV和ASMINF,如下图所示
2.4.3 排除编译
gvmat32c.c和inffas8664.c可能被排除编译。如下图所示:
编译平台为Win32时,inffas8664.c始终被排除编译,gvmat32c.c视是否使用汇编代码而定;
编译平台为x64时,gvmat32c.c始终被排除编译,inffas8664.c视是否使用汇编代码而定;
编译平台为Itanium时,gvmat32c.c和inffas8664.c始终被排除编译。因为这个编译平台的汇编代码压根没有实现。
2.4.4 嵌入汇编obj文件
与VC2002相同,VC2005也不再自定义编译asm文件,而是直接使用asm文件编译后的obj文件。
需要注意的是:Win32和x64平台使用的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。
VC2002和VC2005的宏定义里均有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动态库、客户端调用zlib时zlib的导出函数均是__stdcall的。
第3章版本1.2.8
3.1 编译汇编代码
与版本1.2.3相比,版本1.2.8的longest_match函数的32位汇编代码由gvmat32c.c、gvmat32.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.c和deflate.c;
使用32位汇编代码,需要编译inffas32.asm、match686.asm;
使用64位汇编代码,需要编译inffas8664.c、inffasx64.asm、gvmat64.asm。
3.1.1 编译
编译32位汇编代码:将ml.exe从C:\Program Files\Microsoft Visual Studio 8\VC\bin\复制到contrib\masmx86,运行bld_ml32.bat即可。
编译64位汇编代码:将ml64.exe从C:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_amd64复制到contrib\masmx64,运行bld_ml64.bat即可。
当然,使用vc2008、vc2010、vc2012、vc2013、vc2015的ml.exe、ml64.exe应该也是可以的。
3.2 使用Visual C++编译
进入contrib\vstudio目录,可以发现vc9、vc10、vc11三个子目录,分别用vc2008、vc2010、vc2012编译。设置与上一章大致相同,这里就不赘述了。需要特别说明的是vc2010里的"编译前事件"。
3.2.1 编译前事件
vc2010里有"编译前事件",如下图所示:
其含义为:编译代码之前将执行"编译前事件",上图的命令如下所示:
cd ..\..\masmx64 bld_ml64.bat |
其含义就是设置contrib\masmx64为当前目录,然后执行bld_ml64.bat。
..\..\masmx64是相对路径,相对于项目文件(contrib\vstudio\vc10\zlibvc.vcxproj)的相对路径,即contrib\vstudio\vc10\..\..\masmx64,也就是contrib\masmx64。
使用vc2010编译zlib代码,不用费劲找ml.exe和ml64.exe了,也不用考虑应该使用哪个版本的ml.exe和ml64.exe了。一切方便了很多。
VC++编译zlib的更多相关文章
- vc编译 zlib 1.2.8
最近用到gzip关的算法,于是想起了zlib这个库,于是将其下载下来编译. 首先,在官网上下载源码包:http://zlib.net/zlib-1.2.8.tar.gz 解压之后,打开vc 命令工具: ...
- VC++编译libpng
目录 第1章简介 1 第2章 Visual C++6.0 2 2.1 打开项目 2 2.2 编译宏 3 2.2.1 小结 5 第3章 Visual C++2010 ...
- windows下使用cmake编译zlib与libpng libjpeg
win7下使用VS2010编译jpeglib 1.下载源代码下载地址:http://www.ijg.org/files/, 选择最新版本的windows版本压缩包,进行下载. jpeg ...
- 用VC编译lua源码,生成lua语言的解释器和编译器
用VC编译lua源码,生成lua语言的解释器和编译器 1.去网址下载源码 http://www.lua.org/download.html 2.装一个VC++,我用的是VC6.0 3.接下来我们开始编 ...
- VC++编译MPIR 2.7.0
目录 第1章编译 2 1.1 简介 2 1.2 下载 3 1.3 解决方案 4 1.4 创建项目 5 1.5 复制文件树 6 1.6 不使用预编译头文件 8 ...
- VC++编译GSL
目录 第1章 VC++ 1 1.1 修改行结束符 1 1.2 修改#include "*.c" 为 #include "*.inl" 2 1. ...
- 让VC编译出来的程序不依赖于msvcr80.dll/msvcr90.dll/msvcr100.dll等文件
---转载:http://hi.baidu.com/liu_haitao/item/e2157ac3a3c32a0bc610b253 让VC编译出来的程序不依赖于msvcr80.dll/msvcr90 ...
- 【Python学习】由于windows环境问题导致的不能安装某些需要VC编译的插件
由于windows环境问题导致的不能安装某些需要VC编译的插件 下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/ 安装方法: 在CMD中输入 pip in ...
- VC编译连接选项详解
VC编译连接选项详解 大家可能一直在用VC开发软件,但是对于这个编译器却未必很了解.原因是多方面的.大多数情况下,我们只停留在“使用”它,而不会想去“了解”它.因为它只是一个工具,我们宁可把更多的精力 ...
随机推荐
- JAVAWeb使用POI做导出Excel
一.需要了解的API ①HSSFWorkBook //代表一个Excel文件 ②HSSFSheet //代表一个表 ③HSSFRow //代表一个表中的某一行 ④HSSFCell //代表一个表中的某 ...
- IOSView翻转扭矩位移
CoreGraphics.h CGAffineTransform rotation = CGAffineTransformMakeRotation(M_PI_2);[xxx setTransform: ...
- easyUI学习网站
http://www.runoob.com/jeasyui/plugins-form-timespinner.html http://www.jeasyui.net/plugins/178.html ...
- SaveXml的方法汇总
/// <summary> /// 保存XML文件 /// </summary> /// <returns></returns> public bool ...
- #使用while循环输入1 2 3 4 5 6 8 9 10
#!/usr/bin/env python #使用while循环输入1 2 3 4 5 6 8 9 10 import time start = 1 while True: if start == 7 ...
- CodeForces 454C Little Pony and Expected Maximum
Little Pony and Expected Maximum Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I6 ...
- SetWindowHookEx 做消息响应
HHOOK g_Hook = NULL; LRESULT CALLBACK CallWndProc( _In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM l ...
- 搭建本地的git仓库
折腾了快一天了,终于搭建成功了. 分享一下搭建的步骤: 一.GIT仓库的创建 1. adduser git 2. passwd git 此例设置git的密码为123456 3. cd /home/gi ...
- 【原创】pads layout 画多边形copper,出现Self-Intersecting Polygon,解决办法
在做线性位移传感器的电路板时,需要在一个很小的多边形Copper操作,总是提示“Self-Intersecting Polygon”报错,意思是outline线自身交叉,换句话说就是线宽与多边形尺寸没 ...
- CG绘画笔记
看一些比较好的作品:看作品哪些部分,部件,盔甲比较吸引人,提取一个比较好的点,进行组合创作. 逆光.切光布局构图 创作:故事.情感.经历.朋友.时代 灵感: 电影.音乐 变化(色彩)透视 空气透视视觉 ...