/// <summary> /// Apply the required changes to the lines of the xcode project. /// </summary> /// <param name="lines">Lines.</param> /// <param name="symbolScriptUploadUuid">Symbol script upload UUID.</param> public static void Apply(LinkedList <string> lines, string symbolScriptUploadUuid) { var info = new XcodeProjectInformation(lines); while (info.CurrentLine != null) { ProcessBuildConfigurationSection(info); ProcessShellScriptSection(info); ProcessNativeTargetSection(info); info.AdvanceCurrentLine(); } // if the symbol upload script has not been added to the project file then // we need to insert it in the correct location and identify it with provided // uuid if (!info.SymbolUploadScriptInstalled) { info.SymbolUploadScriptUuid = symbolScriptUploadUuid; foreach (var line in SymbolUploadScript(info.SymbolUploadScriptUuid)) { info.Lines.AddBefore(info.SymbolUploadScriptInsertionNode, line); } } // if the upload script has not been added to the main target then we need // to add the uuid that identifies the upload script as a build phase. if (!info.MainTargetShellScriptUuids.Contains(info.SymbolUploadScriptUuid)) { info.Lines.AddBefore(info.SymbolUploadUuidReferenceInsertionNode, string.Format(@" {0} /* ShellScript */,", info.SymbolUploadScriptUuid)); } }
/// <summary> /// Processes the build configuration section. Here we need to enable two /// build flags relating to certain exception types. We also need to ensure /// that the -ObjC linker flag has been applied. /// </summary> /// <param name="info">Data.</param> static void ProcessBuildConfigurationSection(XcodeProjectInformation info) { if (info.CurrentLine.Value.Equals("/* Begin XCBuildConfiguration section */")) { while (info.CurrentLine != null) { if (info.CurrentLine.Value.Equals("/* End XCBuildConfiguration section */")) { break; } // if these flags are not set at all should we add them? This is all // that we used to do and we did not handle them not being set at all if (info.CurrentLine.Value.Contains("GCC_ENABLE_OBJC_EXCEPTIONS") || info.CurrentLine.Value.Contains("GCC_ENABLE_CPP_EXCEPTIONS")) { info.CurrentLine.Value = info.CurrentLine.Value.Replace("NO", "YES"); } if (info.CurrentLine.Value.EndsWith("OTHER_LDFLAGS = (", System.StringComparison.InvariantCulture)) { bool hasLinkerFlag = false; while (info.CurrentLine != null) { if (info.CurrentLine.Value.EndsWith(");", System.StringComparison.InvariantCulture)) { if (!hasLinkerFlag) { info.Lines.AddBefore(info.CurrentLine, "\t\t\t\t\t\"-ObjC\","); } break; } if (info.CurrentLine.Value.Contains("-ObjC")) { hasLinkerFlag = true; } info.AdvanceCurrentLine(); } } info.AdvanceCurrentLine(); } } }
/// <summary> /// Processes the native target section. Here we need to find the main target /// which is the Unity application itself. We then to take a note of all of /// the shell scripts that have been added to the build phases for this main /// target. We need this so that we can determine if the symbol upload script /// has been added to this build phases. If it hasn't we also take a note of /// the node where we will need to insert the uuid later on. /// </summary> /// <param name="info">Data.</param> static void ProcessNativeTargetSection(XcodeProjectInformation info) { if (info.CurrentLine.Value.Equals("/* Begin PBXNativeTarget section */")) { while (info.CurrentLine != null && !info.CurrentLine.Value.Equals("/* End PBXNativeTarget section */")) { if (MainNativeTargetRegex.IsMatch(info.CurrentLine.Value)) { // we have found the main target, advance to the build phases while (info.CurrentLine != null && !info.CurrentLine.Value.EndsWith("buildPhases = (", System.StringComparison.InvariantCulture)) { info.AdvanceCurrentLine(); } while (info.CurrentLine != null) { if (info.CurrentLine.Value.EndsWith(");", System.StringComparison.InvariantCulture)) { info.SymbolUploadUuidReferenceInsertionNode = info.CurrentLine; break; } if (ShellScriptBuildPhaseRegex.IsMatch(info.CurrentLine.Value)) { var match = ShellScriptBuildPhaseRegex.Match(info.CurrentLine.Value); var group = match.Groups["uuid"]; info.MainTargetShellScriptUuids.Add(group.Value); } info.AdvanceCurrentLine(); } } info.AdvanceCurrentLine(); } } }
/// <summary> /// Processes the shell script section. Here we need to look at all of the /// shell scripts that have been added to the project and determine if the /// symbol upload script has been added. If it has we take a note of the uuid /// that identifies it so that we can add it to the main target if needed. /// We also note the node where we need to insert the script if it is missing /// </summary> /// <param name="info">Data.</param> static void ProcessShellScriptSection(XcodeProjectInformation info) { if (info.CurrentLine.Value.Equals("/* Begin PBXShellScriptBuildPhase section */")) { string uuid = null; while (info.CurrentLine != null) { if (info.CurrentLine.Value.Equals("/* End PBXShellScriptBuildPhase section */")) { // if we haven't inserted the script yet then this is where we need to insert it // we may need to handle this section not existing yet info.SymbolUploadScriptInsertionNode = info.CurrentLine; break; } // the beginning of a shell script if (ShellScriptPhaseRegex.IsMatch(info.CurrentLine.Value)) { uuid = info.CurrentLine.Value; while (info.CurrentLine != null && !info.CurrentLine.Value.EndsWith("};", System.StringComparison.InvariantCulture)) { if (info.CurrentLine.Value.Contains("bugsnag dsym upload script")) { var match = ShellScriptPhaseRegex.Match(uuid); var group = match.Groups["uuid"]; info.SymbolUploadScriptUuid = group.Value; } info.AdvanceCurrentLine(); } } info.AdvanceCurrentLine(); } } }