diff --git a/Makefile b/Makefile index 5a7d72d6bfb..5cdc92fb48e 100644 --- a/Makefile +++ b/Makefile @@ -29,11 +29,14 @@ all-tests:: prepare:: prepare-external prepare-props +# $(call GetPath,path) +GetPath = $(shell $(MSBUILD) $(MSBUILD_FLAGS) /p:DoNotLoadOSProperties=True /nologo /v:minimal /t:Get$(1)FullPath build-tools/scripts/Paths.targets | tr -d '[[:space:]]' ) + prepare-external: git submodule update --init --recursive nuget restore $(SOLUTION) nuget restore Xamarin.Android-Tests.sln - (cd `$(MSBUILD) $(MSBUILD_FLAGS) /p:DoNotLoadOSProperties=True /nologo /v:minimal /t:GetJavaInteropFullPath build-tools/scripts/Paths.targets` && nuget restore) + (cd $(call GetPath,JavaInterop) && nuget restore) prepare-props: cp Configuration.Java.Interop.Override.props external/Java.Interop/Configuration.Override.props diff --git a/README.md b/README.md index 31a9f793da0..1f7592d8619 100644 --- a/README.md +++ b/README.md @@ -292,8 +292,14 @@ within `build-tools/mono-runtimes/obj/$(Configuration)/TARGET`. If you change sources within `external/mono`, a top-level `make`/`xbuild` invocation may not rebuild those mono native binaries. To explicitly rebuild -Mono for a given target, run `make` from the relevant directory. -For example, to rebuild Mono for armeabi-v7a: +*all* Mono runtimes, use the `ForceBuild` target: + + # Build and install all runtimes + $ xbuild /t:ForceBuild build-tools/mono-runtimes/mono-runtimes.mdproj + +To build Mono for a specific target, run `make` from the relevant directory +and invoke the `_InstallRuntimes` target. For example, to rebuild +Mono for armeabi-v7a: $ cd build-tools/mono-runtimes $ make -C obj/Debug/armeabi-v7a diff --git a/Xamarin.Android.sln b/Xamarin.Android.sln index 2a68f802337..03bb4f780aa 100644 --- a/Xamarin.Android.sln +++ b/Xamarin.Android.sln @@ -89,6 +89,8 @@ Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "libzip-windows", "build-too EndProject Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "bundle", "build-tools\bundle\bundle.mdproj", "{1640725C-4DB8-4D8D-BC96-74E688A06EEF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xa-prep-tasks", "build-tools\xa-prep-tasks\xa-prep-tasks.csproj", "{7CE69551-BD73-4726-ACAA-AAF89C84BAF8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|AnyCPU = Debug|AnyCPU @@ -407,6 +409,14 @@ Global {1640725C-4DB8-4D8D-BC96-74E688A06EEF}.XAIntegrationDebug|AnyCPU.Build.0 = Debug|Any CPU {1640725C-4DB8-4D8D-BC96-74E688A06EEF}.XAIntegrationRelease|AnyCPU.ActiveCfg = Release|Any CPU {1640725C-4DB8-4D8D-BC96-74E688A06EEF}.XAIntegrationRelease|AnyCPU.Build.0 = Release|Any CPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.Release|AnyCPU.Build.0 = Release|Any CPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.XAIntegrationDebug|AnyCPU.ActiveCfg = Debug|Any CPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.XAIntegrationDebug|AnyCPU.Build.0 = Debug|Any CPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.XAIntegrationRelease|AnyCPU.ActiveCfg = Debug|Any CPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.XAIntegrationRelease|AnyCPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} @@ -449,6 +459,7 @@ Global {C9FF2E4D-D927-479E-838B-647C16763F64} = {04E3E11E-B47D-4599-8AFC-50515A95E715} {0DE278D6-000F-4001-BB98-187C0AF58A61} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} {1640725C-4DB8-4D8D-BC96-74E688A06EEF} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 diff --git a/build-tools/android-toolchain/android-toolchain.mdproj b/build-tools/android-toolchain/android-toolchain.mdproj index f904c1a1304..b2742045076 100644 --- a/build-tools/android-toolchain/android-toolchain.mdproj +++ b/build-tools/android-toolchain/android-toolchain.mdproj @@ -26,12 +26,15 @@ + + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8} + xa-prep-tasks + False + {E8492EFB-D14A-4F32-AA28-88848322ECEA} Xamarin.Android.Tools.BootstrapTasks False - Content - PreserveNewest diff --git a/build-tools/android-toolchain/android-toolchain.targets b/build-tools/android-toolchain/android-toolchain.targets index 94cc1e91e98..aed831bd247 100644 --- a/build-tools/android-toolchain/android-toolchain.targets +++ b/build-tools/android-toolchain/android-toolchain.targets @@ -10,10 +10,8 @@ Properties="OutputPath=$(AndroidToolchainDirectory)" /> - - - - + + + + + + + + + + + + + + + + + + bundle-v2-$(Configuration)-$(HostOS)-libzip=$(_LibZipHash),llvm=$(_LlvmHash),mono=$(_MonoHash).zip + + + diff --git a/build-tools/bundle/bundle.mdproj b/build-tools/bundle/bundle.mdproj index eea19bb4499..18118232e81 100644 --- a/build-tools/bundle/bundle.mdproj +++ b/build-tools/bundle/bundle.mdproj @@ -22,6 +22,11 @@ + + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8} + xa-prep-tasks + False + {8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA} android-toolchain diff --git a/build-tools/bundle/bundle.targets b/build-tools/bundle/bundle.targets index 66cd997ebe5..be80ae5297f 100644 --- a/build-tools/bundle/bundle.targets +++ b/build-tools/bundle/bundle.targets @@ -1,78 +1,30 @@ - - + - - - - - - - - - - - - - - <_BundlePath>$(OutputPath)bundle-v2-$(Configuration)-$(HostOS)-libzip=$(_LibZipHash),llvm=$(_LlvmHash),mono=$(_MonoHash).zip - - + + - + DependsOnTargets="GetBundleFileName"> + - - <_Archive Include="@(_BclInstalledItem)" /> - <_Archive Include="$(OutputPath)lib\xbuild-frameworks\MonoAndroid\v1.0\Facades\*.dll*" /> - <_Archive Include="$(OutputPath)lib\xbuild-frameworks\MonoAndroid\v1.0\RedistList\FrameworkList.xml" /> - <_Archive Include="@(_InstallRuntimeOutput)" /> - <_Archive Include="@(_InstallUnstrippedRuntimeOutput)" /> - <_Archive Include="@(_InstallProfilerOutput)" /> - <_Archive Include="@(_InstallUnstrippedProfilerOutput)" /> - <_Archive Include="@(_InstallMonoPosixHelperOutput)" /> - <_Archive Include="@(_InstallUnstrippedMonoPosixHelperOutput)" /> - <_Archive Include="@(_RuntimeEglibHeaderOutput)" /> - <_Archive Include="@(_LibZipTarget->'$(OutputPath)lib\xbuild\Xamarin\Android\%(OutputLibrary)')" /> - <_Archive Include="@(_MonoConstsOutput)" /> - <_Archive Include="$(OutputPath)%(_MonoCrossRuntime.InstallPath)%(_MonoCrossRuntime.CrossMonoName)%(_MonoCrossRuntime.ExeSuffix)" - Condition=" '@(_MonoCrossRuntime)' != '' " - /> - <_Archive Include="@(_LlvmRuntime->'$(OutputPath)bin\llc%(ExeSuffix)')" - Condition=" '%(_LlvmRuntime.InstallBinaries)' == 'true' " - /> - <_Archive Include="@(_LlvmRuntime->'$(OutputPath)bin\opt%(ExeSuffix)')" - Condition=" '%(_LlvmRuntime.InstallBinaries)' == 'true' " - /> - + DependsOnTargets="GetMonoBundleItems;GetLibZipBundleItems"> + DependsOnTargets="GetBundleFileName;_GetArchiveItems" + Inputs="@(BundleItem)" + Outputs="$(OutputPath)$(XABundleFileName)"> diff --git a/build-tools/libzip-windows/libzip-windows.mdproj b/build-tools/libzip-windows/libzip-windows.mdproj index 004197132bb..8dec3429fa9 100644 --- a/build-tools/libzip-windows/libzip-windows.mdproj +++ b/build-tools/libzip-windows/libzip-windows.mdproj @@ -17,8 +17,7 @@ ResolveReferences; - _Configure; - _Make + _BuildUnlessCached diff --git a/build-tools/libzip/libzip.mdproj b/build-tools/libzip/libzip.mdproj index 91559fcd315..3c3286ba68a 100644 --- a/build-tools/libzip/libzip.mdproj +++ b/build-tools/libzip/libzip.mdproj @@ -17,13 +17,19 @@ ResolveReferences; - _Configure; - _Make + _BuildUnlessCached + + + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8} + xa-prep-tasks + False + + diff --git a/build-tools/libzip/libzip.projitems b/build-tools/libzip/libzip.projitems index 8dbfec42784..161b68e3ad6 100644 --- a/build-tools/libzip/libzip.projitems +++ b/build-tools/libzip/libzip.projitems @@ -14,4 +14,8 @@ libzip.so + + + + diff --git a/build-tools/libzip/libzip.targets b/build-tools/libzip/libzip.targets index 9410290413a..7fc900769a2 100644 --- a/build-tools/libzip/libzip.targets +++ b/build-tools/libzip/libzip.targets @@ -1,19 +1,14 @@ - - - - - - - - - - - - - - + + + + _SetCMakeListsTxtTimeToLastCommitTimestamp; + CheckForRequiredPrograms; + _Configure; + _Make + + - - + + + + + + + + + + diff --git a/build-tools/mono-runtimes/mono-runtimes.mdproj b/build-tools/mono-runtimes/mono-runtimes.mdproj index 769a2e8c47a..8d088d3e61d 100644 --- a/build-tools/mono-runtimes/mono-runtimes.mdproj +++ b/build-tools/mono-runtimes/mono-runtimes.mdproj @@ -6,30 +6,13 @@ GenericProject {C03E6CF1-7460-4CDC-A4AB-292BBC0F61F2} - - ..\..\bin\Debug - - - ..\..\bin\Release - - - - - ResolveReferences; - _BuildLlvm; - _InstallLlvm; - _Autogen; - _ConfigureRuntimes; - _BuildRuntimes; - _InstallRuntimes; - _InstallBcl; - _ConfigureCrossRuntimes; - _BuildCrossRuntimes; - _InstallCrossRuntimes; - - + + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8} + xa-prep-tasks + False + {8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA} android-toolchain diff --git a/build-tools/mono-runtimes/mono-runtimes.targets b/build-tools/mono-runtimes/mono-runtimes.targets index d2ac1af851d..afca8c016ec 100644 --- a/build-tools/mono-runtimes/mono-runtimes.targets +++ b/build-tools/mono-runtimes/mono-runtimes.targets @@ -1,5 +1,19 @@ + + ..\..\bin\Debug + + + ..\..\bin\Release + + + + + ResolveReferences; + _BuildUnlessCached + + + <_SourceTopDir>..\.. <_BclFrameworkDir>$(OutputPath)\lib\xbuild-frameworks\MonoAndroid\v1.0 @@ -9,6 +23,20 @@ <_MonoProfileDir>$(MonoSourceFullPath)\mcs\class\lib\monodroid + + + _BuildLlvm; + _InstallLlvm; + _Autogen; + _ConfigureRuntimes; + _BuildRuntimes; + _InstallRuntimes; + _InstallBcl; + _ConfigureCrossRuntimes; + _BuildCrossRuntimes; + _InstallCrossRuntimes; + + @@ -71,8 +99,11 @@ Command="touch -m -t `git log -1 --format=%25cd --date=format-local:%25Y%25m%25d%25H%25M.%25S` autogen.sh" WorkingDirectory="$(MonoSourceFullPath)" /> + - <_LlvmSourceFile Include="$(LlvmSourceFullPath)\lib\**\*.cpp" /> @@ -406,6 +437,41 @@ Files="$(OutputPath)%(_MonoCrossRuntime.InstallPath)%(_MonoCrossRuntime.CrossMonoName)%(_MonoCrossRuntime.ExeSuffix)" /> + + + + + + + + + + + + + + + + + + + + + + diff --git a/build-tools/scripts/Paths.targets b/build-tools/scripts/Paths.targets index c0c88bf4e39..e85354f4610 100644 --- a/build-tools/scripts/Paths.targets +++ b/build-tools/scripts/Paths.targets @@ -19,6 +19,18 @@ Importance="High" /> + + + + + + - + diff --git a/build-tools/xa-prep-tasks/Properties/AssemblyInfo.cs b/build-tools/xa-prep-tasks/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..96312264b62 --- /dev/null +++ b/build-tools/xa-prep-tasks/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("xapreptasks")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("Microsoft Corporation")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("Microsoft Corporation")] +[assembly: AssemblyTrademark ("Microsoft")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/DownloadUri.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/DownloadUri.cs similarity index 78% rename from src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/DownloadUri.cs rename to build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/DownloadUri.cs index 4fd2bb963fb..f1efe95dae2 100644 --- a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/DownloadUri.cs +++ b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/DownloadUri.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Net.Http; using System.Threading.Tasks; @@ -9,7 +9,7 @@ using TTask = System.Threading.Tasks.Task; using MTask = Microsoft.Build.Utilities.Task; -namespace Xamarin.Android.Tools.BootstrapTasks { +namespace Xamarin.Android.BuildTools.PrepTasks { public class DownloadUri : MTask { @@ -58,12 +58,17 @@ async TTask DownloadFile (HttpClient client, string uri, string destinationFile) Log.LogMessage (MessageImportance.Normal, $"Skipping uri '{uri}' as destination file already exists '{destinationFile}'."); return; } - Log.LogMessage (MessageImportance.Low, $"Downloading '{uri}'."); + var dp = Path.GetDirectoryName (destinationFile); + var dn = Path.GetFileName (destinationFile); + var tempPath = Path.Combine (dp, "." + dn + ".download"); + + Log.LogMessage (MessageImportance.Low, $"Downloading `{uri}` to `{tempPath}`."); using (var r = await client.GetAsync (uri)) - using (var o = File.OpenWrite (destinationFile)) { + using (var o = File.OpenWrite (tempPath)) { await r.Content.CopyToAsync (o); } + Log.LogMessage (MessageImportance.Low, $"mv '{tempPath}' '{destinationFile}'."); + File.Move (tempPath, destinationFile); } } } - diff --git a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/Git.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/Git.cs similarity index 96% rename from src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/Git.cs rename to build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/Git.cs index b81a88e823b..a2ade4bc7ab 100644 --- a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/Git.cs +++ b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/Git.cs @@ -8,11 +8,9 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -using Xamarin.Tools.Zip; - using IOFile = System.IO.File; -namespace Xamarin.Android.Tools.BootstrapTasks +namespace Xamarin.Android.BuildTools.PrepTasks { public class Git : ToolTask { diff --git a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GitBranch.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitBranch.cs similarity index 94% rename from src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GitBranch.cs rename to build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitBranch.cs index 18c467cf67f..826b94031e8 100644 --- a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GitBranch.cs +++ b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitBranch.cs @@ -8,11 +8,9 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -using Xamarin.Tools.Zip; - using IOFile = System.IO.File; -namespace Xamarin.Android.Tools.BootstrapTasks +namespace Xamarin.Android.BuildTools.PrepTasks { public sealed class GitBranch : Git { diff --git a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GitCommitHash.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitCommitHash.cs similarity index 94% rename from src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GitCommitHash.cs rename to build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitCommitHash.cs index 2a94226e8af..0dec568fcbd 100644 --- a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GitCommitHash.cs +++ b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/GitCommitHash.cs @@ -5,11 +5,9 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -using Xamarin.Tools.Zip; - using IOFile = System.IO.File; -namespace Xamarin.Android.Tools.BootstrapTasks +namespace Xamarin.Android.BuildTools.PrepTasks { public sealed class GitCommitHash : Git { 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 new file mode 100644 index 00000000000..0953c7dec1e --- /dev/null +++ b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/SystemUnzip.cs @@ -0,0 +1,153 @@ +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; } + + [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 = 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); + + if (string.Equals (HostOS, "Windows", StringComparison.OrdinalIgnoreCase)) { + 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 = GetExtractedSourceEntries (nestedTemp); + + // "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); + Directory.CreateDirectory (Path.GetDirectoryName (dest)); + Log.LogMessage (MessageImportance.Low, $"mv '{file}' '{dest}'"); + if (Directory.Exists (entry)) + Process.Start ("/bin/mv", $@"""{file}"" ""{dest}""").WaitForExit (); + else { + if (File.Exists (dest)) + File.Delete (dest); + File.Move (file, dest); + } + } + } + } + + IEnumerable GetExtractedSourceEntries (string root) + { + var entries = Directory.EnumerateFileSystemEntries (root, SourceEntryGlobParts [0], SearchOption.TopDirectoryOnly); + for (int i = 1; i < SourceEntryGlobParts.Length; ++i) { + entries = entries + .SelectMany (e => Directory.EnumerateFileSystemEntries (e, SourceEntryGlobParts [i], SearchOption.TopDirectoryOnly)); + } + return entries; + } +#pragma warning restore 1998 + } +} + diff --git a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/Which.cs b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/Which.cs similarity index 77% rename from src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/Which.cs rename to build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/Which.cs index acc334f9fde..f18af287eab 100644 --- a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/Which.cs +++ b/build-tools/xa-prep-tasks/Xamarin.Android.BuildTools.PrepTasks/Which.cs @@ -5,7 +5,7 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -namespace Xamarin.Android.Tools.BootstrapTasks +namespace Xamarin.Android.BuildTools.PrepTasks { public class Which : Task { @@ -19,13 +19,18 @@ public class Which : Task [Output] public ITaskItem Location { get; set; } - static readonly string[] FileExtensions = new []{ - null, - ".bat", - ".cmd", - ".com", - ".exe", - }; + static readonly string[] FileExtensions; + + static Which () + { + var pathExt = Environment.GetEnvironmentVariable ("PATHEXT"); + var pathExts = pathExt?.Split (new char [] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries); + FileExtensions = new string [(pathExts?.Length ?? 0) + 1]; + FileExtensions [0] = null; + if (pathExts != null) { + Array.Copy (pathExts, 0, FileExtensions, 1, pathExt.Length); + } + } public override bool Execute () { diff --git a/build-tools/xa-prep-tasks/xa-prep-tasks.csproj b/build-tools/xa-prep-tasks/xa-prep-tasks.csproj new file mode 100644 index 00000000000..51d8804045c --- /dev/null +++ b/build-tools/xa-prep-tasks/xa-prep-tasks.csproj @@ -0,0 +1,49 @@ + + + + Debug + AnyCPU + {7CE69551-BD73-4726-ACAA-AAF89C84BAF8} + Library + Xamarin.Android.BuildTools.PrepTasks + xa-prep-tasks + v4.5 + + + + true + full + false + ..\..\bin\BuildDebug + DEBUG; + prompt + 4 + false + + + true + ..\..\bin\BuildRelease + prompt + 4 + false + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build-tools/xa-prep-tasks/xa-prep-tasks.targets b/build-tools/xa-prep-tasks/xa-prep-tasks.targets new file mode 100644 index 00000000000..54358ef9f55 --- /dev/null +++ b/build-tools/xa-prep-tasks/xa-prep-tasks.targets @@ -0,0 +1,43 @@ + + + + + + + <_AzureBaseUri>https://xamjenkinsartifact.blob.core.windows.net/xamarin-android/xamarin-android/bin/ + + + + <_BundlePath>$(OutputPath)$(XABundleFileName) + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks.csproj b/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks.csproj index f821f59d2dd..02525f44277 100644 --- a/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks.csproj +++ b/src/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks.csproj @@ -38,14 +38,9 @@ - - - - - diff --git a/src/monodroid/monodroid.targets b/src/monodroid/monodroid.targets index 9e9b04e8cb4..ec50cd2d848 100644 --- a/src/monodroid/monodroid.targets +++ b/src/monodroid/monodroid.targets @@ -1,7 +1,5 @@ - -