pnggroup/libpng

CMake: How to configure options for pnglibconf generation?

flsobral opened this issue · 4 comments

Currently, this is how I use libpng in my cross platform project:

cmake_minimum_required(VERSION 3.5)
cmake_policy(SET CMP0007 NEW) # CMP0007: list command no longer ignores empty elements.

include(FetchContent)

FetchContent_GetProperties(libpng)
if(NOT libpng_POPULATED)
    message("Setting up PNG...")

    FetchContent_Populate(libpng)
    set(PNG_BUILD_ZLIB ON CACHE BOOL "" FORCE) # Use our own version of zlib
    set(PNG_SHARED OFF CACHE BOOL "" FORCE)
    set(PNG_FRAMEWORK OFF CACHE BOOL "" FORCE)
    set(PNG_EXECUTABLES OFF CACHE BOOL "" FORCE)
    set(PNG_TESTS OFF CACHE BOOL "" FORCE)
    set(PNG_DEBUG_POSTFIX "" CACHE STRING "" FORCE) # XCode gets confused if used

    file(READ ${libpng_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt FILE_CONTENTS)
    string(REPLACE "#endif /* PNGLCONF_H */" "\n#ifndef PNG_ABORT\n#ifdef EXIT_INSTEAD_ABORT\n#  define PNG_ABORT() exit(0)\n#else\n#  define PNG_ABORT() abort()\n#endif\n#endif\n#endif  /* PNGLCONF_H */" FILE_CONTENTS "${FILE_CONTENTS}")
    
    # Disable PNG_WRITE operations
    SET(FILE_OUTPUT "")
    STRING(REGEX REPLACE ";" "\\\\;" FILE_CONTENTS "${FILE_CONTENTS}")
    STRING(REGEX REPLACE "\r?\n" ";" FILE_CONTENTS "${FILE_CONTENTS}")
    list(LENGTH FILE_CONTENTS FILE_LENGTH)
    math(EXPR N "${FILE_LENGTH}-1")
    foreach(FILE_INDEX RANGE ${N})
        list(GET FILE_CONTENTS ${FILE_INDEX} line)
        string(REGEX REPLACE "^(#define PNG_.*WRITE.*_SUPPORTED)$" "//\\1" line "${line}")
        string(REGEX REPLACE "^(#define PNG_SAVE_INT_32_SUPPORTED)$" "//\\1" line "${line}")
        SET(FILE_OUTPUT "${FILE_OUTPUT}${line}\n")
    endforeach()
    file(WRITE ${libpng_BINARY_DIR}/pnglibconf.h "${FILE_OUTPUT}")

    # Replace abort with PNG_ABORT
    file(READ ${libpng_SOURCE_DIR}/pngerror.c FILE_CONTENTS)
    string(REPLACE "abort();" "PNG_ABORT();" FILE_CONTENTS "${FILE_CONTENTS}")
    file(WRITE ${libpng_SOURCE_DIR}/pngerror.c "${FILE_CONTENTS}")

    add_subdirectory(${libpng_SOURCE_DIR} ${libpng_BINARY_DIR})

    # Need this with SKIP_INSTALL_ALL enabled to find the headers
    target_include_directories(png_static PUBLIC 
        ${libpng_SOURCE_DIR}
        ${libpng_BINARY_DIR}
    )

    set_target_properties(
        png_static
        PROPERTIES
        PUBLIC_HEADER "${libpng_SOURCE_DIR} ${libpng_BINARY_DIR}"
        XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET 13.0
    )
endif()

This works for me now, but I can't shake the feeling that there should be a way of configuring the options instead, but I couldn't find out how.

EDIT: Actually, pnglibconf.h gets overwritten by a new one during build. The only way I got it to work was using this instead:
file(READ ${libpng_BINARY_DIR}/pnglibconf.h FILE_CONTENTS)

This way the build fails the first time because the file isn't available, but subsequent builds works fine.

Overwriting the existing pnglibconf is the expected behavior?

Overwriting the existing pnglibconf is the expected behavior?

Yes. Modify the file pngusr.dfa instead. This is not cmake specific.

pnglibconf.h should NEVER be modified; it's almost impossible to get right which is why the whole configuration stuff was created.

See contrib/conftest for examples and the documentation (in the README file.)

I think pngusr.dfa might not be included; it should be included immediately after pnglibconf.dfa. Support for DFA_XTRA is also desirable because that avoids the need to edit the checked-in source file. See Makefile.am line 310 on. I can't work out where this is in cmake.

@flsobral pngusr.dfa does seem to be handled by cmake now, please can you verify it and it this is all fixed close this issue.

@ctruta: fixed (by fixes in CMakeLists.txt et al.)