protected override BuildResult OnBuild (MonoDevelop.Core.IProgressMonitor monitor, ConfigurationSelector configuration)
		{
			var restResult = RestClient.CompileScripts ();
			var result = new BuildResult ();

			foreach (var message in restResult.Messages)
			{
				var file = BaseDirectory + "/" + message.File;
				var msg = message.Message;
				var errorNum = "";
				
				var messageStrings = message.Message.Split(':');

				if (messageStrings.Length == 3)
				{
					var errorNumStrings = messageStrings[1].Split(' ');

					if (errorNumStrings.Length > 1)
						errorNum = errorNumStrings[errorNumStrings.Length - 1];

					msg = messageStrings[2];
				}

				if(message.Type == "warning")
					result.AddWarning(file, message.Line, message.Column, errorNum, msg);
				else
					result.AddError(file, message.Line, message.Column, errorNum, msg);
			}
			
			return result;
		}
Пример #2
0
		static BuildResult GetIdentity (IProgressMonitor monitor, IPhoneProject proj, IPhoneProjectConfiguration conf,
		                                out IPhoneAppIdentity identity)
		{
			var result = new BuildResult ();
			identity = new IPhoneAppIdentity ();
			bool defaultID = string.IsNullOrEmpty (proj.BundleIdentifier);
			
			if (!defaultID)
				identity.BundleID = proj.BundleIdentifier;
			
			//treat empty as "developer automatic"
			if (string.IsNullOrEmpty (conf.CodesignKey)) {
				conf.CodesignKey = IPhoneProject.DEV_CERT_PREFIX;
			}
			
			IList<X509Certificate2> certs = null;
			if (conf.CodesignKey == IPhoneProject.DEV_CERT_PREFIX || conf.CodesignKey == IPhoneProject.DIST_CERT_PREFIX) {
				certs = Keychain.FindNamedSigningCertificates (x => x.StartsWith (conf.CodesignKey)).ToList ();
				if (certs.Count == 0) {
					result.AddError ("No valid iPhone code signing keys found in keychain.");
					return result;
				}
			} else {
				identity.SigningKey = Keychain.FindNamedSigningCertificates (x => x == conf.CodesignKey).FirstOrDefault ();
				if (identity.SigningKey == null) {
					result.AddError (string.Format ("iPhone code signing key '{0}' not found in keychain.", conf.CodesignKey));
					return result;
				}
				certs = new X509Certificate2[] { identity.SigningKey };
			}
			
			if (!string.IsNullOrEmpty (conf.CodesignProvision)) {
				//if the profile was installed by Xcode, we can determine the filename directly from the UUID
				//but if it was installed by iTunes, we need to search all profiles for the UUID.
				var file = MobileProvision.ProfileDirectory.Combine (conf.CodesignProvision).ChangeExtension (".mobileprovision");
				if (File.Exists (file)) {
					try {
						identity.Profile = MobileProvision.LoadFromFile (file);
					} catch (Exception ex) {
						string msg = "Could not read provisioning profile '" + file + "'.";
						monitor.ReportError (msg, ex);
						result.AddError (msg);
						return result;
					}
				} else {
					identity.Profile = MobileProvision.GetAllInstalledProvisions ()
						.Where (p => p.Uuid == conf.CodesignProvision).FirstOrDefault ();
				}
				
				if (identity.Profile == null) {
					result.AddError (string.Format ("The specified provisioning profile '{0}' could not be found", conf.CodesignProvision));
					return result;
				}
				
				var prof = identity.Profile; //capture ref for lambda
				identity.SigningKey = certs.Where (c => prof.DeveloperCertificates
				                           .Any (p => p.Thumbprint == c.Thumbprint)).FirstOrDefault ();
				if (identity.SigningKey == null) {
					result.AddError (string.Format ("No iPhone code signing key matches specified provisioning profile '{0}'.", conf.CodesignProvision));
					return result;
				}
				
				if (defaultID) {
					identity.BundleID = GetDefaultBundleID (proj, GetProfileBundleID (identity.Profile));
					result.AddWarning (string.Format ("Project does not have bundle identifier specified. Generated '{0}' to match provisioning profile.", identity.BundleID));
				}
				
				bool exact;
				identity.AppID = ConstructValidAppId (identity.Profile, identity.BundleID, out exact);
				if (identity.AppID == null) {
					result.AddError (string.Format (
						"Project bundle ID '{0}' does not match specified provisioning profile '{1}'", identity.BundleID, conf.CodesignProvision));
					return result;
				}
				return result;
			}
			
			var pairs = (from p in MobileProvision.GetAllInstalledProvisions ()
				from c in certs
				where p.DeveloperCertificates.Any (d => d.Thumbprint == c.Thumbprint)
				select new { Cert = c, Profile = p }).ToList ();
				
			if (pairs.Count == 0) {
				result.AddError ("No installed provisioning profiles match the installed iPhone code signing keys.");
				return result;
			}
			
			if (!defaultID) {
				//find a provisioning profile with compatible appid, preferring exact match
				foreach (var p in pairs) {
					bool exact;
					var id = ConstructValidAppId (p.Profile, identity.BundleID, out exact);
					if (id != null) {
						if (exact || identity.AppID == null) {
							identity.Profile = p.Profile;
							identity.SigningKey = p.Cert;
							identity.AppID = id;
						}
						if (exact)
							break;
					}
				}
			} else {
				//pick provisioning profile to provide appid and better default bundle ID, preferring star bundle IDs
				foreach (var p in pairs) {
					var suggestion = GetProfileBundleID (p.Profile);
					bool star = (suggestion != null) && suggestion.EndsWith ("*");
					if (star || identity.Profile == null) {
						identity.Profile = p.Profile;
						identity.SigningKey = p.Cert;
						identity.BundleID = GetDefaultBundleID (proj, suggestion);
						bool exact;
						identity.AppID = ConstructValidAppId (p.Profile, identity.BundleID, out exact);
					}
					if (star)
						break;
				}
				result.AddWarning (string.Format ("Project does not have bundle identifier specified. Generated '{0}' to match an installed provisioning profile.", identity.BundleID));
			}
			
			if (identity.Profile != null && identity.SigningKey != null && identity.AppID != null)
				return result;
			
			if (identity.SigningKey != null) {
				result.AddError (string.Format (
					"Bundle identifier '{0}' does not match any installed provisioning profile for selected signing identity '{0}'.",
					identity.BundleID, identity.SigningKey));
			} else {
				result.AddError (string.Format (
					"Bundle identifier '{0}' does not match any installed provisioning profile.",
					identity.BundleID));
			}
			return result;
		}
Пример #3
0
		static void AddErrorsToResult (BuildResult result, string filename, IEnumerable<Error> errors)
		{
			foreach (var err in errors) {
				if (err.ErrorType == ErrorType.Warning)
					result.AddWarning (filename, err.Region.BeginLine, err.Region.BeginColumn, null, err.Message);
				else
					result.AddError (filename, err.Region.BeginLine, err.Region.BeginColumn, null, err.Message);
			}
		}
Пример #4
0
		BuildResult UpdateInfoPlist (IProgressMonitor monitor, IPhoneSdkVersion sdkVersion, IPhoneProject proj,
			IPhoneProjectConfiguration conf, IPhoneAppIdentity identity, ProjectFile template, string plistOut)
		{
			return MacBuildUtilities.CreateMergedPlist (monitor, template, plistOut, (PlistDocument doc) => {
				var result = new BuildResult ();
				var dict = doc.Root as PlistDictionary;
				if (dict == null)
					doc.Root = dict = new PlistDictionary ();
				
				bool sim = conf.Platform != IPhoneProject.PLAT_IPHONE;
				bool v3_2_orNewer = sdkVersion >= IPhoneSdkVersion.V3_2;
				bool v3_1_orNewer = sdkVersion >= IPhoneSdkVersion.V3_1;
				bool v4_0_orNewer = sdkVersion >= IPhoneSdkVersion.V4_0;
				bool supportsIPhone = (proj.SupportedDevices & TargetDevice.IPhone) != 0;
				bool supportsIPad = (proj.SupportedDevices & TargetDevice.IPad) != 0;
				
				var sdkSettings = IPhoneFramework.GetSdkSettings (sdkVersion);
				var dtSettings = IPhoneFramework.GetDTSettings ();
				
				SetIfNotPresent (dict, "BuildMachineOSBuild", dtSettings.BuildMachineOSBuild);
				
				SetIfNotPresent (dict, "CFBundleDevelopmentRegion",
					String.IsNullOrEmpty (proj.BundleDevelopmentRegion)? "en" : proj.BundleDevelopmentRegion);
				
				SetIfNotPresent (dict, "CFBundleDisplayName", proj.BundleDisplayName ?? proj.Name);
				SetIfNotPresent (dict, "CFBundleExecutable", conf.NativeExe.FileName);
				
				// < 3.2 icon
				if (supportsIPhone) {
					if (!dict.ContainsKey ("CFBundleIconFile")) {
						var icon = proj.BundleIcon.ToRelative (proj.BaseDirectory);
						if (icon.IsNullOrEmpty || icon.ToString () == ".")
							result.AddWarning ("Application bundle icon has not been set (iPhone Application options panel)");
						else
							dict ["CFBundleIconFile"] = icon.FileName;
					}
				}
				
				//newer icons - see http://developer.apple.com/library/ios/#qa/qa2010/qa1686.html
				if (v3_2_orNewer && !dict.ContainsKey ("CFBundleIconFiles")) {
					var arr = new PlistArray ();
					dict["CFBundleIconFiles"] = arr;
					
					if (supportsIPhone)
						AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIcon, "Icon.png");
					
					if (v4_0_orNewer && supportsIPhone)
						if (!AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconHigh, "*****@*****.**"))
							result.AddWarning ("iPhone high res bundle icon has not been set (iPhone Application options panel)");
					
					if (supportsIPad)
						if (!AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconIPad, "Icon-72.png"))
							result.AddWarning ("iPad bundle icon has not been set (iPhone Application options panel)");
					
					AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconSpotlight, "Icon-Small.png");
					
					if (supportsIPad)
						AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconIPadSpotlight, "Icon-Small-50.png");
					
					if (v4_0_orNewer && supportsIPhone)
						AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconSpotlightHigh, "*****@*****.**");
				}
				
				SetIfNotPresent (dict, "CFBundleIdentifier", identity.BundleID);
				SetIfNotPresent (dict, "CFBundleInfoDictionaryVersion", "6.0");
				SetIfNotPresent (dict, "CFBundleName", proj.Name);
				SetIfNotPresent (dict, "CFBundlePackageType", "APPL");
				if (!sim)
					dict["CFBundleResourceSpecification"] = "ResourceRules.plist";
				SetIfNotPresent (dict, "CFBundleSignature", "????");
				SetIfNotPresent (dict,  "CFBundleSupportedPlatforms",
					new PlistArray () { sim? "iPhoneSimulator" : "iPhoneOS" });
				SetIfNotPresent (dict, "CFBundleVersion", proj.BundleVersion ?? "1.0");
				
				if (!sim) {
					SetIfNotPresent (dict, "DTCompiler", sdkSettings.DTCompiler);
					SetIfNotPresent (dict, "DTPlatformBuild", dtSettings.DTPlatformBuild);
					SetIfNotPresent (dict, "DTSDKBuild", sdkSettings.DTSDKBuild);
				}
				SetIfNotPresent (dict, "DTPlatformName", sim? "iphonesimulator" : "iphoneos");
				if (!sim) {
					SetIfNotPresent (dict, "DTPlatformVersion", dtSettings.DTPlatformVersion);
				}
				SetIfNotPresent (dict, "DTSDKName", sim? sdkSettings.AlternateSDK : sdkSettings.CanonicalName);
				if (!sim) {
					SetIfNotPresent (dict, "DTXcode", dtSettings.DTXcode);
					SetIfNotPresent (dict, "DTXcodeBuild", dtSettings.DTXcodeBuild);
				}
				
				SetIfNotPresent (dict,  "LSRequiresIPhoneOS", true);
				if (v3_2_orNewer)
					SetIfNotPresent (dict,  "UIDeviceFamily", GetSupportedDevices (proj.SupportedDevices));
				
				if (v3_1_orNewer) {
					if (conf.MtouchArch != MtouchArch.ARMv6_ARMv7) {
						var val = conf.MtouchArch == MtouchArch.ARMv6? "armv6" : "armv7";
						var key = "UIRequiredDeviceCapabilities";
						var caps = dict.TryGetValue (key) ?? (dict[key] = new PlistArray ());
						var a = caps as PlistArray;
						if (a != null) {
							a.Add (val);
						} else {
							var d = (PlistDictionary) caps;
							d[val] = new PlistBoolean (true);
						}
					}
				}
				
				SetIfNotPresent (dict, "MinimumOSVersion", conf.MtouchMinimumOSVersion);
				
				SetNibProperty (dict, proj, proj.MainNibFile, "NSMainNibFile");
				if (proj.SupportedDevices == TargetDevice.IPhoneAndIPad)
					SetNibProperty (dict, proj, proj.MainNibFileIPad, "NSMainNibFile~ipad");
				
				
				if (v3_2_orNewer) {
					if (!dict.ContainsKey (OrientationUtil.KEY)) {
						result.AddWarning ("Supported orientations have not been set (iPhone Application options panel)");
					} else {
						var val = OrientationUtil.Parse ((PlistArray)dict[OrientationUtil.KEY]);
						if (!OrientationUtil.IsValidPair (val))
							result.AddWarning ("Supported orientations are not matched pairs (Info.plist)");
						if (dict.ContainsKey (OrientationUtil.KEY_IPAD)) {
							var pad = OrientationUtil.Parse ((PlistArray)dict[OrientationUtil.KEY_IPAD]);
							if (pad != Orientation.None && !OrientationUtil.IsValidPair (pad))
								result.AddWarning ("iPad orientations are not matched pairs (Info.plist)");
						}
					}
				}   
				
				return result;
			});
		}
Пример #5
0
		protected override BuildResult Build (IProgressMonitor monitor, SolutionEntityItem item, ConfigurationSelector configuration)
		{
			IPhoneProject proj = item as IPhoneProject;
			if (proj == null || proj.CompileTarget != CompileTarget.Exe)
				return base.Build (monitor, item, configuration);
			
			IPhoneFramework.CheckInfoCaches ();
			
			//prebuild
			var conf = (IPhoneProjectConfiguration) proj.GetConfiguration (configuration);
			bool isDevice = conf.Platform == IPhoneProject.PLAT_IPHONE;
			
			if (IPhoneFramework.SimOnly && isDevice) {
				//if in the GUI, show a dialog too
				if (MonoDevelop.Ide.IdeApp.IsInitialized)
					Gtk.Application.Invoke (delegate { IPhoneFramework.ShowSimOnlyDialog (); } );
				return IPhoneFramework.GetSimOnlyError ();
			}
			
			var result = new BuildResult ();
			
			var sdkVersion = conf.MtouchSdkVersion.ResolveIfDefault ();
			
			if (!IPhoneFramework.SdkIsInstalled (sdkVersion)) {
				sdkVersion = IPhoneFramework.GetClosestInstalledSdk (sdkVersion);
				
				if (sdkVersion.IsUseDefault || !IPhoneFramework.SdkIsInstalled (sdkVersion)) {
					if (conf.MtouchSdkVersion.IsUseDefault)
						result.AddError (
							string.Format ("The Apple iPhone SDK is not installed."));
					else
						result.AddError (
							string.Format ("Apple iPhone SDK version '{0}' is not installed, and no newer version was found.",
							conf.MtouchSdkVersion));
					return result;
				}
					
				result.AddWarning (
					string.Format ("Apple iPhone SDK version '{0}' is not installed. Using newer version '{1}' instead'.",
					conf.MtouchSdkVersion, sdkVersion));
			}
			
			IPhoneAppIdentity identity = null;
			if (isDevice) {
				monitor.BeginTask (GettextCatalog.GetString ("Detecting signing identity..."), 0);
				if ((result = GetIdentity (monitor, proj, conf, out identity).Append (result)).ErrorCount > 0)
					return result;
				monitor.Log.WriteLine ("Provisioning profile: \"{0}\" ({1})", identity.Profile.Name, identity.Profile.Uuid);
				monitor.Log.WriteLine ("Signing Identity: \"{0}\"", Keychain.GetCertificateCommonName (identity.SigningKey));
				monitor.Log.WriteLine ("App ID: \"{0}\"", identity.AppID);
				monitor.EndTask ();
			} else {
				identity = new IPhoneAppIdentity () {
					BundleID = !string.IsNullOrEmpty (proj.BundleIdentifier)?
						proj.BundleIdentifier : GetDefaultBundleID (proj, null)
				};
			}
			
			result = base.Build (monitor, item, configuration).Append (result);
			if (result.ErrorCount > 0)
				return result;
			
			if (!Directory.Exists (conf.AppDirectory))
				Directory.CreateDirectory (conf.AppDirectory);
			
			var assemblyRefs = proj.GetReferencedAssemblies (configuration).Distinct ().ToList ();
			
			FilePath mtouchOutput = conf.NativeExe;
			if (new FilePair (conf.CompiledOutputName, mtouchOutput).NeedsBuilding ()) {
				BuildResult error;
				var mtouch = GetMTouch (proj, monitor, out error);
				if (error != null)
					return error.Append (result);
				
				var args = new ProcessArgumentBuilder ();
				//FIXME: make verbosity configurable?
				args.Add ("-v");
				
				args.Add ("--nomanifest", "--nosign");
					
				//FIXME: should we error out if the platform is invalid?
				if (conf.Platform == IPhoneProject.PLAT_IPHONE) {
					args.Add ("-dev");
					args.AddQuoted (conf.AppDirectory);
				} else {
					args.Add ("-sim");
					args.AddQuoted (conf.AppDirectory);
				}
				
				foreach (string asm in assemblyRefs)
					args.AddQuotedFormat ("-r={0}", asm);
				
				IPhoneSdkVersion osVersion = IPhoneSdkVersion.V3_0;
				try {
					osVersion = IPhoneSdkVersion.Parse (conf.MtouchMinimumOSVersion);
				} catch {
					result.AddWarning ("Could not parse minimum OS version '" + conf.MtouchMinimumOSVersion + "'");
				}
				
				if (osVersion < IPhoneSdkVersion.V3_0 && conf.MtouchArch == MtouchArch.ARMv7) {
					result.AddError ("Apps with a minimum OS older than 3.1 cannot be ARMv7 only");
					return result;
				}
				
				AppendExtrasMtouchArgs (args, sdkVersion, proj, conf);
				
				args.AddQuoted (conf.CompiledOutputName);
				
				mtouch.WorkingDirectory = conf.OutputDirectory;
				mtouch.Arguments = args.ToString ();
				
				monitor.BeginTask (GettextCatalog.GetString ("Compiling to native code"), 0);
				
				string output;
				int code;
				monitor.Log.WriteLine ("{0} {1}", mtouch.FileName, mtouch.Arguments);
				if ((code = MacBuildUtilities.ExecuteCommand (monitor, mtouch, out output)) != 0) {
					if (String.IsNullOrEmpty (output)) {
						result.AddError (null, 0, 0, code.ToString (), "mtouch failed with no output");
					} else {
						result.AddError (null, 0, 0, code.ToString (), "mtouch failed with the following message:\n" + output);
					}
					return result;
				}
				
				monitor.EndTask ();
			}
			
			//unpack nibs and content from dll resources (MT 4+ only)
			if (IPhoneFramework.MonoTouchVersion >= new IPhoneSdkVersion (3, 99))
				if (result.Append (UnpackContent (monitor, conf, assemblyRefs)).ErrorCount > 0)
					return result;
			
			//create the info.plist, merging in the template if it exists
			var plistOut = conf.AppDirectory.Combine ("Info.plist");
			ProjectFile appInfoIn = proj.Files.GetFile (proj.BaseDirectory.Combine ("Info.plist"));
			if (new FilePair (proj.FileName, plistOut).NeedsBuilding () ||
			    	(appInfoIn != null && new FilePair (appInfoIn.FilePath, plistOut).NeedsBuilding ())) {
				try {
					monitor.BeginTask (GettextCatalog.GetString ("Updating application manifest"), 0);
					if (result.Append (UpdateInfoPlist (monitor, sdkVersion, proj, conf, identity, appInfoIn, plistOut)).ErrorCount > 0)
						return result;
				} finally {
					monitor.EndTask ();
				}
			}
			
			//create the Setting.bundle plist for debug settings, merging in the template if it exists
			try {
				monitor.BeginTask (GettextCatalog.GetString ("Updating debug settings manifest"), 0);
				var sbRootRel = Path.Combine ("Settings.bundle", "Root.plist");
				var sbRootOut = conf.AppDirectory.Combine (sbRootRel);
				var sbRootIn  = proj.Files.GetFile (proj.BaseDirectory.Combine (sbRootRel));
				if (result.Append (UpdateDebugSettingsPlist (monitor, conf, sbRootIn, sbRootOut)).ErrorCount > 0)
					return result;
			} finally {
				monitor.EndTask ();
			}
			
			try {
				if (result.Append (ProcessPackaging (monitor, sdkVersion, proj, conf, identity)).ErrorCount > 0)
					return result;
			} finally {
				//if packaging failed, make sure that it's marked as needing building
				if (result.ErrorCount > 0 && File.Exists (conf.AppDirectory.Combine ("PkgInfo")))
					File.Delete (conf.AppDirectory.Combine ("PkgInfo"));	
			}	
			
			//TODO: create/update the xcode project
			return result;
		}
Пример #6
0
		static BuildResult UpdateDebugSettingsPlist (IProgressMonitor monitor, IPhoneProjectConfiguration conf,
		                                             ProjectFile template, string target)
		{
			if (template != null && template.BuildAction != BuildAction.Content)
				template = null;
			
			//if not in debug mode, make sure that the settings file is either
			//copied cleanly or deleted
			if (!conf.DebugMode) {
				if (template != null) {
					MacBuildUtilities.EnsureDirectoryForFile (target);
					File.Copy (template.FilePath, target, true);
				} else if (File.Exists (target)) {
					File.Delete (target);
				}
				return null;
			}
			
			return MacBuildUtilities.CreateMergedPlist (monitor, template, target, (PlistDocument doc) => {
				var br = new BuildResult ();
				var debuggerIP = System.Net.IPAddress.Any;
				bool sim = conf.Platform == IPhoneProject.PLAT_SIM;
				
				try {
					debuggerIP = IPhoneSettings.GetDebuggerHostIP (sim);
				} catch {
					br.AddWarning (GettextCatalog.GetString ("Could not resolve host IP for debugger settings"));
				}
				
				var dict = doc.Root as PlistDictionary;
				if (dict == null)
					doc.Root = dict = new PlistDictionary ();
				
				SetIfNotPresent (dict, "Title", "AppSettings");
				SetIfNotPresent (dict, "StringsTable", "Root");
				
				var arr = dict.TryGetValue ("PreferenceSpecifiers") as PlistArray;
				if (arr == null)
					dict["PreferenceSpecifiers"] = arr = new PlistArray ();
				
				arr.Add (new PlistDictionary (true) {
					{ "Type", "PSGroupSpecifier" },
					{ "Title", "Debug Settings" }
				});
				
				arr.Add (new PlistDictionary (true) {
					{ "Type", "PSToggleSwitchSpecifier" },
					{ "Title", "Enabled" },
					{ "Key", "__monotouch_debug_enabled" },
					{ "DefaultValue", "1" },
					{ "TrueValue", "1" },
					{ "FalseValue", "0" }
				});
				
				arr.Add (new PlistDictionary (true) {
					{ "Type", "PSTextFieldSpecifier" },
					{ "Title", "Debugger Host" },
					{ "Key", "__monotouch_debug_host" },
					{ "AutocapitalizationType", "None" },
					{ "AutocorrectionType", "No" },
					{ "DefaultValue", debuggerIP.ToString () }
				});
					
				arr.Add (new PlistDictionary (true) {
					{ "Type", "PSTextFieldSpecifier" },
					{ "Title", "Debugger Port" },
					{ "Key", "__monotouch_debug_port" },
					{ "AutocapitalizationType", "None" },
					{ "AutocorrectionType", "No" },
					{ "DefaultValue", IPhoneSettings.DebuggerPort.ToString () }
				});
					
				arr.Add (new PlistDictionary (true) {
					{ "Type", "PSTextFieldSpecifier" },
					{ "Title", "Output Port" },
					{ "Key", "__monotouch_output_port" },
					{ "AutocapitalizationType", "None" },
					{ "AutocorrectionType", "No" },
					{ "DefaultValue", IPhoneSettings.DebuggerOutputPort.ToString () }
				});
				
				return br;
			});
		}
Пример #7
0
		static BuildResult UnpackContent (IProgressMonitor monitor, IPhoneProjectConfiguration cfg, List<string> assemblies)
		{
			bool isDevice = cfg.Platform == IPhoneProject.PLAT_IPHONE;
			
			//remove framework references, they don't contain embedded content
			List<string> toProcess = new List<string> ();
			for (int i = 0; i < assemblies.Count; i++) {
				var asm = assemblies[i];
				if (!asm.StartsWith ("/Developer/MonoTouch/usr/lib/mono/2.1") && asm != "mscorlib")
					toProcess.Add (asm);
			}
			//optimize the case where there are no non-framework references
			if (toProcess.Count == 0)
				return null;
			
			var result = new BuildResult ();
			var appDir = cfg.AppDirectory;
			
			//check that the dlls are also in the app bundle
			for (int i = 0; i < toProcess.Count; i++) {
				var asmInBundle = appDir.Combine (Path.GetFileName (toProcess[i]));
				if (!File.Exists (asmInBundle)) {
					var m = GettextCatalog.GetString ("Library '{0}' missing in app bundle, cannot extract content", asmInBundle.FileName);
					result.AddWarning (m);
					toProcess.RemoveAt (i--);
				}
			}
			
			//determine which dlls have been extracted, so we can skip re-extracting their content
			var previouslyProcessedDlls = new HashSet<string> ();
			var infoFile = cfg.ObjDir.Combine ("monotouch_dll_content_processed");
			bool hasInfoFile = File.Exists (infoFile);
			DateTime infoFileWritten = DateTime.MinValue;
			List<bool> skipExtractList = null;
			if (hasInfoFile) {
				infoFileWritten = File.GetLastWriteTimeUtc (infoFile);
				foreach (var line in File.ReadAllLines (infoFile))
					previouslyProcessedDlls.Add (line);
				
				//remove logged dlls that are no longer in the build
				previouslyProcessedDlls.IntersectWith (toProcess);
				
				//don't re-process dlls that were written before the info file and are in the info file
				skipExtractList = toProcess.Select (asm =>
					!previouslyProcessedDlls.Add (asm)
					&& infoFileWritten > File.GetLastWriteTimeUtc (asm)
				).ToList ();
			} else {
				previouslyProcessedDlls.UnionWith (toProcess);
			}
			
			//early exit if nothing needs to be extracted or stripped
			if (toProcess.Count == 0 || (!isDevice && skipExtractList != null && skipExtractList.All (b => b)))
				return result;
			
			monitor.BeginTask ("Extracting embedded content", 0);
			for (int i = 0; i < toProcess.Count; i++) {
				FilePath asmFile = toProcess[i];
				bool skipExtract = skipExtractList != null && skipExtractList[i];
				if (skipExtract)
					continue;
				try {
					ExtractFromContentAssembly (monitor, appDir, asmFile);
				} catch (Exception ex) {
					string message = string.Format ("Error extracting content from assembly '{0}'", asmFile);
					monitor.ReportError (message, ex);
					result.AddError (message);
					monitor.EndTask ();
					return result;
				}
			}
			monitor.EndTask ();
			
			var dir = infoFile.ParentDirectory;
			if (!Directory.Exists (dir))
				Directory.CreateDirectory (dir);
			File.WriteAllLines (infoFile, previouslyProcessedDlls.ToArray ());
			
			return result;
		}
Пример #8
0
		static bool CheckPageNamePermitted (string virtualPath, BuildResult result)
		{
			int i = virtualPath.IndexOf (Path.DirectorySeparatorChar);
			if (i < 0)
				return false;
			string rootDir = virtualPath.Substring (0, i);
			if (forbiddenContentFolders.Contains (rootDir)) {
				if (result != null)
					result.AddWarning (virtualPath, 0, 0, "", GettextCatalog.GetString (
						"The folder name '{0}' is reserved and cannot used for Page files", rootDir));
				return false;
			}
			return true;
		}
		BuildResult UpdateInfoPlist (IProgressMonitor monitor, IPhoneProject proj, IPhoneProjectConfiguration conf,
		                             IPhoneAppIdentity identity, ProjectFile template, string plistOut)
		{
			return CreateMergedPlist (monitor, conf, template, plistOut, 
				(IPhoneProjectConfiguration config, PlistDocument doc) => 
			{
				var result = new BuildResult ();
				var dict = doc.Root as PlistDictionary;
				if (dict == null)
					doc.Root = dict = new PropertyList.PlistDictionary ();
				
				bool sim = conf.Platform != IPhoneProject.PLAT_IPHONE;
				
				SetIfNotPresent (dict, "CFBundleDevelopmentRegion",
					String.IsNullOrEmpty (proj.BundleDevelopmentRegion)? "English" : proj.BundleDevelopmentRegion);
				
				SetIfNotPresent (dict, "CFBundleDisplayName", proj.BundleDisplayName ?? proj.Name);
				SetIfNotPresent (dict, "CFBundleExecutable", conf.NativeExe.FileName);
				
				//iphone icons
				if ((proj.SupportedDevices & TargetDevice.IPhone) != 0) {
					if (!dict.ContainsKey ("CFBundleIconFile")) {
						var icon = proj.BundleIcon.ToRelative (proj.BaseDirectory);
						if (icon.IsNullOrEmpty || icon.ToString () == ".")
							result.AddWarning ("Application bundle icon has not been set");
						else
							dict ["CFBundleIconFile"] = icon.FileName;
					}
				}
				
				//ipad and universal icons
				if ((proj.SupportedDevices & TargetDevice.IPad) != 0 && !dict.ContainsKey ("CFBundleIconFiles")) {
					var arr = new PlistArray ();
					dict["CFBundleIconFiles"] = arr;
					//universal only
					if ((proj.SupportedDevices & TargetDevice.IPhone) != 0)
						AddRelativeIfNotEmpty (proj, arr, proj.BundleIcon);
					//ipad and universal
					AddRelativeIfNotEmpty (proj, arr, proj.BundleIconSpotlight);
					AddRelativeIfNotEmpty (proj, arr, proj.BundleIconIPadSpotlight);
					if (!AddRelativeIfNotEmpty (proj, arr, proj.BundleIconIPad))
						result.AddWarning ("iPad bundle icon has not been set");
				}
				
				SetIfNotPresent (dict, "CFBundleIdentifier", identity.BundleID);
				SetIfNotPresent (dict, "CFBundleInfoDictionaryVersion", "6.0");
				SetIfNotPresent (dict, "CFBundleName", proj.Name);
				SetIfNotPresent (dict, "CFBundlePackageType", "APPL");
				if (!sim)
					dict["CFBundleResourceSpecification"] = "ResourceRules.plist";
				SetIfNotPresent (dict, "CFBundleSignature", "????");
				SetIfNotPresent (dict,  "CFBundleSupportedPlatforms",
					new PropertyList.PlistArray () { sim? "iPhoneSimulator" : "iPhoneOS" });
				SetIfNotPresent (dict, "CFBundleVersion", proj.BundleVersion ?? "1.0");
				SetIfNotPresent (dict, "DTPlatformName", sim? "iphonesimulator" : "iphoneos");
				SetIfNotPresent (dict, "DTSDKName", (sim? "iphonesimulator" : "iphoneos")  + conf.MtouchSdkVersion);
				SetIfNotPresent (dict,  "LSRequiresIPhoneOS", true);
				if (proj.SupportedDevices != TargetDevice.IPhone)
					SetIfNotPresent (dict,  "UIDeviceFamily", GetSupportedDevices (proj.SupportedDevices));
				SetIfNotPresent (dict, "DTPlatformVersion", conf.MtouchSdkVersion);
				
				SetIfNotPresent (dict, "MinimumOSVersion", conf.MtouchMinimumOSVersion);
				
				SetNibProperty (dict, proj, proj.MainNibFile, "NSMainNibFile");
				if (proj.SupportedDevices == TargetDevice.IPhoneAndIPad)
					SetNibProperty (dict, proj, proj.MainNibFileIPad, "NSMainNibFile~ipad");
				
				return result;
			});
		}
		protected override BuildResult Compile (MonoDevelop.Core.IProgressMonitor monitor, SolutionEntityItem item, BuildData buildData)
		{
#if DEBUG			
			monitor.Log.WriteLine("MonoGame Extension Compile Called");	
#endif			
			try
			{	
				var cfg = buildData.Configuration as MonoGameContentProjectConfiguration;
				var proj = item as MonoGameContentProject;
				if (proj == null || cfg == null)
				{
					monitor.Log.WriteLine("Compiling for Unknown MonoGame Project");
					return base.Compile(monitor, item, buildData);
				}
				monitor.Log.WriteLine("Detected {0} MonoGame Platform", cfg.MonoGamePlatform);
				var result = new BuildResult();
				var manager = new PipelineManager(proj.BaseDirectory.FullPath,
				                                  Path.Combine(buildData.Configuration.OutputDirectory, cfg.MonoGamePlatform),
				                                  buildData.Configuration.IntermediateOutputDirectory);
			
				manager.Logger = new MonitorBuilder(monitor, result);
				manager.Platform =  (TargetPlatform)Enum.Parse(typeof(TargetPlatform), cfg.MonoGamePlatform);
				try {
				foreach(var pr in proj.ParentSolution.GetAllProjects()) {
					if (pr is DotNetAssemblyProject) {
						var dot = pr as DotNetAssemblyProject;
						foreach(var r in dot.References)
						{
							if (r.Package.Name == "monogame-contentpipeline" ) {

								var output = dot.GetOutputFileName(buildData.ConfigurationSelector).FullPath;
								monitor.Log.WriteLine("Adding {0} to Content Pipeline Assembly List", output);
								manager.AddAssembly(output);
								proj.Manager.AddAssembly(output);
								break;
							}
						}
					}
				}
				}
				catch(Exception ex) {
					result.AddWarning(string.Format("Problem processing Content Extensions {0}", ex.Message));
				}

				var dict = new Microsoft.Xna.Framework.Content.Pipeline.OpaqueDataDictionary();
				if (cfg != null) {
					if (cfg.XnaCompressContent.ToLower() == "true") {
						// tell the manager to compress the output
					}
				}
				foreach(var file in proj.Files)
				{
					if (file.BuildAction == "Compile") {
						try 
						{
							dict.Clear();
							foreach(object key in file.ExtendedProperties.Keys) {
								string k = key as string;
								if (k != null && k.StartsWith("ProcessorParameters_")) {
									if (!dict.ContainsKey(k.Replace("ProcessorParameters_", String.Empty))) {
										dict.Add(k.Replace("ProcessorParameters_", String.Empty), file.ExtendedProperties[k]);
									} else {
										dict[k.Replace("ProcessorParameters_", String.Empty)] = file.ExtendedProperties[k];
									}
								}
							}

							// check if the file has changed and rebuild if required.
							manager.BuildContent(file.FilePath.FullPath, 
					                     null, 
							             file.ExtendedProperties.Contains("Importer") ? (string)file.ExtendedProperties["Importer"] : null,
							             file.ExtendedProperties.Contains("Processor") ? (string)file.ExtendedProperties["Processor"] : null, 
							             dict);
						}
						catch(Exception ex)
						{
							monitor.Log.WriteLine(ex.ToString());
							result.AddError(ex.Message);
						}

					}
				}
				return result;
			}
			finally
			{
#if DEBUG				
				monitor.Log.WriteLine("MonoGame Extension Compile Ended");	
#endif				
			}
		}
Пример #11
0
		public void Compile (PythonProject project,
		                     FilePath fileName,
		                     PythonConfiguration config,
		                     BuildResult result)
		{
			if (String.IsNullOrEmpty (fileName))
				throw new ArgumentNullException ("fileName");
			else if (config == null)
				throw new ArgumentNullException ("config");
			else if (result == null)
				throw new ArgumentNullException ("result");
			else if (Runtime == null)
				throw new InvalidOperationException ("No supported runtime!");
			
			// Get our relative path within the project
			if (!fileName.IsChildPathOf (project.BaseDirectory)) {
				Console.WriteLine ("File is not within our project!");
				return;
			}
			
			FilePath relName = fileName.ToRelative (project.BaseDirectory);
			string outFile = relName.ToAbsolute (config.OutputDirectory);
			
			if (!outFile.EndsWith (".py"))
				return;
			
			// Create the destination directory
			FileInfo fileInfo = new FileInfo (outFile);
			if (!fileInfo.Directory.Exists)
				fileInfo.Directory.Create ();
			
			// Create and start our process to generate the byte code
			Process process = BuildCompileProcess (fileName, outFile, config.Optimize);
			process.Start ();
			process.WaitForExit ();
			
			// Parse errors and warnings
			string output = process.StandardError.ReadToEnd ();
			
			// Extract potential Warnings
			foreach (Match m in m_WarningRegex.Matches (output)) {
				string lineNum  = m.Groups[m_WarningRegex.GroupNumberFromName ("line")].Value;
				string message  = m.Groups[m_WarningRegex.GroupNumberFromName ("message")].Value;
				
				result.AddWarning (fileName, Int32.Parse (lineNum), 0, String.Empty, message);
			}
			
			// Extract potential SyntaxError
			foreach (Match m in m_ErrorRegex.Matches (output)) {
				string lineNum = m.Groups[m_ErrorRegex.GroupNumberFromName ("line")].Value;
				result.AddError (fileName, Int32.Parse (lineNum), 0, String.Empty, "SyntaxError");
			}
		}
Пример #12
0
		BuildResult UpdateInfoPlist (IProgressMonitor monitor, IPhoneProject proj, IPhoneProjectConfiguration conf,
		                             IPhoneAppIdentity identity, ProjectFile template, string plistOut)
		{
			return MacBuildUtilities.CreateMergedPlist (monitor, template, plistOut, (PlistDocument doc) => {
				var result = new BuildResult ();
				var dict = doc.Root as PlistDictionary;
				if (dict == null)
					doc.Root = dict = new PlistDictionary ();
				
				bool sim = conf.Platform != IPhoneProject.PLAT_IPHONE;
				var sdkversion = IPhoneSdkVersion.Parse (conf.MtouchSdkVersion);
				bool v3_2_orNewer = sdkversion.CompareTo (IPhoneSdkVersion.V3_2) >= 0;
				bool v4_0_orNewer = sdkversion.CompareTo (IPhoneSdkVersion.V4_0) >= 0;
				bool supportsIPhone = (proj.SupportedDevices & TargetDevice.IPhone) != 0;
				bool supportsIPad = (proj.SupportedDevices & TargetDevice.IPad) != 0;
				
				SetIfNotPresent (dict, "CFBundleDevelopmentRegion",
					String.IsNullOrEmpty (proj.BundleDevelopmentRegion)? "English" : proj.BundleDevelopmentRegion);
				
				SetIfNotPresent (dict, "CFBundleDisplayName", proj.BundleDisplayName ?? proj.Name);
				SetIfNotPresent (dict, "CFBundleExecutable", conf.NativeExe.FileName);
				
				// < 3.2 icon
				if (supportsIPhone) {
					if (!dict.ContainsKey ("CFBundleIconFile")) {
						var icon = proj.BundleIcon.ToRelative (proj.BaseDirectory);
						if (icon.IsNullOrEmpty || icon.ToString () == ".")
							result.AddWarning ("Application bundle icon has not been set (iPhone Application options panel)");
						else
							dict ["CFBundleIconFile"] = icon.FileName;
					}
				}
				
				//newer icons
				if (v3_2_orNewer && !dict.ContainsKey ("CFBundleIconFiles")) {
					var arr = new PlistArray ();
					dict["CFBundleIconFiles"] = arr;
					
					if (supportsIPhone)
						AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIcon);
					
					AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconSpotlight, "Icon-Small.png");
					if (supportsIPad) {
						AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconIPadSpotlight, "Icon-Small-50.png");
						if (!AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconIPad))
							result.AddWarning ("iPad bundle icon has not been set (iPhone Application options panel)");
					}
					
					if (v4_0_orNewer) {
						if (supportsIPhone) {
							if (!AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconHigh))
								result.AddWarning ("iPhone high res bundle icon has not been set (iPhone Application options panel)");
							AddIconRelativeIfNotEmpty (proj, arr, proj.BundleIconSpotlightHigh, "*****@*****.**");
						}
					}
				}
				
				SetIfNotPresent (dict, "CFBundleIdentifier", identity.BundleID);
				SetIfNotPresent (dict, "CFBundleInfoDictionaryVersion", "6.0");
				SetIfNotPresent (dict, "CFBundleName", proj.Name);
				SetIfNotPresent (dict, "CFBundlePackageType", "APPL");
				if (!sim)
					dict["CFBundleResourceSpecification"] = "ResourceRules.plist";
				SetIfNotPresent (dict, "CFBundleSignature", "????");
				SetIfNotPresent (dict,  "CFBundleSupportedPlatforms",
					new PlistArray () { sim? "iPhoneSimulator" : "iPhoneOS" });
				SetIfNotPresent (dict, "CFBundleVersion", proj.BundleVersion ?? "1.0");
				SetIfNotPresent (dict, "DTPlatformName", sim? "iphonesimulator" : "iphoneos");
				SetIfNotPresent (dict, "DTSDKName", IPhoneFramework.GetDTSdkName (sdkversion, sim));
				SetIfNotPresent (dict,  "LSRequiresIPhoneOS", true);
				if (v3_2_orNewer)
					SetIfNotPresent (dict,  "UIDeviceFamily", GetSupportedDevices (proj.SupportedDevices));
				SetIfNotPresent (dict, "DTPlatformVersion", IPhoneFramework.DTPlatformVersion);
				
				SetIfNotPresent (dict, "MinimumOSVersion", conf.MtouchMinimumOSVersion);
				
				SetNibProperty (dict, proj, proj.MainNibFile, "NSMainNibFile");
				if (proj.SupportedDevices == TargetDevice.IPhoneAndIPad)
					SetNibProperty (dict, proj, proj.MainNibFileIPad, "NSMainNibFile~ipad");
				
				
				if (v3_2_orNewer) {
					if (!dict.ContainsKey (OrientationUtil.KEY)) {
						result.AddWarning ("Supported orientations have not been set (iPhone Application options panel)");
					} else {
						var val = OrientationUtil.Parse ((PlistArray)dict[OrientationUtil.KEY]);
						if (!OrientationUtil.IsValidPair (val))
							result.AddWarning ("Supported orientations are not matched pairs (Info.plist)");
						if (dict.ContainsKey (OrientationUtil.KEY_IPAD)) {
							var pad = OrientationUtil.Parse ((PlistArray)dict[OrientationUtil.KEY_IPAD]);
							if (pad != Orientation.None && !OrientationUtil.IsValidPair (pad))
								result.AddWarning ("iPad orientations are not matched pairs (Info.plist)");
						}
					}
				}   
				
				return result;
			});
		}