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
79include(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
3051Basic usage:
3152
3253```cmake
3354# CMakeLists.txt
55+
3456include(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 ()
4271endif ()
4372
73+ include_guard (GLOBAL )
74+
4475include (CheckSymbolExists)
4576include (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)
0 commit comments