public static ProcessStartInfo CreateMtouchSimStartInfo (IPhoneExecutionCommand cmd, bool logSimOutput, 
		                                                         IPhoneSimulatorTarget forceTarget)
		{
			string mtouchPath = cmd.Runtime.GetToolPath (cmd.Framework, "mtouch");
			if (string.IsNullOrEmpty (mtouchPath))
				throw new InvalidOperationException ("Cannot execute iPhone application. mtouch tool is missing.");
			
			var outLog = cmd.OutputLogPath;
			var errLog = cmd.ErrorLogPath;
			try {
				if (File.Exists (errLog))
				    File.Delete (errLog);
				if (File.Exists (outLog))
				    File.Delete (outLog);
			} catch (IOException) {}
			
			var cb = new ProcessArgumentBuilder ();
			cb.AddQuotedFormat ("-launchsim={0}", cmd.AppPath);
			if (logSimOutput) {
				cb.AddQuotedFormat ("-stderr={0}", errLog);
				cb.AddQuotedFormat ("-stdout={0}", outLog);
			}
			
			if (forceTarget != null) {
				var version = forceTarget.Version;
				
				if (!version.IsUseDefault && !IPhoneFramework.SdkIsInstalled (version, true)) {
					version = IPhoneFramework.GetClosestInstalledSdk (version, true);
					LoggingService.LogWarning ("iOS SDK '{0}' not installed, falling back to simulator '{1}'",
						forceTarget.Version, version);
				}
				
				if (!version.IsUseDefault)
					cb.AddQuotedFormat ("-sdk={0}", forceTarget.Version);
				
				if (forceTarget.Device == TargetDevice.IPad)
					cb.Add ("-device=2");
			}
			
			var psi = new ProcessStartInfo (mtouchPath, cb.ToString ()) {
				WorkingDirectory = cmd.LogDirectory,
				UseShellExecute = false
			};
			
			return psi;
		}
예제 #2
0
		void GenerateXCodeProject (IPhoneProject proj, IPhoneProjectConfiguration conf, ConfigurationSelector slnConf)
		{
			string mtouchPath = IPhoneUtility.GetMtouchPath (proj.TargetRuntime, proj.TargetFramework);
			
			var xcodeDir = conf.OutputDirectory.Combine ("XcodeProject");
			if (!Directory.Exists (xcodeDir)) {
				try {
					Directory.CreateDirectory (xcodeDir);
				} catch (IOException ex) {
					MessageService.ShowException (ex, "Failed to create directory '" + xcodeDir +"' for Xcode project");
					return;
				}
			}
			
			var args = new ProcessArgumentBuilder ();
			args.AddQuotedFormat ("-xcode={0}", xcodeDir);
			args.Add ("-v");
			
			foreach (ProjectFile pf in proj.Files) {
				if (pf.BuildAction == BuildAction.Content) {
					var rel = pf.ProjectVirtualPath;
					args.AddQuotedFormat ("-res={0},{1}", pf.FilePath, rel);
					
					//hack around mtouch 1.0 bug. create resource directories
					string subdir = rel.ParentDirectory;
					if (string.IsNullOrEmpty (subdir))
						continue;
					subdir = xcodeDir.Combine (subdir);
					try {
						if (!Directory.Exists (subdir))
							Directory.CreateDirectory (subdir);
					} catch (IOException ex) {
						MessageService.ShowException (ex, "Failed to create directory '" + subdir +"' for Xcode project");
						return;
					}
				} else if (pf.BuildAction == BuildAction.Page) {
					args.AddQuotedFormat ("-res={0}", pf.FilePath);
				}
			}
			
			args.AddQuotedFormat ("-res={0},Info.plist", conf.AppDirectory.Combine ("Info.plist"));
			
			foreach (string asm in proj.GetReferencedAssemblies (slnConf).Distinct ())
				args.AddQuotedFormat ("-r={0}", asm);
			
			var sdkVersion = conf.MtouchSdkVersion.ResolveIfDefault ();
			if (!IPhoneFramework.SdkIsInstalled (sdkVersion))
				sdkVersion = IPhoneFramework.GetClosestInstalledSdk (sdkVersion);
			
			IPhoneBuildExtension.AppendExtrasMtouchArgs (args, sdkVersion, proj, conf);
			args.AddQuoted (conf.CompiledOutputName);
			
			string argStr = args.ToString ();
			
			var console = (IConsole) IdeApp.Workbench.ProgressMonitors.GetOutputProgressMonitor (
				GettextCatalog.GetString ("Generate Xcode project"), MonoDevelop.Ide.Gui.Stock.RunProgramIcon, true, true);
			console.Log.WriteLine (mtouchPath + " " + argStr);
			Runtime.ProcessService.StartConsoleProcess (mtouchPath, argStr, conf.OutputDirectory, console, null);
		}
예제 #3
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;
		}
예제 #4
0
		static internal void AppendExtrasMtouchArgs (ProcessArgumentBuilder args, IPhoneSdkVersion sdkVersion, 
			IPhoneProject proj, IPhoneProjectConfiguration conf)
		{
			if (conf.MtouchDebug)
				args.Add ("-debug");
			
			switch (conf.MtouchLink) {
			case MtouchLinkMode.SdkOnly:
				args.Add ("-linksdkonly");
				break;
			case MtouchLinkMode.None:
				args.Add ("-nolink");
				break;
			case MtouchLinkMode.Full:
			default:
				break;
			}
			
			if (!string.IsNullOrEmpty (conf.MtouchI18n)) {
				args.AddQuotedFormat ("-i18n={0}", conf.MtouchI18n);
			}
			
			if (!sdkVersion.Equals (IPhoneSdkVersion.V3_0))
				args.AddQuotedFormat ("-sdk={0}", sdkVersion);
			
			if (conf.MtouchMinimumOSVersion != "3.0")
				args.AddQuotedFormat ("-targetver={0}", conf.MtouchMinimumOSVersion);
			
			if (IPhoneFramework.MonoTouchVersion >= new IPhoneSdkVersion (3, 99)) {
				if (conf.MtouchUseSGen)
					args.Add ("--sgen");
				if (conf.MtouchUseLlvm) {
					args.Add ("--llvm");
					switch (conf.MtouchArch) {
					case MtouchArch.ARMv6_ARMv7:
						args.Add ("--fat");
						break;
					case MtouchArch.ARMv7:
						args.Add ("--armv7");
						break;
					}
					if (conf.MtouchArch != MtouchArch.ARMv6 && conf.MtouchUseThumb)
						args.Add ("--thumb");
				}
			}
			
			AddExtraArgs (args, conf.MtouchExtraArgs, proj, conf);
		}
예제 #5
0
		static BuildResult SignAppBundle (IProgressMonitor monitor, IPhoneProject proj, IPhoneProjectConfiguration conf,
		                           X509Certificate2 key, string resRules, string xcent)
		{
			monitor.BeginTask (GettextCatalog.GetString ("Signing application"), 0);
			
			var args = new ProcessArgumentBuilder ();
			args.Add ("-v", "-f", "-s");
			args.AddQuoted (Keychain.GetCertificateCommonName (key));
			args.AddQuotedFormat ("--resource-rules={0}", resRules);
			args.Add ("--entitlements");
			args.AddQuoted (xcent);
			args.AddQuoted (conf.AppDirectory);
			
			AddExtraArgs (args, conf.CodesignExtraArgs, proj, conf);
				
			int signResultCode;
			var psi = new ProcessStartInfo ("codesign") {
				UseShellExecute = false,
				RedirectStandardError = true,
				RedirectStandardOutput = true,
				Arguments = args.ToString (),
			};
			
			monitor.Log.WriteLine ("codesign " + psi.Arguments);
			psi.EnvironmentVariables.Add ("CODESIGN_ALLOCATE",
				"/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate");
			string output;
			if ((signResultCode = MacBuildUtilities.ExecuteCommand (monitor, psi, out output)) != 0) {
				monitor.Log.WriteLine (output);
				return BuildError (string.Format ("Code signing failed with error code {0}. See output for details.", signResultCode));
			}
			monitor.EndTask ();
			
			return null;
		}
예제 #6
0
		void AddDirArgs (ProcessArgumentBuilder pb)
		{
			foreach (var dir in HelpService.Sources)
				pb.AddQuotedFormat ("--docdir={0}", dir);
		}
		static internal void AppendExtrasMtouchArgs (ProcessArgumentBuilder args, IPhoneSdkVersion sdkVersion, 
			IPhoneProject proj, IPhoneProjectConfiguration conf)
		{
			if (conf.MtouchDebug)
				args.Add ("-debug");
			
			switch (conf.MtouchLink) {
			case MtouchLinkMode.SdkOnly:
				args.Add ("-linksdkonly");
				break;
			case MtouchLinkMode.None:
				args.Add ("-nolink");
				break;
			case MtouchLinkMode.Full:
			default:
				break;
			}
			
			if (!string.IsNullOrEmpty (conf.MtouchI18n)) {
				args.AddQuotedFormat ("-i18n={0}", conf.MtouchI18n);
			}
			
			if (!sdkVersion.Equals (IPhoneSdkVersion.V3_0))
				args.AddQuotedFormat ("-sdk={0}", sdkVersion);
			
			if (conf.MtouchMinimumOSVersion != "3.0")
				args.AddQuotedFormat ("-targetver={0}", conf.MtouchMinimumOSVersion);
			
			
			AddExtraArgs (args, conf.MtouchExtraArgs, proj, conf);
		}