CMake構(gòu)建學(xué)習(xí)筆記25-SpatiaLite庫的構(gòu)建
1. 引言
嘗試使用CMake構(gòu)建SpatiaLite及其依賴庫,但是沒有成功。因?yàn)镾patiaLite及其依賴庫很多都是老牌的C庫,這種庫由于年代的原因一般都不提供CMake的構(gòu)建方式,在Windows下提供的構(gòu)建方式一般是基于nmake的。這意味著難以實(shí)現(xiàn)通過一個(gè)配置來實(shí)現(xiàn)跨平臺(tái)構(gòu)建,不過筆者也沒有糾結(jié)這個(gè)問題,這種問題只能交給時(shí)間來解決,比如GDAL、GEOS這樣庫最開始都是nmake構(gòu)建,后來陸續(xù)都升級(jí)為使用CMake構(gòu)建。在這里就記錄一下筆者使用nmake構(gòu)建SpatiaLite庫的過程。
SpatiaLite是一個(gè)為SQLite數(shù)據(jù)庫引擎擴(kuò)展空間數(shù)據(jù)存儲(chǔ)與分析功能的開源庫,使其能夠支持地理信息系統(tǒng)(GIS)操作。
2. nmake構(gòu)建
在具體總結(jié)SpatiaLite庫的構(gòu)建之前,最好需要了解下Windows下使用namke構(gòu)建的一般步驟。
在Windows下構(gòu)建程序最方便的當(dāng)然是直接使用Visual Studio,通過GUI界面來構(gòu)建程序。不過GUI方式也有很麻煩的地方,比如CICD需要通過腳本來實(shí)現(xiàn)代碼到產(chǎn)品的過程,而從終端批處理的方式就是通過nmake來提供的。
2.1 步驟
具體來說,就是在安裝Visual Studio之后,開始菜單中打開相應(yīng)的開發(fā)命令行環(huán)境。以Visual Studio 2019為例,就是x64 Native Tools Command Prompt for VS 2019工具。這個(gè)工具本質(zhì)上就是一個(gè)CMD,只不過已經(jīng)內(nèi)置了開發(fā)命令行環(huán)境,如下所示:

打開這個(gè)VS終端之后,通常輸入如下指令來構(gòu)建程序:
nmake -f makefile.vc
這個(gè)makefile.vc就是代碼項(xiàng)目的主構(gòu)建腳本,定義了這個(gè)項(xiàng)目如何編譯、鏈接。為了找到這個(gè)文件,需要先通過CD指令跳轉(zhuǎn)到代碼項(xiàng)目包含這個(gè)文件的目錄下。除了makefile.vc這個(gè)文件之外,還可能有nmake.opt這個(gè)文件;這是一個(gè)自定義的配置文件,用于覆蓋默認(rèn)編譯選項(xiàng)(如宏定義、包含路徑、庫路徑、優(yōu)化選項(xiàng)等)。通常makefile.vc中的內(nèi)容不用修改,通過修改nmake.opt中的內(nèi)容來實(shí)現(xiàn)自定義配置。
除了上述指令之外,為了區(qū)分構(gòu)建步驟,以下步驟也很常見,例如清理構(gòu)建過程的文件:
nmake -f makefile.vc clean
將構(gòu)建結(jié)果進(jìn)行安裝:
nmake -f makefile.vc install
不過clean和install需要看makefile.vc和nmake.opt中是否提供了這個(gè)構(gòu)建目標(biāo)。如果沒有提供,那么上述指令就不起作用。類似的構(gòu)建還有DEBUG和RELEASE版本,也需要看makefile.vc和nmake.opt中是否存在相關(guān)的參數(shù)。
2.2 缺點(diǎn)
了解了上述指令之后,大概感覺跟CMake的構(gòu)建指令差不多。其實(shí)差別還是很大的,跟現(xiàn)代構(gòu)建系統(tǒng)相比,nmake還缺失一個(gè)關(guān)鍵的步驟——配置。nmake其實(shí)只是一個(gè)簡(jiǎn)單的make系統(tǒng),對(duì)應(yīng)的就是Linux下的Makefile,可以進(jìn)行編譯、鏈接,也可以把構(gòu)建參數(shù)提取出來,但是無法動(dòng)態(tài)去生成構(gòu)建參數(shù)。具體來說,nmake的配置參數(shù)文件是nmake.opt,但是只有這個(gè)文件還不夠,還需要根據(jù)構(gòu)建環(huán)境不同,動(dòng)態(tài)生成這個(gè)nmake.opt文件。
所以使用nmake構(gòu)建項(xiàng)目的麻煩就在這里,無法根據(jù)需要?jiǎng)討B(tài)地生成項(xiàng)目配置文件,只能手動(dòng)去修改它。比如在之前的文章《CMake構(gòu)建學(xué)習(xí)筆記19-OpenSSL庫的構(gòu)建》中就是如此,也是通過nmake來構(gòu)建OpenSSL庫,但是不能動(dòng)態(tài)生成配置怎么辦呢?OpenSSL的維護(hù)者引入了perl來解決這個(gè)問題。嗯,不得不說,C/C++項(xiàng)目的構(gòu)建系統(tǒng)太混亂了,簡(jiǎn)直是各顯神通;希望以后的項(xiàng)目都能升級(jí)成CMake的構(gòu)建方式吧,不是CMake有多好,先把構(gòu)建的行為統(tǒng)一了再說。
3. 構(gòu)建SpatiaLite
3.1 主項(xiàng)目
在理解了使用nmake構(gòu)建的一般步驟之后,構(gòu)建具體的SpatiaLite項(xiàng)目反而比較簡(jiǎn)單了。從官網(wǎng)上下載最新的5.1.0版本,解壓到本地,可以看到SpatiaLite提供了四個(gè)版本的構(gòu)建配置,如下圖所示:

其中:
makefile.vc是32位構(gòu)建配置。makefile64.vc是64位構(gòu)建配置。makefile_mod.vc是32位模塊化構(gòu)建配置。makefile_mod64.vc是64位模塊化構(gòu)建配置。
這里也可以看到使用nmake構(gòu)建的缺陷,應(yīng)對(duì)不同的構(gòu)建需求,需要提供多個(gè)配置文件。如果是使用CMake構(gòu)建,使用一個(gè)CMakeList.txt即可。現(xiàn)在一般都是64位系統(tǒng),選擇makefile64.vc和nmake64.opt進(jìn)行構(gòu)建。不過為了能正確構(gòu)建,修改nmake64.opt中的內(nèi)容如下:
# Directory tree where SpatiaLite will be installed.
INSTDIR=C:\Work\3rdparty
# Uncomment the first for an optimized build, or the second for debug.
OPTFLAGS= /source-charset:windows-1252 /nologo /Ox /fp:precise /W4 /MD /D_CRT_SECURE_NO_WARNINGS \
/DDLL_EXPORT /DYY_NO_UNISTD_H
#OPTFLAGS= /nologo /Zi /MD /Fdspatialite.pdb /DDLL_EXPORT
# Set the version number for the DLL. Normally we leave this blank since
# we want software that is dynamically loading the DLL to have no problem
# with version numbers.
VERSION=
主要修改了兩點(diǎn):
- INSTDIR表示構(gòu)建后安裝的目錄,按需進(jìn)行修改。
- /source-charset:windows-1252是額外增加的編譯選項(xiàng),用于設(shè)置代碼文件的數(shù)據(jù)集。
修改makefile64.vc中的內(nèi)容為:
# $Id: $
#
# NMAKE Makefile to build libspatialite on Windows
#
!INCLUDE nmake64.opt
LIBOBJ = src\gaiaaux\gg_sqlaux.obj src\gaiaaux\gg_utf8.obj \
src\gaiaexif\gaia_exif.obj src\gaiageo\gg_advanced.obj \
src\gaiageo\gg_endian.obj src\gaiageo\gg_ewkt.obj \
src\gaiageo\gg_geodesic.obj src\gaiageo\gg_geoJSON.obj \
src\gaiageo\gg_geometries.obj src\gaiageo\gg_geoscvt.obj \
src\gaiageo\gg_gml.obj src\gaiageo\gg_kml.obj \
src\gaiageo\gg_relations.obj src\gaiageo\gg_shape.obj \
src\gaiageo\gg_transform.obj src\gaiageo\gg_vanuatu.obj \
src\gaiageo\gg_wkb.obj src\gaiageo\gg_wkt.obj \
src\gaiageo\gg_extras.obj src\gaiageo\gg_xml.obj \
src\gaiageo\gg_voronoj.obj src\gaiageo\gg_matrix.obj \
src\gaiageo\gg_relations_ext.obj src\gaiageo\gg_rttopo.obj \
src/connection_cache/alloc_cache.obj src/connection_cache/gg_sequence.obj \
src\spatialite\mbrcache.obj src\shapefiles\shapefiles.obj \
src\spatialite\spatialite.obj src\spatialite\virtualdbf.obj \
src\spatialite\virtualfdo.obj src\spatialite\virtualnetwork.obj \
src\spatialite\virtualshape.obj src\spatialite\virtualspatialindex.obj \
src\spatialite\statistics.obj src\spatialite\metatables.obj \
src\spatialite\virtualXL.obj src\spatialite\extra_tables.obj \
src\spatialite\virtualxpath.obj src\spatialite\virtualbbox.obj \
src\spatialite\spatialite_init.obj src\spatialite\se_helpers.obj \
src\spatialite\srid_aux.obj src\spatialite\table_cloner.obj \
src\spatialite\virtualelementary.obj src\spatialite\virtualgeojson.obj \
src\spatialite\virtualrouting.obj src\spatialite\create_routing.obj \
src\spatialite\dbobj_scopes.obj src\spatialite\pause.obj \
src\wfs\wfs_in.obj src\srsinit\srs_init.obj src\spatialite\virtualgpkg.obj \
src\dxf\dxf_parser.obj src\dxf\dxf_loader.obj src\dxf\dxf_writer.obj \
src\dxf\dxf_load_distinct.obj src\dxf\dxf_load_mixed.obj \
src\shapefiles\validator.obj src\md5\md5.obj src\md5\gaia_md5.obj \
src\srsinit\epsg_inlined_00.obj src\srsinit\epsg_inlined_01.obj \
src\srsinit\epsg_inlined_02.obj src\srsinit\epsg_inlined_03.obj \
src\srsinit\epsg_inlined_04.obj src\srsinit\epsg_inlined_05.obj \
src\srsinit\epsg_inlined_06.obj src\srsinit\epsg_inlined_07.obj \
src\srsinit\epsg_inlined_08.obj src\srsinit\epsg_inlined_09.obj \
src\srsinit\epsg_inlined_10.obj src\srsinit\epsg_inlined_11.obj \
src\srsinit\epsg_inlined_12.obj src\srsinit\epsg_inlined_13.obj \
src\srsinit\epsg_inlined_14.obj src\srsinit\epsg_inlined_15.obj \
src\srsinit\epsg_inlined_16.obj src\srsinit\epsg_inlined_17.obj \
src\srsinit\epsg_inlined_18.obj src\srsinit\epsg_inlined_19.obj \
src\srsinit\epsg_inlined_20.obj src\srsinit\epsg_inlined_21.obj \
src\srsinit\epsg_inlined_22.obj src\srsinit\epsg_inlined_23.obj \
src\srsinit\epsg_inlined_24.obj src\srsinit\epsg_inlined_25.obj \
src\srsinit\epsg_inlined_26.obj src\srsinit\epsg_inlined_27.obj \
src\srsinit\epsg_inlined_28.obj src\srsinit\epsg_inlined_29.obj \
src\srsinit\epsg_inlined_30.obj src\srsinit\epsg_inlined_31.obj \
src\srsinit\epsg_inlined_32.obj src\srsinit\epsg_inlined_33.obj \
src\srsinit\epsg_inlined_34.obj src\srsinit\epsg_inlined_35.obj \
src\srsinit\epsg_inlined_36.obj src\srsinit\epsg_inlined_37.obj \
src\srsinit\epsg_inlined_38.obj src\srsinit\epsg_inlined_39.obj \
src\srsinit\epsg_inlined_40.obj src\srsinit\epsg_inlined_41.obj \
src\srsinit\epsg_inlined_42.obj src\srsinit\epsg_inlined_43.obj \
src\srsinit\epsg_inlined_44.obj src\srsinit\epsg_inlined_45.obj \
src\srsinit\epsg_inlined_46.obj src\srsinit\epsg_inlined_47.obj \
src\srsinit\epsg_inlined_48.obj src\srsinit\epsg_inlined_49.obj \
src\srsinit\epsg_inlined_50.obj src\srsinit\epsg_inlined_51.obj \
src\srsinit\epsg_inlined_52.obj src\srsinit\epsg_inlined_53.obj \
src\srsinit\epsg_inlined_54.obj src\srsinit\epsg_inlined_55.obj \
src\srsinit\epsg_inlined_56.obj src\srsinit\epsg_inlined_57.obj \
src\srsinit\epsg_inlined_58.obj src\srsinit\epsg_inlined_59.obj \
src\srsinit\epsg_inlined_60.obj src\srsinit\epsg_inlined_61.obj \
src\srsinit\epsg_inlined_62.obj src\srsinit\epsg_inlined_63.obj \
src\srsinit\epsg_inlined_extra.obj src\srsinit\epsg_inlined_prussian.obj \
src\srsinit\epsg_inlined_wgs84_00.obj src\srsinit\epsg_inlined_wgs84_01.obj \
src\versioninfo\version.obj src\virtualtext\virtualtext.obj \
src\cutter\gaia_cutter.obj \
src\spatialite\virtualknn.obj src\spatialite\virtualknn2.obj \
src\control_points\gaia_control_points.obj \
src\control_points\grass_crs3d.obj src\control_points\grass_georef_tps.obj \
src\control_points\grass_georef.obj src\stored_procedures\stored_procedures.obj \
src\geopackage\gaia_cvt_gpkg.obj \
src\geopackage\gpkgAddGeometryColumn.obj \
src\geopackage\gpkg_add_geometry_triggers.obj \
src\geopackage\gpkg_add_spatial_index.obj \
src\geopackage\gpkg_add_tile_triggers.obj \
src\geopackage\gpkgBinary.obj \
src\geopackage\gpkgCreateBaseTables.obj \
src\geopackage\gpkgCreateTilesTable.obj \
src\geopackage\gpkgCreateTilesZoomLevel.obj \
src\geopackage\gpkgGetImageType.obj \
src\geopackage\gpkg_get_normal_row.obj \
src\geopackage\gpkg_get_normal_zoom.obj \
src\geopackage\gpkgInsertEpsgSRID.obj \
src\geopackage\gpkgMakePoint.obj \
src\topology\gaia_auxnet.obj src\topology\gaia_auxtopo.obj \
src\topology\gaia_auxtopo_table.obj src\topology\gaia_netstmts.obj \
src\topology\gaia_network.obj src\topology\gaia_topology.obj \
src\topology\gaia_topostmts.obj src\topology\lwn_network.obj \
src\topology\net_callbacks.obj src\topology\topo_callbacks.obj
SPATIALITE_DLL = spatialite$(VERSION).dll
CFLAGS = /nologo -I.\src\headers -I.\src\topology \
-I. -IC:\Work\3rdparty\include -IC:\Work\3rdparty\include\libxml2 $(OPTFLAGS)
default: all
all: spatialite.lib spatialite_i.lib
#$(EXIF_LOADER_EXE)
spatialite.lib: $(LIBOBJ)
if exist spatialite.lib del spatialite.lib
lib /out:spatialite.lib $(LIBOBJ)
$(SPATIALITE_DLL): spatialite_i.lib
spatialite_i.lib: $(LIBOBJ)
link /dll /out:$(SPATIALITE_DLL) \
/implib:spatialite_i.lib $(LIBOBJ) \
C:\Work\3rdparty\lib\proj.lib C:\Work\3rdparty\lib\geos_c.lib \
C:\Work\3rdparty\lib\freexl_i.lib C:\Work\3rdparty\lib\iconv.lib \
C:\Work\3rdparty\lib\sqlite3.lib C:\Work\3rdparty\lib\zlib.lib \
C:\Work\3rdparty\lib\libxml2.lib C:\Work\3rdparty\lib\librttopo.lib
if exist $(SPATIALITE_DLL).manifest mt -manifest \
$(SPATIALITE_DLL).manifest -outputresource:$(SPATIALITE_DLL);2
.c.obj:
$(CC) $(CFLAGS) /c $*.c /Fo$@
clean:
del *.dll
del *.exp
del *.manifest
del *.lib
del src\connection_cache\*.obj
del src\cutter\*.obj
del src\gaiaaux\*.obj
del src\gaiaexif\*.obj
del src\gaiageo\*.obj
del src\shapefiles\*.obj
del src\spatialite\*.obj
del src\srsinit\*.obj
del src\versioninfo\*.obj
del src\virtualtext\*.obj
del src\wfs\*.obj
del src\dxf\*.obj
del src\md5\*.obj
del src\topology\*.obj
del src\stored_procedures\*.obj
del *.pdb
install: all
-mkdir $(INSTDIR)
-mkdir $(INSTDIR)\bin
-mkdir $(INSTDIR)\lib
-mkdir $(INSTDIR)\include
-mkdir $(INSTDIR)\include\spatialite
copy *.dll $(INSTDIR)\bin
copy *.lib $(INSTDIR)\lib
copy src\headers\spatialite.h $(INSTDIR)\include
copy src\headers\spatialite\*.h $(INSTDIR)\include\spatialite
主要修改了以下兩點(diǎn):
- 修改include文件:
CFLAGS = /nologo -I.\src\headers -I.\src\topology \
-I. -IC:\Work\3rdparty\include -IC:\Work\3rdparty\include\libxml2 $(OPTFLAGS)
- 修改依賴庫文件:
spatialite_i.lib: $(LIBOBJ)
link /dll /out:$(SPATIALITE_DLL) \
/implib:spatialite_i.lib $(LIBOBJ) \
C:\Work\3rdparty\lib\proj.lib C:\Work\3rdparty\lib\geos_c.lib \
C:\Work\3rdparty\lib\freexl_i.lib C:\Work\3rdparty\lib\iconv.lib \
C:\Work\3rdparty\lib\sqlite3.lib C:\Work\3rdparty\lib\zlib.lib \
C:\Work\3rdparty\lib\libxml2.lib C:\Work\3rdparty\lib\librttopo.lib
if exist $(SPATIALITE_DLL).manifest mt -manifest \
$(SPATIALITE_DLL).manifest -outputresource:$(SPATIALITE_DLL);2
都修改完成之后,執(zhí)行:
nmake -f makefile.vc #構(gòu)建
nmake -f makefile.vc install #安裝
nmake -f makefile.vc clean #清理
3.2 依賴項(xiàng)
需要注意的是,makefile64.vc中的內(nèi)容需要根據(jù)依賴庫的安裝地址來進(jìn)行修改。SpatiaLite的依賴項(xiàng)有:proj、geos、freexl、iconv、sqlite3、zlib、libxml2以及l(fā)ibrttopo,這些依賴項(xiàng)都需要提前安裝好,筆者是安裝到C:\Work\3rdparty目錄中。至于具體的構(gòu)建安裝過程,大部分依賴庫可參看如下文章:
- 《CMake構(gòu)建學(xué)習(xí)筆記24-使用通用腳本構(gòu)建PROJ和GEOS》
- 《CMake構(gòu)建學(xué)習(xí)筆記20-iconv庫的構(gòu)建》
- 《CMake構(gòu)建學(xué)習(xí)筆記23-SQLite庫的構(gòu)建》
- 《CMake構(gòu)建學(xué)習(xí)筆記2-zlib庫的構(gòu)建》
- 《CMake構(gòu)建學(xué)習(xí)筆記22-libxml2庫的構(gòu)建》
剩下的就只有freexl和librttopo兩個(gè)依賴性的構(gòu)建了,正好這兩個(gè)也是依賴于nmake構(gòu)建的庫。
3.2.1 構(gòu)建libexpat
在構(gòu)建freexl之前,需要先構(gòu)建libexpat庫。libexpat是一個(gè)用C語言編寫的、開源的、高效的XML解析庫,已經(jīng)支持使用CMake構(gòu)建。那么可以使用以下腳本:
param(
[string]$Name = "libexpat-R_2_7_0",
[string]$SourceDir = "../Source",
[string]$Generator,
[string]$MSBuild,
[string]$InstallDir,
[string]$SymbolDir
)
# 根據(jù) $Name 動(dòng)態(tài)構(gòu)建路徑
$zipFilePath = Join-Path -Path $SourceDir -ChildPath "$Name.zip"
$SourcePath = Join-Path -Path $SourceDir -ChildPath $Name
$BuildDir = Join-Path -Path "." -ChildPath $Name
# 檢查是否已經(jīng)安裝(通過目標(biāo) DLL)
$TargetDll = "$InstallDir/bin/libexpat.dll"
if (-not $Force -and $TargetDll -and (Test-Path $TargetDll)) {
Write-Output "Library already installed: $TargetDll"
exit 0
}
# 確保源碼目錄存在:解壓 ZIP
if (!(Test-Path $SourcePath)) {
if (!(Test-Path $zipFilePath)) {
Write-Error "Archive not found: $zipFilePath"
exit 1
}
Write-Output "Extracting $zipFilePath to $SourceDir..."
Expand-Archive -LiteralPath $zipFilePath -DestinationPath $SourceDir -Force
}
# 如果是強(qiáng)制構(gòu)建,且構(gòu)建目錄已存在,先刪除舊的構(gòu)建目錄(確保干凈構(gòu)建)
if ($Force -and (Test-Path $BuildDir)) {
Write-Output "Force mode enabled. Removing previous build directory: $BuildDir"
Remove-Item $BuildDir -Recurse -Force -ErrorAction SilentlyContinue
}
# # 復(fù)制符號(hào)庫
$PdbFiles = @(
"$BuildDir/RelWithDebInfo/libexpat.pdb"
)
# 額外構(gòu)建參數(shù)
$CMakeCacheVariables = @{
EXPAT_BUILD_DOCS = "OFF"
EXPAT_BUILD_EXAMPLES = "OFF"
EXPAT_BUILD_TESTS = "OFF"
}
# 調(diào)用通用 CMake 構(gòu)建腳本
$cmakeSourcePath = Join-Path -Path $SourcePath -ChildPath "expat"
Write-Output "Starting build for $Name..."
. ./cmake-build.ps1 -SourceLocalPath $cmakeSourcePath `
-BuildDir $BuildDir `
-Generator $Generator `
-InstallDir $InstallDir `
-SymbolDir $SymbolDir `
-PdbFiles $PdbFiles `
-CMakeCacheVariables $CMakeCacheVariables `
-MultiConfig $true
if ($LASTEXITCODE -ne 0) {
Write-Error "Build failed for $Name."
exit $LASTEXITCODE
}
# 構(gòu)建成功后,根據(jù) Cleanup 開關(guān)決定是否刪除
if ($Cleanup) {
Write-Output "Build succeeded. Cleaning up temporary directories..."
if (Test-Path $SourcePath) {
Remove-Item $SourcePath -Recurse -Force -ErrorAction SilentlyContinue
Write-Output "Removed source directory: $SourcePath"
}
if (Test-Path $BuildDir) {
Remove-Item $BuildDir -Recurse -Force -ErrorAction SilentlyContinue
Write-Output "Removed build directory: $BuildDir"
}
}
Write-Output "Build completed for $Name."
腳本cmake-build.ps1筆者已經(jīng)在《CMake構(gòu)建學(xué)習(xí)筆記21-通用的CMake構(gòu)建腳本》這篇文章中介紹過。
3.2.1 freexl構(gòu)建
freexl是一個(gè)開源庫,主要用于讀取Microsoft Excel的.xls文件格式。構(gòu)建freexl與前面介紹nmake構(gòu)建的一般方法基本一致:
nmake -f makefile.vc #構(gòu)建
nmake -f makefile.vc install #安裝
nmake -f makefile.vc clean #清理
當(dāng)然nmake64.opt和makefile64.vc中的內(nèi)容需要根據(jù)自己的情況按需修改。對(duì)于nmake64.opt,修改的內(nèi)容為:
#INSTDIR=C:\OSGeo4W64
INSTDIR=C:\OSGeo4W64
而對(duì)于makefile64.vc,修改的內(nèi)容為:
# CFLAGS = /nologo -I. -Iheaders -IC:\OSGeo4W64\include $(OPTFLAGS)
CFLAGS = /nologo -I. -Iheaders -IC:\Work\3rdparty\include $(OPTFLAGS)
#freexl_i.lib: $(LIBOBJ)
# link /debug /dll /out:$(FREEXL_DLL) \
# /implib:freexl_i.lib $(LIBOBJ) \
# C:\Work\3rdparty\lib\iconv.lib \
# C:\Work\3rdparty\lib\libexpat.lib \
# C:\Work\3rdparty\lib\minizip.lib \
# C:\Work\3rdparty\lib\zlib.lib
# if exist $(FREEXL_DLL).manifest mt -manifest \
# $(FREEXL_DLL).manifest -outputresource:$(FREEXL_DLL);2
freexl_i.lib: $(LIBOBJ)
link /debug /dll /out:$(FREEXL_DLL) \
/implib:freexl_i.lib $(LIBOBJ) \
C:\OSGeo4w64\lib\iconv.lib \
C:\OSGeo4W64\lib\libexpat.lib \
C:\OSGeo4W64\lib\libminizip.lib \
C:\OSGeo4w64\lib\zlib.lib
if exist $(FREEXL_DLL).manifest mt -manifest \
$(FREEXL_DLL).manifest -outputresource:$(FREEXL_DLL);2
3.2.1 librttopo構(gòu)建
librttopo是一個(gè)開源的地理空間操作庫,是PostGIS項(xiàng)目的一部分,提供了一系列用于處理和分析地理數(shù)據(jù)的功能,比如幾何圖形的操作、空間關(guān)系判斷、坐標(biāo)轉(zhuǎn)換等。librttopo使用nmake構(gòu)建有點(diǎn)麻煩,主要原因就是跨平臺(tái)兼容性有點(diǎn)問題,在Windows下有些文件沒有生成導(dǎo)致編譯出錯(cuò)。
可以使用這篇文章中提供了一個(gè)源代碼版本,然后按需修改nmake64.opt:
#INSTDIR=C:\OSGeo4W64
INSTDIR=C:\Work\3rdparty
同樣修改makefile64.vc:
#CFLAGS = /nologo -IC:\OSGeo4W64\include -I. -Iheaders $(OPTFLAGS)
CFLAGS = /nologo -IC:\Work\3rdparty\include -I. -Iheaders $(OPTFLAGS)
#librttopo_i.lib: $(LIBOBJ)
# link /debug /dll /out:$(LIBRTTOPO_DLL) \
# /implib:librrttopo_i.lib $(LIBOBJ) \
# C:\OSGeo4W64\lib\geos_c.lib
# if exist $(LIBRTTOPO_DLL).manifest mt -manifest \
# $(LIBRTTOPO_DLL).manifest -outputresource:$(LIBRTTOPO_DLL);2
librttopo_i.lib: $(LIBOBJ)
link /debug /dll /out:$(LIBRTTOPO_DLL) \
/implib:librrttopo_i.lib $(LIBOBJ) \
C:\Work\3rdparty\lib\geos_c.lib
if exist $(LIBRTTOPO_DLL).manifest mt -manifest \
$(LIBRTTOPO_DLL).manifest -outputresource:$(LIBRTTOPO_DLL);2
三個(gè)nmake構(gòu)建庫修改的配置文件內(nèi)容大致差不多,都是修改安裝目錄,修改依賴庫include目錄,修改鏈接的庫文件,然后執(zhí)行:
nmake -f makefile.vc #構(gòu)建
nmake -f makefile.vc install #安裝
nmake -f makefile.vc clean #清理
4. 問題
如文中所說,這種nmake構(gòu)建的方式有個(gè)很大的問題就是總是需要臨時(shí)修改nmake64.opt和makefile64.vc來應(yīng)對(duì)不同的環(huán)境,這對(duì)于使用腳本自動(dòng)批處理的方式來說不太友好。說白了Windows下所有的邏輯都是基于GUI的,nmake不過是個(gè)臨時(shí)補(bǔ)丁。不過理論上也可以考慮使用環(huán)境變量的方式來避免這個(gè)問題,就留待后續(xù)解決了。

浙公網(wǎng)安備 33010602011771號(hào)