Skip to content

Commit

Permalink
Various enhancements for dotnet (#4362)
Browse files Browse the repository at this point in the history
  • Loading branch information
hez2010 authored and mattgodbolt committed Jan 4, 2023
1 parent 64bd250 commit 61aad90
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 79 deletions.
26 changes: 14 additions & 12 deletions etc/config/csharp.defaults.properties
@@ -1,17 +1,19 @@
compilers=dotnet6csharp:dotnet7csharp
compilers=&csharpdef
supportsBinary=true
needsMulti=false
compilerType=csharp
defaultCompiler=dotnet7csharp
defaultCompiler=dotnet7csharpdef

compiler.dotnet6csharp.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
compiler.dotnet6csharp.name=.NET 6.0.403
compiler.dotnet6csharp.clrDir=/opt/compiler-explorer/dotnet-v6.0.11
compiler.dotnet6csharp.buildConfig=Release
compiler.dotnet6csharp.langVersion=latest
group.csharpdef.compilers=dotnet6csharpdef:dotnet7csharpdef

compiler.dotnet7csharp.exe=/opt/compiler-explorer/dotnet-v7.0.0/.dotnet/dotnet
compiler.dotnet7csharp.name=.NET 7.0.100
compiler.dotnet7csharp.clrDir=/opt/compiler-explorer/dotnet-v7.0.0
compiler.dotnet7csharp.buildConfig=Release
compiler.dotnet7csharp.langVersion=latest
compiler.dotnet6csharpdef.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
compiler.dotnet6csharpdef.name=.NET 6.0.403
compiler.dotnet6csharpdef.clrDir=/opt/compiler-explorer/dotnet-v6.0.11
compiler.dotnet6csharpdef.buildConfig=Release
compiler.dotnet6csharpdef.langVersion=latest

compiler.dotnet7csharpdef.exe=/opt/compiler-explorer/dotnet-v7.0.0/.dotnet/dotnet
compiler.dotnet7csharpdef.name=.NET 7.0.100
compiler.dotnet7csharpdef.clrDir=/opt/compiler-explorer/dotnet-v7.0.0
compiler.dotnet7csharpdef.buildConfig=Release
compiler.dotnet7csharpdef.langVersion=latest
26 changes: 14 additions & 12 deletions etc/config/fsharp.defaults.properties
@@ -1,17 +1,19 @@
compilers=dotnet6fsharp:dotnet7fsharp
compilers=&fsharpdef
supportsBinary=true
needsMulti=false
compilerType=fsharp
defaultCompiler=dotnet7fsharp
defaultCompiler=dotnet7fsharpdef

compiler.dotnet6fsharp.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
compiler.dotnet6fsharp.name=.NET 6.0.403
compiler.dotnet6fsharp.clrDir=/opt/compiler-explorer/dotnet-v6.0.11
compiler.dotnet6fsharp.buildConfig=Release
compiler.dotnet6fsharp.langVersion=latest
group.fsharpdef.compilers=dotnet6fsharpdef:dotnet7fsharpdef

compiler.dotnet7fsharp.exe=/opt/compiler-explorer/dotnet-v7.0.0/.dotnet/dotnet
compiler.dotnet7fsharp.name=.NET 7.0.100
compiler.dotnet7fsharp.clrDir=/opt/compiler-explorer/dotnet-v7.0.0
compiler.dotnet7fsharp.buildConfig=Release
compiler.dotnet7fsharp.langVersion=latest
compiler.dotnet6fsharpdef.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
compiler.dotnet6fsharpdef.name=.NET 6.0.403
compiler.dotnet6fsharpdef.clrDir=/opt/compiler-explorer/dotnet-v6.0.11
compiler.dotnet6fsharpdef.buildConfig=Release
compiler.dotnet6fsharpdef.langVersion=latest

compiler.dotnet7fsharpdef.exe=/opt/compiler-explorer/dotnet-v7.0.0/.dotnet/dotnet
compiler.dotnet7fsharpdef.name=.NET 7.0.100
compiler.dotnet7fsharpdef.clrDir=/opt/compiler-explorer/dotnet-v7.0.0
compiler.dotnet7fsharpdef.buildConfig=Release
compiler.dotnet7fsharpdef.langVersion=latest
26 changes: 14 additions & 12 deletions etc/config/vb.defaults.properties
@@ -1,17 +1,19 @@
compilers=dotnet6vb:dotnet7vb
compilers=&vbdef
supportsBinary=true
needsMulti=false
compilerType=vb
defaultCompiler=dotnet7vb
defaultCompiler=dotnet7vbdef

compiler.dotnet6vb.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
compiler.dotnet6vb.name=.NET 6.0.403
compiler.dotnet6vb.clrDir=/opt/compiler-explorer/dotnet-v6.0.11
compiler.dotnet6vb.buildConfig=Release
compiler.dotnet6vb.langVersion=latest
group.vbdef.compilers=dotnet6vbdef:dotnet7vbdef

compiler.dotnet7vb.exe=/opt/compiler-explorer/dotnet-v7.0.0/.dotnet/dotnet
compiler.dotnet7vb.name=.NET 7.0.100
compiler.dotnet7vb.clrDir=/opt/compiler-explorer/dotnet-v7.0.0
compiler.dotnet7vb.buildConfig=Release
compiler.dotnet7vb.langVersion=latest
compiler.dotnet6vbdef.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
compiler.dotnet6vbdef.name=.NET 6.0.403
compiler.dotnet6vbdef.clrDir=/opt/compiler-explorer/dotnet-v6.0.11
compiler.dotnet6vbdef.buildConfig=Release
compiler.dotnet6vbdef.langVersion=latest

compiler.dotnet7vbdef.exe=/opt/compiler-explorer/dotnet-v7.0.0/.dotnet/dotnet
compiler.dotnet7vbdef.name=.NET 7.0.100
compiler.dotnet7vbdef.clrDir=/opt/compiler-explorer/dotnet-v7.0.0
compiler.dotnet7vbdef.buildConfig=Release
compiler.dotnet7vbdef.langVersion=latest
94 changes: 51 additions & 43 deletions lib/compilers/dotnet.ts
Expand Up @@ -114,74 +114,88 @@ class DotNetCompiler extends BaseCompiler {
await fs.writeFile(projectFilePath, projectFileContent);
}

setCompilerExecOptions(execOptions: ExecutionOptions, programDir: string) {
if (!execOptions) {
execOptions = this.getDefaultExecOptions();
}

// See https://github.com/dotnet/runtime/issues/50391 - the .NET runtime tries to make a 2TB memfile if we have
// this feature enabled (which is on by default on .NET 7) This blows out our nsjail sandbox limit, so for now
// we disable it.
execOptions.env.DOTNET_EnableWriteXorExecute = '0';
// Disable any phone-home.
execOptions.env.DOTNET_CLI_TELEMETRY_OPTOUT = 'true';
// Some versions of .NET complain if they can't work out what the user's directory is. We force it to the output
// directory here.
execOptions.env.DOTNET_CLI_HOME = programDir;
// Place nuget packages in the output directory.
execOptions.env.NUGET_PACKAGES = path.join(programDir, '.nuget');
// Try to be less chatty
execOptions.env.DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 'true';
execOptions.env.DOTNET_NOLOGO = 'true';

execOptions.customCwd = programDir;
}

override async buildExecutable(compiler, options, inputFilename, execOptions) {
const dirPath = path.dirname(inputFilename);
const inputFilenameSafe = this.filename(inputFilename);
const sourceFile = path.basename(inputFilenameSafe);
await this.writeProjectfile(dirPath, true, sourceFile);

return super.buildExecutable(compiler, options, inputFilename, execOptions);
return await this.buildToDll(compiler, options, inputFilename, execOptions);
}

override async doCompilation(inputFilename, dirPath, key, options, filters, backendOptions, libraries, tools) {
const inputFilenameSafe = this.filename(inputFilename);
const sourceFile = path.basename(inputFilenameSafe);
await this.writeProjectfile(dirPath, filters.binary, sourceFile);

return super.doCompilation(inputFilename, dirPath, key, options, filters, backendOptions, libraries, tools);
}

override async runCompiler(
async buildToDll(
compiler: string,
options: string[],
inputFilename: string,
execOptions: ExecutionOptions,
): Promise<CompilationResult> {
if (!execOptions) {
execOptions = this.getDefaultExecOptions();
}

const programDir = path.dirname(inputFilename);

const crossgen2Path = path.join(this.clrBuildDir, 'crossgen2', 'crossgen2.dll');
const nugetConfigPath = path.join(programDir, 'nuget.config');

const programOutputPath = path.join(programDir, 'bin', this.buildConfig, this.targetFramework);
const programDllPath = path.join(programOutputPath, 'CompilerExplorer.dll');

const nugetConfigFileContent = `<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<packageSource key="fsharp" value="${path.join(
this.sdkBaseDir,
this.sdkVersion,
'/FSharp/library-packs/',
)}" />
</packageSources>
</configuration>
`;

// See https://github.com/dotnet/runtime/issues/50391 - the .NET runtime tries to make a 2TB memfile if we have
// this feature enabled (which is on by default on .NET 7) This blows out our nsjail sandbox limit, so for now
// we disable it.
execOptions.env.DOTNET_EnableWriteXorExecute = '0';
// Disable any phone-home.
execOptions.env.DOTNET_CLI_TELEMETRY_OPTOUT = 'true';
// Some versions of .NET complain if they can't work out what the user's directory is. We force it to the output
// directory here.
execOptions.env.DOTNET_CLI_HOME = programDir;
// Place nuget packages in the output directory.
execOptions.env.NUGET_PACKAGES = path.join(programDir, '.nuget');
// Try to be less chatty
execOptions.env.DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 'true';
execOptions.env.DOTNET_NOLOGO = 'true';

execOptions.customCwd = programDir;
await fs.writeFile(nugetConfigPath, nugetConfigFileContent);

this.setCompilerExecOptions(execOptions, programDir);
const restoreOptions = ['restore', '--configfile', nugetConfigPath, '-v', 'q', '--nologo', '/clp:NoSummary'];
const restoreResult = await this.exec(compiler, restoreOptions, execOptions);
if (restoreResult.code !== 0) {
return this.transformToCompilationResult(restoreResult, inputFilename);
}

const compilerResult = await super.runCompiler(compiler, this.compilerOptions, inputFilename, execOptions);
if (compilerResult.code === 0) {
await fs.createFile(this.getOutputFilename(programDir, this.outputFilebase));
}
return compilerResult;
}

override async runCompiler(
compiler: string,
options: string[],
inputFilename: string,
execOptions: ExecutionOptions,
): Promise<CompilationResult> {
const crossgen2Path = path.join(this.clrBuildDir, 'crossgen2', 'crossgen2.dll');
const crossgen2Options: string[] = [];
const configurableOptions = this.configurableOptions;
const programDir = path.dirname(inputFilename);
const programOutputPath = path.join(programDir, 'bin', this.buildConfig, this.targetFramework);
const programDllPath = path.join(programOutputPath, 'CompilerExplorer.dll');

for (const configurableOption of configurableOptions) {
const optionIndex = options.indexOf(configurableOption);
Expand All @@ -200,14 +214,8 @@ class DotNetCompiler extends BaseCompiler {
crossgen2Options.push(options[switchIndex]);
}

const restoreOptions = ['restore', '--configfile', nugetConfigPath, '-v', 'q', '--nologo', '/clp:NoSummary'];
const restoreResult = await this.exec(compiler, restoreOptions, execOptions);
if (restoreResult.code !== 0) {
return this.transformToCompilationResult(restoreResult, inputFilename);
}

const compilerResult = await super.runCompiler(compiler, this.compilerOptions, inputFilename, execOptions);

this.setCompilerExecOptions(execOptions, programDir);
const compilerResult = await this.buildToDll(compiler, options, inputFilename, execOptions);
if (compilerResult.code !== 0) {
return compilerResult;
}
Expand Down

0 comments on commit 61aad90

Please sign in to comment.