Repository: compiler-explorer/compiler-explorer
Pull request #6939 (2024-10-07 06:37:09)

Add trompeloeil v49
<!-- THIS COMMENT IS INVISIBLE IN THE FINAL PR, BUT FEEL FREE TO REMOVE IT
Thanks for taking the time to improve CE. We really appreciate it.
  Before opening the PR, please make sure that the tests & linter pass their checks,
  by running `make check`.
  In the best case scenario, you are also adding tests to back up your changes,
  but don't sweat it if you don't. We can discuss them at a later date.
Feel free to append your name to the CONTRIBUTORS.md file
Thanks again, we really appreciate this!
-->



Patch:
diff --git a/etc/config/c++.amazon.properties b/etc/config/c++.amazon.properties
index 8e7b13c4b..4ac108242 100644
--- a/etc/config/c++.amazon.properties
+++ b/etc/config/c++.amazon.properties
@@ -5326,8 +5326,10 @@ libs.tomlplusplus.versions.124.version=1.2.4
 libs.tomlplusplus.versions.124.path=/opt/compiler-explorer/libs/tomlplusplus/v1.2.4/include
 
 libs.trompeloeil.name=trompeloeil
-libs.trompeloeil.versions=48:47:46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
+libs.trompeloeil.versions=49:48:47:46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
 libs.trompeloeil.url=https://github.com/rollbear/trompeloeil
+libs.trompeloeil.versions.49.path=/opt/compiler-explorer/libs/trompeloeil/v49/include
+libs.trompeloeil.versions.49.version=v49
 libs.trompeloeil.versions.48.path=/opt/compiler-explorer/libs/trompeloeil/v48/include
 libs.trompeloeil.versions.48.version=v48
 libs.trompeloeil.versions.47.path=/opt/compiler-explorer/libs/trompeloeil/v47/include
diff --git a/etc/config/c.amazon.properties b/etc/config/c.amazon.properties
index 22440a9e3..f3d12da01 100644
--- a/etc/config/c.amazon.properties
+++ b/etc/config/c.amazon.properties
@@ -377,7 +377,7 @@ compiler.nvc_x86_24_9.demangler=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.9
 compiler.nvc_x86_24_9.cuobjdump=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.9/cuda/12.6/bin/cuobjdump
 compiler.nvc_x86_24_9.nvdisasm=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.9/cuda/12.6/bin/nvdisasm
 compiler.nvc_x86_24_9.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.9/compilers/bin/nvc
-
+compiler.nvc_x86_24_9.semver=24.9
 
 # Clang for Arm
 # Provides 32- and 64-bit menu items for clang-9 and trunk
diff --git a/etc/config/circle.amazon.properties b/etc/config/circle.amazon.properties
index d6aa724fe..205101d04 100644
--- a/etc/config/circle.amazon.properties
+++ b/etc/config/circle.amazon.properties
@@ -1021,8 +1021,10 @@ libs.tomlplusplus.versions.124.version=1.2.4
 libs.tomlplusplus.versions.124.path=/opt/compiler-explorer/libs/tomlplusplus/v1.2.4/include
 
 libs.trompeloeil.name=trompeloeil
-libs.trompeloeil.versions=48:47:46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
+libs.trompeloeil.versions=49:48:47:46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
 libs.trompeloeil.url=https://github.com/rollbear/trompeloeil
+libs.trompeloeil.versions.49.path=/opt/compiler-explorer/libs/trompeloeil/v49/include
+libs.trompeloeil.versions.49.version=v49
 libs.trompeloeil.versions.48.path=/opt/compiler-explorer/libs/trompeloeil/v48/include
 libs.trompeloeil.versions.48.version=v48
 libs.trompeloeil.versions.47.path=/opt/compiler-explorer/libs/trompeloeil/v47/include
diff --git a/etc/config/objc++.amazon.properties b/etc/config/objc++.amazon.properties
index 7a7f40d0d..419bd435a 100644
--- a/etc/config/objc++.amazon.properties
+++ b/etc/config/objc++.amazon.properties
@@ -1866,8 +1866,10 @@ libs.tomlplusplus.versions.124.version=1.2.4
 libs.tomlplusplus.versions.124.path=/opt/compiler-explorer/libs/tomlplusplus/v1.2.4/include
 
 libs.trompeloeil.name=trompeloeil
-libs.trompeloeil.versions=48:47:46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
+libs.trompeloeil.versions=49:48:47:46:45:44:43:42:41:40:39:38:37:36:35:34:33:32:31:30:29:28
 libs.trompeloeil.url=https://github.com/rollbear/trompeloeil
+libs.trompeloeil.versions.49.path=/opt/compiler-explorer/libs/trompeloeil/v49/include
+libs.trompeloeil.versions.49.version=v49
 libs.trompeloeil.versions.48.path=/opt/compiler-explorer/libs/trompeloeil/v48/include
 libs.trompeloeil.versions.48.version=v48
 libs.trompeloeil.versions.47.path=/opt/compiler-explorer/libs/trompeloeil/v47/include
diff --git a/lib/base-compiler.ts b/lib/base-compiler.ts
index 4bfe0a5a3..adf8d1ce0 100644
--- a/lib/base-compiler.ts
+++ b/lib/base-compiler.ts
@@ -432,7 +432,7 @@ export class BaseCompiler implements ICompiler {
         return {mtime: this.mtime, compiler, args, options};
     }
 
-    protected async execCompilerCached(
+    public async execCompilerCached(
         compiler: string,
         args: string[],
         options?: ExecutionOptionsWithEnv,
@@ -3462,7 +3462,11 @@ but nothing was dumped. Possible causes are:
         return this.env.getPossibleToolchains();
     }
 
-    async initialise(mtime: Date, clientOptions: ClientOptionsType, isPrediscovered = false) {
+    async initialise(
+        mtime: Date,
+        clientOptions: ClientOptionsType,
+        isPrediscovered = false,
+    ): Promise<BaseCompiler | null> {
         this.mtime = mtime;
 
         if (this.buildenvsetup) {
@@ -3484,7 +3488,7 @@ but nothing was dumped. Possible causes are:
             }
             const fullVersion = result.stdout + result.stderr;
             _.each(utils.splitLines(fullVersion), line => {
-                if (version) return;
+                if (version) return null;
                 const match = line.match(versionRe);
                 if (match) version = match[0];
             });
diff --git a/lib/compilers/argument-parsers.ts b/lib/compilers/argument-parsers.ts
index 091db6747..3df178316 100644
--- a/lib/compilers/argument-parsers.ts
+++ b/lib/compilers/argument-parsers.ts
@@ -25,22 +25,27 @@
 import path from 'path';
 import process from 'process';
 
+import * as Sentry from '@sentry/node';
 import fs from 'fs-extra';
 import _ from 'underscore';
 
 import {CompilerOverrideOptions} from '../../types/compilation/compiler-overrides.interfaces.js';
+import {Argument} from '../../types/compiler-arguments.interfaces.js';
+import {BaseCompiler} from '../base-compiler.js';
 import {logger} from '../logger.js';
 import * as props from '../properties.js';
 import * as utils from '../utils.js';
 
+import {JuliaCompiler} from './julia.js';
+
 export class BaseParser {
-    static setCompilerSettingsFromOptions(compiler, options) {}
+    static setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {}
 
-    static hasSupport(options, forOption) {
+    static hasSupport(options: Record<string, Argument>, forOption: string) {
         return _.keys(options).find(option => option.includes(forOption));
     }
 
-    static hasSupportStartsWith(options, forOption) {
+    static hasSupportStartsWith(options: Record<string, Argument>, forOption: string) {
         return _.keys(options).find(option => option.startsWith(forOption));
     }
 
@@ -59,9 +64,9 @@ export class BaseParser {
         return filename;
     }
 
-    static parseLines(stdout, optionWithDescRegex: RegExp, optionWithoutDescRegex?: RegExp) {
+    static parseLines(stdout: string, optionWithDescRegex: RegExp, optionWithoutDescRegex?: RegExp) {
         let previousOption: false | string = false;
-        const options = {};
+        const options: Record<string, Argument> = {};
 
         utils.eachLine(stdout, line => {
             const match1 = line.match(optionWithDescRegex);
@@ -114,19 +119,20 @@ export class BaseParser {
         return text.replaceAll('  ', ' ');
     }
 
-    static async getPossibleTargets(compiler): Promise<string[]> {
+    static async getPossibleTargets(compiler: BaseCompiler): Promise<string[]> {
         return [];
     }
 
-    static async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         return [];
     }
 
-    static async getPossibleEditions(compiler): Promise<string[]> {
+    // Currently used only for Rust
+    static async getPossibleEditions(compiler: BaseCompiler): Promise<string[]> {
         return [];
     }
 
-    static async getOptions(compiler, helpArg) {
+    static async getOptions(compiler: BaseCompiler, helpArg: string) {
         const optionFinder1 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)  +(.*)/i;
         const optionFinder2 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, [helpArg]);
@@ -136,13 +142,14 @@ export class BaseParser {
         return options;
     }
 
-    static parse(compiler) {
+    // async for compatibility with children, who call getOptions
+    static async parse(compiler: BaseCompiler) {
         return compiler;
     }
 }
 
 export class GCCParser extends BaseParser {
-    static async checkAndSetMasmIntelIfSupported(compiler) {
+    static async checkAndSetMasmIntelIfSupported(compiler: BaseCompiler) {
         // -masm= may be available but unsupported by the compiler.
         const res = await compiler.execCompilerCached(compiler.compiler.exe, [
             '-fsyntax-only',
@@ -155,7 +162,7 @@ export class GCCParser extends BaseParser {
         }
     }
 
-    static override async setCompilerSettingsFromOptions(compiler, options) {
+    static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {
         const keys = _.keys(options);
         logger.debug(`gcc-like compiler options: ${keys.join(' ')}`);
         if (this.hasSupport(options, '-masm=')) {
@@ -186,7 +193,7 @@ export class GCCParser extends BaseParser {
         if (this.hasSupportStartsWith(options, '--target ')) compiler.compiler.supportsTarget = true;
     }
 
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const results = await Promise.all([
             this.getOptions(compiler, '-fsyntax-only --help'),
             this.getOptions(compiler, '-fsyntax-only --target-help'),
@@ -200,7 +207,7 @@ export class GCCParser extends BaseParser {
         return compiler;
     }
 
-    static override async getPossibleTargets(compiler): Promise<string[]> {
+    static override async getPossibleTargets(compiler: BaseCompiler): Promise<string[]> {
         const re = /Known valid arguments for -march= option:\s+(.*)/;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, ['-fsyntax-only', '--target-help']);
         const match = result.stdout.match(re);
@@ -215,7 +222,7 @@ export class GCCParser extends BaseParser {
         return ['-fsyntax-only', '--help=c++'];
     }
 
-    static override async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         const possible: CompilerOverrideOptions = [];
         const options = await this.getOptionsStrict(compiler, this.getLanguageSpecificHelpFlags());
         for (const opt in options) {
@@ -230,7 +237,7 @@ export class GCCParser extends BaseParser {
         return possible;
     }
 
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const optionFinder1 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)  +(.*)/i;
         const optionFinder2 = /^ *(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' '));
@@ -240,7 +247,7 @@ export class GCCParser extends BaseParser {
         return options;
     }
 
-    static async getOptionsStrict(compiler, helpArgs: string[]) {
+    static async getOptionsStrict(compiler: BaseCompiler, helpArgs: string[]) {
         const optionFinder = /^ {2}(--?[\d+,<=>[\]a-z|-]*) *(.*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArgs);
         return result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder) : {};
@@ -250,7 +257,7 @@ export class GCCParser extends BaseParser {
 export class ClangParser extends BaseParser {
     static mllvmOptions = new Set<string>();
 
-    static override setCompilerSettingsFromOptions(compiler, options) {
+    static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {
         const keys = _.keys(options);
         logger.debug(`clang-like compiler options: ${keys.join(' ')}`);
 
@@ -321,7 +328,7 @@ export class ClangParser extends BaseParser {
         return ['--print-targets'];
     }
 
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         try {
             const options = await this.getOptions(compiler, this.getMainHelpOptions().join(' '));
 
@@ -331,14 +338,15 @@ export class ClangParser extends BaseParser {
                 _.keys(await this.getOptions(compiler, this.getHiddenHelpOptions(filename).join(' '), false, true)),
             );
             this.setCompilerSettingsFromOptions(compiler, options);
-            return compiler;
         } catch (error) {
-            logger.error(`Error while trying to generate llvm backend arguments for ${compiler.compiler.id}: ${error}`);
-            return null;
+            const err = `Error while trying to generate llvm backend arguments for ${compiler.compiler.id}: ${error}`;
+            logger.error(err);
+            Sentry.captureMessage(err);
         }
+        return compiler;
     }
 
-    static getRegexMatchesAsStdver(match, maxToMatch): CompilerOverrideOptions {
+    static getRegexMatchesAsStdver(match: RegExpMatchArray | null, maxToMatch: number): CompilerOverrideOptions {
         if (!match) return [];
         if (!match[maxToMatch]) return [];
 
@@ -385,7 +393,7 @@ export class ClangParser extends BaseParser {
         return possible;
     }
 
-    static override async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         let possible: CompilerOverrideOptions = [];
 
         // clang doesn't have a --help option to get the std versions, we'll have to compile with a fictional stdversion to coax a response
@@ -421,12 +429,12 @@ export class ClangParser extends BaseParser {
             .filter(Boolean) as string[];
     }
 
-    static override async getPossibleTargets(compiler): Promise<string[]> {
+    static override async getPossibleTargets(compiler: BaseCompiler): Promise<string[]> {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, this.getTargetsHelpOptions());
         return this.extractPossibleTargets(utils.splitLines(result.stdout));
     }
 
-    static override async getOptions(compiler, helpArg: string, populate = true, isolate = false) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string, populate = true, isolate = false) {
         const optionFinderWithDesc = /^ {2}?(--?[\d#+,<=>A-Z[\]a-z|-]*\s?[\d+,<=>A-Z[\]a-z|-]*)\s+([A-Z].*)/;
         const optionFinderWithoutDesc = /^ {2}?(--?[\d#+,<=>[\]a-z|-]*\s?[\d+,<=>[\]a-z|-]*)/i;
         const execOptions = {...compiler.getDefaultExecOptions()};
@@ -442,7 +450,7 @@ export class ClangParser extends BaseParser {
 }
 
 export class ClangirParser extends ClangParser {
-    static override setCompilerSettingsFromOptions(compiler, options) {
+    static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {
         ClangParser.setCompilerSettingsFromOptions(compiler, options);
 
         compiler.compiler.optPipeline = {
@@ -482,7 +490,7 @@ export class ClangCParser extends ClangParser {
 }
 
 export class CircleParser extends ClangParser {
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const optionFinder1 = /^ +(--?[\w#,.<=>[\]|-]*)  +- (.*)/i;
         const optionFinder2 = /^ +(--?[\w#,.<=>[\]|-]*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' '));
@@ -491,7 +499,7 @@ export class CircleParser extends ClangParser {
         return options;
     }
 
-    static override async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         const possible: CompilerOverrideOptions = [];
         const optionFinder = /^ {4}=([\w+]*) +- +(.*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help']);
@@ -521,7 +529,7 @@ export class CircleParser extends ClangParser {
 }
 
 export class LDCParser extends BaseParser {
-    static override setCompilerSettingsFromOptions(compiler, options) {
+    static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {
         if (this.hasSupport(options, '--fsave-optimization-record')) {
             compiler.compiler.optArg = '--fsave-optimization-record';
             compiler.compiler.supportsOptOutput = true;
@@ -550,13 +558,13 @@ export class LDCParser extends BaseParser {
         }
     }
 
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const options = await this.getOptions(compiler, '--help-hidden');
         this.setCompilerSettingsFromOptions(compiler, options);
         return compiler;
     }
 
-    static override async getOptions(compiler, helpArg, populate = true) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string, populate = true) {
         const optionFinder = /^\s*(--?[\d+,<=>[\]a-z|-]*)\s*(.*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' '));
         const options = result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder) : {};
@@ -568,28 +576,28 @@ export class LDCParser extends BaseParser {
 }
 
 export class ElixirParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '--help');
         return compiler;
     }
 }
 
 export class ErlangParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '-help');
         return compiler;
     }
 }
 
 export class PascalParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '-help');
         return compiler;
     }
 }
 
 export class ICCParser extends GCCParser {
-    static override async setCompilerSettingsFromOptions(compiler, options) {
+    static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {
         const keys = _.keys(options);
         if (this.hasSupport(options, '-masm=')) {
             compiler.compiler.intelAsm = '-masm=intel';
@@ -641,14 +649,14 @@ export class ICCParser extends GCCParser {
         return possible;
     }
 
-    static override async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help']);
         const lines = utils.splitLines(result.stdout);
 
         return this.extractPossibleStdvers(lines);
     }
 
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const results = await Promise.all([this.getOptions(compiler, '-fsyntax-only --help')]);
         const options = Object.assign({}, ...results);
         await this.setCompilerSettingsFromOptions(compiler, options);
@@ -657,20 +665,20 @@ export class ICCParser extends GCCParser {
 }
 
 export class ISPCParser extends BaseParser {
-    static override async setCompilerSettingsFromOptions(compiler, options) {
+    static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {
         if (this.hasSupport(options, '--x86-asm-syntax')) {
             compiler.compiler.intelAsm = '--x86-asm-syntax=intel';
             compiler.compiler.supportsIntel = true;
         }
     }
 
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const options = await this.getOptions(compiler, '--help');
         await this.setCompilerSettingsFromOptions(compiler, options);
         return compiler;
     }
 
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, [helpArg]);
         const optionFinder = /^\s*\[(--?[\d\s()+,/<=>a-z{|}-]*)]\s*(.*)/i;
         const options = result.code === 0 ? this.parseLines(result.stdout + result.stderr, optionFinder) : {};
@@ -680,37 +688,37 @@ export class ISPCParser extends BaseParser {
 }
 
 export class JavaParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '-help');
         return compiler;
     }
 }
 
 export class KotlinParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '-help');
         return compiler;
     }
 }
 
 export class ScalaParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '-help');
         return compiler;
     }
 }
 
 export class VCParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '/help');
         return compiler;
     }
 
-    static override parseLines(stdout, optionRegex) {
+    static override parseLines(stdout: string, optionRegex: RegExp) {
         let previousOption: string | false = false;
-        const options = {};
+        const options: Record<string, Argument> = {};
 
-        const matchLine = line => {
+        const matchLine = (line: string) => {
             if (line.startsWith('/?')) return;
 
             const match = line.match(optionRegex);
@@ -790,14 +798,14 @@ export class VCParser extends BaseParser {
         return possible;
     }
 
-    static override async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, ['/help']);
         const lines = utils.splitLines(result.stdout);
 
         return this.extractPossibleStdvers(lines);
     }
 
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, [helpArg]);
         const optionFinder = /^\s*(\/[\w#+,.:<=>[\]{|}-]*)\s*(.*)/i;
         const options = result.code === 0 ? this.parseLines(result.stdout, optionFinder) : {};
@@ -807,7 +815,7 @@ export class VCParser extends BaseParser {
 }
 
 export class RustParser extends BaseParser {
-    static override async setCompilerSettingsFromOptions(compiler, options) {
+    static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {
         if (this.hasSupport(options, '--color')) {
             if (compiler.compiler.options) compiler.compiler.options += ' ';
             compiler.compiler.options += '--color=always';
@@ -816,7 +824,7 @@ export class RustParser extends BaseParser {
         if (this.hasSupportStartsWith(options, '--target ')) compiler.compiler.supportsTarget = true;
     }
 
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const results = await Promise.all([
             this.getOptions(compiler, '--help'),
             this.getOptions(compiler, '-C help'),
@@ -827,7 +835,7 @@ export class RustParser extends BaseParser {
         return compiler;
     }
 
-    static override async getPossibleEditions(compiler): Promise<string[]> {
+    static override async getPossibleEditions(compiler: BaseCompiler): Promise<string[]> {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help']);
         const re = /--edition ([\d|]*)/;
 
@@ -839,14 +847,14 @@ export class RustParser extends BaseParser {
         return [];
     }
 
-    static override async getPossibleTargets(compiler): Promise<string[]> {
+    static override async getPossibleTargets(compiler: BaseCompiler): Promise<string[]> {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--print', 'target-list']);
         return utils.splitLines(result.stdout).filter(Boolean);
     }
 
-    static parseRustHelpLines(stdout) {
+    static parseRustHelpLines(stdout: string) {
         let previousOption: false | string = false;
-        const options = {};
+        const options: Record<string, Argument> = {};
 
         const doubleOptionFinder = /^\s{4}(-\w, --\w*\s?[\w:=[\]]*)\s*(.*)/i;
         const singleOptionFinder = /^\s{8}(--[\w-]*\s?[\w:=[\]|-]*)\s*(.*)/i;
@@ -895,7 +903,7 @@ export class RustParser extends BaseParser {
         return options;
     }
 
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' '));
         let options = {};
         if (result.code === 0) {
@@ -913,7 +921,7 @@ export class RustParser extends BaseParser {
 }
 
 export class ZksolcParser extends RustParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const options = await this.getOptions(compiler, '--help');
         await this.setCompilerSettingsFromOptions(compiler, options);
         return compiler;
@@ -921,28 +929,28 @@ export class ZksolcParser extends RustParser {
 }
 
 export class MrustcParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '--help');
         return compiler;
     }
 }
 
 export class NimParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '-help');
         return compiler;
     }
 }
 
 export class CrystalParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, 'build');
         return compiler;
     }
 }
 
 export class TableGenParser extends BaseParser {
-    static async getPossibleActions(compiler): Promise<CompilerOverrideOptions> {
+    static async getPossibleActions(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         const result = await compiler.execCompilerCached(compiler.compiler.exe, ['--help']);
         return this.extractPossibleActions(utils.splitLines(result.stdout));
     }
@@ -977,21 +985,21 @@ export class TableGenParser extends BaseParser {
 }
 
 export class TypeScriptNativeParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '--help');
         return compiler;
     }
 }
 
 export class TurboCParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '');
         return compiler;
     }
 }
 
 export class ToitParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '-help');
         return compiler;
     }
@@ -999,7 +1007,7 @@ export class ToitParser extends BaseParser {
 
 export class JuliaParser extends BaseParser {
     // Get help line from wrapper not Julia runtime
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: JuliaCompiler, helpArg: string) {
         const optionFinder = /^\s*(--?[\d+,<=>[\]a-z|-]*)\s*(.*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, [
             compiler.compilerWrapperPath,
@@ -1010,14 +1018,14 @@ export class JuliaParser extends BaseParser {
         return options;
     }
 
-    static override async parse(compiler) {
+    static override async parse(compiler: JuliaCompiler) {
         await this.getOptions(compiler, '--help');
         return compiler;
     }
 }
 
 export class Z88dkParser extends BaseParser {
-    static override async getPossibleTargets(compiler): Promise<string[]> {
+    static override async getPossibleTargets(compiler: BaseCompiler): Promise<string[]> {
         const configPath = path.join(path.dirname(compiler.compiler.exe), '../share/z88dk/lib/config');
         const targets: string[] = [];
         const dir = await fs.readdir(configPath);
@@ -1031,7 +1039,7 @@ export class Z88dkParser extends BaseParser {
 }
 
 export class WasmtimeParser extends BaseParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         await this.getOptions(compiler, '--help');
         return compiler;
     }
@@ -1070,7 +1078,7 @@ export class FlangParser extends ClangParser {
         return 'fortran/default.f90';
     }
 
-    static override setCompilerSettingsFromOptions(compiler, options) {
+    static override async setCompilerSettingsFromOptions(compiler: BaseCompiler, options: Record<string, Argument>) {
         super.setCompilerSettingsFromOptions(compiler, options);
 
         // flang does not allow -emit-llvm to be used as it is with clang
@@ -1086,7 +1094,7 @@ export class FlangParser extends ClangParser {
         compiler.compiler.intelAsm = '-masm=intel';
     }
 
-    static override hasSupport(options, param) {
+    static override hasSupport(options: Record<string, Argument>, param: string) {
         // param is available but we get a warning, so lets not use it
         if (param === '-fcolor-diagnostics') return;
 
@@ -1110,14 +1118,14 @@ export class FlangParser extends ClangParser {
 }
 
 export class GHCParser extends GCCParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const results = await Promise.all([this.getOptions(compiler, '--help')]);
         const options = Object.assign({}, ...results);
         await this.setCompilerSettingsFromOptions(compiler, options);
         return compiler;
     }
 
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const optionFinder1 = /^ {4}(-[\w[\]]+)\s+(.*)/i;
         const optionFinder2 = /^ {4}(-[\w[\]]+)/;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' '));
@@ -1129,31 +1137,31 @@ export class GHCParser extends GCCParser {
 }
 
 export class SwiftParser extends ClangParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const results = await Promise.all([this.getOptions(compiler, '--help')]);
         const options = Object.assign({}, ...results);
         this.setCompilerSettingsFromOptions(compiler, options);
         return compiler;
     }
 
-    static override async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         return [];
     }
 
-    static override async getPossibleTargets(compiler): Promise<string[]> {
+    static override async getPossibleTargets(compiler: BaseCompiler): Promise<string[]> {
         return [];
     }
 }
 
 export class TendraParser extends GCCParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const results = await Promise.all([this.getOptions(compiler, '--help')]);
         const options = Object.assign({}, ...results);
         await this.setCompilerSettingsFromOptions(compiler, options);
         return compiler;
     }
 
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const optionFinder = /^ *(-[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*) : +(.*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, helpArg.split(' '));
         const options = this.parseLines(result.stdout + result.stderr, optionFinder);
@@ -1161,11 +1169,11 @@ export class TendraParser extends GCCParser {
         return options;
     }
 
-    static override async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         return [];
     }
 
-    static override async getPossibleTargets(compiler): Promise<string[]> {
+    static override async getPossibleTargets(compiler: BaseCompiler): Promise<string[]> {
         return [];
     }
 }
@@ -1175,7 +1183,7 @@ export class GolangParser extends GCCParser {
         return 'go/default.go';
     }
 
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const results = await Promise.all([
             this.getOptions(compiler, 'build -o ./output.s "-gcflags=-S --help" ' + this.getExampleFilepath()),
         ]);
@@ -1184,7 +1192,7 @@ export class GolangParser extends GCCParser {
         return compiler;
     }
 
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const optionFinder1 = /^\s*(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)\s+(.*)/i;
         const optionFinder2 = /^\s*(--?[\d#+,<=>[\]a-z|-]* ?[\d+,<=>[\]a-z|-]*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, utils.splitArguments(helpArg), {
@@ -1202,7 +1210,7 @@ export class GnuCobolParser extends GCCParser {
         return ['--help'];
     }
 
-    static override async getPossibleStdvers(compiler: any): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         const possible: CompilerOverrideOptions = [];
         const options = await this.getOptionsStrict(compiler, this.getLanguageSpecificHelpFlags());
         for (const opt in options) {
@@ -1226,14 +1234,14 @@ export class GnuCobolParser extends GCCParser {
 }
 
 export class MadpascalParser extends GCCParser {
-    static override async parse(compiler) {
+    static override async parse(compiler: BaseCompiler) {
         const results = await Promise.all([this.getOptions(compiler, '')]);
         const options = Object.assign({}, ...results);
         await this.setCompilerSettingsFromOptions(compiler, options);
         return compiler;
     }
 
-    static override async getOptions(compiler, helpArg) {
+    static override async getOptions(compiler: BaseCompiler, helpArg: string) {
         const optionFinder = /^(-[\w:<>]*) *(.*)/i;
         const result = await compiler.execCompilerCached(compiler.compiler.exe, []);
         const options = this.parseLines(result.stdout + result.stderr, optionFinder);
@@ -1241,11 +1249,11 @@ export class MadpascalParser extends GCCParser {
         return options;
     }
 
-    static override async getPossibleStdvers(compiler): Promise<CompilerOverrideOptions> {
+    static override async getPossibleStdvers(compiler: BaseCompiler): Promise<CompilerOverrideOptions> {
         return [];
     }
 
-    static override async getPossibleTargets(compiler): Promise<string[]> {
+    static override async getPossibleTargets(compiler: BaseCompiler): Promise<string[]> {
         return ['a8', 'c64', 'c4p', 'raw', 'neo'];
     }
 }
diff --git a/lib/compilers/dosbox-compiler.ts b/lib/compilers/dosbox-compiler.ts
index c0d5313d6..0b317c705 100644
--- a/lib/compilers/dosbox-compiler.ts
+++ b/lib/compilers/dosbox-compiler.ts
@@ -101,7 +101,7 @@ export class DosboxCompiler extends BaseCompiler {
         };
     }
 
-    protected override async execCompilerCached(
+    public override async execCompilerCached(
         compiler: string,
         args: string[],
         options?: ExecutionOptionsWithEnv,
diff --git a/lib/compilers/dotnet.ts b/lib/compilers/dotnet.ts
index 230c3df4d..beca56e99 100644
--- a/lib/compilers/dotnet.ts
+++ b/lib/compilers/dotnet.ts
@@ -359,9 +359,7 @@ using System.Reflection;
         await fs.writeFile(assemblyInfoPath, assemblyInfo);
 
         options.push(`-define:${defines.join(';')}`, `-out:${outputFilename}`, inputFilename, assemblyInfoPath);
-        const respFile = path.join(programDir, 'CompilerExplorer.rsp');
-        await fs.writeFile(respFile, options.join('\n'));
-        return await super.runCompiler(compiler, [this.cscPath, `@${respFile}`], inputFilename, execOptions);
+        return await super.runCompiler(compiler, [this.cscPath, ...options], inputFilename, execOptions);
     }
 
     async runVbc(
@@ -429,9 +427,7 @@ Imports System.Reflection
         await fs.writeFile(assemblyInfoPath, assemblyInfo);
 
         options.push(`-define:${defines.join(',')}`, `-out:${outputFilename}`, inputFilename, assemblyInfoPath);
-        const respFile = path.join(programDir, 'CompilerExplorer.rsp');
-        await fs.writeFile(respFile, options.join('\n'));
-        return await super.runCompiler(compiler, [this.vbcPath, `@${respFile}`], inputFilename, execOptions);
+        return await super.runCompiler(compiler, [this.vbcPath, ...options], inputFilename, execOptions);
     }
 
     async runFsc(
@@ -497,9 +493,7 @@ do()
             assemblyInfoPath,
             inputFilename,
         );
-        const respFile = path.join(programDir, 'CompilerExplorer.rsp');
-        await fs.writeFile(respFile, options.join('\n'));
-        return await super.runCompiler(compiler, [this.fscPath, `@${respFile}`], inputFilename, execOptions);
+        return await super.runCompiler(compiler, [this.fscPath, ...options], inputFilename, execOptions);
     }
 
     async runIlasm(
diff --git a/lib/compilers/julia.ts b/lib/compilers/julia.ts
index 4600a3622..6e710ece2 100644
--- a/lib/compilers/julia.ts
+++ b/lib/compilers/julia.ts
@@ -35,7 +35,7 @@ import * as utils from '../utils.js';
 import {JuliaParser} from './argument-parsers.js';
 
 export class JuliaCompiler extends BaseCompiler {
-    private compilerWrapperPath: string;
+    public compilerWrapperPath: string;
 
     static get key() {
         return 'julia';


Test patch:
diff --git a/lib/compilers/fake-for-test.ts b/lib/compilers/fake-for-test.ts
index bb9c3c859..5c4c371ec 100644
--- a/lib/compilers/fake-for-test.ts
+++ b/lib/compilers/fake-for-test.ts
@@ -54,6 +54,7 @@ export class FakeCompiler implements ICompiler {
 
     initialise(mtime: Date, clientOptions: any, isPrediscovered: boolean) {
         throw new Error('Method not implemented.');
+        return null;
     }
 
     getInfo() {
diff --git a/test/compilers/argument-parsers-tests.ts b/test/compilers/argument-parsers-tests.ts
index 610cf12dd..225f30d63 100644
--- a/test/compilers/argument-parsers-tests.ts
+++ b/test/compilers/argument-parsers-tests.ts
@@ -50,9 +50,9 @@ function makeCompiler(stdout?: string, stderr?: string, code?: number) {
 }
 
 describe('option parser', () => {
-    it('should do nothing for the base parser', () => {
+    it('should do nothing for the base parser', async () => {
         const compiler = makeCompiler();
-        expect(BaseParser.parse(compiler)).toEqual(compiler);
+        await expect(BaseParser.parse(compiler)).resolves.toEqual(compiler);
     });
     it('should handle empty options', async () => {
         await expect(BaseParser.getOptions(makeCompiler(), '')).resolves.toEqual({});