Skip to content

Commit 6eb2483

Browse files
committed
Add CMakeLists.txt wrapper
This is attempt to simplify using this repository few steps further. It uses the CMake `FetchContent` module to download PHP sources, adds CMake files and patches PHP sources. Usage: ```sh cmake -B php-build cmake --build php-build -j ```
1 parent ad33ac7 commit 6eb2483

File tree

7 files changed

+360
-511
lines changed

7 files changed

+360
-511
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,25 +127,22 @@ jobs:
127127

128128
- name: Build and install
129129
run: |
130-
./bin/php.cmake ${{ matrix.php }}
131-
cd php-${{ matrix.php }}
132130
cmake --preset all-enabled
133131
cmake --build --preset all-enabled -j
134132
135133
- name: Setup SNMP agents
136134
run: |
137-
cd php-${{ matrix.php }}
135+
cd php-build/all-enabled/php/php-src
138136
sudo cp ext/snmp/tests/snmpd.conf /etc/snmp
139137
sudo cp ext/snmp/tests/bigtest /etc/snmp
140138
sudo systemctl restart snmpd
141139
142140
- name: Setup Dovecot for testing imap extension
143141
run: |
144-
cd php-${{ matrix.php }}
142+
cd php-build/all-enabled/php/php-src/
145143
sudo sh ext/imap/tests/setup/setup.sh
146144
sudo systemctl restart dovecot
147145
148146
- name: Run tests
149147
run: |
150-
cd php-${{ matrix.php }}
151148
ctest --preset all-enabled

.gitignore

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
# to exclude them using the .git/info/exclude in the cloned repository or a
44
# global .gitignore file.
55

6-
# Customizable CMake presets file.
7-
/cmake/CMakeUserPresets.json
8-
96
# All PHP downloaded archives and extracted directories.
107
/php-*
8+
9+
# CMake-related files.
10+
/cmake/CMakeUserPresets.json
11+
/CMakeCache.txt
12+
/CMakeFiles/
13+
/CMakeUserPresets.json

CMakeLists.txt

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# Wrapper for integrating PHP sources with CMake
2+
#
3+
# This file uses the FetchContent module to download the PHP source code (from
4+
# a tarball), integrate additional CMake files, and apply necessary patches to
5+
# enable building PHP with CMake.
6+
#
7+
# While not part of the CMake-based build system itself, this file serves as a
8+
# wrapper to bridge the upstream PHP source code with the CMake-based build
9+
# system in this repository, streamlining the integration process.
10+
11+
cmake_minimum_required(VERSION 3.25...3.31)
12+
13+
if(CMAKE_SOURCE_DIR PATH_EQUAL CMAKE_BINARY_DIR)
14+
message(
15+
FATAL_ERROR
16+
"In-source builds are disabled. Please, set the build directory.\n"
17+
"For example:\n"
18+
" cmake -B php-build\n"
19+
" cmake --build php-build -j"
20+
)
21+
endif()
22+
23+
project(
24+
PhpBuildSystem
25+
VERSION 8.3
26+
DESCRIPTION "CMake-based PHP build system"
27+
HOMEPAGE_URL "https://github.com/petk/php-build-system"
28+
LANGUAGES NONE
29+
)
30+
31+
################################################################################
32+
# Configuration.
33+
################################################################################
34+
35+
block(PROPAGATE phpUrl)
36+
# The PHP_VERSION_DOWNLOAD format: <major>.<minor>[.<patch>][<extra>]
37+
#
38+
# For example:
39+
#
40+
# cmake -B <build-dir> -D PHP_VERSION_DOWNLOAD=8.3-dev
41+
# will download PHP-8.3 Git branch archive file from GitHub.
42+
#
43+
# cmake -B <build-dir> -D PHP_VERSION_DOWNLOAD=8.3.15
44+
# will download this specific PHP version tarball from php.net.
45+
#
46+
# cmake -B <build-dir> -D PHP_VERSION_DOWNLOAD=8.3
47+
# will download latest stable 8.3 release tarball from php.net.
48+
#
49+
set(
50+
PHP_VERSION_DOWNLOAD ${PROJECT_VERSION}
51+
CACHE STRING "The PHP version to download"
52+
)
53+
mark_as_advanced(PHP_VERSION_DOWNLOAD)
54+
55+
# PHP <major>.<minor> version currently in development (the master branch).
56+
set(phpDevelopmentBranch 8.5)
57+
58+
# Validate PHP version.
59+
if(NOT PHP_VERSION_DOWNLOAD MATCHES [[^[0-9]+\.[0-9]+(\.[0-9]+|-dev|$)]])
60+
message(
61+
FATAL_ERROR
62+
"Unsupported PHP version format given: ${PHP_VERSION_DOWNLOAD}\n"
63+
"Expected PHP version format is <major>.<minor>[.<patch>][<extra>]"
64+
)
65+
elseif(NOT PHP_VERSION_DOWNLOAD MATCHES "^${PROJECT_VERSION}(\\.[0-9]+|-dev|$)")
66+
string(REGEX MATCH [[^([0-9]+\.[0-9]+)]] _ "${PHP_VERSION_DOWNLOAD}")
67+
message(
68+
FATAL_ERROR
69+
"Version ${PHP_VERSION_DOWNLOAD} is not supported by the current "
70+
"php-build-system Git repository branch. "
71+
"Please, checkout php-build-system Git branch if available:\n"
72+
" git checkout PHP-${CMAKE_MATCH_1}"
73+
)
74+
endif()
75+
76+
if(PHP_VERSION_DOWNLOAD STREQUAL phpDevelopmentBranch)
77+
set(branch "master")
78+
elseif(PHP_VERSION_DOWNLOAD MATCHES [[^([0-9]+\.[0-9]+)-dev$]])
79+
set(branch "PHP-${CMAKE_MATCH_1}")
80+
elseif(PHP_VERSION_DOWNLOAD MATCHES [[^[0-9]+\.[0-9]+$]])
81+
# Get the latest PHP stable version from JSON API.
82+
string(TIMESTAMP t %s)
83+
set(file "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/php-${t}.json")
84+
file(
85+
DOWNLOAD
86+
"https://www.php.net/releases/?json&version=${PHP_VERSION_DOWNLOAD}"
87+
"${file}"
88+
)
89+
file(READ "${file}" json)
90+
file(REMOVE "${file}")
91+
92+
string(JSON version ERROR_VARIABLE error GET "${json}" version)
93+
94+
if(error)
95+
message(
96+
WARNING
97+
"Latest PHP version could not be determined. "
98+
"Setting version to ${PROJECT_VERSION}-dev.\n${error}"
99+
)
100+
set(version "")
101+
set(branch "PHP-${PROJECT_VERSION}")
102+
endif()
103+
else()
104+
set(branch "")
105+
set(version ${PHP_VERSION_DOWNLOAD})
106+
endif()
107+
108+
if(branch)
109+
set(phpUrl https://github.com/php/php-src/archive/refs/heads/${branch}.tar.gz)
110+
elseif(version)
111+
set(phpUrl https://www.php.net/distributions/php-${version}.tar.gz)
112+
else()
113+
message(FATAL_ERROR "Something went wrong.")
114+
endif()
115+
endblock()
116+
117+
include(FetchContent)
118+
119+
FetchContent_Declare(
120+
php
121+
URL ${phpUrl}
122+
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/php-src
123+
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/php
124+
PATCH_COMMAND
125+
${CMAKE_COMMAND}
126+
-P
127+
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/PhpBuildSystem/patch.cmake
128+
)
129+
130+
# Create script for the FetchContent_Declare(PATCH_COMMAND).
131+
file(
132+
CONFIGURE
133+
OUTPUT CMakeFiles/PhpBuildSystem/patch.cmake
134+
CONTENT [=[
135+
message(STATUS "Adding CMake files to PHP sources")
136+
file(
137+
COPY
138+
"@CMAKE_CURRENT_SOURCE_DIR@/cmake/"
139+
DESTINATION "@CMAKE_CURRENT_BINARY_DIR@/php-src"
140+
)
141+
142+
string(REGEX MATCH [[^([0-9]+\.[0-9]+)]] _ "@PROJECT_VERSION@")
143+
file(
144+
GLOB
145+
patches
146+
"@CMAKE_CURRENT_SOURCE_DIR@/patches/${CMAKE_MATCH_1}/*.patch"
147+
)
148+
149+
if(NOT patches)
150+
return()
151+
endif()
152+
153+
find_package(Git QUIET)
154+
if(NOT Git_FOUND)
155+
# See: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/10164
156+
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.32)
157+
find_package(Patch QUIET)
158+
else()
159+
find_program(Patch_EXECUTABLE patch)
160+
if(Patch_EXECUTABLE)
161+
set(Patch_FOUND TRUE)
162+
endif()
163+
endif()
164+
endif()
165+
166+
if(NOT Git_FOUND AND NOT Patch_FOUND)
167+
message(WARNING "Patches not applied. Install Git or the patch command.")
168+
return()
169+
endif()
170+
171+
message(STATUS "Applying patches to PHP sources\n")
172+
173+
if(Git_FOUND)
174+
# Add .git directory to be able to apply patches.
175+
execute_process(
176+
COMMAND ${GIT_EXECUTABLE} init
177+
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/php-src"
178+
RESULT_VARIABLE result
179+
OUTPUT_VARIABLE output
180+
ERROR_VARIABLE error
181+
ERROR_STRIP_TRAILING_WHITESPACE
182+
OUTPUT_QUIET
183+
)
184+
if(NOT result EQUAL 0)
185+
message(WARNING "Failed to create .git directory:\n${output}\n${error}")
186+
endif()
187+
188+
execute_process(
189+
COMMAND ${GIT_EXECUTABLE} apply --ignore-whitespace ${patches}
190+
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/php-src"
191+
RESULT_VARIABLE result
192+
OUTPUT_VARIABLE output
193+
ERROR_VARIABLE error
194+
ERROR_STRIP_TRAILING_WHITESPACE
195+
OUTPUT_QUIET
196+
)
197+
if(NOT result EQUAL 0)
198+
message(WARNING "Failed to apply patches:\n${output}\n${error}.")
199+
endif()
200+
201+
# Clean temporary .git directory. Checks are done as safeguards.
202+
if(
203+
IS_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/php-src/.git"
204+
AND EXISTS "@CMAKE_CURRENT_BINARY_DIR@/php-src/main/php_version.h"
205+
AND EXISTS "@CMAKE_CURRENT_BINARY_DIR@/php-src/CMakeLists.txt"
206+
)
207+
file(REMOVE_RECURSE "@CMAKE_CURRENT_BINARY_DIR@/php-src/.git/")
208+
endif()
209+
elseif(Patch_FOUND)
210+
foreach(patch IN LISTS patches)
211+
execute_process(
212+
COMMAND ${Patch_EXECUTABLE} -p1 -i "${patch}"
213+
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/php-src"
214+
RESULT_VARIABLE result
215+
OUTPUT_VARIABLE output
216+
ERROR_VARIABLE error
217+
ERROR_STRIP_TRAILING_WHITESPACE
218+
OUTPUT_QUIET
219+
)
220+
if(NOT result EQUAL 0)
221+
cmake_path(GET patch FILENAME filename)
222+
message(WARNING "Patch ${filename} failed:\n${output}\n${error}\n")
223+
endif()
224+
endforeach()
225+
endif()
226+
]=]
227+
@ONLY
228+
)
229+
230+
cmake_path(
231+
RELATIVE_PATH
232+
CMAKE_CURRENT_BINARY_DIR
233+
BASE_DIRECTORY ${CMAKE_SOURCE_DIR}
234+
OUTPUT_VARIABLE relativeDir
235+
)
236+
message(STATUS "Downloading ${phpUrl} to ${relativeDir}")
237+
FetchContent_MakeAvailable(php)
238+
239+
enable_testing()

CMakePresets.json

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
{
2+
"version": 4,
3+
"include": [
4+
"cmake/cmake/presets/all-disabled.json",
5+
"cmake/cmake/presets/all-enabled.json"
6+
],
7+
"configurePresets": [
8+
{
9+
"name": "default",
10+
"displayName": "Default PHP configuration",
11+
"description": "Configuration with the most commonly used PHP extensions enabled",
12+
"binaryDir": "${sourceDir}/php-build/default",
13+
"installDir": "/tmp"
14+
},
15+
{
16+
"name": "default-ts",
17+
"inherits": "default",
18+
"displayName": "Default PHP configuration with thread safety (ZTS)",
19+
"description": "Configuration with the most commonly used PHP extensions enabled and thread safety enabled (ZTS)",
20+
"binaryDir": "${sourceDir}/php-build/default-ts",
21+
"cacheVariables": {
22+
"PHP_THREAD_SAFETY": true
23+
}
24+
},
25+
{
26+
"name": "default-ninja",
27+
"inherits": "default",
28+
"displayName": "Ninja generator with default PHP configuration",
29+
"description": "Ninja generator with default PHP configuration",
30+
"binaryDir": "${sourceDir}/php-build/default-ninja",
31+
"generator": "Ninja"
32+
}
33+
],
34+
"buildPresets": [
35+
{
36+
"name": "default",
37+
"configurePreset": "default"
38+
},
39+
{
40+
"name": "default-ts",
41+
"configurePreset": "default-ts"
42+
},
43+
{
44+
"name": "default-ninja",
45+
"configurePreset": "default-ninja"
46+
}
47+
],
48+
"testPresets": [
49+
{
50+
"name": "default",
51+
"configurePreset": "default",
52+
"environment": {
53+
"SKIP_IO_CAPTURE_TESTS": "1"
54+
},
55+
"output": {
56+
"shortProgress": true,
57+
"verbosity": "verbose"
58+
}
59+
},
60+
{
61+
"name": "default-ts",
62+
"configurePreset": "default-ts",
63+
"inherits": "default"
64+
},
65+
{
66+
"name": "default-ninja",
67+
"configurePreset": "default-ninja",
68+
"inherits": "default"
69+
},
70+
{
71+
"name": "all-disabled",
72+
"configurePreset": "all-disabled",
73+
"inherits": "default"
74+
},
75+
{
76+
"name": "all-disabled-ts",
77+
"configurePreset": "all-disabled-ts",
78+
"inherits": "default"
79+
},
80+
{
81+
"name": "all-disabled-ninja",
82+
"configurePreset": "all-disabled-ninja",
83+
"inherits": "default"
84+
},
85+
{
86+
"name": "all-enabled",
87+
"configurePreset": "all-enabled",
88+
"inherits": "default"
89+
},
90+
{
91+
"name": "all-enabled-shared",
92+
"configurePreset": "all-enabled-shared",
93+
"inherits": "default"
94+
},
95+
{
96+
"name": "all-enabled-ts",
97+
"configurePreset": "all-enabled-ts",
98+
"inherits": "default"
99+
},
100+
{
101+
"name": "all-enabled-2",
102+
"configurePreset": "all-enabled-2",
103+
"inherits": "default"
104+
},
105+
{
106+
"name": "all-enabled-ninja",
107+
"configurePreset": "all-enabled-ninja",
108+
"inherits": "default"
109+
}
110+
]
111+
}

0 commit comments

Comments
 (0)