补丁示例:为libpng打补丁以适配x64-UWP平台
本文介绍如何为kmpkg端口文件中的libpng库开发并应用补丁,解决其在x64-UWP平台下的兼容性问题。
第一步:查看初始错误日志
首先尝试构建libpng:x64-uwp包(--editable参数保留源码目录,方便调试):
PS D:\src\kmpkg> kmpkg install libpng:x64-uwp --editable
Computing installation plan...
The following packages will be built and installed:
libpng[core]:x64-uwp
Starting package 1/1: libpng:x64-uwp
Building package libpng[core]:x64-uwp...
-- Using cached D:/src/kmpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
-- Extracting source D:/src/kmpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
-- Using source at D:/src/kmpkg/buildtrees/libpng/src/v1.6.37-c993153cdf
-- Configuring x64-uwp
-- Building x64-uwp-rel
CMake Error at scripts/cmake/execute_required_process.cmake:14 (message):
Command failed: C:/Program Files/CMake/bin/cmake.exe;--build;.;--config;Release
Working Directory: D:/src/kmpkg/buildtrees/libpng/x64-uwp-rel
See logs for more information:
D:\src\kmpkg\buildtrees\libpng\build-x64-uwp-rel-out.log
D:\src\kmpkg\buildtrees\libpng\build-x64-uwp-rel-err.log
Call Stack (most recent call first):
scripts/cmake/kmpkg_build_cmake.cmake:3 (execute_required_process)
ports/libpng/portfile.cmake:22 (kmpkg_build_cmake)
scripts/ports.cmake:84 (include)
Error: build command failed
接下来查看日志文件(build-xxx-out.log 和 build-xxx-err.log),核心错误如下:
// build-x64-uwp-rel-out.log
...
"D:\src\kmpkg\buildtrees\libpng\x64-uwp-rel\ALL_BUILD.vcxproj" (默认目标) (1) ->
"D:\src\kmpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj" (默认目标) (3) ->
(ClCompile 目标) ->
D:\src\kmpkg\buildtrees\libpng\src\v1.6.37-c993153cdf\pngerror.c(775): 警告 C4013: “ExitProcess”未定义;假设外部返回 int [D:\src\kmpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj]
"D:\src\kmpkg\buildtrees\libpng\x64-uwp-rel\ALL_BUILD.vcxproj" (默认目标) (1) ->
"D:\src\kmpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj" (默认目标) (3) ->
(Link 目标) ->
pngerror.obj : 错误 LNK2019: 无法解析的外部符号 _ExitProcess,该符号在函数 _png_longjmp 中被引用 [D:\src\kmpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj]
D:\src\kmpkg\buildtrees\libpng\x64-uwp-rel\Release\libpng16.dll : 致命错误 LNK1120: 1 个无法解析的外部命令 [D:\src\kmpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj]
1 个警告
2 个错误
耗时 00:00:04.19
第二步:定位问题代码
查阅Microsoft Learn文档可知,ExitProcess 仅适用于桌面应用程序;结合代码上下文进一步分析:
/* buildtrees\libpng\src\v1.6.37-c993153cdf\pngerror.c:769 */
/* 如果执行到此处,png_longjmp() 一定不能返回。
* 唯一的选择是终止整个进程(或线程);
* 除非通过覆盖默认配置项 PNG_ABORT() 实现自定义逻辑,
* 否则将调用ANSI-C标准的abort()函数。
*/
PNG_ABORT();
递归搜索 PNG_ABORT 宏的定义:
PS D:\src\kmpkg\buildtrees\libpng\src\v1.6.37-c993153cdf> findstr /snipl "PNG_ABORT" *
CHANGES:701: 新增 PNG_SETJMP_SUPPORTED、PNG_SETJMP_NOT_SUPPORTED 和 PNG_ABORT() 宏
libpng-manual.txt:432:错误将触发 PNG_ABORT() 调用(默认指向 abort())。
libpng-manual.txt:434:你可以通过 #define PNG_ABORT() 自定义处理函数
libpng-manual.txt:2753:错误将触发 PNG_ABORT() 调用(默认指向 abort())。
libpng-manual.txt:2755:你可以通过 #define PNG_ABORT() 自定义处理函数
libpng-manual.txt:4226:PNG_NO_SETJMP 模式下,错误将通过 PNG_ABORT() 处理),
libpng.3:942:错误将触发 PNG_ABORT() 调用(默认指向 abort())。
libpng.3:944:你可以通过 #define PNG_ABORT() 自定义处理函数
libpng.3:3263:错误将触发 PNG_ABORT() 调用(默认指向 abort())。
libpng.3:3265:你可以通过 #define PNG_ABORT() 自定义处理函数
libpng.3:4736:PNG_NO_SETJMP 模式下,错误将通过 PNG_ABORT() 处理),
png.h:994: * 会使用该函数;否则将调用 PNG_ABORT()。该函数于
pngerror.c:773: * PNG_ABORT()。
pngerror.c:775: PNG_ABORT();
pngpriv.h:459:#ifndef PNG_ABORT
pngpriv.h:461:# define PNG_ABORT() ExitProcess(0)
pngpriv.h:463:# define PNG_ABORT() abort()
完整的宏定义暴露了核心问题:
/* buildtrees\libpng\src\v1.6.37-c993153cdf\pngpriv.h:459 */
#ifndef PNG_ABORT
# ifdef _WINDOWS_
# define PNG_ABORT() ExitProcess(0) // UWP平台不支持该函数
# else
# define PNG_ABORT() abort()
# endif
#endif
abort() 是标准C运行时(CRT)函数,UWP平台完全支持。因此只需修改代码,让libpng在所有平台下统一使用 abort() 即可。
说明:本案例中也可通过编译器参数覆盖
PNG_ABORT定义,但该宏位于私有头文件中,直接打补丁是更可靠的方式(避免引入额外编译开关,尤其当库未将该选项暴露为CMake配置项时)。
第三步:打补丁以提升兼容性
推荐使用Git创建补丁文件(前提是已安装Git):
1. 初始化Git仓库并提交源码(仅用于生成补丁)
PS D:\src\kmpkg\buildtrees\libpng\src\v1.6.37-c993153cdf> git init .
已初始化空的 Git 仓库于 D:/src/kmpkg/buildtrees/libpng/src/v1.6.37-c993153cdf/.git/
PS D:\src\kmpkg\buildtrees\libpng\src\v1.6.37-c993153cdf> git add .
warning: LF 将被替换为 CRLF 于 ANNOUNCE。
文件在工作目录中会保留其原始行结束符。
...
PS D:\src\kmpkg\buildtrees\libpng\src\v1.6.37-c993153cdf> git commit -m "temp"
[master (根提交) 68f253f] temp
422 个文件被更改,插入 167717 行(+)
...
2. 修改代码,统一使用 abort()
编辑 pngpriv.h,移除平台判断,让 PNG_ABORT 全局指向 abort():
/* buildtrees\libpng\src\v1.6.37-c993153cdf\pngpriv.h:459 */
#ifndef PNG_ABORT
# define PNG_ABORT() abort() // 所有平台统一使用abort()
#endif
3. 导出补丁文件到端口目录
PS buildtrees\libpng\src\v1.6.37-c993153cdf> git diff --output ..\..\..\..\ports\libpng\use-abort-on-all-platforms.patch
4. 在端口文件中添加补丁应用逻辑
修改 ports\libpng\portfile.cmake,在源码解压后应用补丁:
# ports\libpng\portfile.cmake
...
kmpkg_extract_source_archive_ex(
OUT_SOURCE_PATH SOURCE_PATH
ARCHIVE ${ARCHIVE}
PATCHES
"use-abort-on-all-platforms.patch" # 新增补丁引用
)
kmpkg_cmake_configure(
...
第四步:验证补丁效果
为确保补丁从全新环境生效,先卸载已构建的包:
PS D:\src\kmpkg> kmpkg remove libpng:x64-uwp
Package libpng:x64-uwp was successfully removed
重新执行全新安装,验证构建是否成功:
PS D:\src\kmpkg> kmpkg install libpng:x64-uwp
Computing installation plan...
The following packages will be built and installed:
libpng[core]:x64-uwp
Starting package 1/1: libpng:x64-uwp
Building package libpng[core]:x64-uwp...
Could not locate cached archive: C:\Users\me\AppData\Local\kmpkg/archives\f4\f44b54f818f78b9a4ccd34b3666f566f94286850.zip
-- Using cached D:/src/kmpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
-- Extracting source D:/src/kmpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
-- Applying patch use_abort.patch
-- Applying patch cmake.patch
-- Applying patch pkgconfig.patch
-- Applying patch pkgconfig.2.patch
-- Using source at D:/src/kmpkg/buildtrees/libpng/src/v1.6.37-10db9f58e4.clean
-- Configuring x64-uwp
-- Building x64-uwp-dbg
-- Building x64-uwp-rel
-- Fixing pkgconfig file: D:/src/kmpkg/packages/libpng_x64-uwp/lib/pkgconfig/libpng.pc
-- Fixing pkgconfig file: D:/src/kmpkg/packages/libpng_x64-uwp/lib/pkgconfig/libpng16.pc
-- Fixing pkgconfig file: D:/src/kmpkg/packages/libpng_x64-uwp/debug/lib/pkgconfig/libpng.pc
-- Fixing pkgconfig file: D:/src/kmpkg/packages/libpng_x64-uwp/debug/lib/pkgconfig/libpng16.pc
-- Installing: D:/src/kmpkg/packages/libpng_x64-uwp/share/libpng/copyright
-- Performing post-build validation
-- Performing post-build validation done
Stored binary cache: C:\Users\me\AppData\Local\kmpkg/archives\f4\f44b54f818f78b9a4ccd34b3666f566f94286850.zip
Building package libpng[core]:x64-uwp... done
Installing package libpng[core]:x64-uwp...
Installing package libpng[core]:x64-uwp... done
Elapsed time for package libpng:x64-uwp: 11.94 s
Total elapsed time: 11.95 s
The package libpng:x64-uwp provides CMake targets:
find_package(libpng CONFIG REQUIRED)
target_link_libraries(main PRIVATE png)
第五步:提交并发布修改
最后需更新 kmpkg.json 中的端口版本号(标识端口文件有修改),将补丁文件加入版本控制,并提交Pull Request:
{
"name": "libpng",
"version": "1.6.37",
"port-version": 1, // 端口版本号+1
"dependencies": [
"zlib"
]
}
至此,完成libpng适配x64-UWP平台的补丁开发与应用全流程。