手把手教你如何为microsoft/vcpkg提交PR
vcpkg是微软出品的C++软件包管理器,包含超过1700个库。使用时如果喜欢的库不在microsoft/vcpkg中或者发现安装后有bug,或者需要升级库到新版本时,可以给microsoft/vcpkg提交PR。本文介绍提交升级vcpkg中库的PR。
以abseil库为例说明。 每个软件包的对应的cmake文件位于ports 目录 假定我们想将abseil由20210324升级到20211102版本.
修改vcpkg.json
将ports/abseil/vcpkg.json中的version-string字段改为新版本的version-string.
修改portfile.cmake
首先我们修改ports/abseil/portfile.cmake,将vcpkg_from_github中的PATCHS 参数中的所有内容删除,REF字段的commitID改为新版本20211102对应的git commitID. SHA512改为0. 如何获取新版本的SHA512呢?在vcpkg工程根目录下运行./vcpkg install abseil,终端打印出如下内容
...
File does not have expected hash:
File path: [ /home/rob/vcpkg/downloads/abseil-abseil-cpp-215105818dfde3174fe799600bb0f3cae233d0bf.tar.gz ]
Expected hash: [ 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ]
Actual hash: [ 75d234eac76be8790cf09e3e1144e4b4cf5cacb61e46961a9e4a35b37d0fa85243afdd5de5f47a006ef96af6fc91ecc0c233297c4c32258c08d46304b3361330 ]
...
将SHA512字段由0改为 75d234eac76be8790cf09e3e1144e4b4cf5cacb61e46961a9e4a35b37d0fa85243afdd5de5f47a006ef96af6fc91ecc0c233297c4c32258c08d46304b3361330 。
重新制作patch
由portfile.cmake中vcpkg_from_github函数可以看到abseil 20210321版本有两个patch,查看内容后发现其中一个已经合入官方abseil的20211102版本,因此对于新版本,我们只需要制作一个patch:fix-cxx-standard.patch。
安装abseil
~/vcpkg/$ ./vcpkg install abseil
Computing installation plan...
The following packages will be built and installed:
abseil[core]:x64-linux -> 20211102.1
Detecting compiler hash for triplet x64-linux...
Restored 0 packages from /home/rob/.cache/vcpkg/archives in 6.639 us. Use --debug to see more details.
Starting package 1/1: abseil:x64-linux
Building package abseil[core]:x64-linux...
-- Using cached abseil-abseil-cpp-215105818dfde3174fe799600bb0f3cae233d0bf.tar.gz.
-- Extracting source /home/rob/vcpkg/downloads/abseil-abseil-cpp-215105818dfde3174fe799600bb0f3cae233d0bf.tar.gz
-- Using source at /home/rob/vcpkg/buildtrees/abseil/src/cae233d0bf-c7dcd484c3.clean
...
从上文中可以看到abseil的20211102版本的源码位于/home/rob/vcpkg/buildtrees/abseil/src/cae233d0bf-c7dcd484c3.clean, 我们到/home/rob/vcpkg/buildtrees/abseil/src/cae233d0bf-c7dcd484c3.clean目录制作patch。
制作新patch
vcpkg使用git diff的输出制作patch,为了使用git diff。我们首先在 /home/rob/vcpkg/buildtrees/abseil/src/cae233d0bf-c7dcd484c3.clean 目录依次运行
git init
git add *
git commit -m "tmp"
这样我们就在/home/rob/vcpkg/buildtrees/abseil/src/cae233d0bf-c7dcd484c3.clean中创建了一个git repo并提交了第一个commit. 然后需要制作 fix-cxx-standard.patch,我们先看看老的patch能否直接使用:
~/vcpkg/buildtrees/abseil/src/cae233d0bf-c7dcd484c3.clean$ patch -p1 < ../../../../ports/abseil/fix-cxx-standard.patch
patching file CMake/abslConfig.cmake.in
patching file CMakeLists.txt
Hunk #1 succeeded at 74 with fuzz 1 (offset 17 lines).
patching file absl/base/CMakeLists.txt
patching file absl/base/options.h
成功了,我们不需要自己修改options.h等文件了。 然后更新fix-cxx-standard.patch
~/vcpkg/buildtrees/abseil/src/cae233d0bf-c7dcd484c3.clean$ git diff . > ../../../../ports/abseil/fix-cxx-standard.patch
再次修改ports/abseil/portfile.cmake 将fix-cxx-standard.patch加回vcpkg_from_github PATCHS参数
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO abseil/abseil-cpp
REF 215105818dfde3174fe799600bb0f3cae233d0bf #LTS 20211102, Patch 1
SHA512 75d234eac76be8790cf09e3e1144e4b4cf5cacb61e46961a9e4a35b37d0fa85243afdd5de5f47a006ef96af6fc91ecc0c233297c4c32258c08d46304b3361330
HEAD_REF master
PATCHES
# in C++17 mode, use std::any, std::optional, std::string_view, std::variant
# instead of the library replacement types
# in C++11 mode, force use of library replacement types, otherwise the automatic
# detection can cause ABI issues depending on which compiler options
# are enabled for consuming user code
fix-cxx-standard.patch
)
重新安装验证新patch能工作
~/vcpkg$ ./vcpkg remove abseil
~/vcpkg$ ./vcpkg install abseil
Computing installation plan...
The following packages will be built and installed:
abseil[core]:x64-linux -> 20211102.1
Detecting compiler hash for triplet x64-linux...
Restored 0 packages from /home/rob/.cache/vcpkg/archives in 3.718 us. Use --debug to see more details.
Starting package 1/1: abseil:x64-linux
Building package abseil[core]:x64-linux...
-- Using cached abseil-abseil-cpp-215105818dfde3174fe799600bb0f3cae233d0bf.tar.gz.
-- Cleaning sources at /home/rob/vcpkg/buildtrees/abseil/src/cae233d0bf-9df62c4674.clean. Use --editable to skip cleaning for the packages you specify.
-- Extracting source /home/rob/vcpkg/downloads/abseil-abseil-cpp-215105818dfde3174fe799600bb0f3cae233d0bf.tar.gz
-- Applying patch fix-cxx-standard.patch
-- Using source at /home/rob/vcpkg/buildtrees/abseil/src/cae233d0bf-9df62c4674.clean
-- Configuring x64-linux-dbg
-- Configuring x64-linux-rel
-- Building x64-linux-dbg
提交更改
更改需要分两次提交,因为vcpkg的versions/中用到ports/中的git tree index的信息。 首先提交一次 ports的更改
git add ports/abseil
git commit -m"[abseil] update to 20211102"
然后修改versions
~/vcpkg$ ./vcpkg x-add-version --skip-version-format-check abseil
~/vcpkg$ git status
On branch proxygen
Your branch is ahead of 'origin/proxygen' by 2 commits.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: versions/a-/abseil.json
modified: versions/baseline.json
然后再amend versions的修改
git commit -a --amend --no-edit
大功告成! 接下来,我们便可以将对abseil的更新push到自己fork的vcpkg仓库,然后向microsoft/vcpkg提交pr了。
bonus: 制作一个port的多个patch
有时我们需要制作多个patch,针对不同的功能,这时需要在port的buildtree下的源码目录提交多次
~/openSrc/vcpkg/buildtrees/abseil/src/cae233d0bf-0b16e4be7c.clean master> git log
34c4a53 (Wed Apr 13 11:39:33 2022) jiayuehua second patch
3209c04 (Wed Apr 13 11:37:44 2022) jiayuehua first patch
ae508e7 (Wed Apr 13 11:34:53 2022) jiayuehua tmp
这里tmp是直接下载源码后的提交,”first patch”是第一个改动的提交,”second patch”是第二个改动的提交。确保源码目录所有改动都已经提交
~/openSrc/vcpkg/buildtrees/abseil/src/cae233d0bf-0b16e4be7c.clean master> git status
On branch master
nothing to commit, working tree clean
这时可运行vcpkgformatpatch
~/openSrc/vcpkg/buildtrees/abseil/src/cae233d0bf-0b16e4be7c.clean master> vcpkgformatpatch
0001-first-patch.patch
0002-second-patch.patch
然后将0001-firt-patch.patch 和0002-second-patch.patch拷贝到 ~/openSrc/vcpkg/ports/abseil/目录,再修改 ~/openSrc/vcpkg/ports/abseil/portfile.cmake 中的vcpkg_from_github函数,将这两个patch作为PATCHES的参数
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO abseil/abseil-cpp
REF 215105818dfde3174fe799600bb0f3cae233d0bf #LTS 20211102, Patch 1
SHA512 75d234eac76be8790cf09e3e1144e4b4cf5cacb61e46961a9e4a35b37d0fa85243afdd5de5f47a006ef96af6fc91ecc0c233297c4c32258c08d46304b3361330
HEAD_REF master
PATCHES
0001-first-patch.patch
0002-second-patch.patch
)
vcpkgformatpatch是我写的一个脚本,内容
/usr/local/bin> cat vcpkgformatpatch
#!/bin/zsh
CommitsNum=`git rev-list --count master`
git format-patch --no-stat --no-signature "-$((CommitsNum-1))"
sed -i -n '/^diff/,$p' 0*.patch
你便了解了制作多个patch的全部奥秘。
参考了 https://github.com/microsoft/vcpkg/pull/22017 我以前成功被merge的abseil的Pull request。