OLD | NEW |
1 | 1 |
2 using System; | 2 using System; |
3 using System.Collections.Generic; | 3 using System.Collections.Generic; |
4 using System.Text; | 4 using System.Text; |
5 using System.Collections; | 5 using System.Collections; |
6 using System.IO; | 6 using System.IO; |
7 using System.Reflection; | 7 using System.Reflection; |
8 using System.Resources; | 8 using System.Resources; |
| 9 using System.Windows.Forms; |
9 using Microsoft.Build.Framework; | 10 using Microsoft.Build.Framework; |
| 11 using Microsoft.Win32; |
10 using Microsoft.Build.Utilities; | 12 using Microsoft.Build.Utilities; |
| 13 using System.Collections.Specialized; |
11 | 14 |
12 using System.Diagnostics; | 15 using System.Diagnostics; |
13 | 16 |
14 namespace NaCl.Build.CPPTasks | 17 namespace NaCl.Build.CPPTasks |
15 { | 18 { |
16 public class NaClCompile : ToolTask | 19 public class NaClCompile : ToolTask |
17 { | 20 { |
18 private XamlParser m_XamlParser; | 21 private XamlParser m_XamlParser; |
19 private ITaskItem[] excludedInputPaths; | 22 private ITaskItem[] excludedInputPaths; |
20 private ITaskItem[] tlogReadFiles; | 23 private ITaskItem[] tlogReadFiles; |
(...skipping 11 matching lines...) Expand all Loading... |
32 [Required] | 35 [Required] |
33 public string PropertiesFile { get; set; } | 36 public string PropertiesFile { get; set; } |
34 | 37 |
35 [Required] | 38 [Required] |
36 public ITaskItem[] Sources { get; set; } | 39 public ITaskItem[] Sources { get; set; } |
37 | 40 |
38 [Required] | 41 [Required] |
39 public string NaCLCompilerPath { get; set; } | 42 public string NaCLCompilerPath { get; set; } |
40 | 43 |
41 [Required] | 44 [Required] |
42 public string OutputCommandLine { get; set; } | 45 public bool OutputCommandLine { get; set; } |
| 46 |
| 47 public int ProcessorNumber { get; set; } |
| 48 |
| 49 public bool MultiProcessorCompilation { get; set; } |
43 | 50 |
44 [Required] | 51 [Required] |
45 public string TrackerLogDirectory { get; set; } | 52 public string TrackerLogDirectory { get; set; } |
46 | 53 |
| 54 protected override StringDictionary EnvironmentOverride |
| 55 { |
| 56 get { |
| 57 string show = OutputCommandLine ? "1" : "0"; |
| 58 string cores = Convert.ToString(ProcessorNumber); |
| 59 return new StringDictionary() { |
| 60 {"NACL_GCC_CORES", cores}, |
| 61 {"NACL_GCC_SHOW_COMMANDS", show } |
| 62 }; |
| 63 } |
| 64 } |
47 | 65 |
48 protected override string GenerateFullPathToTool() { return ToolName; } | 66 protected override string GenerateFullPathToTool() { return ToolName; } |
49 | 67 |
50 public NaClCompile() | 68 public NaClCompile() |
51 : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources
", Assembly.GetExecutingAssembly())) | 69 : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources
", Assembly.GetExecutingAssembly())) |
52 { | 70 { |
53 this.pathToLog = string.Empty; | 71 this.pathToLog = string.Empty; |
54 this.EnvironmentVariables = new string []{"CYGWIN=nodosfilewarning",
"LC_CTYPE=C"}; | 72 this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning"
, "LC_CTYPE=C" }; |
55 } | 73 } |
56 | 74 |
57 protected IDictionary<string, string> GenerateCommandLinesFromTlog() | 75 protected IDictionary<string, string> GenerateCommandLinesFromTlog() |
58 { | 76 { |
59 IDictionary<string, string> cmdLineDictionary = new Dictionary<strin
g, string>(StringComparer.OrdinalIgnoreCase); | 77 IDictionary<string, string> cmdLineDictionary = new Dictionary<strin
g, string>(StringComparer.OrdinalIgnoreCase); |
60 string tlogFilename = this.TLogCommandFile.GetMetadata("FullPath"); | 78 string tlogFilename = this.TLogCommandFile.GetMetadata("FullPath"); |
61 if (File.Exists(tlogFilename)) | 79 if (File.Exists(tlogFilename)) |
62 { | 80 { |
63 using (StreamReader reader = File.OpenText(tlogFilename)) | 81 using (StreamReader reader = File.OpenText(tlogFilename)) |
64 { | 82 { |
65 string filename = string.Empty; | 83 string filename = string.Empty; |
66 for (string lineStr = reader.ReadLine(); lineStr != null; li
neStr = reader.ReadLine()) | 84 for (string lineStr = reader.ReadLine(); lineStr != null; li
neStr = reader.ReadLine()) |
67 { | 85 { |
68 if (lineStr.Length == 0 || | 86 if (lineStr.Length == 0 || |
69 (lineStr[0] == '^' && lineStr.Length == 1)) | 87 (lineStr[0] == '^' && lineStr.Length == 1)) |
70 { | 88 { |
71 Log.LogMessage(MessageImportance.High, "Invalid line
in command tlog"); | 89 Log.LogError("Invalid line in command tlog"); |
72 break; | 90 break; |
73 } | 91 } |
74 else if (lineStr[0] == '^') | 92 else if (lineStr[0] == '^') |
75 { | 93 { |
76 filename = lineStr.Substring(1); | 94 filename = lineStr.Substring(1); |
77 } | 95 } |
78 else | 96 else |
79 { | 97 { |
80 cmdLineDictionary[filename] = lineStr; | 98 cmdLineDictionary[filename] = lineStr; |
81 } | 99 } |
82 } | 100 } |
83 } | 101 } |
84 } | 102 } |
85 return cmdLineDictionary; | 103 return cmdLineDictionary; |
86 } | 104 } |
87 | 105 |
88 protected override void LogEventsFromTextOutput(string singleLine, Messa
geImportance messageImportance) | 106 protected override void LogEventsFromTextOutput(string singleLine, Messa
geImportance messageImportance) |
89 { | 107 { |
90 base.LogEventsFromTextOutput(GCCUtilities.Convert_Output_GCC_to_VS(s
ingleLine), messageImportance); | 108 base.LogEventsFromTextOutput(GCCUtilities.ConvertGCCOutput(singleLin
e), messageImportance); |
| 109 } |
| 110 |
| 111 static string GetObjectFile(ITaskItem source) |
| 112 { |
| 113 string objectFilePath = Path.GetFullPath(source.GetMetadata("ObjectF
ileName")); |
| 114 // cl.exe will accept a folder name as the ObjectFileName in which c
ase |
| 115 // the objectfile is created as <ObjectFileName>/<basename>.obj. He
re |
| 116 // we mimic this behaviour. |
| 117 if ((File.GetAttributes(objectFilePath) & FileAttributes.Directory)
!= 0) |
| 118 { |
| 119 objectFilePath = Path.Combine(objectFilePath, Path.GetFileName(s
ource.ItemSpec)); |
| 120 objectFilePath = Path.ChangeExtension(objectFilePath, ".obj"); |
| 121 } |
| 122 return objectFilePath; |
91 } | 123 } |
92 | 124 |
93 private void ConstructReadTLog(ITaskItem[] compiledSources, CanonicalTra
ckedOutputFiles outputs) | 125 private void ConstructReadTLog(ITaskItem[] compiledSources, CanonicalTra
ckedOutputFiles outputs) |
94 { | 126 { |
95 string trackerPath = Path.GetFullPath(TlogDirectory + ReadTLogFilena
mes[0]); | 127 string trackerPath = Path.GetFullPath(TlogDirectory + ReadTLogFilena
mes[0]); |
96 | 128 |
97 //save tlog for sources not compiled during this execution | 129 //save tlog for sources not compiled during this execution |
98 TaskItem readTrackerItem = new TaskItem(trackerPath); | 130 TaskItem readTrackerItem = new TaskItem(trackerPath); |
99 CanonicalTrackedInputFiles files = new CanonicalTrackedInputFiles(ne
w TaskItem[] { readTrackerItem }, Sources, outputs, false, false); | 131 CanonicalTrackedInputFiles files = new CanonicalTrackedInputFiles(ne
w TaskItem[] { readTrackerItem }, Sources, outputs, false, false); |
100 files.RemoveEntriesForSource(compiledSources); | 132 files.RemoveEntriesForSource(compiledSources); |
101 files.SaveTlog(); | 133 files.SaveTlog(); |
102 | 134 |
103 //add tlog information for compiled sources | 135 //add tlog information for compiled sources |
104 using (StreamWriter writer = new StreamWriter(trackerPath, true, Enc
oding.Unicode)) | 136 using (StreamWriter writer = new StreamWriter(trackerPath, true, Enc
oding.Unicode)) |
105 { | 137 { |
106 foreach (ITaskItem source in compiledSources) | 138 foreach (ITaskItem source in compiledSources) |
107 { | 139 { |
108 string sourcePath = Path.GetFullPath(source.ItemSpec).ToUppe
rInvariant(); | 140 string sourcePath = Path.GetFullPath(source.ItemSpec).ToUppe
rInvariant(); |
109 | 141 string objectFilePath = GetObjectFile(source); |
110 string objectFilePath = Path.GetFullPath(source.GetMetadata(
"ObjectFileName")); | |
111 string depFilePath = Path.ChangeExtension(objectFilePath, ".
d"); | 142 string depFilePath = Path.ChangeExtension(objectFilePath, ".
d"); |
112 | 143 |
113 try | 144 try |
114 { | 145 { |
115 if (File.Exists(depFilePath) == false) | 146 if (File.Exists(depFilePath) == false) |
116 { | 147 { |
117 Log.LogMessage(MessageImportance.High, depFilePath +
" not found"); | 148 Log.LogMessage(MessageImportance.High, depFilePath +
" not found"); |
118 } | 149 } |
119 else | 150 else |
120 { | 151 { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 string path = Path.Combine(TlogDirectory, WriteTLogFilename); | 191 string path = Path.Combine(TlogDirectory, WriteTLogFilename); |
161 TaskItem item = new TaskItem(path); | 192 TaskItem item = new TaskItem(path); |
162 CanonicalTrackedOutputFiles trackedFiles = new CanonicalTrackedOutpu
tFiles(new TaskItem[] { item }); | 193 CanonicalTrackedOutputFiles trackedFiles = new CanonicalTrackedOutpu
tFiles(new TaskItem[] { item }); |
163 | 194 |
164 foreach (ITaskItem sourceItem in compiledSources) | 195 foreach (ITaskItem sourceItem in compiledSources) |
165 { | 196 { |
166 //remove this entry associated with compiled source which is abo
ut to be recomputed | 197 //remove this entry associated with compiled source which is abo
ut to be recomputed |
167 trackedFiles.RemoveEntriesForSource(sourceItem); | 198 trackedFiles.RemoveEntriesForSource(sourceItem); |
168 | 199 |
169 //add entry with updated information | 200 //add entry with updated information |
170 trackedFiles.AddComputedOutputForSourceRoot( Path.GetFullPath(so
urceItem.ItemSpec).ToUpperInvariant(), | 201 trackedFiles.AddComputedOutputForSourceRoot(Path.GetFullPath(sou
rceItem.ItemSpec).ToUpperInvariant(), |
171 Path.GetFullPath(so
urceItem.GetMetadata("ObjectFileName")).ToUpperInvariant()); | 202 Path.GetFullPath(Get
ObjectFile(sourceItem)).ToUpperInvariant()); |
172 } | 203 } |
173 | 204 |
174 //output tlog | 205 //output tlog |
175 trackedFiles.SaveTlog(); | 206 trackedFiles.SaveTlog(); |
176 | 207 |
177 return trackedFiles; | 208 return trackedFiles; |
178 } | 209 } |
179 | 210 |
180 private void OutputCommandTrackerLog(ITaskItem[] compiledSources) | 211 private void OutputCommandTrackerLog(ITaskItem[] compiledSources) |
181 { | 212 { |
(...skipping 14 matching lines...) Expand all Loading... |
196 { | 227 { |
197 foreach (KeyValuePair<string, string> p in commandLines) | 228 foreach (KeyValuePair<string, string> p in commandLines) |
198 { | 229 { |
199 string keyLine = "^" + p.Key; | 230 string keyLine = "^" + p.Key; |
200 writer.WriteLine(keyLine); | 231 writer.WriteLine(keyLine); |
201 writer.WriteLine(p.Value); | 232 writer.WriteLine(p.Value); |
202 } | 233 } |
203 } | 234 } |
204 } | 235 } |
205 | 236 |
206 protected string GenerateCommandLineFromProps(ITaskItem sourceFile) | 237 protected string GenerateCommandLineFromProps(ITaskItem sourceFile, bool
fullOutputName=false) |
207 { | 238 { |
208 StringBuilder commandLine = new StringBuilder(GCCUtilities.s_Command
LineLength); | 239 StringBuilder commandLine = new StringBuilder(GCCUtilities.s_Command
LineLength); |
209 | 240 |
210 if (sourceFile != null) | 241 if (sourceFile != null) |
211 { | 242 { |
212 string sourcePath = GCCUtilities.Convert_Path_Windows_To_Posix(s
ourceFile.ToString()); | |
213 | |
214 // Remove rtti items as they are not relevant in C compilation a
nd will produce warnings | 243 // Remove rtti items as they are not relevant in C compilation a
nd will produce warnings |
215 if (SourceIsC(sourceFile.ToString())) | 244 if (SourceIsC(sourceFile.ToString())) |
216 { | 245 { |
217 commandLine.Replace("-fno-rtti", ""); | 246 commandLine.Replace("-fno-rtti", ""); |
218 commandLine.Replace("-frtti", ""); | 247 commandLine.Replace("-frtti", ""); |
219 } | 248 } |
220 | 249 |
221 //build command line from components and add required switches | 250 //build command line from components and add required switches |
222 string props = m_XamlParser.Parse(sourceFile); | 251 string props = m_XamlParser.Parse(sourceFile, fullOutputName); |
223 commandLine.Append(props); | 252 commandLine.Append(props); |
224 commandLine.Append(" -MD -c "); | 253 commandLine.Append(" -MD -c "); |
225 commandLine.Append("\"" + sourcePath + "\""); | |
226 } | 254 } |
227 | 255 |
228 return commandLine.ToString(); | 256 return commandLine.ToString(); |
229 } | 257 } |
230 | 258 |
231 protected ITaskItem[] MergeOutOfDateSources(ITaskItem[] outOfDateSources
FromTracking, List<ITaskItem> outOfDateSourcesFromCommandLineChanges) | 259 protected ITaskItem[] MergeOutOfDateSources(ITaskItem[] outOfDateSources
FromTracking, List<ITaskItem> outOfDateSourcesFromCommandLineChanges) |
232 { | 260 { |
233 List<ITaskItem> mergedSources = new List<ITaskItem>(outOfDateSources
FromTracking); | 261 List<ITaskItem> mergedSources = new List<ITaskItem>(outOfDateSources
FromTracking); |
234 | 262 |
235 foreach (ITaskItem item in outOfDateSourcesFromCommandLineChanges) | 263 foreach (ITaskItem item in outOfDateSourcesFromCommandLineChanges) |
(...skipping 29 matching lines...) Expand all Loading... |
265 return true; | 293 return true; |
266 } | 294 } |
267 else | 295 else |
268 { | 296 { |
269 return false; | 297 return false; |
270 } | 298 } |
271 } | 299 } |
272 | 300 |
273 private int Compile(string pathToTool) | 301 private int Compile(string pathToTool) |
274 { | 302 { |
| 303 // If multiprocess complication is enabled (not the VS default) |
| 304 // and the number of processors to use is not 1, then use the |
| 305 // compiler_wrapper python script to run multiple instances of |
| 306 // gcc |
| 307 if (MultiProcessorCompilation && ProcessorNumber != 1) |
| 308 { |
| 309 |
| 310 string envvar = (string)Registry.GetValue("HKEY_CURRENT_USER\\En
vironment", "PATH", ""); |
| 311 List<string> pathList = new List<string>(envvar.Split(';')); |
| 312 envvar = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\System\\
CurrentControlSet\\Control\\Session Manager\\Environment", "PATH", ""); |
| 313 pathList.AddRange(new List<string>(envvar.Split(';'))); |
| 314 string pythonExe = null; |
| 315 foreach (string path in pathList) |
| 316 { |
| 317 string testPath = Path.Combine(path, "python.bat"); |
| 318 if (File.Exists(testPath)) |
| 319 { |
| 320 pythonExe = testPath; |
| 321 break; |
| 322 } |
| 323 testPath = Path.Combine(path, "python.exe"); |
| 324 if (File.Exists(testPath)) |
| 325 { |
| 326 pythonExe = testPath; |
| 327 break; |
| 328 } |
| 329 } |
| 330 |
| 331 if (pythonExe == null) |
| 332 { |
| 333 MessageBox.Show("Multi-processor Compilation with NaCl requi
res that python available in the PATH.\n" + |
| 334 "Please disable Multi-processor Compilation
in the project properties or add python " + |
| 335 "to the your PATH\n" + |
| 336 "Falling back to serial compilation.\n"); |
| 337 } |
| 338 else |
| 339 { |
| 340 return CompileParallel(pathToTool, pythonExe); |
| 341 } |
| 342 } |
| 343 return CompileSerial(pathToTool); |
| 344 } |
| 345 |
| 346 private int CompileSerial(string pathToTool) |
| 347 { |
275 int returnCode = 0; | 348 int returnCode = 0; |
276 | 349 |
277 foreach (ITaskItem sourceFileItem in CompileSourceList) | 350 foreach (ITaskItem sourceItem in CompileSourceList) |
278 { | 351 { |
279 try | 352 try |
280 { | 353 { |
281 string commandLine = GenerateCommandLineFromProps(sourceFile
Item); | 354 string commandLine = GenerateCommandLineFromProps(sourceItem
, true); |
| 355 commandLine += "\"" + GCCUtilities.ConvertPathWindowsToPosix
(sourceItem.ToString()) + "\""; |
282 | 356 |
283 base.Log.LogMessageFromText(Path.GetFileName(sourceFileItem.
ToString()), MessageImportance.High); | 357 if (OutputCommandLine) |
284 | |
285 if (OutputCommandLine == "true") | |
286 { | 358 { |
287 string logMessage = pathToTool + " " + commandLine; | 359 string logMessage = pathToTool + " " + commandLine; |
288 Log.LogMessageFromText(logMessage, MessageImportance.Hig
h); | 360 Log.LogMessage(logMessage); |
| 361 } |
| 362 else |
| 363 { |
| 364 base.Log.LogMessage(Path.GetFileName(sourceItem.ToString
())); |
289 } | 365 } |
290 | 366 |
291 | 367 |
292 // compile | 368 // compile |
293 returnCode = base.ExecuteTool(pathToTool, commandLine, strin
g.Empty); | 369 returnCode = base.ExecuteTool(pathToTool, commandLine, strin
g.Empty); |
294 } | 370 } |
295 catch (Exception) | 371 catch (Exception) |
296 { | 372 { |
297 returnCode = base.ExitCode; | 373 returnCode = base.ExitCode; |
298 } | 374 } |
299 | 375 |
300 //abort if an error was encountered | 376 //abort if an error was encountered |
301 if (returnCode != 0) | 377 if (returnCode != 0) |
302 { | 378 { |
303 return returnCode; | 379 return returnCode; |
304 } | 380 } |
305 } | 381 } |
306 return returnCode; | 382 return returnCode; |
307 } | 383 } |
308 | 384 |
| 385 private int CompileParallel(string pathToTool, string pythonExe) |
| 386 { |
| 387 int returnCode = 0; |
| 388 |
| 389 // Compute sources that can be compiled together. |
| 390 Dictionary<string, List<ITaskItem>> srcGroups = |
| 391 new Dictionary<string, List<ITaskItem>>(); |
| 392 |
| 393 foreach (ITaskItem sourceItem in CompileSourceList) |
| 394 { |
| 395 string commandLine = GenerateCommandLineFromProps(sourceItem); |
| 396 if (srcGroups.ContainsKey(commandLine)) |
| 397 { |
| 398 srcGroups[commandLine].Add(sourceItem); |
| 399 } |
| 400 else |
| 401 { |
| 402 srcGroups.Add(commandLine, new List<ITaskItem> {sourceItem})
; |
| 403 } |
| 404 } |
| 405 |
| 406 string pythonScript = Path.GetDirectoryName(Path.GetDirectoryName(Pr
opertiesFile)); |
| 407 pythonScript = Path.Combine(pythonScript, "compiler_wrapper.py"); |
| 408 |
| 409 foreach (KeyValuePair<string, List<ITaskItem>> entry in srcGroups) |
| 410 { |
| 411 string commandLine = entry.Key; |
| 412 string cmd = "\"" + pathToTool + "\" " + commandLine + "--"; |
| 413 List<ITaskItem> sources = entry.Value; |
| 414 |
| 415 foreach (ITaskItem sourceItem in sources) |
| 416 { |
| 417 string src = GCCUtilities.ConvertPathWindowsToPosix(sourceIt
em.ToString()); |
| 418 cmd += " \"" + src + "\""; |
| 419 } |
| 420 |
| 421 try |
| 422 { |
| 423 // compile this group of sources |
| 424 returnCode = base.ExecuteTool(pythonExe, cmd, "\"" + pythonS
cript + "\""); |
| 425 } |
| 426 catch (Exception e) |
| 427 { |
| 428 Log.LogMessage("compiler exception: {0}", e); |
| 429 returnCode = base.ExitCode; |
| 430 } |
| 431 |
| 432 //abort if an error was encountered |
| 433 if (returnCode != 0) |
| 434 break; |
| 435 } |
| 436 |
| 437 Log.LogMessage(MessageImportance.Low, "compiler returned: {0}", retu
rnCode); |
| 438 return returnCode; |
| 439 } |
| 440 |
309 protected override int ExecuteTool(string pathToTool, string responseFil
eCommands, string commandLineCommands) | 441 protected override int ExecuteTool(string pathToTool, string responseFil
eCommands, string commandLineCommands) |
310 { | 442 { |
311 if (File.Exists(pathToTool) == false) | 443 if (File.Exists(pathToTool) == false) |
312 { | 444 { |
313 base.Log.LogMessageFromText("Unable to find NaCL compiler: " + p
athToTool, MessageImportance.High); | 445 base.Log.LogMessageFromText("Unable to find NaCL compiler: " + p
athToTool, MessageImportance.High); |
314 return -1; | 446 return -1; |
315 } | 447 } |
316 | 448 |
317 int returnCode = -1; | 449 int returnCode = -1; |
318 | 450 |
(...skipping 17 matching lines...) Expand all Loading... |
336 { | 468 { |
337 if (this.TrackFileAccess || this.MinimalRebuildFromTracking) | 469 if (this.TrackFileAccess || this.MinimalRebuildFromTracking) |
338 { | 470 { |
339 this.SetTrackerLogPaths(); | 471 this.SetTrackerLogPaths(); |
340 } | 472 } |
341 | 473 |
342 //check if full recompile is required otherwise perform incremental | 474 //check if full recompile is required otherwise perform incremental |
343 if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking
== false) | 475 if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking
== false) |
344 { | 476 { |
345 this.CompileSourceList = this.Sources; | 477 this.CompileSourceList = this.Sources; |
346 if ((this.CompileSourceList == null) || (this.CompileSourceList.
Length == 0)) | 478 if (this.CompileSourceList == null || this.CompileSourceList.Len
gth == 0) |
347 { | 479 { |
348 this.SkippedExecution = true; | 480 this.SkippedExecution = true; |
349 } | 481 } |
350 } | 482 } |
351 else | 483 else |
352 { | 484 { |
353 //retrieve list of sources out of date due to command line chang
es | 485 //retrieve list of sources out of date due to command line chang
es |
354 List<ITaskItem> outOfDateSourcesFromCommandLineChanges = this.Ge
tOutOfDateSourcesFromCommandLineChanges(); | 486 List<ITaskItem> outOfDateSourcesFromCommandLineChanges = this.Ge
tOutOfDateSourcesFromCommandLineChanges(); |
355 | 487 |
356 //retrieve sources out of date due to tracking | 488 //retrieve sources out of date due to tracking |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 | 767 |
636 protected override Encoding ResponseFileEncoding | 768 protected override Encoding ResponseFileEncoding |
637 { | 769 { |
638 get | 770 get |
639 { | 771 { |
640 return Encoding.ASCII; | 772 return Encoding.ASCII; |
641 } | 773 } |
642 } | 774 } |
643 } | 775 } |
644 } | 776 } |
OLD | NEW |