pnggroup / libpng

LIBPNG: Portable Network Graphics support, official libpng repository
http://libpng.sf.net
Other
1.25k stars 611 forks source link

CMake: How to configure options for pnglibconf generation? #559

Open flsobral opened 4 months ago

flsobral commented 4 months ago

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?

jbowler commented 4 months ago

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.)

jbowler commented 3 weeks ago

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.