Skip to content

Add ZLIB with FetchContent #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: PHP-8.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ jobs:
libsasl2-dev \
libpq-dev \
libmm-dev \
zlib1g-dev \
libdmalloc-dev \
dovecot-core \
dovecot-pop3d \
Expand Down
10 changes: 0 additions & 10 deletions cmake/cmake/Configuration.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,6 @@ set(PHP_SQLITE_MIN_VERSION 3.7.7)
# Minimum required version for the PostgreSQL dependency.
set(PHP_POSTGRESQL_MIN_VERSION 9.1)

# Minimum required version for the zlib dependency.
set(PHP_ZLIB_MIN_VERSION 1.2.0.4)

# Additional metadata for external packages to avoid duplication.
set_package_properties(
BZip2
Expand Down Expand Up @@ -251,13 +248,6 @@ set_package_properties(
DESCRIPTION "SQL database engine library"
)

set_package_properties(
ZLIB
PROPERTIES
URL "https://zlib.net/"
DESCRIPTION "Compression library"
)

# Set base directory for ExternalProject CMake module.
set_directory_properties(
PROPERTIES EP_BASE ${PHP_BINARY_DIR}/CMakeFiles/PHP/ExternalProject
Expand Down
99 changes: 99 additions & 0 deletions cmake/cmake/modules/PHP/Package/ZLIB.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#[=============================================================================[
# PHP/Package/Zlib

Finds or downloads the zlib library:

```cmake
include(PHP/Package/Zlib)
```

This module is a wrapper for finding the `ZLIB` library. It first tries to find
the `ZLIB` library on the system. If not successful it tries to download it from
the upstream source with `ExternalProject` module and builds it together with
the PHP build.

See: https://cmake.org/cmake/help/latest/module/FindZLIB.html

## Examples

```cmake
include(PHP/Package/ZLIB)
target_link_libraries(php_ext_foo PRIVATE ZLIB::ZLIB)
#]=============================================================================]

include(FeatureSummary)
include(ExternalProject)

set_package_properties(
ZLIB
PROPERTIES
URL "https://zlib.net/"
DESCRIPTION "Compression library"
)

# Minimum required version for the zlib dependency.
set(PHP_ZLIB_MIN_VERSION 1.2.0.4)
#set(PHP_ZLIB_MIN_VERSION 1.3.1)

# Download version when system dependency is not found.
set(PHP_ZLIB_DOWNLOAD_VERSION 1.3.1)

if(TARGET ZLIB::ZLIB)
set(ZLIB_FOUND TRUE)
return()
endif()

find_package(ZLIB ${PHP_ZLIB_MIN_VERSION})

if(NOT ZLIB_FOUND)
message(
STATUS
"ZLIB ${PHP_ZLIB_DOWNLOAD_VERSION} will be downloaded at build phase"
)

set(zlib_options "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>")

if(PHP_ZLIB_DOWNLOAD_VERSION VERSION_LESS_EQUAL 1.3.1)
list(APPEND zlib_options -DZLIB_BUILD_EXAMPLES=OFF)
endif()

if(PHP_ZLIB_DOWNLOAD_VERSION VERSION_GREATER 1.3.1)
list(APPEND zlib_options -DZLIB_BUILD_TESTING=OFF)
endif()

ExternalProject_Add(
ZLIB
STEP_TARGETS build install
URL
https://github.com/madler/zlib/releases/download/v${PHP_ZLIB_DOWNLOAD_VERSION}/zlib-${PHP_ZLIB_DOWNLOAD_VERSION}.tar.gz
CMAKE_ARGS ${zlib_options}
INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/zlib-installation
INSTALL_BYPRODUCTS <INSTALL_DIR>/lib/libz.so
)

# Move dependency to PACKAGES_FOUND.
block()
get_cmake_property(packagesNotFound PACKAGES_NOT_FOUND)
list(REMOVE_ITEM packagesNotFound ZLIB)
set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND packagesNotFound)
get_cmake_property(packagesFound PACKAGES_FOUND)
set_property(GLOBAL APPEND PROPERTY PACKAGES_FOUND ZLIB)
endblock()

ExternalProject_Get_Property(ZLIB INSTALL_DIR)

# Bypass issue with non-existing include directory for the imported target.
file(MAKE_DIRECTORY ${INSTALL_DIR}/include)

add_library(ZLIB::ZLIB STATIC IMPORTED GLOBAL)
set_target_properties(
ZLIB::ZLIB
PROPERTIES
IMPORTED_LOCATION "${INSTALL_DIR}/lib/libz.${CMAKE_STATIC_LIBRARY_SUFFIX}"
INTERFACE_INCLUDE_DIRECTORIES "${INSTALL_DIR}/include"
)
add_dependencies(ZLIB::ZLIB ZLIB-install)

# Mark package as found.
set(ZLIB_FOUND TRUE)
endif()
2 changes: 2 additions & 0 deletions cmake/cmake/modules/Packages/LibXml2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ FetchContent_Declare(
find_package(LibXml2 ${PHP_LIBXML2_MIN_VERSION})

if(NOT LibXml2_FOUND)
include(PHP/Package/ZLIB)

set(FETCHCONTENT_QUIET NO)
set(LIBXML2_WITH_PYTHON OFF)
set(LIBXML2_WITH_LZMA OFF)
Expand Down
82 changes: 82 additions & 0 deletions cmake/cmake/modules/Packages/PNG.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#[=============================================================================[
Wrapper for finding the `PNG` library.

Module first tries to find the `PNG` library on the system. If not
successful it tries to download it from the upstream source with `FetchContent`
module and build it together with the PHP build.

See: https://cmake.org/cmake/help/latest/module/FindPNG.html

The `FetchContent` CMake module does things differently compared to the
`find_package()` flow:
* By default, it uses `QUIET` in its `find_package()` call when calling the
`FetchContent_MakeAvailable()`;
* When using `FeatureSummary`, dependencies must be moved manually to
`PACKAGES_FOUND` from the `PACKAGES_NOT_FOUND` global property;

TODO: Improve this. This is for now only initial `FetchContent` integration for
testing purposes and will be changed in the future.
#]=============================================================================]

include(FeatureSummary)
include(FetchContent)

set_package_properties(
PNG
PROPERTIES
URL "http://libpng.org"
DESCRIPTION "Portable Network Graphics (PNG image format) library"
)

# Minimum required version for the PNG dependency.
#set(PHP_PNG_MIN_VERSION ?.?.??)

# Download version when system dependency is not found.
set(PHP_PNG_DOWNLOAD_VERSION 1.6.44)

FetchContent_Declare(
PNG
URL https://download.sourceforge.net/libpng/libpng-${PHP_PNG_DOWNLOAD_VERSION}.tar.gz
EXCLUDE_FROM_ALL
SYSTEM
FIND_PACKAGE_ARGS
)

find_package(PNG ${PHP_PNG_MIN_VERSION})

if(NOT PNG_FOUND)
include(Packages/ZLIB)

set(FETCHCONTENT_QUIET NO)

# The above EXCLUDE_FROM_ALL was introduced in CMake 3.28.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.28)
FetchContent_MakeAvailable(PNG)
else()
FetchContent_GetProperties(PNG)
if(NOT PNG_POPULATED)
FetchContent_Populate(PNG)

add_subdirectory(
${PNG_SOURCE_DIR}
${PNG_BINARY_DIR}
EXCLUDE_FROM_ALL
)
endif()
endif()

# Move dependency to PACKAGES_FOUND.
block()
get_cmake_property(packagesNotFound PACKAGES_NOT_FOUND)
list(REMOVE_ITEM packagesNotFound PNG)
set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND packagesNotFound)
get_cmake_property(packagesFound PACKAGES_FOUND)
set_property(GLOBAL APPEND PROPERTY PACKAGES_FOUND PNG)
endblock()

# Mark package as found.
set(PNG_FOUND TRUE)

# Clean used variables.
unset(FETCHCONTENT_QUIET)
endif()
83 changes: 83 additions & 0 deletions cmake/cmake/modules/Packages/libzip.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#[=============================================================================[
Wrapper for finding the `libzip` library.

Module first tries to find the `libzip` library on the system. If not
successful it tries to download it from the upstream source with `FetchContent`
module and build it together with the PHP build.

The `FetchContent` CMake module does things differently compared to the
`find_package()` flow:
* By default, it uses `QUIET` in its `find_package()` call when calling the
`FetchContent_MakeAvailable()`;
* When using `FeatureSummary`, dependencies must be moved manually to
`PACKAGES_FOUND` from the `PACKAGES_NOT_FOUND` global property;

TODO: Improve this. This is for now only initial `FetchContent` integration for
testing purposes and will be changed in the future.
#]=============================================================================]

include(FeatureSummary)
include(FetchContent)

set_package_properties(
libzip
PROPERTIES
URL "https://libzip.org/"
DESCRIPTION "Library for reading and writing ZIP compressed archives"
)

# Minimum required version for the libzip dependency.
set(PHP_libzip_MIN_VERSION 1.7.1)

# Download version when system dependency is not found.
set(PHP_libzip_DOWNLOAD_VERSION 1.11.2)

FetchContent_Declare(
libzip
URL https://github.com/nih-at/libzip/releases/download/v${PHP_libzip_DOWNLOAD_VERSION}/libzip-${PHP_libzip_DOWNLOAD_VERSION}.tar.gz
EXCLUDE_FROM_ALL
SYSTEM
FIND_PACKAGE_ARGS
)

find_package(libzip ${PHP_libzip_MIN_VERSION})

if(NOT libzip_FOUND)
include(Packages/ZLIB)

set(FETCHCONTENT_QUIET NO)

# The above EXCLUDE_FROM_ALL was introduced in CMake 3.28.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.28)
FetchContent_MakeAvailable(libzip)
else()
FetchContent_GetProperties(libzip)
if(NOT libzip_POPULATED)
FetchContent_Populate(libzip)

add_subdirectory(
${libzip_SOURCE_DIR}
${libzip_BINARY_DIR}
EXCLUDE_FROM_ALL
)
endif()
endif()

# Move dependency to PACKAGES_FOUND.
block()
get_cmake_property(packagesNotFound PACKAGES_NOT_FOUND)
list(REMOVE_ITEM packagesNotFound libzip)
set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND packagesNotFound)
get_cmake_property(packagesFound PACKAGES_FOUND)
set_property(GLOBAL APPEND PROPERTY PACKAGES_FOUND libzip)
endblock()

add_library(libzip::libzip INTERFACE IMPORTED GLOBAL)
target_link_libraries(libzip::libzip INTERFACE zip)

# Mark package as found.
set(libzip_FOUND TRUE)

# Clean used variables.
unset(FETCHCONTENT_QUIET)
endif()
4 changes: 2 additions & 2 deletions cmake/ext/gd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ if(NOT PHP_EXT_GD_EXTERNAL)
)
endif()

find_package(ZLIB ${PHP_ZLIB_MIN_VERSION})
include(PHP/Package/ZLIB)
set_package_properties(
ZLIB
PROPERTIES
Expand All @@ -326,7 +326,7 @@ if(NOT PHP_EXT_GD_EXTERNAL)

target_link_libraries(php_ext_gd PRIVATE ZLIB::ZLIB)

find_package(PNG)
include(Packages/PNG)
set_package_properties(
PNG
PROPERTIES
Expand Down
2 changes: 1 addition & 1 deletion cmake/ext/mysqlnd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ target_link_libraries(
)

if(PHP_EXT_MYSQLND_COMPRESSION)
find_package(ZLIB ${PHP_ZLIB_MIN_VERSION})
include(PHP/Package/ZLIB)
set_package_properties(
ZLIB
PROPERTIES
Expand Down
3 changes: 3 additions & 0 deletions cmake/ext/standard/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Use external crypt library, such as libcrypt or libxcrypt, instead of the
bundled PHP crypt.
#]=============================================================================]

# TODO: ext/standard/image.c depends on zlib extension and its macros but it
# should only depend on zlib library.

project(
PhpExtensionStandard
LANGUAGES C
Expand Down
2 changes: 1 addition & 1 deletion cmake/ext/zip/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ target_sources(

add_dependencies(php_ext_zip php_ext_pcre)

find_package(libzip 1.7.1)
include(Packages/libzip)
set_package_properties(
libzip
PROPERTIES
Expand Down
13 changes: 11 additions & 2 deletions cmake/ext/zlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,24 @@ endif()

target_compile_definitions(php_ext_zlib PRIVATE ZEND_ENABLE_STATIC_TSRMLS_CACHE)

find_package(ZLIB ${PHP_ZLIB_MIN_VERSION})
include(PHP/Package/ZLIB)
set_package_properties(
ZLIB
PROPERTIES
TYPE REQUIRED
PURPOSE "Necessary to enable the zlib extension."
)

target_link_libraries(php_ext_zlib PRIVATE ZLIB::ZLIB)
# Link publicly for internal_functions files and ext/standard/image.c.
target_link_libraries(php_ext_zlib PUBLIC ZLIB::ZLIB)

# TODO: zlib.h must exist when building php_main* targets.
add_dependencies(
php_ext_zlib
php_main
php_main_internal_functions
php_main_internal_functions_cli
)

set(HAVE_ZLIB TRUE)

Expand Down
Loading