Skip to content

Commit

Permalink
WIP for xamarin#3755.
Browse files Browse the repository at this point in the history
  • Loading branch information
rolfbjarne committed Jul 26, 2019
1 parent f480c0b commit c870e38
Show file tree
Hide file tree
Showing 32 changed files with 1,274 additions and 273 deletions.
2 changes: 1 addition & 1 deletion Make.config
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ SYSTEM_MSBUILD=unset MSBuildExtensionsPath && $(MONO_PREFIX)/bin/msbuild
SYSTEM_RESGEN=$(MONO_PREFIX)/bin/resgen

XIBUILD_EXE_PATH=$(abspath $(TOP)/tools/xibuild/bin/Debug/xibuild.exe)
SYSTEM_XIBUILD=$(SYSTEM_MONO) $(XIBUILD_EXE_PATH) $(XIBUILD_VERBOSITY)
SYSTEM_XIBUILD=$(SYSTEM_MONO) --debug $(XIBUILD_EXE_PATH) $(XIBUILD_VERBOSITY)

PKG_CONFIG=$(MONO_PREFIX)/bin/pkg-config

Expand Down
1 change: 1 addition & 0 deletions msbuild/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.build-stamp
.nuget-stamp
.stamp-test-xml

6 changes: 5 additions & 1 deletion msbuild/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ MSBUILD_SYMLINKS =
MSBUILD_TASK_ASSEMBLIES =

ALL_SOURCES:= $(shell git ls-files | sed 's/ /\\ /g') $(wildcard $(XAMARIN_MACDEV_PATH)/Xamarin.MacDev/*.cs) $(wildcard $(XAMARIN_MACDEV_PATH)/Xamarin.MacDev/*.csproj)
NUGET_SOURCES:= $(shell git ls-files | grep -E "(csproj|packages.config)$$" | sed 's/ /\\ /g')
CONFIG = Debug

##
Expand Down Expand Up @@ -300,8 +301,11 @@ $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)/lib/msbuild/%.dll: build/%.dll | $(MA
# we must install locally during 'make all', because the F# build depends on the msbuild targets/assemblies.
all-local:: $(MSBUILD_PRODUCTS) .stamp-test-xml

.build-stamp: $(ALL_SOURCES)
.nuget-stamp: $(NUGET_SOURCES)
$(Q) $(SYSTEM_MONO) /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/nuget/NuGet.exe restore
$(Q) touch $@

.build-stamp: .nuget-stamp $(ALL_SOURCES)
$(Q) $(SYSTEM_MSBUILD) $(XBUILD_VERBOSITY)
$(Q) touch $@

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ public override bool Execute ()
Log.LogError ("Error writing archived-expanded-entitlements.xcent file: {0}", ex.Message);
return false;
}
} else {
Log.LogMessage (MessageImportance.Low, "The compiled entitlements have not changed.");
}

return !Log.HasLoggedErrors;
Expand Down
2 changes: 0 additions & 2 deletions msbuild/Xamarin.MacDev.Tasks.Core/Tasks/DSymUtilTaskBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ public abstract class DSymUtilTaskBase : ToolTask
[Required]
public string AppBundleDir { get; set; }

public string Architectures { get; set; }

[Required]
public string DSymDir { get; set; }

Expand Down
182 changes: 163 additions & 19 deletions msbuild/Xamarin.MacDev.Tasks.Core/Tasks/DittoTaskBase.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

using Xamarin.Bundler;

namespace Xamarin.MacDev.Tasks
{
public abstract class DittoTaskBase : ToolTask
public abstract class DittoTaskBase : Task
{
#region Inputs

Expand All @@ -19,38 +24,177 @@ public abstract class DittoTaskBase : ToolTask
[Output]
public ITaskItem Destination { get; set; }

#endregion
// Files or directories in the destination which are ignored.
// Must be relative paths.
// Only considered if Source is a directory.
public ITaskItem[] Ignore { get; set; }

protected override string ToolName {
get { return "ditto"; }
}
[Output]
public ITaskItem[] CopiedFiles { get; set; }

[Output]
public bool AnyCopiedFiles { get; set; }

protected override string GenerateFullPathToTool ()
public ITaskItem ToolExe { get; set; }
public ITaskItem ToolPath { get; set; }

#endregion

public override bool Execute ()
{
if (!string.IsNullOrEmpty (ToolPath))
return Path.Combine (ToolPath, ToolExe);
var src = Path.GetFullPath (Source.ItemSpec);
var dst = Path.GetFullPath (Destination.ItemSpec);

if (File.Exists (src)) {
Log.LogMessage ("Copying file from {0} to {1}: {2}", src, dst, Directory.Exists (dst));
if (Directory.Exists (dst))
dst = Path.Combine (dst, Path.GetFileName (src));
Log.LogMessage ("Copying file from {0} to {1}", src, dst);

if (!FileCopier.IsUptodate (src, dst, check_stamp: false)) {
File.Copy (src, dst, true);
files_copied.Add (dst);
Log.LogMessage ("Copied {0} to {1}", src, dst);
} else {
files_skipped.Add (dst);
Log.LogMessage ("Target '{0}' is up-to-date", dst);
}

var path = Path.Combine ("/usr/bin", ToolExe);
} else if (Directory.Exists (src)) {

return File.Exists (path) ? path : ToolExe;
Log.LogMessage ("Copying directory from {0} to {1}", src, dst);

//dst = Path.GetDirectoryName (dst);
//FileCopier.UpdateDirectory (src, dst, CopyFileCallback);
UpdateDirectory (src, dst);
} else {
Log.LogError ("Could not find the source location {0}", src);
}

var copiedFiles = new List<ITaskItem> ();
foreach (var file in files_copied) {
copiedFiles.Add (new TaskItem (file));
Log.LogMessage ($"Copied: {file}: target: {new FileInfo (file).LastWriteTimeUtc}");
}
foreach (var file in files_skipped)
Log.LogMessage ($"Skipped: {file}: {new FileInfo (file).LastWriteTimeUtc}");

AnyCopiedFiles = files_copied.Count > 0;

return !Log.HasLoggedErrors;
}

protected override string GenerateCommandLineCommands ()
List<string> files_copied = new List<string> ();
List<string> files_skipped = new List<string> ();
List<string> files_deleted = new List<string> ();


void UpdateDirectory (string source, string destination)
{
var args = new CommandLineArgumentBuilder ();
var isDirty = false;

source = source.TrimEnd (Path.DirectorySeparatorChar);
destination = destination.TrimEnd (Path.DirectorySeparatorChar);

var src = Directory.GetFileSystemEntries (source, "*", SearchOption.AllDirectories);
var dst = new List<string> ();
foreach (var s in src)
dst.Add (destination + s.Substring (source.Length));

args.Add ("-rsrc");
// Delete any existing files or directories that aren't in the input
if (Directory.Exists (destination)) {
var ignored = Ignore != null ? new HashSet<string> (Ignore.Select ((v) => v.ItemSpec)) : null;
var ignoredDirectories = ignored?.Where ((v) => Directory.Exists (Path.Combine (destination, v))).Select ((v) => v + Path.DirectorySeparatorChar);
var existingFiles = Directory.GetFileSystemEntries (destination);
foreach (var file in existingFiles) {
if (dst.Contains (file))
continue;

args.AddQuoted (Source.ItemSpec);
args.AddQuoted (Destination.ItemSpec);
if (ignored != null) {
var relativePath = file.Substring (destination.Length + 1);
if (ignored.Contains (relativePath)) {
Console.WriteLine ($"The file or directory {file} exists in the destination, but will be ignored.");
continue;
}
var ignoredContainer = ignoredDirectories.FirstOrDefault ((v) => relativePath.StartsWith (v, StringComparison.Ordinal));
if (ignoredContainer != null) {
Console.WriteLine ($"The file or directory {file} exists in the destination, but will be ignored because the containing directory '{ignoredContainer}' is ignored.");
continue;
}
}

return args.ToString ();
if (File.Exists (file)) {
Console.WriteLine ($"Deleting file {file}");
File.Delete (file);
} else {
Console.WriteLine ($"Deleting directory {file}");
Directory.Delete (file, true);
}
isDirty = true;
files_deleted.Add (file);
}
}

// Copy (clone) existing files
for (var i = 0; i < src.Length; i++) {
var s = src [i];
var d = dst [i];
if (Directory.Exists (s)) { // If the source is a directory
if (Directory.Exists (d)) {
Log.LogMessage ("Target '{0}' is up-to-date", d);
} else {
if (File.Exists (d)) // If target is a file
File.Delete (d);
Directory.CreateDirectory (d);
isDirty = true;
}
} else if (FileCopier.IsUptodate (s, d, check_stamp: false)) {
Log.LogMessage ("Target '{0}' is up-to-date", d);
files_skipped.Add (d);
} else {
isDirty = true;
files_copied.Add (d);
Directory.CreateDirectory (Path.GetDirectoryName (d));
File.Copy (s, d, true);
Log.LogMessage ($"Copied: {s} to {d}: target's timestamp: {new FileInfo (d).LastWriteTimeUtc}");
}
}
Console.WriteLine ("IsDirty: {0}", isDirty);
}

protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
CopyFileResult CopyFileCallback (CopyFileWhat what, CopyFileStep stage, IntPtr state, string source, string target, IntPtr ctx)
{
// TODO: do proper parsing of error messages and such
Log.LogMessage (messageImportance, "{0}", singleLine);
Console.WriteLine ("CopyFileCallback ({0}, {1}, 0x{2}, {3}, {4}, 0x{5}) src: {6} tgt: {7}", what, stage, state.ToString ("x"), source, target, ctx.ToString ("x"), new FileInfo (source).LastWriteTimeUtc, new FileInfo (target).LastWriteTimeUtc);

switch (what) {
case CopyFileWhat.File:
if (stage == CopyFileStep.Start) {
if (FileCopier.IsUptodate (source, target, check_stamp: false)) {
files_skipped.Add (target);
Log.LogMessage ("Target '{0}' is up-to-date", target);
return CopyFileResult.Skip;
}
files_copied.Add (target);
if (File.Exists (target))
File.Delete (target);
Log.LogMessage ("Copying {0} to {1}", source, target);
} else if (stage == CopyFileStep.Err) {
Log.LogMessage ("Copying {0} to {1} FAILEEEEEED!!! errno: {2}", source, target, Marshal.GetLastWin32Error ());
return CopyFileResult.Quit;
}
return CopyFileResult.Continue;
case CopyFileWhat.Error:
Log.LogError ("Could not copy the file '{0}' to '{1}': {2}", source, target, FileCopier.strerror (Marshal.GetLastWin32Error ()));
return CopyFileResult.Quit;
case CopyFileWhat.Dir:
case CopyFileWhat.DirCleanup:
case CopyFileWhat.CopyData:
case CopyFileWhat.CopyXattr:
default:
if (stage == CopyFileStep.Err)
return CopyFileResult.Quit;
return CopyFileResult.Continue;
}
}
}
}
11 changes: 11 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ReadItemsFromFileBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ public abstract class ReadItemsFromFileBase : Task
[Required]
public ITaskItem File { get; set; }

// A directory whose contents will be listed, and stored into the specified TargetVariable
// I couldn't figure out how to do this in the .targets file's xml after the call to
// this target, so I ended up adding it here instead.
public ITaskItem ListDirectory { get; set; }
public ITaskItem ListDirectoryTargetVariable { get; set; }

#endregion

#region Outputs
Expand Down Expand Up @@ -55,6 +61,11 @@ private ITaskItem CreateItemFromElement (XElement element)
item.SetMetadata (metadata.Name.LocalName, metadata.Value);
}

if (ListDirectory != null) {
var files = Directory.GetFiles (ListDirectory.ItemSpec);
item.SetMetadata (ListDirectoryTargetVariable.ItemSpec, string.Join (";", files));
}

return item;
}
}
Expand Down
45 changes: 39 additions & 6 deletions msbuild/Xamarin.MacDev.Tasks.Core/Tasks/WriteItemsToFileBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using Microsoft.Build.Tasks;
using System.Xml.Linq;

using F = System.IO.File;

namespace Xamarin.MacDev.Tasks
{
public abstract class WriteItemsToFileBase : Task
Expand All @@ -34,6 +36,8 @@ public abstract class WriteItemsToFileBase : Task

public bool IncludeMetadata { get; set; }

public bool CompareContents { get; set; } = true; // FIXME

#endregion

public override bool Execute ()
Expand All @@ -47,13 +51,42 @@ public override bool Execute ()
new XElement (ItemGroupElementName,
items.Select (item => this.CreateElementFromItem(item)))));

if (this.Overwrite && System.IO.File.Exists (this.File.ItemSpec))
System.IO.File.Delete (this.File.ItemSpec);

if (!Directory.Exists (Path.GetDirectoryName (this.File.ItemSpec)))
Directory.CreateDirectory (Path.GetDirectoryName (this.File.ItemSpec));
var filename = File.ItemSpec;
if (!Overwrite && F.Exists (filename)) {
Log.LogError ($"Target file {filename} already exists.");
return false;
}

document.Save (this.File.ItemSpec);
Directory.CreateDirectory (Path.GetDirectoryName (filename));

if (CompareContents) {
var tmpfile = filename + ".tmp";
document.Save (tmpfile);
if (F.Exists (filename)) {
if (F.ReadAllText (tmpfile) == F.ReadAllText (filename)) {
Log.LogMessage ($"Did not write to {filename} because it didn't change.");
F.Delete (tmpfile);
return true;
} else {
Log.LogMessage ($"Saving to {filename} (target is different).");
Log.LogMessage ("Before:");
Log.LogMessage (F.ReadAllText (filename));
Log.LogMessage ("After:");
Log.LogMessage (F.ReadAllText (tmpfile));
}
F.Copy /* FIXME */ (filename, filename + ".previous", true);
F.Delete (filename);
} else {
Log.LogMessage ($"Saving to {filename} (target does not exist).");
}
F.Move (tmpfile, filename);
} else {
if (F.Exists (filename))
F.Delete (filename);
document.Save (filename);
Log.LogMessage ($"Saving to {filename} (not comparing content).");
}
Log.LogMessage ($"Saved to {filename}.");

return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,20 @@ bool NeedsCodesign (string path)
{
var output = GetOutputPath (path);

return !File.Exists (output) || File.GetLastWriteTimeUtc (path) >= File.GetLastWriteTimeUtc (output);
if (!File.Exists (output)) {
Log.LogMessage ($"Signing {path} because {output} does not exist.");
return true;
}

var a = File.GetLastWriteTimeUtc (path);
var b = File.GetLastWriteTimeUtc (output);

if (a >= b) {
Log.LogMessage ($"Signing {path} because {output} is out-of-date ({a} vs {b}).");
return true;
}

return false;
}

public override bool Execute ()
Expand Down
3 changes: 3 additions & 0 deletions msbuild/Xamarin.iOS.Tasks.Core/Tasks/GetFilesTaskBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
Expand Down Expand Up @@ -67,6 +68,8 @@ public override bool Execute ()

Files = items.ToArray ();

Log.LogMessage ("GetFiles found: {0}", string.Join (", ", Files.Select ((v) => v.ItemSpec).ToArray ()));

return !Log.HasLoggedErrors;
}
}
Expand Down
Loading

0 comments on commit c870e38

Please sign in to comment.