CMakeでlibpngにリンクする

#9279469e537b4825be32d853dcd8f5d2
2025.11.29
2025.11.29
  • 環境

    • MacBook Pro (2021)

    • macOS 15.1.1

    • CMake 3.31.5

  • CMakeでFetchContent_Declareを使ってlibpngをリンクする試み

  • libpngはzlibに依存しているため、まずはzlibを持ってくる必要がある

    FetchContent_Declare(
      zlib
      GIT_REPOSITORY https://github.com/madler/zlib.git
      GIT_TAG 5a82f71ed1dfc0bec044d9702463dbdf84ea3b71
      OVERRIDE_FIND_PACKAGE
    )
    FetchContent_MakeAvailable(zlib)
    • 最新リリースはv1.3.1だが、v1.3.1だとZLIB::ZLIBとして別名定義されないためエラーとなる。そのためdevelopの最新コミットを指定している

    • OVERRIDE_FIND_PACKAGEを指定しているのは、libpngのCMakeLists.txtがzlibをfind_packageしているため。OVERRIDE_FIND_PACKAGEを指定することで、find_packageがFetchしたリポジトリを参照するようになる

    • OVERRIDE_FIND_PACKAGEは、CMake 3.24以降でのみ使うことができる

  • zlibのFetchの後で、libpngをFetchする

    • libpngはCMakeLists.txtを提供しているものの、ビルドプロセスに問題がある

    • libpngのビルドプロセスには、<zlib.h>を参照してzlibのバージョン情報を取得するなどの処理が組み込まれている。これは、ビルド時にpnglibconf.hとして生成される

    • しかしこのpnglibconfは、どうやらシステム側の<zlib.h>を参照しているようで、Fetchしたzlibが無視されてしまうという問題がある。これにより、ビルドエラーが発生する:

      .../build/_deps/libpng-src/pngpriv.h:1027:4: error: The include path of <zlib.h> is incorrect
       1027 | #  error The include path of <zlib.h> is incorrect
            |    ^
    • しかしこのpnglibconf.hの生成は、実はスキップしてもビルドが可能である。スキップされた場合には、pnglibconf.h.prebuiltが使われる。特に、システムにawkが入っていない場合は、生成がスキップされる:

      if(PNG_LIBCONF_HEADER STREQUAL "")
        # No custom configuration header file has been specified, so we build it
        # from our DFA files and (optionally) out of the user-supplied DFA file.
        # Find an AWK language processor.
        # Start with specific AWK implementations like gawk and nawk, which are
        # known to work with our scripts, then fall back to the system awk.
        find_program(AWK NAMES gawk nawk awk)
        if(AWK)
          message(STATUS "Found AWK program: ${AWK}")
        else()
          message(STATUS "Could not find an AWK-compatible program")
        endif()
      endif()
      
      # Include the internal module PNGCheckLibconf.cmake
      include("${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/PNGCheckLibconf.cmake")
      
      if(NOT PNG_LIBCONF_HEADER STREQUAL "")
        # Configure libpng with the user-defined pnglibconf.h file.
        png_check_libconf(HEADER "${PNG_LIBCONF_HEADER}")
        configure_file("${PNG_LIBCONF_HEADER}"
                      "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
                      @ONLY)
        add_custom_target(png_genfiles)
      elseif(NOT AWK)
        # No AWK program available to generate pnglibconf.h.
        # Configure libpng with pnglibconf.h.prebuilt.
        png_check_libconf(HEADER "${PNG_LIBCONF_HEADER_PREBUILT}")
        configure_file("${PNG_LIBCONF_HEADER_PREBUILT}"
                      "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
                      @ONLY)
        add_custom_target(png_genfiles)
      else()
        ...
      endif()
    • システム側にawkがあるかどうかに関わらず、pnglibconf.hの生成をスキップするには、次のようにしてfind_programの検索を防止し、常にpnglibconf.h.prebuiltが使われるようにすればよい:

      set(AWK "OFF")
      FetchContent_Declare(
        libpng
        GIT_REPOSITORY https://github.com/pnggroup/libpng.git
        GIT_TAG v1.6.51
      )
      FetchContent_MakeAvailable(libpng)
      unset(AWK)