Skip to content

Commit bbd55fa

Browse files
committed
Improve installation
- New CMake module: PHP/Install that enables all CMAKE_INSTALL_* variables inside the install(CODE <code> ...) - PEAR installation fixed a bit further with some bugs bypassed - Installation is now one step more standard according to GNU standards
1 parent a8495c3 commit bbd55fa

File tree

8 files changed

+243
-57
lines changed

8 files changed

+243
-57
lines changed

bin/check-cmake/cmake-includes.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ modules="
9191
PHP/CheckAttribute
9292
PHP/CheckCompilerFlag
9393
PHP/ConfigureFile
94+
PHP/Install
9495
PHP/PkgConfigGenerator
9596
PHP/SearchLibraries
9697
PHP/SystemExtensions
@@ -158,6 +159,7 @@ PHP_CheckAttribute="
158159
"
159160
PHP_CheckCompilerFlag="php_check_compiler_flag"
160161
PHP_ConfigureFile="php_configure_file"
162+
PHP_Install="php_install"
161163
PHP_PkgConfigGenerator="pkgconfig_generate_pc"
162164
PHP_SearchLibraries="php_search_libraries"
163165
PHP_SystemExtensions='PHP::SystemExtensions'
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#[=============================================================================[
2+
Set the `CMAKE_INSTALL_*` variables inside the `install(CODE|SCRIPT)`.
3+
4+
This is built on top of the CMake's `GNUInstallDirs` module. At the time of
5+
writing, CMake documentation mentions special cases where, for example, the
6+
`CMAKE_INSTALL_FULL_SYSCONFDIR` variable becomes the `/etc`, when the install
7+
prefix is `/usr`, and similar.
8+
9+
However, some of these special cases aren't taken into account when using the
10+
`install()` commands.
11+
12+
This module exposes the following function:
13+
14+
```cmake
15+
php_install(CODE <code> ...)
16+
```
17+
18+
It acts the same as `install(CODE <code> ...)`, except that also the
19+
`CMAKE_INSTALL_*` variables are available inside the <code> argument, like in
20+
the rest of the CMake code.
21+
22+
```cmake
23+
php_install(CODE "
24+
message(STATUS \"CMAKE_INSTALL_SYSCONFDIR=\${CMAKE_INSTALL_SYSCONFDIR}\")
25+
")
26+
```
27+
28+
See:
29+
30+
* https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
31+
* https://cmake.org/cmake/help/latest/command/install.html
32+
#]=============================================================================]
33+
34+
include_guard(GLOBAL)
35+
36+
if(NOT CMAKE_SCRIPT_MODE_FILE)
37+
include(GNUInstallDirs)
38+
endif()
39+
40+
function(_php_install_set_absolute var)
41+
if(IS_ABSOLUTE "${CMAKE_INSTALL_${var}}")
42+
set(CMAKE_INSTALL_FULL_${var} "${CMAKE_INSTALL_${var}}" PARENT_SCOPE)
43+
else()
44+
set(
45+
CMAKE_INSTALL_FULL_${var}
46+
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${var}}"
47+
PARENT_SCOPE
48+
)
49+
endif()
50+
endfunction()
51+
52+
function(_php_install_set_absolute_special var)
53+
if(var STREQUAL "RUNSTATEDIR")
54+
set(directoryName "var/run")
55+
elseif(var STREQUAL "LOCALSTATEDIR")
56+
set(directoryName "var")
57+
elseif(var STREQUAL "SYSCONFDIR")
58+
set(directoryName "etc")
59+
else()
60+
message(
61+
FATAL_ERROR
62+
"CMAKE_INSTALL_${var} is not a special-case GNU standard variable")
63+
endif()
64+
65+
if(IS_ABSOLUTE "${CMAKE_INSTALL_${var}}")
66+
set(dir "${CMAKE_INSTALL_${var}}")
67+
set(fulldir "${CMAKE_INSTALL_${var}}")
68+
elseif(
69+
CMAKE_INSTALL_${var} MATCHES "^(etc|var|var/run)$"
70+
AND CMAKE_INSTALL_PREFIX MATCHES "^/usr[/]?$"
71+
)
72+
set(dir "${CMAKE_INSTALL_${var}}")
73+
set(fulldir "/${CMAKE_INSTALL_${var}}")
74+
elseif(
75+
CMAKE_INSTALL_${var} MATCHES "^(etc|var|var/run)$"
76+
AND NOT CMAKE_INSTALL_PREFIX MATCHES "^/opt/homebrew$|^/opt/homebrew/.*$"
77+
AND CMAKE_INSTALL_PREFIX MATCHES "^/opt/(.*)"
78+
)
79+
set(dir "${CMAKE_INSTALL_${var}}")
80+
set(fulldir "/${directoryName}/opt/${CMAKE_MATCH_1}")
81+
else()
82+
set(dir "${CMAKE_INSTALL_${var}}")
83+
set(fulldir "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${var}}")
84+
endif()
85+
86+
set(CMAKE_INSTALL_${var} "${dir}" PARENT_SCOPE)
87+
set(CMAKE_INSTALL_FULL_${var} "${fulldir}" PARENT_SCOPE)
88+
endfunction()
89+
90+
macro(_php_install_gnu_install_dirs)
91+
foreach(
92+
var
93+
BINDIR
94+
SBINDIR
95+
LIBEXECDIR
96+
SHAREDSTATEDIR
97+
LIBDIR
98+
INCLUDEDIR
99+
OLDINCLUDEDIR
100+
DATAROOTDIR
101+
DATADIR
102+
INFODIR
103+
LOCALEDIR
104+
MANDIR
105+
DOCDIR
106+
)
107+
_php_install_set_absolute(${var})
108+
endforeach()
109+
110+
_php_install_set_absolute_special(LOCALSTATEDIR)
111+
_php_install_set_absolute_special(RUNSTATEDIR)
112+
_php_install_set_absolute_special(SYSCONFDIR)
113+
endmacro()
114+
115+
function(php_install type code)
116+
if(NOT type STREQUAL "CODE")
117+
message(FATAL_ERROR "Type ${type} is not supported.")
118+
endif()
119+
120+
install(CODE "
121+
set(CMAKE_INSTALL_BINDIR \"${CMAKE_INSTALL_BINDIR}\")
122+
set(CMAKE_INSTALL_SBINDIR \"${CMAKE_INSTALL_SBINDIR}\")
123+
set(CMAKE_INSTALL_LIBEXECDIR \"${CMAKE_INSTALL_LIBEXECDIR}\")
124+
set(CMAKE_INSTALL_SYSCONFDIR \"${CMAKE_INSTALL_SYSCONFDIR}\")
125+
set(CMAKE_INSTALL_SHAREDSTATEDIR \"${CMAKE_INSTALL_SHAREDSTATEDIR}\")
126+
set(CMAKE_INSTALL_LOCALSTATEDIR \"${CMAKE_INSTALL_LOCALSTATEDIR}\")
127+
set(CMAKE_INSTALL_RUNSTATEDIR \"${CMAKE_INSTALL_RUNSTATEDIR}\")
128+
set(CMAKE_INSTALL_LIBDIR \"${CMAKE_INSTALL_LIBDIR}\")
129+
set(CMAKE_INSTALL_INCLUDEDIR \"${CMAKE_INSTALL_INCLUDEDIR}\")
130+
set(CMAKE_INSTALL_OLDINCLUDEDIR \"${CMAKE_INSTALL_OLDINCLUDEDIR}\")
131+
set(CMAKE_INSTALL_DATAROOTDIR \"${CMAKE_INSTALL_DATAROOTDIR}\")
132+
set(CMAKE_INSTALL_DATADIR \"${CMAKE_INSTALL_DATADIR}\")
133+
set(CMAKE_INSTALL_INFODIR \"${CMAKE_INSTALL_INFODIR}\")
134+
set(CMAKE_INSTALL_LOCALEDIR \"${CMAKE_INSTALL_LOCALEDIR}\")
135+
set(CMAKE_INSTALL_MANDIR \"${CMAKE_INSTALL_MANDIR}\")
136+
set(CMAKE_INSTALL_DOCDIR \"${CMAKE_INSTALL_DOCDIR}\")
137+
138+
include(${CMAKE_CURRENT_FUNCTION_LIST_FILE})
139+
140+
_php_install_gnu_install_dirs()
141+
142+
${code}
143+
" ${ARGN})
144+
endfunction()

cmake/ext/phar/CMakeLists.txt

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
include(CMakeDependentOption)
22
include(FeatureSummary)
3+
include(PHP/Install)
34

45
option(EXT_PHAR "Enable the phar extension" ON)
56

@@ -81,13 +82,6 @@ endif()
8182

8283
# Generate phar.php.
8384
if(PHP_EXECUTABLE)
84-
file(
85-
GLOB_RECURSE
86-
dependent_files
87-
${CMAKE_CURRENT_SOURCE_DIR}/phar/*.inc
88-
${CMAKE_CURRENT_SOURCE_DIR}/phar/*.php
89-
)
90-
9185
if(EXT_PHAR_SHARED OR BUILD_SHARED_LIBS)
9286
set(
9387
phar_shared_options
@@ -170,21 +164,28 @@ if(PHP_EXECUTABLE)
170164
COMMENT "[ext/phar] Generating phar"
171165
)
172166

167+
file(
168+
GLOB_RECURSE
169+
dependentFiles
170+
${CMAKE_CURRENT_SOURCE_DIR}/phar/*.inc
171+
${CMAKE_CURRENT_SOURCE_DIR}/phar/*.php
172+
)
173+
173174
add_custom_target(
174175
php_phar_generate_file
175176
ALL
176177
DEPENDS
177178
php_cli
178179
php_phar
179-
${dependent_files}
180+
${dependentFiles}
180181
php_phar_generated_phar
181182
)
182183
set_property(SOURCE php_phar_generated_phar PROPERTY SYMBOLIC TRUE)
183184

184185
# Install phar.phar file to destination. Here a duplicate phar.phar generation
185186
# step is used to generate it to a destination directory because of the
186187
# install prefix used in shebang (when using 'cmake --install --prefix ...').
187-
install(CODE "
188+
php_install(CODE "
188189
execute_process(
189190
COMMAND
190191
${PHP_EXECUTABLE}
@@ -196,20 +197,19 @@ if(PHP_EXECUTABLE)
196197
-d phar.readonly=0
197198
${CMAKE_CURRENT_BINARY_DIR}/phar.php
198199
pack
199-
-f ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PHP_PROGRAM_PREFIX}phar${PHP_PROGRAM_SUFFIX}.phar
200+
-f ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/phar.phar
200201
-a pharcommand
201202
-c auto
202203
-p 0
203204
-s ${CMAKE_CURRENT_SOURCE_DIR}/phar/phar.php
204205
-h sha1
205-
-b \${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/$<TARGET_FILE_NAME:php_cli>
206+
-b \${CMAKE_INSTALL_FULL_BINDIR}/$<TARGET_FILE_NAME:php_cli>
206207
${CMAKE_CURRENT_SOURCE_DIR}/phar
207208
)
208209
209210
file(
210-
INSTALL
211-
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PHP_PROGRAM_PREFIX}phar${PHP_PROGRAM_SUFFIX}.phar
212-
DESTINATION \${DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}
211+
CHMOD
212+
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/phar.phar
213213
FILE_PERMISSIONS
214214
OWNER_READ
215215
OWNER_WRITE
@@ -220,10 +220,16 @@ if(PHP_EXECUTABLE)
220220
WORLD_EXECUTE
221221
)
222222
223+
file(
224+
COPY_FILE
225+
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/phar.phar
226+
\$ENV{DESTDIR}\${CMAKE_INSTALL_FULL_BINDIR}/${PHP_PROGRAM_PREFIX}phar${PHP_PROGRAM_SUFFIX}.phar
227+
)
228+
223229
file(
224230
CREATE_LINK
225231
${PHP_PROGRAM_PREFIX}phar${PHP_PROGRAM_SUFFIX}.phar
226-
\${DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/phar
232+
\$ENV{DESTDIR}\${CMAKE_INSTALL_FULL_BINDIR}/${PHP_PROGRAM_PREFIX}phar${PHP_PROGRAM_SUFFIX}
227233
SYMBOLIC
228234
)
229235
")

cmake/ext/skeleton/cmake/Bootstrap.cmake

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# Set GNU standard installation directories.
22
include(GNUInstallDirs)
33

4-
set(CMAKE_INSTALL_INCLUDEDIR "${PHP_INSTALL_INCLUDEDIR}")
5-
64
# Run at the end of the extension's configuration phase.
75
cmake_language(DEFER DIRECTORY ${CMAKE_SOURCE_DIR} CALL _php_hook_end_of_configure())
86
function(_php_hook_end_of_configure)

cmake/pear/CMakeLists.txt

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
include(FeatureSummary)
2+
include(PHP/Install)
23

34
option(PHP_PEAR "Whether to install PEAR" OFF)
45

@@ -53,19 +54,16 @@ endif()
5354
# TODO: INSTALL_PREFIX here cannot be evaluated during the install phase.
5455
set(EXPANDED_PEAR_INSTALLDIR "${_php_pear_dir}" CACHE INTERNAL "PEAR dir")
5556

56-
# TODO: Recheck if _php_pear_dir needs to be manually created here.
57-
install(CODE "
58-
set(_php_pear_installer_url \"https://pear.php.net/install-pear-nozlib.phar\")
57+
if(NOT CMAKE_CROSSCOMPILING)
58+
set(PHP_EXECUTABLE "$<TARGET_FILE:php_cli>")
59+
elseif(CMAKE_CROSSCOMPILING AND CMAKE_CROSSCOMPILING_EMULATOR)
60+
set(PHP_EXECUTABLE "${CMAKE_CROSSCOMPILING_EMULATOR};$<TARGET_FILE:php_cli>")
61+
endif()
5962

60-
# The generator expression $<INSTALL_PREFIX> inside CODE argument is evaluated
61-
# in CMake 3.27+.
62-
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.27)
63-
set(prefix $<INSTALL_PREFIX>)
64-
else()
65-
set(prefix \${CMAKE_INSTALL_PREFIX})
66-
endif()
63+
set(_phpPearInstallerUrl "https://pear.php.net/install-pear-nozlib.phar")
6764

68-
message(STATUS \"Installing PEAR environment: ${_php_pear_dir}\")
65+
php_install(CODE "
66+
message(STATUS \"Installing PEAR: \$ENV{DESTDIR}${_php_pear_dir}\")
6967
7068
if(EXISTS \"${CMAKE_CURRENT_SOURCE_DIR}/install-pear-nozlib.phar\"
7169
AND NOT \"${CMAKE_CURRENT_SOURCE_DIR}\" STREQUAL \"${CMAKE_CURRENT_BINARY_DIR}\"
@@ -80,31 +78,51 @@ install(CODE "
8078
if(NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/install-pear-nozlib.phar\")
8179
file(
8280
DOWNLOAD
83-
\${_php_pear_installer_url}
81+
${_phpPearInstallerUrl}
8482
\"${CMAKE_CURRENT_BINARY_DIR}/install-pear-nozlib.phar\"
8583
SHOW_PROGRESS
86-
STATUS _php_pear_download
84+
STATUS downloadStatus
8785
)
8886
89-
if(NOT _php_pear_download)
87+
if(NOT downloadStatus)
9088
# Download using fetch.php.
9189
execute_process(
92-
COMMAND ${PHP_BINARY_DIR}/sapi/cli/php
93-
-n
94-
${CMAKE_CURRENT_BINARY_DIR}/fetch.php
95-
\"\${_php_pear_installer_url}\"
96-
${CMAKE_CURRENT_BINARY_DIR}/install-pear-nozlib.phar
90+
COMMAND ${PHP_EXECUTABLE}
91+
-n
92+
${CMAKE_CURRENT_BINARY_DIR}/fetch.php
93+
${_phpPearInstallerUrl}
94+
${CMAKE_CURRENT_BINARY_DIR}/install-pear-nozlib.phar
95+
OUTPUT_VARIABLE output
96+
ERROR_VARIABLE output
9797
)
98+
if(output)
99+
message(STATUS \"\${output}\")
100+
endif()
98101
endif()
99102
endif()
100103
101104
if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/install-pear-nozlib.phar)
102-
# PEAR reads the INSTALL_ROOT environment variable to install pear.conf.
103-
# TODO: Adjust this further.
104-
#set(ENV{INSTALL_ROOT} \"\${prefix}\")
105+
# PEAR reads the staging INSTALL_ROOT environment variable if set. However,
106+
# there is a bug where .channels, .registry and temporary dot files are
107+
# duplicated outside of the INSTALL_ROOT into the install prefix. No known
108+
# workaround. See: https://pear.php.net/bugs/bug.php?id=20383
109+
if(DEFINED ENV{DESTDIR})
110+
set(ENV{INSTALL_ROOT} \"\$ENV{DESTDIR}\")
111+
endif()
112+
113+
# The PEAR's --config option doesn't seem to install the pear.conf into the
114+
# specified directory, but the sysconf can be also bypassed with the
115+
# environment variable.
116+
set(ENV{PHP_PEAR_SYSCONF_DIR} \${CMAKE_INSTALL_FULL_SYSCONFDIR})
117+
118+
file(
119+
MAKE_DIRECTORY
120+
\$ENV{DESTDIR}${_php_pear_dir}
121+
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/pear
122+
)
105123
106124
execute_process(
107-
COMMAND ${PHP_BINARY_DIR}/sapi/cli/php
125+
COMMAND ${PHP_EXECUTABLE}
108126
-n
109127
-dshort_open_tag=0
110128
-dopen_basedir=
@@ -113,19 +131,26 @@ install(CODE "
113131
-ddetect_unicode=0
114132
${CMAKE_CURRENT_BINARY_DIR}/install-pear-nozlib.phar
115133
--dir \"${_php_pear_dir}\"
116-
--bin \"\${prefix}/${CMAKE_INSTALL_BINDIR}\"
117-
--config \"\${prefix}/${CMAKE_INSTALL_SYSCONFDIR}\"
118-
--metadata \"\${prefix}/${CMAKE_INSTALL_DATADIR}\"
134+
--bin \"\${CMAKE_INSTALL_FULL_BINDIR}\"
135+
--metadata \"${_php_pear_dir}\"
136+
--data \"${_php_pear_dir}\"
137+
--temp \"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/pear\"
138+
#--php \${CMAKE_INSTALL_FULL_BINDIR}/$<TARGET_FILE_NAME:php_cli>
119139
-dp a${PHP_PROGRAM_PREFIX}
120-
-ds a$(PHP_PROGRAM_SUFFIX)
140+
-ds a${PHP_PROGRAM_SUFFIX}
141+
OUTPUT_VARIABLE output
142+
ERROR_VARIABLE output
121143
)
144+
if(output)
145+
message(STATUS \"\${output}\")
146+
endif()
122147
else()
123148
message(
124149
WARNING
125150
\"The installation process is not complete. The following resources \"
126151
\"were not installed:\\n\"
127152
\" PEAR: PHP Extension and Application Repository\\n\"
128-
\"To install these components, download \${_php_pear_installer_url} to \"
153+
\"To install these components, download ${_phpPearInstallerUrl} to \"
129154
\"to php-src/pear/ and repeat the 'cmake --install' command.\"
130155
)
131156
endif()

0 commit comments

Comments
 (0)