Understanding PHP Extension Paths: no-debug-non-zts Directory Structure and Best Practices for Custom Installation


7 views

When working with PHP extensions, you'll frequently encounter paths containing no-debug-non-zts-20090626 or similar timestamps. This directory name actually conveys three critical pieces of information about your PHP build:

  • no-debug: Indicates this PHP build was compiled without debugging symbols
  • non-zts: Means this is a non-thread-safe (NTS) build of PHP
  • 20090626: Represents the API version number (format: YYYYMMDD)

The timestamp portion is particularly important as it must match your PHP binary's internal API version. You can verify this using:

php -i | grep "PHP Extension"

For development environments, I typically recommend one of these approaches:

Option 1: Using the Default Extension Directory

Simply set in php.ini:

extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626"

Then load extensions with:

extension=memcached.so
extension=xdebug.so

Option 2: Custom Extension Directory

For more control during compilation:

./configure --prefix=/usr/local/php/extensions \
            --with-php-config=/usr/local/php/bin/php-config
make && sudo make install

Then configure php.ini:

extension_dir = "/usr/local/php/extensions/lib/php/extensions/no-debug-non-zts-20090626"

The main risk occurs when:

  1. Upgrading PHP to a new API version
  2. Switching between thread-safe and non-thread-safe builds

To check compatibility before installation:

php -i | grep "Thread Safety"
php -i | grep "Debug Build"
php -i | grep "PHP Extension"

Here's a complete workflow for memcached with custom directory:

wget https://pecl.php.net/get/memcached-3.2.0.tgz
tar -xzf memcached-3.2.0.tgz
cd memcached-3.2.0
phpize
./configure --prefix=/custom/path \
            --with-libmemcached-dir=/usr/local \
            --with-php-config=/usr/local/php/bin/php-config
make
sudo make install

Then verify the correct installation path was used:

find / -name "memcached.so" 2>/dev/null

For production systems, consider this bash script to handle directory verification:

#!/bin/bash
EXT_DIR=$(php -r "echo ini_get('extension_dir');")
API_VERSION=$(php -r "echo PHP_ZEND_EXTENSION_API_NO;")
EXPECTED_DIR="no-debug-non-zts-${API_VERSION}"

if [[ "$EXT_DIR" != *"$EXPECTED_DIR"* ]]; then
  echo "Warning: Extension directory mismatch!"
  echo "Current: $EXT_DIR"
  echo "Expected to contain: $EXPECTED_DIR"
  exit 1
fi

When compiling PHP extensions like memcached or xdebug, you'll notice they get installed in directories named like no-debug-non-zts-20090626. Let's break down what this means:

/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626
|-- memcached.so
|-- xdebug.so

This naming convention follows this pattern:

  • no-debug: The extension was compiled without debug symbols
  • non-zts: Non-Thread Safe (ZTS stands for Zend Thread Safety)
  • 20090626: The API version number (from PHP 5.3.0 release)

You have two main approaches for managing extensions:

Option 1: Using the Default Directory

// In php.ini
extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626"
extension=memcached.so
extension=xdebug.so

Option 2: Custom Extension Directory

When compiling:

./configure --prefix=/usr/local/php/extensions
make
make install

Then in php.ini:

extension_dir = "/usr/local/php/extensions"
extension=memcached.so

Yes, there can be risks of extensions ending up in different directories when:

  • You switch PHP versions (changes API number)
  • You compile with different flags (debug vs non-debug)
  • Thread safety mode changes (ZTS vs non-ZTS)

To check your current PHP's expected extension directory:

php -i | grep extension_dir
php -i | grep "PHP Extension" | grep "API"

For more robust extension management, consider this bash script:

#!/bin/bash
PHP_API=$(php -i | grep "PHP Extension" | grep "API" | cut -d " " -f 3)
EXT_DIR="/usr/local/php/lib/php/extensions/no-debug-non-zts-${PHP_API}"

# Ensure directory exists
mkdir -p $EXT_DIR

# Compile and install extension
./configure --with-php-config=/usr/local/php/bin/php-config \
            --prefix=/usr/local/php \
            --libdir=$EXT_DIR
make
make install

This ensures your extensions always land in the correct directory matching your PHP version's requirements.