protected override BuildResult Build(IProgressMonitor monitor, SolutionEntityItem item, ConfigurationSelector configuration)
        {
            MonobjcProject proj = item as MonobjcProject;
            if (proj == null || proj.CompileTarget != CompileTarget.Exe)
                return base.Build(monitor, item, configuration);

            BuildResult result = base.Build(monitor, item, configuration);
            if (result.ErrorCount > 0)
                return result;

            var conf = (MonobjcProjectConfiguration) proj.GetConfiguration(configuration);

            // Create directories
            monitor.BeginTask("Creating application bundle", 0);
            foreach (var path in new [] { conf.ResourcesDirectory, conf.MacOSDirectory }) {
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
            }
            monitor.EndTask();

            string exeName = Path.GetFileNameWithoutExtension(conf.CompiledOutputName);

            // Write Info.plist into 'Contents' directory

            monitor.BeginTask("Updating application manifest", 0);
            var doc = new PlistDocument();
            var docRoot = new PlistDictionary();
              			docRoot["CFBundleExecutable"]            = exeName;
            docRoot["CFBundleInfoDictionaryVersion"] = "6.0";
            docRoot["CFBundlePackageType"]           = "APPL";
            docRoot["CFBundleName"]                  = proj.BundleDisplayName ?? proj.Name;
            docRoot["CFBundleDisplayName"]           = proj.BundleDisplayName ?? proj.Name;
            docRoot["CFBundleIdentifier"]            = proj.BundleIdentifier ?? String.Format("com.yourcompany.{0}", proj.Name);
            docRoot["CFBundleVersion"]               = proj.BundleVersion ?? "1.0";
            docRoot["CFBundleDevelopmentRegion"]     = proj.BundleDevelopmentRegion ?? "English";

            FilePath icon = proj.BundleIcon.ToRelative (proj.BaseDirectory);
            if (!(icon.IsNullOrEmpty || icon.ToString () == "."))
                docRoot["CFBundleIconFile"] = icon.FileName;

            if (!String.IsNullOrEmpty (proj.MainNibFile.ToString ()))
                docRoot["NSMainNibFile"] = Path.GetFileNameWithoutExtension(proj.MainNibFile.ToString ());

            doc.Root = docRoot;

            var plistOut = conf.ContentsDirectory.Combine("Info.plist");
            using (XmlTextWriter writer = new XmlTextWriter(plistOut, Encoding.UTF8)) {
                doc.Write(writer);
            }
            monitor.EndTask();

            // Copy project binary into 'Resources' directory
            monitor.BeginTask("Copying application binary", 0);
            File.Copy(conf.CompiledOutputName, conf.ResourcesDirectory.Combine(conf.CompiledOutputName.FileName), true);
            if (File.Exists(conf.CompiledOutputName + ".mdb"))
                File.Copy(conf.CompiledOutputName + ".mdb", conf.ResourcesDirectory.Combine(conf.CompiledOutputName.FileName + ".mdb"), true);
            monitor.EndTask();

            // Copy references into 'Resources' directory
            var references = BuildUtils.GetReferencesFilePairs(proj, configuration);
            foreach (var pair in references) {
                pair.EnsureOutputDirectory();
                monitor.Log.WriteLine("Copying '{0}' to '{1}'", pair.Input, pair.Output);
                File.Copy(pair.Input, pair.Output, true);
                monitor.Step(1);
            }
            monitor.EndTask();

            // Write launcher script into 'MacOS' directory
            monitor.BeginTask("Writing launcher script", 0);
            string scriptPath = conf.MacOSDirectory.Combine(exeName);
            var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("LaunchScript.sh");
            using (StreamReader reader = new StreamReader(stream)) {
                using (StreamWriter writer = new StreamWriter(scriptPath)) {
                    writer.Write(reader.ReadToEnd());
                }
            }

            // Make executable (755)
            new UnixFileInfo(scriptPath).FileAccessPermissions = FileAccessPermissions.UserReadWriteExecute |
                FileAccessPermissions.GroupRead | FileAccessPermissions.GroupExecute |
                FileAccessPermissions.OtherRead | FileAccessPermissions.OtherExecute;

            monitor.EndTask();

            return result;
        }
		static void WriteXcent (PlistDocument doc, string file)
		{
			//write the plist to a byte[] as UTF8 without a BOM
			var ms = new MemoryStream ();
			var xmlSettings = new XmlWriterSettings () {
				Encoding = new UTF8Encoding (false), //no BOM
				CloseOutput = false,
				Indent = true,
				IndentChars = "\t",
				NewLineChars = "\n",
			};
			using (var writer = XmlTextWriter.Create (ms, xmlSettings))
				doc.Write (writer);
			
			//HACK: workaround for bug in Apple's entitlements XML parser
			//having written to a UTF8 stream to convince the xmlwriter to do the right thing,
			//we now convert to string and back to do some substitutions to work around bugs
			//in Apple's braindead entitlements XML parser.
			//Specifically, it chokes on "<true />" but accepts "<true">
			//Hence, to be on the safe side, we produce EXACTLY the same format
			var sb = new StringBuilder (Encoding.UTF8.GetString (ms.GetBuffer ()));
			sb.Replace ("-//Apple Computer//DTD PLIST 1.0//EN", "-//Apple//DTD PLIST 1.0//EN");
			sb.Replace ("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			sb.Replace ("\n\t", "\n");
			sb.Replace (" />\n", "/>\n");
			sb.Append ("\n");
			var buf = Encoding.UTF8.GetBytes (sb.ToString ());
			
			//write the xcent file with the magic header, length, and the plist
			byte[] magic = new byte[] { 0xfa, 0xde, 0x71, 0x71 };
			byte[] fileLen = Mono.DataConverter.BigEndian.GetBytes ((uint)buf.Length + 8); // 8 = magic.length + magicLen.Length
			using (var fs = File.Open (file, FileMode.Create)) {
				fs.Write (magic, 0, magic.Length);
				fs.Write (fileLen, 0, fileLen.Length);
				fs.Write (buf, 0, (int)buf.Length);
			}
		}
        public override bool Execute()
        {
            string displayName = DisplayName ?? Name;
            string identifier  = Identifier ?? String.Format("com.yourcompany.{0}", Name);
            string version     = Version ?? "1.0";
            string region      = DevelopmentRegion ?? "English";

            var doc = new PlistDocument();
            var docRoot = new PlistDictionary();
              			docRoot["CFBundleExecutable"]            = ExeName;
            docRoot["CFBundleInfoDictionaryVersion"] = "6.0";
            docRoot["CFBundlePackageType"]           = "APPL";
            docRoot["CFBundleName"]                  = displayName;
            docRoot["CFBundleDisplayName"]           = displayName;
            docRoot["CFBundleIdentifier"]            = identifier;
            docRoot["CFBundleVersion"]               = version;
            docRoot["CFBundleDevelopmentRegion"]     = region;

            if (!String.IsNullOrEmpty(Icon))
                docRoot["CFBundleIconFile"] = Icon;

            if (!String.IsNullOrEmpty(MainNibFile))
                docRoot["NSMainNibFile"] = Path.GetFileNameWithoutExtension(MainNibFile);

            doc.Root = docRoot;

            using (XmlTextWriter writer = new XmlTextWriter(FileName, Encoding.UTF8)) {
                doc.Write(writer);
            }

            Log.LogMessage("Wrote {0}", FileName);

            return true;
        }
		static BuildResult CreateMergedPlist (IProgressMonitor monitor, IPhoneProjectConfiguration conf,
			ProjectFile template, string outPath,
			Func<IPhoneProjectConfiguration, PlistDocument,BuildResult> merge)
		{
			var result = new BuildResult ();
			
			var doc = new PlistDocument ();
			if (template != null) {
				try {
					doc.LoadFromXmlFile (template.FilePath);
				} catch (Exception ex) {
					if (ex is XmlException)
						result.AddError (template.FilePath, ((XmlException)ex).LineNumber,
						                 ((XmlException)ex).LinePosition, null, ex.Message);
					else
						result.AddError (template.FilePath, 0, 0, null, ex.Message);
					monitor.ReportError (GettextCatalog.GetString ("Could not load file '{0}': {1}",
					                                               template.FilePath, ex.Message), null);
					return result;
				}
			}
			
			if (result.Append (merge (conf, doc)).ErrorCount > 0)
				return result;
			
			try {
				EnsureDirectoryForFile (outPath);
				using (XmlTextWriter writer = new XmlTextWriter (outPath, Encoding.UTF8)) {
					writer.Formatting = Formatting.Indented;
					doc.Write (writer);
				}
			} catch (Exception ex) {
				result.AddError (outPath, 0, 0, null, ex.Message);
				monitor.ReportError (GettextCatalog.GetString ("Could not write file '{0}'", outPath), ex);
			}
			return result;
		}