• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2# CMakeLists.txt - CMake lists for libpng
3#
4# Copyright (c) 2018-2024 Cosmin Truta.
5# Copyright (c) 2007-2018 Glenn Randers-Pehrson.
6# Originally written by Christian Ehrlicher, 2007.
7#
8# Use, modification and distribution are subject to
9# the same licensing terms and conditions as libpng.
10# Please see the copyright notice in png.h or visit
11# http://libpng.org/pub/png/src/libpng-LICENSE.txt
12#
13# For copyright and licensing purposes, please see
14# the accompanying file scripts/cmake/AUTHORS.md
15#
16# SPDX-License-Identifier: libpng-2.0
17
18cmake_minimum_required(VERSION 3.6)
19
20set(PNGLIB_MAJOR 1)
21set(PNGLIB_MINOR 6)
22set(PNGLIB_REVISION 43)
23set(PNGLIB_SUBREVISION 0)
24#set(PNGLIB_SUBREVISION "git")
25set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_REVISION})
26set(PNGLIB_ABI_VERSION ${PNGLIB_MAJOR}${PNGLIB_MINOR})
27set(PNGLIB_SHARED_VERSION ${PNGLIB_ABI_VERSION}.${PNGLIB_REVISION}.${PNGLIB_SUBREVISION})
28
29project(libpng
30        VERSION ${PNGLIB_VERSION}
31        LANGUAGES C ASM)
32
33if(POLICY CMP0074)
34  # Allow find_package() to use the ZLIB_ROOT variable, if available.
35  cmake_policy(SET CMP0074 NEW)
36endif()
37
38include(CheckCSourceCompiles)
39include(GNUInstallDirs)
40
41# Allow the users to specify an application-specific API prefix for libpng
42# vendoring purposes. A standard libpng build should have no such prefix.
43set(PNG_PREFIX ""
44    CACHE STRING "Prefix to prepend to the API function names")
45
46# Allow the users to override the postfix appended to debug library file names.
47# Previously, we used to set CMAKE_DEBUG_POSTFIX globally. That variable should
48# not be cached, however, because doing so would affect all projects processed
49# after libpng, in unexpected and undesirable ways.
50set(PNG_DEBUG_POSTFIX "d"
51    CACHE STRING "Postfix to append to library file names under the Debug configuration")
52
53# Allow the users to import their own extra configuration settings.
54set(DFA_XTRA ""
55    CACHE FILEPATH "File containing extra configuration settings")
56
57# Allow the users to switch on/off various library build types.
58option(PNG_SHARED "Build libpng as a shared library" ON)
59option(PNG_STATIC "Build libpng as a static library" ON)
60if(APPLE)
61  option(PNG_FRAMEWORK "Build libpng as a framework bundle" ON)
62endif()
63
64# Allow the users to switch on/off the auxiliary build and test artifacts.
65# These artifacts are NOT part of libpng proper, and are subject to change
66# at any time.
67option(PNG_TESTS "Build the libpng tests" ON)
68
69# Same as above, but for the third-party tools.
70# Although these tools are targetted at development environments only,
71# the users are allowed to override the option to build by default.
72if (ANDROID OR IOS)
73  option(PNG_TOOLS "Build the libpng tools" OFF)
74else()
75  option(PNG_TOOLS "Build the libpng tools" ON)
76endif()
77
78# Maintain backwards compatibility with the deprecated option PNG_EXECUTABLES.
79option(PNG_EXECUTABLES "[Deprecated; please use PNG_TOOLS]" ON)
80if(NOT PNG_EXECUTABLES)
81  message(DEPRECATION "The option PNG_EXECUTABLES has been deprecated in favour of PNG_TOOLS")
82  if(PNG_TOOLS)
83    message(AUTHOR_WARNING
84            "Setting PNG_TOOLS to ${PNG_EXECUTABLES}, to stay compatible with PNG_EXECUTABLES")
85    set(PNG_TOOLS "${PNG_EXECUTABLES}")
86  endif()
87endif()
88
89# Allow the users to configure various compilation options.
90option(PNG_DEBUG "Enable debug output" OFF)
91option(PNG_HARDWARE_OPTIMIZATIONS "Enable hardware optimizations" ON)
92
93# Allow the users to specify a custom location of zlib.
94# This option is deprecated, and no longer needed with CMake 3.12 and newer.
95# Under the CMake policy CMP0074, if zlib is being built alongside libpng as a
96# subproject, its location can be passed on to CMake via the ZLIB_ROOT variable.
97option(PNG_BUILD_ZLIB "Custom zlib location, else find_package is used" OFF)
98if(NOT PNG_BUILD_ZLIB)
99  find_package(ZLIB REQUIRED)
100elseif(POLICY CMP0074)
101  if("x${ZLIB_ROOT}" STREQUAL "x")
102    message(DEPRECATION
103            "The option PNG_BUILD_ZLIB has been deprecated; please use ZLIB_ROOT instead")
104  else()
105    message(SEND_ERROR
106            "The option PNG_BUILD_ZLIB=${PNG_BUILD_ZLIB} and "
107            "the variable ZLIB_ROOT=\"${ZLIB_ROOT}\" are mutually exclusive")
108  endif()
109endif()
110
111if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU AND NOT EMSCRIPTEN)
112  find_library(M_LIBRARY m)
113  if(M_LIBRARY)
114    set(M_LIBRARY m)
115  else()
116    set(M_LIBRARY "")
117  endif()
118else()
119  # libm is not available or not needed.
120endif()
121
122# CMake currently sets CMAKE_SYSTEM_PROCESSOR to one of x86_64 or arm64 on macOS,
123# based upon the OS architecture, not the target architecture. As such, we need
124# to check CMAKE_OSX_ARCHITECTURES to identify which hardware-specific flags to
125# enable. Note that this will fail if you attempt to build a universal binary in
126# a single CMake invocation.
127if (APPLE AND CMAKE_OSX_ARCHITECTURES)
128  set(TARGET_ARCH ${CMAKE_OSX_ARCHITECTURES})
129else()
130  set(TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR})
131endif()
132
133if(PNG_HARDWARE_OPTIMIZATIONS)
134
135# Set definitions and sources for ARM.
136if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)")
137  if(TARGET_ARCH MATCHES "^(ARM64|arm64|aarch64)")
138    set(PNG_ARM_NEON_POSSIBLE_VALUES on off)
139    set(PNG_ARM_NEON "on"
140        CACHE STRING "Enable ARM NEON optimizations: on|off; on is default")
141  else()
142    set(PNG_ARM_NEON_POSSIBLE_VALUES check on off)
143    set(PNG_ARM_NEON "off"
144        CACHE STRING "Enable ARM NEON optimizations: check|on|off; off is default")
145  endif()
146  set_property(CACHE PNG_ARM_NEON
147               PROPERTY STRINGS ${PNG_ARM_NEON_POSSIBLE_VALUES})
148  list(FIND PNG_ARM_NEON_POSSIBLE_VALUES ${PNG_ARM_NEON} index)
149  if(index EQUAL -1)
150    message(FATAL_ERROR "PNG_ARM_NEON must be one of [${PNG_ARM_NEON_POSSIBLE_VALUES}]")
151  elseif(NOT PNG_ARM_NEON STREQUAL "off")
152    set(libpng_arm_sources
153        arm/arm_init.c
154        arm/filter_neon_intrinsics.c
155        arm/palette_neon_intrinsics.c)
156    if(NOT MSVC)
157      list(APPEND libpng_arm_sources arm/filter_neon.S)
158    endif()
159    if(PNG_ARM_NEON STREQUAL "on")
160      add_definitions(-DPNG_ARM_NEON_OPT=2)
161    elseif(PNG_ARM_NEON STREQUAL "check")
162      add_definitions(-DPNG_ARM_NEON_CHECK_SUPPORTED)
163    endif()
164  else()
165    add_definitions(-DPNG_ARM_NEON_OPT=0)
166  endif()
167endif()
168
169# Set definitions and sources for PowerPC.
170if(TARGET_ARCH MATCHES "^(powerpc|ppc64)")
171  set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off)
172  set(PNG_POWERPC_VSX "on"
173      CACHE STRING "Enable POWERPC VSX optimizations: on|off; on is default")
174  set_property(CACHE PNG_POWERPC_VSX
175               PROPERTY STRINGS ${PNG_POWERPC_VSX_POSSIBLE_VALUES})
176  list(FIND PNG_POWERPC_VSX_POSSIBLE_VALUES ${PNG_POWERPC_VSX} index)
177  if(index EQUAL -1)
178    message(FATAL_ERROR "PNG_POWERPC_VSX must be one of [${PNG_POWERPC_VSX_POSSIBLE_VALUES}]")
179  elseif(NOT PNG_POWERPC_VSX STREQUAL "off")
180    set(libpng_powerpc_sources
181        powerpc/powerpc_init.c
182        powerpc/filter_vsx_intrinsics.c)
183    if(PNG_POWERPC_VSX STREQUAL "on")
184      add_definitions(-DPNG_POWERPC_VSX_OPT=2)
185    endif()
186  else()
187    add_definitions(-DPNG_POWERPC_VSX_OPT=0)
188  endif()
189endif()
190
191# Set definitions and sources for Intel.
192if(TARGET_ARCH MATCHES "^(i[3-6]86|x86|AMD64)")
193  set(PNG_INTEL_SSE_POSSIBLE_VALUES on off)
194  set(PNG_INTEL_SSE "on"
195      CACHE STRING "Enable INTEL_SSE optimizations: on|off; on is default")
196  set_property(CACHE PNG_INTEL_SSE
197               PROPERTY STRINGS ${PNG_INTEL_SSE_POSSIBLE_VALUES})
198  list(FIND PNG_INTEL_SSE_POSSIBLE_VALUES ${PNG_INTEL_SSE} index)
199  if(index EQUAL -1)
200    message(FATAL_ERROR "PNG_INTEL_SSE must be one of [${PNG_INTEL_SSE_POSSIBLE_VALUES}]")
201  elseif(NOT PNG_INTEL_SSE STREQUAL "off")
202    set(libpng_intel_sources
203        intel/intel_init.c
204        intel/filter_sse2_intrinsics.c)
205    if(PNG_INTEL_SSE STREQUAL "on")
206      add_definitions(-DPNG_INTEL_SSE_OPT=1)
207    endif()
208  else()
209    add_definitions(-DPNG_INTEL_SSE_OPT=0)
210  endif()
211endif()
212
213# Set definitions and sources for MIPS.
214if(TARGET_ARCH MATCHES "^(mipsel|mips64el)")
215  set(PNG_MIPS_MSA_POSSIBLE_VALUES on off)
216  set(PNG_MIPS_MSA "on"
217      CACHE STRING "Enable MIPS_MSA optimizations: on|off; on is default")
218  set_property(CACHE PNG_MIPS_MSA
219               PROPERTY STRINGS ${PNG_MIPS_MSA_POSSIBLE_VALUES})
220  list(FIND PNG_MIPS_MSA_POSSIBLE_VALUES ${PNG_MIPS_MSA} index_msa)
221  if(index_msa EQUAL -1)
222    message(FATAL_ERROR "PNG_MIPS_MSA must be one of [${PNG_MIPS_MSA_POSSIBLE_VALUES}]")
223  endif()
224
225  set(PNG_MIPS_MMI_POSSIBLE_VALUES on off)
226  set(PNG_MIPS_MMI "on"
227      CACHE STRING "Enable MIPS_MMI optimizations: on|off; on is default")
228  set_property(CACHE PNG_MIPS_MMI
229               PROPERTY STRINGS ${PNG_MIPS_MMI_POSSIBLE_VALUES})
230  list(FIND PNG_MIPS_MMI_POSSIBLE_VALUES ${PNG_MIPS_MMI} index_mmi)
231  if(index_mmi EQUAL -1)
232    message(FATAL_ERROR "PNG_MIPS_MMI must be one of [${PNG_MIPS_MMI_POSSIBLE_VALUES}]")
233  endif()
234
235  if(PNG_MIPS_MSA STREQUAL "on" AND PNG_MIPS_MMI STREQUAL "on")
236    set(libpng_mips_sources
237        mips/mips_init.c
238        mips/filter_msa_intrinsics.c
239        mips/filter_mmi_inline_assembly.c)
240    add_definitions(-DPNG_MIPS_MSA_OPT=2)
241    add_definitions(-DPNG_MIPS_MMI_OPT=1)
242  elseif(PNG_MIPS_MSA STREQUAL "on")
243    set(libpng_mips_sources
244        mips/mips_init.c
245        mips/filter_msa_intrinsics.c)
246    add_definitions(-DPNG_MIPS_MSA_OPT=2)
247    add_definitions(-DPNG_MIPS_MMI_OPT=0)
248  elseif(PNG_MIPS_MMI STREQUAL "on")
249    set(libpng_mips_sources
250        mips/mips_init.c
251        mips/filter_mmi_inline_assembly.c)
252    add_definitions(-DPNG_MIPS_MSA_OPT=0)
253    add_definitions(-DPNG_MIPS_MMI_OPT=1)
254    else()
255    add_definitions(-DPNG_MIPS_MSA_OPT=0)
256    add_definitions(-DPNG_MIPS_MMI_OPT=0)
257    endif()
258endif()
259
260# Set definitions and sources for LoongArch.
261if(TARGET_ARCH MATCHES "^(loongarch)")
262  include(CheckCCompilerFlag)
263  set(PNG_LOONGARCH_LSX_POSSIBLE_VALUES on off)
264  set(PNG_LOONGARCH_LSX "on"
265      CACHE STRING "Enable LOONGARCH_LSX optimizations: on|off; on is default")
266  set_property(CACHE PNG_LOONGARCH_LSX
267               PROPERTY STRINGS ${PNG_LOONGARCH_LSX_POSSIBLE_VALUES})
268  list(FIND PNG_LOONGARCH_LSX_POSSIBLE_VALUES ${PNG_LOONGARCH_LSX} index)
269  if(index EQUAL -1)
270    message(FATAL_ERROR "PNG_LOONGARCH_LSX must be one of [${PNG_LOONGARCH_LSX_POSSIBLE_VALUES}]")
271  elseif(NOT PNG_LOONGARCH_LSX STREQUAL "off")
272    CHECK_C_COMPILER_FLAG("-mlsx" COMPILER_SUPPORTS_LSX)
273    if(COMPILER_SUPPORTS_LSX)
274      set(libpng_loongarch_sources
275          loongarch/loongarch_lsx_init.c
276          loongarch/filter_lsx_intrinsics.c)
277      set_source_files_properties(${libpng_loongarch_sources}
278                                  PROPERTIES
279                                  COMPILE_FLAGS "-mlsx")
280      add_definitions(-DPNG_LOONGARCH_LSX_OPT=1)
281    else()
282      message(FATAL_ERROR "Compiler does not support -mlsx option")
283    endif()
284  else()
285    add_definitions(-DPNG_LOONGARCH_LSX_OPT=0)
286  endif()
287endif()
288
289else(PNG_HARDWARE_OPTIMIZATIONS)
290
291# Set definitions and sources for ARM.
292if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)")
293  add_definitions(-DPNG_ARM_NEON_OPT=0)
294endif()
295
296# Set definitions and sources for PowerPC.
297if(TARGET_ARCH MATCHES "^(powerpc|ppc64)")
298  add_definitions(-DPNG_POWERPC_VSX_OPT=0)
299endif()
300
301# Set definitions and sources for Intel.
302if(TARGET_ARCH MATCHES "^(i[3-6]86|x86|AMD64)")
303  add_definitions(-DPNG_INTEL_SSE_OPT=0)
304endif()
305
306# Set definitions and sources for MIPS.
307if(TARGET_ARCH MATCHES "^(mipsel|mips64el)")
308  add_definitions(-DPNG_MIPS_MSA_OPT=0)
309endif()
310
311# Set definitions and sources for LoongArch.
312if(TARGET_ARCH MATCHES "^(loongarch)")
313  add_definitions(-DPNG_LOONGARCH_LSX_OPT=0)
314endif()
315
316endif(PNG_HARDWARE_OPTIMIZATIONS)
317
318option(ld-version-script "Enable linker version script" ON)
319if(ld-version-script AND NOT ANDROID AND NOT APPLE)
320  # Check if LD supports linker scripts.
321  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "
322VERS_1 { global: sym1; local: *; };
323VERS_2 { global: sym2; main; } VERS_1;
324")
325  set(_SAVED_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
326  if(NOT CMAKE_HOST_SOLARIS)
327    # Avoid using CMAKE_SHARED_LIBRARY_C_FLAGS in version script checks on
328    # Solaris, because of an incompatibility with the Solaris link editor.
329    list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_SHARED_LIBRARY_C_FLAGS})
330  endif()
331  list(APPEND CMAKE_REQUIRED_FLAGS "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/conftest.map'")
332  check_c_source_compiles("
333void sym1(void) {}
334void sym2(void) {}
335int main(void) { return 0; }
336" HAVE_LD_VERSION_SCRIPT)
337  if(NOT HAVE_LD_VERSION_SCRIPT)
338    set(CMAKE_REQUIRED_FLAGS ${_SAVED_CMAKE_REQUIRED_FLAGS})
339    if(NOT CMAKE_HOST_SOLARIS)
340      # Again, avoid using CMAKE_SHARED_LIBRARY_C_FLAGS in version script
341      # checks on Solaris.
342      list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_SHARED_LIBRARY_C_FLAGS})
343    endif()
344    list(APPEND CMAKE_REQUIRED_FLAGS "-Wl,-M -Wl,${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
345    check_c_source_compiles("
346void sym1(void) {}
347void sym2(void) {}
348int main(void) { return 0; }
349" HAVE_SOLARIS_LD_VERSION_SCRIPT)
350  endif()
351  set(CMAKE_REQUIRED_FLAGS ${_SAVED_CMAKE_REQUIRED_FLAGS})
352  file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
353endif()
354
355# Find an AWK language processor.
356# Start with specific AWK implementations like gawk and nawk, which are
357# known to work with our scripts, then fall back to the system awk.
358find_program(AWK NAMES gawk nawk awk)
359if(AWK)
360  message(STATUS "Found AWK program: ${AWK}")
361else()
362  message(STATUS "Could not find an AWK-compatible program")
363endif()
364
365include_directories(${CMAKE_CURRENT_BINARY_DIR})
366
367if(NOT AWK OR ANDROID OR IOS)
368  # No awk available to generate sources; use pre-built pnglibconf.h
369  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt
370                 ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h)
371  add_custom_target(png_genfiles)
372else()
373  # Copy the awk scripts, converting their line endings to Unix (LF)
374  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/checksym.awk
375                 ${CMAKE_CURRENT_BINARY_DIR}/scripts/checksym.awk
376                 @ONLY
377                 NEWLINE_STYLE LF)
378  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk
379                 ${CMAKE_CURRENT_BINARY_DIR}/scripts/options.awk
380                 @ONLY
381                 NEWLINE_STYLE LF)
382  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/dfn.awk
383                 ${CMAKE_CURRENT_BINARY_DIR}/scripts/dfn.awk
384                 @ONLY
385                 NEWLINE_STYLE LF)
386
387  # Generate .chk from .out with awk:
388  # generate_chk(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
389  function(generate_chk)
390    set(options)
391    set(oneValueArgs INPUT OUTPUT)
392    set(multiValueArgs DEPENDS)
393    cmake_parse_arguments(_GC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
394    if(NOT _GC_INPUT)
395      message(FATAL_ERROR "generate_chk: Missing INPUT argument")
396    endif()
397    if(NOT _GC_OUTPUT)
398      message(FATAL_ERROR "generate_chk: Missing OUTPUT argument")
399    endif()
400
401    add_custom_command(OUTPUT "${_GC_OUTPUT}"
402                       COMMAND "${CMAKE_COMMAND}"
403                               "-DINPUT=${_GC_INPUT}"
404                               "-DOUTPUT=${_GC_OUTPUT}"
405                               -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/genchk.cmake"
406                       DEPENDS "${_GC_INPUT}" ${_GC_DEPENDS}
407                       WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
408  endfunction()
409
410  # Generate .out from .c with awk
411  # generate_out(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
412  function(generate_out)
413    set(options)
414    set(oneValueArgs INPUT OUTPUT)
415    set(multiValueArgs DEPENDS)
416    cmake_parse_arguments(_GO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
417    if(NOT _GO_INPUT)
418      message(FATAL_ERROR "generate_out: Missing INPUT argument")
419    endif()
420    if(NOT _GO_OUTPUT)
421      message(FATAL_ERROR "generate_out: Missing OUTPUT argument")
422    endif()
423
424    add_custom_command(OUTPUT "${_GO_OUTPUT}"
425                       COMMAND "${CMAKE_COMMAND}"
426                               "-DINPUT=${_GO_INPUT}"
427                               "-DOUTPUT=${_GO_OUTPUT}"
428                               -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/genout.cmake"
429                       DEPENDS "${_GO_INPUT}" ${_GO_DEPENDS}
430                       WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
431  endfunction()
432
433  # Generate specific source file with awk
434  # generate_source(OUTPUT outputfile [DEPENDS dep1 [dep2...]])
435  function(generate_source)
436    set(options)
437    set(oneValueArgs OUTPUT)
438    set(multiValueArgs DEPENDS)
439    cmake_parse_arguments(_GSO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
440    if(NOT _GSO_OUTPUT)
441      message(FATAL_ERROR "generate_source: Missing OUTPUT argument")
442    endif()
443
444    add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_GSO_OUTPUT}"
445                       COMMAND "${CMAKE_COMMAND}"
446                               "-DOUTPUT=${_GSO_OUTPUT}"
447                               -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/gensrc.cmake"
448                       DEPENDS ${_GSO_DEPENDS}
449                       WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
450  endfunction()
451
452  # Copy file
453  # generate_copy(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
454  function(generate_copy)
455    set(options)
456    set(oneValueArgs INPUT OUTPUT)
457    set(multiValueArgs DEPENDS)
458    cmake_parse_arguments(_GCO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
459    if(NOT _GCO_INPUT)
460      message(FATAL_ERROR "generate_copy: Missing INPUT argument")
461    endif()
462    if(NOT _GCO_OUTPUT)
463      message(FATAL_ERROR "generate_copy: Missing OUTPUT argument")
464    endif()
465
466    add_custom_command(OUTPUT "${_GCO_OUTPUT}"
467                       COMMAND "${CMAKE_COMMAND}"
468                               -E remove "${_GCO_OUTPUT}"
469                       COMMAND "${CMAKE_COMMAND}"
470                               -E copy "${_GCO_INPUT}" "${_GCO_OUTPUT}"
471                       DEPENDS "${source}" ${_GCO_DEPENDS})
472  endfunction()
473
474  # Generate scripts/pnglibconf.h
475  generate_source(OUTPUT "scripts/pnglibconf.c"
476                  DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
477                          "${CMAKE_CURRENT_BINARY_DIR}/scripts/options.awk"
478                          "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
479  add_custom_target(png_scripts_pnglibconf_c
480                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c")
481
482  # Generate pnglibconf.c
483  generate_source(OUTPUT "pnglibconf.c"
484                  DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
485                          "${CMAKE_CURRENT_BINARY_DIR}/scripts/options.awk"
486                          "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
487  add_custom_target(pnglibconf_c
488                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c")
489
490  if(PNG_PREFIX)
491    set(PNGLIBCONF_H_EXTRA_DEPENDS
492        "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
493        "${CMAKE_CURRENT_SOURCE_DIR}/scripts/macro.lst")
494    set(PNGPREFIX_H_EXTRA_DEPENDS
495        "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out")
496  endif()
497
498  generate_out(INPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
499               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
500               DEPENDS pnglibconf_c)
501  add_custom_target(pnglibconf_out
502                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
503
504  # Generate pnglibconf.h
505  generate_source(OUTPUT "pnglibconf.h"
506                  DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" pnglibconf_out
507                          ${PNGLIBCONF_H_EXTRA_DEPENDS})
508  add_custom_target(pnglibconf_h
509                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
510
511  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/intprefix.c"
512               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
513               DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" pnglibconf_h)
514  add_custom_target(png_scripts_intprefix_out
515                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out")
516
517  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/prefix.c"
518               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
519               DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
520                       "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
521                       "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" pnglibconf_out)
522  add_custom_target(png_scripts_prefix_out
523                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out")
524
525  # Generate pngprefix.h
526  generate_source(OUTPUT "pngprefix.h"
527                  DEPENDS ${PNGPREFIX_H_EXTRA_DEPENDS})
528  add_custom_target(pngprefix_h
529                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h")
530
531  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/sym.c"
532               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
533               DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" pnglibconf_h)
534  add_custom_target(png_scripts_sym_out
535                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out")
536
537  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.c"
538               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
539               DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
540                       "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
541                       "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt")
542  add_custom_target(png_scripts_symbols_out
543                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out")
544
545  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/vers.c"
546               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
547               DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
548                       "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
549                       "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" pnglibconf_h)
550  add_custom_target(png_scripts_vers_out
551                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out")
552
553  generate_chk(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
554               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
555               DEPENDS png_scripts_symbols_out
556                       "${CMAKE_CURRENT_BINARY_DIR}/scripts/checksym.awk"
557                       "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def")
558
559  add_custom_target(png_scripts_symbols_chk
560                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk")
561
562  generate_copy(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
563                OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym"
564                DEPENDS png_scripts_sym_out)
565  generate_copy(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
566                OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers"
567                DEPENDS png_scripts_vers_out)
568
569  add_custom_target(png_genvers
570                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
571  add_custom_target(png_gensym
572                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
573
574  add_custom_target(png_genprebuilt
575                    COMMAND "${CMAKE_COMMAND}"
576                            "-DOUTPUT=scripts/pnglibconf.h.prebuilt"
577                            -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/gensrc.cmake"
578                    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
579
580  # A single target handles generation of all generated files.
581  add_custom_target(png_genfiles
582                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym" png_gensym
583                            "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers" png_genvers
584                            "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c" pnglibconf_c
585                            "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" pnglibconf_h
586                            "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" pnglibconf_out
587                            "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h" pngprefix_h
588                            "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out" png_scripts_intprefix_out
589                            "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c" png_scripts_pnglibconf_c
590                            "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out" png_scripts_prefix_out
591                            "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out" png_scripts_sym_out
592                            "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk" png_scripts_symbols_chk
593                            "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out" png_scripts_symbols_out
594                            "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out" png_scripts_vers_out)
595endif(NOT AWK OR ANDROID OR IOS)
596
597# List the source code files.
598set(libpng_public_hdrs
599    png.h
600    pngconf.h
601    "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
602)
603set(libpng_private_hdrs
604    pngpriv.h
605    pngdebug.h
606    pnginfo.h
607    pngstruct.h
608)
609if(AWK AND NOT ANDROID AND NOT IOS)
610  list(APPEND libpng_private_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h")
611endif()
612set(libpng_sources
613    ${libpng_public_hdrs}
614    ${libpng_private_hdrs}
615    png.c
616    pngerror.c
617    pngget.c
618    pngmem.c
619    pngpread.c
620    pngread.c
621    pngrio.c
622    pngrtran.c
623    pngrutil.c
624    pngset.c
625    pngtrans.c
626    pngwio.c
627    pngwrite.c
628    pngwtran.c
629    pngwutil.c
630    ${libpng_arm_sources}
631    ${libpng_intel_sources}
632    ${libpng_mips_sources}
633    ${libpng_powerpc_sources}
634    ${libpng_loongarch_sources}
635)
636set(pngtest_sources
637    pngtest.c
638)
639set(pngvalid_sources
640    contrib/libtests/pngvalid.c
641)
642set(pngstest_sources
643    contrib/libtests/pngstest.c
644)
645set(pngunknown_sources
646    contrib/libtests/pngunknown.c
647)
648set(pngimage_sources
649    contrib/libtests/pngimage.c
650)
651set(pngfix_sources
652    contrib/tools/pngfix.c
653)
654set(png_fix_itxt_sources
655    contrib/tools/png-fix-itxt.c
656)
657
658if(MSVC OR (WIN32 AND (CMAKE_C_COMPILER_ID MATCHES "Clang")))
659  add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
660  add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
661endif()
662
663if(PNG_DEBUG)
664  add_definitions(-DPNG_DEBUG)
665endif()
666
667# Now build our targets.
668
669# Initialize the list of libpng library targets.
670set(PNG_LIBRARY_TARGETS "")
671
672# Initialize the libpng library file names.
673if(UNIX
674   OR (WIN32 AND NOT CMAKE_SHARED_LIBRARY_PREFIX STREQUAL "")
675   OR (WIN32 AND NOT CMAKE_STATIC_LIBRARY_PREFIX STREQUAL ""))
676  # We are on a Unix or Unix-like toolchain like the GNU toolchain on Windows.
677  # Library file names are expected to have an implicit prefix such as "lib".
678  # Let CMake prepend and append its usual prefixes and suffixes by default.
679  set(PNG_SHARED_OUTPUT_NAME "png${PNGLIB_ABI_VERSION}")
680  set(PNG_STATIC_OUTPUT_NAME "png${PNGLIB_ABI_VERSION}")
681else()
682  # We are, most likely, on a Windows toolchain like MSVC, Clang on Windows,
683  # Borland/Embarcadero, etc. We need to specify the "libpng" name explicitly.
684  # We also need to use a custom suffix, in order to distinguish between the
685  # shared import library name and the static library name.
686  set(PNG_SHARED_OUTPUT_NAME "libpng${PNGLIB_ABI_VERSION}")
687  set(PNG_STATIC_OUTPUT_NAME "libpng${PNGLIB_ABI_VERSION}_static")
688endif()
689
690if(PNG_SHARED)
691  add_library(png_shared SHARED ${libpng_sources})
692  add_dependencies(png_shared png_genfiles)
693  list(APPEND PNG_LIBRARY_TARGETS png_shared)
694  set_target_properties(png_shared PROPERTIES
695                        OUTPUT_NAME "${PNG_SHARED_OUTPUT_NAME}"
696                        DEBUG_POSTFIX "${PNG_DEBUG_POSTFIX}"
697                        VERSION "${PNGLIB_SHARED_VERSION}"
698                        SOVERSION "${PNGLIB_ABI_VERSION}")
699  if(UNIX AND AWK)
700    if(HAVE_LD_VERSION_SCRIPT)
701      set_target_properties(png_shared PROPERTIES
702                            LINK_FLAGS "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'")
703    elseif(HAVE_SOLARIS_LD_VERSION_SCRIPT)
704      set_target_properties(png_shared PROPERTIES
705                            LINK_FLAGS "-Wl,-M -Wl,'${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'")
706    endif()
707  endif()
708  if(APPLE)
709    # Avoid CMake's implicit compile definition "png_shared_EXPORTS".
710    set_target_properties(png_shared PROPERTIES DEFINE_SYMBOL "")
711  elseif(WIN32)
712    # Use the explicit compile definition "PNG_BUILD_DLL" for Windows DLLs.
713    set_target_properties(png_shared PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL)
714  endif()
715  target_include_directories(png_shared
716                             PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
717  target_include_directories(png_shared SYSTEM
718                             INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/libpng${PNGLIB_ABI_VERSION}>)
719  target_link_libraries(png_shared PUBLIC ZLIB::ZLIB ${M_LIBRARY})
720endif()
721
722if(PNG_STATIC)
723  add_library(png_static STATIC ${libpng_sources})
724  add_dependencies(png_static png_genfiles)
725  list(APPEND PNG_LIBRARY_TARGETS png_static)
726  set_target_properties(png_static PROPERTIES
727                        OUTPUT_NAME "${PNG_STATIC_OUTPUT_NAME}"
728                        DEBUG_POSTFIX "${PNG_DEBUG_POSTFIX}")
729  target_include_directories(png_static
730                             PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
731  target_include_directories(png_static SYSTEM
732                             INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/libpng${PNGLIB_ABI_VERSION}>)
733  target_link_libraries(png_static PUBLIC ZLIB::ZLIB ${M_LIBRARY})
734endif()
735
736if(PNG_FRAMEWORK AND NOT APPLE)
737  message(AUTHOR_WARNING
738          "Setting PNG_FRAMEWORK to OFF, as it only applies to Apple systems")
739  set(PNG_FRAMEWORK OFF)
740endif()
741
742if(PNG_FRAMEWORK)
743  add_library(png_framework SHARED ${libpng_sources})
744  add_dependencies(png_framework png_genfiles)
745  list(APPEND PNG_LIBRARY_TARGETS png_framework)
746  set_target_properties(png_framework PROPERTIES
747                        FRAMEWORK TRUE
748                        FRAMEWORK_VERSION "${PNGLIB_VERSION}"
749                        MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${PNGLIB_MAJOR}.${PNGLIB_MINOR}"
750                        MACOSX_FRAMEWORK_BUNDLE_VERSION "${PNGLIB_VERSION}"
751                        MACOSX_FRAMEWORK_IDENTIFIER "org.libpng.libpng"
752                        XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
753                        PUBLIC_HEADER "${libpng_public_hdrs}"
754                        OUTPUT_NAME "png"
755                        DEBUG_POSTFIX "${PNG_DEBUG_POSTFIX}")
756  # Avoid CMake's implicit compile definition "-Dpng_framework_EXPORTS".
757  set_target_properties(png_framework PROPERTIES DEFINE_SYMBOL "")
758  target_include_directories(png_framework
759                             PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
760  target_include_directories(png_framework SYSTEM
761                             INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/libpng${PNGLIB_ABI_VERSION}>)
762  target_link_libraries(png_framework PUBLIC ZLIB::ZLIB ${M_LIBRARY})
763endif()
764
765if(NOT PNG_LIBRARY_TARGETS)
766  message(SEND_ERROR "No library variant selected to build. "
767                     "Please enable at least one of the following options: "
768                     "PNG_SHARED, PNG_STATIC, PNG_FRAMEWORK")
769endif()
770
771if(PNG_TESTS AND PNG_SHARED)
772  enable_testing()
773
774  function(png_add_test)
775    set(options)
776    set(oneValueArgs NAME COMMAND)
777    set(multiValueArgs OPTIONS FILES)
778    cmake_parse_arguments(_PAT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
779    if(NOT _PAT_NAME)
780      message(FATAL_ERROR "png_add_test: Missing NAME argument")
781    endif()
782    if(NOT _PAT_COMMAND)
783      message(FATAL_ERROR "png_add_test: Missing COMMAND argument")
784    endif()
785
786    set(TEST_OPTIONS "${_PAT_OPTIONS}")
787    set(TEST_FILES "${_PAT_FILES}")
788
789    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/test.cmake.in"
790                   "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake"
791                   @ONLY)
792    add_test(NAME "${_PAT_NAME}"
793             COMMAND "${CMAKE_COMMAND}"
794                     "-DLIBPNG=$<TARGET_FILE:png_shared>"
795                     "-DTEST_COMMAND=$<TARGET_FILE:${_PAT_COMMAND}>"
796                     -P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake")
797  endfunction()
798
799  # Find test PNG files by globbing, but sort lists to ensure
800  # consistency between different filesystems.
801  file(GLOB PNGSUITE_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/*.png")
802  list(SORT PNGSUITE_PNGS)
803  file(GLOB TEST_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/*.png")
804  list(SORT TEST_PNGS)
805
806  set(PNGTEST_PNG "${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png")
807
808  add_executable(pngtest ${pngtest_sources})
809  target_link_libraries(pngtest PRIVATE png_shared)
810
811  png_add_test(NAME pngtest
812               COMMAND pngtest
813               FILES "${PNGTEST_PNG}")
814
815  add_executable(pngvalid ${pngvalid_sources})
816  target_link_libraries(pngvalid PRIVATE png_shared)
817
818  png_add_test(NAME pngvalid-gamma-16-to-8
819               COMMAND pngvalid
820               OPTIONS --gamma-16-to-8)
821  png_add_test(NAME pngvalid-gamma-alpha-mode
822               COMMAND pngvalid
823               OPTIONS --gamma-alpha-mode)
824  png_add_test(NAME pngvalid-gamma-background
825               COMMAND pngvalid
826               OPTIONS --gamma-background)
827  png_add_test(NAME pngvalid-gamma-expand16-alpha-mode
828               COMMAND pngvalid
829               OPTIONS --gamma-alpha-mode --expand16)
830  png_add_test(NAME pngvalid-gamma-expand16-background
831               COMMAND pngvalid
832               OPTIONS --gamma-background --expand16)
833  png_add_test(NAME pngvalid-gamma-expand16-transform
834               COMMAND pngvalid
835               OPTIONS --gamma-transform --expand16)
836  png_add_test(NAME pngvalid-gamma-sbit
837               COMMAND pngvalid
838               OPTIONS --gamma-sbit)
839  png_add_test(NAME pngvalid-gamma-threshold
840               COMMAND pngvalid
841               OPTIONS --gamma-threshold)
842  png_add_test(NAME pngvalid-gamma-transform
843               COMMAND pngvalid
844               OPTIONS --gamma-transform)
845  png_add_test(NAME pngvalid-progressive-interlace-standard
846               COMMAND pngvalid
847               OPTIONS --standard --progressive-read --interlace)
848  png_add_test(NAME pngvalid-progressive-size
849               COMMAND pngvalid
850               OPTIONS --size --progressive-read)
851  png_add_test(NAME pngvalid-progressive-standard
852               COMMAND pngvalid
853               OPTIONS --standard --progressive-read)
854  png_add_test(NAME pngvalid-standard
855               COMMAND pngvalid
856               OPTIONS --standard)
857  png_add_test(NAME pngvalid-transform
858               COMMAND pngvalid
859               OPTIONS --transform)
860
861  add_executable(pngstest ${pngstest_sources})
862  target_link_libraries(pngstest PRIVATE png_shared)
863
864  foreach(gamma_type 1.8 linear none sRGB)
865    foreach(alpha_type none alpha)
866      set(PNGSTEST_FILES)
867      foreach(test_png ${TEST_PNGS})
868        string(REGEX MATCH "-linear[-.]" TEST_PNG_LINEAR "${test_png}")
869        string(REGEX MATCH "-sRGB[-.]" TEST_PNG_SRGB "${test_png}")
870        string(REGEX MATCH "-1.8[-.]" TEST_PNG_G18 "${test_png}")
871        string(REGEX MATCH "-alpha-" TEST_PNG_ALPHA "${test_png}")
872
873        set(TEST_PNG_VALID TRUE)
874
875        if(TEST_PNG_ALPHA)
876          if(NOT alpha_type STREQUAL "alpha")
877            set(TEST_PNG_VALID FALSE)
878          endif()
879        else()
880          if(alpha_type STREQUAL "alpha")
881            set(TEST_PNG_VALID FALSE)
882          endif()
883        endif()
884
885        if(TEST_PNG_LINEAR)
886          if(NOT gamma_type STREQUAL "linear")
887            set(TEST_PNG_VALID FALSE)
888          endif()
889        elseif(TEST_PNG_SRGB)
890          if(NOT gamma_type STREQUAL "sRGB")
891            set(TEST_PNG_VALID FALSE)
892          endif()
893        elseif(TEST_PNG_G18)
894          if(NOT gamma_type STREQUAL "1.8")
895            set(TEST_PNG_VALID FALSE)
896          endif()
897        else()
898          if(NOT gamma_type STREQUAL "none")
899            set(TEST_PNG_VALID FALSE)
900          endif()
901        endif()
902
903        if(TEST_PNG_VALID)
904          list(APPEND PNGSTEST_FILES "${test_png}")
905        endif()
906      endforeach()
907      # Should already be sorted, but sort anyway to be certain.
908      list(SORT PNGSTEST_FILES)
909      png_add_test(NAME pngstest-${gamma_type}-${alpha_type}
910                   COMMAND pngstest
911                   OPTIONS --tmpfile "${gamma_type}-${alpha_type}-" --log
912                   FILES ${PNGSTEST_FILES})
913    endforeach()
914  endforeach()
915
916  add_executable(pngunknown ${pngunknown_sources})
917  target_link_libraries(pngunknown PRIVATE png_shared)
918
919  png_add_test(NAME pngunknown-discard
920               COMMAND pngunknown
921               OPTIONS --strict default=discard
922               FILES "${PNGTEST_PNG}")
923  png_add_test(NAME pngunknown-IDAT
924               COMMAND pngunknown
925               OPTIONS --strict default=discard IDAT=save
926               FILES "${PNGTEST_PNG}")
927  png_add_test(NAME pngunknown-if-safe
928               COMMAND pngunknown
929               OPTIONS --strict default=if-safe
930               FILES "${PNGTEST_PNG}")
931  png_add_test(NAME pngunknown-sAPI
932               COMMAND pngunknown
933               OPTIONS --strict bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save
934               FILES "${PNGTEST_PNG}")
935  png_add_test(NAME pngunknown-save
936               COMMAND pngunknown
937               OPTIONS --strict default=save
938               FILES "${PNGTEST_PNG}")
939  png_add_test(NAME pngunknown-sTER
940               COMMAND pngunknown
941               OPTIONS --strict sTER=if-safe
942               FILES "${PNGTEST_PNG}")
943  png_add_test(NAME pngunknown-vpAg
944               COMMAND pngunknown
945               OPTIONS --strict vpAg=if-safe
946               FILES "${PNGTEST_PNG}")
947
948  add_executable(pngimage ${pngimage_sources})
949  target_link_libraries(pngimage PRIVATE png_shared)
950
951  png_add_test(NAME pngimage-quick
952               COMMAND pngimage
953               OPTIONS --list-combos --log
954               FILES ${PNGSUITE_PNGS})
955  png_add_test(NAME pngimage-full
956               COMMAND pngimage
957               OPTIONS --exhaustive --list-combos --log
958               FILES ${PNGSUITE_PNGS})
959endif()
960
961if(PNG_SHARED AND PNG_TOOLS)
962  add_executable(pngfix ${pngfix_sources})
963  target_link_libraries(pngfix PRIVATE png_shared)
964  set(PNG_BIN_TARGETS pngfix)
965
966  add_executable(png-fix-itxt ${png_fix_itxt_sources})
967  target_link_libraries(png-fix-itxt PRIVATE ZLIB::ZLIB ${M_LIBRARY})
968  list(APPEND PNG_BIN_TARGETS png-fix-itxt)
969endif()
970
971# Create a symlink from src to dest (if possible), or, alternatively,
972# copy src to dest if different.
973function(create_symlink DEST_FILE)
974  cmake_parse_arguments(_SYM "" "FILE;TARGET" "" ${ARGN})
975  if(NOT _SYM_FILE AND NOT _SYM_TARGET)
976    message(FATAL_ERROR "create_symlink: Missing FILE or TARGET argument")
977  endif()
978  if(_SYM_FILE AND _SYM_TARGET)
979    message(FATAL_ERROR "create_symlink: "
980                        "The arguments FILE (${_SYM_FILE}) and TARGET (${_SYM_TARGET}) "
981                        "are mutually-exclusive")
982  endif()
983
984  if(_SYM_FILE)
985    # If we don't need to symlink something that's coming from a build target,
986    # we can go ahead and symlink/copy at configure time.
987    if(CMAKE_HOST_WIN32 AND NOT CYGWIN)
988      execute_process(COMMAND "${CMAKE_COMMAND}"
989                              -E copy_if_different
990                              ${_SYM_FILE} ${DEST_FILE}
991                      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
992    else()
993      execute_process(COMMAND "${CMAKE_COMMAND}"
994                              -E create_symlink
995                              ${_SYM_FILE} ${DEST_FILE}
996                      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
997    endif()
998  endif()
999
1000  if(_SYM_TARGET)
1001    # We need to use generator expressions, which can be a bit tricky.
1002    # For simplicity, make the symlink a POST_BUILD step, and use the TARGET
1003    # signature of add_custom_command.
1004    if(CMAKE_HOST_WIN32 AND NOT CYGWIN)
1005      add_custom_command(TARGET ${_SYM_TARGET}
1006                         POST_BUILD
1007                         COMMAND "${CMAKE_COMMAND}"
1008                                 -E copy_if_different
1009                                 $<TARGET_LINKER_FILE_DIR:${_SYM_TARGET}>/$<TARGET_LINKER_FILE_NAME:${_SYM_TARGET}>
1010                                 $<TARGET_LINKER_FILE_DIR:${_SYM_TARGET}>/${DEST_FILE})
1011    else()
1012      add_custom_command(TARGET ${_SYM_TARGET}
1013                         POST_BUILD
1014                         COMMAND "${CMAKE_COMMAND}"
1015                                 -E create_symlink
1016                                 $<TARGET_LINKER_FILE_NAME:${_SYM_TARGET}>
1017                                 $<TARGET_LINKER_FILE_DIR:${_SYM_TARGET}>/${DEST_FILE})
1018    endif()
1019  endif()
1020endfunction()
1021
1022# Create source generation scripts.
1023configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/genchk.cmake.in
1024               ${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/genchk.cmake
1025               @ONLY)
1026configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/genout.cmake.in
1027               ${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/genout.cmake
1028               @ONLY)
1029configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/gensrc.cmake.in
1030               ${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/gensrc.cmake
1031               @ONLY)
1032
1033# libpng is a library so default to 'lib'
1034if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
1035  set(CMAKE_INSTALL_LIBDIR lib)
1036endif()
1037
1038# Create pkgconfig files.
1039# We use the same files like ./configure, so we have to set its vars.
1040# Only do this on Windows for Cygwin - the files don't make much sense
1041# outside of a UNIX look-alike.
1042if(NOT WIN32 OR CYGWIN OR MINGW)
1043  set(prefix      ${CMAKE_INSTALL_PREFIX})
1044  set(exec_prefix ${CMAKE_INSTALL_PREFIX})
1045  set(libdir      ${CMAKE_INSTALL_FULL_LIBDIR})
1046  set(includedir  ${CMAKE_INSTALL_FULL_INCLUDEDIR})
1047  set(LIBS        "-lz -lm")
1048  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in
1049                 ${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}.pc
1050                 @ONLY)
1051  create_symlink(libpng.pc FILE libpng${PNGLIB_ABI_VERSION}.pc)
1052  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng-config.in
1053                 ${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}-config
1054                 @ONLY)
1055  create_symlink(libpng-config FILE libpng${PNGLIB_ABI_VERSION}-config)
1056endif()
1057
1058# Install.
1059if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
1060  install(TARGETS ${PNG_LIBRARY_TARGETS}
1061          EXPORT libpng
1062          RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1063          LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
1064          ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
1065          FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR})
1066
1067  if(PNG_SHARED)
1068    # Create a symlink for libpng.dll.a => libpng16.dll.a on Cygwin
1069    if(NOT WIN32 OR CYGWIN OR MINGW)
1070      create_symlink(libpng${CMAKE_SHARED_LIBRARY_SUFFIX} TARGET png_shared)
1071      install(FILES $<TARGET_LINKER_FILE_DIR:png_shared>/libpng${CMAKE_SHARED_LIBRARY_SUFFIX}
1072              DESTINATION ${CMAKE_INSTALL_LIBDIR})
1073    endif()
1074  endif()
1075
1076  if(PNG_STATIC)
1077    if(NOT WIN32 OR CYGWIN OR MINGW)
1078      create_symlink(libpng${CMAKE_STATIC_LIBRARY_SUFFIX} TARGET png_static)
1079      install(FILES $<TARGET_LINKER_FILE_DIR:png_static>/libpng${CMAKE_STATIC_LIBRARY_SUFFIX}
1080              DESTINATION ${CMAKE_INSTALL_LIBDIR})
1081    endif()
1082  endif()
1083endif()
1084
1085if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
1086  install(FILES ${libpng_public_hdrs}
1087          DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
1088  install(FILES ${libpng_public_hdrs}
1089          DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libpng${PNGLIB_ABI_VERSION})
1090endif()
1091if(NOT SKIP_INSTALL_EXECUTABLES AND NOT SKIP_INSTALL_ALL)
1092  if(NOT WIN32 OR CYGWIN OR MINGW)
1093    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config
1094            DESTINATION ${CMAKE_INSTALL_BINDIR})
1095    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}-config
1096            DESTINATION ${CMAKE_INSTALL_BINDIR})
1097  endif()
1098endif()
1099
1100if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL)
1101  install(TARGETS ${PNG_BIN_TARGETS}
1102          RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
1103endif()
1104
1105if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL)
1106  # Install the man pages.
1107  install(FILES libpng.3 libpngpf.3
1108          DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
1109  install(FILES png.5
1110          DESTINATION ${CMAKE_INSTALL_MANDIR}/man5)
1111  # Install the pkg-config files.
1112  if(NOT CMAKE_HOST_WIN32 OR CYGWIN OR MINGW)
1113    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc
1114            DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
1115    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config
1116            DESTINATION ${CMAKE_INSTALL_BINDIR})
1117    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}.pc
1118            DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
1119    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}-config
1120            DESTINATION ${CMAKE_INSTALL_BINDIR})
1121  endif()
1122endif()
1123
1124# Create an export file that CMake users can include() to import our targets.
1125if(NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL)
1126  install(EXPORT libpng
1127          DESTINATION ${CMAKE_INSTALL_LIBDIR}/libpng
1128          FILE libpng${PNGLIB_ABI_VERSION}.cmake)
1129endif()
1130
1131# TODO: Create MSVC import lib for MinGW-compiled shared lib.
1132# pexports libpng.dll > libpng.def
1133# lib /def:libpng.def /machine:x86
1134