diff --git a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CreateFrameworkList.cs b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CreateFrameworkList.cs deleted file mode 100644 index d654035edb4..00000000000 --- a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CreateFrameworkList.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Xml.Linq; - -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.Tools.BootstrapTasks -{ - public class CreateFrameworkList : Task - { - [Required] - public ITaskItem FrameworkListFile { get; set; } - - [Required] - public ITaskItem FrameworkDirectory { get; set; } - - [Required] - public ITaskItem[] FrameworkFiles { get; set; } - - public ITaskItem[] FrameworkFileOverrides { get; set; } - - [Required] - public string Redist { get; set; } - - [Required] - public string Name { get; set; } - - public override bool Execute() - { - var files = new List(FrameworkFiles); - files.Sort ((x, y) => { - var a = Path.GetFileNameWithoutExtension (x.ItemSpec); - var b = Path.GetFileNameWithoutExtension (y.ItemSpec); - return string.Compare (a, b, StringComparison.OrdinalIgnoreCase); - }); - var contents = new XElement ("FileList", - new XAttribute ("Redist", Redist), - new XAttribute ("Name", Name), - files.Select (f => ToFileElement (f))); - contents.Save (FrameworkListFile.ItemSpec); - return true; - } - - XElement ToFileElement (ITaskItem file) - { - var path = Path.Combine (FrameworkDirectory.ItemSpec, file.ItemSpec); - if (!File.Exists (path)) { - path = Path.Combine (FrameworkDirectory.ItemSpec, "Facades", file.ItemSpec); - } - - var assemblyName = AssemblyName.GetAssemblyName (path); - - var taskVersion = Nullable (file.GetMetadata ("Version")); - var overrideVersion = Nullable (FrameworkFileOverrides?.FirstOrDefault (o => o.ItemSpec == file.ItemSpec)?.GetMetadata ("Version")); - var assemblyVersion = assemblyName.Version.ToString (); - var version = taskVersion ?? overrideVersion ?? assemblyVersion; - - var publicKeyToken = string.Join ("", assemblyName.GetPublicKeyToken ().Select(b => b.ToString ("x2"))); - - return new XElement ("File", - new XAttribute ("AssemblyName", assemblyName.Name), - new XAttribute ("Version", version), - new XAttribute ("PublicKeyToken", publicKeyToken), - new XAttribute ("ProcessorArchitecture", "MSIL")); - } - - static string Nullable (string value) => string.IsNullOrEmpty (value) ? null : value; - } -} diff --git a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateMonoDroidIncludes.cs b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateMonoDroidIncludes.cs deleted file mode 100644 index bd8f01012be..00000000000 --- a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateMonoDroidIncludes.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.IO; -using System.Globalization; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.Tools.BootstrapTasks -{ - public class GenerateMonoDroidIncludes : Task - { - [Required] - public ITaskItem [] SourceFiles { get; set; } - - [Required] - public ITaskItem [] DestinationFiles { get; set; } - - public override bool Execute () - { - Log.LogMessage (MessageImportance.Low, $"Task {nameof (GenerateMonoDroidIncludes)}"); - - if (SourceFiles.Length != DestinationFiles.Length) { - Log.LogError ($"{nameof(SourceFiles)}.Length must equal {nameof(DestinationFiles)}.Length."); - return false; - } - - Log.LogMessage (MessageImportance.Low, $"\t{nameof(SourceFiles)} : "); - for (int i = 0; i < SourceFiles.Length; i++) { - var source = SourceFiles [i]; - var destination = DestinationFiles [i]; - Log.LogMessage (MessageImportance.Low, "\t\t{0} -> {1}", source.ItemSpec, destination.ItemSpec); - - var bytes = File.ReadAllBytes (source.ItemSpec); - - //Should be equivalent of "xxd -i %(_EmbeddedBlob.Config) | sed 's/^unsigned /static const unsigned /g' > jni/%(_EmbeddedBlob.Include)" - using (var fs = File.Create (destination.ItemSpec)) - using (var writer = new StreamWriter(fs)) { - var variableName = "monodroid_" + Path.GetFileNameWithoutExtension (source.ItemSpec).Replace ('.', '_'); - writer.Write ("static const unsigned char "); - writer.Write (variableName); - writer.Write ("[] = {"); - - for (int j = 0; j < bytes.Length; j++) { - if (j != 0) - writer.Write (","); - - //12 per line - if (j % 12 == 0) { - writer.WriteLine (); - writer.Write (" "); - } else { - writer.Write (" "); - } - - writer.Write ("0x"); - writer.Write (bytes [j].ToString ("x2", CultureInfo.InvariantCulture)); - } - - //Needs to be a null-terminating string and include a trailing \0 - writer.WriteLine (", 0x00"); - writer.WriteLine ("};"); - - //Length - writer.Write ("static const unsigned int "); - writer.Write (variableName); - writer.Write ("_len = "); - writer.Write (bytes.Length + 1); - writer.WriteLine (";"); - } - } - - return !Log.HasLoggedErrors; - } - } -} diff --git a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateProfile.cs b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateProfile.cs deleted file mode 100644 index d5c4b31693b..00000000000 --- a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateProfile.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.Tools.BootstrapTasks -{ - public class GenerateProfile : Task - { - [Required] - public ITaskItem[] Files { get; set; } - - [Required] - public ITaskItem OutputFile { get; set; } - - public override bool Execute () - { - Log.LogMessage (MessageImportance.Low, "Task GenerateProfile"); - Log.LogMessage (MessageImportance.Low, "\tOutputFile : {0}", OutputFile); - Log.LogMessage (MessageImportance.Low, "\tFiles : "); - foreach (var file in Files) { - Log.LogMessage (MessageImportance.Low, "\t\t{0}", file.ItemSpec); - } - - var sb = new StringBuilder (); - sb.AppendLine ("using System.Collections.Generic;"); - sb.AppendLine (); - sb.AppendLine ("namespace Xamarin.Android.Tasks {"); - sb.AppendLine ("\tpublic partial class Profile {"); - sb.AppendLine ("\t\t// KEEP THIS SORTED ALPHABETICALLY, CASE-INSENSITIVE"); - sb.AppendLine ("\t\tpublic static readonly string [] SharedRuntimeAssemblies = new []{"); - foreach (var file in Files.Select(x => Path.GetFileName (x.ItemSpec)).Distinct().OrderBy(x => x)) { - sb.AppendFormat ("\t\t\t\"{0}\"," + Environment.NewLine, file); - } - sb.AppendLine ("\t\t};"); - sb.AppendLine ("\t}"); - sb.AppendLine ("}"); - - var newContents = sb.ToString (); - var curContents = ""; - if (File.Exists (OutputFile.ItemSpec)) { - curContents = File.ReadAllText (OutputFile.ItemSpec); - } - if (newContents != curContents) { - File.WriteAllText (OutputFile.ItemSpec, sb.ToString ()); - } - - return !Log.HasLoggedErrors; - } - } -} - diff --git a/build-tools/scripts/XAVersionInfo.targets b/build-tools/scripts/XAVersionInfo.targets index e21107348e5..72083c497a4 100644 --- a/build-tools/scripts/XAVersionInfo.targets +++ b/build-tools/scripts/XAVersionInfo.targets @@ -10,7 +10,6 @@ - diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/AcceptAndroidSdkLicenses.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/AcceptAndroidSdkLicenses.cs deleted file mode 100644 index 467fe24310e..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/AcceptAndroidSdkLicenses.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public class AcceptAndroidSdkLicenses : Task - { - [Required] - public string AndroidSdkDirectory { get; set; } - - public string JavaSdkDirectory { get; set; } - - public override bool Execute () - { - Log.LogMessage (MessageImportance.Low, $"Task {nameof (AcceptAndroidSdkLicenses)}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (AndroidSdkDirectory)}: {AndroidSdkDirectory}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (JavaSdkDirectory)}: {JavaSdkDirectory}"); - - var licdir = Path.Combine (Path.Combine (AndroidSdkDirectory, "licenses")); - Directory.CreateDirectory (licdir); - - if (!string.IsNullOrEmpty (JavaSdkDirectory)) { - Environment.SetEnvironmentVariable ("JAVA_HOME", JavaSdkDirectory); - } - - string _; - var path = Which.GetProgramLocation ("sdkmanager", out _, new [] { Path.Combine (AndroidSdkDirectory, "tools", "bin") }); - var psi = new ProcessStartInfo (path, "--licenses") { UseShellExecute = false, RedirectStandardInput = true }; - var proc = Process.Start (psi); - for (int i = 0; i < 10; i++) - proc.StandardInput.WriteLine ('y'); - proc.WaitForExit (); - - return true; - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/CheckoutExternalGitDependency.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/CheckoutExternalGitDependency.cs deleted file mode 100644 index a7da2478199..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/CheckoutExternalGitDependency.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.IO; -using Microsoft.Build.Framework; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public class CheckoutExternalGitDependency : Git - { - [Required] - public ITaskItem ExternalGitDependency { get; set; } - - protected override bool LogTaskMessages { - get { return false; } - } - - string commit; - string owner; - string name; - string singleLine; - - public override bool Execute () - { - commit = ExternalGitDependency.ItemSpec; - owner = ExternalGitDependency.GetMetadata ("Owner"); - name = ExternalGitDependency.GetMetadata ("Name"); - string destination = Path.Combine (GetWorkingDirectory (), name); - - if (!Directory.Exists (destination)) { - Clone (destination); - } - - WorkingDirectory.ItemSpec = destination; - Fetch (); - CheckoutCommit (); - - return !Log.HasLoggedErrors; - } - - void Clone (string destination) - { - string ghToken = Environment.GetEnvironmentVariable("GH_AUTH_SECRET"); - if (!string.IsNullOrEmpty (ghToken)) { - Arguments = $"clone https://{ghToken}@github.com/{owner}/{name} --progress \"{destination}\""; - } else { - if (IsHttps ()) { - // Just use a plain git clone for https - Arguments = $"clone https://github.com/{owner}/{name} --progress \"{destination}\""; - } else { - // Fallback to SSH URI - Arguments = $"clone git@github.com:{owner}/{name} --progress \"{destination}\""; - } - } - - base.Execute (); - } - - void Fetch () - { - Arguments = $"fetch --all --no-recurse-submodules --progress"; - base.Execute (); - } - - void CheckoutCommit () - { - Arguments = $"checkout {commit} --force --progress"; - base.Execute (); - } - - bool IsHttps () - { - Arguments = "config --get remote.origin.url"; - base.Execute (); - return singleLine != null && singleLine.Contains ("https://"); - } - - protected override void LogToolCommand(string message) - { - // Do nothing - } - - protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance) - { - if (!string.IsNullOrEmpty (singleLine)) - this.singleLine = singleLine; - - base.LogEventsFromTextOutput (singleLine, messageImportance); - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/CreateFilePaths.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/CreateFilePaths.cs deleted file mode 100644 index 5f9637d1477..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/CreateFilePaths.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public class CreateFilePaths : Task - { - [Required] - public string[] SourceFileNames { get; set; } - - [Required] - public string[] SourceDirectories { get; set; } - - [Required] - public string[] DestinationDirectories { get; set; } - - [Output] - public ITaskItem[] FullSourceFilePaths { get; set; } - - [Output] - public ITaskItem[] FullDestinationFilePaths { get; set; } - - public override bool Execute () - { - if (SourceFileNames.Length != SourceDirectories.Length || SourceFileNames.Length != DestinationDirectories.Length) - Log.LogError ("Input paramters must be arrays of the same size"); - else - DoExecute (); - - return !Log.HasLoggedErrors; - } - - void DoExecute () - { - var sourcePaths = new List (); - var destinationPaths = new List (); - - for (int i = 0; i < SourceFileNames.Length; i++) { - string sourceFile = SourceFileNames [i].Trim (); - string sourceDir = SourceDirectories [i].Trim (); - string destDir = DestinationDirectories [i].Trim (); - bool canContinue = true; - - canContinue &= AssertNotEmpty (sourceFile, nameof (SourceFileNames), i); - canContinue &= AssertNotEmpty (sourceDir, nameof (SourceDirectories), i); - canContinue &= AssertNotEmpty (destDir, nameof (DestinationDirectories), i); - - if (!canContinue) - continue; - - string[] parts = sourceFile.Split (':'); - if (parts.Length > 2) { - Log.LogError ($"Too many colons in {sourceFile} (SourceFileNames[{i}]), the format is 'file[:dest/file]'"); - continue; - } - - sourcePaths.Add (new TaskItem (Path.Combine (sourceDir, parts [0]))); - destinationPaths.Add (new TaskItem (Path.Combine (destDir, parts.Length == 1 ? parts [0] : parts [1]))); - } - - FullSourceFilePaths = sourcePaths.ToArray (); - FullDestinationFilePaths = destinationPaths.ToArray (); - - bool AssertNotEmpty (string s, string name, int i) - { - if (String.IsNullOrEmpty (s)) { - Log.LogError ($"Element {i} of input array {name} must not be an empty/whitespace-only string"); - return false; - } - - return true; - } - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitCommitTime.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitCommitTime.cs deleted file mode 100644 index bc2e7bc69cf..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitCommitTime.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -using Microsoft.Build.Framework; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public sealed class GitCommitTime : Git - { - [Output] - public string Time { get; set; } - - protected override bool LogTaskMessages { - get { return false; } - } - - public GitCommitTime () - { - } - - public override bool Execute () - { - Log.LogMessage (MessageImportance.Low, $"Task {nameof (GitCommitTime)}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (WorkingDirectory)}: {WorkingDirectory.ItemSpec}"); - - base.Execute (); - - Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (Time)}: {Time}"); - - return !Log.HasLoggedErrors; - } - - protected override string GenerateCommandLineCommands () - { - //NOTE: this command needs to return a string that is valid to pass to DateTime.Parse() - // The MSBuild task requires this: https://docs.microsoft.com/en-us/visualstudio/msbuild/touch-task - return "log -1 --format=%cd --date=format-local:\"%Y/%m/%d %H:%M:%S\""; - } - - protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance) - { - if (string.IsNullOrEmpty (singleLine)) - return; - Time = singleLine; - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitDiff.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitDiff.cs deleted file mode 100644 index a59a540d67c..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitDiff.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; - -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -using IOFile = System.IO.File; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public sealed class GitDiff : Git - { - protected override bool LogTaskMessages { - get { return false; } - } - - protected override bool PreserveOutput { - get { return false; } - } - - protected override string GenerateCommandLineCommands () - { - return "diff " + Arguments; - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/HashFileContents.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/HashFileContents.cs deleted file mode 100644 index 5cefc7e7518..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/HashFileContents.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; - -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public class HashFileContents : Task - { - [Required] - public ITaskItem[] Files { get; set; } - - - public string HashAlgorithm { get; set; } = "SHA1"; - - public int AbbreviatedHashLength { get; set; } = 8; - - [Output] - // Specifies %(Hashes.Target), %(Hashes.AbbreviatedHash). Hash is %(Hashes.Identity)). - public ITaskItem[] Hashes { get; set; } - - [Output] - public string CompleteHash { get; set; } - - [Output] - public string AbbreviatedCompleteHash { get; set; } - - public override bool Execute () - { - Log.LogMessage (MessageImportance.Low, $"Task {nameof (HashFileContents)}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (AbbreviatedHashLength)}: {AbbreviatedHashLength}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (HashAlgorithm)}: {HashAlgorithm}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (Files)}:"); - foreach (var e in Files) { - Log.LogMessage (MessageImportance.Low, $" {e.ItemSpec}"); - } - - ProcessFiles (); - - Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (AbbreviatedCompleteHash)}: {AbbreviatedCompleteHash}"); - Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (CompleteHash)}: {CompleteHash}"); - Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (Hashes)}:"); - foreach (var e in Hashes) { - Log.LogMessage (MessageImportance.Low, $" {e.GetMetadata ("Target")}: {e.ItemSpec}:"); - } - return !Log.HasLoggedErrors; - } - - void ProcessFiles () - { - var hashes = new List (Files.Length); - byte[] block = new byte [4096]; - using (var complete = CreateHashAlgorithm (HashAlgorithm)) { - foreach (var file in Files) { - var hash = ProcessFile (complete, block, file.ItemSpec); - var e = new TaskItem (hash); - e.SetMetadata ("Target", Path.GetFullPath (file.ItemSpec)); - e.SetMetadata ("AbbreviatedHash", hash.Substring (0, AbbreviatedHashLength)); - hashes.Add (e); - } - complete.TransformFinalBlock (block, 0, 0); - CompleteHash = FormatHash (complete.Hash); - AbbreviatedCompleteHash = CompleteHash.Substring (0, AbbreviatedHashLength); - } - Hashes = hashes.ToArray (); - } - - string ProcessFile (HashAlgorithm complete, byte[] block, string path) - { - using (var memoryStream = new MemoryStream ()) { - - //Read the file into a MemoryStream, ignoring newlines - using (var file = File.OpenRead (path)) { - int readByte; - while ((readByte = file.ReadByte()) != -1) { - byte b = (byte)readByte; - if (b != '\r' && b != '\n') { - memoryStream.WriteByte (b); - } - } - } - memoryStream.Seek (0, SeekOrigin.Begin); - - using (var fileHash = CreateHashAlgorithm (HashAlgorithm)) { - int read; - while ((read = memoryStream.Read (block, 0, block.Length)) > 0) { - complete.TransformBlock (block, 0, read, block, 0); - fileHash.TransformBlock (block, 0, read, block, 0); - } - fileHash.TransformFinalBlock (block, 0, 0); - return FormatHash (fileHash.Hash); - } - } - } - - string FormatHash (byte[] hash) - { - return string.Join ("", hash.Select (b => b.ToString ("x2"))); - } - - #pragma warning disable CA5350 // used for content hashing, not security - static System.Security.Cryptography.HashAlgorithm CreateHashAlgorithm (string name) => - name.ToUpperInvariant () switch { - "SHA1" => SHA1.Create (), - "SHA256" => SHA256.Create (), - "SHA384" => SHA384.Create (), - "SHA512" => SHA512.Create (), - _ => throw new NotSupportedException ($"Hash algorithm '{name}' is not supported."), - }; - #pragma warning restore CA5350 - } -} - diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/NDKInfo.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/NDKInfo.cs deleted file mode 100644 index b7f1aee7246..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/NDKInfo.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.IO; -using System.Text; - -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public class NDKInfo : Task - { - [Required] - public string NDKDirectory { get; set; } - - [Output] - public string NDKRevision { get; set; } - - [Output] - public string NDKVersionMajor { get; set; } - - [Output] - public string NDKVersionMinor { get; set; } - - [Output] - public string NDKVersionMicro { get; set; } - - [Output] - public string NDKMinimumApiAvailable { get; set; } - - public override bool Execute () - { - string props = Path.Combine (NDKDirectory, "source.properties"); - - if (!File.Exists (props)) - Log.LogError ($"NDK version file not found at {props}"); - else - GatherInfo (props); - - return !Log.HasLoggedErrors; - } - - void GatherInfo (string props) - { - string[] lines = File.ReadAllLines (props); - - foreach (string l in lines) { - string line = l.Trim (); - string[] parts = line.Split (new char[] {'='}, 2); - if (parts.Length != 2) - continue; - - if (String.Compare ("Pkg.Revision", parts [0].Trim (), StringComparison.Ordinal) != 0) - continue; - - string rev = parts [1].Trim (); - NDKRevision = rev; - - Version ver; - if (!Version.TryParse (rev, out ver)) { - Log.LogError ($"Unable to parse NDK revision '{rev}' as a valid version string"); - return; - } - - NDKVersionMajor = ver.Major.ToString (); - NDKVersionMinor = ver.Minor.ToString (); - NDKVersionMicro = ver.Build.ToString (); - break; - } - - int minimumApi = Int32.MaxValue; - string platforms = Path.Combine (NDKDirectory, "platforms"); - foreach (string p in Directory.EnumerateDirectories (platforms, "android-*", SearchOption.TopDirectoryOnly)) { - string pdir = Path.GetFileName (p); - string[] parts = pdir.Split (new char[] { '-' }, 2); - if (parts.Length != 2) - continue; - - int api; - if (!Int32.TryParse (parts [1].Trim (), out api)) - continue; - - if (api >= minimumApi) - continue; - - minimumApi = api; - } - - NDKMinimumApiAvailable = minimumApi.ToString (); - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/ParseExternalGitDependencies.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/ParseExternalGitDependencies.cs deleted file mode 100644 index 71a89b40252..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/ParseExternalGitDependencies.cs +++ /dev/null @@ -1,70 +0,0 @@ - -using System.Collections.Generic; -using System.IO; -using System.Text.RegularExpressions; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public class ParseExternalGitDependencies : Task - { - [Required] - public string ExternalFilePath { get; set; } - - /* %(ExternalGitDependencies.Owner) - Repo owner - * %(ExternalGitDependencies.Name) - Repo name - * %(ExternalGitDependencies.Branch) - Branch name - * %(ExternalGitDependencies.Identity) - Commit hash - */ - [Output] - public ITaskItem[] ExternalGitDependencies { get; set; } - - static readonly Regex externalRegex = new Regex (@" -^ -\s* -(?\#.*) -| -( - \s* - (?[^/]+) - / - (?[^:]+) - : - (?[^@]+) - @ - (?.*) -) -$ -", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); - - public override bool Execute () - { - if (!File.Exists (ExternalFilePath)) { - Log.LogError($"Unable to find dependency file at: {ExternalFilePath}"); - return false; - } - - string[] unparsedExternals = File.ReadAllLines (ExternalFilePath); - var externals = new List (unparsedExternals.Length); - - foreach (string external in unparsedExternals) { - Match match = externalRegex.Match (external); - if (match != null && match.Success) { - if (match.Groups["comment"].Success) { - // Ignore matching lines which start with '#'. - continue; - } - var e = new TaskItem (match.Groups["commit"].Value); - e.SetMetadata ("Owner", match.Groups["owner"].Value); - e.SetMetadata ("Name", match.Groups["repo"].Value); - e.SetMetadata ("Branch", match.Groups["branch"].Value); - externals.Add (e); - } - } - - ExternalGitDependencies = externals.ToArray (); - return !Log.HasLoggedErrors; - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/PrepareInstall.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/PrepareInstall.cs deleted file mode 100644 index 04a456866f3..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/PrepareInstall.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public class PrepareInstall : Task - { - [Required] - public ITaskItem Program { get; set; } - - public bool UseSudo { get; set; } - public string HostOS { get; set; } - public string HostOSName { get; set; } - - [Output] - public string InstallCommand { get; set; } - - [Output] - public ITaskItem DownloadUrl { get; set; } - - string Sudo; - string SudoBrew; - - public override bool Execute () - { - Log.LogMessage (MessageImportance.Low, $"Task {nameof (PrepareInstall)}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (HostOS)}: {HostOS}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (HostOSName)}: {HostOSName}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (Program)}: {Program}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (UseSudo)}: {UseSudo}"); - - SetSudo (); - SetDownloadUrl (); - SetInstallCommand (); - - Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (DownloadUrl)}: {DownloadUrl} [Url: {DownloadUrl?.GetMetadata ("Url")}]"); - Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (InstallCommand)}: {InstallCommand}"); - - return !Log.HasLoggedErrors; - } - - string GetHostProperty (string property) - { - return Which.GetHostProperty (Program, property, HostOS, HostOSName); - } - - void SetSudo () - { - if (!UseSudo || string.Equals ("Windows", HostOS, StringComparison.OrdinalIgnoreCase)) - return; - - Sudo = "sudo "; - - if (!string.Equals ("Darwin", HostOS, StringComparison.OrdinalIgnoreCase)) { - return; - } - string brewFilename; - var brewPath = Which.GetProgramLocation ("brew", out brewFilename); - if (string.IsNullOrEmpty (brewPath)) { - return; - } - var brewVersion = Which.GetProgramVersion (HostOS, $"{brewPath} --version"); - if (brewVersion < new Version (1, 1)) { - SudoBrew = "sudo "; - return; - } - } - - void SetDownloadUrl () - { - var minUrl = GetHostProperty ("MinimumUrl"); - if (string.IsNullOrEmpty (minUrl)) - return; - - DownloadUrl = new TaskItem (GetFilenameFromUrl (minUrl)); - DownloadUrl.SetMetadata ("Url", minUrl); - } - - string GetFilenameFromUrl (string url) - { - var u = new Uri (url); - var p = u.AbsolutePath; - var s = p.LastIndexOf ('/'); - if (s >= 0 && p.Length > (s+1)) { - return p.Substring (s+1); - } - return Program.ItemSpec + ".bin"; - } - - void SetInstallCommand () - { - var install = GetHostProperty ("Install"); - if (install != null) { - InstallCommand = Sudo + install; - return; - } - if (string.Equals (HostOS, "Darwin", StringComparison.OrdinalIgnoreCase)) { - string tap = Program.GetMetadata ("HomebrewTap"); - if (!string.IsNullOrEmpty (tap)) { - tap = $"{SudoBrew}brew tap '{tap}';"; - } - - var brew = Program.GetMetadata ("Homebrew"); - if (!string.IsNullOrEmpty (brew)) { - InstallCommand = $"{tap}{SudoBrew}brew install '{brew}'"; - } - return; - } - // TODO: other platforms - var min = Program.GetMetadata ("MinimumVersion"); - var ver = ""; - if (!string.IsNullOrEmpty (min)) { - ver = $", version >= {min}"; - var max = Program.GetMetadata ("MaximumVersion"); - if (!string.IsNullOrEmpty (max)) { - ver += $" and <= {max}"; - } - } - Log.LogError ($"Missing dependency detected. For {HostOS} we do not know how to install program `{Program.ItemSpec}`{ver}."); - } - } -} - diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/RunParallelTargets.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/RunParallelTargets.cs deleted file mode 100644 index 8b496cfff76..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/RunParallelTargets.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; - -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Xamarin.Android.BuildTools.PrepTasks.Xamarin.Android.BuildTools.PrepTasks -{ - public class RunParallelTargets : Task - { - [Required] - public ITaskItem ProjectFile {get; set;} - - public string Configuration {get; set;} - - public string MSBuildBinPath {get; set;} - - public string MSBuildBinaryLogParameterPrefix {get; set;} - - public ITaskItem[] Targets {get; set;} - - public override bool Execute () - { - if (Targets?.Length == 0) - return true; - - var processes = new Process [Targets.Length]; - for (int i = 0; i < Targets.Length; ++i) { - processes[i] = CreateProcess (Targets[i].ItemSpec); - } - - bool success = true; - for (int i = 0; i < processes.Length; ++i) { - processes[i].WaitForExit (); - if (processes[i].ExitCode != 0) { - Log.LogError ($"Execution of target {Targets [i].ItemSpec} exited with code {processes [i].ExitCode}."); - success = false; - } - } - return success; - } - - Process CreateProcess (string target) - { - var binlogOption = ""; - if (!string.IsNullOrEmpty (MSBuildBinaryLogParameterPrefix)) { - var date = DateTime.Now.ToString ("yyyyMMddTHHmmss"); - // -$([System.DateTime]::Now.ToString ("yyyyMMddTHHmmss"))-Target-%(Identity).binlog - binlogOption = $"{MSBuildBinaryLogParameterPrefix}-{date}-Target-{target}.binlog\""; - } - var config = string.IsNullOrEmpty (Configuration) ? "" : $"/p:Configuration={Configuration}"; - var command = $"{config} \"{ProjectFile.ItemSpec}\" {binlogOption} /t:{target}"; - var msbuild = (string.IsNullOrEmpty (MSBuildBinPath) || Path.DirectorySeparatorChar == '/') - ? "msbuild" - : Path.Combine (MSBuildBinPath, "msbuild"); - var parameters = new ProcessStartInfo (msbuild, command) { - CreateNoWindow = true, - UseShellExecute = false, - WindowStyle = ProcessWindowStyle.Hidden, - }; - var process = Process.Start (parameters); - return process; - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/SetEnvironmentVariable.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/SetEnvironmentVariable.cs deleted file mode 100644 index e46cd9f3d92..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/SetEnvironmentVariable.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -using System; - -namespace Xamarin.Android.BuildTools.PrepTasks -{ - public class SetEnvironmentVariable : Task - { - [Required] - public string Name { get; set; } - - [Required] - public string Value { get; set; } - - public override bool Execute () - { - Log.LogMessage (MessageImportance.Low, $"Task {nameof (SetEnvironmentVariable)}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (Name)}: {Name}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (Value)}: {Value}"); - - Environment.SetEnvironmentVariable(Name, Value); - - return !Log.HasLoggedErrors; - } - } -} diff --git a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/SystemUnzip.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/SystemUnzip.cs deleted file mode 100644 index 3a661ec9117..00000000000 --- a/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/SystemUnzip.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -using TTask = System.Threading.Tasks.Task; -using MTask = Microsoft.Build.Utilities.Task; - -namespace Xamarin.Android.BuildTools.PrepTasks { - - public class SystemUnzip : MTask - { - [Required] - public ITaskItem[] SourceFiles { get; set; } - - public string SourceEntryGlob { get; set; } - - public string EntryNameEncoding { get; set; } - - public string HostOS { get; set; } - - public string TempUnzipDir { get; set; } - - [Required] - public ITaskItem DestinationFolder { get; set; } - - string[] SourceEntryGlobParts; - - public override bool Execute () - { - Log.LogMessage (MessageImportance.Low, $"{nameof (SystemUnzip)}:"); - Log.LogMessage (MessageImportance.Low, $" {nameof (DestinationFolder)}: {DestinationFolder.ItemSpec}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (EntryNameEncoding)}: {EntryNameEncoding}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (HostOS)}: {HostOS}"); - - Log.LogMessage (MessageImportance.Low, $" {nameof (SourceEntryGlob)}: {SourceEntryGlob}"); - Log.LogMessage (MessageImportance.Low, $" {nameof (SourceFiles)}:"); - for (int i = 0; i < SourceFiles.Length; ++i) { - var sf = SourceFiles [i].ItemSpec; - var rp = SourceFiles [i].GetMetadata ("DestDir"); - rp = string.IsNullOrEmpty (rp) - ? "" - : " [ " + rp + " ]"; - Log.LogMessage (MessageImportance.Low, " {0}{1}", sf, rp); - } - - if (File.Exists (DestinationFolder.ItemSpec)) { - Log.LogError ($"{nameof (DestinationFolder)} must be a directory!"); - return false; - } - - SourceEntryGlobParts = (SourceEntryGlob ?? "*").Split ('/', '\\'); - - Directory.CreateDirectory (DestinationFolder.ItemSpec); - - var tempDir = TempUnzipDir ?? Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ()); - Directory.CreateDirectory (tempDir); - Log.LogMessage (MessageImportance.Low, $" Extracting into temporary directory: {tempDir}"); - - var encoding = string.IsNullOrEmpty (EntryNameEncoding) - ? null - : Encoding.GetEncoding (EntryNameEncoding); - - var tasks = new TTask [SourceFiles.Length]; - for (int i = 0; i < SourceFiles.Length; ++i) { - var td = tempDir; - var sourceFile = SourceFiles [i].ItemSpec; - var relativeDestDir = SourceFiles [i].GetMetadata ("DestDir"); - var enc = encoding; - var destFolder = DestinationFolder.ItemSpec; - tasks [i] = TTask.Run (() => ExtractFile (td, sourceFile, relativeDestDir, destFolder, enc)); - } - - TTask.WaitAll (tasks); - - Directory.Delete (tempDir, recursive: true); - - return !Log.HasLoggedErrors; - } - - // Ignore CS1998 because there's no async System.IO APIs to use here. - // Instead, we're using Tasks so that we can extract multiple files - // in parallel via Task.Run() and Task.WaitAll(). -#pragma warning disable 1998 - async TTask ExtractFile (string tempDir, string sourceFile, string relativeDestDir, string destinationFolder, Encoding encoding) - { - var tempName = Path.GetRandomFileName (); - var nestedTemp = Path.Combine (tempDir, tempName); - Directory.CreateDirectory (nestedTemp); - - relativeDestDir = relativeDestDir?.Replace ('\\', Path.DirectorySeparatorChar); - - bool isWindows = string.Equals (HostOS, "Windows", StringComparison.OrdinalIgnoreCase); - if (isWindows) { - ZipFile.ExtractToDirectory (sourceFile, nestedTemp, encoding); - } else { - var start = new ProcessStartInfo ("unzip", $"\"{sourceFile}\" -d \"{nestedTemp}\"") { - CreateNoWindow = true, - UseShellExecute = false, - }; - Log.LogMessage (MessageImportance.Low, $"unzip \"{sourceFile}\" -d \"{nestedTemp}\""); - var p = Process.Start (start); - p.WaitForExit (); - } - - var entries = GetExtractedSourceDirectories (nestedTemp); - - var seenDestFiles = new HashSet (); - - // "merge" directories from `name`/within `sourceFile` and `destinationFolder`. - // If we did e.g. `mv foo/lib destination/lib` *and* `destination/lib` *already exists*, - // we'd create `destination/lib/lib`, which isn't intended. - // If we did e.g. `mv foo/lib destination`, **mv**(1) may *overwrite* `destination/lib` - // if it already exists, which *also* isn't intended. - // If `destination/lib/example` and `sourceFile` contains a `lib/another` entry, - // then we want to create a `destination/lib/another` file. - foreach (var entry in entries) { - var name = Path.GetFileName (entry); - var destDir = string.IsNullOrEmpty (relativeDestDir) - ? destinationFolder - : Path.Combine (destinationFolder, relativeDestDir); - destDir = Path.Combine (destDir, name); - foreach (var file in Directory.EnumerateFiles (entry, "*", SearchOption.AllDirectories)) { - var relPath = file.Substring (entry.Length + 1); - var dest = Path.Combine (destDir, relPath); - seenDestFiles.Add (dest); - var destMdb = dest + ".mdb"; - if (File.Exists (destMdb) && !seenDestFiles.Contains (destMdb)) { - Log.LogMessage (MessageImportance.Low, $"rm \"{destMdb}\""); - File.Delete (destMdb); - } - var destPdb = Path.ChangeExtension (dest, ".pdb"); - if (File.Exists (destPdb) && !seenDestFiles.Contains (destPdb)) { - Log.LogMessage (MessageImportance.Low, $"rm \"{destPdb}\""); - File.Delete (destPdb); - } - Directory.CreateDirectory (Path.GetDirectoryName (dest)); - Log.LogMessage (MessageImportance.Low, $"mv '{file}' '{dest}'"); - if (Directory.Exists (entry)) { - ProcessStartInfo psi; - if (isWindows) { - psi = new ProcessStartInfo ("cmd", $@"/C move ""{file}"" ""{dest}""") { - CreateNoWindow = true, - UseShellExecute = false, - }; - } else { - psi = new ProcessStartInfo ("/bin/mv", $@"""{file}"" ""{dest}"""); - } - using (var p = Process.Start (psi)) { - p.WaitForExit (); - } - } - else { - if (File.Exists (dest)) - File.Delete (dest); - File.Move (file, dest); - } - // Don't attempt to set write/access time on linked files. - var destFileInfo = new FileInfo (dest); - if (!destFileInfo.Attributes.HasFlag (FileAttributes.ReparsePoint)) { - File.SetLastWriteTimeUtc (dest, DateTime.UtcNow); - } - } - } - } - - IEnumerable GetExtractedSourceDirectories (string root) - { - var entries = Directory.EnumerateDirectories (root, SourceEntryGlobParts [0], SearchOption.TopDirectoryOnly); - for (int i = 1; i < SourceEntryGlobParts.Length; ++i) { - entries = entries - .SelectMany (e => Directory.EnumerateDirectories (e, SourceEntryGlobParts [i], SearchOption.TopDirectoryOnly)); - } - return entries; - } -#pragma warning restore 1998 - } -} - diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index c454e15162d..abf151ec204 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -249,7 +249,7 @@ False diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets index 34f67926f65..55879da55c6 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets @@ -1,6 +1,5 @@ -