4 using System
.Collections
.Generic
;
10 // Google V8 style options:
11 // - bool: --foo/--no-foo
18 // 'Option' is already used by Mono.Options
20 public Flag (string name
, string desc
, FlagType type
) {
30 public FlagType FlagType
{
34 public string Description
{
39 class BoolFlag
: Flag
{
40 public BoolFlag (string name
, string description
, bool def_value
, Action
<bool> action
) : base (name
, description
, FlagType
.BoolFlag
) {
42 DefaultValue
= def_value
;
45 public Action
<bool> Setter
{
49 public bool DefaultValue
{
55 static bool enable_debug
, enable_linker
;
56 static string app_prefix
, framework_prefix
, bcl_tools_prefix
, bcl_facades_prefix
, out_prefix
;
57 static List
<string> bcl_prefixes
;
58 static HashSet
<string> asm_map
= new HashSet
<string> ();
59 static List
<string> file_list
= new List
<string> ();
60 static HashSet
<string> assemblies_with_dbg_info
= new HashSet
<string> ();
61 static List
<string> root_search_paths
= new List
<string>();
63 const string BINDINGS_ASM_NAME
= "WebAssembly.Bindings";
64 const string BINDINGS_RUNTIME_CLASS_NAME
= "WebAssembly.Runtime";
65 const string HTTP_ASM_NAME
= "System.Net.Http.WebAssemblyHttpHandler";
66 const string WEBSOCKETS_ASM_NAME
= "WebAssembly.Net.WebSockets";
67 const string BINDINGS_MODULE
= "corebindings.o";
68 const string BINDINGS_MODULE_SUPPORT
= "$tool_prefix/src/binding_support.js";
74 public string filename
;
75 // Path outside build tree
76 public string src_path
;
78 public string bc_path
;
79 // Path of the wasm object file
82 public string app_path
;
83 // Path of the AOT depfile
84 public string aot_depfile_path
;
86 public string linkin_path
;
88 public string linkout_path
;
89 // Linker pdb input path
90 public string linkin_pdb_path
;
91 // Linker pdb output path
92 public string linkout_pdb_path
;
94 public string aotin_path
;
95 // Final output path after IL strip
96 public string final_path
;
97 // Whenever to AOT this assembly
101 static List
<AssemblyData
> assemblies
= new List
<AssemblyData
> ();
110 void AddFlag (OptionSet options
, Flag flag
) {
111 if (flag
is BoolFlag
) {
112 options
.Add (flag
.Name
, s
=> (flag
as BoolFlag
).Setter (true));
113 options
.Add ("no-" + flag
.Name
, s
=> (flag
as BoolFlag
).Setter (false));
115 option_list
.Add (flag
);
118 static List
<Flag
> option_list
= new List
<Flag
> ();
120 static void Usage () {
121 Console
.WriteLine ("Usage: packager.exe <options> <assemblies>");
122 Console
.WriteLine ("Valid options:");
123 Console
.WriteLine ("\t--help Show this help message");
124 Console
.WriteLine ("\t--debugrt Use the debug runtime (default release) - this has nothing to do with C# debugging");
125 Console
.WriteLine ("\t--aot Enable AOT mode");
126 Console
.WriteLine ("\t--aot-interp Enable AOT+INTERP mode");
127 Console
.WriteLine ("\t--prefix=x Set the input assembly prefix to 'x' (default to the current directory)");
128 Console
.WriteLine ("\t--out=x Set the output directory to 'x' (default to the current directory)");
129 Console
.WriteLine ("\t--mono-sdkdir=x Set the mono sdk directory to 'x'");
130 Console
.WriteLine ("\t--deploy=x Set the deploy prefix to 'x' (default to 'managed')");
131 Console
.WriteLine ("\t--vfs=x Set the VFS prefix to 'x' (default to 'managed')");
132 Console
.WriteLine ("\t--template=x Set the template name to 'x' (default to 'runtime.js')");
133 Console
.WriteLine ("\t--asset=x Add specified asset 'x' to list of assets to be copied");
134 Console
.WriteLine ("\t--search-path=x Add specified path 'x' to list of paths used to resolve assemblies");
135 Console
.WriteLine ("\t--copy=always|ifnewer Set the type of copy to perform.");
136 Console
.WriteLine ("\t\t 'always' overwrites the file if it exists.");
137 Console
.WriteLine ("\t\t 'ifnewer' copies or overwrites the file if modified or size is different.");
138 Console
.WriteLine ("\t--profile=x Enable the 'x' mono profiler.");
139 Console
.WriteLine ("\t--aot-assemblies=x List of assemblies to AOT in AOT+INTERP mode.");
140 Console
.WriteLine ("\t--aot-profile=x Use 'x' as the AOT profile.");
141 Console
.WriteLine ("\t--link-mode=sdkonly|all Set the link type used for AOT. (EXPERIMENTAL)");
142 Console
.WriteLine ("\t\t 'sdkonly' only link the Core libraries.");
143 Console
.WriteLine ("\t\t 'all' link Core and User assemblies. (default)");
144 Console
.WriteLine ("\t--pinvoke-libs=x DllImport libraries used.");
145 Console
.WriteLine ("\t--native-lib=x Link the native library 'x' into the final executable.");
146 Console
.WriteLine ("\t--preload-file=x Preloads the file or directory 'x' into the virtual filesystem.");
147 Console
.WriteLine ("\t--embed-file=x Embeds the file or directory 'x' into the virtual filesystem.");
149 Console
.WriteLine ("foo.dll Include foo.dll as one of the root assemblies");
150 Console
.WriteLine ();
152 Console
.WriteLine ("Additional options (--option/--no-option):");
153 foreach (var flag
in option_list
) {
154 if (flag
is BoolFlag
) {
155 Console
.WriteLine (" --" + flag
.Name
+ " (" + flag
.Description
+ ")");
156 Console
.WriteLine (" type: bool default: " + ((flag
as BoolFlag
).DefaultValue
? "true" : "false"));
161 static void Debug (string s
) {
162 Console
.WriteLine (s
);
165 static string FindFrameworkAssembly (string asm
) {
169 static bool Try (string prefix
, string name
, out string out_res
) {
172 string res
= (Path
.Combine (prefix
, name
));
173 if (File
.Exists (res
)) {
174 out_res
= Path
.GetFullPath (res
);
180 static string ResolveWithExtension (string prefix
, string name
) {
183 if (Try (prefix
, name
, out res
))
185 if (Try (prefix
, name
+ ".dll", out res
))
187 if (Try (prefix
, name
+ ".exe", out res
))
192 static string ResolveUser (string asm_name
) {
193 return ResolveWithExtension (app_prefix
, asm_name
);
196 static string ResolveFramework (string asm_name
) {
197 return ResolveWithExtension (framework_prefix
, asm_name
);
200 static string ResolveBcl (string asm_name
) {
201 foreach (var prefix
in bcl_prefixes
) {
202 string res
= ResolveWithExtension (prefix
, asm_name
);
209 static string ResolveBclFacade (string asm_name
) {
210 return ResolveWithExtension (bcl_facades_prefix
, asm_name
);
213 static string Resolve (string asm_name
, out AssemblyKind kind
) {
214 kind
= AssemblyKind
.User
;
215 var asm
= ResolveUser (asm_name
);
219 kind
= AssemblyKind
.Framework
;
220 asm
= ResolveFramework (asm_name
);
224 kind
= AssemblyKind
.Bcl
;
225 asm
= ResolveBcl (asm_name
);
227 asm
= ResolveBclFacade (asm_name
);
231 kind
= AssemblyKind
.None
;
232 throw new Exception ($"Could not resolve {asm_name}");
235 static bool is_sdk_assembly (string filename
) {
236 foreach (var prefix
in bcl_prefixes
)
237 if (filename
.StartsWith (prefix
))
242 static void Import (string ra
, AssemblyKind kind
) {
243 if (!asm_map
.Add (Path
.GetFullPath (ra
)))
245 ReaderParameters rp
= new ReaderParameters();
246 bool add_pdb
= enable_debug
&& File
.Exists (Path
.ChangeExtension (ra
, "pdb"));
248 rp
.ReadSymbols
= true;
249 // Facades do not have symbols
250 rp
.ThrowIfSymbolsAreNotMatching
= false;
251 rp
.SymbolReaderProvider
= new DefaultSymbolReaderProvider(false);
254 var resolver
= new DefaultAssemblyResolver();
255 root_search_paths
.ForEach(resolver
.AddSearchDirectory
);
256 foreach (var prefix
in bcl_prefixes
)
257 resolver
.AddSearchDirectory (prefix
);
258 resolver
.AddSearchDirectory(bcl_facades_prefix
);
259 resolver
.AddSearchDirectory(framework_prefix
);
260 rp
.AssemblyResolver
= resolver
;
263 var image
= ModuleDefinition
.ReadModule (ra
, rp
);
265 //Debug ($"Processing {ra} debug {add_pdb}");
267 var data
= new AssemblyData () { name = image.Assembly.Name.Name, src_path = ra }
;
268 assemblies
.Add (data
);
270 if (add_pdb
&& (kind
== AssemblyKind
.User
|| kind
== AssemblyKind
.Framework
)) {
271 var pdb_path
= Path
.ChangeExtension (Path
.GetFullPath (ra
), "pdb");
272 file_list
.Add (pdb_path
);
273 assemblies_with_dbg_info
.Add (pdb_path
);
276 var parent_kind
= kind
;
278 foreach (var ar
in image
.AssemblyReferences
) {
279 // Resolve using root search paths first
280 AssemblyDefinition resolved
= null;
282 resolved
= image
.AssemblyResolver
.Resolve(ar
, rp
);
286 if (resolved
== null && is_sdk_assembly (ra
))
287 // FIXME: netcore assemblies have missing references
290 if (resolved
!= null) {
291 Import (resolved
.MainModule
.FileName
, parent_kind
);
293 var resolve
= Resolve (ar
.Name
, out kind
);
294 Import(resolve
, kind
);
299 void GenDriver (string builddir
, List
<string> profilers
, ExecMode ee_mode
, bool link_icalls
) {
300 var symbols
= new List
<string> ();
301 foreach (var adata
in assemblies
) {
303 symbols
.Add (String
.Format ("mono_aot_module_{0}_info", adata
.name
.Replace ('.', '_').Replace ('-', '_')));
306 var w
= File
.CreateText (Path
.Combine (builddir
, "driver-gen.c.in"));
308 foreach (var symbol
in symbols
) {
309 w
.WriteLine ($"extern void *{symbol};");
312 w
.WriteLine ("static void register_aot_modules ()");
314 foreach (var symbol
in symbols
)
315 w
.WriteLine ($"\tmono_aot_register_module ({symbol});");
318 foreach (var profiler
in profilers
) {
319 w
.WriteLine ($"void mono_profiler_init_{profiler} (const char *desc);");
320 w
.WriteLine ("EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_" + profiler
+ " (const char *desc) { mono_profiler_init_" + profiler + " (desc); }");
324 case ExecMode
.AotInterp
:
325 w
.WriteLine ("#define EE_MODE_LLVMONLY_INTERP 1");
328 w
.WriteLine ("#define EE_MODE_LLVMONLY 1");
335 w
.WriteLine ("#define LINK_ICALLS 1");
340 public static int Main (string[] args
) {
341 return new Driver ().Run (args
);
365 public bool DebugRuntime
;
366 public bool AddBinding
;
368 public bool LinkIcalls
;
370 public bool LinkerVerbose
;
371 public bool EnableZLib
;
372 public bool EnableFS
;
373 public bool EnableThreads
;
374 public bool NativeStrip
;
376 public bool EnableDynamicRuntime
;
377 public bool LinkerExcludeDeserialization
;
378 public bool EnableCollation
;
381 int Run (string[] args
) {
382 var add_binding
= true;
383 var root_assemblies
= new List
<string> ();
384 enable_debug
= false;
385 string builddir
= null;
386 string sdkdir
= null;
387 string emscripten_sdkdir
= null;
388 var aot_assemblies
= "";
389 app_prefix
= Environment
.CurrentDirectory
;
390 var deploy_prefix
= "managed";
391 var vfs_prefix
= "managed";
392 var use_release_runtime
= true;
393 var enable_aot
= false;
394 var enable_dedup
= true;
395 var print_usage
= false;
396 var emit_ninja
= false;
397 bool build_wasm
= false;
398 bool enable_lto
= false;
399 bool link_icalls
= false;
400 bool gen_pinvoke
= false;
401 bool enable_zlib
= false;
402 bool enable_fs
= false;
403 bool enable_threads
= false;
404 bool enable_dynamic_runtime
= false;
405 bool is_netcore
= false;
406 bool enable_simd
= false;
407 var il_strip
= false;
408 var linker_verbose
= false;
409 var runtimeTemplate
= "runtime.js";
410 var assets
= new List
<string> ();
411 var profilers
= new List
<string> ();
412 var native_libs
= new List
<string> ();
413 var preload_files
= new List
<string> ();
414 var embed_files
= new List
<string> ();
415 var pinvoke_libs
= "";
416 var copyTypeParm
= "default";
417 var copyType
= CopyType
.Default
;
418 var ee_mode
= ExecMode
.Interp
;
419 var linkModeParm
= "all";
420 var linkMode
= LinkMode
.All
;
421 var linkDescriptor
= "";
423 var runtimepack_dir
= "";
424 string coremode
, usermode
;
425 string aot_profile
= null;
426 string wasm_runtime_path
= null;
428 var opts
= new WasmOptions () {
431 DebugRuntime
= false,
434 LinkerVerbose
= false,
439 EnableDynamicRuntime
= false,
440 LinkerExcludeDeserialization
= true,
441 EnableCollation
= false
444 var p
= new OptionSet () {
445 { "nobinding", s => opts.AddBinding = false }
,
446 { "out=", s => out_prefix = s }
,
447 { "appdir=", s => out_prefix = s }
,
448 { "builddir=", s => builddir = s }
,
449 { "mono-sdkdir=", s => sdkdir = s }
,
450 { "emscripten-sdkdir=", s => emscripten_sdkdir = s }
,
451 { "runtimepack-dir=", s => runtimepack_dir = s }
,
452 { "prefix=", s => app_prefix = s }
,
453 { "wasm-runtime-path=", s => wasm_runtime_path = s }
,
454 { "deploy=", s => deploy_prefix = s }
,
455 { "vfs=", s => vfs_prefix = s }
,
456 { "aot", s => ee_mode = ExecMode.Aot }
,
457 { "aot-interp", s => ee_mode = ExecMode.AotInterp }
,
458 { "template=", s => runtimeTemplate = s }
,
459 { "asset=", s => assets.Add(s) }
,
460 { "search-path=", s => root_search_paths.Add(s) }
,
461 { "profile=", s => profilers.Add (s) }
,
462 { "copy=", s => copyTypeParm = s }
,
463 { "aot-assemblies=", s => aot_assemblies = s }
,
464 { "aot-profile=", s => aot_profile = s }
,
465 { "link-mode=", s => linkModeParm = s }
,
466 { "link-descriptor=", s => linkDescriptor = s }
,
467 { "pinvoke-libs=", s => pinvoke_libs = s }
,
468 { "native-lib=", s => native_libs.Add (s) }
,
469 { "preload-file=", s => preload_files.Add (s) }
,
470 { "embed-file=", s => embed_files.Add (s) }
,
471 { "framework=", s => framework = s }
,
472 { "help", s => print_usage = true }
,
475 AddFlag (p
, new BoolFlag ("debug", "enable c# debugging", opts
.Debug
, b
=> opts
.Debug
= b
));
476 AddFlag (p
, new BoolFlag ("debugrt", "enable debug runtime", opts
.DebugRuntime
, b
=> opts
.DebugRuntime
= b
));
477 AddFlag (p
, new BoolFlag ("linker", "enable the linker", opts
.Linker
, b
=> opts
.Linker
= b
));
478 AddFlag (p
, new BoolFlag ("binding", "enable the binding engine", opts
.AddBinding
, b
=> opts
.AddBinding
= b
));
479 AddFlag (p
, new BoolFlag ("link-icalls", "link away unused icalls", opts
.LinkIcalls
, b
=> opts
.LinkIcalls
= b
));
480 AddFlag (p
, new BoolFlag ("il-strip", "strip IL code from assemblies in AOT mode", opts
.ILStrip
, b
=> opts
.ILStrip
= b
));
481 AddFlag (p
, new BoolFlag ("linker-verbose", "set verbose option on linker", opts
.LinkerVerbose
, b
=> opts
.LinkerVerbose
= b
));
482 AddFlag (p
, new BoolFlag ("zlib", "enable the use of zlib for System.IO.Compression support", opts
.EnableZLib
, b
=> opts
.EnableZLib
= b
));
483 AddFlag (p
, new BoolFlag ("enable-fs", "enable filesystem support (through Emscripten's file_packager.py in a later phase)", opts
.EnableFS
, b
=> opts
.EnableFS
= b
));
484 AddFlag (p
, new BoolFlag ("threads", "enable threads", opts
.EnableThreads
, b
=> opts
.EnableThreads
= b
));
485 AddFlag (p
, new BoolFlag ("dynamic-runtime", "enable dynamic runtime (support for Emscripten's dlopen)", opts
.EnableDynamicRuntime
, b
=> opts
.EnableDynamicRuntime
= b
));
486 AddFlag (p
, new BoolFlag ("native-strip", "strip final executable", opts
.NativeStrip
, b
=> opts
.NativeStrip
= b
));
487 AddFlag (p
, new BoolFlag ("simd", "enable SIMD support", opts
.Simd
, b
=> opts
.Simd
= b
));
488 AddFlag (p
, new BoolFlag ("linker-exclude-deserialization", "Link out .NET deserialization support", opts
.LinkerExcludeDeserialization
, b
=> opts
.LinkerExcludeDeserialization
= b
));
489 AddFlag (p
, new BoolFlag ("collation", "enable unicode collation support", opts
.EnableCollation
, b
=> opts
.EnableCollation
= b
));
491 var new_args
= p
.Parse (args
).ToArray ();
492 foreach (var a
in new_args
) {
493 root_assemblies
.Add (a
);
501 if (!Enum
.TryParse(copyTypeParm
, true, out copyType
)) {
502 Console
.WriteLine("Invalid copy value");
507 if (!Enum
.TryParse(linkModeParm
, true, out linkMode
)) {
508 Console
.WriteLine("Invalid link-mode value");
513 if (out_prefix
== null) {
514 Console
.Error
.WriteLine ("The --appdir= argument is required.");
518 enable_debug
= opts
.Debug
;
519 enable_linker
= opts
.Linker
;
520 add_binding
= opts
.AddBinding
;
521 use_release_runtime
= !opts
.DebugRuntime
;
522 il_strip
= opts
.ILStrip
;
523 linker_verbose
= opts
.LinkerVerbose
;
524 gen_pinvoke
= pinvoke_libs
!= "";
525 enable_zlib
= opts
.EnableZLib
;
526 enable_fs
= opts
.EnableFS
;
527 enable_threads
= opts
.EnableThreads
;
528 enable_dynamic_runtime
= opts
.EnableDynamicRuntime
;
529 enable_simd
= opts
.Simd
;
531 if (ee_mode
== ExecMode
.Aot
|| ee_mode
== ExecMode
.AotInterp
)
534 if (enable_aot
|| opts
.Linker
)
535 enable_linker
= true;
538 if (!enable_linker
|| !enable_aot
)
539 enable_dedup
= false;
540 if (enable_aot
|| link_icalls
|| gen_pinvoke
|| profilers
.Count
> 0 || native_libs
.Count
> 0 || preload_files
.Count
> 0 || embed_files
.Count
> 0) {
544 if (!enable_aot
&& link_icalls
)
546 if (ee_mode
!= ExecMode
.Aot
)
547 // Can't strip out IL code in mixed mode, since the interpreter might execute some methods even if they have AOTed code available
550 if (aot_assemblies
!= "") {
551 if (ee_mode
!= ExecMode
.AotInterp
) {
552 Console
.Error
.WriteLine ("The --aot-assemblies= argument requires --aot-interp.");
556 if (link_icalls
&& !enable_linker
) {
557 Console
.Error
.WriteLine ("The --link-icalls option requires the --linker option.");
560 if (framework
!= "") {
561 if (framework
.StartsWith ("net5")) {
563 if (runtimepack_dir
== "") {
564 Console
.Error
.WriteLine ("The --runtimepack-dir= argument is required.");
567 if (!Directory
.Exists (runtimepack_dir
)) {
568 Console
.Error
.WriteLine ($"The directory '{runtimepack_dir}' doesn't exist.");
571 if (!Directory
.Exists (Path
.Combine (runtimepack_dir
, "runtimes", "browser-wasm"))) {
572 Console
.Error
.WriteLine ($"The directory '{runtimepack_dir}' doesn't contain a 'runtimes/browser-wasm' subdirectory.");
575 runtimepack_dir
= Path
.Combine (runtimepack_dir
, "runtimes", "browser-wasm");
577 Console
.Error
.WriteLine ("The only valid value for --framework is 'net5...'");
582 if (aot_profile
!= null && !File
.Exists (aot_profile
)) {
583 Console
.Error
.WriteLine ($"AOT profile file '{aot_profile}' not found.");
587 if (enable_simd
&& !is_netcore
) {
588 Console
.Error
.WriteLine ("--simd is only supported with netcore.");
592 var tool_prefix
= Path
.GetDirectoryName (typeof (Driver
).Assembly
.Location
);
594 //are we working from the tree?
595 if (sdkdir
!= null) {
596 framework_prefix
= Path
.Combine (tool_prefix
, "framework"); //all framework assemblies are currently side built to packager.exe
597 } else if (Directory
.Exists (Path
.Combine (tool_prefix
, "../out/wasm-bcl/wasm"))) {
598 framework_prefix
= Path
.Combine (tool_prefix
, "framework"); //all framework assemblies are currently side built to packager.exe
599 sdkdir
= Path
.Combine (tool_prefix
, "../out");
601 framework_prefix
= Path
.Combine (tool_prefix
, "framework");
602 sdkdir
= tool_prefix
;
604 string bcl_root
= Path
.Combine (sdkdir
, "wasm-bcl");
605 var bcl_prefix
= Path
.Combine (bcl_root
, "wasm");
606 bcl_tools_prefix
= Path
.Combine (bcl_root
, "wasm_tools");
607 bcl_facades_prefix
= Path
.Combine (bcl_prefix
, "Facades");
608 bcl_prefixes
= new List
<string> ();
611 bcl_prefixes
.Add (Path
.Combine (runtimepack_dir
, "native"));
613 bcl_prefixes
.Add (Path
.Combine (runtimepack_dir
, "lib", "net5.0"));
615 bcl_prefixes
.Add (bcl_prefix
);
618 foreach (var ra
in root_assemblies
) {
620 var resolved
= Resolve (ra
, out kind
);
621 Import (resolved
, kind
);
624 var bindings
= ResolveFramework (BINDINGS_ASM_NAME
+ ".dll");
625 Import (bindings
, AssemblyKind
.Framework
);
626 var http
= ResolveFramework (HTTP_ASM_NAME
+ ".dll");
627 Import (http
, AssemblyKind
.Framework
);
628 var websockets
= ResolveFramework (WEBSOCKETS_ASM_NAME
+ ".dll");
629 Import (websockets
, AssemblyKind
.Framework
);
633 var to_aot
= new Dictionary
<string, bool> ();
635 to_aot
["System.Private.CoreLib"] = true;
637 to_aot
["mscorlib"] = true;
638 if (aot_assemblies
!= "") {
639 foreach (var s
in aot_assemblies
.Split (','))
642 foreach (var ass
in assemblies
) {
643 if (aot_assemblies
== "" || to_aot
.ContainsKey (ass
.name
)) {
645 to_aot
.Remove (ass
.name
);
648 if (to_aot
.Count
> 0) {
649 Console
.Error
.WriteLine ("Unknown assembly name '" + to_aot
.Keys
.ToArray ()[0] + "' in --aot-assemblies option.");
654 if (builddir
!= null) {
656 if (!Directory
.Exists (builddir
))
657 Directory
.CreateDirectory (builddir
);
661 if (!Directory
.Exists (out_prefix
))
662 Directory
.CreateDirectory (out_prefix
);
663 var bcl_dir
= Path
.Combine (out_prefix
, deploy_prefix
);
664 if (Directory
.Exists (bcl_dir
))
665 Directory
.Delete (bcl_dir
, true);
666 Directory
.CreateDirectory (bcl_dir
);
667 foreach (var f
in file_list
) {
668 CopyFile(f
, Path
.Combine (bcl_dir
, Path
.GetFileName (f
)), copyType
);
672 if (deploy_prefix
.EndsWith ("/"))
673 deploy_prefix
= deploy_prefix
.Substring (0, deploy_prefix
.Length
- 1);
674 if (vfs_prefix
.EndsWith ("/"))
675 vfs_prefix
= vfs_prefix
.Substring (0, vfs_prefix
.Length
- 1);
677 // wasm core bindings module
678 var wasm_core_bindings
= string.Empty
;
680 wasm_core_bindings
= BINDINGS_MODULE
;
682 // wasm core bindings support file
683 var wasm_core_support
= string.Empty
;
684 var wasm_core_support_library
= string.Empty
;
686 wasm_core_support
= BINDINGS_MODULE_SUPPORT
;
687 wasm_core_support_library
= $"--js-library {BINDINGS_MODULE_SUPPORT}";
689 var runtime_js
= Path
.Combine (emit_ninja
? builddir
: out_prefix
, "runtime.js");
691 File
.Delete (runtime_js
);
692 File
.Copy (runtimeTemplate
, runtime_js
);
694 if (File
.Exists(runtime_js
) && (File
.Exists(runtimeTemplate
))) {
695 CopyFile (runtimeTemplate
, runtime_js
, CopyType
.IfNewer
, $"runtime template <{runtimeTemplate}> ");
697 if (File
.Exists(runtimeTemplate
))
698 CopyFile (runtimeTemplate
, runtime_js
, CopyType
.IfNewer
, $"runtime template <{runtimeTemplate}> ");
700 var runtime_gen
= "\nvar Module = {\n\tonRuntimeInitialized: function () {\n\t\tMONO.mono_load_runtime_and_bcl (\n\t\tconfig.vfs_prefix,\n\t\tconfig.deploy_prefix,\n\t\tconfig.enable_debugging,\n\t\tconfig.file_list,\n\t\tfunction () {\n\t\t\tApp.init ();\n\t\t}\n\t)\n\t},\n};";
701 File
.Delete (runtime_js
);
702 File
.WriteAllText (runtime_js
, runtime_gen
);
707 AssemblyData dedup_asm
= null;
710 dedup_asm
= new AssemblyData () { name
= "aot-instances",
711 filename
= "aot-instances.dll",
712 bc_path
= "$builddir/aot-instances.dll.bc",
713 o_path
= "$builddir/aot-instances.dll.o",
714 app_path
= "$appdir/$deploy_prefix/aot-instances.dll",
715 linkout_path
= "$builddir/linker-out/aot-instances.dll",
718 assemblies
.Add (dedup_asm
);
719 file_list
.Add ("aot-instances.dll");
722 var file_list_str
= string.Join (",", file_list
.Select (f
=> $"\"{Path.GetFileName (f)}\"").Distinct());
723 var config
= String
.Format ("config = {{\n \tvfs_prefix: \"{0}\",\n \tdeploy_prefix: \"{1}\",\n \tenable_debugging: {2},\n \tfile_list: [ {3} ],\n", vfs_prefix
, deploy_prefix
, enable_debug
? "1" : "0", file_list_str
);
725 var config_js
= Path
.Combine (emit_ninja
? builddir
: out_prefix
, "mono-config.js");
726 File
.Delete (config_js
);
727 File
.WriteAllText (config_js
, config
);
729 string wasm_runtime_dir
;
731 wasm_runtime_dir
= Path
.Combine (runtimepack_dir
, "native", "wasm", "runtimes", use_release_runtime
? "release" : "debug");
733 if (wasm_runtime_path
== null)
734 wasm_runtime_path
= Path
.Combine (tool_prefix
, "builds");
737 wasm_runtime_dir
= Path
.Combine (wasm_runtime_path
, use_release_runtime
? "threads-release" : "threads-debug");
738 else if (enable_dynamic_runtime
)
739 wasm_runtime_dir
= Path
.Combine (wasm_runtime_path
, use_release_runtime
? "dynamic-release" : "dynamic-debug");
741 wasm_runtime_dir
= Path
.Combine (wasm_runtime_path
, use_release_runtime
? "release" : "debug");
744 var interp_files
= new List
<string> { "dotnet.js", "dotnet.wasm" }
;
745 if (enable_threads
) {
746 interp_files
.Add ("dotnet.worker.js");
748 foreach (var fname
in interp_files
) {
749 File
.Delete (Path
.Combine (out_prefix
, fname
));
751 Path
.Combine (wasm_runtime_dir
, fname
),
752 Path
.Combine (out_prefix
, fname
));
755 foreach(var asset
in assets
) {
757 Path
.Combine (out_prefix
, Path
.GetFileName (asset
)), copyType
, "Asset: ");
764 if (builddir
== null) {
765 Console
.Error
.WriteLine ("The --builddir argument is required.");
769 var filenames
= new Dictionary
<string, string> ();
770 foreach (var a
in assemblies
) {
771 var assembly
= a
.src_path
;
772 if (assembly
== null)
774 string filename
= Path
.GetFileName (assembly
);
775 if (filenames
.ContainsKey (filename
)) {
776 Console
.WriteLine ("Duplicate input assembly: " + assembly
+ " " + filenames
[filename
]);
779 filenames
[filename
] = assembly
;
783 if (sdkdir
== null) {
784 Console
.WriteLine ("The --mono-sdkdir argument is required.");
787 if (emscripten_sdkdir
== null) {
788 Console
.WriteLine ("The --emscripten-sdkdir argument is required.");
791 GenDriver (builddir
, profilers
, ee_mode
, link_icalls
);
795 string runtime_libdir
;
797 runtime_dir
= "$runtimepack_dir/native";
798 runtime_libdir
= "$runtimepack_dir/native";
800 runtime_dir
= "$mono_sdkdir/wasm-runtime-release";
801 runtime_libdir
= $"{runtime_dir}/lib";
803 string runtime_libs
= "";
804 if (ee_mode
== ExecMode
.Interp
|| ee_mode
== ExecMode
.AotInterp
|| link_icalls
) {
805 runtime_libs
+= $"$runtime_libdir/libmono-ee-interp.a $runtime_libdir/libmono-ilgen.a ";
806 // We need to link the icall table because the interpreter uses it to lookup icalls even if the aot-ed icall wrappers are available
808 runtime_libs
+= $"$runtime_libdir/libmono-icall-table.a ";
810 runtime_libs
+= $"$runtime_libdir/libmonosgen-2.0.a ";
812 runtime_libs
+= $"$runtime_libdir/libSystem.Native.a";
814 runtime_libs
+= $"$runtime_libdir/libmono-native.a";
816 string aot_args
= "llvm-path=$emscripten_sdkdir/upstream/bin,";
817 string profiler_libs
= "";
818 string profiler_aot_args
= "";
819 foreach (var profiler
in profilers
) {
820 profiler_libs
+= $"$runtime_libdir/libmono-profiler-{profiler}-static.a ";
821 if (profiler_aot_args
!= "")
822 profiler_aot_args
+= " ";
823 profiler_aot_args
+= $"--profile={profiler}";
825 string extra_link_libs
= "";
826 foreach (var lib
in native_libs
)
827 extra_link_libs
+= lib
+ " ";
828 if (aot_profile
!= null) {
829 CopyFile (aot_profile
, Path
.Combine (builddir
, Path
.GetFileName (aot_profile
)), CopyType
.IfNewer
, "");
830 aot_args
+= $"profile={aot_profile},profile-only,";
832 if (ee_mode
== ExecMode
.AotInterp
)
833 aot_args
+= "interp,";
839 wasm_runtime_dir
= Path
.GetFullPath (wasm_runtime_dir
);
840 sdkdir
= Path
.GetFullPath (sdkdir
);
841 out_prefix
= Path
.GetFullPath (out_prefix
);
843 string driver_deps
= "";
845 driver_deps
+= " $builddir/icall-table.h";
847 driver_deps
+= " $builddir/pinvoke-table.h";
848 string emcc_flags
= "";
850 emcc_flags
+= "--llvm-lto 1 ";
851 if (enable_zlib
|| is_netcore
)
852 emcc_flags
+= "-s USE_ZLIB=1 ";
854 emcc_flags
+= "-s FORCE_FILESYSTEM=1 ";
855 foreach (var pf
in preload_files
)
856 emcc_flags
+= "--preload-file " + pf
+ " ";
857 foreach (var f
in embed_files
)
858 emcc_flags
+= "--embed-file " + f
+ " ";
859 string emcc_link_flags
= "";
861 emcc_link_flags
+= "-O0 ";
862 string strip_cmd
= "";
863 if (opts
.NativeStrip
)
864 strip_cmd
= " && $wasm_opt --strip-dwarf $out_wasm -o $out_wasm";
866 aot_args
+= "mattr=simd,";
867 emcc_flags
+= "-s SIMD=1 ";
869 if (!use_release_runtime
)
870 // -s ASSERTIONS=2 is very slow
871 emcc_flags
+= "-s ASSERTIONS=1 ";
873 var ninja
= File
.CreateText (Path
.Combine (builddir
, "build.ninja"));
876 ninja
.WriteLine ($"mono_sdkdir = {sdkdir}");
877 ninja
.WriteLine ($"emscripten_sdkdir = {emscripten_sdkdir}");
878 ninja
.WriteLine ($"tool_prefix = {tool_prefix}");
879 ninja
.WriteLine ($"appdir = {out_prefix}");
880 ninja
.WriteLine ($"builddir = .");
882 ninja
.WriteLine ($"runtimepack_dir = {runtimepack_dir}");
883 ninja
.WriteLine ($"wasm_runtime_dir = {wasm_runtime_dir}");
884 ninja
.WriteLine ($"runtime_libdir = {runtime_libdir}");
885 ninja
.WriteLine ($"deploy_prefix = {deploy_prefix}");
886 ninja
.WriteLine ($"bcl_dir = {bcl_prefix}");
887 ninja
.WriteLine ($"bcl_facades_dir = {bcl_facades_prefix}");
888 ninja
.WriteLine ($"framework_dir = {framework_prefix}");
889 ninja
.WriteLine ($"tools_dir = {bcl_tools_prefix}");
890 ninja
.WriteLine ($"emsdk_env = $builddir/emsdk_env.sh");
892 ninja
.WriteLine ($"wasm_core_bindings = $builddir/{BINDINGS_MODULE}");
893 ninja
.WriteLine ($"wasm_core_support = {wasm_core_support}");
894 ninja
.WriteLine ($"wasm_core_support_library = {wasm_core_support_library}");
896 ninja
.WriteLine ("wasm_core_bindings =");
897 ninja
.WriteLine ("wasm_core_support =");
898 ninja
.WriteLine ("wasm_core_support_library =");
901 ninja
.WriteLine ("cross = $runtimepack_dir/native/cross/mono-aot-cross");
903 ninja
.WriteLine ("cross = $mono_sdkdir/wasm-cross-release/bin/wasm32-unknown-none-mono-sgen");
904 ninja
.WriteLine ("emcc = source $emsdk_env && emcc");
905 ninja
.WriteLine ("wasm_opt = $emscripten_sdkdir/upstream/bin/wasm-opt");
906 ninja
.WriteLine ($"emcc_flags = -Oz -g {emcc_flags}-s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_MEMORY=134217728 -s NO_EXIT_RUNTIME=1 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s \"EXTRA_EXPORTED_RUNTIME_METHODS=[\'ccall\', \'cwrap\', \'setValue\', \'getValue\', \'UTF8ToString\']\" -s \"EXPORTED_FUNCTIONS=[\'___cxa_is_pointer_type\', \'___cxa_can_catch\']\" -s \"DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[\'setThrew\', \'memset\']\"");
907 ninja
.WriteLine ($"aot_base_args = llvmonly,asmonly,no-opt,static,direct-icalls,deterministic,{aot_args}");
910 ninja
.WriteLine ("rule aot");
911 ninja
.WriteLine ($" command = MONO_PATH=$mono_path $cross --debug {profiler_aot_args} --aot=$aot_args,$aot_base_args,depfile=$depfile,llvm-outfile=$outfile $src_file");
912 ninja
.WriteLine (" description = [AOT] $src_file -> $outfile");
913 ninja
.WriteLine ("rule aot-instances");
914 ninja
.WriteLine ($" command = MONO_PATH=$mono_path $cross --debug {profiler_aot_args} --aot=$aot_base_args,llvm-outfile=$outfile,dedup-include=$dedup_image $src_files");
915 ninja
.WriteLine (" description = [AOT-INSTANCES] $outfile");
916 ninja
.WriteLine ("rule mkdir");
917 ninja
.WriteLine (" command = mkdir -p $out");
918 ninja
.WriteLine ("rule cp");
919 ninja
.WriteLine (" command = cp $in $out");
920 // Copy $in to $out only if it changed
921 ninja
.WriteLine ("rule cpifdiff");
922 ninja
.WriteLine (" command = if cmp -s $in $out ; then : ; else cp $in $out ; fi");
923 ninja
.WriteLine (" restat = true");
924 ninja
.WriteLine (" description = [CPIFDIFF] $in -> $out");
925 ninja
.WriteLine ("rule create-emsdk-env");
926 ninja
.WriteLine (" command = $emscripten_sdkdir/emsdk construct_env > $out");
927 ninja
.WriteLine ("rule emcc");
928 ninja
.WriteLine (" command = bash -c '$emcc $emcc_flags $flags -c -o $out $in'");
929 ninja
.WriteLine (" description = [EMCC] $in -> $out");
930 ninja
.WriteLine ("rule emcc-link");
931 ninja
.WriteLine ($" command = bash -c '$emcc $emcc_flags {emcc_link_flags} -o $out_js --js-library $tool_prefix/src/library_mono.js --js-library $tool_prefix/src/dotnet_support.js {wasm_core_support_library} $in' {strip_cmd}");
932 ninja
.WriteLine (" description = [EMCC-LINK] $in -> $out_js");
933 ninja
.WriteLine ("rule linker");
934 ninja
.WriteLine (" command = mono $tools_dir/monolinker.exe -out $builddir/linker-out -l none --deterministic --disable-opt unreachablebodies --exclude-feature com,remoting,etw $linker_args || exit 1; mono $tools_dir/wasm-tuner.exe --gen-empty-assemblies $out");
935 ninja
.WriteLine (" description = [IL-LINK]");
936 ninja
.WriteLine ("rule aot-instances-dll");
937 ninja
.WriteLine (" command = echo > aot-instances.cs; csc /deterministic /out:$out /target:library aot-instances.cs");
938 ninja
.WriteLine ("rule gen-runtime-icall-table");
939 ninja
.WriteLine (" command = $cross --print-icall-table > $out");
940 ninja
.WriteLine ("rule gen-icall-table");
941 ninja
.WriteLine (" command = mono $tools_dir/wasm-tuner.exe --gen-icall-table $runtime_table $in > $out");
942 ninja
.WriteLine ("rule gen-pinvoke-table");
943 ninja
.WriteLine (" command = mono $tools_dir/wasm-tuner.exe --gen-pinvoke-table $pinvoke_libs $in > $out");
944 ninja
.WriteLine ("rule ilstrip");
945 ninja
.WriteLine (" command = cp $in $out; mono $tools_dir/mono-cil-strip.exe -q $out");
946 ninja
.WriteLine (" description = [IL-STRIP]");
949 ninja
.WriteLine ("build $appdir: mkdir");
950 ninja
.WriteLine ("build $appdir/$deploy_prefix: mkdir");
951 ninja
.WriteLine ("build $appdir/runtime.js: cpifdiff $builddir/runtime.js");
952 ninja
.WriteLine ("build $appdir/mono-config.js: cpifdiff $builddir/mono-config.js");
957 src_prefix
= Path
.Combine (runtimepack_dir
, "native", "wasm", "src");
959 src_prefix
= Path
.Combine (tool_prefix
, "src");
960 var source_file
= Path
.GetFullPath (Path
.Combine (src_prefix
, "driver.c"));
961 ninja
.WriteLine ($"build $builddir/driver.c: cpifdiff {source_file}");
962 ninja
.WriteLine ($"build $builddir/driver-gen.c: cpifdiff $builddir/driver-gen.c.in");
963 source_file
= Path
.GetFullPath (Path
.Combine (src_prefix
, "pinvoke.c"));
964 ninja
.WriteLine ($"build $builddir/pinvoke.c: cpifdiff {source_file}");
965 source_file
= Path
.GetFullPath (Path
.Combine (src_prefix
, "pinvoke.h"));
966 ninja
.WriteLine ($"build $builddir/pinvoke.h: cpifdiff {source_file}");
968 var pinvoke_file_name
= is_netcore
? "pinvoke-table.h" : "pinvoke-tables-default.h";
969 var pinvoke_file
= Path
.GetFullPath (Path
.Combine (src_prefix
, pinvoke_file_name
));
970 ninja
.WriteLine ($"build $builddir/pinvoke-tables-default.h: cpifdiff {pinvoke_file}");
971 driver_deps
+= $" $builddir/pinvoke-tables-default.h";
973 var driver_cflags
= enable_aot
? "-DENABLE_AOT=1" : "";
976 var bindings_source_file
= Path
.GetFullPath (Path
.Combine (src_prefix
, "corebindings.c"));
977 ninja
.WriteLine ($"build $builddir/corebindings.c: cpifdiff {bindings_source_file}");
979 ninja
.WriteLine ($"build $builddir/corebindings.o: emcc $builddir/corebindings.c | $emsdk_env");
980 ninja
.WriteLine ($" flags = -I{runtime_dir}/include/mono-2.0");
981 driver_cflags
+= " -DCORE_BINDINGS ";
984 driver_cflags
+= " -DGEN_PINVOKE ";
986 driver_cflags
+= " -DENABLE_NETCORE ";
988 ninja
.WriteLine ("build $emsdk_env: create-emsdk-env");
989 ninja
.WriteLine ($"build $builddir/driver.o: emcc $builddir/driver.c | $emsdk_env $builddir/driver-gen.c {driver_deps}");
990 ninja
.WriteLine ($" flags = {driver_cflags} -DDRIVER_GEN=1 -I{runtime_dir}/include/mono-2.0");
991 ninja
.WriteLine ($"build $builddir/pinvoke.o: emcc $builddir/pinvoke.c | $emsdk_env {driver_deps}");
992 ninja
.WriteLine ($" flags = {driver_cflags} -DDRIVER_GEN=1 -I{runtime_dir}/include/mono-2.0");
995 var zlib_source_file
= Path
.GetFullPath (Path
.Combine (src_prefix
, "zlib-helper.c"));
996 ninja
.WriteLine ($"build $builddir/zlib-helper.c: cpifdiff {zlib_source_file}");
998 ninja
.WriteLine ($"build $builddir/zlib-helper.o: emcc $builddir/zlib-helper.c | $emsdk_env");
999 ninja
.WriteLine ($" flags = -s USE_ZLIB=1 -I{runtime_dir}/include/mono-2.0");
1002 ninja
.WriteLine ("build $appdir/dotnet.js: cpifdiff $wasm_runtime_dir/dotnet.js");
1003 ninja
.WriteLine ("build $appdir/dotnet.wasm: cpifdiff $wasm_runtime_dir/dotnet.wasm");
1004 if (enable_threads
) {
1005 ninja
.WriteLine ("build $appdir/dotnet.worker.js: cpifdiff $wasm_runtime_dir/dotnet.worker.js");
1009 ninja
.WriteLine ("build $builddir/aot-in: mkdir");
1011 foreach (var file
in new string[] { "linker-subs.xml", "linker-disable-collation.xml", "linker-preserves.xml" }
) {
1012 var source_file
= Path
.GetFullPath (Path
.Combine (tool_prefix
, "src", file
));
1013 ninja
.WriteLine ($"build $builddir/{file}: cpifdiff {source_file}");
1018 string linker_infiles
= "";
1019 string linker_ofiles
= "";
1020 string dedup_infiles
= "";
1021 if (enable_linker
) {
1022 string path
= Path
.Combine (builddir
, "linker-in");
1023 if (!Directory
.Exists (path
))
1024 Directory
.CreateDirectory (path
);
1026 string aot_in_path
= enable_linker
? "$builddir/linker-out" : "$builddir";
1027 foreach (var a
in assemblies
) {
1028 var assembly
= a
.src_path
;
1029 if (assembly
== null)
1031 string filename
= Path
.GetFileName (assembly
);
1032 var filename_noext
= Path
.GetFileNameWithoutExtension (filename
);
1033 string filename_pdb
= Path
.ChangeExtension (filename
, "pdb");
1034 var source_file_path
= Path
.GetFullPath (assembly
);
1035 var source_file_path_pdb
= Path
.ChangeExtension (source_file_path
, "pdb");
1037 string infile_pdb
= "";
1038 bool emit_pdb
= assemblies_with_dbg_info
.Contains (source_file_path_pdb
);
1039 if (enable_linker
) {
1040 a
.linkin_path
= $"$builddir/linker-in/{filename}";
1041 a
.linkin_pdb_path
= $"$builddir/linker-in/{filename_pdb}";
1042 a
.linkout_path
= $"$builddir/linker-out/{filename}";
1043 a
.linkout_pdb_path
= $"$builddir/linker-out/{filename_pdb}";
1044 linker_infiles
+= $"{a.linkin_path} ";
1045 linker_ofiles
+= $" {a.linkout_path}";
1046 ninja
.WriteLine ($"build {a.linkin_path}: cp {source_file_path}");
1047 if (File
.Exists(source_file_path_pdb
)) {
1048 ninja
.WriteLine($"build {a.linkin_pdb_path}: cp {source_file_path_pdb}");
1049 linker_ofiles
+= $" {a.linkout_pdb_path}";
1050 infile_pdb
= a
.linkout_pdb_path
;
1052 a
.aotin_path
= a
.linkout_path
;
1053 infile
= $"{a.aotin_path}";
1055 infile
= $"$builddir/{filename}";
1056 ninja
.WriteLine ($"build $builddir/{filename}: cpifdiff {source_file_path}");
1057 a
.linkout_path
= infile
;
1059 ninja
.WriteLine ($"build $builddir/{filename_pdb}: cpifdiff {source_file_path_pdb}");
1060 infile_pdb
= $"$builddir/{filename_pdb}";
1064 a
.final_path
= infile
;
1066 ninja
.WriteLine ($"build $builddir/ilstrip-out/{filename} : ilstrip {infile}");
1067 a
.final_path
= $"$builddir/ilstrip-out/{filename}";
1070 ninja
.WriteLine ($"build $appdir/$deploy_prefix/{filename}: cpifdiff {a.final_path}");
1071 if (emit_pdb
&& infile_pdb
!= "")
1072 ninja
.WriteLine ($"build $appdir/$deploy_prefix/{filename_pdb}: cpifdiff {infile_pdb}");
1074 a
.bc_path
= $"$builddir/{filename}.bc";
1075 a
.o_path
= $"$builddir/{filename}.o";
1076 a
.aot_depfile_path
= $"$builddir/linker-out/{filename}.depfile";
1078 if (filename
== "mscorlib.dll") {
1079 // mscorlib has no dependencies so we can skip the aot step if the input didn't change
1080 // The other assemblies depend on their references
1081 infile
= "$builddir/aot-in/mscorlib.dll";
1082 a
.aotin_path
= infile
;
1083 ninja
.WriteLine ($"build {a.aotin_path}: cpifdiff {a.linkout_path}");
1085 ninja
.WriteLine ($"build {a.bc_path}.tmp: aot {infile}");
1086 ninja
.WriteLine ($" src_file={infile}");
1087 ninja
.WriteLine ($" outfile={a.bc_path}.tmp");
1088 ninja
.WriteLine ($" mono_path=$builddir/aot-in:{aot_in_path}");
1089 ninja
.WriteLine ($" depfile={a.aot_depfile_path}");
1091 ninja
.WriteLine ($" aot_args=dedup-skip");
1093 ninja
.WriteLine ($"build {a.bc_path}: cpifdiff {a.bc_path}.tmp");
1094 ninja
.WriteLine ($"build {a.o_path}: emcc {a.bc_path} | $emsdk_env");
1096 ofiles
+= " " + $"{a.o_path}";
1097 bc_files
+= " " + $"{a.bc_path}";
1098 dedup_infiles
+= $" {a.aotin_path}";
1103 * Run the aot compiler in dedup mode:
1104 * mono --aot=<args>,dedup-include=aot-instances.dll <assemblies> aot-instances.dll
1105 * This will process all assemblies and emit all instances into the aot image of aot-instances.dll
1109 * The dedup process will read in the .dedup files created when running with dedup-skip, so add all the
1110 * .bc files as dependencies.
1112 ninja
.WriteLine ($"build {a.bc_path}.tmp: aot-instances | {bc_files} {a.linkout_path}");
1113 ninja
.WriteLine ($" dedup_image={a.filename}");
1114 ninja
.WriteLine ($" src_files={dedup_infiles} {a.linkout_path}");
1115 ninja
.WriteLine ($" outfile={a.bc_path}.tmp");
1116 ninja
.WriteLine ($" mono_path=$builddir/aot-in:{aot_in_path}");
1117 ninja
.WriteLine ($"build {a.app_path}: cpifdiff {a.linkout_path}");
1118 ninja
.WriteLine ($"build {a.linkout_path}: aot-instances-dll");
1119 // The dedup image might not have changed
1120 ninja
.WriteLine ($"build {a.bc_path}: cpifdiff {a.bc_path}.tmp");
1121 ninja
.WriteLine ($"build {a.o_path}: emcc {a.bc_path} | $emsdk_env");
1122 ofiles
+= $" {a.o_path}";
1125 string icall_assemblies
= "";
1126 foreach (var a
in assemblies
) {
1127 if (a
.name
== "mscorlib" || a
.name
== "System")
1128 icall_assemblies
+= $"{a.linkout_path} ";
1130 ninja
.WriteLine ("build $builddir/icall-table.json: gen-runtime-icall-table");
1131 ninja
.WriteLine ($"build $builddir/icall-table.h: gen-icall-table {icall_assemblies}");
1132 ninja
.WriteLine ($" runtime_table=$builddir/icall-table.json");
1135 string pinvoke_assemblies
= "";
1136 foreach (var a
in assemblies
)
1137 pinvoke_assemblies
+= $"{a.linkout_path} ";
1138 ninja
.WriteLine ($"build $builddir/pinvoke-table.h: cpifdiff $builddir/pinvoke-table.h.tmp");
1139 ninja
.WriteLine ($"build $builddir/pinvoke-table.h.tmp: gen-pinvoke-table {pinvoke_assemblies}");
1140 ninja
.WriteLine ($" pinvoke_libs=System.Native,{pinvoke_libs}");
1143 string zlibhelper
= enable_zlib
? "$builddir/zlib-helper.o" : "";
1144 ninja
.WriteLine ($"build $appdir/dotnet.js $appdir/dotnet.wasm: emcc-link $builddir/driver.o $builddir/pinvoke.o {zlibhelper} {wasm_core_bindings} {ofiles} {profiler_libs} {extra_link_libs} {runtime_libs} | $tool_prefix/src/library_mono.js $tool_prefix/src/dotnet_support.js {wasm_core_support} $emsdk_env");
1145 ninja
.WriteLine (" out_js=$appdir/dotnet.js");
1146 ninja
.WriteLine (" out_wasm=$appdir/dotnet.wasm");
1148 if (enable_linker
) {
1150 case LinkMode
.SdkOnly
:
1164 string linker_args
= "";
1166 // Only used by the AOT compiler
1167 linker_args
+= "--explicit-reflection ";
1168 linker_args
+= "--used-attrs-only true ";
1169 linker_args
+= "--substitutions linker-subs.xml ";
1170 linker_infiles
+= "| linker-subs.xml ";
1171 linker_args
+= "-x linker-preserves.xml ";
1172 linker_infiles
+= "linker-preserves.xml ";
1173 if (opts
.LinkerExcludeDeserialization
)
1174 linker_args
+= "--exclude-feature deserialization ";
1175 if (!opts
.EnableCollation
) {
1176 linker_args
+= "--substitutions linker-disable-collation.xml ";
1177 linker_infiles
+= "linker-disable-collation.xml";
1180 linker_args
+= "-b true ";
1182 if (!string.IsNullOrEmpty (linkDescriptor
)) {
1183 linker_args
+= $"-x {linkDescriptor} ";
1184 foreach (var assembly
in root_assemblies
) {
1185 string filename
= Path
.GetFileName (assembly
);
1186 linker_args
+= $"-p {usermode} {filename} -r linker-in/{filename} ";
1189 foreach (var assembly
in root_assemblies
) {
1190 string filename
= Path
.GetFileName (assembly
);
1191 linker_args
+= $"-a linker-in/{filename} ";
1195 if (linker_verbose
) {
1196 linker_args
+= "--verbose ";
1198 linker_args
+= $"-d linker-in -d $bcl_dir -d $bcl_facades_dir -d $framework_dir -c {coremode} -u {usermode} ";
1200 ninja
.WriteLine ("build $builddir/linker-out: mkdir");
1201 ninja
.WriteLine ($"build {linker_ofiles}: linker {linker_infiles}");
1202 ninja
.WriteLine ($" linker_args={linker_args}");
1205 ninja
.WriteLine ("build $builddir/ilstrip-out: mkdir");
1207 foreach(var asset
in assets
) {
1208 var filename
= Path
.GetFileName (asset
);
1209 var abs_path
= Path
.GetFullPath (asset
);
1210 ninja
.WriteLine ($"build $appdir/{filename}: cpifdiff {abs_path}");
1218 static void CopyFile(string sourceFileName
, string destFileName
, CopyType copyType
, string typeFile
= "")
1220 Console
.WriteLine($"{typeFile}cp: {copyType} - {sourceFileName} -> {destFileName}");
1223 case CopyType
.Always
:
1224 File
.Copy(sourceFileName
, destFileName
, true);
1226 case CopyType
.IfNewer
:
1227 if (!File
.Exists(destFileName
))
1229 File
.Copy(sourceFileName
, destFileName
);
1233 var srcInfo
= new FileInfo (sourceFileName
);
1234 var dstInfo
= new FileInfo (destFileName
);
1236 if (srcInfo
.LastWriteTime
.Ticks
> dstInfo
.LastWriteTime
.Ticks
|| srcInfo
.Length
> dstInfo
.Length
)
1237 File
.Copy(sourceFileName
, destFileName
, true);
1239 Console
.WriteLine($" skipping: {sourceFileName}");
1243 File
.Copy(sourceFileName
, destFileName
);