6 using System
.Diagnostics
;
7 using System
.Collections
.Generic
;
13 private string application_name
;
14 private List
<string> external_assemblies
;
15 private List
<string> reference_assemblies
;
16 private List
<string> mdb_files
;
17 private List
<string> csharp_files
;
18 private List
<string> xaml_files
;
19 private List
<string> defines
;
20 private Dictionary
<string, string> resources
;
21 private Dictionary
<string, string> assembly_resources
;
22 private Dictionary
<string, string> content_resources
;
23 private string top_builddir
= null; // Defaults to null
24 private bool desktop
= false; // Defaults to false
25 private bool generate_html
= true; // Defaults to true
26 private bool include_mdb
= true; // Defaults to true
27 private bool verbose
= false; //default to false
28 private bool generate_manifest
= true;
29 private bool list_generated
= false;
30 private string entry_point_type
= null;
31 private string cs_sources
;
33 private bool in_place
= true;
35 const string RuntimeVersion2
= "2.0.31005.0";
36 const string RuntimeVersion3
= "3.0.40624.0";
38 private string RuntimeVersion
= RuntimeVersion2
;
40 public string CSSources
{
41 get { return cs_sources; }
42 set { cs_sources = value; }
45 public string EntryPointType
{
46 get { return entry_point_type; }
47 set { entry_point_type = value; }
50 public bool GenerateManifest
{
51 get { return generate_manifest; }
52 set { generate_manifest = value; }
55 public bool GenerateHtml
{
56 get { return generate_html; }
57 set { generate_html = value; }
61 get { return desktop; }
62 set { desktop = value; }
65 public string TopBuildDir
{
66 get { return top_builddir; }
67 set { top_builddir = value; }
70 public bool IncludeMdb
{
71 get { return include_mdb; }
72 set { include_mdb = value; }
76 get { return verbose; }
77 set { verbose = value; }
80 public bool ListGenerated
{
81 get { return list_generated; }
82 set { list_generated = value; }
90 public string ApplicationName
{
92 if (application_name
== null) {
93 DirectoryInfo di
= new DirectoryInfo (Directory
.GetCurrentDirectory ());
94 application_name
= di
.Name
;
95 application_name
.Replace ("-", "_");
98 return application_name
;
101 application_name
= value;
105 public List
<string> ReferenceAssemblies
{
107 if (reference_assemblies
== null)
108 reference_assemblies
= new List
<string> ();
109 return reference_assemblies
;
113 public List
<string> ExternalAssemblies
{
115 if (external_assemblies
== null)
116 external_assemblies
= new List
<string> ();
117 return external_assemblies
;
121 public List
<string> MdbFiles
{
123 if (mdb_files
== null)
124 mdb_files
= new List
<string> ();
129 public List
<string> CSharpFiles
{
131 if (csharp_files
== null)
132 csharp_files
= new List
<string> ();
137 public List
<string> XamlFiles
{
139 if (xaml_files
== null)
140 xaml_files
= new List
<string> ();
145 public List
<string> Defines
{
148 defines
= new List
<string> ();
153 public Dictionary
<string, string> Resources
{
155 if (resources
== null)
156 resources
= new Dictionary
<string, string> ();
161 public Dictionary
<string, string> AssemblyResources
{
163 if (assembly_resources
== null)
164 assembly_resources
= new Dictionary
<string, string> ();
165 return assembly_resources
;
169 public Dictionary
<string, string> ContentResources
{
171 if (content_resources
== null)
172 content_resources
= new Dictionary
<string, string> ();
173 return content_resources
;
177 public string TmpDir { get; set; }
178 public string WorkingDir { get; set; }
179 public string OutputDir { get; set; }
180 public bool InPlace
{
181 get { return in_place; }
182 set { in_place = value; }
187 return (CreateManifest ()
188 && CreateCodeBehind ()
189 && CreateResources ()
190 && CreateApplicationAssembly ()
192 && CreateHtmlWrapper ());
195 public bool CreateManifest ()
197 string AppManifest_Filename
= "AppManifest.xaml";
199 if (!GenerateManifest
)
203 Console
.WriteLine (AppManifest_Filename
);
207 StringBuilder manifest
= new StringBuilder ();
209 manifest
.Append ("<Deployment xmlns=\"http://schemas.microsoft.com/client/2007/deployment\"");
210 manifest
.Append (" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" ");
211 manifest
.AppendFormat ("EntryPointAssembly=\"{0}\" EntryPointType=\"", ApplicationName
);
212 if (entry_point_type
!= null)
213 manifest
.Append (entry_point_type
);
215 manifest
.AppendFormat ("{0}.App", ApplicationName
);
216 manifest
.AppendFormat ("\" RuntimeVersion=\"{0}\">\n", RuntimeVersion
);
218 manifest
.AppendLine (" <Deployment.Parts>");
220 foreach (string assembly
in ReferenceAssemblies
) {
221 manifest
.AppendFormat (" <AssemblyPart x:Name=\"{0}\" Source=\"{1}\" />\n", Path
.GetFileNameWithoutExtension (assembly
), Path
.GetFileName (assembly
));
223 manifest
.AppendFormat (" <AssemblyPart x:Name=\"{0}\" Source=\"{1}.dll\" />\n", ApplicationName
, ApplicationName
);
225 manifest
.AppendLine (" </Deployment.Parts>");
226 manifest
.AppendLine ("</Deployment>");
228 File
.WriteAllText (AppManifest_Filename
, manifest
.ToString ());
233 public bool CreateCodeBehind ()
236 foreach (string xaml_file
in XamlFiles
) {
237 if (Path
.GetFileName (xaml_file
) == "AppManifest.xaml")
239 Console
.WriteLine ("{0}.g.cs", Path
.GetFileName (xaml_file
));
244 StringBuilder xamlg_args
= new StringBuilder ();
246 xamlg_args
.AppendFormat (" -sl2app:{0} ", ApplicationName
);
247 xamlg_args
.AppendFormat (" -root:{0} ", WorkingDir
);
249 foreach (string xaml_file
in XamlFiles
) {
250 if (Path
.GetFileName (xaml_file
) == "AppManifest.xaml")
252 //xamlg_args.AppendFormat (" {0}", Path.GetFileName (xaml_file));
253 xamlg_args
.AppendFormat (" \"{0}\"", xaml_file
);
256 return RunTool ("xamlg",
257 "tools/xamlg/xamlg.exe",
258 xamlg_args
.ToString ());
262 public bool CreateResources ()
265 Console
.WriteLine ("{0}.g.resources", ApplicationName
);
269 StringBuilder respack_args
= new StringBuilder ();
271 respack_args
.AppendFormat ("{0}.g.resources ", ApplicationName
);
273 foreach (string xaml_file
in XamlFiles
) {
274 if (Path
.GetFileName (xaml_file
) == "AppManifest.xaml")
276 //respack_args.AppendFormat (" {0}", Path.GetFileName (xaml_file));
277 respack_args
.AppendFormat (" \"{0}\"", xaml_file
);
280 foreach (KeyValuePair
<string, string> pair
in Resources
)
281 respack_args
.AppendFormat (" \"{0},{1}\"", pair
.Value
, pair
.Key
);
283 return RunTool ("respack",
284 "tools/respack/respack.exe",
285 respack_args
.ToString ());
288 public bool CreateApplicationAssembly ()
291 Console
.WriteLine ("{0}.dll", ApplicationName
);
295 StringBuilder compiler_args
= new StringBuilder ();
298 compiler_args
.Append (" -d:DESKTOP ");
299 foreach (string define
in Defines
) {
300 compiler_args
.AppendFormat (" -d:{0} ", define
);
303 compiler_args
.AppendFormat (" -debug+ -target:library -out:{0}.dll ", ApplicationName
);
305 foreach (string asm
in ReferenceAssemblies
) {
306 compiler_args
.AppendFormat (" -r:\"{0}\" ", asm
);
309 foreach (string asm
in ExternalAssemblies
) {
310 compiler_args
.AppendFormat (" -r:{0} ", asm
);
313 if (desktop
&& top_builddir
== null) {
314 compiler_args
.Append (" -pkg:silverdesktop ");
315 compiler_args
.Append (" -pkg:gtksilver ");
318 foreach (string cs
in CSharpFiles
) {
319 if (cs
.EndsWith (".g.cs"))
321 compiler_args
.AppendFormat (" \"{0}\" ", cs
);
324 foreach (string xaml
in XamlFiles
) {
325 if (Path
.GetFileName (xaml
) == "AppManifest.xaml")
327 if (!File
.Exists (Path
.GetFileName (xaml
) + ".g.cs"))
329 compiler_args
.AppendFormat (" {0}.g.cs ", Path
.GetFileName (xaml
));
332 compiler_args
.AppendFormat (" -resource:{0}.g.resources ", ApplicationName
);
334 foreach (KeyValuePair
<string, string> pair
in AssemblyResources
)
335 compiler_args
.AppendFormat (" -resource:\"{0},{1}\"", pair
.Value
, pair
.Key
);
338 return RunProcess ("gmcs", compiler_args
.ToString());
340 return Run21Tool ("smcs",
341 "class/lib/2.1/smcs.exe",
342 compiler_args
.ToString());
345 public bool CreateXap ()
348 Console
.WriteLine ("{0}.xap", ApplicationName
);
352 StringBuilder zip_args
= new StringBuilder ();
353 zip_args
.AppendFormat (" {0}.xap ", ApplicationName
);
355 foreach (string asm
in ReferenceAssemblies
) {
356 zip_args
.AppendFormat (" {0} ", Path
.GetFileName (asm
));
358 foreach (string mdb
in MdbFiles
) {
359 zip_args
.AppendFormat (" {0} ", Path
.GetFileName (mdb
));
362 zip_args
.AppendFormat (" AppManifest.xaml ");
363 zip_args
.AppendFormat (" {0}.dll ", ApplicationName
);
364 zip_args
.AppendFormat (" {0}.dll.mdb ", ApplicationName
);
366 foreach (KeyValuePair
<string, string> pair
in ContentResources
)
367 zip_args
.AppendFormat (" " + pair
.Value
);
369 return RunProcess ("zip", zip_args
.ToString ());
372 public bool CreateHtmlWrapper ()
378 Console
.WriteLine ("{0}.html", ApplicationName
);
382 StringBuilder xaml2html_args
= new StringBuilder ();
384 xaml2html_args
.AppendFormat (" {0}.xap ", ApplicationName
);
386 return RunTool ("xaml2html",
387 "tools/xaml2html/xaml2html.exe",
388 xaml2html_args
.ToString ());
391 private bool Run21Tool (string filename
, string builddir_exe
, string args
)
393 string old_mono_path
= Environment
.GetEnvironmentVariable ("MONO_PATH");
394 if (TopBuildDir
!= null) {
395 string new_mono_path
= Path
.Combine (
397 Path
.Combine (TopBuildDir
, "class"),
400 if (!string.IsNullOrEmpty (old_mono_path
))
401 new_mono_path
= string.Format ("{0}:{1}", new_mono_path
, old_mono_path
);
402 Environment
.SetEnvironmentVariable ("MONO_PATH", new_mono_path
);
405 bool rv
= RunTool (filename
, builddir_exe
, args
);
407 if (TopBuildDir
!= null)
408 Environment
.SetEnvironmentVariable ("MONO_PATH", old_mono_path
);
414 private bool RunTool (string filename
, string builddir_exe
, string args
)
416 if (top_builddir
!= null) {
417 bool need_smcs_hack
= false;
418 if (filename
== "smcs")
419 need_smcs_hack
= true;
421 args
= String
.Format ("{3}{0}/{1} {2}", top_builddir
, builddir_exe
, args
,
422 need_smcs_hack
? "--runtime=moonlight --security=temporary-smcs-hack " : "");
425 return RunProcess (filename
, args
);
428 private bool RunProcess (string filename
, string args
)
431 Console
.WriteLine ("Running {0} {1}", filename
, args
);
433 Process process
= new Process ();
435 process
.StartInfo
.FileName
= filename
;
436 process
.StartInfo
.Arguments
= args
;
438 process
.StartInfo
.CreateNoWindow
= true;
439 process
.StartInfo
.UseShellExecute
= false;
443 process
.WaitForExit ();
445 return (process
.ExitCode
== 0);
448 static void ShowHelp (OptionSet os
)
450 Console
.WriteLine ("mxap usage is: mxap [options] [directory]");
451 Console
.WriteLine ();
452 os
.WriteOptionDescriptions (Console
.Out
);
455 void AddResource (string v
)
457 if (string.IsNullOrEmpty (v
))
460 string name
, filename
;
461 bool local
= Path
.GetFullPath (v
).StartsWith (Path
.GetFullPath ("."));
462 int comma
= v
.IndexOf (',');
468 name
= filename
= Path
.GetFileName (v
);
470 File
.Copy (v
, Path
.Combine (TmpDir
, Path
.GetFileName (v
)));
472 File
.Copy (v
, Path
.Combine (WorkingDir
, Path
.GetFileName (v
)));
475 name
= v
.Substring (comma
+ 1);
476 filename
= v
.Substring (0, comma
);
478 File
.Copy (filename
, Path
.Combine (TmpDir
, Path
.GetFileName (filename
)));
479 filename
= Path
.Combine (TmpDir
, Path
.GetFileName (filename
));
483 Resources
.Add (name
, filename
);
486 void AddAssemblyResource (string v
)
488 if (string.IsNullOrEmpty (v
))
491 string name
, filename
;
493 bool local
= Path
.GetFullPath (v
).StartsWith (Path
.GetFullPath ("."));
494 int comma
= v
.IndexOf (',');
497 name
= ApplicationName
+ "." + v
.Replace ('/', '.');
500 name
= ApplicationName
+ "." + Path
.GetFileName (v
);
501 filename
= Path
.GetFileName (v
);
503 File
.Copy (v
, Path
.Combine (TmpDir
, filename
));
505 File
.Copy (v
, Path
.Combine (WorkingDir
, filename
));
508 name
= v
.Substring (comma
+ 1);
509 filename
= v
.Substring (0, comma
);
511 File
.Copy (filename
, Path
.Combine (TmpDir
, Path
.GetFileName (filename
)));
512 filename
= Path
.Combine (TmpDir
, Path
.GetFileName (filename
));
516 AssemblyResources
.Add (name
, filename
);
519 void AddContentResource (string v
)
521 if (string.IsNullOrEmpty (v
))
524 string name
, filename
;
525 bool local
= Path
.GetFullPath (v
).StartsWith (Path
.GetFullPath ("."));
526 int comma
= v
.IndexOf (',');
532 name
= filename
= Path
.GetFileName (v
);
534 File
.Copy (v
, Path
.Combine (TmpDir
, Path
.GetFileName (v
)));
536 File
.Copy (v
, Path
.Combine (WorkingDir
, Path
.GetFileName (v
)));
539 name
= v
.Substring (comma
+ 1);
540 filename
= v
.Substring (0, comma
);
542 File
.Copy (filename
, Path
.Combine (TmpDir
, Path
.GetFileName (filename
)));
543 filename
= Path
.Combine (TmpDir
, Path
.GetFileName (filename
));
547 ContentResources
.Add (name
, filename
);
550 void SetRuntimeVersion (string v
)
554 RuntimeVersion
= RuntimeVersion2
;
557 RuntimeVersion
= RuntimeVersion3
;
565 static void DoClean (string app
)
567 File
.Delete (app
+ ".dll");
568 File
.Delete (app
+ ".dll.mdb");
569 File
.Delete (app
+ ".g.resources");
570 File
.Delete (app
+ ".html");
571 File
.Delete (app
+ ".xap");
572 File
.Delete ("AppManifest.xaml");
573 foreach (string path
in Directory
.GetFiles (Directory
.GetCurrentDirectory(), "*.g.cs"))
577 static void RecursiveCopy (string source
, string dir
, string dest
)
579 foreach (string file
in Directory
.GetFiles (source
+ dir
))
580 File
.Copy (file
, Path
.Combine (dest
+ dir
, Path
.GetFileName (file
)));
581 foreach (string d
in Directory
.GetDirectories (source
+ dir
)) {
582 string d1
= d
.Replace (source
, "");
583 Directory
.CreateDirectory (dest
+ d1
);
584 RecursiveCopy (source
, d1
, dest
);
589 static bool ParseBool (string v
, bool defaul
) {
590 if (v
== null) return true;
592 if (bool.TryParse (v
, out ret
))
594 if (v
.ToLower() == "no") return false;
595 if (v
.ToLower() == "yes") return true;
599 public static int Main (string [] args
)
601 MXap mxap
= new MXap ();
604 List
<string> resources
= new List
<string>();
605 List
<string> aresources
= new List
<string>();
606 List
<string> cresources
= new List
<string>();
607 string resourceFile
= null;
608 string aresourceFile
= null;
609 string cresourceFile
= null;
611 mxap
.Cd
= Directory
.GetCurrentDirectory ();
613 var p
= new OptionSet () {
614 { "h|?|help", v => help = v != null }
,
615 { "generate-html:", v => mxap.GenerateHtml = ParseBool (v, mxap.GenerateHtml) }
,
616 { "include-mdb:", v => mxap.IncludeMdb = ParseBool (v, mxap.IncludeMdb) }
,
617 { "application-name=", v => mxap.ApplicationName = v }
,
618 { "generate-manifest:", v => mxap.GenerateManifest = ParseBool (v, mxap.GenerateManifest) }
,
619 { "use-existing-manifest", v => mxap.GenerateManifest = v == null }
,
620 { "entry-point-type=", v => mxap.EntryPointType = v }
,
621 { "cs-sources=", v => mxap.CSSources = v }
,
622 { "res-sources=", v => resourceFile = v }
,
623 { "ares-sources=", v => aresourceFile = v }
,
624 { "cres-sources=", v => cresourceFile = v }
,
625 { "desktop:", v => mxap.Desktop = ParseBool (v, mxap.Desktop) }
,
626 { "builddirhack=", v => mxap.TopBuildDir = v }
,
627 { "r=|reference=", v => mxap.ExternalAssemblies.Add (v) }
,
628 { "l:|list-generated:", v => mxap.ListGenerated = ParseBool (v, mxap.ListGenerated) }
,
629 { "v:|verbose:", v => mxap.Verbose = ParseBool (v, mxap.Verbose) }
,
630 { "res=|resource=", "-res=filename[,resource name]", v => resources.Add (v) }
,
631 { "ares=|assembly-resource=", "-ares=filename[,resource name]", v => aresources.Add (v) }
,
632 { "cres=|content-resource=", "-cres=filename[,resource name]", v => cresources.Add (v) }
,
633 { "d:|define:", "-d:name", v => mxap.Defines.Add (v) }
,
634 { "clean", "Removes generated files. Use with caution!", v => clean = v != null }
,
635 { "out=|output-dir=", v => mxap.OutputDir = v }
,
636 { "inplace:", "Don't use a temporary directory", v => mxap.InPlace = ParseBool (v, mxap.InPlace) }
,
637 { "runtime-version=|rv=", String.Format ("Select the Silverlight Runtime Version (2 = {0}
, 3 = {1}
, or use the full version
string)", RuntimeVersion2, RuntimeVersion3), v => mxap.SetRuntimeVersion (v) }
640 List<string> extra = null;
642 extra = p.Parse(args);
643 } catch (OptionException){
644 Console.WriteLine ("Try `mxap
--help
' for more information.");
654 DoClean (mxap.ApplicationName);
659 mxap.Cd = Path.GetFullPath (extra [0]);
661 if (mxap.TopBuildDir == null && mxap.ExternalAssemblies.Count > 0) {
662 Console.Error.WriteLine ("--reference requires --builddirhack");
666 if (mxap.OutputDir == null)
667 mxap.OutputDir = mxap.Cd;
669 mxap.OutputDir = Path.GetFullPath (mxap.OutputDir);
671 Directory.SetCurrentDirectory (mxap.Cd);
672 mxap.WorkingDir = mxap.Cd;
674 Console.WriteLine ("Using source directory " + mxap.WorkingDir);
677 mxap.TmpDir = Path.Combine (Path.GetTempPath(), Path.GetRandomFileName ());
680 Console.WriteLine ("Using temporary directory " + mxap.TmpDir);
682 Directory.CreateDirectory (mxap.TmpDir);
683 RecursiveCopy (mxap.WorkingDir, "", mxap.TmpDir);
686 if (resourceFile != null)
687 foreach (string res in File.ReadAllLines (resourceFile))
688 mxap.AddResource (res);
690 if (aresourceFile != null)
691 foreach (string res in File.ReadAllLines (aresourceFile))
692 mxap.AddAssemblyResource (res);
694 if (cresourceFile != null)
695 foreach (string res in File.ReadAllLines (cresourceFile))
696 mxap.AddContentResource (res);
698 foreach (string res in resources) {
699 mxap.AddResource (res);
702 foreach (string res in aresources) {
703 mxap.AddAssemblyResource (res);
706 foreach (string res in cresources) {
707 mxap.AddContentResource (res);
711 Directory.SetCurrentDirectory (mxap.TmpDir);
712 mxap.WorkingDir = mxap.TmpDir;
715 mxap.ReferenceAssemblies.AddRange (Directory.GetFiles (mxap.WorkingDir, "*.dll"));
716 mxap.XamlFiles.AddRange (Directory.GetFiles (mxap.WorkingDir, "*.xaml"));
717 if (mxap.CSSources == null) {
718 mxap.CSharpFiles.AddRange (Directory.GetFiles (mxap.WorkingDir, "*.cs"));
720 mxap.CSharpFiles.AddRange (File.ReadAllLines (mxap.CSSources));
724 mxap.MdbFiles.AddRange (Directory.GetFiles (mxap.WorkingDir, "*.mdb"));
726 if (mxap.XamlFiles.Count == 0 || mxap.CSharpFiles.Count == 0) {
727 Console.Error.WriteLine ("No XAML files or C# files found");
732 // Make sure we didn't
add the Application assembly
into the referenced assemblies
733 DirectoryInfo info
= new DirectoryInfo (mxap
.WorkingDir
);
735 if (mxap
.ReferenceAssemblies
.Contains (Path
.Combine (mxap
.WorkingDir
, info
.Name
+ ".dll")))
736 mxap
.ReferenceAssemblies
.Remove (Path
.Combine (mxap
.WorkingDir
, info
.Name
+ ".dll"));
742 Console
.WriteLine ("Using Output directory " + mxap
.OutputDir
);
744 if (!Directory
.Exists (mxap
.OutputDir
)) {
745 Console
.WriteLine ("warning: output directory doesn't exist, defaulting to source directory " + mxap
.Cd
+ " ...");
746 mxap
.OutputDir
= mxap
.Cd
;
749 if (!mxap
.InPlace
|| mxap
.Cd
!= mxap
.OutputDir
) {
750 string app
= mxap
.ApplicationName
;
751 File
.Copy (Path
.Combine (mxap
.WorkingDir
, app
+ ".dll"), Path
.Combine (mxap
.OutputDir
, app
+ ".dll"), true);
752 File
.Copy (Path
.Combine (mxap
.WorkingDir
, app
+ ".dll.mdb"), Path
.Combine (mxap
.OutputDir
, app
+ ".dll.mdb"), true);
753 File
.Copy (Path
.Combine (mxap
.WorkingDir
, app
+ ".g.resources"), Path
.Combine (mxap
.OutputDir
, app
+ ".g.resources"), true);
754 File
.Copy (Path
.Combine (mxap
.WorkingDir
, app
+ ".html"), Path
.Combine (mxap
.OutputDir
, app
+ ".html"), true);
755 File
.Copy (Path
.Combine (mxap
.WorkingDir
, app
+ ".xap"), Path
.Combine (mxap
.OutputDir
, app
+ ".xap"), true);
756 File
.Copy (Path
.Combine (mxap
.WorkingDir
, "AppManifest.xaml"), Path
.Combine (mxap
.OutputDir
, "AppManifest.xaml"), true);
757 foreach (string file
in Directory
.GetFiles (mxap
.WorkingDir
, "*.g.cs"))
758 File
.Copy (file
, Path
.Combine (mxap
.OutputDir
, Path
.GetFileName (file
)), true);
761 Directory
.Delete (mxap
.TmpDir
, true);