AndroidSupportComponents/build.cake

352 строки
12 KiB
C#

// Tools needed by cake addins
#tool nuget:?package=vswhere&version=2.7.1
// Cake Addins
#addin nuget:?package=Cake.FileHelpers&version=3.2.0
#addin nuget:?package=Cake.Compression&version=0.2.3
#addin nuget:?package=Xamarin.Nuget.Validator&version=1.1.1
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using Xamarin.Nuget.Validator;
// The main configuration points
var TARGET = Argument ("t", Argument ("target", "Default"));
var BUILD_CONFIG = Argument ("config", "Release");
var VERBOSITY = (Verbosity) Enum.Parse (typeof(Verbosity), Argument ("v", Argument ("verbosity", "Normal")), true);
var PACKAGE_VERSION_SUFFIX = EnvironmentVariable ("PACKAGE_VERSION_SUFFIX");
var XAMARIN_ANDROID_PATH = EnvironmentVariable ("XAMARIN_ANDROID_PATH");
var JAVA_HOME = EnvironmentVariable ("JAVA_HOME");
// Lists all the artifacts and their versions for com.android.support.*
// https://dl.google.com/dl/android/maven2/com/android/support/group-index.xml
// Master list of all the packages in the repo:
// https://dl.google.com/dl/android/maven2/master-index.xml
var REF_DOCS_URL = "https://bosstoragemirror.blob.core.windows.net/android-docs-scraper/a7/a712886a8b4ee709f32d51823223039883d38734/androidx.zip";
// In order to create the type mapping, we need to get the AndroidSupport.Merged.dll
var SUPPORT_MERGED_DLL_URL = EnvironmentVariable("SUPPORT_MERGED_DLL_URL") ?? $"https://github.com/xamarin/AndroidSupportComponents/releases/download/28.0.0.2/AndroidSupport.Merged.dll";
// Resolve Xamarin.Android installation
var ANDROID_SDK_BASE_VERSION = "v1.0";
var ANDROID_SDK_VERSION = "v9.0";
if (string.IsNullOrEmpty(XAMARIN_ANDROID_PATH)) {
if (IsRunningOnWindows()) {
var vsInstallPath = VSWhereLatest(new VSWhereLatestSettings { Requires = "Component.Xamarin" });
XAMARIN_ANDROID_PATH = vsInstallPath.Combine("Common7/IDE/ReferenceAssemblies/Microsoft/Framework/MonoAndroid").FullPath;
} else {
if (DirectoryExists("/Library/Frameworks/Xamarin.Android.framework/Versions/Current/lib/xamarin.android/xbuild-frameworks/MonoAndroid"))
XAMARIN_ANDROID_PATH = "/Library/Frameworks/Xamarin.Android.framework/Versions/Current/lib/xamarin.android/xbuild-frameworks/MonoAndroid";
else
XAMARIN_ANDROID_PATH = "/Library/Frameworks/Xamarin.Android.framework/Versions/Current/lib/xbuild-frameworks/MonoAndroid";
}
}
if (!DirectoryExists($"{XAMARIN_ANDROID_PATH}/{ANDROID_SDK_VERSION}"))
throw new Exception($"Unable to find Xamarin.Android {ANDROID_SDK_VERSION} at {XAMARIN_ANDROID_PATH}.");
// Load all the git variables
var BUILD_COMMIT = EnvironmentVariable("BUILD_SOURCEVERSION") ?? "DEV";
var BUILD_NUMBER = EnvironmentVariable("BUILD_NUMBER") ?? "DEBUG";
var BUILD_TIMESTAMP = DateTime.UtcNow.ToString();
var REQUIRED_DOTNET_TOOLS = new [] {
"xamarin-android-binderator",
"api-tools",
"xamarin.androidx.migration.tool"
};
// Log some variables
Information ("XAMARIN_ANDROID_PATH: {0}", XAMARIN_ANDROID_PATH);
Information ("ANDROID_SDK_VERSION: {0}", ANDROID_SDK_VERSION);
Information ("BUILD_COMMIT: {0}", BUILD_COMMIT);
Information ("BUILD_NUMBER: {0}", BUILD_NUMBER);
Information ("BUILD_TIMESTAMP: {0}", BUILD_TIMESTAMP);
// You shouldn't have to configure anything below here
// ######################################################
void RunProcess(FilePath fileName, string processArguments)
{
var exitCode = StartProcess(fileName, processArguments);
if (exitCode != 0)
throw new Exception ($"Process {fileName} exited with code {exitCode}.");
}
string[] RunProcessWithOutput(FilePath fileName, string processArguments)
{
var exitCode = StartProcess(fileName, new ProcessSettings {
Arguments = processArguments,
RedirectStandardOutput = true,
RedirectStandardError = true
}, out var procOut);
if (exitCode != 0)
throw new Exception ($"Process {fileName} exited with code {exitCode}.");
return procOut.ToArray();;
}
Task("javadocs")
.Does(() =>
{
if (!FileExists("./externals/docs.zip"))
DownloadFile(REF_DOCS_URL, "./externals/docs.zip");
if (!DirectoryExists("./externals/docs"))
Unzip ("./externals/docs.zip", "./externals/docs");
var astJar = new FilePath("./util/JavaASTParameterNames-1.0.jar");
var sourcesJars = GetFiles("./externals/**/*-sources.jar");
foreach (var srcJar in sourcesJars) {
var srcJarPath = MakeAbsolute(srcJar).FullPath;
var outTxtPath = srcJarPath.Replace("-sources.jar", "-paramnames.txt");
var outXmlPath = srcJarPath.Replace("-sources.jar", "-paramnames.xml");
RunProcess("java", "-jar \"" + MakeAbsolute(astJar).FullPath + "\" --text \"" + srcJarPath + "\" \"" + outTxtPath + "\"");
RunProcess("java", "-jar \"" + MakeAbsolute(astJar).FullPath + "\" --xml \"" + srcJarPath + "\" \"" + outXmlPath + "\"");
}
});
Task("check-tools")
.Does(() =>
{
var installedTools = RunProcessWithOutput("dotnet", "tool list -g");
foreach (var toolName in REQUIRED_DOTNET_TOOLS) {
if (installedTools.All(l => l.IndexOf(toolName, StringComparison.OrdinalIgnoreCase) == -1))
throw new Exception ($"Missing dotnet tool: {toolName}");
}
});
Task ("binderate")
.Does (() =>
{
var configFile = MakeAbsolute(new FilePath("./config.json")).FullPath;
var basePath = MakeAbsolute(new DirectoryPath ("./")).FullPath;
// Run the dotnet tool for binderator
RunProcess("xamarin-android-binderator",
$"--config=\"{configFile}\" --basepath=\"{basePath}\"");
// format the targets file so they are pretty in the package
var targetsFiles = GetFiles("generated/**/*.targets");
var xmlns = (XNamespace)"http://schemas.microsoft.com/developer/msbuild/2003";
foreach (var targets in targetsFiles) {
var xdoc = XDocument.Load(targets.FullPath);
xdoc.Save(targets.FullPath);
}
});
Task("libs")
.Does(() =>
{
var settings = new MSBuildSettings()
.SetConfiguration(BUILD_CONFIG)
.SetVerbosity(VERBOSITY)
.SetMaxCpuCount(0)
.WithRestore()
.WithProperty("PackageVersionSuffix", PACKAGE_VERSION_SUFFIX)
.WithProperty("DesignTimeBuild", "false")
.WithProperty("AndroidSdkBuildToolsVersion", "28.0.3");
if (!string.IsNullOrEmpty (JAVA_HOME))
settings.WithProperty ("JavaSdkDirectory", JAVA_HOME);
MSBuild("./generated/AndroidX.sln", settings);
});
Task("nuget")
.IsDependentOn("libs")
.Does(() =>
{
var settings = new MSBuildSettings()
.SetConfiguration(BUILD_CONFIG)
.SetVerbosity(VERBOSITY)
.SetMaxCpuCount(0)
.WithRestore()
.WithProperty("PackageVersionSuffix", PACKAGE_VERSION_SUFFIX)
.WithProperty("PackageRequireLicenseAcceptance", "true")
.WithProperty("PackageOutputPath", MakeAbsolute ((DirectoryPath)"./output/").FullPath)
.WithProperty("DesignTimeBuild", "false")
.WithProperty("AndroidSdkBuildToolsVersion", "28.0.3")
.WithTarget("Pack");
if (!string.IsNullOrEmpty (JAVA_HOME))
settings.WithProperty ("JavaSdkDirectory", JAVA_HOME);
MSBuild("./generated/AndroidX.sln", settings);
});
Task("samples")
.IsDependentOn("nuget")
.Does(() =>
{
// TODO: make this actually work with more than just this sample
// make a big .targets file that pulls in everything
var xmlns = (XNamespace)"http://schemas.microsoft.com/developer/msbuild/2003";
var itemGroup = new XElement(xmlns + "ItemGroup");
foreach (var nupkg in GetFiles("./output/*.nupkg")) {
// Skip Wear as it has special implications requiring more packages to be used properly in an app
if (nupkg.FullPath.Contains(".Wear."))
continue;
var filename = nupkg.GetFilenameWithoutExtension();
var match = Regex.Match(filename.ToString(), @"(.+?)\.(\d+[\.0-9\-a-zA-Z]+)");
itemGroup.Add(new XElement(xmlns + "PackageReference",
new XAttribute("Include", match.Groups[1]),
new XAttribute("Version", match.Groups[2])));
}
var xdoc = new XDocument(new XElement(xmlns + "Project", itemGroup));
xdoc.Save("./output/AllPackages.targets");
// clear the packages folder so we always use the latest
var packagesPath = MakeAbsolute((DirectoryPath)"./samples/packages").FullPath;
EnsureDirectoryExists(packagesPath);
CleanDirectories(packagesPath);
// build the samples
var settings = new MSBuildSettings()
.SetConfiguration(BUILD_CONFIG)
.SetVerbosity(VERBOSITY)
.SetMaxCpuCount(0)
.WithRestore()
.WithProperty("RestoreNoCache", "true")
.WithProperty("RestorePackagesPath", packagesPath)
.WithProperty("DesignTimeBuild", "false")
.WithProperty("AndroidSdkBuildToolsVersion", "28.0.3");
if (!string.IsNullOrEmpty (JAVA_HOME))
settings.WithProperty ("JavaSdkDirectory", JAVA_HOME);
MSBuild("./samples/BuildAll/BuildAll.sln", settings);
});
Task("nuget-validation")
.Does(() =>
{
var options = new NugetValidatorOptions {
Copyright = "© Microsoft Corporation. All rights reserved.",
Author = "Microsoft",
Owner = "Microsoft",
NeedsProjectUrl = true,
NeedsLicenseUrl = true,
ValidateRequireLicenseAcceptance = true,
ValidPackageNamespace = new [] { "Xamarin" },
};
var nupkgFiles = GetFiles("./output/*.nupkg");
Information("Found {0} NuGet packages to validate.", nupkgFiles.Count());
foreach (var nupkgFile in nupkgFiles) {
var fname = nupkgFile.GetFilename();
Information($"Verifiying metadata of {fname}...");
var result = NugetValidator.Validate(MakeAbsolute(nupkgFile).FullPath, options);
if (!result.Success) {
Error($"Metadata validation failed for: {fname} ");
Error(string.Join("\n ", result.ErrorMessages));
throw new Exception($"Invalid Metadata for: {fname}");
} else {
Information($"Metadata validation passed for: {fname}");
}
}
});
Task ("diff")
.Does (() =>
{
RunProcess("api-tools",
"nuget-diff output --latest --prerelease --group-ids --ignore-unchanged --output output/api-diff --cache externals/package_cache");
});
Task ("generate-mapping")
.IsDependentOn ("merge")
.Does (() =>
{
// download the AndroidSupport.Merged.dll from a past build
if (!FileExists ("./output/AndroidSupport.Merged.dll")) {
EnsureDirectoryExists ("./output/");
DownloadFile (SUPPORT_MERGED_DLL_URL, "./output/AndroidSupport.Merged.dll");
}
// generate the mapping
RunProcess("androidx-migrator",
$"generate -v " +
$" --support ./output/AndroidSupport.Merged.dll" +
$" --androidx ./output/AndroidX.Merged.dll" +
$" --output ./output/androidx-mapping.csv");
});
Task ("merge")
.IsDependentOn ("libs")
.Does (() =>
{
// find all the dlls
var allDlls = GetFiles($"./generated/*/bin/{BUILD_CONFIG}/monoandroid*/Xamarin.*.dll");
var mergeDlls = allDlls
.GroupBy(d => new FileInfo(d.FullPath).Name)
.Select(g => g.FirstOrDefault())
.ToList();
// merge them all
EnsureDirectoryExists("./output/");
RunProcess("androidx-migrator",
$"merge" +
$" --assembly " + string.Join(" --assembly ", mergeDlls) +
$" --output ./output/AndroidX.Merged.dll" +
$" --search \"{XAMARIN_ANDROID_PATH}/{ANDROID_SDK_VERSION}\" " +
$" --search \"{XAMARIN_ANDROID_PATH}/{ANDROID_SDK_BASE_VERSION}\" " +
$" --inject-assemblyname");
});
Task("inject-variables")
.WithCriteria(!BuildSystem.IsLocalBuild)
.Does(() =>
{
var glob = "./source/AssemblyInfo.cs";
ReplaceTextInFiles(glob, "{BUILD_COMMIT}", BUILD_COMMIT);
ReplaceTextInFiles(glob, "{BUILD_NUMBER}", BUILD_NUMBER);
ReplaceTextInFiles(glob, "{BUILD_TIMESTAMP}", BUILD_TIMESTAMP);
});
Task ("clean")
.Does (() =>
{
if (DirectoryExists ("./externals"))
DeleteDirectory ("./externals", true);
if (DirectoryExists ("./generated"))
DeleteDirectory ("./generated", true);
CleanDirectories ("./**/packages");
});
Task ("packages")
.IsDependentOn ("binderate")
.IsDependentOn ("nuget");
Task ("full-run")
.IsDependentOn ("binderate")
.IsDependentOn ("nuget")
.IsDependentOn ("samples");
Task ("Default")
.IsDependentOn ("binderate")
.IsDependentOn ("nuget")
.IsDependentOn ("nuget-validation")
.IsDependentOn ("generate-mapping")
.IsDependentOn ("diff")
.IsDependentOn ("samples");
Task ("ci")
.IsDependentOn ("check-tools")
.IsDependentOn ("inject-variables")
.IsDependentOn ("binderate")
.IsDependentOn ("nuget")
.IsDependentOn ("nuget-validation")
.IsDependentOn ("generate-mapping")
.IsDependentOn ("diff")
.IsDependentOn ("samples");
RunTarget (TARGET);