Files
compiler-explorer/docs/Configuration.md
Matt Godbolt 54c942ba76 Replace nopt with commander.js for argument parsing (#7673)
- Replace nopt with commander.js for better command-line argument parsing
- Add automatic help generation with detailed descriptions
- Maintain backward compatibility with existing arguments
- Remove unused nopt dependency from package.json

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-05-12 12:49:28 -05:00

265 lines
9.4 KiB
Markdown

# Compiler Explorer Configuration System
This document describes the configuration system used by Compiler Explorer, which is based on `.properties` files that
follow a hierarchical structure with inheritance and specialized handling for various property types.
## Configuration File Structure
Compiler Explorer uses `.properties` files located in the `etc/config/` directory for all its configuration needs. These
files follow a simple key-value format:
```
key=value
```
Comments are lines that start with a hash character, and are not processed:
```
# This is a comment
key=value # This is also a comment
```
### File Naming Convention
Configuration files follow a specific naming pattern:
```
CATEGORY.ENVIRONMENT.properties
```
Where:
- `CATEGORY` represents a configuration category (like `c++`, `rust`, `compiler-explorer`, `aws`)
- `ENVIRONMENT` represents where the configuration will be used (like `defaults`, `amazon`, `local`)
For example:
- `c++.defaults.properties` - Default C++ configuration
- `c++.amazon.properties` - C++ configuration for the Amazon environment (used in production)
- `c++.local.properties` - Local C++ configuration (ignored by git, for personal settings)
## Configuration Hierarchy
The system loads configuration files in a specific order, creating a cascade of settings. The actual hierarchy used for
property resolution, from lowest to highest priority, is:
1. `defaults` - Base configuration that applies to all environments
2. Environment-specific settings (such as `dev`, `beta`, `staging`, `amazon`)
3. Platform-specific environment settings (like `dev.linux`, `staging.darwin`)
4. Platform-specific settings (like `linux`, `darwin`, `win32`)
5. Host-specific settings (using the machine's hostname)
6. `local` - User-specific configuration that overrides all others (can be disabled with the `--no-local` flag)
For example, if you're running on a Linux machine named "myserver" in the "staging" environment, a property would be
looked up in this order:
1. `etc/config/category.defaults.properties`
2. `etc/config/category.staging.properties`
3. `etc/config/category.staging.linux.properties`
4. `etc/config/category.linux.properties`
5. `etc/config/category.myserver.properties`
6. `etc/config/category.local.properties`
This means if the same property is defined in multiple files, the one from the most specific environment will be used.
### Important Note on Group Properties
The hierarchy/cascade only works for top-level properties. Group properties (discussed below) do not inherit across
different environment files. That is, if you define a group property in `c++.defaults.properties`, but that group is
defined without that property in `c++.amazon.properties`, the property will not be carried forward to the amazon
environment.
## Property Types
While all properties are stored as strings in the files, the system automatically converts values to appropriate types
using the `toProperty` function:
1. **Strings** - The default type for all properties
```
compiler.clang.name=Clang
```
2. **Booleans** - Values `true`, `yes`, `false`, `no` are converted to boolean values
```
compiler.clang.supportsBinary=true
```
3. **Numbers** - Numeric strings are converted to integers or floats
```
compiler.clang.timeout=10
```
4. **Special Version Properties** - Properties ending with `.version` or `.semver` are never converted to numbers, even
if they look like numbers. This preserves version formatting with leading zeros or other special characters:
```
compiler.gcc123.version=9.0.0 # Remains the string "9.0.0" instead of becoming a number
```
## Lists and Separators
Many properties in Compiler Explorer represent lists of values. These use specific separators:
1. **Colon-separated lists** (`:`) - Most commonly used for lists of identifiers, compiler names, etc.
```
compilers=gcc:clang:msvc
```
2. **Pipe-separated lists** (`|`) - Used for argument lists, particularly when options might contain colons
```
compiler.clang.demanglerArgs=-n|-C|--no-verbose
```
## Compiler and Group Configuration
### Basic Compiler Configuration
Compilers are configured using properties with the `compiler.ID` prefix:
```
compiler.gcc.name=GCC
compiler.gcc.exe=/usr/bin/gcc
compiler.gcc.options=-Wall
```
### Group System with &IDENTIFIER
A key feature of the configuration system is the ability to define groups of compilers with shared settings using `&`
syntax:
```
compilers=&gcc:&clang:specific_compiler
group.gcc.compilers=gcc7:gcc8:gcc9
group.gcc.groupName=GCC
group.gcc.supportsBinary=true
group.clang.compilers=clang9:clang10
group.clang.groupName=Clang
group.clang.intelAsm=-mllvm --x86-asm-syntax=intel
```
In this example:
1. The `compilers` list includes two groups (`&gcc` and `&clang`) and one individual compiler
2. Each group defines its own list of compilers
3. Properties set at the group level (like `supportsBinary` or `intelAsm`) are inherited by all compilers in that group
Groups can contain other groups by using the `&` syntax within a group's compilers list:
```
group.newer.compilers=&clang:&gcc
group.newer.groupName=Modern Compilers
```
### Property Inheritance
Properties are inherited from groups to individual compilers. If both a group and a compiler define the same property,
the compiler's value takes precedence. This allows for group-wide defaults with compiler-specific overrides.
**There are some notable exceptions to this rule**: some unique-per-compiler properties are not inherited from groups,
but we hope to fix this. See [this GitHub issue](https://github.com/compiler-explorer/compiler-explorer/issues/7150).
## Configuration Keys
Common configuration keys include:
| Key Name | Type | Description |
|----------------|---------|-----------------------------------------------------|
| name | String | Human-readable name displayed to users |
| exe | Path | Path to the executable |
| options | String | Default compiler options |
| compilerType | String | Refers to the handler class in `lib/compilers/*.ts` |
| intelAsm | String | Flags for Intel assembly syntax |
| supportsX | Boolean | Capability flags for various features |
| versionFlag | String | Flag to pass to compiler to get version |
| demanglerArgs | String | Arguments for the demangler (pipe-separated) |
| objdumperArgs | String | Arguments for the object dumper (pipe-separated) |
| instructionSet | String | Default instruction set for the compiler |
## Variable Substitution
Some properties support variable substitution to make configuration more flexible. The most common variables are:
### Path Variables
1. **${exePath}**: Replaced with the directory path of the compiler executable
```
ldPath=/opt/compiler-explorer/lib/|${exePath}/../lib/
```
2. **${ceToolsPath}**: Replaced with the path to the Compiler Explorer tools directory
```
demangler=${ceToolsPath}/demangler
```
### Special Properties for Environment Variables
Environment variables can be configured using a special format:
```
envVars=VAR1=value1:VAR2=value2
```
This is parsed and converted into environment variable key-value pairs that are passed to the compiler when it's
executed.
### Path Lists
Multiple types of path lists exist in the system, mainly using two separator styles:
1. **Colon-separated**: Used for general lists (compilers, versions, etc.)
```
compilers=gcc:clang:msvc
```
2. **Pipe-separated**: Used for path lists and command arguments
```
ldPath=/path/to/lib1|/path/to/lib2
demanglerArgs=-n|-C|--no-verbose
```
Note that path-style properties often support variable substitution as shown above.
## Advanced Configuration Features
### Property Debugging
You can enable detailed debugging of property resolution by using the `--prop-debug` flag when starting Compiler
Explorer. This shows every property lookup, including where properties are being overridden and which configuration
source they come from.
### Remote Compiler Configuration
Compiler Explorer supports defining remote compilers using a special syntax in the configuration:
```
compilers=local1:local2:remote@hostname:port
```
When a compiler ID contains the `@` symbol followed by a hostname and port, it is interpreted as a remote compiler. This
allows running compilers on separate machines and accessing them through the main Compiler Explorer instance.
### Orphaned Property Detection
The system has built-in detection for "orphaned" properties - configurations for compilers or groups that are not
referenced anywhere. This helps maintain configuration cleanliness by identifying unused configuration entries.
## Configuration System Implementation
The configuration system is implemented primarily in the following files:
- `lib/properties.ts` - Core implementation of the properties system
- `lib/properties.interfaces.ts` - TypeScript interfaces for the properties system
- `lib/compiler-finder.ts` - Handles compiler discovery and group expansion
- `lib/utils.ts` - Contains property value conversion functions
## Debugging Configuration
If you need to troubleshoot configuration issues, you can run Compiler Explorer with debug output:
```
make EXTRA_ARGS='--prop-debug' dev
```
This will show detailed logs about property resolution, including which properties are being overridden and from which
source.