Composer path repositories install a package as a symlink, so a source
directory reached through one contributed no files at all: PHP's
RecursiveDirectoryIterator does not descend into symlinked directories
unless asked, because RecursiveIteratorIterator calls hasChildren() and
its $allowLinks argument defaults to false.
The build still reported success, and the missing classes only surfaced
at runtime as `class 'X' is undefined`.
Scan with FilesystemIterator::FOLLOW_SYMLINKS. A linked directory is an
ordinary source entry with no setting of its own; what is compiled stays
with `sources` and `ignore`.
Exclusions match the path that reached a file, the one the project wrote
and the scanner traversed. An `ignore` entry is no longer resolved to its
link target, which compared a real path against a linked one and so never
matched.
Real paths are kept for identity alone. A link is refused when it closes
the branch that reached it, so a link to one of its own ancestors cannot
recurse; files reachable through several links are reduced to one path
after exclusions have run, since deduplicating before that would drop an
allowed alias along with an excluded one.
* fix(installer): keep the embed build inside its own prefix
The libphp.so installer reuses the configure options of the PHP already on
the machine so the private build matches it feature for feature. A
distribution build records where *it* installs, though, and those paths are
absolute. On Debian and Ubuntu the options carry --mandir=/usr/share/man,
--includedir=/usr/include, --libdir, --libexecdir, --sysconfdir and
--localstatedir. Inherited unchanged, they survive the --prefix rewrite, and
`make install` tries to write into system directories:
Installing PHP CLI man page: /usr/share/man/man1/
cp: cannot create regular file '/usr/share/man/man1/#INST@3023727#': Permission denied
make: *** [Makefile:265: install-cli] Error 1
Fatal error: Unable to install libphp.so: Command failed: make install
So the build only completed for root, or inside a container where the user
owns /usr. Everyone else got a PHP compiled from scratch and then thrown
away at the last step.
Two further options escape the same way. --program-suffix=8.3 installs the
binaries as php8.3 and php-config8.3, but LibPhpInstaller::installedVersion(),
writePhpIni() and UnixPlatform::findPhpConfig() all look for the plain names,
so a build that got past `make install` still looked like it had produced
nothing. --cache-file points at the distribution's build directory
(/tmp/buildd/nonexistent/config.cache), a path that does not exist here and
whose answers were recorded for a different prefix.
Drop all of them. Autoconf derives every installation directory from --prefix
when it is absent, so the private build lands entirely under the requested
prefix: bin/php, lib/libphp.so, include/php and share/man/man1. Options that
name a *dependency* rather than a destination, such as --with-zlib=/usr and
--with-layout=GNU, are untouched; the built PHP still matches the one it was
derived from.
* fix(installer): offer an existing build before asking to make one
Running a build twice asked four questions to arrive at the answer it
already had:
The current PHP installation does not provide libphp.so: /usr
Build a private PHP embed library now? [Y/n]
PHP version [8.5.10]:
Install directory [/home/alganet/.typephp]:
PHP 8.5.10 with libphp.so already exists in /home/alganet/.typephp; use it? [Y/n]
The reuse check sat at the bottom because it needs a version and a
directory, and those were read from the prompts. But both have defaults
that are known without asking anyone: the directory this installer always
proposes, and the PHP that is running it. That is the case being answered
here, so it can be offered first.
Ask it up front. Accepting now ends the exchange at one question, and the
`--prefix` rewrite no longer has to be reasoned about at all. The later
check stays for a directory or version typed by hand, and is skipped when
the answers repeat the defaults, so the same question is never asked twice.
ensure() also fetched the release list from php.net before looking for an
existing build, so the reuse path made a network round trip to learn the
URL of an archive it was not going to download. Move the fetch next to the
install that needs it.
Nothing recorded PHP_HOME anywhere but this process, and that has not
changed: a fresh run still has to rediscover the build. Being asked once
instead of four times is the part that is worth fixing separately.
- Add project-release.yml with embedded vendor files for standalone builds
- Implement YAML include mechanism in ProjectYamlLoader with circular reference detection
- Support single file or list of files in include directive with ordered merging
- Add recursive map merging and list replacement for included configurations
- Create CompilerProjectConfigurationTest to verify release compiler embedding
- Add ProjectYamlLoaderTest with comprehensive include scenarios
- Update GitHub workflows to build standalone compiler using project-release.yml
- Document include feature usage in README files with examples
- Remove embedded-files from development project.yml to reduce initialization cost
- Add validation for absolute paths and proper error handling for missing files
- Add version field to expose extension version through Zend module entry
- Add info mapping to accept arbitrary labels and scalar values for phpinfo()
- Generate PHP_MINFO_FUNCTION to display custom extension information
- Preserve info mapping order in module's phpinfo() section
- Validate version as non-empty string without NUL bytes
- Validate info as mapping of non-empty string labels to scalar values
- Add comprehensive tests for metadata parsing and generation
- Update documentation with extension metadata configuration examples
- Add testGccOnWindowsUsesGccIncludeSyntaxForAllSourceTypes method to verify include path formatting
- Test include paths with GCC compiler on Windows for C, C++, and assembler files
- Verify that GCC uses -I flag syntax instead of /I for all source types on Windows
- Confirm proper escaping of include paths with spaces using escapeshellarg
- Add formatIncludePaths method to handle include flag formatting consistently across platforms
- Add referencedClasses array to store fully resolved class names
- Implement recordReferencedClass method to track class references
- Enhance function call parsing with static function resolution
- Add native function lookup and return type detection
- Insert type conversion for runtime call results
- Resolve extension dependencies based on internal functions and classes
- Append extension requirements to generated module header
- Update tests to validate extension dependency detection
- Add test case for runtime builtin int property assignment
- Modify polymorphic class dispatch to restore string representation
- Removed strtotime from the list of functions that use direct PHPX wrappers
- Updated test case to verify only supported datetime calls use direct wrappers
- Modified strtotime test to include absolute, relative, epoch 0 and invalid dates
- Added timezone setting and additional test cases for relative date handling
- Updated expected test output to reflect new strtotime behavior
- Adjusted assertions to check for correct persistent function calls
- Added assertion to check opcodeBuildChecked property is false
- Used reflection to access parent class properties when needed
- Removed anonymousOpcode configuration from build parameters
- Ensured proper state verification for compiler fingerprint tests
- Renamed typephp_get_method_call_cache to get_method_call_cache
- Renamed typephp_get_function_call_cache to get_function_call_cache
- Renamed typephp_get_function_resolution_cache to get_function_resolution_cache
- Updated all references in compiler base and translator classes
- Modified renderDataDeclarations to accept includeGlobals parameter
- Added renderGlobalDeclarationsForSource to handle per-source global declarations
- Updated extension generation to use new naming convention
- Adjusted test assertions to match new function names
- Support single array parameter initialization for std::array, std::vector, std::map,
std::orderedMap, std::list, and std::dict
- Implement type inference from array initializer expressions with exact type matching
- Add rectangular shape validation for std::array initializers
- Generate appropriate C++ code for value initializers using lambda expressions
- Update documentation to reflect new value initializer capabilities
- Add comprehensive tests for valid and invalid initializer scenarios
- Defer StdFunc/StdArgInfo implementation as documented in design records
- Introduce StdVector, StdMap, and StdOrderedMap parameter attributes
- Add explicit std-container contract to ArgInfo entity
- Implement parameter validation and type checking logic
- Add error handling for invalid container parameter usage
- Support container parameter contracts in function signatures
- Generate automatic type conversion at function entry points
- Add compilation tests for std container parameter contracts
- Update documentation with container parameter rules and examples
- Implement compatibility checks between child and parent classes
- Add support for container parameters in trait methods and inheritance
- Add constant initialization code separation with before/after statement handling
- Implement constant finalization logic to prevent metadata replacement during re-parsing
- Create scoped initialization blocks using do-while constructs for temporary variables
- Add codegenFinalized flag to track constant processing state
- Introduce new test case for global nested array constants initialization
- Add incremental declaration test for constant initializer preservation
- Move constant value parsing to dedicated finalizeGlobalConstantValue method
- Update translator to handle scoped constant initialization code generation
- Add getDeclarationInputFiles method to include stub files in header generation
- Modify incremental compilation to process stub files alongside regular PHP files
- Update build state tracking to handle stub files differently (no translation units)
- Add test coverage for stub declaration generation and dependency invalidation
- Implement MSVC /bigobj flag for large object format support in generated commands
- Generate wrapper callbacks for stub functions and methods bridging to native implementations
- Update source pipeline to handle native/import stub metadata in module entry
- Modify declaration header generation to include stub callback registrations
- Add comprehensive test suite for stub functionality
- Add loadPristineAst method to CompilerBase for independent AST loading
- Introduce PreparedProjectCacheTrait with conservative whole-project caching mechanism
- Implement translation unit splitting for large C++ files with splitLargeTranslationUnit
- Add preprocessing warning count tracking in CompilerDiagnosticTrait
- Enhance gen_stub.php to use cached AST when available instead of reparsing
- Improve incremental compilation checks with splitTranslationUnits validation
- Add comprehensive test coverage for AST caching, prepared project cache, and translation unit splitting
- Optimize precompiled header manager with dependency digest caching and improved invalidation
- Implement file digest memoization for faster native compilation input processing
- Add support for persistent AST cache reuse across compiler processes
- Add CompilerGeneratorFingerprintTest to verify embedded snapshot usage
- Test that compiler snapshots are stable and change with source or options
- Verify ordinary programs and extensions do not register compiler snapshots
- Add separate process attribute for accurate testing conditions
- Test incremental generator fingerprint generation and registration logic
feat(build): implement compiler build fingerprint registration
- Embed immutable source snapshot in self-hosted compiler builds
- Add fallback mechanism for executables built before metadata introduction
- Optimize performance by avoiding expensive source file hashing
- Generate compiled generator fingerprint registration during translation
- Prevent recursive fingerprinting in repeated self-hosted builds
- Register compiler build fingerprint only for binary builds with specific criteria
- Move large array-valued class constant initialization from module_init() to isolated functions
- Generate independent cacheable translation units for request-lifecycle helpers
- Add static zend_class_entry pointers with null initialization for module entry unit
- Preserve arginfo-backed class registration in extension-*.cc while splitting array constants
- Implement proper cleanup of split lifecycle sources during incremental builds
- Cache PHP SDK discovery results to avoid repeated php-config invocations
- Add comprehensive tests for class constant lifecycle splitting behavior
- Verify static class entry declarations do not expose unnecessary linkable symbols
- Add explicit response file path support to compiler backends
- Implement TYPEPHP_COMPILER_EXECUTABLE constant for compiler fingerprinting
- Add exception handling for native source project compilation
- Create dedicated extension header inclusion logic to reduce build invalidations
- Implement small task lane reservation in parallel compilation
- Add DOM extension requirement check for native project support
- Optimize symbol collection with single depth-first AST walk
- Add request array default metadata finalization
- Implement content-based rather than timestamp-based object caching
- Add link cache metadata file management
- Update incremental compilation to preserve timestamps for identical content
- Add comprehensive test coverage for response file and caching features
- Replace sequential indexing with stable ID allocation for persistent entities
- Add StableIdRegistry to maintain consistent IDs across builds
- Implement incremental compilation with dependency tracking
- Add IncrementalBuildState for tracking file dependencies and dirty propagation
- Update anonymous class generation to use stable call site IDs
- Modify type ID allocation to start from 1 and avoid renumbering
- Add literal string ID allocation using stable registry
- Implement global variable usage recording and tracking
- Add dependency symbols for classes, functions, constants, and globals
- Update property and function index allocation to use stable IDs
- Add cache site ID allocation based on call site context
- Implement compilation statistics merging and delta calculation
- Add file writing with content comparison to avoid unnecessary writes
- Implement incremental build cache clearing functionality
- Add metadata restoration for incremental compilation
- Create dependency graph building and dirty file propagation logic
- Implement translation unit emission tracking for incremental builds
- Implemented AstCache class with schema versioning and file-based storage
- Added cache validation using source hash, PHP version, and parser version
- Integrated atomic file operations to ensure cache consistency
- Updated CompilerBase to use lazy-initialized AST cache instance
- Replaced direct parser calls with cache-aware load operations in preprocessor
- Modified translator to utilize cached AST instead of reparsing
- Added comprehensive test coverage including cache hit, invalid
- Add reflection to access compiler's persistentFuncMap and literalStrings properties
- Retrieve actual function ID and string ID for 'get_class' at runtime
- Replace hardcoded regex values with dynamic IDs from compiler state
- Ensure polymorphic get_class dispatch uses correct persistent function lookup
- Maintain existing assertion logic while making test more robust to compiler changes
- Removed pcntl dependency and related functions from PlatformBase and Windows classes
- Implemented proc_open-based process pool in NativeBuilder for cross-platform parallel compilation
- Updated dispatchParallel to dispatchProcessParallel with new process management logic
- Modified Translator to use process pool instead of pcntl for parallel compilation
- Added fallback to sequential compilation when proc_open is unavailable
- Updated ParallelCompileTest to use process-based tests instead of pcntl mocking
- Bumped version from 0.8.1 to 0.8.2 in project configuration files
* fix(compiler): preserve runtime class dispatch and introspection for polymorphic objects
When an object variable has an upper-bound declared type (e.g. assigned from
a function or method return), SSA marks it as a stable object. However,
stableObjects does not guarantee the concrete runtime class: the instance
may be a subclass at runtime, or null if nullable.
1. FuncCallOptimizer::genGetClassOptimized checked isStableObject($obj->name)
and folded get_class($obj) to the declared type literal string. For
$a = getAnimal() returning a Dog, get_class($a) was incorrectly folded
to "Animal" at compile time.
2. MethodCallTrait::parseStaticCall checked isStableObject($class) and
jumped to _do_call with the declared base class. For $a::who(), this
statically invoked Base::who() instead of dispatching to Dog::who() on
the runtime object.
Require proven exact object instances (exactObjects, populated from direct
new ConcreteClass() definitions) before folding get_class() or devirtualizing
static calls on object variables. Non-exact variables fall back to runtime
class resolution (php::fn::get_class() and php::callStaticMethod()),
matching PHP semantics.
Add unit test coverage verifying exact objects continue to fold/devirtualize
while polymorphic variables retain dynamic runtime dispatch.
* fix(compiler): preserve lexical scope in dynamic static calls and runtime type checks for get_class
- Use php::callScoped with getCallableScopeExpr() for dynamic static calls inside class methods to preserve caller visibility on protected methods
- Fall back to runtime php::call for get_class on non-exact values so nullable objects throw TypeError instead of dereferencing null
- Add behavioral PHPT tests for protected polymorphic static calls and nullable get_class
- Update unit tests for scoped dispatch and runtime introspection
* test(compiler): remove stray top-level main call from PHPT tests
In TypePHP AOT compilation, function main(): void serves as the binary
entrypoint. Top-level function calls outside a function are rejected by
the preprocessor as stray code.
* fix(compiler): resolve function imports before dispatch and policy checks
* test: close PHP section in function import PHPT
* fix(compiler): resolve first-class function aliases
* fix(compiler): preserve called class in direct method calls
* fix(compiler): resolve called-class function targets
* fix(compiler): retain optimized namespace builtins
- Add materializeTrailingDefaults parameter to CallArgumentGenerator for default argument handling
- Implement native object stack slot allocation and promotion analysis
- Add nativeStackPromotions context tracking for non-escaping object allocations
- Generate NativeStackSlot declarations in compiler base code generation
- Update native method call generation to use direct member access patterns
- Add comprehensive native object member name validation and conflict detection
- Implement native destructor state management and finalization chains
- Add test cases for native class member name conflicts and stack promotion scenarios
- Replace nativeDeref calls with nativeRequireObject for improved object access safety
- Introduce CompilationStatistics class to track function, class, type, and dynamic capability usage
- Add statistics collection to CompilerBase for functions, classes, and types during conversion
- Implement NanoExtensionSelector to convert statistics into selective extension component needs
- Add fine-grained feature selection for standard extension components like arrays, strings, filesystem
- Create ComposerNativeComponent class for selective composition of native package parts
- Extend ComposerNativePackage with component metadata parsing and validation
- Update NanoSourceComposer to use statistics-driven selective composition
- Add test coverage for compilation statistics and extension selection scenarios
- Include example code and comprehensive test suite for new
- Configure kernel-only paging with separate user virtual regions
- Add PHP Nano project compilation with link library support
- Implement aligned memory block management for Zend allocator
- Create reusable libtypephp-os.a platform archive for TypePHP userspace
- Add uname system call support and update user-space syscalls
- Increase QEMU memory allocation from 128M to 160M
- Add TNHELLO.ELF as full TypePHP + PHPX
- Add objects section to project.yml for linking precompiled .o/.obj files
- Implement getProjectObjectFiles method to retrieve precompiled objects
- Add c-flags and asm-flags support in CompilerBase
- Extend GCC backend to handle cflags and nativeflags configuration
- Update compiler to include project object files in linking process
- Add freestanding C++ allocation ABI implementation using Zend MM
- Include example TypePHP OS with kernel entry point and hardware stubs
- Add assembly files for boot sequence and kernel entry point
- Implement basic libc compatibility layer for Zend bootstrap
- Add try/catch macro replacement in generated code indentation
- Create bridge between C++ kernel and PHP code
- Add linker script for 64-bit kernel binary generation
- Add native source project compilation workflow with project.xml configuration
- Implement closure reference capture analysis and type degradation for native objects
- Add WASI and nano mode function support checks with comprehensive API exclusions
- Introduce Composer native package discovery and validation system
- Add build scripts for WASI nano program compilation with browser module support
- Implement closure generator enhancements for reference capture handling
- Add CLI usage tests and compiler base API validations
- Integrate php-nano runtime dependencies and native package management
- Add type degradation analysis for closure use variables in generators and functions
- Renamed std::ordered_map to std::orderedMap following camelCase naming convention
- Added new std::object() function to restore concrete object type information
- Updated all test files to use the new orderedMap naming
- Modified parser to recognize orderedmap in assign operations
- Updated documentation to reflect the new naming and function
- Added polyfill implementation for std::object()
- Updated README and changelog with
* fix(compiler): support first-class callable of internal functions
PHP 8.1 `foo(...)` builds a Closure from a single VariadicPlaceholder
argument instead of calling foo. Two paths mishandled it:
- checkInternalFunctionArgCount() counted the placeholder as a real
argument, so first-class callables of internal functions requiring 2+
parameters (e.g. `posix_kill(...)`) failed with a bogus "expects at
least N arguments, 1 given".
- The math-function return-type optimization read `$expr->args[0]->value`
on callables such as `round(...)`, crashing on the undefined
VariadicPlaceholder::$value property.
Guard both with isFirstClassCallable() so the expression falls through to
Closure (Type::OBJECT) resolution.
* fix(compiler): infer builtin callables before return optimizations
---------
Co-authored-by: Tinywan <tinywan@gmail.com>
- Removed redundant zval macro handling for property access
- Replaced Z_LVAL_P and Z_DVAL_P calls with direct attribute accessors
- Updated property getter logic to use attrInt and attrFloat methods
- Modified tests to match new property access pattern
- Added comprehensive test case for inherited property reference handling
- Implement Android platform class with API level detection and compiler configuration
- Add Android-specific library linking with proper archive grouping and system libraries
- Integrate Android target detection and SDK directory resolution in build configuration
- Add Android-specific compile flags including static libstdc++ and security hardening
- Include Android platform support in translator and compiler base classes
- Add PHPX_ANDROID=1 define flag for Android builds
- Support