Executes the compiler.
64 {
65 if (options is null)
66 throw new ArgumentNullException(nameof(options));
67
68 using var w = new StringWriter();
69
70 if (options.Output is not null)
71 w.WriteLine($"-out \"{options.Output}\"");
72
73 if (options.Assembly is not null)
74 w.WriteLine($"-assembly \"{options.Assembly}\"");
75
76 if (options.Version is not null)
77 w.WriteLine($"-version {options.Version}");
78
79 if (options.Target is not null)
80 {
81 switch (options.Target)
82 {
84 w.WriteLine($"-target library");
85 break;
87 w.WriteLine($"-target exe");
88 break;
90 w.WriteLine($"-target winexe");
91 break;
93 w.WriteLine($"-target module");
94 break;
95 }
96 }
97
98 if (options.Platform is not null)
99 w.WriteLine($"-platform {options.Platform.ToString().ToLowerInvariant()}");
100
101 if (options.KeyFile is not null)
102 w.WriteLine($"-keyfile \"{options.KeyFile}\"");
103
104 if (options.Key is not null)
105 w.WriteLine($"-key {options.Key}");
106
107 if (options.DelaySign)
108 w.WriteLine("-delay");
109
110 if (options.References is not null)
111 foreach (var reference in options.References)
112 w.WriteLine($"-reference \"{reference}\"");
113
114 if (options.Recurse is not null)
115 foreach (var recurse in options.Recurse)
116 w.WriteLine($"-recurse \"{recurse}\"");
117
118 if (options.Exclude is not null)
119 w.WriteLine($"-exclude \"{options.Exclude}\"");
120
121 if (options.FileVersion is not null)
122 w.WriteLine($"-fileversion {options.FileVersion}");
123
124 if (options.Win32Icon is not null)
125 w.WriteLine($"-win32icon {options.Win32Icon}");
126
127 if (options.Win32Manifest is not null)
128 w.WriteLine($"-win32manifest {options.Win32Manifest}");
129
130 if (options.Resources is not null)
131 foreach (var resource in options.Resources)
132 w.WriteLine($"-resource \"{resource.ResourcePath}={resource.FilePath}\"");
133
134 if (options.ExternalResources is not null)
135 foreach (var resource in options.ExternalResources)
136 w.WriteLine($"-externalresource \"{resource.ResourcePath}={resource.FilePath}\"");
137
138 if (options.CompressResources)
139 w.WriteLine("-compressresources");
140
142 w.WriteLine("-debug portable");
144 w.WriteLine("-debug embedded");
145
146 if (options.NoAutoSerialization)
147 w.WriteLine("-noautoserialization");
148
149 if (options.NoGlobbing)
150 w.WriteLine("-noglobbing");
151
152 if (options.NoJNI)
153 w.WriteLine("-nojni");
154
155 if (options.Optimize)
156 w.WriteLine("-optimize");
157
158 if (options.OptFields)
159 w.WriteLine("-opt:fields");
160
161 if (options.RemoveAssertions)
162 w.WriteLine("-removeassertions");
163
164 if (options.StrictFinalFieldSemantics)
165 w.WriteLine("-strictfinalfieldsemantics");
166
167 if (options.NoWarn is not null)
168 {
169 if (options.NoWarn.Count == 0)
170 w.WriteLine("-nowarn");
171 else
172 w.WriteLine($"-nowarn {string.Join(",", options.NoWarn)}");
173 }
174
175 if (options.WarningsAsErrors is not null)
176 {
177 if (options.WarningsAsErrors.Count == 0)
178 w.WriteLine("-warnaserror");
179 else
180 w.WriteLine($"-warnaserror {string.Join(",", options.WarningsAsErrors)}");
181 }
182
183 if (options.Main is not null)
184 w.WriteLine($"-main {options.Main}");
185
186 if (options.SrcPath is not null)
187 w.WriteLine($"-srcpath {options.SrcPath}");
188
189 if (options.Apartment is not null)
190 w.WriteLine($"-apartment {options.Apartment}");
191
192 if (options.SetProperties is not null)
193 foreach (var kvp in options.SetProperties)
194 w.WriteLine($"-D \"{kvp.Key}={kvp.Value}\"");
195
196 if (options.NoStackTraceInfo)
197 w.WriteLine("-nostacktraceinfo");
198
199 if (options.PrivatePackages is not null)
200 foreach (var i in options.PrivatePackages)
201 w.WriteLine($"-privatepackage {i}");
202
203 if (options.ClassLoader is not null)
204 w.WriteLine($"-classloader {options.ClassLoader}");
205
206 if (options.SharedClassLoader)
207 w.WriteLine("-sharedclassloader");
208
209 if (options.BaseAddress is not null)
210 w.WriteLine($"-baseaddress {options.BaseAddress}");
211
212 if (options.FileAlign is not null)
213 w.WriteLine($"-filealign {options.FileAlign}");
214
215 if (options.NoPeerCrossReference)
216 w.WriteLine("-nopeercrossreference");
217
218 if (options.NoStdLib)
219 w.WriteLine("-nostdlib");
220
221 if (options.Lib is not null)
222 foreach (var i in options.Lib)
223 w.WriteLine($"-lib \"{i}\"");
224
225 if (options.HighEntropyVA)
226 w.WriteLine("-highentropyva");
227
228 if (options.Static)
229 w.WriteLine("-static");
230
231 if (options.AssemblyAttributes is not null)
232 foreach (var i in options.AssemblyAttributes)
233 w.WriteLine($"-assemblyattributes \"{i}\"");
234
235 if (options.Runtime is not null)
236 w.WriteLine($"-runtime \"{options.Runtime}\"");
237
238 if (options.WarningLevel is not null)
239 w.WriteLine($"-w{options.WarningLevel}");
240
241 if (options.NoParameterReflection)
242 w.WriteLine($"-noparameterreflection");
243
244 if (options.Remap is not null)
245 w.WriteLine($"-remap \"{options.Remap}\"");
246
247 w.WriteLine($"-log json,file=stderr");
248
249 if (options.Input != null)
250 foreach (var i in options.Input)
251 w.Write($"\"{i}\"");
252
253
254 var response = string.IsNullOrWhiteSpace(options.ResponseFile) == false ? Path.GetFullPath(options.ResponseFile) : Path.GetTempFileName();
255
256
257 var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, new CancellationToken());
258
259
260 var ctk = cts.Token;
261 if (options.Timeout != Timeout.Infinite)
262 ctk = CancellationTokenSource.CreateLinkedTokenSource(ctk, new CancellationTokenSource(options.Timeout).Token).Token;
263
264 try
265 {
266
267 Directory.CreateDirectory(Path.GetDirectoryName(response) ?? throw new InvalidOperationException());
268 File.WriteAllText(response, w.ToString());
269
270
271 string? wrap = null;
273 if (exe is null || File.Exists(exe) == false)
274 throw new FileNotFoundException($"Could not locate tool at '{exe}'.");
275
276
277 if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
278 {
279
280 if (exe.EndsWith(".exe"))
281 {
282 wrap = "mono";
283 }
284 else
285 {
286
287
288 try
289 {
290 var psx = Mono.Unix.UnixFileSystemInfo.GetFileSystemEntry(exe);
291 if (psx.FileAccessPermissions.HasFlag(Mono.Unix.FileAccessPermissions.UserExecute) == false)
292 psx.FileAccessPermissions |= Mono.Unix.FileAccessPermissions.UserExecute;
293 }
294 catch (Exception e)
295 {
296 throw new IkvmToolException($"Could not set user executable bit on '{exe}'.", e);
297 }
298 }
299 }
300
301
302 var args = new List<string>();
303 args.Add($"@{response}");
304
305
306 Command cli;
307 if (wrap != null)
308 {
309 cli = Cli.Wrap(wrap);
310 args.Insert(0, exe);
311 }
312 else
313 cli = Cli.Wrap(exe);
314
315
316 cli = cli.WithWorkingDirectory(Environment.CurrentDirectory);
317
318
319 cli = cli.WithArguments(args);
320 cli = cli.WithValidation(CommandResultValidation.None);
321
322
324
325
327
328
329 using var pid = cli.ExecuteAsync(ctk);
330
331
332 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
333 {
334 try
335 {
336 if (pid.Task.IsCompleted == false)
338 }
339 catch
340 {
342 }
343 }
344
345
346 var ret = await pid;
347
348
349 return ret.ExitCode;
350 }
351 finally
352 {
353
354 if (cts != null)
355 cts.Cancel();
356
357
358 if (options.ResponseFile == null && response != null && File.Exists(response))
359 {
360 try
361 {
362 File.Delete(response);
363 }
364 catch (IOException)
365 {
366
367 }
368 }
369 }
370 }