Skip to content

Commit e79aa12

Browse files
BenedekFarkasHongGit
authored andcommitted
Adding the ability to define a custom (local) path to Roslyn (#25) (#26)
* CompilationSettings: C# 6 code styling and making CompilationSettingsHelper.CompilerFullPath public * Compiler: Adding the ability to define a custom compiler path for the current build process * Compiler: Fixing that the compiler path wasn't set when the override parameter is not present
1 parent 44fec6e commit e79aa12

4 files changed

Lines changed: 71 additions & 43 deletions

File tree

src/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/Compiler.cs

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4-
using System;
4+
using System;
55
using System.CodeDom;
66
using System.CodeDom.Compiler;
77
using System.Collections.Generic;
@@ -12,18 +12,21 @@
1212
using System.Security.Permissions;
1313
using System.Security.Principal;
1414
using System.Text;
15+
using static Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Constants.CustomCompilerParameters;
1516

1617
namespace Microsoft.CodeDom.Providers.DotNetCompilerPlatform {
1718
internal abstract class Compiler : ICodeCompiler {
1819
private readonly CodeDomProvider _codeDomProvider;
1920
private readonly ICompilerSettings _compilerSettings;
20-
private string _compilerFullPath = null;
2121
private const string CLR_PROFILING_SETTING = "COR_ENABLE_PROFILING";
2222
private const string DISABLE_PROFILING = "0";
2323

24+
// Needs to be initialized using InitializeCompilerFullPath where the CompilerParameters are available.
25+
private string _compilerFullPath = null;
26+
2427
public Compiler(CodeDomProvider codeDomProvider, ICompilerSettings compilerSettings) {
25-
this._codeDomProvider = codeDomProvider;
26-
this._compilerSettings = compilerSettings;
28+
_codeDomProvider = codeDomProvider;
29+
_compilerSettings = compilerSettings;
2730
}
2831

2932
public CompilerResults CompileAssemblyFromDom(CompilerParameters options, CodeCompileUnit compilationUnit) {
@@ -47,6 +50,8 @@ public CompilerResults CompileAssemblyFromDomBatch(CompilerParameters options, C
4750
throw new ArgumentNullException("compilationUnits");
4851
}
4952

53+
InitializeCompilerFullPath(options);
54+
5055
try {
5156
var sources = compilationUnits.Select(c => {
5257
var writer = new StringWriter();
@@ -82,6 +87,8 @@ public CompilerResults CompileAssemblyFromFileBatch(CompilerParameters options,
8287
throw new ArgumentNullException("fileNames");
8388
}
8489

90+
InitializeCompilerFullPath(options);
91+
8592
try {
8693
// Try opening the files to make sure they exists. This will throw an exception
8794
// if it doesn't
@@ -117,6 +124,8 @@ public CompilerResults CompileAssemblyFromSourceBatch(CompilerParameters options
117124
throw new ArgumentNullException("sources");
118125
}
119126

127+
InitializeCompilerFullPath(options);
128+
120129
try {
121130
return FromSourceBatch(options, sources);
122131
}
@@ -129,17 +138,41 @@ protected abstract string FileExtension {
129138
get;
130139
}
131140

132-
protected virtual string CompilerName {
133-
get {
134-
if (null == _compilerFullPath) {
135-
_compilerFullPath = _compilerSettings.CompilerFullPath;
141+
protected void InitializeCompilerFullPath(CompilerParameters options = null) {
142+
if (string.IsNullOrEmpty(_compilerFullPath)) {
143+
if (options != null) {
144+
// Determining whether the custom compiler path parameter is provided.
145+
var customCompilerPathParameter = options.CompilerOptions.Split('/').FirstOrDefault(p => p.StartsWith(CustomCompilerPath));
146+
if (!string.IsNullOrEmpty(customCompilerPathParameter)) {
147+
if (!customCompilerPathParameter.Contains(":")) {
148+
throw new ArgumentException($"There's no value defined for the \"{CustomCompilerPath}\" compiler parameter!");
149+
}
136150

137-
// Try opening the file to make sure the compiler exist. This will throw an exception
138-
// if it doesn't
139-
using (var str = File.OpenRead(_compilerFullPath)) { }
151+
// Removing trailing space (when this is not the last parameter) and extracting value.
152+
var customCompilerPath = customCompilerPathParameter.TrimEnd(' ').Split(':')[1];
153+
154+
if (string.IsNullOrEmpty(customCompilerPath)) {
155+
throw new ArgumentException($"The value of the \"{CustomCompilerPath}\" compiler parameter can't be empty!");
156+
}
157+
158+
// Extracting the name of the compiler executable from the default path.
159+
var compilerExecutable = _compilerSettings.CompilerFullPath.Substring(_compilerSettings.CompilerFullPath.LastIndexOf('\\'));
160+
161+
// And finally, we're able to construct the complete custom path to the compiler executable.
162+
// If the custom path contains spaces, then it has to be surrounded by quotes, which we don't need now.
163+
_compilerFullPath = CompilationSettingsHelper.CompilerFullPath($"{customCompilerPath.Trim('"')}\\{compilerExecutable}");
164+
165+
// Removing the custom parameter, as the compiler can't process it.
166+
options.CompilerOptions = options.CompilerOptions.Replace($"/{CustomCompilerPath}:{customCompilerPath}", "");
167+
}
168+
// Falling back to the default behavior.
169+
else _compilerFullPath = _compilerSettings.CompilerFullPath;
140170
}
171+
else _compilerFullPath = _compilerSettings.CompilerFullPath;
141172

142-
return _compilerFullPath;
173+
// Try opening the file to make sure that the compiler exists.
174+
// This will throw an exception if it doesn't.
175+
using (var str = File.OpenRead(_compilerFullPath)) { }
143176
}
144177
}
145178

@@ -282,7 +315,7 @@ private CompilerResults FromFileBatch(CompilerParameters options, string[] fileN
282315
}
283316

284317
Compile(options,
285-
CompilerName,
318+
_compilerFullPath,
286319
args,
287320
ref outputFile,
288321
ref retValue);
@@ -300,7 +333,7 @@ private CompilerResults FromFileBatch(CompilerParameters options, string[] fileN
300333
replacedArgs = true;
301334
var outputLine = string.Format("{0}>{1} {2}",
302335
Environment.CurrentDirectory,
303-
CompilerName,
336+
_compilerFullPath,
304337
trueArgs);
305338
results.Output.Add(outputLine);
306339
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Microsoft.CodeDom.Providers.DotNetCompilerPlatform {
2+
/// <summary>
3+
/// Common, reusable constant values.
4+
/// </summary>
5+
public static class Constants {
6+
/// <summary>
7+
/// Custom compiler parameters used to modify the behavior of the compiler service.
8+
/// </summary>
9+
public static class CustomCompilerParameters {
10+
/// <summary>
11+
/// Roslyn path override.
12+
/// </summary>
13+
public const string CustomCompilerPath = "compilerPath";
14+
}
15+
}
16+
}

src/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
<ItemGroup>
5555
<Compile Include="AppSettings.cs" />
5656
<Compile Include="Compiler.cs" />
57+
<Compile Include="Constants.cs" />
5758
<Compile Include="CSharpCompiler.cs" />
5859
<Compile Include="CSharpCodeProvider.cs">
5960
<SubType>Component</SubType>

src/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/Util/CompilationSettings.cs

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,9 @@ public CompilerSettings(string compilerFullPath, int compilerServerTimeToLive) {
2121
_compilerServerTimeToLive = compilerServerTimeToLive;
2222
}
2323

24-
string ICompilerSettings.CompilerFullPath {
25-
get {
26-
return _compilerFullPath;
27-
}
28-
}
24+
string ICompilerSettings.CompilerFullPath => _compilerFullPath;
2925

30-
int ICompilerSettings.CompilerServerTimeToLive {
31-
get{
32-
return _compilerServerTimeToLive;
33-
}
34-
}
26+
int ICompilerSettings.CompilerServerTimeToLive => _compilerServerTimeToLive;
3527
}
3628

3729
internal static class CompilationSettingsHelper {
@@ -88,28 +80,14 @@ static CompilationSettingsHelper() {
8880
}
8981
}
9082

91-
public static ICompilerSettings CSC2 {
92-
get {
93-
return _csc;
94-
}
95-
}
83+
public static ICompilerSettings CSC2 => _csc;
9684

97-
public static ICompilerSettings VBC2 {
98-
get {
99-
return _vb;
100-
}
101-
}
85+
public static ICompilerSettings VBC2 => _vb;
10286

103-
private static string CompilerFullPath(string relativePath) {
104-
string compilerFullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativePath);
105-
return compilerFullPath;
106-
}
87+
public static string CompilerFullPath(string relativePath) =>
88+
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativePath);
10789

108-
private static bool IsDebuggerAttached {
109-
get {
110-
return IsDebuggerPresent() || Debugger.IsAttached;
111-
}
112-
}
90+
private static bool IsDebuggerAttached => IsDebuggerPresent() || Debugger.IsAttached;
11391

11492
[DllImport("kernel32.dll")]
11593
private extern static bool IsDebuggerPresent();

0 commit comments

Comments
 (0)