パッチ適用の例: x64-uwp で動作するように libpng にパッチを適用する

初期エラー ログ

まず、次のビルドを試します。

PS D:\src\vcpkg> vcpkg 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/vcpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
-- Extracting source D:/src/vcpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
-- Using source at D:/src/vcpkg/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/vcpkg/buildtrees/libpng/x64-uwp-rel

  See logs for more information:

      D:\src\vcpkg\buildtrees\libpng\build-x64-uwp-rel-out.log
      D:\src\vcpkg\buildtrees\libpng\build-x64-uwp-rel-err.log

Call Stack (most recent call first):
  scripts/cmake/vcpkg_build_cmake.cmake:3 (execute_required_process)
  ports/libpng/portfile.cmake:22 (vcpkg_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\vcpkg\buildtrees\libpng\x64-uwp-rel\ALL_BUILD.vcxproj" (default target) (1) ->
"D:\src\vcpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj" (default target) (3) ->
(ClCompile target) -> 
  D:\src\vcpkg\buildtrees\libpng\src\v1.6.37-c993153cdf\pngerror.c(775): warning C4013: 'ExitProcess' undefined; assuming extern returning int [D:\src\vcpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj]


"D:\src\vcpkg\buildtrees\libpng\x64-uwp-rel\ALL_BUILD.vcxproj" (default target) (1) ->
"D:\src\vcpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj" (default target) (3) ->
(Link target) -> 
  pngerror.obj : error LNK2019: unresolved external symbol _ExitProcess referenced in function _png_longjmp [D:\src\vcpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj]
  D:\src\vcpkg\buildtrees\libpng\x64-uwp-rel\Release\libpng16.dll : fatal error LNK1120: 1 unresolved externals [D:\src\vcpkg\buildtrees\libpng\x64-uwp-rel\png.vcxproj]

    1 Warning(s)
    2 Error(s)

Time Elapsed 00:00:04.19

問題のあるコードを特定する

MSDN見ると、デスクトップ アプリでのみ使用できる内容ExitProcessが示されています。 さらに、周囲のコンテキストを確認すると便利です。

/* buildtrees\libpng\src\v1.6.37-c993153cdf\pngerror.c:769 */
    /* If control reaches this point, png_longjmp() must not return. The only
    * choice is to terminate the whole process (or maybe the thread); to do
    * this the ANSI-C abort() function is used unless a different method is
    * implemented by overriding the default configuration setting for
    * PNG_ABORT().
    */
    PNG_ABORT();

再帰的に検索すると PNG_ABORT 、次の定義が表示されます。

PS D:\src\vcpkg\buildtrees\libpng\src\v1.6.37-c993153cdf> findstr /snipl "PNG_ABORT" *
CHANGES:701:  Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros
libpng-manual.txt:432:errors will result in a call to PNG_ABORT() which defaults to abort().
libpng-manual.txt:434:You can #define PNG_ABORT() to a function that does something
libpng-manual.txt:2753:errors will result in a call to PNG_ABORT() which defaults to abort().
libpng-manual.txt:2755:You can #define PNG_ABORT() to a function that does something
libpng-manual.txt:4226:PNG_NO_SETJMP, in which case it is handled via PNG_ABORT()),
libpng.3:942:errors will result in a call to PNG_ABORT() which defaults to abort().
libpng.3:944:You can #define PNG_ABORT() to a function that does something
libpng.3:3263:errors will result in a call to PNG_ABORT() which defaults to abort().
libpng.3:3265:You can #define PNG_ABORT() to a function that does something
libpng.3:4736:PNG_NO_SETJMP, in which case it is handled via PNG_ABORT()),
png.h:994: * will use it; otherwise it will call PNG_ABORT().  This function was
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)
#  else
#    define PNG_ABORT() abort()
#  endif
#endif

abort() は標準的な CRT 呼び出しであり、UWP で確実に利用できるため、libpng をよりプラットフォームに依存しないように確信する必要があります。 これを実現する最も簡単で最も信頼性の高い方法は、コードにパッチを適用することです。この特定のケースでは、これがプライベート ヘッダーであるため、オーバーライド PNG_ABORT するコンパイラ フラグを渡すことができますが、一般に、必要なコンパイラ スイッチを可能な限り追加しないようにする方が信頼性が高くなります (特に、CMake オプションとしてまだ公開されていない場合)。

互換性を向上させるためにコードに修正プログラムを適用する

既にインストールされているので、git を使用してパッチ ファイルを作成することをお勧めします。

PS D:\src\vcpkg\buildtrees\libpng\src\v1.6.37-c993153cdf> git init .
Initialized empty Git repository in D:/src/vcpkg/buildtrees/libpng/src/v1.6.37-c993153cdf/.git/

PS D:\src\vcpkg\buildtrees\libpng\src\v1.6.37-c993153cdf> git add .
warning: LF will be replaced by CRLF in ANNOUNCE.
The file will have its original line endings in your working directory.
...

PS D:\src\vcpkg\buildtrees\libpng\src\v1.6.37-c993153cdf> git commit -m "temp"
[master (root-commit) 68f253f] temp
 422 files changed, 167717 insertions(+)
...

これで、あらゆる場所で使用abort()するように変更pngpriv.hできます。

/* buildtrees\libpng\src\v1.6.37-c993153cdf\pngpriv.h:459 */
#ifndef PNG_ABORT
#  define PNG_ABORT() abort()
#endif

出力 git diff は既にパッチ形式なので、パッチをディレクトリに ports/libpng 保存するだけで済みます。

PS buildtrees\libpng\src\v1.6.37-c993153cdf> git diff --ignore-space-at-eol | out-file -enc ascii ..\..\..\..\ports\libpng\use-abort-on-all-platforms.patch

最後に、ソースを抽出した後にパッチを適用する必要があります。

# ports\libpng\portfile.cmake
...
vcpkg_extract_source_archive_ex(
  OUT_SOURCE_PATH SOURCE_PATH
  ARCHIVE ${ARCHIVE}
  PATCHES 
    "use-abort-on-all-platforms.patch"
)

vcpkg_cmake_configure(
...

検証

これがゼロから動作することを完全に確認するには、パッケージを削除して再構築する必要があります。

PS D:\src\vcpkg> vcpkg remove libpng:x64-uwp
Package libpng:x64-uwp was successfully removed

今、私たちは最初から、新しいインストールを試してみてください。

PS D:\src\vcpkg> vcpkg 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\vcpkg/archives\f4\f44b54f818f78b9a4ccd34b3666f566f94286850.zip
-- Using cached D:/src/vcpkg/downloads/glennrp-libpng-v1.6.37.tar.gz
-- Extracting source D:/src/vcpkg/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/vcpkg/buildtrees/libpng/src/v1.6.37-10db9f58e4.clean
-- Configuring x64-uwp
-- Building x64-uwp-dbg
-- Building x64-uwp-rel
-- Fixing pkgconfig file: D:/src/vcpkg/packages/libpng_x64-uwp/lib/pkgconfig/libpng.pc
-- Fixing pkgconfig file: D:/src/vcpkg/packages/libpng_x64-uwp/lib/pkgconfig/libpng16.pc
-- Fixing pkgconfig file: D:/src/vcpkg/packages/libpng_x64-uwp/debug/lib/pkgconfig/libpng.pc
-- Fixing pkgconfig file: D:/src/vcpkg/packages/libpng_x64-uwp/debug/lib/pkgconfig/libpng16.pc
-- Installing: D:/src/vcpkg/packages/libpng_x64-uwp/share/libpng/copyright
-- Performing post-build validation
-- Performing post-build validation done
Stored binary cache: C:\Users\me\AppData\Local\vcpkg/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)

最後に、変更を完全にコミットして発行するには、ポート バージョンをバンプイン vcpkg.jsonし、パッチ ファイルをソース管理に追加してから、プル要求を行う必要があります。

{
  "name": "libpng",
  "version": "1.6.37",
  "port-version": 1,
  "dependencies": [
    "zlib"
  ]
}