1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00
Files
archived-php-src/Zend/Zend.m4
Calvin Buckley 13b83a46cf Bump libtool to serial 63 from 2.5.4 (#21067)
The libtool 1.5.26 is bundled with PHP since the very early days of the
Autotools build system to ease the building process and avoid additional
dependency on the system Libtool. This updates the bundled libtool to
2.5.4 version.

Fixes and implementations:

- Fixed race conditions when building PHP in parallel ("cannot create
  .libs" warnings).
- Implements request https://bugs.php.net/70374 (Update libtool.m4)
- Fixes libtool eating -flto flags.
- Fixes GH-17310 (configure producing errors on macOS)
- Fixes GH-15946 (./configure error when building with NixOS)

Changes:
- Add a script to update autotools files.
- libtool is spread across multiple files; phpize is updated to handle
  this.
- Remove outdated hacks, i.e. for `ar`.
- Remove documentation references to external libtool, as we vendor it.
- `--with-pic` is now `--enable-pic`. Error out on the old flag.
- On macOS linker now uses -undefined dynamic_lookup flag for shared
  extensions and shared embed SAPI (libphp) instead of older
  '-undefined suppress -flat_namespace' combination.

Co-authored-by: Peter Kokot <peterkokot@gmail.com>
2026-03-11 12:37:56 -03:00

576 lines
16 KiB
Plaintext

dnl This file contains Zend specific autoconf macros.
dnl
dnl ZEND_CHECK_FLOAT_PRECISION
dnl
dnl x87 floating point internal precision control checks
dnl See: https://wiki.php.net/rfc/rounding
dnl
AC_DEFUN([ZEND_CHECK_FLOAT_PRECISION], [dnl
AC_CACHE_CHECK([for usable _FPU_SETCW],
[php_cv_have__fpu_setcw],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <fpu_control.h>], [dnl
fpu_control_t fpu_oldcw, fpu_cw;
volatile double result;
double a = 2877.0;
volatile double b = 1000000.0;
_FPU_GETCW(fpu_oldcw);
fpu_cw = (fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE;
_FPU_SETCW(fpu_cw);
result = a / b;
_FPU_SETCW(fpu_oldcw);
(void)result;
])],
[php_cv_have__fpu_setcw=yes],
[php_cv_have__fpu_setcw=no])])
AS_VAR_IF([php_cv_have__fpu_setcw], [yes],
[AC_DEFINE([HAVE__FPU_SETCW], [1],
[Define to 1 if _FPU_SETCW is present and usable.])])
AC_CACHE_CHECK([for usable fpsetprec],
[php_cv_have_fpsetprec],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <machine/ieeefp.h>], [dnl
fp_prec_t fpu_oldprec;
volatile double result;
double a = 2877.0;
volatile double b = 1000000.0;
fpu_oldprec = fpgetprec();
fpsetprec(FP_PD);
result = a / b;
fpsetprec(fpu_oldprec);
(void)result;
])],
[php_cv_have_fpsetprec=yes],
[php_cv_have_fpsetprec=no])])
AS_VAR_IF([php_cv_have_fpsetprec], [yes],
[AC_DEFINE([HAVE_FPSETPREC], [1],
[Define to 1 if fpsetprec is present and usable.])])
AC_CACHE_CHECK([for usable _controlfp],
[php_cv_have__controlfp],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <float.h>], [dnl
unsigned int fpu_oldcw;
volatile double result;
double a = 2877.0;
volatile double b = 1000000.0;
fpu_oldcw = _controlfp(0, 0);
_controlfp(_PC_53, _MCW_PC);
result = a / b;
_controlfp(fpu_oldcw, _MCW_PC);
(void)result;
])],
[php_cv_have__controlfp=yes],
[php_cv_have__controlfp=no])])
AS_VAR_IF([php_cv_have__controlfp], [yes],
[AC_DEFINE([HAVE__CONTROLFP], [1],
[Define to 1 if _controlfp is present and usable.])])
AC_CACHE_CHECK([for usable _controlfp_s],
[php_cv_have__controlfp_s],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <float.h>], [dnl
unsigned int fpu_oldcw, fpu_cw;
volatile double result;
double a = 2877.0;
volatile double b = 1000000.0;
_controlfp_s(&fpu_cw, 0, 0);
fpu_oldcw = fpu_cw;
_controlfp_s(&fpu_cw, _PC_53, _MCW_PC);
result = a / b;
_controlfp_s(&fpu_cw, fpu_oldcw, _MCW_PC);
(void)result;
])],
[php_cv_have__controlfp_s=yes],
[php_cv_have__controlfp_s=no])])
AS_VAR_IF([php_cv_have__controlfp_s], [yes],
[AC_DEFINE([HAVE__CONTROLFP_S], [1],
[Define to 1 if _controlfp_s is present and usable.])])
AC_CACHE_CHECK([whether FPU control word can be manipulated by inline assembler],
[php_cv_have_fpu_inline_asm_x86],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([], [dnl
unsigned int oldcw, cw;
volatile double result;
double a = 2877.0;
volatile double b = 1000000.0;
__asm__ __volatile__ ("fnstcw %0" : "=m" (*&oldcw));
cw = (oldcw & ~0x0 & ~0x300) | 0x200;
__asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
result = a / b;
__asm__ __volatile__ ("fldcw %0" : : "m" (*&oldcw));
(void)result;
])],
[php_cv_have_fpu_inline_asm_x86=yes],
[php_cv_have_fpu_inline_asm_x86=no])])
AS_VAR_IF([php_cv_have_fpu_inline_asm_x86], [yes],
[AC_DEFINE([HAVE_FPU_INLINE_ASM_X86], [1],
[Define to 1 if FPU control word can be manipulated by inline assembler.])])
])
dnl
dnl ZEND_DLSYM_CHECK
dnl
dnl Ugly hack to check if dlsym() requires a leading underscore in symbol name.
dnl
AC_DEFUN([ZEND_DLSYM_CHECK], [dnl
AC_MSG_CHECKING([whether dlsym() requires a leading underscore in symbol names])
_LT_TRY_DLOPEN_SELF([AC_MSG_RESULT([no])], [
AC_MSG_RESULT([yes])
AC_DEFINE([DLSYM_NEEDS_UNDERSCORE], [1],
[Define to 1 if 'dlsym()' requires a leading underscore in symbol names.])
], [AC_MSG_RESULT([no])], [])
])
dnl
dnl ZEND_INIT
dnl
dnl Configure checks and initialization specific for the Zend engine library.
dnl
AC_DEFUN([ZEND_INIT], [dnl
AC_REQUIRE([AC_PROG_CC])
AC_CHECK_HEADERS(m4_normalize([
cpuid.h
libproc.h
]))
dnl Check for library functions.
AC_CHECK_FUNCS(m4_normalize([
getpid
gettid
kill
mremap
pthread_attr_get_np
pthread_attr_getstack
pthread_get_stackaddr_np
pthread_getattr_np
pthread_stackseg_np
strnlen
]))
AC_CHECK_DECL([clock_gettime_nsec_np],
[AC_DEFINE([HAVE_CLOCK_GETTIME_NSEC_NP], [1],
[Define to 1 if you have the declaration of 'clock_gettime_nsec_np'.])],,
[#include <time.h>])
dnl
dnl Check for sigsetjmp. If sigsetjmp is defined as a macro, use AC_CHECK_DECL
dnl as a fallback since AC_CHECK_FUNC cannot detect macros.
dnl
AC_CHECK_FUNC([sigsetjmp],,
[AC_CHECK_DECL([sigsetjmp],,
[AC_MSG_FAILURE([Required sigsetjmp not found.])],
[#include <setjmp.h>])])
ZEND_CHECK_STACK_DIRECTION
ZEND_CHECK_FLOAT_PRECISION
ZEND_DLSYM_CHECK
ZEND_CHECK_GLOBAL_REGISTER_VARIABLES
ZEND_CHECK_PRESERVE_NONE
ZEND_CHECK_CPUID_COUNT
AC_MSG_CHECKING([whether to enable thread safety])
AC_MSG_RESULT([$ZEND_ZTS])
AS_VAR_IF([ZEND_ZTS], [yes], [
AC_DEFINE([ZTS], [1], [Define to 1 if thread safety (ZTS) is enabled.])
AS_VAR_APPEND([CFLAGS], [" -DZTS"])
])
AC_MSG_CHECKING([whether to enable Zend debugging])
AC_MSG_RESULT([$ZEND_DEBUG])
AH_TEMPLATE([ZEND_DEBUG],
[Define to 1 if debugging is enabled, and to 0 if not.])
AS_VAR_IF([ZEND_DEBUG], [yes], [
AC_DEFINE([ZEND_DEBUG], [1])
echo " $CFLAGS" | grep ' -g' >/dev/null || CFLAGS="$CFLAGS -g"
], [AC_DEFINE([ZEND_DEBUG], [0])])
AS_VAR_IF([GCC], [yes],
[CFLAGS="-Wall -Wextra -Wno-unused-parameter -Wno-sign-compare $CFLAGS"])
dnl Check if compiler supports -Wno-clobbered (only GCC).
AX_CHECK_COMPILE_FLAG([-Wno-clobbered],
[CFLAGS="-Wno-clobbered $CFLAGS"])
dnl Check for support for implicit fallthrough level 1, also add after previous
dnl CFLAGS as level 3 is enabled in -Wextra.
AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough=1],
[CFLAGS="$CFLAGS -Wimplicit-fallthrough=1"])
AX_CHECK_COMPILE_FLAG([-Wduplicated-cond],
[CFLAGS="-Wduplicated-cond $CFLAGS"])
AX_CHECK_COMPILE_FLAG([-Wlogical-op],
[CFLAGS="-Wlogical-op $CFLAGS"])
AX_CHECK_COMPILE_FLAG([-Wformat-truncation],
[CFLAGS="-Wformat-truncation $CFLAGS"])
AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes],
[CFLAGS="-Wstrict-prototypes $CFLAGS"])
AX_CHECK_COMPILE_FLAG([-fno-common],
[CFLAGS="-fno-common $CFLAGS"])
ZEND_CHECK_ALIGNMENT
ZEND_CHECK_SIGNALS
ZEND_CHECK_MAX_EXECUTION_TIMERS
])
dnl
dnl ZEND_CHECK_STACK_DIRECTION
dnl
dnl Check whether the stack grows downwards, assumes contiguous stack.
dnl
AC_DEFUN([ZEND_CHECK_STACK_DIRECTION],
[AC_CACHE_CHECK([whether the stack grows downwards],
[php_cv_have_stack_limit],
[AC_RUN_IFELSE([AC_LANG_SOURCE([dnl
#include <stdint.h>
#ifdef __has_builtin
# if __has_builtin(__builtin_frame_address)
# define builtin_frame_address __builtin_frame_address(0)
# endif
#endif
int (*volatile f)(uintptr_t);
int stack_grows_downwards(uintptr_t arg) {
#ifdef builtin_frame_address
uintptr_t addr = (uintptr_t)builtin_frame_address;
#else
int local;
uintptr_t addr = (uintptr_t)&local;
#endif
return addr < arg;
}
int main(void) {
#ifdef builtin_frame_address
uintptr_t addr = (uintptr_t)builtin_frame_address;
#else
int local;
uintptr_t addr = (uintptr_t)&local;
#endif
f = stack_grows_downwards;
return f(addr) ? 0 : 1;
}])],
[php_cv_have_stack_limit=yes],
[php_cv_have_stack_limit=no],
[php_cv_have_stack_limit=no])])
AS_VAR_IF([php_cv_have_stack_limit], [yes],
[AC_DEFINE([ZEND_CHECK_STACK_LIMIT], [1],
[Define to 1 if checking the stack limit is supported.])])
])
dnl
dnl ZEND_CHECK_GLOBAL_REGISTER_VARIABLES
dnl
dnl Check whether to enable global register variables if supported.
dnl
AC_DEFUN([ZEND_CHECK_GLOBAL_REGISTER_VARIABLES], [dnl
AC_ARG_ENABLE([gcc-global-regs],
[AS_HELP_STRING([--disable-gcc-global-regs],
[Disable GCC global register variables])],
[ZEND_GCC_GLOBAL_REGS=$enableval],
[ZEND_GCC_GLOBAL_REGS=yes])
AS_VAR_IF([ZEND_GCC_GLOBAL_REGS], [no],,
[AC_CACHE_CHECK([whether system supports global register variables],
[php_cv_have_global_register_vars],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#if defined(__GNUC__)
# define ZEND_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#else
# define ZEND_GCC_VERSION 0
#endif
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
# define ZEND_VM_FP_GLOBAL_REG "%esi"
# define ZEND_VM_IP_GLOBAL_REG "%edi"
#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
# define ZEND_VM_FP_GLOBAL_REG "%r14"
# define ZEND_VM_IP_GLOBAL_REG "%r15"
#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
# define ZEND_VM_FP_GLOBAL_REG "r28"
# define ZEND_VM_IP_GLOBAL_REG "r29"
#elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
# define ZEND_VM_FP_GLOBAL_REG "r28"
# define ZEND_VM_IP_GLOBAL_REG "r29"
#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__aarch64__)
# define ZEND_VM_FP_GLOBAL_REG "x27"
# define ZEND_VM_IP_GLOBAL_REG "x28"
#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__riscv) && __riscv_xlen == 64
# define ZEND_VM_FP_GLOBAL_REG "x18"
# define ZEND_VM_IP_GLOBAL_REG "x19"
#else
# error "global register variables are not supported"
#endif
typedef int (*opcode_handler_t)(void);
register void *FP __asm__(ZEND_VM_FP_GLOBAL_REG);
register const opcode_handler_t *IP __asm__(ZEND_VM_IP_GLOBAL_REG);
int emu(const opcode_handler_t *ip, void *fp) {
const opcode_handler_t *orig_ip = IP;
void *orig_fp = FP;
IP = ip;
FP = fp;
while ((*ip)());
FP = orig_fp;
IP = orig_ip;
}], [])],
[php_cv_have_global_register_vars=yes],
[php_cv_have_global_register_vars=no])
])
AS_VAR_IF([php_cv_have_global_register_vars], [yes],
[AC_DEFINE([HAVE_GCC_GLOBAL_REGS], [1],
[Define to 1 if the target system has support for global register
variables.])],
[ZEND_GCC_GLOBAL_REGS=no])
])
AC_MSG_CHECKING([whether to enable global register variables support])
AC_MSG_RESULT([$ZEND_GCC_GLOBAL_REGS])
])
dnl
dnl ZEND_CHECK_CPUID_COUNT
dnl
dnl Check whether __cpuid_count is available.
dnl
AC_DEFUN([ZEND_CHECK_CPUID_COUNT],
[AC_CACHE_CHECK([whether __cpuid_count is available],
[php_cv_have___cpuid_count],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <cpuid.h>], [dnl
unsigned eax, ebx, ecx, edx;
__cpuid_count(0, 0, eax, ebx, ecx, edx);
])],
[php_cv_have___cpuid_count=yes],
[php_cv_have___cpuid_count=no])])
AS_VAR_IF([php_cv_have___cpuid_count], [yes],
[AC_DEFINE([HAVE_CPUID_COUNT], [1],
[Define to 1 if '__cpuid_count' is available.])])
])
dnl
dnl ZEND_CHECK_ALIGNMENT
dnl
dnl Test and set the alignment defines for the Zend memory manager (ZEND_MM).
dnl This also does the logarithmic test.
dnl
AC_DEFUN([ZEND_CHECK_ALIGNMENT],
[AC_CACHE_CHECK([for Zend memory manager alignment and log values],
[php_cv_align_mm],
[AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <stdio.h>
#include <stdlib.h>
typedef union _mm_align_test {
void *ptr;
double dbl;
long lng;
} mm_align_test;
#if (defined (__GNUC__) && __GNUC__ >= 2)
#define ZEND_MM_ALIGNMENT (__alignof__ (mm_align_test))
#else
#define ZEND_MM_ALIGNMENT (sizeof(mm_align_test))
#endif
int main(void)
{
size_t i = ZEND_MM_ALIGNMENT;
int zeros = 0;
FILE *fp;
while (i & ~0x1) {
zeros++;
i = i >> 1;
}
fp = fopen("conftest.zend", "w");
fprintf(fp, "(size_t)%zu (size_t)%d %d\n",
ZEND_MM_ALIGNMENT, zeros, ZEND_MM_ALIGNMENT < 4);
fclose(fp);
return 0;
}
])],
[php_cv_align_mm=$(cat conftest.zend)],
[php_cv_align_mm=failed],
[php_cv_align_mm="(size_t)8 (size_t)3 0"])])
AS_VAR_IF([php_cv_align_mm], [failed],
[AC_MSG_FAILURE([ZEND_MM alignment defines failed.])],
[zend_mm_alignment=$(echo $php_cv_align_mm | cut -d ' ' -f 1)
zend_mm_alignment_log2=$(echo $php_cv_align_mm | cut -d ' ' -f 2)
zend_mm_8byte_realign=$(echo $php_cv_align_mm | cut -d ' ' -f 3)
AC_DEFINE_UNQUOTED([ZEND_MM_ALIGNMENT],
[$zend_mm_alignment],
[Number of bytes for the ZEND_MM alignment.])
AC_DEFINE_UNQUOTED([ZEND_MM_ALIGNMENT_LOG2],
[$zend_mm_alignment_log2],
[Number of bytes for the logarithmic ZEND_MM alignment.])
AC_DEFINE_UNQUOTED([ZEND_MM_NEED_EIGHT_BYTE_REALIGNMENT],
[$zend_mm_8byte_realign],
[Define to 1 if ZEND_MM needs 8-byte realignment, and to 0 if not.])
])
])
dnl
dnl ZEND_CHECK_SIGNALS
dnl
dnl Check whether to enable Zend signal handling if supported by the system.
dnl
AC_DEFUN([ZEND_CHECK_SIGNALS], [dnl
AC_ARG_ENABLE([zend-signals],
[AS_HELP_STRING([--disable-zend-signals],
[Disable Zend signal handling])],
[ZEND_SIGNALS=$enableval],
[ZEND_SIGNALS=yes])
AC_CHECK_FUNCS([sigaction],, [ZEND_SIGNALS=no])
AS_VAR_IF([ZEND_SIGNALS], [yes],
[AC_DEFINE([ZEND_SIGNALS], [1],
[Define to 1 if Zend signal handling is supported and enabled.])
AS_VAR_APPEND([CFLAGS], [" -DZEND_SIGNALS"])])
AC_MSG_CHECKING([whether to enable Zend signal handling])
AC_MSG_RESULT([$ZEND_SIGNALS])
])
dnl
dnl ZEND_CHECK_MAX_EXECUTION_TIMERS
dnl
dnl Check whether to enable Zend max execution timers.
dnl
AC_DEFUN([ZEND_CHECK_MAX_EXECUTION_TIMERS], [dnl
AC_ARG_ENABLE([zend-max-execution-timers],
[AS_HELP_STRING([--enable-zend-max-execution-timers],
[Enable Zend max execution timers; when building with thread safety
(--enable-zts), they are automatically enabled by default based on the
system support])],
[ZEND_MAX_EXECUTION_TIMERS=$enableval],
[ZEND_MAX_EXECUTION_TIMERS=$ZEND_ZTS])
AS_CASE([$host_alias], [*linux*|*freebsd*],,
[ZEND_MAX_EXECUTION_TIMERS=no])
AS_VAR_IF([ZEND_MAX_EXECUTION_TIMERS], [yes],
[AC_SEARCH_LIBS([timer_create], [rt],,
[ZEND_MAX_EXECUTION_TIMERS=no])])
AS_VAR_IF([ZEND_MAX_EXECUTION_TIMERS], [yes],
[AC_DEFINE([ZEND_MAX_EXECUTION_TIMERS], [1],
[Define to 1 if Zend max execution timers are supported and enabled.])
AS_VAR_APPEND([CFLAGS], [" -DZEND_MAX_EXECUTION_TIMERS"])])
AC_MSG_CHECKING([whether to enable Zend max execution timers])
AC_MSG_RESULT([$ZEND_MAX_EXECUTION_TIMERS])
])
dnl
dnl ZEND_CHECK_PRESERVE_NONE
dnl
dnl Check if the preserve_none calling convention is supported and matches our
dnl expectations.
dnl
AC_DEFUN([ZEND_CHECK_PRESERVE_NONE], [dnl
AC_CACHE_CHECK([for preserve_none calling convention],
[php_cv_preserve_none],
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdio.h>
#include <stdint.h>
const char * const1 = "str1";
const char * const2 = "str2";
const char * const3 = "str3";
uint64_t key = UINT64_C(0x9d7f71d2bd296364);
uintptr_t _a = 0;
uintptr_t _b = 0;
uintptr_t __attribute__((preserve_none,noinline,used)) fun(uintptr_t a, uintptr_t b) {
_a = a;
_b = b;
return (uintptr_t)const3;
}
uintptr_t __attribute__((preserve_none)) test(void) {
uintptr_t ret;
#if defined(__x86_64__)
__asm__ __volatile__(
/* XORing to make it unlikely the value exists in any other register */
"movq %1, %%r12\n"
"xorq %3, %%r12\n"
"movq %2, %%r13\n"
"xorq %3, %%r13\n"
"xorq %%rax, %%rax\n"
#if defined(__APPLE__)
"call _fun\n"
#else
"call fun\n"
#endif
: "=a" (ret)
: "r" (const1), "r" (const2), "r" (key)
: "r12", "r13"
);
#elif defined(__aarch64__)
__asm__ __volatile__(
/* XORing to make it unlikely the value exists in any other register */
"eor x20, %1, %3\n"
"eor x21, %2, %3\n"
"eor x0, x0, x0\n"
#if defined(__APPLE__)
"bl _fun\n"
#else
"bl fun\n"
#endif
"mov %0, x0\n"
: "=r" (ret)
: "r" (const1), "r" (const2), "r" (key)
: "x0", "x21", "x22", "x30"
);
#else
# error
#endif
return ret;
}
int main(void) {
/* JIT is making the following expectations about preserve_none:
* - The registers used for integer args 1 and 2
* - The register used for a single integer return value
*
* We check these expectations here:
*/
uintptr_t ret = test();
if (_a != ((uintptr_t)const1 ^ key)) {
fprintf(stderr, "arg1 mismatch\n");
return 1;
}
if (_b != ((uintptr_t)const2 ^ key)) {
fprintf(stderr, "arg2 mismatch\n");
return 2;
}
if (ret != (uintptr_t)const3) {
fprintf(stderr, "ret mismatch\n");
return 3;
}
fprintf(stderr, "OK\n");
return 0;
}]])],
[php_cv_preserve_none=yes],
[php_cv_preserve_none=no],
[php_cv_preserve_none=no])
])
AS_VAR_IF([php_cv_preserve_none], [yes], [
AC_DEFINE([HAVE_PRESERVE_NONE], [1],
[Define to 1 if you have preserve_none support.])
])
])