- 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>
9.4 KiB
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:
CATEGORYrepresents a configuration category (likec++,rust,compiler-explorer,aws)ENVIRONMENTrepresents where the configuration will be used (likedefaults,amazon,local)
For example:
c++.defaults.properties- Default C++ configurationc++.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:
defaults- Base configuration that applies to all environments- Environment-specific settings (such as
dev,beta,staging,amazon) - Platform-specific environment settings (like
dev.linux,staging.darwin) - Platform-specific settings (like
linux,darwin,win32) - Host-specific settings (using the machine's hostname)
local- User-specific configuration that overrides all others (can be disabled with the--no-localflag)
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:
etc/config/category.defaults.propertiesetc/config/category.staging.propertiesetc/config/category.staging.linux.propertiesetc/config/category.linux.propertiesetc/config/category.myserver.propertiesetc/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:
-
Strings - The default type for all properties
compiler.clang.name=Clang -
Booleans - Values
true,yes,false,noare converted to boolean valuescompiler.clang.supportsBinary=true -
Numbers - Numeric strings are converted to integers or floats
compiler.clang.timeout=10 -
Special Version Properties - Properties ending with
.versionor.semverare 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:
-
Colon-separated lists (
:) - Most commonly used for lists of identifiers, compiler names, etc.compilers=gcc:clang:msvc -
Pipe-separated lists (
|) - Used for argument lists, particularly when options might contain colonscompiler.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:
- The
compilerslist includes two groups (&gccand&clang) and one individual compiler - Each group defines its own list of compilers
- Properties set at the group level (like
supportsBinaryorintelAsm) 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.
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
-
${exePath}: Replaced with the directory path of the compiler executable
ldPath=/opt/compiler-explorer/lib/|${exePath}/../lib/ -
${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:
-
Colon-separated: Used for general lists (compilers, versions, etc.)
compilers=gcc:clang:msvc -
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 systemlib/properties.interfaces.ts- TypeScript interfaces for the properties systemlib/compiler-finder.ts- Handles compiler discovery and group expansionlib/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.