[msbuild] Refactor the IBTool task to be cleaner and more efficient (#1457)
[msbuild] Refactor the IBTool task to be cleaner and more efficient Besides making the IBTool task cleaner and easier to understand, a side-effect of this refactor was also to optimize the collecting of the compiled outputs because we now only need to scan the obj/ibtool directory once to collect each of the outputs.
This commit is contained in:
Родитель
cf169d43ac
Коммит
e26ee5ca6c
|
@ -373,12 +373,10 @@ namespace Xamarin.MacDev.Tasks
|
|||
specs.Save (outputSpecs, true);
|
||||
}
|
||||
|
||||
var output = new TaskItem (intermediateBundleDir);
|
||||
|
||||
Directory.CreateDirectory (intermediateBundleDir);
|
||||
|
||||
// Note: Compile() will set the PartialAppManifest property if it is used...
|
||||
if ((Compile (catalogs.ToArray (), output, manifest)) != 0)
|
||||
if ((Compile (catalogs.ToArray (), intermediateBundleDir, manifest)) != 0)
|
||||
return false;
|
||||
|
||||
if (PartialAppManifest != null && !File.Exists (PartialAppManifest.GetMetadata ("FullPath")))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Build.Framework;
|
||||
|
@ -68,11 +69,11 @@ namespace Xamarin.MacDev.Tasks
|
|||
|
||||
string GetBundleRelativeOutputPath (ITaskItem input)
|
||||
{
|
||||
// Note: InterfaceDefinition files are *always* installed into the root of the app bundle
|
||||
// InterfaceDefinition files that are contained within an .lproj translation directory
|
||||
// will retain the .lproj directory as their parent, but the .lproj directory will be
|
||||
// Note: InterfaceDefinition files are *always* installed into the root of the app bundle.
|
||||
//
|
||||
// InterfaceDefinition files that are contained within a *.lproj translation directory
|
||||
// will retain the *.lproj directory as their parent, but the *.lproj directory will be
|
||||
// in the root of the app bundle.
|
||||
//var bundleName = BundleResource.GetLogicalName (ProjectDir, ResourcePrefixes, input);
|
||||
var components = input.ItemSpec.Split (Path.DirectorySeparatorChar);
|
||||
var bundleName = components[components.Length - 1];
|
||||
if (components.Length > 1 && components[components.Length - 2].EndsWith (".lproj", StringComparison.Ordinal))
|
||||
|
@ -88,6 +89,236 @@ namespace Xamarin.MacDev.Tasks
|
|||
}
|
||||
}
|
||||
|
||||
static string GetPathWithoutExtension (string path)
|
||||
{
|
||||
int dot = path.LastIndexOf ('.');
|
||||
|
||||
return path.Substring (0, dot);
|
||||
}
|
||||
|
||||
IEnumerable<ITaskItem> GetCompilationDirectoryOutput (string baseOutputDir, IDictionary<string, IDictionary> mapping)
|
||||
{
|
||||
var baseOutputDirs = new List<string> ();
|
||||
|
||||
baseOutputDirs.Add (baseOutputDir);
|
||||
|
||||
// Note: all storyboardc's/nib's will be found in the top-level or within a top-level *.lproj dir (if they've been translated)
|
||||
for (int i = 0; i < baseOutputDirs.Count; i++) {
|
||||
foreach (var path in Directory.EnumerateFileSystemEntries (baseOutputDirs[i])) {
|
||||
if (i == 0 && path.EndsWith (".lproj", StringComparison.Ordinal) && Directory.Exists (path)) {
|
||||
baseOutputDirs.Add (path);
|
||||
continue;
|
||||
}
|
||||
|
||||
IDictionary metadata;
|
||||
|
||||
if (!mapping.TryGetValue (path, out metadata))
|
||||
continue;
|
||||
|
||||
var compiled = new TaskItem (path, metadata);
|
||||
|
||||
// adjust the LogicalName since the LogicalName metadata is based on the generic output name
|
||||
// (e.g. it does not include things like ~ipad or ~iphone)
|
||||
var logicalName = compiled.GetMetadata ("LogicalName");
|
||||
var logicalDir = Path.GetDirectoryName (logicalName);
|
||||
var fileName = Path.GetFileName (path);
|
||||
|
||||
compiled.SetMetadata ("LogicalName", Path.Combine (logicalDir, fileName));
|
||||
|
||||
yield return compiled;
|
||||
}
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
IEnumerable<ITaskItem> GetCompilationOutput (ITaskItem expected)
|
||||
{
|
||||
if (IsWatchApp) {
|
||||
var logicalName = expected.GetMetadata ("LogicalName");
|
||||
|
||||
foreach (var extension in WatchAppExtensions) {
|
||||
var path = GetPathWithoutExtension (expected.ItemSpec) + extension;
|
||||
if (File.Exists (path)) {
|
||||
var item = new TaskItem (path);
|
||||
expected.CopyMetadataTo (item);
|
||||
item.SetMetadata ("LogicalName", GetPathWithoutExtension (logicalName) + extension);
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yield return expected;
|
||||
}
|
||||
|
||||
static bool LogExists (string path)
|
||||
{
|
||||
if (!File.Exists (path))
|
||||
return false;
|
||||
|
||||
try {
|
||||
PDictionary.FromFile (path);
|
||||
return true;
|
||||
} catch {
|
||||
File.Delete (path);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool InterfaceDefinitionChanged (ITaskItem interfaceDefinition, ITaskItem log)
|
||||
{
|
||||
return !LogExists (log.ItemSpec) || File.GetLastWriteTime (log.ItemSpec) < File.GetLastWriteTime (interfaceDefinition.ItemSpec);
|
||||
}
|
||||
|
||||
bool CompileInterfaceDefinitions (string baseManifestDir, string baseOutputDir, List<ITaskItem> compiled, IList<ITaskItem> manifests, out bool changed)
|
||||
{
|
||||
var mapping = new Dictionary<string, IDictionary> ();
|
||||
var unique = new Dictionary<string, ITaskItem> ();
|
||||
var targets = GetTargetDevices (plist).ToList ();
|
||||
|
||||
changed = false;
|
||||
|
||||
foreach (var item in InterfaceDefinitions) {
|
||||
var bundleName = GetBundleRelativeOutputPath (item);
|
||||
var manifest = new TaskItem (Path.Combine (baseManifestDir, bundleName));
|
||||
var manifestDir = Path.GetDirectoryName (manifest.ItemSpec);
|
||||
ITaskItem duplicate;
|
||||
string output;
|
||||
|
||||
if (!File.Exists (item.ItemSpec)) {
|
||||
Log.LogError (null, null, null, item.ItemSpec, 0, 0, 0, 0, "The file '{0}' does not exist.", item.ItemSpec);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unique.TryGetValue (bundleName, out duplicate)) {
|
||||
Log.LogError (null, null, null, item.ItemSpec, 0, 0, 0, 0, "The file '{0}' conflicts with '{1}'.", item.ItemSpec, duplicate.ItemSpec);
|
||||
continue;
|
||||
}
|
||||
|
||||
unique.Add (bundleName, item);
|
||||
|
||||
var resourceTags = item.GetMetadata ("ResourceTags");
|
||||
var path = Path.Combine (baseOutputDir, bundleName);
|
||||
var outputDir = Path.GetDirectoryName (path);
|
||||
var name = GetPathWithoutExtension (path);
|
||||
var extension = Path.GetExtension (path);
|
||||
var expected = new TaskItem (path);
|
||||
|
||||
expected.SetMetadata ("InterfaceDefinition", item.ItemSpec);
|
||||
expected.SetMetadata ("LogicalName", bundleName);
|
||||
expected.SetMetadata ("Optimize", "false");
|
||||
|
||||
if (!string.IsNullOrEmpty (resourceTags))
|
||||
expected.SetMetadata ("ResourceTags", resourceTags);
|
||||
|
||||
if (UseCompilationDirectory) {
|
||||
// Note: When using --compilation-directory, we need to specify the output path as the parent directory
|
||||
output = Path.GetDirectoryName (path);
|
||||
} else {
|
||||
output = expected.ItemSpec;
|
||||
}
|
||||
|
||||
if (InterfaceDefinitionChanged (item, manifest)) {
|
||||
Directory.CreateDirectory (manifestDir);
|
||||
Directory.CreateDirectory (outputDir);
|
||||
|
||||
if ((Compile (new[] { item }, output, manifest)) != 0)
|
||||
return false;
|
||||
|
||||
changed = true;
|
||||
} else {
|
||||
Log.LogMessage (MessageImportance.Low, "Skipping `{0}' as the output file, `{1}', is newer.", item.ItemSpec, manifest.ItemSpec);
|
||||
}
|
||||
|
||||
try {
|
||||
var dict = PDictionary.FromFile (manifest.ItemSpec);
|
||||
|
||||
LogWarningsAndErrors (dict, item);
|
||||
} catch (Exception ex) {
|
||||
Log.LogError ("Failed to load output log file for {0}: {1}", ToolName, ex.Message);
|
||||
if (File.Exists (manifest.ItemSpec))
|
||||
Log.LogError ("ibtool log: {0}", File.ReadAllText (manifest.ItemSpec));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (UseCompilationDirectory) {
|
||||
// Note: When using a compilation-directory, we'll scan dir the baseOutputDir later as
|
||||
// an optimization to collect all of the compiled output in one fell swoop.
|
||||
var metadata = expected.CloneCustomMetadata ();
|
||||
|
||||
foreach (var target in targets)
|
||||
mapping.Add (name + "~" + target + extension, metadata);
|
||||
|
||||
mapping.Add (path, metadata);
|
||||
} else {
|
||||
compiled.AddRange (GetCompilationOutput (expected));
|
||||
}
|
||||
|
||||
manifests.Add (manifest);
|
||||
}
|
||||
|
||||
if (UseCompilationDirectory)
|
||||
compiled.AddRange (GetCompilationDirectoryOutput (baseOutputDir, mapping));
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
bool LinkStoryboards (string baseManifestDir, string baseOutputDir, List<ITaskItem> storyboards, List<ITaskItem> linked, IList<ITaskItem> manifests, bool changed)
|
||||
{
|
||||
var manifest = new TaskItem (Path.Combine (baseManifestDir, "link"));
|
||||
var mapping = new Dictionary<string, IDictionary> ();
|
||||
var unique = new HashSet<string> ();
|
||||
var items = new List<ITaskItem> ();
|
||||
|
||||
// Make sure that `Main.storyboardc` is listed *before* `Main~ipad.storyboardc` and `Main~iphone.storyboardc`,
|
||||
// this is important for the next step to filter out the device-specific storyboards based on the same source.
|
||||
storyboards.Sort ((x, y) => string.Compare (x.ItemSpec, y.ItemSpec, StringComparison.Ordinal));
|
||||
|
||||
// Populate our metadata mapping table so we can properly restore the metadata to the linked items.
|
||||
//
|
||||
// While we are at it, we'll also filter out device-specific storyboards since ibtool doesn't
|
||||
// require them if we have an equivalent generic version.
|
||||
for (int i = 0; i < storyboards.Count; i++) {
|
||||
var interfaceDefinition = storyboards[i].GetMetadata ("InterfaceDefinition");
|
||||
var bundleName = storyboards[i].GetMetadata ("LogicalName");
|
||||
var path = Path.Combine (baseOutputDir, bundleName);
|
||||
|
||||
storyboards[i].RemoveMetadata ("InterfaceDefinition");
|
||||
var metadata = storyboards[i].CloneCustomMetadata ();
|
||||
mapping.Add (path, metadata);
|
||||
|
||||
if (unique.Add (interfaceDefinition))
|
||||
items.Add (storyboards[i]);
|
||||
}
|
||||
|
||||
// We only need to run `ibtool --link` if storyboards have changed...
|
||||
if (changed) {
|
||||
if (Directory.Exists (baseOutputDir))
|
||||
Directory.Delete (baseOutputDir, true);
|
||||
|
||||
if (File.Exists (manifest.ItemSpec))
|
||||
File.Delete (manifest.ItemSpec);
|
||||
|
||||
Directory.CreateDirectory (baseManifestDir);
|
||||
Directory.CreateDirectory (baseOutputDir);
|
||||
|
||||
try {
|
||||
Link = true;
|
||||
|
||||
if ((Compile (items.ToArray (), baseOutputDir, manifest)) != 0)
|
||||
return false;
|
||||
} finally {
|
||||
Link = false;
|
||||
}
|
||||
}
|
||||
|
||||
linked.AddRange (GetCompilationDirectoryOutput (baseOutputDir, mapping));
|
||||
|
||||
manifests.Add (manifest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IEnumerable<ITaskItem> RecursivelyEnumerateFiles (ITaskItem output)
|
||||
{
|
||||
var nibDir = output.GetMetadata ("LogicalName");
|
||||
|
@ -120,106 +351,36 @@ namespace Xamarin.MacDev.Tasks
|
|||
yield break;
|
||||
}
|
||||
|
||||
static string GetPathWithoutExtension (string path)
|
||||
IEnumerable<ITaskItem> GetBundleResources (ITaskItem compiledItem)
|
||||
{
|
||||
int dot = path.LastIndexOf ('.');
|
||||
var baseLogicalName = compiledItem.GetMetadata ("LogicalName");
|
||||
var baseDir = compiledItem.ItemSpec;
|
||||
|
||||
return path.Substring (0, dot);
|
||||
}
|
||||
// Note: Watch App storyboards will be compiled to something like Interface.storyboardc/Interface.plist, but
|
||||
// Interface.plist needs to be moved up 1 level (e.g. drop the "Interface.storyboardc").
|
||||
// See https://bugzilla.xamarin.com/show_bug.cgi?id=33853 for details
|
||||
if (IsWatchApp && baseLogicalName.EndsWith (".storyboardc", StringComparison.Ordinal))
|
||||
baseLogicalName = Path.GetDirectoryName (baseLogicalName);
|
||||
|
||||
IEnumerable<ITaskItem> GetCompilationDirectoryOutput (ITaskItem expected)
|
||||
{
|
||||
var dir = Path.GetDirectoryName (expected.ItemSpec);
|
||||
foreach (var path in Directory.EnumerateFiles (baseDir, "*.*", SearchOption.AllDirectories)) {
|
||||
var rpath = PathUtils.AbsoluteToRelative (baseDir, Path.GetFullPath (path));
|
||||
var bundleResource = new TaskItem (path);
|
||||
string logicalName;
|
||||
|
||||
if (!Directory.Exists (dir))
|
||||
yield break;
|
||||
if (!string.IsNullOrEmpty (baseLogicalName))
|
||||
logicalName = Path.Combine (baseLogicalName, rpath);
|
||||
else
|
||||
logicalName = rpath;
|
||||
|
||||
var name = Path.GetFileNameWithoutExtension (expected.ItemSpec);
|
||||
var extension = Path.GetExtension (expected.ItemSpec);
|
||||
var nibDir = expected.GetMetadata ("LogicalName");
|
||||
var targets = GetTargetDevices (plist).ToList ();
|
||||
compiledItem.CopyMetadataTo (bundleResource);
|
||||
bundleResource.SetMetadata ("LogicalName", logicalName);
|
||||
|
||||
foreach (var path in Directory.GetFileSystemEntries (dir)) {
|
||||
// check that the FileNameWithoutExtension matches *exactly*
|
||||
if (string.Compare (path, dir.Length + 1, name, 0, name.Length) != 0)
|
||||
continue;
|
||||
|
||||
int startIndex = dir.Length + 1 + name.Length;
|
||||
|
||||
// match against files that have a "~" + $target (iphone, ipad, etc)
|
||||
if (path.Length > startIndex && path[startIndex] == '~') {
|
||||
bool matched = false;
|
||||
|
||||
startIndex++;
|
||||
|
||||
foreach (var target in targets) {
|
||||
// Note: we match the target case-insensitively because of https://bugzilla.xamarin.com/show_bug.cgi?id=44811
|
||||
if (string.Compare (path, startIndex, target, 0, target.Length, StringComparison.OrdinalIgnoreCase) == 0) {
|
||||
startIndex += target.Length;
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched)
|
||||
continue;
|
||||
}
|
||||
|
||||
// at this point, all that should be left is the file/directory extension
|
||||
if (path.Length != startIndex + extension.Length || string.Compare (path, startIndex, extension, 0, extension.Length) != 0)
|
||||
continue;
|
||||
|
||||
var fileName = Path.GetFileName (path);
|
||||
var logicalName = !string.IsNullOrEmpty (nibDir) ? Path.Combine (nibDir, fileName) : fileName;
|
||||
var item = new TaskItem (path);
|
||||
expected.CopyMetadataTo (item);
|
||||
item.SetMetadata ("LogicalName", logicalName);
|
||||
|
||||
yield return item;
|
||||
yield return bundleResource;
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
IEnumerable<ITaskItem> GetCompiledBundleResources (ITaskItem output)
|
||||
{
|
||||
if (IsWatchApp && !UseCompilationDirectory) {
|
||||
var logicalName = output.GetMetadata ("LogicalName");
|
||||
|
||||
foreach (var extension in WatchAppExtensions) {
|
||||
var path = GetPathWithoutExtension (output.ItemSpec) + extension;
|
||||
if (File.Exists (path)) {
|
||||
var item = new TaskItem (path);
|
||||
item.SetMetadata ("LogicalName", GetPathWithoutExtension (logicalName) + extension);
|
||||
item.SetMetadata ("Optimize", "false");
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
} else if (Directory.Exists (output.ItemSpec)) {
|
||||
// Note: historically, only storyboard files compiled to directories containing the real nib files, but the new iOS 8 .xib's do as well.
|
||||
foreach (var file in RecursivelyEnumerateFiles (output))
|
||||
yield return file;
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return output;
|
||||
}
|
||||
|
||||
static bool ManifestExists (string path)
|
||||
{
|
||||
if (!File.Exists (path))
|
||||
return false;
|
||||
|
||||
try {
|
||||
PDictionary.FromFile (path);
|
||||
return true;
|
||||
} catch {
|
||||
File.Delete (path);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Execute ()
|
||||
{
|
||||
Log.LogTaskName ("IBTool");
|
||||
|
@ -242,12 +403,11 @@ namespace Xamarin.MacDev.Tasks
|
|||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
var ibtoolManifestDir = Path.Combine (IntermediateOutputPath, ToolName + "-manifests");
|
||||
var ibtoolOutputDir = Path.Combine (IntermediateOutputPath, ToolName);
|
||||
var bundleResources = new List<ITaskItem> ();
|
||||
var ibtoolManifestDir = Path.Combine (IntermediateOutputPath, "ibtool-manifests");
|
||||
var ibtoolOutputDir = Path.Combine (IntermediateOutputPath, "ibtool");
|
||||
var outputManifests = new List<ITaskItem> ();
|
||||
var compiled = new List<ITaskItem> ();
|
||||
bool changed = false;
|
||||
bool changed;
|
||||
|
||||
if (InterfaceDefinitions.Length > 0) {
|
||||
if (AppManifest != null) {
|
||||
|
@ -264,105 +424,51 @@ namespace Xamarin.MacDev.Tasks
|
|||
|
||||
Directory.CreateDirectory (ibtoolManifestDir);
|
||||
Directory.CreateDirectory (ibtoolOutputDir);
|
||||
}
|
||||
|
||||
foreach (var item in InterfaceDefinitions) {
|
||||
var bundleName = GetBundleRelativeOutputPath (item);
|
||||
var manifest = new TaskItem (Path.Combine (ibtoolManifestDir, bundleName));
|
||||
var manifestDir = Path.GetDirectoryName (manifest.ItemSpec);
|
||||
var resourceTags = item.GetMetadata ("ResourceTags");
|
||||
ITaskItem expected, output;
|
||||
string rpath, outputDir;
|
||||
|
||||
if (!File.Exists (item.ItemSpec)) {
|
||||
Log.LogError (null, null, null, item.ItemSpec, 0, 0, 0, 0, "The file '{0}' does not exist.", item.ItemSpec);
|
||||
continue;
|
||||
}
|
||||
if (!CompileInterfaceDefinitions (ibtoolManifestDir, ibtoolOutputDir, compiled, outputManifests, out changed))
|
||||
return false;
|
||||
|
||||
rpath = Path.Combine (ibtoolOutputDir, bundleName);
|
||||
outputDir = Path.GetDirectoryName (rpath);
|
||||
expected = new TaskItem (rpath);
|
||||
if (CanLinkStoryboards) {
|
||||
var storyboards = new List<ITaskItem> ();
|
||||
var linked = new List<ITaskItem> ();
|
||||
var unique = new HashSet<string> ();
|
||||
|
||||
expected.SetMetadata ("LogicalName", bundleName);
|
||||
expected.SetMetadata ("Optimize", "false");
|
||||
for (int i = 0; i < compiled.Count; i++) {
|
||||
// pretend that non-storyboardc items (e.g. *.nib) are already 'linked'
|
||||
if (compiled[i].ItemSpec.EndsWith (".storyboardc", StringComparison.Ordinal)) {
|
||||
var interfaceDefinition = compiled[i].GetMetadata ("InterfaceDefinition");
|
||||
unique.Add (interfaceDefinition);
|
||||
storyboards.Add (compiled[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty (resourceTags))
|
||||
expected.SetMetadata ("ResourceTags", resourceTags);
|
||||
// just pretend any *nib's have already been 'linked'...
|
||||
compiled[i].RemoveMetadata ("InterfaceDefinition");
|
||||
linked.Add (compiled[i]);
|
||||
}
|
||||
|
||||
if (UseCompilationDirectory) {
|
||||
// Note: When using --compilation-directory, we need to specify the output path as the parent directory
|
||||
output = new TaskItem (expected);
|
||||
output.ItemSpec = Path.GetDirectoryName (output.ItemSpec);
|
||||
output.SetMetadata ("LogicalName", Path.GetDirectoryName (bundleName));
|
||||
// only link the storyboards if there are multiple unique storyboards
|
||||
if (unique.Count > 1) {
|
||||
var linkOutputDir = Path.Combine (IntermediateOutputPath, "ibtool-link");
|
||||
|
||||
if (!LinkStoryboards (ibtoolManifestDir, linkOutputDir, storyboards, linked, outputManifests, changed))
|
||||
return false;
|
||||
|
||||
compiled = linked;
|
||||
}
|
||||
} else {
|
||||
output = expected;
|
||||
for (int i = 0; i < compiled.Count; i++)
|
||||
compiled[i].RemoveMetadata ("InterfaceDefinition");
|
||||
}
|
||||
|
||||
if (!ManifestExists (manifest.ItemSpec) || File.GetLastWriteTime (manifest.ItemSpec) < File.GetLastWriteTime (item.ItemSpec)) {
|
||||
Directory.CreateDirectory (manifestDir);
|
||||
Directory.CreateDirectory (outputDir);
|
||||
|
||||
if ((Compile (new[] { item }, output, manifest)) != 0)
|
||||
return false;
|
||||
|
||||
changed = true;
|
||||
} else {
|
||||
Log.LogMessage (MessageImportance.Low, "Skipping `{0}' as the output file, `{1}', is newer.", item.ItemSpec, manifest.ItemSpec);
|
||||
}
|
||||
|
||||
try {
|
||||
var dict = PDictionary.FromFile (manifest.ItemSpec);
|
||||
|
||||
LogWarningsAndErrors (dict, item);
|
||||
} catch (Exception ex) {
|
||||
Log.LogError ("Failed to load output manifest for {0}: {1}", ToolName, ex.Message);
|
||||
if (File.Exists (manifest.ItemSpec))
|
||||
Log.LogError ("Output manifest contents: {0}", File.ReadAllText (manifest.ItemSpec));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (UseCompilationDirectory)
|
||||
compiled.AddRange (GetCompilationDirectoryOutput (expected));
|
||||
else
|
||||
bundleResources.AddRange (GetCompiledBundleResources (output));
|
||||
|
||||
outputManifests.Add (manifest);
|
||||
}
|
||||
|
||||
if (InterfaceDefinitions.Length > 0 && UseCompilationDirectory) {
|
||||
var output = new TaskItem (ibtoolOutputDir);
|
||||
output.SetMetadata ("LogicalName", "");
|
||||
var bundleResources = new List<ITaskItem> ();
|
||||
|
||||
if (!CanLinkStoryboards)
|
||||
bundleResources.AddRange (GetCompiledBundleResources (output));
|
||||
}
|
||||
|
||||
if (CanLinkStoryboards && compiled.Count > 0) {
|
||||
var linkOutputDir = Path.Combine (IntermediateOutputPath, ToolName + "-link");
|
||||
var manifest = new TaskItem (Path.Combine (ibtoolManifestDir, "link"));
|
||||
var output = new TaskItem (linkOutputDir);
|
||||
|
||||
if (changed) {
|
||||
if (Directory.Exists (output.ItemSpec))
|
||||
Directory.Delete (output.ItemSpec, true);
|
||||
|
||||
if (File.Exists (manifest.ItemSpec))
|
||||
File.Delete (manifest.ItemSpec);
|
||||
|
||||
Directory.CreateDirectory (Path.GetDirectoryName (manifest.ItemSpec));
|
||||
Directory.CreateDirectory (output.ItemSpec);
|
||||
|
||||
Link = true;
|
||||
|
||||
if ((Compile (compiled.ToArray (), output, manifest)) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
output = new TaskItem (linkOutputDir);
|
||||
output.SetMetadata ("LogicalName", "");
|
||||
|
||||
bundleResources.AddRange (GetCompiledBundleResources (output));
|
||||
outputManifests.Add (manifest);
|
||||
foreach (var compiledItem in compiled) {
|
||||
if (Directory.Exists (compiledItem.ItemSpec))
|
||||
bundleResources.AddRange (GetBundleResources (compiledItem));
|
||||
else if (File.Exists (compiledItem.ItemSpec))
|
||||
bundleResources.Add (compiledItem);
|
||||
}
|
||||
|
||||
BundleResources = bundleResources.ToArray ();
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace Xamarin.MacDev.Tasks
|
|||
return startInfo;
|
||||
}
|
||||
|
||||
protected int Compile (ITaskItem[] items, ITaskItem output, ITaskItem manifest)
|
||||
protected int Compile (ITaskItem[] items, string output, ITaskItem manifest)
|
||||
{
|
||||
var environment = new Dictionary<string, string> ();
|
||||
var args = new ProcessArgumentBuilder ();
|
||||
|
@ -147,7 +147,7 @@ namespace Xamarin.MacDev.Tasks
|
|||
else
|
||||
args.Add ("--compile");
|
||||
|
||||
args.AddQuoted (output.GetMetadata ("FullPath"));
|
||||
args.AddQuoted (Path.GetFullPath (output));
|
||||
|
||||
foreach (var item in items)
|
||||
args.AddQuoted (item.GetMetadata ("FullPath"));
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="5xv-Yx-H4r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="lP3-9c-L6b">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="MyLinkedViewController" id="5xv-Yx-H4r" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="vTD-aw-nUj"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="IyX-Ik-oKG"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="gMo-tm-chA">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Linked!" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gd9-6P-3AQ">
|
||||
<rect key="frame" x="159" y="323" width="56" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="J6q-Vo-r8c" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="201" y="102"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="suC-9c-gGU">
|
||||
<rect key="frame" x="164" y="318" width="46" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<connections>
|
||||
<segue destination="Xa5-w5-hXO" kind="show" id="1S1-fR-EBd"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
<!--Linked-->
|
||||
<scene sceneID="brE-JR-pH9">
|
||||
<objects>
|
||||
<viewControllerPlaceholder storyboardIdentifier="MyLinkedViewController" storyboardName="Linked" id="Xa5-w5-hXO" sceneMemberID="viewController"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="C8X-qd-oxE" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="522" y="94"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>IBToolTaskTest</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.your-company.ibtooltasktest</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>IBToolTaskTest</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>10.1</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="5xv-Yx-H4r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="lP3-9c-L6b">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="MyLinkedViewController" id="5xv-Yx-H4r" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="vTD-aw-nUj"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="IyX-Ik-oKG"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="gMo-tm-chA">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Linked!" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gd9-6P-3AQ">
|
||||
<rect key="frame" x="159" y="323" width="56" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="J6q-Vo-r8c" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="201" y="102"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="suC-9c-gGU">
|
||||
<rect key="frame" x="164" y="318" width="46" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<connections>
|
||||
<segue destination="Xa5-w5-hXO" kind="show" id="1S1-fR-EBd"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
<!--Linked-->
|
||||
<scene sceneID="brE-JR-pH9">
|
||||
<objects>
|
||||
<viewControllerPlaceholder storyboardIdentifier="MyLinkedViewController" storyboardName="Linked" id="Xa5-w5-hXO" sceneMemberID="viewController"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="C8X-qd-oxE" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="522" y="94"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -433,14 +433,9 @@ namespace Xamarin.iOS.Tasks
|
|||
public void BundleResources ()
|
||||
{
|
||||
var actool = Path.Combine ("obj", "iPhoneSimulator", "Debug", "actool", "bundle");
|
||||
var ibtool = Path.Combine ("obj", "iPhoneSimulator", "Debug", "ibtool");
|
||||
var path = Path.Combine (MonoTouchProjectPath, "Info.plist");
|
||||
var plist = PDictionary.FromFile (path);
|
||||
string ibtool;
|
||||
|
||||
if (AppleSdkSettings.XcodeVersion.Major >= 7)
|
||||
ibtool = Path.Combine ("obj", "iPhoneSimulator", "Debug", "ibtool-link");
|
||||
else
|
||||
ibtool = Path.Combine ("obj", "iPhoneSimulator", "Debug", "ibtool");
|
||||
|
||||
plist.SetMinimumOSVersion ("6.1");
|
||||
plist.Save (path, true);
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Xamarin.MacDev;
|
||||
using Xamarin.MacDev.Tasks;
|
||||
|
||||
namespace Xamarin.iOS.Tasks
|
||||
{
|
||||
[TestFixture]
|
||||
public class IBToolTaskTests
|
||||
{
|
||||
static IBTool CreateIBToolTask (PlatformFramework framework, string projectDir, string intermediateOutputPath)
|
||||
{
|
||||
var interfaceDefinitions = new List<ITaskItem> ();
|
||||
var sdk = IPhoneSdks.GetSdk (framework);
|
||||
var version = IPhoneSdkVersion.GetDefault (sdk, false);
|
||||
var root = sdk.GetSdkPath (version, false);
|
||||
var usr = Path.Combine (sdk.DeveloperRoot, "usr");
|
||||
var bin = Path.Combine (usr, "bin");
|
||||
string platform;
|
||||
|
||||
switch (framework) {
|
||||
case PlatformFramework.WatchOS:
|
||||
platform = "WatchOS";
|
||||
break;
|
||||
case PlatformFramework.TVOS:
|
||||
platform = "AppleTVOS";
|
||||
break;
|
||||
default:
|
||||
platform = "iPhoneOS";
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var item in Directory.EnumerateFiles (projectDir, "*.storyboard", SearchOption.AllDirectories))
|
||||
interfaceDefinitions.Add (new TaskItem (item));
|
||||
|
||||
foreach (var item in Directory.EnumerateFiles (projectDir, "*.xib", SearchOption.AllDirectories))
|
||||
interfaceDefinitions.Add (new TaskItem (item));
|
||||
|
||||
return new IBTool {
|
||||
AppManifest = new TaskItem (Path.Combine (projectDir, "Info.plist")),
|
||||
InterfaceDefinitions = interfaceDefinitions.ToArray (),
|
||||
IntermediateOutputPath = intermediateOutputPath,
|
||||
BuildEngine = new TestEngine (),
|
||||
ResourcePrefix = "Resources",
|
||||
ProjectDir = projectDir,
|
||||
SdkPlatform = platform,
|
||||
SdkVersion = version.ToString (),
|
||||
SdkUsrPath = usr,
|
||||
SdkBinPath = bin,
|
||||
SdkRoot = root,
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBasicIBToolFunctionality ()
|
||||
{
|
||||
var tmp = Path.Combine (Path.GetTempPath (), "basic-ibtool");
|
||||
|
||||
Directory.CreateDirectory (tmp);
|
||||
|
||||
try {
|
||||
var ibtool = CreateIBToolTask (PlatformFramework.iOS, "../MyIBToolLinkTest", tmp);
|
||||
var bundleResources = new HashSet<string> ();
|
||||
|
||||
Assert.IsTrue (ibtool.Execute (), "Execution of IBTool task failed.");
|
||||
|
||||
foreach (var bundleResource in ibtool.BundleResources) {
|
||||
Assert.IsTrue (File.Exists (bundleResource.ItemSpec), "File does not exist: {0}", bundleResource.ItemSpec);
|
||||
Assert.IsNotNullOrEmpty (bundleResource.GetMetadata ("LogicalName"), "The 'LogicalName' metadata must be set.");
|
||||
Assert.IsNotNullOrEmpty (bundleResource.GetMetadata ("Optimize"), "The 'Optimize' metadata must be set.");
|
||||
|
||||
bundleResources.Add (bundleResource.GetMetadata ("LogicalName"));
|
||||
}
|
||||
|
||||
string[] expected = { "LaunchScreen~ipad.nib/objects-8.0+.nib",
|
||||
"LaunchScreen~ipad.nib/runtime.nib",
|
||||
"LaunchScreen~iphone.nib/objects-8.0+.nib",
|
||||
"LaunchScreen~iphone.nib/runtime.nib",
|
||||
"Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC~ipad.nib/objects-8.0+.nib",
|
||||
"Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC~ipad.nib/runtime.nib",
|
||||
"Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC~iphone.nib/objects-8.0+.nib",
|
||||
"Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC~iphone.nib/runtime.nib",
|
||||
"Main.storyboardc/UIViewController-BYZ-38-t0r~ipad.nib/objects-8.0+.nib",
|
||||
"Main.storyboardc/UIViewController-BYZ-38-t0r~ipad.nib/runtime.nib",
|
||||
"Main.storyboardc/UIViewController-BYZ-38-t0r~iphone.nib/objects-8.0+.nib",
|
||||
"Main.storyboardc/UIViewController-BYZ-38-t0r~iphone.nib/runtime.nib",
|
||||
"Main~ipad.storyboardc/Info-8.0+.plist",
|
||||
"Main~ipad.storyboardc/Info.plist",
|
||||
"Main~iphone.storyboardc/Info-8.0+.plist",
|
||||
"Main~iphone.storyboardc/Info.plist"
|
||||
};
|
||||
|
||||
foreach (var bundleResource in expected)
|
||||
Assert.IsTrue (bundleResources.Contains (bundleResource), "BundleResources should include '{0}'", bundleResource);
|
||||
|
||||
Assert.AreEqual (expected.Length, bundleResources.Count, "Unexpected number of BundleResources");
|
||||
} finally {
|
||||
Directory.Delete (tmp, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAdvancedIBToolFunctionality ()
|
||||
{
|
||||
var tmp = Path.Combine (Path.GetTempPath (), "advanced-ibtool");
|
||||
IBTool ibtool;
|
||||
|
||||
Directory.CreateDirectory (tmp);
|
||||
|
||||
try {
|
||||
ibtool = CreateIBToolTask (PlatformFramework.iOS, "../IBToolTaskTests/LinkedAndTranslated", tmp);
|
||||
var bundleResources = new HashSet<string> ();
|
||||
|
||||
// Add some ResourceTags...
|
||||
foreach (var storyboard in ibtool.InterfaceDefinitions) {
|
||||
var tag = Path.GetFileNameWithoutExtension (storyboard.ItemSpec);
|
||||
storyboard.SetMetadata ("ResourceTags", tag);
|
||||
}
|
||||
|
||||
Assert.IsTrue (ibtool.Execute (), "Execution of IBTool task failed.");
|
||||
|
||||
foreach (var bundleResource in ibtool.BundleResources) {
|
||||
var bundleName = bundleResource.GetMetadata ("LogicalName");
|
||||
var tag = bundleResource.GetMetadata ("ResourceTags");
|
||||
|
||||
Assert.IsTrue (File.Exists (bundleResource.ItemSpec), "File does not exist: {0}", bundleResource.ItemSpec);
|
||||
Assert.IsNotNullOrEmpty (bundleResource.GetMetadata ("LogicalName"), "The 'LogicalName' metadata must be set.");
|
||||
Assert.IsNotNullOrEmpty (bundleResource.GetMetadata ("Optimize"), "The 'Optimize' metadata must be set.");
|
||||
|
||||
Assert.IsNotNullOrEmpty (tag, "The 'ResourceTags' metadata should be set.");
|
||||
Assert.IsTrue (bundleName.Contains (".lproj/" + tag + ".storyboardc/"), "BundleResource does not have the proper ResourceTags set: {0}", bundleName);
|
||||
|
||||
bundleResources.Add (bundleName);
|
||||
}
|
||||
|
||||
string[] expected = {
|
||||
"Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib",
|
||||
"Base.lproj/LaunchScreen.storyboardc/Info.plist",
|
||||
"Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib",
|
||||
"Base.lproj/Linked.storyboardc/5xv-Yx-H4r-view-gMo-tm-chA.nib",
|
||||
"Base.lproj/Linked.storyboardc/Info.plist",
|
||||
"Base.lproj/Linked.storyboardc/MyLinkedViewController.nib",
|
||||
"Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib",
|
||||
"Base.lproj/Main.storyboardc/Info.plist",
|
||||
"Base.lproj/Main.storyboardc/MyLinkedViewController.nib",
|
||||
"Base.lproj/Main.storyboardc/UIViewController-BYZ-38-t0r.nib",
|
||||
"en.lproj/Linked.storyboardc/5xv-Yx-H4r-view-gMo-tm-chA.nib",
|
||||
"en.lproj/Linked.storyboardc/Info.plist",
|
||||
"en.lproj/Linked.storyboardc/MyLinkedViewController.nib",
|
||||
"en.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib",
|
||||
"en.lproj/Main.storyboardc/Info.plist",
|
||||
"en.lproj/Main.storyboardc/MyLinkedViewController.nib",
|
||||
"en.lproj/Main.storyboardc/UIViewController-BYZ-38-t0r.nib"
|
||||
};
|
||||
|
||||
foreach (var bundleResource in expected)
|
||||
Assert.IsTrue (bundleResources.Contains (bundleResource), "BundleResources should include '{0}'", bundleResource);
|
||||
|
||||
Assert.AreEqual (expected.Length, bundleResources.Count, "Unexpected number of BundleResources");
|
||||
} finally {
|
||||
Directory.Delete (tmp, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -108,6 +108,7 @@
|
|||
<Compile Include="TaskTests\GeneratePlistTaskTests\GeneratePlistTaskTests_watchOS.cs" />
|
||||
<Compile Include="ProjectsTests\ReleaseBuild.cs" />
|
||||
<Compile Include="TaskTests\PropertyListEditorTaskTests.cs" />
|
||||
<Compile Include="TaskTests\IBToolTaskTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче