Files
compiler-explorer/CLAUDE.md
2025-10-11 18:06:46 +02:00

9.5 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build & Test Commands

  • Build: npm run webpack, npm start
  • Dev Mode: make dev, make gpu-dev
  • Lint: npm run lint (auto-fix), npm run lint-check (check only)
  • Type Check: npm run ts-check
  • Test: npm run test (all), npm run test-min (minimal)
  • Test Single File: npm run test -- --run base-compiler-tests.ts
  • Test Specific Pattern: npm run test -- -t "should handle execution failures"
  • Cypress Tests: npm run cypress
  • Pre-commit Check: make pre-commit or npm run check

Important Workflow Requirements

  • ⚠️ NEVER BYPASS PRE-COMMIT HOOKS! NEVER use git commit -n or --no-verify ⚠️
  • ALWAYS run make pre-commit or at minimum npm run ts-check and npm run lint before committing
  • The full process must always be:
    1. Make changes
    2. Run npm run ts-check to verify TypeScript types
    3. Run npm run lint to fix style issues (will auto-fix many problems)
    4. Run npm run test to verify functionality (or at least npm run test-min)
    5. ONLY THEN commit changes with plain git commit (NO FLAGS!)
  • Bypassing these checks will lead to broken builds, failed tests, and PRs that cannot be merged

Style Guidelines

  • TypeScript: Strict typing, no implicit any, no unused locals
  • Formatting: 4-space indentation, 120 char line width, single quotes
  • No semicolon omission, prefer const/let over var
  • Client-side: TypeScript transpiled to ES5 JavaScript. This process requires import of blah.js even though blah.ts is the actual filename
  • ALWAYS place imports at the top of files, never inside functions or methods, unless absolutely necessary (and confirm before proposing)
  • Use Underscore.js for utility functions
  • Write tests for new server-side components
  • Where appropriate suggest follow-up improvements to code to improve code quality, and DRY up where feasible
  • Documentation is in docs/ directory; update where necessary, in particular if anything about the RESTful API changes
  • Don't add comments above code that's clearly self-documenting. For example, don't put comments like this:
    // Initialises the thing
    initialiseThing();
    
  • Avoid redundant function header comments that merely repeat the function name. For example:
    /**
     * Sets up compiler change handling
     */
    function setupCompilerChangeHandling() {...}
    
    In this case, the function name already clearly states what it does.
  • Comments should provide additional context or explain "why" something is done, not just restate "what" is being done.
  • Only add function header comments when they provide meaningful information beyond what the function name and signature convey.
  • Use British English spellings for things like "initialise" and "colour", but only in new code. It's a preference not a hard requirement
  • Use modern Typescript features like optional chaining when updating existing code or adding new code

Architecture Guidelines

  • Frontend/Backend Separation: Frontend code (static/) MUST NOT import from backend code (lib/)
    • Frontend should use API calls to communicate with backend
    • Shared types should be imported from types/ directory instead
    • This separation is enforced by pre-commit hooks (npm run check-frontend-imports)
    • Violations will cause build failures and prevent commits

Worker Mode Configuration

  • Compilation Workers: New feature for offloading compilation tasks to dedicated worker instances
    • compilequeue.is_worker=true: Enables compilation worker mode (similar to execution workers)
    • compilequeue.queue_url: SQS queue URL for compilation requests (both regular and CMake)
    • compilequeue.events_url: WebSocket URL for sending compilation results
    • compilequeue.worker_threads=2: Number of concurrent worker threads
    • compilequeue.poll_interval_ms=1000: Interval between poll attempts after processing or errors (default: 1000ms). Note: SQS long polling means actual wait time is up to 20 seconds when queue is empty
    • --instance-color <color>: Optional command-line parameter to differentiate deployment instances. When specified (blue or green), modifies the queue URL by appending the color to the queue name (e.g., staging-compilation-queue-blue.fifo)
  • Implementation: Located in /lib/compilation/sqs-compilation-queue.ts with shared parsing utilities in /lib/compilation/compilation-request-parser.ts
  • Queue Architecture: Uses single AWS SQS FIFO queue for reliable message delivery, messages contain isCMake flag to distinguish compilation types
  • S3 Overflow Support: Large compilation requests exceeding SQS message size limits (256KB) are automatically stored in S3
    • Messages exceeding the limit are stored in S3 bucket compiler-explorer-sqs-overflow
    • SQS receives a lightweight reference message with type s3-overflow containing S3 location
    • Workers automatically detect overflow messages and fetch the full request from S3
    • S3 objects are automatically deleted after 1 day via lifecycle policy
  • Result Delivery: Uses WebSocket-based communication via PersistentEventsSender for improved performance with persistent connections
  • Message Production: Queue messages are produced by external Lambda functions, not by the main Compiler Explorer server
  • Shared Parsing: Common request parsing logic is shared between web handlers and SQS workers for consistency
  • Remote Compiler Support: Workers automatically detect and proxy requests to remote compilers using HTTP, maintaining compatibility with existing remote compiler infrastructure
  • S3 Storage Integration: Compilation results include an s3Key property containing the cache key hash for S3 storage reference. Large results (>31KiB) can be stored in S3 and referenced by this key. The s3Key is removed from API responses before sending to users.
  • Metrics & Statistics: SQS workers track separate Prometheus metrics (ce_sqs_compilations_total, ce_sqs_executions_total, ce_sqs_cmake_compilations_total, ce_sqs_cmake_executions_total) and record compilation statistics via statsNoter.noteCompilation for Grafana monitoring, mirroring the regular API route behavior.

Configuration Management

CE Properties Wizard

  • Location: /etc/scripts/ce-properties-wizard/ - Interactive tool for adding compilers to local CE installations
  • Usage: Run via ./run.sh (Linux/macOS) or .\run.ps1 (Windows) with optional compiler path and flags
  • Auto-Detection: Automatically detects compiler type, language, version, and configuration from executable paths
  • MSVC Auto-Configuration: Enhanced support for Microsoft Visual C++ compilers:
    • Demangler: Automatically detects and configures undname.exe with demanglerType=win32
    • Objdumper: Auto-detects LLVM objdump (llvm-objdump.exe) and configures objdumperType=llvm when available
    • SDK Integration: Supports Windows SDK path specification via --sdk-path for non-interactive use
    • Architecture Matching: Correctly maps compiler architecture (x64, x86, arm64) to tool paths
  • Group Management: Automatically creates and manages compiler groups with appropriate properties
  • Validation: Integrates with propscheck.py and discovery validation to ensure configurations work
  • Safe Operations: Creates backups and preserves existing configurations, only adding new content

Properties Validation

  • Propscheck Script: Use python3 etc/scripts/util/propscheck.py --config-dir etc/config --check-local to validate all property files
  • Run after modifying any .properties files to check for duplicates, misconfigurations, and other issues

Testing Guidelines

  • Use Vitest for unit tests (compatible with Jest syntax)
  • Tests are in the /test directory, typically named like the source files they test
  • Use spy functions with vi.spyOn() for mocking dependencies
  • Test structure follows describe/it pattern with descriptive test names
  • Separate tests with clear section headers using comments for readability
  • Consider cross-platform compatibility (especially Windows path handling)
  • For complex files, organize tests by functionality rather than by method
  • Use beforeEach/afterEach to set up and clean up test environment
  • Remember to restore mocks with vi.restoreAllMocks() after tests
  • Test both success and error cases
  • Coverage is available with npm test:coverage
  • For Windows-specific path issues, either:
    • Skip tests with if (process.platform === 'win32') return;
    • Write platform-specific assertions
    • Use path-agnostic checks

Test Execution with Expensive Test Skipping

  • The SKIP_EXPENSIVE_TESTS=true environment variable skips expensive tests (like filter tests)
  • Pre-commit hooks use vitest related to run only tests related to changed files
  • Use npm run test-min to run tests with expensive tests skipped
  • Use npm run test to run all tests including expensive ones
  • To mark tests as expensive, use: describe.skipIf(process.env.SKIP_EXPENSIVE_TESTS === 'true')('Test suite', () => {...})

Compiler Testing Specifics

  • Mock filesystem operations when testing file I/O
  • Use makeFakeCompilerInfo() for creating test compiler configurations
  • Use makeCompilationEnvironment() to create test environments
  • Mock exec calls for testing compilation and execution
  • For BaseCompiler, use the test utils from /test/utils.js
  • Test specific combinations of compiler capabilities
  • Focus tests on behavior, not implementation details
  • Use platform-agnostic assertions where possible