Skip to content

Commit 1ea0a5f

Browse files
authored
Add CMakeLists.txt wrapper (#30)
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 applies patches to PHP sources. Usage: ```sh cmake -B php-build cmake --build php-build -j ```
1 parent ad33ac7 commit 1ea0a5f

File tree

11 files changed

+356
-561
lines changed

11 files changed

+356
-561
lines changed

.github/workflows/check-cmake.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,11 @@ jobs:
3636
- name: Run checks
3737
run: ./bin/check-cmake.php
3838

39+
# TODO: Remove PHP_CS_FIXER_IGNORE_ENV once php-cs-fixer supports PHP 8.4.
3940
- name: Run PHP CS Fixer
40-
run: php-cs-fixer check --diff --rules=@Symfony,@PER-CS --using-cache=no -- bin
41+
run: |
42+
PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer check \
43+
--diff \
44+
--rules=@Symfony,@PER-CS \
45+
--using-cache=no \
46+
-- bin

.github/workflows/ci.yaml

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,14 @@ jobs:
3232
- { name: LLVM15, CC: clang-15, CXX: clang++-15, packages: clang-15 libomp-15-dev llvm-15-dev libc++-15-dev libc++abi1-15 lld-15 clang-tools-15 mlir-15-tools libmlir-15-dev }
3333
build_type:
3434
- Release
35-
target:
36-
- build
3735
generator:
3836
- Unix Makefiles
3937
php:
4038
- 8.3-dev
4139
env:
4240
CC: ${{ matrix.compiler.CC }}
4341
CXX: ${{ matrix.compiler.CXX }}
44-
SRC_DIR: ${{ github.workspace }}/php-src
45-
BINARY_DIR: ${{ github.workspace }}/php-src
46-
INSTALL_PREFIX: ${{ github.workspace }}/php-src/install
4742
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
48-
GENERATOR: ${{ matrix.generator }}
49-
TARGET: ${{ matrix.target }}
5043
steps:
5144
- name: Install compiler ${{ matrix.compiler.name }}
5245
run: |
@@ -127,25 +120,21 @@ jobs:
127120

128121
- name: Build and install
129122
run: |
130-
./bin/php.cmake ${{ matrix.php }}
131-
cd php-${{ matrix.php }}
132123
cmake --preset all-enabled
133124
cmake --build --preset all-enabled -j
134125
135126
- name: Setup SNMP agents
136127
run: |
137-
cd php-${{ matrix.php }}
138-
sudo cp ext/snmp/tests/snmpd.conf /etc/snmp
139-
sudo cp ext/snmp/tests/bigtest /etc/snmp
128+
cd php-build/all-enabled/php-src
129+
sudo cp ext/snmp/tests/{snmpd.conf,bigtest} /etc/snmp
140130
sudo systemctl restart snmpd
141131
142132
- name: Setup Dovecot for testing imap extension
143133
run: |
144-
cd php-${{ matrix.php }}
134+
cd php-build/all-enabled/php-src
145135
sudo sh ext/imap/tests/setup/setup.sh
146136
sudo systemctl restart dovecot
147137
148138
- name: Run tests
149139
run: |
150-
cd php-${{ matrix.php }}
151140
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: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
#[=============================================================================[
2+
Wrapper for integrating PHP sources with CMake
3+
4+
This file uses the FetchContent module to download the PHP source code tarball,
5+
integrate CMake files, and apply necessary patches to enable building PHP with
6+
CMake.
7+
8+
While not part of the CMake-based build system itself, this file serves as a
9+
wrapper to bridge the upstream PHP source code with the CMake-based build system
10+
in this repository located at the cmake directory, streamlining the integration
11+
process.
12+
13+
Basic usage:
14+
15+
cmake -B <build-dir> [<options>...]
16+
17+
Configuration variables:
18+
19+
PHP_VERSION_DOWNLOAD
20+
PHP version to download. Format: <major>.<minor>[.<patch>][<extra>]
21+
22+
For example:
23+
24+
cmake -B <build-dir>
25+
will download PHP-8.3 Git branch archive from GitHub. Same as:
26+
cmake -B <build-dir> -D PHP_VERSION_DOWNLOAD=8.3-dev
27+
28+
cmake -B <build-dir> -D PHP_VERSION_DOWNLOAD=8.3
29+
will download latest stable 8.3 release tarball from php.net.
30+
31+
cmake -B <build-dir> -D PHP_VERSION_DOWNLOAD=8.3.15
32+
will download specific PHP version tarball from php.net.
33+
34+
Other PHP-related configuration variables can be passed similarly. For example:
35+
36+
cmake -B <build-dir> -D PHP_VERSION_DOWNLOAD=8.3 -D PHP_THREAD_SAFETY=ON
37+
will download latest PHP 8.3 tarball and enable PHP thread safety (ZTS).
38+
39+
After configuration and generation phase is complete, PHP can be built by:
40+
41+
cmake --build <build-dir> -j
42+
and the built PHP binary should be then ready to run:
43+
<build-dir>/php/sapi/cli/php -v
44+
45+
See build system documentation for available PHP configuration variables and
46+
further information.
47+
#]=============================================================================]
48+
49+
cmake_minimum_required(VERSION 3.25...3.31)
50+
51+
if(CMAKE_SOURCE_DIR PATH_EQUAL CMAKE_BINARY_DIR)
52+
message(
53+
FATAL_ERROR
54+
"In-source builds are disabled. Please, set the build directory.\n"
55+
"For example:\n"
56+
" cmake -B php-build\n"
57+
" cmake --build php-build -j"
58+
)
59+
endif()
60+
61+
project(
62+
PhpBuildSystem
63+
VERSION 8.3
64+
DESCRIPTION "CMake-based PHP build system"
65+
HOMEPAGE_URL "https://github.com/petk/php-build-system"
66+
LANGUAGES NONE
67+
)
68+
69+
# Configuration.
70+
block(PROPAGATE phpUrl)
71+
set(
72+
PHP_VERSION_DOWNLOAD "${PROJECT_VERSION}-dev"
73+
CACHE STRING "The PHP version to download"
74+
)
75+
mark_as_advanced(PHP_VERSION_DOWNLOAD)
76+
77+
# PHP <major>.<minor> version currently in development (the master branch).
78+
set(phpDevelopmentBranch 8.5)
79+
80+
# Validate PHP version.
81+
if(NOT PHP_VERSION_DOWNLOAD MATCHES [[^[0-9]+\.[0-9]+(\.[0-9]+|-dev|$)]])
82+
message(
83+
FATAL_ERROR
84+
"Unsupported PHP version format given: ${PHP_VERSION_DOWNLOAD}\n"
85+
"Expected PHP version format is <major>.<minor>[.<patch>][<extra>]"
86+
)
87+
elseif(NOT PHP_VERSION_DOWNLOAD MATCHES "^${PROJECT_VERSION}(\\.[0-9]+|-dev|$)")
88+
string(REGEX MATCH [[^([0-9]+\.[0-9]+)]] _ "${PHP_VERSION_DOWNLOAD}")
89+
message(
90+
FATAL_ERROR
91+
"Version ${PHP_VERSION_DOWNLOAD} is not supported by the current Git "
92+
"branch of the php-build-system repository. Please checkout the "
93+
"PHP-${CMAKE_MATCH_1} Git branch if it exists:\n"
94+
" git checkout PHP-${CMAKE_MATCH_1}"
95+
)
96+
endif()
97+
98+
set(branch "")
99+
set(version "")
100+
101+
if(PHP_VERSION_DOWNLOAD MATCHES "^${phpDevelopmentBranch}(-dev)?(.*)$")
102+
if(CMAKE_MATCH_2)
103+
message(
104+
WARNING
105+
"PHP ${phpDevelopmentBranch} is marked as development branch. Version "
106+
"has been set to ${phpDevelopmentBranch}-dev"
107+
)
108+
endif()
109+
set(branch "master")
110+
elseif(PHP_VERSION_DOWNLOAD MATCHES [[^([0-9]+\.[0-9]+)-dev$]])
111+
set(branch "PHP-${CMAKE_MATCH_1}")
112+
else()
113+
# Get the latest PHP stable version from JSON API.
114+
string(TIMESTAMP timestamp %s)
115+
set(file "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/php-${timestamp}.json")
116+
file(
117+
DOWNLOAD
118+
"https://www.php.net/releases/?json&version=${PHP_VERSION_DOWNLOAD}"
119+
"${file}"
120+
)
121+
file(READ "${file}" json)
122+
file(REMOVE "${file}")
123+
124+
string(JSON version ERROR_VARIABLE error GET "${json}" version)
125+
126+
if(PHP_VERSION_DOWNLOAD MATCHES [[^[0-9]+\.[0-9]+$]] AND error)
127+
message(
128+
WARNING
129+
"Latest PHP version could not be determined. Setting version to "
130+
"${PROJECT_VERSION}-dev."
131+
)
132+
set(version "")
133+
set(branch "PHP-${PROJECT_VERSION}")
134+
elseif(NOT version)
135+
message(
136+
FATAL_ERROR
137+
"PHP version ${PHP_VERSION_DOWNLOAD} could not be found. Either this "
138+
"version is not available for download or some error happened. "
139+
"Available versions can be found at:\n"
140+
" https://www.php.net/downloads.php"
141+
)
142+
endif()
143+
endif()
144+
145+
if(branch)
146+
set(phpUrl https://github.com/php/php-src/archive/refs/heads/${branch}.tar.gz)
147+
elseif(version)
148+
set(phpUrl https://www.php.net/distributions/php-${version}.tar.gz)
149+
else()
150+
message(FATAL_ERROR "Something went wrong.")
151+
endif()
152+
endblock()
153+
154+
include(FetchContent)
155+
156+
FetchContent_Declare(
157+
php
158+
URL ${phpUrl}
159+
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/php-src
160+
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/php
161+
PATCH_COMMAND
162+
${CMAKE_COMMAND}
163+
-P
164+
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/PhpBuildSystem/patch.cmake
165+
)
166+
167+
# Create script for the FetchContent_Declare(PATCH_COMMAND).
168+
file(
169+
CONFIGURE
170+
OUTPUT CMakeFiles/PhpBuildSystem/patch.cmake
171+
CONTENT [=[
172+
message(STATUS "Adding CMake files to PHP sources")
173+
file(
174+
COPY
175+
"@CMAKE_CURRENT_SOURCE_DIR@/cmake/"
176+
DESTINATION "@CMAKE_CURRENT_BINARY_DIR@/php-src"
177+
)
178+
179+
string(REGEX MATCH [[^([0-9]+\.[0-9]+)]] _ "@PROJECT_VERSION@")
180+
file(
181+
GLOB
182+
patches
183+
"@CMAKE_CURRENT_SOURCE_DIR@/patches/${CMAKE_MATCH_1}/*.patch"
184+
)
185+
186+
if(NOT patches)
187+
return()
188+
endif()
189+
190+
find_package(Git QUIET)
191+
if(NOT Git_FOUND)
192+
# See: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/10164
193+
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.32)
194+
find_package(Patch QUIET)
195+
else()
196+
find_program(Patch_EXECUTABLE patch)
197+
if(Patch_EXECUTABLE)
198+
set(Patch_FOUND TRUE)
199+
endif()
200+
endif()
201+
endif()
202+
203+
if(NOT Git_FOUND AND NOT Patch_FOUND)
204+
message(WARNING "Patches not applied. Install Git or the patch command.")
205+
return()
206+
endif()
207+
208+
message(STATUS "Applying patches to PHP sources\n")
209+
210+
if(Git_FOUND)
211+
# Add .git directory to be able to apply patches.
212+
execute_process(
213+
COMMAND ${GIT_EXECUTABLE} init
214+
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/php-src"
215+
RESULT_VARIABLE result
216+
OUTPUT_VARIABLE output
217+
ERROR_VARIABLE error
218+
ERROR_STRIP_TRAILING_WHITESPACE
219+
OUTPUT_QUIET
220+
)
221+
if(NOT result EQUAL 0)
222+
message(WARNING "Failed to create .git directory:\n${output}\n${error}")
223+
endif()
224+
225+
execute_process(
226+
COMMAND ${GIT_EXECUTABLE} apply --ignore-whitespace ${patches}
227+
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/php-src"
228+
RESULT_VARIABLE result
229+
OUTPUT_VARIABLE output
230+
ERROR_VARIABLE error
231+
ERROR_STRIP_TRAILING_WHITESPACE
232+
OUTPUT_QUIET
233+
)
234+
if(NOT result EQUAL 0)
235+
message(WARNING "Failed to apply patches:\n${output}\n${error}.")
236+
endif()
237+
238+
# Clean temporary .git directory. Checks are done as safeguards.
239+
if(
240+
IS_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/php-src/.git"
241+
AND EXISTS "@CMAKE_CURRENT_BINARY_DIR@/php-src/main/php_version.h"
242+
AND EXISTS "@CMAKE_CURRENT_BINARY_DIR@/php-src/CMakeLists.txt"
243+
)
244+
file(REMOVE_RECURSE "@CMAKE_CURRENT_BINARY_DIR@/php-src/.git/")
245+
endif()
246+
elseif(Patch_FOUND)
247+
foreach(patch IN LISTS patches)
248+
execute_process(
249+
COMMAND ${Patch_EXECUTABLE} -p1 -i "${patch}"
250+
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/php-src"
251+
RESULT_VARIABLE result
252+
OUTPUT_VARIABLE output
253+
ERROR_VARIABLE error
254+
ERROR_STRIP_TRAILING_WHITESPACE
255+
OUTPUT_QUIET
256+
)
257+
if(NOT result EQUAL 0)
258+
cmake_path(GET patch FILENAME filename)
259+
message(WARNING "Patch ${filename} failed:\n${output}\n${error}\n")
260+
endif()
261+
endforeach()
262+
endif()
263+
]=]
264+
@ONLY
265+
)
266+
267+
cmake_path(
268+
RELATIVE_PATH
269+
CMAKE_CURRENT_BINARY_DIR
270+
BASE_DIRECTORY ${CMAKE_SOURCE_DIR}
271+
OUTPUT_VARIABLE relativeDir
272+
)
273+
message(STATUS "Downloading ${phpUrl} to ${relativeDir}")
274+
FetchContent_MakeAvailable(php)
275+
276+
enable_testing()

CMakePresets.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"version": 4,
3+
"include": [
4+
"cmake/CMakePresets.json"
5+
]
6+
}

0 commit comments

Comments
 (0)