# When Is `main()` Required for a TypePHP Build? Executable vs Library Guide

> Learn when TypePHP's main() function is essential for executable builds versus library and test targets. Understand TypePHP compilation requirements.

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

---

**In TypePHP, a `main()` function is required only when compiling to an executable target—either a native binary or a WASI WebAssembly module—while library and test builds compile successfully without this entry point.**

The swoole/typephp compiler uses the presence of a `function main(...): void` declaration to determine the artifact type it will produce. Understanding this distinction ensures you implement the correct entry point for your use case and avoid compilation errors in executable builds.

## Executable Builds That Require `main()`

TypePHP mandates a `main()` function whenever the compilation target is an executable, as the runtime needs a defined entry point to begin execution.

### Native Stand-Alone Executables

When running the compiler in default mode (without special flags), TypePHP generates a native binary that starts execution at your user-defined `main()` function. The compiler expects the exact signature `function main(int $argc, array $argv): void` to properly handle command-line arguments.

```php
<?php
function main(int $argc, array $argv): void
{
    echo "Hello from TypePHP!\n";
    // Application logic receives $argv via the parameter
}

```

According to the source code in [`src/Translator.php`](https://github.com/swoole/typephp/blob/main/src/Translator.php), the compilation process validates that this entry point exists before generating the binary artifact. The [`src/compiler.php`](https://github.com/swoole/typephp/blob/main/src/compiler.php) file itself implements this pattern, containing a `function main(int $argc, array $argv)` that serves as the CLI entry point for the compiler tool.

### WASI and WebAssembly Targets (`--wasm`)

When targeting WebAssembly with the `--wasm` flag, TypePHP produces a WASI program that still requires an exported `main` function. As documented in [`docs/en/wasm.md`](https://github.com/swoole/typephp/blob/main/docs/en/wasm.md), the WASI runtime expects this specific function to serve as the module entry point.

```php
<?php
function main(): void
{
    // WASI programs start here; access stdin/stdout via WASI APIs
    echo "Running inside WASI\n";
}

```

While the parameter signature can be flexible for WASI builds, the function name must be `main` for the WebAssembly module to initialize correctly when loaded by the host runtime.

## Builds That Omit `main()`

Not every TypePHP project requires an entry point. Library and test builds skip the `main()` requirement entirely since they produce code invoked by other systems rather than standing alone.

### Library Builds (`--library`)

When compiling with the `--library` flag (or equivalent), TypePHP generates only object files or a static archive. Since library code is linked into other applications rather than executed directly, no entry point is necessary.

```php
<?php
// Compiled into a library archive without a main function
function add(int $a, int $b): int
{
    return $a + $b;
}

```

The [`src/Translator.php`](https://github.com/swoole/typephp/blob/main/src/Translator.php) logic bypasses entry point validation when operating in library mode, focusing instead on exporting the public API defined in your source files.

### Test Harnesses and Internal Scripts

Test builds executed through the built-in test runner ([`run-tests.php`](https://github.com/swoole/typephp/blob/main/run-tests.php)) or PHPUnit do not require a `main()` function. The test harness invokes your code directly, making an entry point unnecessary. Files like [`phpunit/src/Testing/TestCoverageAnalyzerTest.php`](https://github.com/swoole/typephp/blob/main/phpunit/src/Testing/TestCoverageAnalyzerTest.php) demonstrate this pattern, containing test logic without a `main()` implementation.

## How the Compiler Detects the Entry Point

The TypePHP build system inspects your source code during the translation phase to determine output type. In [`src/Translator.php`](https://github.com/swoole/typephp/blob/main/src/Translator.php), the project parsing logic checks for the existence of a global `main()` function to decide whether to produce a binary executable or a library archive.

This detection happens early in the compilation pipeline. If the compiler targets an executable format (native or WASI) and cannot locate a `main()` function in the global scope, it will report an error before code generation begins. For library builds, this check is skipped entirely, allowing the compilation to proceed with only utility functions and classes.

## Summary

- **Executable builds require `main()`**: Native binaries and WASI WebAssembly modules must define `function main(int $argc, array $argv): void` (or `function main(): void` for WASI) to provide an entry point.
- **Library builds skip `main()`**: Compiling with `--library` produces object files or archives without needing an entry point.
- **Test builds don't need `main()`**: The test runner invokes code directly, eliminating the requirement for a `main()` function.
- **Compiler validation**: The logic in [`src/Translator.php`](https://github.com/swoole/typephp/blob/main/src/Translator.php) enforces these requirements based on CLI flags passed to the compiler.

## Frequently Asked Questions

### What happens if I forget to include `main()` in an executable build?

The TypePHP compiler will fail with a compilation error during the translation phase. As implemented in [`src/Translator.php`](https://github.com/swoole/typephp/blob/main/src/Translator.php), the build system explicitly verifies that a `main()` function exists when targeting executable output, ensuring the generated binary has a valid entry point to begin execution.

### Can I name my entry point something other than `main()`?

No. TypePHP follows the C convention and requires the entry point to be named exactly `main`. The compilerlooks for this specific function name when determining build type and generating the executable bootstrap code in [`src/compiler.php`](https://github.com/swoole/typephp/blob/main/src/compiler.php).

### Do I need parameters in my `main()` function for WASI builds?

While native executable builds require the signature `function main(int $argc, array $argv): void`, WASI builds documented in [`docs/en/wasm.md`](https://github.com/swoole/typephp/blob/main/docs/en/wasm.md) are more flexible. You can define `function main(): void` without parameters and still access WASI APIs for input/output, though including the parameters is also valid if you need argument access.

### How do I access command-line arguments in a TypePHP application?

For native executable builds, access command-line arguments through the `$argc` (argument count) and `$argv` (argument array) parameters passed to your `main()` function. This mirrors the C convention and is the standard method implemented in the TypePHP runtime as shown in the [`src/compiler.php`](https://github.com/swoole/typephp/blob/main/src/compiler.php) implementation.