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

> Learn to conditionally include source entries in project.yml using php version or OS checks. Master version and OS comparisons with the 'if' field for flexible builds.

- Repository: [Swoole Project/typephp](https://github.com/swoole/typephp)
- Tags: how-to-guide
- Published: 2026-08-30

---

**Use the `if` field in [`project.yml`](https://github.com/swoole/typephp/blob/main/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`](https://github.com/swoole/typephp/blob/main/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`](https://github.com/swoole/typephp/blob/main/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.

```yaml
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:

```yaml
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:

```yaml
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:

```yaml
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:

```yaml
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:

- **[`examples/win32-hello/project.yml`](https://github.com/swoole/typephp/blob/main/examples/win32-hello/project.yml)** — Demonstrates Windows-specific source inclusion using `target.os == "windows"` conditions.
- **[`examples/wasm-hello/project.yml`](https://github.com/swoole/typephp/blob/main/examples/wasm-hello/project.yml)** — Shows conditional logic for non-Windows targets and WebAssembly builds.
- **[`tests/windows/smoke/project.yml`](https://github.com/swoole/typephp/blob/main/tests/windows/smoke/project.yml)** — Contains test suite configurations that leverage OS-based source conditions to validate Windows-specific code paths.

The root [`project.yml`](https://github.com/swoole/typephp/blob/main/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`](https://github.com/swoole/typephp/blob/main/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`](https://github.com/swoole/typephp/blob/main/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`](https://github.com/swoole/typephp/blob/main/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.