Skip to content

Commit 8f7387b

Browse files
committed
Refactor PHP/StandardLibrary module
This avoids defining __MUSL__ and some other redundant internal cache variables.
1 parent 14c6521 commit 8f7387b

File tree

7 files changed

+191
-116
lines changed

7 files changed

+191
-116
lines changed

cmake/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ check_pie_supported()
8989
# Configure build types.
9090
include(cmake/BuildTypes.cmake)
9191

92+
# Detect C standard library implementation.
93+
include(PHP/StandardLibrary)
94+
9295
# Set platform-specific configuration.
9396
include(cmake/Platform.cmake)
9497

cmake/cmake/Platform.cmake

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ target_link_libraries(php_config INTERFACE PHP::SystemExtensions)
2121
# Define GNU standard installation directories.
2222
include(GNUInstallDirs)
2323

24-
# Detect C standard library implementation.
25-
include(PHP/StandardLibrary)
26-
2724
# Platform-specific configuration. When cross-compiling, the host and target can
2825
# be different values with different configurations.
2926
if(NOT CMAKE_HOST_SYSTEM_NAME EQUAL CMAKE_SYSTEM_NAME)
Lines changed: 184 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
#[=============================================================================[
22
# PHP/StandardLibrary
33
4-
This module determines the C standard library used for the build:
4+
This module determines the C standard library used for the build.
5+
6+
Load this module in a CMake project with:
57
68
```cmake
79
include(PHP/StandardLibrary)
810
```
911
10-
## Cache variables
12+
## Variables
13+
14+
Including this module will define the following variables:
15+
16+
### Cache variables
1117
1218
* `PHP_C_STANDARD_LIBRARY`
1319
14-
Lowercase name of the C standard library:
20+
Lowercase name of the C standard library. This internal cache variable will be
21+
set to one of the following values:
1522
1623
* `cosmopolitan`
1724
* `dietlibc`
@@ -20,135 +27,201 @@ include(PHP/StandardLibrary)
2027
* `mscrt`
2128
* `musl`
2229
* `uclibc`
30+
* "" (empty string)
31+
32+
If C standard library cannot be determined, it is set to empty string.
33+
34+
### Result variables:
2335
24-
If library cannot be determined, it is set to empty string.
36+
* `PHP_C_STANDARD_LIBRARY_CODE`
2537
26-
* `__MUSL__` - Whether the C standard library is musl.
38+
CMake variable containing some helper code for use in the C configuration
39+
header.
40+
41+
For example, when C standard library implementation is musl, the value of this
42+
variable will contain:
43+
44+
```c
45+
/* Define to 1 when using musl libc. */
46+
#define __MUSL__ 1
47+
```
2748
2849
## Examples
2950
3051
Basic usage:
3152
3253
```cmake
3354
# CMakeLists.txt
55+
3456
include(PHP/StandardLibrary)
57+
58+
message(STATUS "PHP_C_STANDARD_LIBRARY=${PHP_C_STANDARD_LIBRARY}")
59+
60+
file(CONFIGURE OUTPUT config.h CONTENT [[
61+
@PHP_C_STANDARD_LIBRARY_CODE@
62+
]])
3563
```
3664
#]=============================================================================]
3765

38-
include_guard(GLOBAL)
39-
40-
if(DEFINED PHP_C_STANDARD_LIBRARY)
66+
# Skip in consecutive configuration phases and set configuration header code for
67+
# consecutive module inclusions, if needed.
68+
if(COMMAND _php_standard_library_get_code)
69+
_php_standard_library_get_code(PHP_C_STANDARD_LIBRARY_CODE)
4170
return()
4271
endif()
4372

73+
include_guard(GLOBAL)
74+
4475
include(CheckSymbolExists)
4576
include(CMakePushCheckState)
4677

47-
set(PHP_C_STANDARD_LIBRARY "" CACHE INTERNAL "The C standard library.")
48-
49-
message(CHECK_START "Checking C standard library")
78+
function(_php_standard_library_get_code result)
79+
string(
80+
CONCAT
81+
${result}
82+
"/* Define to 1 when using musl libc. */\n"
83+
"#cmakedefine __MUSL__ 1\n"
84+
)
85+
86+
if(PHP_C_STANDARD_LIBRARY STREQUAL "musl")
87+
set(__MUSL__ TRUE)
88+
else()
89+
set(__MUSL__ FALSE)
90+
endif()
91+
92+
string(CONFIGURE "${${result}}" ${result} @ONLY)
93+
94+
return(PROPAGATE ${result})
95+
endfunction()
96+
97+
function(_php_standard_library_check)
98+
unset(PHP_C_STANDARD_LIBRARY)
99+
unset(PHP_C_STANDARD_LIBRARY CACHE)
100+
101+
# The MS C runtime library (CRT).
102+
if(MSVC)
103+
set(PHP_C_STANDARD_LIBRARY "mscrt")
104+
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
105+
check_symbol_exists(_MSC_VER stdio.h PHP_C_STANDARD_LIBRARY)
106+
endif()
107+
if(PHP_C_STANDARD_LIBRARY)
108+
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "mscrt")
109+
return()
110+
endif()
111+
112+
unset(PHP_C_STANDARD_LIBRARY CACHE)
113+
114+
# The uClibc and its maintained fork uClibc-ng behave like minimalistic GNU C
115+
# library but have differences. They can be determined by the __UCLIBC__
116+
# symbol and must be checked first because they also define the __GLIBC__
117+
# symbol.
118+
check_symbol_exists(__UCLIBC__ features.h PHP_C_STANDARD_LIBRARY)
119+
if(PHP_C_STANDARD_LIBRARY)
120+
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "uclibc")
121+
return()
122+
endif()
123+
124+
unset(PHP_C_STANDARD_LIBRARY CACHE)
125+
126+
# The diet libc.
127+
check_symbol_exists(__dietlibc__ features.h PHP_C_STANDARD_LIBRARY)
128+
if(PHP_C_STANDARD_LIBRARY)
129+
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "dietlibc")
130+
return()
131+
endif()
132+
133+
unset(PHP_C_STANDARD_LIBRARY CACHE)
134+
135+
# The Cosmopolitan Libc.
136+
check_symbol_exists(__COSMOPOLITAN__ "" PHP_C_STANDARD_LIBRARY)
137+
if(PHP_C_STANDARD_LIBRARY)
138+
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "cosmopolitan")
139+
return()
140+
endif()
141+
142+
unset(PHP_C_STANDARD_LIBRARY CACHE)
143+
144+
# The GNU C standard library has __GLIBC__ and __GLIBC_MINOR__ symbols since
145+
# the very early version 2.0.
146+
check_symbol_exists(__GLIBC__ features.h PHP_C_STANDARD_LIBRARY)
147+
if(PHP_C_STANDARD_LIBRARY)
148+
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "glibc")
149+
return()
150+
endif()
151+
152+
unset(PHP_C_STANDARD_LIBRARY CACHE)
153+
154+
# The LLVM libc.
155+
check_symbol_exists(__LLVM_LIBC__ features.h PHP_C_STANDARD_LIBRARY)
156+
if(PHP_C_STANDARD_LIBRARY)
157+
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "llvm")
158+
return()
159+
endif()
160+
161+
unset(PHP_C_STANDARD_LIBRARY CACHE)
162+
163+
# The musl libc doesn't advertise itself with symbols, so it must be
164+
# determined heuristically.
165+
check_symbol_exists(__DEFINED_va_list stdarg.h PHP_C_STANDARD_LIBRARY)
166+
if(PHP_C_STANDARD_LIBRARY)
167+
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "musl")
168+
return()
169+
endif()
170+
171+
unset(PHP_C_STANDARD_LIBRARY CACHE)
50172

51-
# The MS C runtime library (CRT).
52-
if(MSVC)
53-
set(_PHP_C_STANDARD_LIBRARY_MSCRT TRUE)
54-
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
173+
# Otherwise, try determining musl libc with ldd.
174+
execute_process(
175+
COMMAND ldd --version
176+
OUTPUT_VARIABLE version
177+
ERROR_QUIET
178+
OUTPUT_STRIP_TRAILING_WHITESPACE
179+
)
180+
181+
if(version MATCHES ".*musl libc.*")
182+
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "musl")
183+
return()
184+
endif()
185+
186+
set(PHP_C_STANDARD_LIBRARY "" CACHE INTERNAL "")
187+
endfunction()
188+
189+
function(_php_standard_library)
190+
# Skip in consecutive runs.
191+
if(DEFINED PHP_C_STANDARD_LIBRARY)
192+
return()
193+
endif()
194+
195+
message(CHECK_START "Checking C standard library")
55196
cmake_push_check_state(RESET)
56197
set(CMAKE_REQUIRED_QUIET TRUE)
57-
check_symbol_exists(_MSC_VER stdio.h _PHP_C_STANDARD_LIBRARY_MSCRT)
198+
_php_standard_library_check()
58199
cmake_pop_check_state()
59-
endif()
60-
if(_PHP_C_STANDARD_LIBRARY_MSCRT)
61-
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "mscrt")
62-
message(CHECK_PASS "MS C runtime library (CRT)")
63-
return()
64-
endif()
65-
66-
# The uClibc and its maintained fork uClibc-ng behave like minimalistic GNU C
67-
# library but have differences. They can be determined by the __UCLIBC__ symbol
68-
# and must be checked first because they also define the __GLIBC__ symbol.
69-
cmake_push_check_state(RESET)
70-
set(CMAKE_REQUIRED_QUIET TRUE)
71-
check_symbol_exists(__UCLIBC__ features.h _PHP_C_STANDARD_LIBRARY_UCLIBC)
72-
cmake_pop_check_state()
73-
if(_PHP_C_STANDARD_LIBRARY_UCLIBC)
74-
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "uclibc")
75-
message(CHECK_PASS "uClibc")
76-
return()
77-
endif()
78-
79-
# The diet libc.
80-
cmake_push_check_state(RESET)
81-
set(CMAKE_REQUIRED_QUIET TRUE)
82-
check_symbol_exists(__dietlibc__ features.h _PHP_C_STANDARD_LIBRARY_DIETLIBC)
83-
cmake_pop_check_state()
84-
if(_PHP_C_STANDARD_LIBRARY_DIETLIBC)
85-
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "dietlibc")
86-
message(CHECK_PASS "diet libc")
87-
return()
88-
endif()
89-
90-
# The Cosmopolitan Libc.
91-
cmake_push_check_state(RESET)
92-
set(CMAKE_REQUIRED_QUIET TRUE)
93-
check_symbol_exists(__COSMOPOLITAN__ "" _PHP_C_STANDARD_LIBRARY_COSMOPOLITAN)
94-
cmake_pop_check_state()
95-
if(_PHP_C_STANDARD_LIBRARY_COSMOPOLITAN)
96-
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "cosmopolitan")
97-
message(CHECK_PASS "Cosmopolitan Libc")
98-
return()
99-
endif()
100-
101-
# The GNU C standard library has __GLIBC__ and __GLIBC_MINOR__ symbols since the
102-
# very early version 2.0.
103-
cmake_push_check_state(RESET)
104-
set(CMAKE_REQUIRED_QUIET TRUE)
105-
check_symbol_exists(__GLIBC__ features.h _PHP_C_STANDARD_LIBRARY_GLIBC)
106-
cmake_pop_check_state()
107-
if(_PHP_C_STANDARD_LIBRARY_GLIBC)
108-
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "glibc")
109-
message(CHECK_PASS "GNU C (glibc)")
110-
return()
111-
endif()
112-
113-
# The LLVM libc.
114-
cmake_push_check_state(RESET)
115-
set(CMAKE_REQUIRED_QUIET TRUE)
116-
check_symbol_exists(__LLVM_LIBC__ features.h _PHP_C_STANDARD_LIBRARY_LLVM)
117-
cmake_pop_check_state()
118-
if(_PHP_C_STANDARD_LIBRARY_LLVM)
119-
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "llvm")
120-
message(CHECK_PASS "LLVM libc")
121-
return()
122-
endif()
123-
124-
# The musl libc doesn't advertise itself with symbols, so it must be determined
125-
# heuristically.
126-
cmake_push_check_state(RESET)
127-
set(CMAKE_REQUIRED_QUIET TRUE)
128-
check_symbol_exists(__DEFINED_va_list stdarg.h _PHP_C_STANDARD_LIBRARY_MUSL)
129-
cmake_pop_check_state()
130-
if(_PHP_C_STANDARD_LIBRARY_MUSL)
131-
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "musl")
132-
else()
133-
# Otherwise, try determining musl libc with ldd.
134-
block()
135-
execute_process(
136-
COMMAND ldd --version
137-
OUTPUT_VARIABLE version
138-
ERROR_QUIET
139-
OUTPUT_STRIP_TRAILING_WHITESPACE
140-
)
141-
142-
if(version MATCHES ".*musl libc.*")
143-
set_property(CACHE PHP_C_STANDARD_LIBRARY PROPERTY VALUE "musl")
144-
endif()
145-
endblock()
146-
endif()
147-
if(PHP_C_STANDARD_LIBRARY STREQUAL "musl")
148-
set(__MUSL__ TRUE CACHE INTERNAL "Whether the C standard library is musl.")
149-
message(CHECK_PASS "musl")
150-
return()
151-
endif()
152200

153-
# Instead of an "unknown", output a common "libc" result.
154-
message(CHECK_FAIL "libc")
201+
if(PHP_C_STANDARD_LIBRARY STREQUAL "mscrt")
202+
message(CHECK_PASS "MS C runtime library (CRT)")
203+
elseif(PHP_C_STANDARD_LIBRARY STREQUAL "uclibc")
204+
message(CHECK_PASS "uClibc")
205+
elseif(PHP_C_STANDARD_LIBRARY STREQUAL "dietlibc")
206+
message(CHECK_PASS "diet libc")
207+
elseif(PHP_C_STANDARD_LIBRARY STREQUAL "cosmopolitan")
208+
message(CHECK_PASS "Cosmopolitan Libc")
209+
elseif(PHP_C_STANDARD_LIBRARY STREQUAL "glibc")
210+
message(CHECK_PASS "GNU C (glibc)")
211+
elseif(PHP_C_STANDARD_LIBRARY STREQUAL "llvm")
212+
message(CHECK_PASS "LLVM libc")
213+
elseif(PHP_C_STANDARD_LIBRARY STREQUAL "musl")
214+
message(CHECK_PASS "musl libc")
215+
else()
216+
# Instead of an "unknown", output a common "libc" result message.
217+
message(CHECK_FAIL "libc")
218+
endif()
219+
220+
set_property(
221+
CACHE PHP_C_STANDARD_LIBRARY
222+
PROPERTY HELPSTRING "The C standard library."
223+
)
224+
endfunction()
225+
226+
_php_standard_library()
227+
_php_standard_library_get_code(PHP_C_STANDARD_LIBRARY_CODE)

cmake/ext/gettext/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ if(TARGET Intl::Intl)
127127
# Create a symbolic link when intl is built into musl C library. The gettext
128128
# functions there ignore the codeset suffix on directories like 'en_US.UTF-8';
129129
# instead they look only in 'en_US'.
130+
include(PHP/StandardLibrary)
130131
if(Intl_IS_BUILT_IN AND PHP_C_STANDARD_LIBRARY STREQUAL "musl")
131132
message(STATUS "Patching tests: symlinking en_US.UTF-8 messages")
132133
file(

cmake/ext/iconv/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ if(TARGET Iconv::Iconv)
199199
endif()
200200

201201
if(NOT PHP_ICONV_IMPL AND Iconv_IS_BUILT_IN)
202+
include(PHP/StandardLibrary)
202203
message(CHECK_PASS "built in C library ${PHP_C_STANDARD_LIBRARY}")
203204
elseif(NOT PHP_ICONV_IMPL)
204205
message(CHECK_FAIL "not found, unknown")

cmake/ext/posix/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ set(HAVE_MKNOD ${PHP_EXT_POSIX_HAVE_MKNOD})
129129

130130
# Skip pathconf and fpathconf check on musl libc due to limited implementation
131131
# (first argument is not validated and has different error).
132+
include(PHP/StandardLibrary)
132133
if(NOT PHP_C_STANDARD_LIBRARY STREQUAL "musl")
133134
check_symbol_exists(pathconf unistd.h PHP_EXT_POSIX_HAVE_PATHCONF)
134135
set(HAVE_PATHCONF ${PHP_EXT_POSIX_HAVE_PATHCONF})

cmake/main/cmake/php_config.h.in

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -647,8 +647,7 @@
647647
/* Define to 1 if thread safety (ZTS) is enabled. */
648648
#cmakedefine ZTS 1
649649

650-
/* Define to 1 when using musl libc. */
651-
#cmakedefine __MUSL__ 1
650+
@PHP_C_STANDARD_LIBRARY_CODE@
652651

653652
/* Define to '__inline__' or '__inline' if that's what the C compiler
654653
calls it, or to nothing if 'inline' is not supported under any name. */

0 commit comments

Comments
 (0)