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; }
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; }
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); } }
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; }); }
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; }
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; }); }
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; }
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 } }
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"); } }
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; }); }