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 編譯配置項(xiàng)????6
2.2.2 宏ASMV和ASMINF????6
2.2.3 排除編譯????8
2.2.4 自定義編譯????8
2.3 Visual C++ 2002????9
2.3.1 編譯配置項(xiàng)????10
2.3.2 宏ASMV和ASMINF????11
2.3.3 排除編譯????11
2.3.4 嵌入?yún)R編obj文件????11
2.4 Visual C++ 2005????12
2.4.1 編譯配置項(xiàng)????12
2.4.2 宏ASMV和ASMINF????13
2.4.3 排除編譯????13
2.4.4 嵌入?yún)R編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是一個(gè)用于解壓縮的開源C函數(shù)庫。很多項(xiàng)目(如libpng)會用到它。
它的下載網(wǎng)址如下:
http://sourceforge.net/projects/libpng/files/zlib/
本文對zlib自帶的Visual C++項(xiàng)目進(jìn)行解析。
?
?
第2章版本1.2.3
2.1 編譯匯編代碼
版本1.2.3里,為了提高解壓縮效率,函數(shù)inflate_fast和longest_match用匯編代碼實(shí)現(xiàn)了。這兩個(gè)函數(shù)有三個(gè)版本,如下表所示:
| 函數(shù) | 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 |
具體情況為:
函數(shù)inflate_fast在inffast.c里有一份實(shí)現(xiàn)它的C代碼;在inffas32.asm里有一份實(shí)現(xiàn)它的32位匯編代碼;在inffas8664.c里會調(diào)用函數(shù)inffas8664fnc,而后者在文件inffasx64.asm里由64位匯編代碼實(shí)現(xiàn)。
函數(shù)longest_match在deflate.c里有一份實(shí)現(xiàn)它的C代碼;在gvmat32c.c里會調(diào)用函數(shù)longest_match_7fff和longest_match_686,而這兩個(gè)函數(shù)在文件gvmat32.asm里由32位匯編代碼實(shí)現(xiàn);在gvmat64.asm里有一份實(shí)現(xiàn)它的64位匯編代碼。
簡而言之就是:
不用匯編代碼,需要編譯inffast.c和deflate.c;
使用32位匯編代碼,需要編譯inffas32.asm、gvmat32c.c、gvmat32.asm;
使用64位匯編代碼,需要編譯inffas8664.c、inffasx64.asm、gvmat64.asm。
*.c文件在Visual C++編譯時(shí)會自行處理,*.asm文件就需要特別處理了。
2.1.1 32位匯編
contrib\masmx86目錄下的inffas32.asm和gvmat32.asm是32位的匯編代碼。編譯后可運(yùn)行在32位的Windows上,也可運(yùn)行在兼容x86指令的64位Windows上。不能運(yùn)行在不兼容x86指令的64位Windows上(如:CPU為Itanium的Windows)。
進(jìn)入contrib\masmx86目錄,運(yùn)行bld_ml32.bat即可編譯inffas32.asm和gvmat32.asm。文件bld_ml32.bat的內(nèi)容如下:
| ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm ml /coff /Zi /c /Flinffas32.lst inffas32.asm |
它的含義是調(diào)用ml.exe,將gvmat32.asm、inffas32.asm編譯生成gvmat32.obj、inffas32.obj。
ml.exe是微軟的宏匯編程序,安裝了VC++2002至VC++2015后ml.exe也同時(shí)被安裝,它所在的目錄如下表所示:
| 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、兩個(gè)ml.exe和兩個(gè)ml64.exe的區(qū)別:
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從相應(yīng)的目錄中復(fù)制到bld_ml32.bat所在目錄,運(yùn)行bld_ml32.bat即可;
方法二:在bld_ml32.bat所在目錄創(chuàng)建vc2002.bat,其內(nèi)容如下:
| %VSCOMNTOOLS%\..\..\Vc7\bin\ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm %VSCOMNTOOLS%\..\..\Vc7\bin\ml /coff /Zi /c /Flinffas32.lst inffas32.asm |
現(xiàn)在運(yùn)行vc2002.bat即可調(diào)用C:\Program Files\Microsoft Visual Studio .NET\Vc7\bin\ml.exe進(jìn)行編譯。
VSCOMNTOOLS是一個(gè)環(huán)境變量,安裝vc2002后它被自動添加到系統(tǒng)里,如下圖所示:
同理,還可以創(chuàng)建vc2003.bat
| "%VS71COMNTOOLS%..\..\Vc7\bin\ml" /coff /Zi /c /Flgvmat32.lst gvmat32.asm "%VS71COMNTOOLS%..\..\Vc7\bin\ml" /coff /Zi /c /Flinffas32.lst inffas32.asm |
還可以創(chuàng)建vc2005.bat
| "%VS80COMNTOOLS%..\..\VC\bin\ml" /coff /Zi /c /Flgvmat32.lst gvmat32.asm "%VS80COMNTOOLS%..\..\VC\bin\ml" /coff /Zi /c /Flinffas32.lst inffas32.asm |
經(jīng)實(shí)際測試,vc2002.bat和vc2003.bat能夠正常運(yùn)行,而vc2005.bat在編譯時(shí)出錯(cuò)。也就是說ml.exe只能使用vc2002和vc2003附帶的版本,再高的版本就不行了。
2.1.2 64位匯編
contrib\masmx64目錄下的gvmat64.asm和inffasx64.asm是64位的匯編代碼。編譯后可運(yùn)行在64位的Windows上(CPU為Itanium的Windows例外)。
進(jìn)入contrib\masmx64目錄,運(yùn)行bld_ml64.bat即可編譯gvmat64.asm和inffasx64.asm。文件bld_ml64.bat的內(nèi)容如下:
| ml64.exe /Flinffasx64 /c /Zi inffasx64.asm ml64.exe /Flgvmat64 /c /Zi gvmat64.asm |
它的含義是調(diào)用ml64.exe,將gvmat64.asm、inffasx64.asm編譯生成gvmat64.obj、inffasx64.obj。
為了能夠正常編譯,有兩種方法:
方法一:將ml64.exe從C:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_amd64復(fù)制到bld_ml64.bat所在目錄,運(yùn)行bld_ml64.bat即可;
方法二:在bld_ml64.bat所在目錄創(chuàng)建vc2005.bat,其內(nèi)容如下:
| "%VS80COMNTOOLS%..\..\VC\bin\x86_amd64\ml64.exe" /Flinffasx64 /c /Zi inffasx64.asm "%VS80COMNTOOLS%..\..\VC\bin\x86_amd64\ml64.exe" /Flgvmat64 /c /Zi gvmat64.asm |
現(xiàn)在運(yùn)行vc2005.bat即可進(jìn)行編譯。
2.2 Visual C++ 6.0
使用Visual C++6.0打開projects\visualc6\zlib.dsw,如下圖所示。可以看到一共有三個(gè)項(xiàng)目:example、minigzip、zlib。前兩個(gè)項(xiàng)目不用理會,鼠標(biāo)右鍵單擊zlib,然后單擊【Set as Active Project】,設(shè)置zlib為活動項(xiàng)目。
2.2.1 編譯配置項(xiàng)
項(xiàng)目zlib一共有8個(gè)編譯配置項(xiàng),如下圖所示:
"Win32 DLL*"表示編譯生成動態(tài)庫;
"Win32 LIB*"表示編譯生成靜態(tài)庫;
"*Release"表示編譯生成Release版,發(fā)布程序時(shí)使用此版本;
"*Debug"表示編譯生成Debug版,調(diào)試程序時(shí)使用此版本;
含有ASM的表示編譯時(shí)使用匯編代碼;
未含ASM的表示編譯時(shí)不使用匯編代碼。
2.2.2 宏ASMV和ASMINF
查看zlib的配置,當(dāng)選中含有ASM的編譯配置項(xiàng)時(shí),可以看到宏ASMV和ASMINF被定義了。如下圖所示:
宏ASMINF被定義,則inflate_fast的C代碼被禁用,以下代碼節(jié)選自inffast.c
| #ifndef ASMINF void inflate_fast(strm, start) z_streamp strm; unsigned start; { ... ... ... } #endif /* !ASMINF */ |
宏ASMV被定義,則longest_match的C代碼被禁用,以下代碼節(jié)選自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這三個(gè)文件。
zlib項(xiàng)目里含有與32位匯編相關(guān)的三個(gè)文件:gvmat32.asm、gvmat32c.c、inffas32.asm。
當(dāng)選中不含ASM的編譯配置項(xiàng)時(shí),可以看到這三個(gè)文件在編譯時(shí)是被排除在外的,如下圖所示:
當(dāng)選中含有ASM的編譯配置項(xiàng)時(shí),可以看到這三個(gè)文件將參與編譯,如下圖所示:
2.2.4 自定義編譯
當(dāng)選中含有ASM的編譯配置項(xiàng)時(shí),可以看到gvmat32.asm、inffas32.asm是如何被編譯的。如下圖所示:
命令如下所示:
| ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" |
因?yàn)?/span>VC++6.0并不自帶ml.exe,因此上述命令執(zhí)行時(shí)將會失敗。解決方法:將C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\ml.exe復(fù)制到C:\Program Files\Microsoft Visual Studio\VC98\Bin。即將vc2002的ml.exe復(fù)制到vc6的安裝目錄。
2.3 Visual C++ 2002
使用vc2002打開contrib\vstudio\vc7\zlibvc.sln,如下圖所示。可以看到一共有五個(gè)項(xiàng)目:miniunz、minizip、testZlibDll、zlibstat、zlibvc。前三個(gè)項(xiàng)目不用理會,zlibstat、zlibvc分別是zlib的靜態(tài)庫、動態(tài)庫項(xiàng)目。這里只關(guān)心zlibvc項(xiàng)目,鼠標(biāo)右鍵單擊zlibvc,然后單擊【Set as StartUp Project】,設(shè)置zlibvc為活動項(xiàng)目。
2.3.1 編譯配置項(xiàng)
項(xiàng)目zlib一共有5個(gè)編譯配置項(xiàng),如下圖所示:
"Debug"編譯生成Debug版,調(diào)試程序時(shí)使用此版本;
"Release"編譯生成Release版,使用匯編代碼;
"ReleaseAxp"編譯生成Release版,不使用匯編代碼;
"ReleaseWithoutAsm"編譯生成Release版,不使用匯編代碼。它似乎與ReleaseAxp沒什么區(qū)別;
"ReleaseWithoutCrtdll"編譯生成Release版,使用匯編代碼。
Release、ReleaseAxp、ReleaseWithoutAsm使用的C運(yùn)行時(shí)庫文件不是msvcr70.dll,而是crtdll.dll。筆者對此的理解是:crtdll.dll比msvcr70.dll更加普及。
ReleaseWithoutCrtdll使用的C運(yùn)行時(shí)庫文件是msvcr70.dll不再是crtdll.dll。
雖然crtdll.dll比msvcr70.dll更加普及,但是crtdll.lib很難找到了。沒有crtdll.lib的情況下,Release、ReleaseAxp、ReleaseWithoutAsm無法完成鏈接。
2.3.2 宏ASMV和ASMINF
使用匯編代碼的配置項(xiàng),均定義了宏ASMV和ASMINF,如下圖所示
2.3.3 排除編譯
使用匯編代碼的配置項(xiàng),gvmat32c.c被排除編譯。如下圖所示:
未使用匯編代碼的配置項(xiàng),gvmat32c.c未被排除編譯。如下圖所示:
2.3.4 嵌入?yún)R編obj文件
與VC++6.0不同,VC2002里不再自定義編譯asm文件,而是直接使用asm文件編譯后的obj文件。
下圖是配置項(xiàng)"ReleaseWithoutCrtdll"的Linker、Input選項(xiàng)。可以看到它將使用asm文件的編譯結(jié)果文件:gvmat32.obj、inffas32.obj。
2.4 Visual C++ 2005
使用vc2005打開contrib\vstudio\vc8\zlibvc.sln,如下圖所示。可以看到一共有六個(gè)項(xiàng)目。前四個(gè)項(xiàng)目不用理會,zlibstat、zlibvc分別是zlib的靜態(tài)庫、動態(tài)庫項(xiàng)目。這里只關(guān)心zlibvc項(xiàng)目,鼠標(biāo)右鍵單擊zlibvc,然后單擊【Set as StartUp Project】,設(shè)置zlibvc為活動項(xiàng)目。
2.4.1 編譯配置項(xiàng)
項(xiàng)目zlib一共有3個(gè)編譯平臺,如下圖所示:
Win32 編譯出32位程序,可運(yùn)行在32位和64位Windows上;
x64 編譯出64位程序,可運(yùn)行在64位Windows上;
Itanium編譯出64位程序,只能運(yùn)行在CPU為Itanium的Windows上。
每個(gè)編譯平臺又有3個(gè)配置項(xiàng),如下圖所示:
"Debug"編譯生成Debug版,調(diào)試程序時(shí)使用此版本;
"Release"編譯生成Release版,使用匯編代碼;
"ReleaseWithoutAsm"編譯生成Release版,不使用匯編代碼。
2.4.2 宏ASMV和ASMINF
使用匯編代碼的配置項(xiàng),均定義了宏ASMV和ASMINF,如下圖所示
2.4.3 排除編譯
gvmat32c.c和inffas8664.c可能被排除編譯。如下圖所示:
編譯平臺為Win32時(shí),inffas8664.c始終被排除編譯,gvmat32c.c視是否使用匯編代碼而定;
編譯平臺為x64時(shí),gvmat32c.c始終被排除編譯,inffas8664.c視是否使用匯編代碼而定;
編譯平臺為Itanium時(shí),gvmat32c.c和inffas8664.c始終被排除編譯。因?yàn)檫@個(gè)編譯平臺的匯編代碼壓根沒有實(shí)現(xiàn)。
2.4.4 嵌入?yún)R編obj文件
與VC2002相同,VC2005也不再自定義編譯asm文件,而是直接使用asm文件編譯后的obj文件。
需要注意的是:Win32和x64平臺使用的obj文件是不同的。下圖是x64平臺下,使用masmx64目錄下的兩個(gè)obj文件。
2.5 宏ZLIB_WINAPI
定義了ZLIB_WINAPI,則zlib導(dǎo)出的函數(shù)其調(diào)用約定全部被設(shè)置為WINAPI,即__stdcall。這么做的好處是:不是C語言的客戶程序,如VB6.0也可以使用zlib動態(tài)庫了。
VC++6.0的宏定義里沒有發(fā)現(xiàn)ZLIB_WINAPI,也就是說VC++6.0編譯生成的zlib動態(tài)庫,其導(dǎo)出函數(shù)的調(diào)用約定不是__stdcall,而是__cdecl。
VC2002和VC2005的宏定義里均有ZLIB_WINAPI,編譯生成zlib動態(tài)庫后,其導(dǎo)出函數(shù)的調(diào)用約定是__stdcall。
客戶端使用zlib動態(tài)庫時(shí),應(yīng)該也要定義ZLIB_WINAPI,具體代碼如下:
| #define ZLIB_WINAPI #include "zlib.h" |
遺憾的是,至少在libpng1.4.12項(xiàng)目里筆者并沒有發(fā)現(xiàn)#include "zlib.h"之前有#define ZLIB_WINAPI。
筆者認(rèn)為比較好的方法應(yīng)該是把#define ZLIB_WINAPI直接添加到zlib.h里,保證編譯生成zlib動態(tài)庫、客戶端調(diào)用zlib時(shí)zlib的導(dǎo)出函數(shù)均是__stdcall的。
?
第3章版本1.2.8
3.1 編譯匯編代碼
與版本1.2.3相比,版本1.2.8的longest_match函數(shù)的32位匯編代碼由gvmat32c.c、gvmat32.asm兩個(gè)文件合并為match686.asm這一個(gè)文件。具體如下表所示:
| 函數(shù) | C | ASM x86 | ASM x64 |
| inflate_fast | inffast.c | inffas32.asm | inffas8664.c inffasx64.asm |
| longest_match | deflate.c | match686.asm | gvmat64.asm |
現(xiàn)在的情況變?yōu)?#xff1a;
不用匯編代碼,需要編譯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\復(fù)制到contrib\masmx86,運(yùn)行bld_ml32.bat即可。
編譯64位匯編代碼:將ml64.exe從C:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_amd64復(fù)制到contrib\masmx64,運(yùn)行bld_ml64.bat即可。
當(dāng)然,使用vc2008、vc2010、vc2012、vc2013、vc2015的ml.exe、ml64.exe應(yīng)該也是可以的。
3.2 使用Visual C++編譯
進(jìn)入contrib\vstudio目錄,可以發(fā)現(xiàn)vc9、vc10、vc11三個(gè)子目錄,分別用vc2008、vc2010、vc2012編譯。設(shè)置與上一章大致相同,這里就不贅述了。需要特別說明的是vc2010里的"編譯前事件"。
3.2.1 編譯前事件
vc2010里有"編譯前事件",如下圖所示:
其含義為:編譯代碼之前將執(zhí)行"編譯前事件",上圖的命令如下所示:
| cd ..\..\masmx64 bld_ml64.bat |
其含義就是設(shè)置contrib\masmx64為當(dāng)前目錄,然后執(zhí)行bld_ml64.bat。
..\..\masmx64是相對路徑,相對于項(xiàng)目文件(contrib\vstudio\vc10\zlibvc.vcxproj)的相對路徑,即contrib\vstudio\vc10\..\..\masmx64,也就是contrib\masmx64。
使用vc2010編譯zlib代碼,不用費(fèi)勁找ml.exe和ml64.exe了,也不用考慮應(yīng)該使用哪個(gè)版本的ml.exe和ml64.exe了。一切方便了很多。
轉(zhuǎn)載于:https://www.cnblogs.com/hanford/p/6168837.html
總結(jié)
以上是生活随笔為你收集整理的VC++编译zlib的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bash 中的变量可以这么用
- 下一篇: Eclipse java项目转换为web