Skip to content

Commit

Permalink
Refactor fopencookie check
Browse files Browse the repository at this point in the history
- compiler warnings fixed
- comments updated and rechecked across glibc versions
- new module for determining the C standard library
  • Loading branch information
petk committed May 18, 2024
1 parent f65d0c3 commit a889d2e
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 22 deletions.
2 changes: 1 addition & 1 deletion cmake/cmake/ConfigureChecks.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ endif()
if(
(
NOT CMAKE_SYSTEM_NAME MATCHES "^(Android|FreeBSD|OpenBSD)$"
AND NOT PHP_STD_LIBRARY MATCHES "^(musl|uclibc)$"
AND NOT PHP_C_STANDARD_LIBRARY MATCHES "^(musl|uclibc)$"
) OR (
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD"
AND CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL 12
Expand Down
14 changes: 1 addition & 13 deletions cmake/cmake/Platform.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,7 @@ set(
include(GNUInstallDirs)

# Detect C standard library implementation.
# TODO: Fix this better.
execute_process(
COMMAND ldd --version
OUTPUT_VARIABLE _php_ldd_version
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(_php_ldd_version MATCHES ".*musl libc.*")
set(__MUSL__ 1 CACHE INTERNAL "Whether musl libc is used")
set(PHP_STD_LIBRARY "musl")
elseif(_php_ldd_version MATCHES ".*uclibc.*")
set(PHP_STD_LIBRARY "uclibc")
endif()
include(PHP/StandardLibrary)

# See https://bugs.php.net/28605.
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^alpha")
Expand Down
34 changes: 27 additions & 7 deletions cmake/cmake/modules/PHP/CheckFopencookie.cmake
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
#[=============================================================================[
Check if fopencookie() is working as expected.
Check if fopencookie() works as expected.
Module first checks if fopencookie() and type cookie_io_functions_t are
available. Then it checks whether the fopencookie seeker uses type off64_t.
Since off64_t is non-standard and obsolescent, the standard off_t type can be
used on both 64-bit and 32-bit systems, where the _FILE_OFFSET_BITS=64 can make
it behave like off64_t on 32-bit. Since code is in the transition process to use
off_t only, check is left here when using glibc.
Cache variables:
HAVE_FOPENCOOKIE
Whether fopencookie() and cookie_io_functions_t are available.
COOKIE_SEEKER_USES_OFF64_T
Whether a newer seeker definition for fopencookie() is available.
Whether fopencookie seeker uses the off64_t type.
]=============================================================================]#

include_guard(GLOBAL)
Expand All @@ -25,23 +32,30 @@ if(NOT _have_fopencookie)
return()
endif()

# glibcs (since 2.1.2?) have a type called cookie_io_functions_t.
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
set(CMAKE_EXTRA_INCLUDE_FILES "stdio.h")
check_type_size("cookie_io_functions_t" FOPENCOOKIE)
cmake_pop_check_state()

# Newer glibcs have a different seeker definition.
if(NOT HAVE_FOPENCOOKIE)
return()
endif()

# GNU C library can have a different seeker definition using off64_t.
message(
CHECK_START
"Checking whether newer fopencookie seeker definition is available"
"Checking whether fopencookie seeker uses off64_t"
)

if(CMAKE_CROSSCOMPILING AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
if(
CMAKE_CROSSCOMPILING
AND CMAKE_SYSTEM_NAME STREQUAL "Linux"
AND PHP_C_STANDARD_LIBRARY STREQUAL "glibc"
)
set(
COOKIE_SEEKER_USES_OFF64_T 1
CACHE INTERNAL "Whether newer fopencookie seeker definition is available"
CACHE INTERNAL "Whether fopencookie seeker uses off64_t"
)
else()
cmake_push_check_state(RESET)
Expand All @@ -55,19 +69,25 @@ else()
};

ssize_t reader(void *cookie, char *buffer, size_t size) {
(void)cookie;
(void)buffer;
return size;
}

ssize_t writer(void *cookie, const char *buffer, size_t size) {
(void)cookie;
(void)buffer;
return size;
}

int closer(void *cookie) {
(void)cookie;
return 0;
}

int seeker(void *cookie, off64_t *position, int whence) {
((struct cookiedata*)cookie)->pos = *position;
(void)whence;
return 0;
}

Expand Down
76 changes: 76 additions & 0 deletions cmake/cmake/modules/PHP/StandardLibrary.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#[=============================================================================[
Determine C standard library that will be used for the build.
Result variables:
PHP_C_STANDARD_LIBRARY
Lowercase name of the C standard library:
- glibc
- musl
- uclibc
Cache variables:
__MUSL__
]=============================================================================]#

include_guard(GLOBAL)

include(CheckSymbolExists)
include(CMakePushCheckState)

message(CHECK_START "Checking C standard library")

# Initial uClibc and its maintained fork uClibc-ng behave like minimalistic GNU
# C but aren't. These can be determined by the __UCLIBC__ symbol. They must be
# checked first because they also define the __GLIBC__ symbol.
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_QUIET TRUE)
check_symbol_exists(__UCLIBC__ features.h _PHP_C_STANDARD_LIBRARY_UCLIBC)
cmake_pop_check_state()
if(_PHP_C_STANDARD_LIBRARY_UCLIBC)
set(PHP_C_STANDARD_LIBRARY "uclibc")
message(CHECK_PASS "uClibc")
return()
endif()

# GNU C standard library has __GLIBC__ and __GLIBC_MINOR__ symbols synce the
# very early versions 2.0.
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_QUIET TRUE)
check_symbol_exists(__GLIBC__ features.h _PHP_C_STANDARD_LIBRARY_GLIBC)
cmake_pop_check_state()
if(_PHP_C_STANDARD_LIBRARY_GLIBC)
set(PHP_C_STANDARD_LIBRARY "glibc")
message(CHECK_PASS "GNU C (glibc)")
return()
endif()

# The musl libc doesn't advertise itself specifically via symbols, so it must
# be guessed.
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_QUIET TRUE)
check_symbol_exists(__DEFINED_va_list stdarg.h _PHP_C_STANDARD_LIBRARY_MUSL)
cmake_pop_check_state()
if(_PHP_C_STANDARD_LIBRARY_MUSL)
set(PHP_C_STANDARD_LIBRARY "musl")
message(CHECK_PASS "musl")
return()
endif()

# Otherwise, try using ldd.
block(PROPAGATE PHP_C_STANDARD_LIBRARY)
execute_process(
COMMAND ldd --version
OUTPUT_VARIABLE version
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)

if(version MATCHES ".*musl libc.*")
set(__MUSL__ 1 CACHE INTERNAL "Whether musl libc is used")
set(PHP_C_STANDARD_LIBRARY "musl")
message(CHECK_PASS "musl")
return()
endif()
endblock()

message(CHECK_FAIL "unknown")
2 changes: 1 addition & 1 deletion cmake/ext/posix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ check_symbol_exists(mknod "sys/stat.h" HAVE_MKNOD)

# Skip pathconf and fpathconf check on musl libc due to limited implementation
# (first argument is not validated and has different error).
if(NOT PHP_STD_LIBRARY STREQUAL "musl")
if(NOT PHP_C_STANDARD_LIBRARY STREQUAL "musl")
check_symbol_exists(pathconf "unistd.h" HAVE_PATHCONF)
check_symbol_exists(fpathconf "unistd.h" HAVE_FPATHCONF)
endif()
Expand Down

0 comments on commit a889d2e

Please sign in to comment.