cmake_minimum_required (VERSION 3.26)

project(
    ZLIB
    LANGUAGES C
    VERSION 1.4.1.1
    HOMEPAGE_URL "https://zlib.net/"
    DESCRIPTION "a general-purpose lossless data-compression library")
set (CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

#-----------------------------------------------------------------------------
# Basic ZLIB stuff here
#-----------------------------------------------------------------------------
set (ZLIB_PACKAGE_EXT ${HDF_PACKAGE_EXT})
set (HDF_USE_GNU_DIRS ${HDF5_USE_GNU_DIRS})
set (CMAKE_OSX_ARCHITECTURES ${CMAKE_OSX_ARCHITECTURES})
set (CMAKE_TOOLCHAIN_FILE ${CMAKE_TOOLCHAIN_FILE})
set (PACKAGE_NAMESPACE ${HDF_PACKAGE_NAMESPACE})
if (MINGW)
  set (WINDOWS 1) # MinGW tries to imitate Windows
endif ()
if (WINDOWS)
  set (HAVE_STDDEF_H 1)
  set (HAVE_SYS_TYPES_H 1)
endif ()
# ============================================================================
# configuration
# ============================================================================

option(ZLIB_BUILD_TESTING "Enable Zlib Examples as tests" OFF)
option(ZLIB_BUILD_SHARED "Enable building zlib shared library" OFF)
option(ZLIB_BUILD_STATIC "Enable building zlib static library" ON)
option(ZLIB_BUILD_MINIZIP "Enable building libminizip contrib library" OFF)
option(ZLIB_INSTALL "Enable installation of zlib" OFF)
option(ZLIB_PREFIX "prefix for all types and library functions, see zconf.h.in"
       OFF)
mark_as_advanced(ZLIB_PREFIX)

if(WIN32)
    option(ZLIB_INSTALL_COMPAT_DLL "Install a copy as zlib1.dll" ON)
endif(WIN32)

get_property(IS_MULTI GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)

if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT IS_MULTI)
    message(STATUS "No CMAKE_BUILD_TYPE set -- using Release")
    set(CMAKE_BUILD_TYPE Release)
endif(NOT DEFINED CMAKE_BUILD_TYPE AND NOT IS_MULTI)

include(CheckCSourceCompiles)
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CMakePackageConfigHelpers)
include(CheckTypeSize)
include(CPack)
include(GNUInstallDirs)

set(CPACK_INCLUDED FALSE)

if(NOT ZLIB_CONF_WRITTEN)
    set(Z_PREFIX ${ZLIB_PREFIX})
    set(CONF_OUT_FILE ${ZLIB_BINARY_DIR}/zconf.h.cmakein)
    file(READ ${ZLIB_SOURCE_DIR}/zconf.h ZCONF_CONTENT LIMIT 245)
    file(WRITE ${CONF_OUT_FILE} ${ZCONF_CONTENT})
    file(APPEND ${CONF_OUT_FILE} "#cmakedefine Z_PREFIX 1\n")
    file(APPEND ${CONF_OUT_FILE} "#cmakedefine HAVE_STDARG_H 1\n")
    file(APPEND ${CONF_OUT_FILE} "#cmakedefine HAVE_UNISTD_H 1\n")
    file(READ ${ZLIB_SOURCE_DIR}/zconf.h ZCONF_CONTENT OFFSET 244)
    set(FIRST_ITEM TRUE)

    foreach(item IN LISTS ZCONF_CONTENT)
        if(FIRST_ITEM)
            string(APPEND OUT_CONTENT ${item})
            set(FIRST_ITEM FALSE)
        else(FIRST_ITEM)
            string(APPEND OUT_CONTENT "\;" ${item})
        endif(FIRST_ITEM)
    endforeach(item IN LISTS ${ZCONF_CONTENT})

    file(APPEND ${CONF_OUT_FILE} ${OUT_CONTENT})
    set(ZLIB_CONF_WRITTEN
        TRUE
        CACHE BOOL "zconf.h.cmakein was created")
    mark_as_advanced(ZLIB_CONF_WRITTEN)
endif(NOT ZLIB_CONF_WRITTEN)

#
# Check to see if we have large file support
#
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
check_type_size(off64_t OFF64_T)
unset(CMAKE_REQUIRED_DEFINITIONS) # clear variable

#
# Check for fseeko
#
check_function_exists(fseeko HAVE_FSEEKO)

#
# Check for stdarg.h
#
check_include_file(stdarg.h HAVE_STDARG_H)

#
# Check for unistd.h
#
check_include_file(unistd.h HAVE_UNISTD_H)

#
# Check visibility attribute is supported
#
if(MSVC)
    set(CMAKE_REQUIRED_FLAGS "-WX")
else(MSVC)
    set(CMAKE_REQUIRED_FLAGS "-WError")
endif(MSVC)

check_c_source_compiles(
    "
        #include <stdlib.h>
        static void f(void) __attribute__ ((visibility(\"hidden\")));
        int main(void) {return 0;}
    "
    HAVE___ATTR__VIS_HIDDEN)

unset(CMAKE_COMPILE_FLAGS)
set(ZLIB_PC ${ZLIB_BINARY_DIR}/zlib.pc)
configure_file(${ZLIB_SOURCE_DIR}/zlib.pc.cmakein ${ZLIB_PC} @ONLY)
configure_file(${ZLIB_BINARY_DIR}/zconf.h.cmakein ${ZLIB_BINARY_DIR}/zconf.h)
include_directories(${ZLIB_BINARY_DIR} ${ZLIB_SOURCE_DIR})

#-----------------------------------------------------------------------------
# Define some CMake variables for use later in the project
#-----------------------------------------------------------------------------
set (ZLIB_RESOURCES_DIR          ${HDF_RESOURCES_DIR}/ZLIB)
set (ZLIB_SRC_DIR                ${ZLIB_SOURCE_DIR})

#-----------------------------------------------------------------------------
# Set the core names of all the libraries
#-----------------------------------------------------------------------------
set (ZLIB_LIB_CORENAME            "zlib-static")

#-----------------------------------------------------------------------------
# Set the target names of all the libraries
#-----------------------------------------------------------------------------
set (ZLIB_LIB_TARGET            "zlib-static")

#-----------------------------------------------------------------------------
set (ZLIB_PACKAGE "zlib")
set (ZLIB_PACKAGE_NAME "ZLIB")

set (CMAKE_POSITION_INDEPENDENT_CODE ON)

HDF_DIR_PATHS(${ZLIB_PACKAGE_NAME})

#-----------------------------------------------------------------------------
# Targets built within this project are exported at Install time for use
# by other projects
#-----------------------------------------------------------------------------
if (NOT ZLIB_EXPORTED_TARGETS)
  set (ZLIB_EXPORTED_TARGETS "zlib-targets")
endif ()

set_global_variable (ZLIB_LIBRARIES_TO_EXPORT "")

#-----------------------------------------------------------------------------
# All libs/tests/examples need the main include directories
#-----------------------------------------------------------------------------
set_directory_properties (PROPERTIES INCLUDE_DIRECTORIES
    "${ZLIB_BINARY_DIR};${ZLIB_SOURCE_DIR};${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
)

if (MSVC)
  set(CMAKE_DEBUG_POSTFIX "d")
  add_definitions (-D_BIND_TO_CURRENT_VCLIBS_VERSION=1)
  add_definitions (-D_CRT_SECURE_NO_WARNINGS)
  add_definitions (-D_CONSOLE)
  include_directories(${CMAKE_CURRENT_SOURCE_DIR})
endif ()

if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
    # If we're doing an out of source build and the user has a zconf.h
    # in their source tree...
    if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
        message(VERBOSE "Renaming")
        message(VERBOSE "    ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
        message(VERBOSE "to 'zconf.h.included' because this file is included with zlib")
        message(VERBOSE "but CMake generates it automatically in the build directory.")
        file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
  endif()
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})


#-----------------------------------------------------------------------------
# Define ZLIB Library
#-----------------------------------------------------------------------------

set(ZLIB_PUBLIC_HDRS ${ZLIB_BINARY_DIR}/zconf.h zlib.h)

set(ZLIB_PRIVATE_HDRS
    crc32.h
    deflate.h
    gzguts.h
    inffast.h
    inffixed.h
    inflate.h
    inftrees.h
    trees.h
    zutil.h)

set(ZLIB_SRCS
    adler32.c
    compress.c
    crc32.c
    deflate.c
    gzclose.c
    gzlib.c
    gzread.c
    gzwrite.c
    inflate.c
    infback.c
    inftrees.c
    inffast.c
    trees.c
    uncompr.c
    zutil.c)

add_library(${ZLIB_LIB_TARGET} STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
    target_include_directories(
        ${ZLIB_LIB_TARGET}
        PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
               $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
               $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_definitions(
        ${ZLIB_LIB_TARGET}
        PRIVATE $<$<BOOL:NOT:${HAVE_FSEEKO}>:NO_FSEEKO>
                $<$<BOOL:${HAVE___ATTR__VIS_HIDDEN}>:HAVE_HIDDEN>
                $<$<BOOL:${MSVC}>:_CRT_SECURE_NO_DEPRECATE>
                $<$<BOOL:${MSVC}>:_CRT_NONSTDC_NO_DEPRECATE>
                $<$<BOOL:${MSVC}>:_BIND_TO_CURRENT_VCLIBS_VERSION=1>
                $<$<BOOL:${MSVC}>:_CRT_SECURE_NO_WARNINGS>
                $<$<BOOL:${MSVC}>:_CONSOLE>
        PUBLIC $<$<BOOL:${HAVE_OFF64_T}>:_LARGEFILE64_SOURCE=1>)
target_include_directories(${ZLIB_LIB_TARGET}
    PRIVATE "${CMAKE_BINARY_DIR}"
    PUBLIC "${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}"
)
if (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
  if (CMAKE_C_COMPILER_ARCHITECTURE_ID MATCHES "ARM64")
    set_target_properties(${ZLIB_LIB_TARGET} PROPERTIES STATIC_LIBRARY_FLAGS "/machine:ARM64")
  else()
    set_target_properties(${ZLIB_LIB_TARGET} PROPERTIES STATIC_LIBRARY_FLAGS "/machine:x64")
  endif()
endif()
set_target_properties(${ZLIB_LIB_TARGET} PROPERTIES
    PUBLIC_HEADER ""
    LINKER_LANGUAGE C
    INTERFACE_INCLUDE_DIRECTORIES "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>"
)

#-----------------------------------------------------------------------------
# Compiler specific flags
#-----------------------------------------------------------------------------
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
  target_compile_options(${ZLIB_LIB_TARGET} PRIVATE -Wno-strict-prototypes -Wno-implicit-function-declaration)
endif ()
if (CMAKE_C_COMPILER_ID MATCHES "IntelLLVM" OR CMAKE_C_COMPILER_ID MATCHES "[Cc]lang")
  target_compile_options(${ZLIB_LIB_TARGET} PRIVATE -Wno-implicit-function-declaration)
endif ()
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
  target_compile_options(${ZLIB_LIB_TARGET} PRIVATE -fmessage-length=0)
endif ()

set_target_properties(${ZLIB_LIB_TARGET} PROPERTIES OUTPUT_NAME zlib-static)

set_global_variable (ZLIB_LIBRARIES_TO_EXPORT "${ZLIB_LIB_TARGET}")
set (install_targets ${ZLIB_LIB_TARGET})

#-----------------------------------------------------------------------------
# Add Target(s) to CMake Install for import into other projects
#-----------------------------------------------------------------------------
if (ZLIB_EXPORTED_TARGETS)
  install (
      TARGETS
          ${install_targets}
      EXPORT
          ${ZLIB_EXPORTED_TARGETS}
      LIBRARY DESTINATION ${ZLIB_INSTALL_LIB_DIR} COMPONENT libraries
      ARCHIVE DESTINATION ${ZLIB_INSTALL_LIB_DIR} COMPONENT libraries
      RUNTIME DESTINATION ${ZLIB_INSTALL_BIN_DIR} COMPONENT libraries
      FRAMEWORK DESTINATION ${ZLIB_INSTALL_FWRK_DIR} COMPONENT libraries
      PUBLIC_HEADER DESTINATION ${ZLIB_INSTALL_INCLUDE_DIR} COMPONENT headers
  )
endif ()

include (CMakePackageConfigHelpers)

#-----------------------------------------------------------------------------
# Configure the zlib-config.cmake file for the build directory
#-----------------------------------------------------------------------------
set (INCLUDE_INSTALL_DIR ${ZLIB_INSTALL_INCLUDE_DIR})
set (SHARE_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ZLIB_INSTALL_CMAKE_DIR}" )
set (CURRENT_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}" )
configure_package_config_file (
    ${ZLIB_RESOURCES_DIR}/zlib-config.cmake.in
    "${ZLIB_BINARY_DIR}/zlib-config.cmake"
    INSTALL_DESTINATION "${ZLIB_INSTALL_CMAKE_DIR}"
    PATH_VARS INCLUDE_INSTALL_DIR SHARE_INSTALL_DIR CURRENT_BUILD_DIR
    INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}"
)

#-----------------------------------------------------------------------------
# Configure the zlib-config.cmake file for the install directory
#-----------------------------------------------------------------------------
set (INCLUDE_INSTALL_DIR ${ZLIB_INSTALL_INCLUDE_DIR})
set (SHARE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${ZLIB_INSTALL_CMAKE_DIR}" )
set (CURRENT_BUILD_DIR "${CMAKE_INSTALL_PREFIX}")
configure_package_config_file (
    ${ZLIB_RESOURCES_DIR}/zlib-config.cmake.in
    "${ZLIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/zlib-config.cmake"
    INSTALL_DESTINATION "${ZLIB_INSTALL_CMAKE_DIR}"
    PATH_VARS INCLUDE_INSTALL_DIR SHARE_INSTALL_DIR CURRENT_BUILD_DIR
)
if (NOT ZLIB_EXTERNALLY_CONFIGURED)
  install (
      FILES ${ZLIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/zlib-config.cmake
      DESTINATION ${ZLIB_INSTALL_CMAKE_DIR}
      COMPONENT configinstall
  )
endif ()

#-----------------------------------------------------------------------------
# Configure the ZLIB-config-version.cmake file for the install directory
#-----------------------------------------------------------------------------
if (NOT ZLIB_EXTERNALLY_CONFIGURED)
  configure_file (
      ${ZLIB_RESOURCES_DIR}/zlib-config-version.cmake.in
      ${ZLIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/zlib-config-version.cmake @ONLY
  )
  install (
      FILES ${ZLIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/zlib-config-version.cmake
      DESTINATION ${ZLIB_INSTALL_CMAKE_DIR}
      COMPONENT configinstall
  )
endif ()

#-----------------------------------------------------------------------------
# Add Target(s) to CMake Install for import into other projects
#-----------------------------------------------------------------------------
if (NOT ZLIB_EXTERNALLY_CONFIGURED)
  install (
      EXPORT ${ZLIB_EXPORTED_TARGETS}
      DESTINATION ${ZLIB_INSTALL_CMAKE_DIR}
      FILE zlib-targets.cmake
      NAMESPACE ${PACKAGE_NAMESPACE}
      COMPONENT configinstall
  )
endif ()

#-----------------------------------------------------------------------------
# Export all exported targets to the build tree for use by parent project
#-----------------------------------------------------------------------------
if (NOT ZLIB_EXTERNALLY_CONFIGURED)
  export (
      TARGETS ${ZLIB_LIBRARIES_TO_EXPORT}
      FILE zlib-targets.cmake
      NAMESPACE ${PACKAGE_NAMESPACE}
  )
  export (PACKAGE zlib)
endif ()

