How to Specify Conditional Source Entries in `project.yml` Based on PHP Version or OS

Use the if field in project.yml source entries to conditionally include files by evaluating php.version and target.os variables, supporting comparison operators like >=, ==, and logical operators like && and ||.

The swoole/typephp build system allows you to define platform-aware and version-aware compilation sources directly in your project.yml configuration. By leveraging inline conditional maps within the sources list, you can maintain a single build configuration that automatically adapts to different PHP versions and target operating systems without file duplication or manual intervention.

Understanding Conditional Source Syntax

In project.yml, the sources field accepts a list of entries. Each entry can be either a simple string path or an inline map containing path and if keys.

sources:
  - ./src                         # always included

  - path: vendor/lib/foo.c
    if: php.version >= 8.1         # PHP 8.1+ only

  - path: src/windows_special.c
    if: target.os == "windows"    # Windows builds only

Entries without an if clause are unconditionally added to the compilation. When an if clause is present, TypePHP evaluates the expression using its internal expression evaluator. If the result is true, the path is included; if false, the entry is silently omitted.

Built-in Variables for Conditional Logic

The conditional system exposes two primary variables for build-time decisions:

  • php.version — Represents the PHP interpreter version used for the build, formatted as major.minor (e.g., 8.0, 8.1, 8.2).
  • target.os — Identifies the target operating system as a string identifier: "windows", "linux", or "macos".

Expression Operators and Syntax

The condition language supports standard comparison and logical operators:

Comparison operators: ==, !=, <, <=, >, >=

Logical operators: && (and), || (or)

You can combine conditions to create complex inclusion rules:

sources:
  - path: src/modern_unix.c
    if: php.version >= 8.1 && target.os != "windows"

Practical Configuration Patterns

Platform-Specific Source Files

Use target.os checks to isolate platform-dependent implementations:

sources:
  - ./src
  - path: src/windows/main_win.c
    if: target.os == "windows"
  - path: src/unix/posix_compat.c
    if: target.os != "windows"

This pattern ensures Windows-specific code only compiles when target.os == "windows", while Unix-compatible alternatives handle Linux and macOS builds.

PHP Version-Specific Implementations

Branch your source list based on PHP interpreter capabilities:

sources:
  - ./src
  - path: src/php8/fastpath.c
    if: php.version >= 8.0
  - path: src/php7/legacy_impl.c
    if: php.version < 8.0

As implemented in the swoole/typephp source, this approach lets you ship optimized implementations for newer PHP runtimes while maintaining backward compatibility through legacy fallbacks.

Combined OS and Version Constraints

For specialized optimizations requiring both platform and version alignment:

sources:
  - ./src
  - path: src/linux/php82_optimized.c
    if: target.os == "linux" && php.version >= 8.2

Real-World Configuration Examples

The swoole/typephp repository demonstrates these patterns across multiple example projects:

The root project.yml in the repository serves as the canonical reference, defining global source lists with conditional entries that handle cross-platform builds across the entire codebase.

Summary

  • Conditional sources use inline maps with path and if fields in the sources list of project.yml.
  • php.version provides the PHP interpreter version for version-specific compilation.
  • target.os identifies the target platform (windows, linux, macos) for OS-specific logic.
  • Comparison operators (>=, ==, !=, etc.) and logical operators (&&, ||) enable complex conditional expressions.
  • Entries without an if field are always included in the build.

Frequently Asked Questions

How does TypePHP evaluate the condition if the variables are undefined?

TypePHP's expression evaluator treats php.version and target.os as guaranteed build-time constants. These variables are automatically populated from the build environment before project.yml evaluation begins, ensuring all conditional expressions have valid values for comparison.

Can I use parentheses to group conditions in the if field?

Yes, the expression evaluator supports parentheses for explicit operator precedence grouping. For example: if: (php.version >= 8.0 && target.os == "linux") || target.os == "macos".

What happens if a source file referenced in a conditional entry does not exist?

If the condition evaluates to true but the file path does not exist, the build system will raise a compilation error. Conditional inclusion only controls whether the entry is added to the source list; it does not bypass file existence validation during the actual compilation phase.

Is it possible to use other variables besides php.version and target.os in conditional expressions?

According to the current project.yml implementation in swoole/typephp, only php.version and target.os are exposed as built-in variables for conditional source entries. Custom variables are not supported in the if evaluation context for the sources list.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →