aboutsummaryrefslogtreecommitdiff
path: root/lib/compilers
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compilers')
-rw-r--r--lib/compilers/_all.js1
-rw-r--r--lib/compilers/golang.ts (renamed from lib/compilers/golang.js)136
-rw-r--r--lib/compilers/hlsl.ts (renamed from lib/compilers/hlsl.js)25
-rw-r--r--lib/compilers/rga.ts276
-rw-r--r--lib/compilers/rust.ts32
-rw-r--r--lib/compilers/wine-vc.js5
-rw-r--r--lib/compilers/zig.js14
7 files changed, 401 insertions, 88 deletions
diff --git a/lib/compilers/_all.js b/lib/compilers/_all.js
index 9abb0e5ef..3224acc03 100644
--- a/lib/compilers/_all.js
+++ b/lib/compilers/_all.js
@@ -75,6 +75,7 @@ export {PonyCompiler} from './pony';
export {PPCICompiler} from './ppci';
export {PtxAssembler} from './ptxas';
export {PythonCompiler} from './python';
+export {RGACompiler} from './rga';
export {RubyCompiler} from './ruby';
export {RustcCgGCCCompiler} from './rustc-cg-gcc';
export {RustCompiler} from './rust';
diff --git a/lib/compilers/golang.js b/lib/compilers/golang.ts
index 8aa0fd985..b0abb1498 100644
--- a/lib/compilers/golang.js
+++ b/lib/compilers/golang.ts
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, Compiler Explorer Authors
+// Copyright (c) 2022, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -24,6 +24,7 @@
import _ from 'underscore';
+import {ResultLine} from '../../types/resultline/resultline.interfaces';
import {BaseCompiler} from '../base-compiler';
import * as utils from '../utils';
@@ -34,40 +35,61 @@ import {ClangParser} from './argument-parsers';
// x86 -> j, b
// arm -> cb, tb
// s390x -> cmpb, cmpub
-const jumpRe = /^(j|b|cb|tb|cmpb|cmpub).*/i;
+const JUMP_RE = /^(j|b|cb|tb|cmpb|cmpub).*/i;
+const LINE_RE = /^\s+(0[Xx]?[\dA-Za-z]+)?\s?(\d+)\s*\(([^:]+):(\d+)\)\s*([A-Z]+)(.*)/;
+const UNKNOWN_RE = /^\s+(0[Xx]?[\dA-Za-z]+)?\s?(\d+)\s*\(<unknown line number>\)\s*([A-Z]+)(.*)/;
+const FUNC_RE = /TEXT\s+[".]*(\S+)\(SB\)/;
+const LOGGING_RE = /^[^:]+:\d+:(\d+:)?\s.*/;
+const DECIMAL_RE = /(\s+)(\d+)(\s?)$/;
+
+type GoEnv = {
+ GOROOT?: string;
+ GOARCH?: string;
+ GOOS?: string;
+};
export class GolangCompiler extends BaseCompiler {
+ private readonly GOENV: GoEnv;
+
static get key() {
return 'golang';
}
constructor(compilerInfo, env) {
super(compilerInfo, env);
- this.goroot = this.compilerProps(`compiler.${this.compiler.id}.goroot`);
- this.goarch = this.compilerProps(`compiler.${this.compiler.id}.goarch`);
- this.goos = this.compilerProps(`compiler.${this.compiler.id}.goos`);
+ const goroot = this.compilerProps(`compiler.${this.compiler.id}.goroot`);
+ const goarch = this.compilerProps(`compiler.${this.compiler.id}.goarch`);
+ const goos = this.compilerProps(`compiler.${this.compiler.id}.goos`);
+
+ this.GOENV = {};
+ if (goroot) {
+ this.GOENV.GOROOT = goroot;
+ }
+ if (goarch) {
+ this.GOENV.GOARCH = goarch;
+ }
+ if (goos) {
+ this.GOENV.GOOS = goos;
+ }
}
- convertNewGoL(code) {
- const re = /^\s+(0[Xx]?[\dA-Za-z]+)?\s?(\d+)\s*\(([^:]+):(\d+)\)\s*([A-Z]+)(.*)/;
- const reUnknown = /^\s+(0[Xx]?[\dA-Za-z]+)?\s?(\d+)\s*\(<unknown line number>\)\s*([A-Z]+)(.*)/;
- const reFunc = /TEXT\s+[".]*(\S+)\(SB\)/;
- let prevLine = null;
- let file = null;
+ convertNewGoL(code: ResultLine[]): string {
+ let prevLine: string | null = null;
+ let file: string | null = null;
let fileCount = 0;
- let func = null;
- const funcCollisions = {};
- const labels = {};
- const usedLabels = {};
+ let func: string | null = null;
+ const funcCollisions: Record<string, number> = {};
+ const labels: Record<string, boolean> = {};
+ const usedLabels: Record<string, boolean> = {};
const lines = code.map(obj => {
- let pcMatch = null;
- let fileMatch = null;
- let lineMatch = null;
- let ins = null;
- let args = null;
+ let pcMatch: string | null = null;
+ let fileMatch: string | null = null;
+ let lineMatch: string | null = null;
+ let ins: string | null = null;
+ let args: string | null = null;
const line = obj.text;
- let match = line.match(re);
+ let match = line.match(LINE_RE);
if (match) {
pcMatch = match[2];
fileMatch = match[3];
@@ -75,17 +97,17 @@ export class GolangCompiler extends BaseCompiler {
ins = match[5];
args = match[6];
} else {
- match = line.match(reUnknown);
+ match = line.match(UNKNOWN_RE);
if (match) {
pcMatch = match[2];
ins = match[3];
args = match[4];
} else {
- return null;
+ return [];
}
}
- match = line.match(reFunc);
+ match = line.match(FUNC_RE);
if (match) {
// Normalize function name.
func = match[1].replace(/[()*.]+/g, '_');
@@ -103,12 +125,12 @@ export class GolangCompiler extends BaseCompiler {
funcCollisions[func] = collisions;
}
- let res = [];
+ const res: string[] = [];
if (pcMatch && !labels[pcMatch]) {
// Create pseudo-label.
let label = pcMatch.replace(/^0{0,4}/, '');
let suffix = '';
- if (funcCollisions[func] > 0) {
+ if (func && funcCollisions[func] > 0) {
suffix = `_${funcCollisions[func]}`;
}
@@ -130,32 +152,37 @@ export class GolangCompiler extends BaseCompiler {
prevLine = lineMatch;
}
- args = this.replaceJump(func, funcCollisions[func], ins, args, usedLabels);
- res.push(`\t${ins}${args}`);
+ if (func) {
+ args = this.replaceJump(func, funcCollisions[func], ins, args, usedLabels);
+ res.push(`\t${ins}${args}`);
+ }
return res;
});
// Find unused pseudo-labels so they can be filtered out.
const unusedLabels = _.mapObject(labels, (val, key) => !usedLabels[key]);
- return _.chain(lines)
- .flatten()
- .compact()
+ return lines
+ .flat()
.filter(line => !unusedLabels[line])
- .value()
.join('\n');
}
- replaceJump(func, collisions, ins, args, usedLabels) {
+ replaceJump(
+ func: string,
+ collisions: number,
+ ins: string,
+ args: string,
+ usedLabels: Record<string, boolean>,
+ ): string {
// Check if last argument is a decimal number.
- const re = /(\s+)(\d+)(\s?)$/;
- const match = args.match(re);
+ const match = args.match(DECIMAL_RE);
if (!match) {
return args;
}
// Check instruction has a jump prefix
- if (jumpRe.test(ins)) {
+ if (JUMP_RE.test(ins)) {
let label = `${func}_pc${match[2]}`;
if (collisions > 0) {
label += `_${collisions}`;
@@ -167,16 +194,16 @@ export class GolangCompiler extends BaseCompiler {
return args;
}
- extractLogging(stdout) {
- let filepath = `./${this.compileFilename}`;
- const reLogging = /^[^:]+:\d+:(\d+:)?\s.*/;
+ extractLogging(stdout: ResultLine[]): string {
+ const filepath = `./${this.compileFilename}`;
+
return stdout
- .filter(obj => obj.text.match(reLogging))
+ .filter(obj => obj.text.match(LOGGING_RE))
.map(obj => obj.text.replace(filepath, '<source>'))
.join('\n');
}
- async postProcess(result) {
+ override async postProcess(result) {
let out = result.stderr;
if (this.compiler.id === '6g141') {
out = result.stdout;
@@ -185,14 +212,14 @@ export class GolangCompiler extends BaseCompiler {
result.asm = this.convertNewGoL(out);
result.stderr = null;
result.stdout = utils.parseOutput(logging, result.inputFilename);
- return [result, ''];
+ return Promise.all([result, '']);
}
- getSharedLibraryPathsAsArguments() {
+ override getSharedLibraryPathsAsArguments() {
return [];
}
- optionsForFilter(filters, outputFilename, userOptions) {
+ override optionsForFilter(filters, outputFilename, userOptions) {
// If we're dealing with an older version...
if (this.compiler.id === '6g141') {
return ['tool', '6g', '-g', '-o', outputFilename, '-S'];
@@ -206,7 +233,7 @@ export class GolangCompiler extends BaseCompiler {
}
}
- filterUserOptions(userOptions) {
+ override filterUserOptions(userOptions) {
if (this.compiler.id === '6g141') {
return userOptions;
}
@@ -214,21 +241,14 @@ export class GolangCompiler extends BaseCompiler {
return [];
}
- getDefaultExecOptions() {
- const execOptions = super.getDefaultExecOptions();
- if (this.goroot) {
- execOptions.env.GOROOT = this.goroot;
- }
- if (this.goarch) {
- execOptions.env.GOARCH = this.goarch;
- }
- if (this.goos) {
- execOptions.env.GOOS = this.goos;
- }
- return execOptions;
+ override getDefaultExecOptions() {
+ return {
+ ...super.getDefaultExecOptions(),
+ ...this.GOENV,
+ };
}
- getArgumentParser() {
+ override getArgumentParser() {
return ClangParser;
}
}
diff --git a/lib/compilers/hlsl.js b/lib/compilers/hlsl.ts
index 25858839e..2925a0154 100644
--- a/lib/compilers/hlsl.js
+++ b/lib/compilers/hlsl.ts
@@ -24,6 +24,7 @@
import path from 'path';
+import {ParseFilters} from '../../types/features/filters.interfaces';
import {BaseCompiler} from '../base-compiler';
export class HLSLCompiler extends BaseCompiler {
@@ -31,21 +32,39 @@ export class HLSLCompiler extends BaseCompiler {
return 'hlsl';
}
- constructor(info, env) {
+ constructor(info: any, env: any) {
super(info, env);
this.compiler.supportsIntel = false;
}
/* eslint-disable no-unused-vars */
- optionsForFilter(filters, outputFilename) {
+ override optionsForFilter(filters: ParseFilters, outputFilename: string, userOptions?: string[]): string[] {
return [
+ '-Zi', // Embed debug information to get DXIL line associations
+ '-Qembed_debug', // Silences the warning associated with embedded debug information
`-Fc ${outputFilename}`, // Output object
];
}
/* eslint-enable no-unused-vars */
- getIrOutputFilename(inputFilename) {
+ override filterUserOptions(userOptions: any) {
+ // RGA supports a non-standard flag --asic [ASIC] which must be removed when compiling with DXC
+ const options = userOptions.slice(0);
+ // Scan for the RGA-specific argument --asic and strip it and its corresponding argument
+ // Assumes the argument exists at most once (compilation will fail if supplied more than
+ // once regardless)
+ for (let i = 0; i !== options.length; ++i) {
+ const option = options[i];
+ if (option === '--asic') {
+ options.splice(i, 2);
+ break;
+ }
+ }
+ return options;
+ }
+
+ override getIrOutputFilename(inputFilename: string) {
return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase).replace('.s', '.dxil');
}
}
diff --git a/lib/compilers/rga.ts b/lib/compilers/rga.ts
new file mode 100644
index 000000000..aec9d2084
--- /dev/null
+++ b/lib/compilers/rga.ts
@@ -0,0 +1,276 @@
+// Copyright (c) 2022, Compiler Explorer Authors
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+import path from 'path';
+
+import {readdir, readFile, rename, writeFile} from 'fs-extra';
+
+import {CompilationResult, ExecutionOptions} from '../../types/compilation/compilation.interfaces';
+import {ParseFilters} from '../../types/features/filters.interfaces';
+import {BaseCompiler} from '../base-compiler';
+import * as exec from '../exec';
+import {logger} from '../logger';
+
+interface ASICSelection {
+ asic?: string;
+ error?: string;
+ printASICs?: boolean;
+}
+
+// RGA := Radeon GPU Analyzer
+export class RGACompiler extends BaseCompiler {
+ private dxcPath: string;
+
+ static get key() {
+ return 'rga';
+ }
+
+ constructor(info: any, env: any) {
+ super(info, env);
+
+ this.compiler.supportsIntel = false;
+ this.dxcPath = this.compilerProps(`compiler.${this.compiler.id}.dxcPath`);
+ logger.debug(`RGA compiler ${this.compiler.id} configured to use DXC at ${this.dxcPath}`);
+ }
+
+ override optionsForFilter(filters: ParseFilters, outputFilename: any, userOptions?: any): any[] {
+ return [outputFilename];
+ }
+
+ extractASIC(dxcArgs: string[]): ASICSelection {
+ // Scan dxc args for an `--asic` argument that should be stripped and passed later to RGA
+ // Default to RDNA2
+ let asic = 'gfx1030';
+ let printASICs = true;
+ for (let i = 0; i !== dxcArgs.length; ++i) {
+ const arg = dxcArgs[i];
+ if (arg === '--asic') {
+ // NOTE: the last arguments are the input source file and -spirv, so check
+ // if --asic immediately precedes that
+ if (i === dxcArgs.length - 3) {
+ return {
+ error: '--asic flag supplied without subsequent ASIC!',
+ };
+ }
+ asic = dxcArgs[i + 1];
+ // Do a quick sanity check to determine if a valid ASIC was supplied
+ if (!asic.startsWith('gfx')) {
+ return {
+ error: `The argument immediately following --asic doesn't appear to be a valid ASIC.
+Please supply an ASIC from the following options:`,
+ printASICs: true,
+ };
+ }
+ // Remove these two arguments from the dxcArgs list
+ dxcArgs.splice(i, 2);
+
+ // If the user supplied a specific ASIC, don't bother printing available ASIC options
+ printASICs = false;
+ break;
+ }
+ }
+
+ return {
+ asic,
+ printASICs,
+ };
+ }
+
+ execTime(startTime: bigint, endTime: bigint): string {
+ return ((endTime - startTime) / BigInt(1000000)).toString();
+ }
+
+ override async runCompiler(
+ compiler: string,
+ options: string[],
+ inputFilename: string,
+ execOptions: ExecutionOptions,
+ ): Promise<CompilationResult> {
+ if (!execOptions) {
+ execOptions = this.getDefaultExecOptions();
+ }
+
+ if (!execOptions.customCwd) {
+ execOptions.customCwd = path.dirname(inputFilename);
+ }
+
+ const result = await this.execDXCandRGA(compiler, options, execOptions);
+ result.inputFilename = inputFilename;
+ const transformedInput = result.filenameTransform(inputFilename);
+ this.parseCompilationOutput(result, transformedInput);
+ return result;
+ }
+
+ async execDXCandRGA(filepath: string, args: string[], execOptions: ExecutionOptions): Promise<any> {
+ // RGA is invoked in two steps. First, DXC is invoked to compile the SPIR-V output of the HLSL file.
+ // Next, RGA is invoked to consume the SPIR-V output and produce the requested ISA.
+
+ // Track the total time spent instead of relying on executeDirect's internal timing facility
+ const startTime = process.hrtime.bigint();
+
+ // The first argument is the target output file
+ const outputFile = args[0];
+ const outputDir = path.dirname(outputFile);
+ const spvTemp = 'output.spv.txt';
+ logger.debug(`Intermediate SPIR-V output: ${spvTemp}`);
+
+ const dxcArgs = args.slice(1);
+ if (!dxcArgs.includes('-spirv')) {
+ dxcArgs.push('-spirv');
+ }
+ logger.debug(`DXC args: ${dxcArgs}`);
+
+ const asicSelection = this.extractASIC(dxcArgs);
+ if (asicSelection.error) {
+ // Invalid user ASIC selected, bail out immediately
+ const endTime = process.hrtime.bigint();
+
+ // Synthesize a faux-execution result (see promise resolution code in executeDirect)
+ return {
+ code: -1,
+ okToCache: true,
+ filenameTransform: x => x,
+ stdout: asicSelection.error,
+ execTime: this.execTime(startTime, endTime),
+ };
+ }
+
+ const dxcResult = await exec.execute(this.dxcPath, dxcArgs, execOptions);
+ if (dxcResult.code !== 0) {
+ // Failed to compile SPIR-V intermediate product. Exit immediately with DXC invocation result.
+ const endTime = process.hrtime.bigint();
+ dxcResult.execTime = this.execTime(startTime, endTime);
+ return dxcResult;
+ }
+
+ try {
+ await writeFile(path.join(outputDir, spvTemp), dxcResult.stdout);
+ } catch (e) {
+ const endTime = process.hrtime.bigint();
+ return {
+ code: -1,
+ okToCache: true,
+ filenameTransform: x => x,
+ stdout: 'Failed to emit intermediate SPIR-V result.',
+ execTime: this.execTime(startTime, endTime),
+ };
+ }
+
+ let registerAnalysisFile = 'livereg.txt';
+ const rgaArgs = [
+ '-s',
+ 'vk-spv-txt-offline',
+ '-c',
+ asicSelection.asic,
+ '--isa',
+ outputFile,
+ '--livereg',
+ registerAnalysisFile,
+ spvTemp,
+ ];
+ logger.debug(`RGA args: ${rgaArgs}`);
+
+ const rgaResult = await exec.execute(filepath, rgaArgs, execOptions);
+ if (rgaResult.code !== 0) {
+ // Failed to compile AMD ISA
+ const endTime = process.hrtime.bigint();
+ rgaResult.execTime = this.execTime(startTime, endTime);
+ return rgaResult;
+ }
+
+ // RGA doesn't emit the exact file we requested. It prepends the requested GPU
+ // architecture and appends the shader type (with underscore separators). Here,
+ // we rename the generated file to the output file Compiler Explorer expects.
+
+ const files = await readdir(outputDir, {encoding: 'utf-8'});
+ for (const file of files) {
+ if (file.startsWith((asicSelection.asic as string) + '_output')) {
+ await rename(path.join(outputDir, file), outputFile);
+
+ registerAnalysisFile = path.join(outputDir, file.replace('output', 'livereg').replace('.s', '.txt'));
+ // The register analysis file contains a legend, and register liveness data
+ // for each line of disassembly. Interleave those lines into the final output
+ // as assembly comments.
+ const asm = await readFile(outputFile, 'utf-8');
+ const asmLines = asm.split(/\r?\n/);
+ const analysis = await readFile(registerAnalysisFile, 'utf-8');
+ const analysisLines = analysis.split(/\r?\n/);
+
+ // The first few lines of the register analysis are the legend. Emit those lines
+ // as comments at the start of the output.
+ let analysisOffset = analysisLines.indexOf('');
+ analysisOffset += 3;
+ const epilogueOffset = analysisLines.indexOf('', analysisOffset);
+ const outputAsm = analysisLines.slice(epilogueOffset + 1).map(line => `; ${line}`);
+ outputAsm.push(...analysisLines.slice(0, analysisOffset).map(line => `; ${line}`), '\n');
+
+ let asmOffset = asmLines.indexOf('');
+ outputAsm.push(...asmLines.slice(0, asmOffset));
+ asmOffset += 1;
+
+ // Perform the interleave
+ for (let i = 0; i !== asmOffset + asmLines.length; ++i) {
+ if (i + analysisOffset >= epilogueOffset) {
+ outputAsm.push(...asmLines.slice(i));
+ break;
+ }
+
+ // Check if this line of assembly corresponds to a label. If so, emit the asm line
+ // and continue from the next line (the register analysis file operates on instructions,
+ // and labels are not considered instructions)
+ if (asmLines[i + asmOffset].startsWith('label')) {
+ outputAsm.push(asmLines[i + asmOffset]);
+ ++asmOffset;
+ --i;
+ continue;
+ }
+
+ outputAsm.push(`; ${analysisLines[i + analysisOffset]}`, asmLines[i + asmOffset]);
+ }
+
+ await writeFile(outputFile, outputAsm.join('\n'));
+
+ if (asicSelection.printASICs) {
+ rgaResult.stdout += `ISA compiled with the default AMD ASIC (Radeon RX 6800 series RDNA2).
+To override this, pass --asic [ASIC] to the options above (nonstandard DXC option),
+where [ASIC] corresponds to one of the following options:`;
+
+ const asics = await exec.execute(filepath, ['-s', 'vk-spv-txt-offline', '-l'], execOptions);
+ rgaResult.stdout += '\n';
+ rgaResult.stdout += asics.stdout;
+ }
+
+ const endTime = process.hrtime.bigint();
+ rgaResult.execTime = this.execTime(startTime, endTime);
+ return rgaResult;
+ }
+ }
+
+ // Arriving here means the expected ISA result wasn't emitted. Synthesize an error.
+ const endTime = process.hrtime.bigint();
+ rgaResult.execTime = this.execTime(startTime, endTime);
+ rgaResult.stdout += `\nRGA didn't emit expected ISA output.`;
+ return rgaResult;
+ }
+}
diff --git a/lib/compilers/rust.ts b/lib/compilers/rust.ts
index 89b52533d..f1d0d3a89 100644
--- a/lib/compilers/rust.ts
+++ b/lib/compilers/rust.ts
@@ -35,6 +35,7 @@ import {RustParser} from './argument-parsers';
export class RustCompiler extends BaseCompiler {
linker: string;
+
static get key() {
return 'rust';
}
@@ -69,24 +70,19 @@ export class RustCompiler extends BaseCompiler {
override getIncludeArguments(libraries) {
const includeFlag = '--extern';
- return _.flatten(
- _.map(libraries, selectedLib => {
- const foundVersion = this.findLibVersion(selectedLib);
- if (!foundVersion) return false;
- if (!foundVersion.name) return false;
- const list: string[] = [];
- const lowercaseLibName = foundVersion.name.replaceAll('-', '_');
- for (const rlib of foundVersion.path) {
- list.push(
- includeFlag,
- `${lowercaseLibName}=${foundVersion.name}/build/debug/${rlib}`,
- '-L',
- `dependency=${foundVersion.name}/build/debug/deps`,
- );
- }
- return list;
- }),
- );
+ return libraries.flatMap(selectedLib => {
+ const foundVersion = this.findLibVersion(selectedLib);
+ if (!foundVersion || !foundVersion.name) return [];
+ const lowercaseLibName = foundVersion.name.replaceAll('-', '_');
+ return foundVersion.path.flatMap(rlib => {
+ return [
+ includeFlag,
+ `${lowercaseLibName}=${foundVersion.name}/build/debug/${rlib}`,
+ '-L',
+ `dependency=${foundVersion.name}/build/debug/deps`,
+ ];
+ });
+ });
}
override orderArguments(
diff --git a/lib/compilers/wine-vc.js b/lib/compilers/wine-vc.js
index 653f6289e..be60b94d7 100644
--- a/lib/compilers/wine-vc.js
+++ b/lib/compilers/wine-vc.js
@@ -51,7 +51,10 @@ export class WineVcCompiler extends BaseCompiler {
execOptions = this.getDefaultExecOptions();
}
- execOptions.customCwd = path.dirname(inputFilename).substr(2);
+ execOptions.customCwd = path.dirname(inputFilename);
+ if (inputFilename.startsWith('Z:')) {
+ execOptions.customCwd = execOptions.customCwd.substr(2);
+ }
return super.runCompiler(compiler, options, inputFilename, execOptions);
}
diff --git a/lib/compilers/zig.js b/lib/compilers/zig.js
index 1a9d0512d..d524fc1de 100644
--- a/lib/compilers/zig.js
+++ b/lib/compilers/zig.js
@@ -132,14 +132,12 @@ export class ZigCompiler extends BaseCompiler {
}
getIncludeArguments(libraries) {
- return _.flatten(
- _.map(libraries, selectedLib => {
- const foundVersion = this.findLibVersion(selectedLib);
- if (!foundVersion) return false;
- // Zig should not have more than 1 path
- return ['--pkg-begin', foundVersion.name, foundVersion.path, '--pkg-end'];
- }),
- );
+ return libraries.flatMap(selectedLib => {
+ const foundVersion = this.findLibVersion(selectedLib);
+ if (!foundVersion) return [];
+ // Zig should not have more than 1 path, but it's still an array so spread it
+ return ['--pkg-begin', foundVersion.name, ...foundVersion.path, '--pkg-end'];
+ });
}
getIrOutputFilename(inputFilename) {