зеркало из https://github.com/xamarin/AndroidX.git
1006 строки
38 KiB
C#
Executable File
1006 строки
38 KiB
C#
Executable File
// Tools needed by cake addins
|
|
#tool nuget:?package=vswhere&version=3.1.7
|
|
|
|
#tool nuget:?package=Cake.CoreCLR
|
|
#tool nuget:?package=Microsoft.Android.Sdk.Windows&version=34.0.95
|
|
|
|
// Cake Addins
|
|
#addin nuget:?package=Cake.FileHelpers&version=7.0.0
|
|
#addin nuget:?package=Newtonsoft.Json&version=13.0.3
|
|
#addin nuget:?package=Cake.MonoApiTools&version=3.0.5
|
|
#addin nuget:?package=CsvHelper&version=31.0.3
|
|
#addin nuget:?package=SharpZipLib&version=1.4.2
|
|
|
|
// #addin nuget:?package=NuGet.Protocol&loaddependencies=true&version=5.6.0
|
|
// #addin nuget:?package=NuGet.Versioning&loaddependencies=true&version=5.6.0
|
|
// #addin nuget:?package=Microsoft.Extensions.Logging&loaddependencies=true&version=3.0.0
|
|
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using CsvHelper;
|
|
|
|
// The main configuration points
|
|
var TARGET = Argument ("t", Argument ("target", "Default"));
|
|
var CONFIGURATION = Argument ("c", Argument ("configuration", "Release"));
|
|
var VERBOSITY = Argument ("v", Argument ("verbosity", Verbosity.Normal));
|
|
|
|
// 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";
|
|
|
|
var JAVA_INTEROP_ZIP_URL = "https://github.com/xamarin/java.interop/archive/d17-2.zip";
|
|
|
|
var SUPPORT_CONFIG_URL = "https://raw.githubusercontent.com/xamarin/AndroidSupportComponents/master/config.json";
|
|
|
|
var VISUAL_STUDIO_ROOT = EnvironmentVariable ("VISUAL_STUDIO_ROOT") ?? Argument ("vs", "");
|
|
if (IsRunningOnWindows() && string.IsNullOrEmpty(VISUAL_STUDIO_ROOT))
|
|
VISUAL_STUDIO_ROOT = VSWhereLatest(new VSWhereLatestSettings { Requires = "Component.Xamarin", IncludePrerelease = true }).FullPath;
|
|
|
|
// Resolve Xamarin.Android installation
|
|
var XAMARIN_ANDROID_PATH = EnvironmentVariable ("XAMARIN_ANDROID_PATH");
|
|
var ANDROID_SDK_BASE_VERSION = "v1.0";
|
|
var ANDROID_SDK_VERSION = "v12.0";
|
|
var AndroidSdkBuildTools = $"32.0.0";
|
|
|
|
if (string.IsNullOrEmpty(XAMARIN_ANDROID_PATH)) {
|
|
if (IsRunningOnWindows()) {
|
|
XAMARIN_ANDROID_PATH = VISUAL_STUDIO_ROOT + @"\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid";
|
|
} 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_COMMIT") ?? "DEV";
|
|
var BUILD_NUMBER = EnvironmentVariable("BUILD_NUMBER") ?? "DEBUG";
|
|
var BUILD_TIMESTAMP = DateTime.UtcNow.ToString();
|
|
|
|
var REQUIRED_DOTNET_TOOLS = new [] {
|
|
"xamarin-android-binderator"
|
|
};
|
|
|
|
string JAVA_HOME = EnvironmentVariable ("JAVA_HOME") ?? Argument ("java_home", "");
|
|
string ANDROID_HOME = EnvironmentVariable ("ANDROID_HOME") ?? Argument ("android_home", "");
|
|
string ANDROID_SDK_ROOT = EnvironmentVariable ("ANDROID_SDK_ROOT") ?? Argument ("android_sdk_root", "");
|
|
string MSBUILD_PATH = IsRunningOnWindows() && !string.IsNullOrEmpty(VISUAL_STUDIO_ROOT)
|
|
? VISUAL_STUDIO_ROOT + @"\MSBuild\Current\Bin\MSBuild.exe"
|
|
: null;
|
|
|
|
// Log some variables
|
|
Information ($"JAVA_HOME : {JAVA_HOME}");
|
|
Information ($"ANDROID_HOME : {ANDROID_HOME}");
|
|
Information ($"ANDROID_SDK_ROOT : {ANDROID_SDK_ROOT}");
|
|
Information ($"VISUAL_STUDIO_ROOT : {VISUAL_STUDIO_ROOT}");
|
|
Information ($"XAMARIN_ANDROID_PATH : {XAMARIN_ANDROID_PATH}");
|
|
Information ($"MSBUILD_PATH : {MSBUILD_PATH}");
|
|
Information ($"ANDROID_SDK_VERSION : {ANDROID_SDK_VERSION}");
|
|
Information ($"BUILD_COMMIT : {BUILD_COMMIT}");
|
|
Information ($"BUILD_NUMBER : {BUILD_NUMBER}");
|
|
Information ($"BUILD_TIMESTAMP : {BUILD_TIMESTAMP}");
|
|
|
|
|
|
// You shouldn't have to configure anything below here
|
|
// ######################################################
|
|
|
|
var MIGRATION_PACKAGE_VERSION = GetNuGetVersion("Xamarin.AndroidX.Migration");
|
|
var MULTIDEX_PACKAGE_VERSION = GetNuGetVersion("Xamarin.AndroidX.MultiDex");
|
|
|
|
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();;
|
|
}
|
|
|
|
void RunGradle(DirectoryPath root, string target)
|
|
{
|
|
root = MakeAbsolute(root);
|
|
var proc = IsRunningOnWindows()
|
|
? root.CombineWithFilePath("gradlew.bat").FullPath
|
|
: "bash";
|
|
var args = IsRunningOnWindows()
|
|
? ""
|
|
: root.CombineWithFilePath("gradlew").FullPath;
|
|
args += $" {target} -p {root}";
|
|
|
|
var exitCode = StartProcess(proc, args);
|
|
if (exitCode != 0)
|
|
throw new Exception($"Gradle exited with code {exitCode}.");
|
|
}
|
|
|
|
string GetNuGetVersion(string nugetId, string configJson = "./config.json")
|
|
{
|
|
var json = JToken.Parse(FileReadText(configJson));
|
|
|
|
if (json.Type == JTokenType.Array)
|
|
json = ((JArray)json)[0];
|
|
|
|
var artifacts = json["artifacts"];
|
|
var artifact = artifacts.FirstOrDefault(j => (string)j["nugetId"] == nugetId);
|
|
|
|
if (artifact == null)
|
|
{
|
|
/*
|
|
NEEDS INVESTIGATION
|
|
nugetID Xamarin.Jetbrains.Annotations was found as dependency, but it was not listed in config.json
|
|
|
|
buildTransitive might be the issue.
|
|
|
|
workaround was to add following snippet to config.json:
|
|
|
|
{
|
|
"groupId": "org.jetbrains",
|
|
"artifactId": "annotations",
|
|
"version": "13.0",
|
|
"nugetVersion": "13.0.0.4",
|
|
"nugetId": "Xamarin.Jetbrains.Annotations",
|
|
"dependencyOnly": true
|
|
},
|
|
*/
|
|
}
|
|
|
|
return (string)(artifact["nugetVersion"] ?? artifact["version"]);
|
|
}
|
|
|
|
string GetNuGetId(string assemblyName, string configJson = "./config.json")
|
|
{
|
|
var json = JToken.Parse(FileReadText(configJson));
|
|
|
|
if (json.Type == JTokenType.Array)
|
|
json = ((JArray)json)[0];
|
|
|
|
var artifacts = json["artifacts"];
|
|
var artifact =
|
|
artifacts.FirstOrDefault(j => (string)j["assemblyName"] == assemblyName) ??
|
|
artifacts.FirstOrDefault(j => (string)j["nugetId"] == assemblyName);
|
|
|
|
if (artifact == null)
|
|
return assemblyName;
|
|
|
|
return (string)artifact["nugetId"];
|
|
}
|
|
|
|
IEnumerable<string> GetArtifacts(string configJson = "./config.json")
|
|
{
|
|
var json = JToken.Parse(FileReadText(configJson));
|
|
|
|
if (json.Type == JTokenType.Array)
|
|
json = ((JArray)json)[0];
|
|
|
|
var artifacts = json["artifacts"];
|
|
foreach (var artifact in artifacts) {
|
|
yield return $"{artifact["groupId"]}.{artifact["artifactId"]}";
|
|
}
|
|
}
|
|
|
|
// Preparation
|
|
|
|
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("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("tools-update")
|
|
.Does
|
|
(
|
|
() =>
|
|
{
|
|
/*
|
|
dotnet tool uninstall -g Cake.Tool
|
|
dotnet tool install -g Cake.Tool
|
|
dotnet tool uninstall -g xamarin.androidbinderator.tool
|
|
dotnet tool install -g xamarin.androidbinderator.tool
|
|
|
|
StartProcess("dotnet", "tool uninstall -g Cake.Tool");
|
|
StartProcess("dotnet", "tool install -g Cake.Tool");
|
|
*/
|
|
StartProcess("dotnet", "tool uninstall -g xamarin.androidbinderator.tool");
|
|
StartProcess("dotnet", "tool install -g xamarin.androidbinderator.tool");
|
|
}
|
|
);
|
|
|
|
// Android X
|
|
|
|
Task("javadocs")
|
|
.Does(() =>
|
|
{
|
|
EnsureDirectoryExists("./externals/");
|
|
|
|
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 ("binderate")
|
|
.IsDependentOn("binderate-config-verify")
|
|
.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);
|
|
}
|
|
|
|
// different lint.jar files in artifacts causing R8 errors
|
|
foreach (var file in GetFiles("./externals/**/lint.jar")) {
|
|
Information($"Deleting: {file}");
|
|
DeleteFile(file);
|
|
|
|
foreach (var aar in GetFiles($"{file.GetDirectory()}/../*.aar")) {
|
|
Information($"Deleting: lint.jar from {aar}");
|
|
using (var zipFile = new ICSharpCode.SharpZipLib.Zip.ZipFile(aar.ToString())) {
|
|
zipFile.BeginUpdate();
|
|
var entry = zipFile.GetEntry("lint.jar");
|
|
if (entry != null) {
|
|
Information($" Deleting lint.jar from {aar}");
|
|
zipFile.Delete(entry);
|
|
}
|
|
zipFile.CommitUpdate();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
string version_suffix = "";
|
|
string nuget_version_template = $"x.y.z.w{version_suffix}";
|
|
JArray binderator_json_array = null;
|
|
|
|
Task("binderate-config-verify")
|
|
.IsDependentOn("binderate-fix")
|
|
.Does
|
|
(
|
|
() =>
|
|
{
|
|
if (!(binderator_json_array?.Count > 0))
|
|
{
|
|
using (StreamReader reader = System.IO.File.OpenText(@"./config.json"))
|
|
{
|
|
JsonTextReader jtr = new JsonTextReader(reader);
|
|
binderator_json_array = (JArray)JToken.ReadFrom(jtr);
|
|
}
|
|
}
|
|
|
|
Information("config.json verification...");
|
|
foreach(JObject jo in binderator_json_array[0]["artifacts"])
|
|
{
|
|
bool? dependency_only = (bool?) jo["dependencyOnly"];
|
|
if ( dependency_only == true)
|
|
{
|
|
continue;
|
|
}
|
|
string artifact_version = (string) jo["version"];
|
|
string nuget_version = (string) jo["nugetVersion"];
|
|
|
|
string[] artifact_version_parts = artifact_version.Split(new string[]{ "-" }, StringSplitOptions.RemoveEmptyEntries);
|
|
string[] nuget_version_parts = nuget_version.Split(new string[]{ "-" }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
string nuget_version_prefix = nuget_version_parts[0];
|
|
string artifact_version_prefix = artifact_version_parts[0];
|
|
string nuget_version_suffix = null;
|
|
string artifact_version_suffix = null;
|
|
|
|
if (nuget_version_parts.Length > 1)
|
|
{
|
|
nuget_version_suffix = nuget_version_parts[1];
|
|
}
|
|
if (artifact_version_parts.Length > 1)
|
|
{
|
|
artifact_version_suffix = artifact_version_parts[1];
|
|
}
|
|
|
|
Information($"groupId = {jo["groupId"]}");
|
|
Information($"artifactId = {jo["artifactId"]}");
|
|
Information($"artifact_version = {artifact_version}");
|
|
Information($"artifact_version_prefix = {artifact_version_prefix}");
|
|
Information($"artifact_version_suffix = {artifact_version_suffix}");
|
|
Information($"nuget_version = {nuget_version}");
|
|
Information($"nuget_version_prefix = {nuget_version_prefix}");
|
|
Information($"nuget_version_suffix = {nuget_version_suffix}");
|
|
Information($"nugetId = {jo["nugetId"]}");
|
|
|
|
|
|
string[] artifact_version_prefix_parts = artifact_version_prefix.Split(new string[]{ "." }, StringSplitOptions.RemoveEmptyEntries);
|
|
string[] nuget_version_prefix_parts = nuget_version_prefix.Split(new string[]{ "." }, StringSplitOptions.RemoveEmptyEntries);
|
|
string x = nuget_version_prefix_parts[0];
|
|
string y = nuget_version_prefix_parts[1];
|
|
string z = nuget_version_prefix_parts[2];
|
|
|
|
string w = null;
|
|
if (nuget_version_prefix_parts.Length > 3)
|
|
{
|
|
w = nuget_version_prefix_parts[3];
|
|
}
|
|
|
|
string nuget_version_new = nuget_version_template;
|
|
nuget_version_new = nuget_version_new.Replace("x", x);
|
|
nuget_version_new = nuget_version_new.Replace("y", y);
|
|
nuget_version_new = nuget_version_new.Replace("z", z);
|
|
nuget_version_new = nuget_version_new.Replace("w", w);
|
|
|
|
if ( ! string.IsNullOrEmpty(nuget_version_suffix) )
|
|
{
|
|
nuget_version_new += $"-{nuget_version_suffix}";
|
|
}
|
|
|
|
Information($"nuget_version_new = {nuget_version_new}");
|
|
|
|
if
|
|
(
|
|
! nuget_version_new.StartsWith($"{artifact_version_prefix}")
|
|
&&
|
|
! nuget_version_new.EndsWith($"{artifact_version_suffix}")
|
|
)
|
|
{
|
|
Error("check config.json for nuget id");
|
|
Error ($" groupId = {jo["groupId"]}");
|
|
Error ($" artifactId = {jo["artifactId"]}");
|
|
Error ($" artifact_version = {artifact_version}");
|
|
Error ($" nuget_version = {nuget_version}");
|
|
Error ($" nuget_version_new = {nuget_version_new}");
|
|
Error ($" nugetId = {jo["nugetId"]}");
|
|
|
|
Warning($" expected : ");
|
|
Warning($" nuget_version = {nuget_version_new}");
|
|
throw new Exception("check config.json for nuget id");
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
);
|
|
|
|
Task("binderate-diff")
|
|
.IsDependentOn("binderate")
|
|
.Does
|
|
(
|
|
() =>
|
|
{
|
|
EnsureDirectoryExists("./output/");
|
|
|
|
// "git diff master:config.json config.json" > ./output/config.json.diff-from-master.txt"
|
|
string process = "git";
|
|
string process_args = "diff master:config.json config.json";
|
|
IEnumerable<string> redirectedStandardOutput;
|
|
ProcessSettings process_settings = new ProcessSettings ()
|
|
{
|
|
Arguments = process_args,
|
|
RedirectStandardOutput = true
|
|
};
|
|
int exitCodeWithoutArguments = StartProcess(process, process_settings, out redirectedStandardOutput);
|
|
System.IO.File.WriteAllLines("./output/config.json.diff-from-master.txt", redirectedStandardOutput.ToArray());
|
|
Information("Exit code: {0}", exitCodeWithoutArguments);
|
|
}
|
|
);
|
|
|
|
Task("binderate-fix")
|
|
.Does
|
|
(
|
|
() =>
|
|
{
|
|
if (!(binderator_json_array?.Count > 0))
|
|
{
|
|
using (StreamReader reader = System.IO.File.OpenText(@"./config.json"))
|
|
{
|
|
JsonTextReader jtr = new JsonTextReader(reader);
|
|
binderator_json_array = (JArray)JToken.ReadFrom(jtr);
|
|
}
|
|
}
|
|
|
|
Warning("config.json fixing missing folder strucutre ...");
|
|
foreach(JObject jo in binderator_json_array[0]["artifacts"])
|
|
{
|
|
string groupId = (string) jo["groupId"];
|
|
string artifactId = (string) jo["artifactId"];
|
|
|
|
Information($" Verifying files for :");
|
|
Information($" group : {groupId}");
|
|
Information($" artifact : {artifactId}");
|
|
|
|
bool? dependency_only = (bool?) jo["dependencyOnly"];
|
|
if ( dependency_only == true)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
string dir_group = $"source/{groupId}";
|
|
if ( ! DirectoryExists(dir_group) )
|
|
{
|
|
Warning($" Creating {dir_group}");
|
|
CreateDirectory(dir_group);
|
|
}
|
|
string dir_artifact = $"{dir_group}/artifactId";
|
|
if ( ! DirectoryExists(dir_group) )
|
|
{
|
|
Warning($" Creating artifact folder : {dir_artifact}");
|
|
CreateDirectory(dir_group);
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
);
|
|
|
|
|
|
// using System.Threading;
|
|
// using Microsoft.Extensions.Logging;
|
|
// using Microsoft.Extensions.Logging.Abstractions;
|
|
|
|
// using NuGet.Protocol.Core.Types;
|
|
// using NuGet.Versioning;
|
|
// using NuGet.Protocol.Core.Types;
|
|
|
|
Task("binderate-nuget-check")
|
|
.Does
|
|
(
|
|
() =>
|
|
{
|
|
if (!(binderator_json_array?.Count > 0))
|
|
{
|
|
using (StreamReader reader = System.IO.File.OpenText(@"./config.json"))
|
|
{
|
|
JsonTextReader jtr = new JsonTextReader(reader);
|
|
binderator_json_array = (JArray)JToken.ReadFrom(jtr);
|
|
}
|
|
}
|
|
|
|
Warning("config.json fixing missing folder structure ...");
|
|
foreach(JObject jo in binderator_json_array[0]["artifacts"])
|
|
{
|
|
string groupId = (string) jo["groupId"];
|
|
string artifactId = (string) jo["artifactId"];
|
|
string nugetId = (string) jo["nugetId"];
|
|
string nugetVersion = (string) jo["nugetVersion"];
|
|
|
|
Information($" Verifying nuget :");
|
|
Information($" nugetId : {nugetId}");
|
|
Information($" config.json veriosn : {nugetVersion}");
|
|
|
|
// ILogger logger = NullLogger.Instance;
|
|
// CancellationToken cancellationToken = CancellationToken.None;
|
|
|
|
// SourceCacheContext cache = new SourceCacheContext();
|
|
// SourceRepository repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
|
|
// FindPackageByIdResource resource = await repository.GetResourceAsync<FindPackageByIdResource>().Result;
|
|
|
|
// IEnumerable<NuGetVersion> versions = resource.GetAllVersionsAsync
|
|
// (
|
|
// nugetId,
|
|
// cache,
|
|
// logger,
|
|
// cancellationToken
|
|
// ).Result;
|
|
|
|
// foreach (NuGetVersion version in versions)
|
|
// {
|
|
// Information($" Found version {version}");
|
|
// }
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
);
|
|
|
|
|
|
System.Xml.XmlDocument xmldoc = null;
|
|
System.Xml.XmlNamespaceManager ns = null;
|
|
|
|
Task("metadata-verify")
|
|
.Does
|
|
(
|
|
() =>
|
|
{
|
|
FilePathCollection metadata_files = null;
|
|
|
|
// namespace is required, otherwise NRE
|
|
string xml_namespace_name = "ax"; // could be "apixml" but it is irrelevant, keeping it short
|
|
|
|
string xpath_expression_nodes_to_find =
|
|
//$@"//attr[contains(@path,'interface') and contains(@name ,'visibility')]"
|
|
$@"//attr[contains(@path,'interface')]"
|
|
;
|
|
|
|
metadata_files = GetFiles($"./generated/**/Metadata*.xml");
|
|
foreach(FilePath fp in metadata_files)
|
|
{
|
|
Information($"Metadata = {fp}");
|
|
throw new Exception("Move this file to source");
|
|
}
|
|
metadata_files = GetFiles($"./source/**/Metadata*.xml");
|
|
foreach(FilePath fp in metadata_files)
|
|
{
|
|
Information($"Metadata = {fp}");
|
|
xmldoc = new System.Xml.XmlDocument();
|
|
xmldoc.Load(fp.ToString());
|
|
ns = new System.Xml.XmlNamespaceManager(xmldoc.NameTable);
|
|
|
|
List<(string Path, bool IsPublic)> result = GetXmlMetadata(xpath_expression_nodes_to_find, ns).ToList();
|
|
foreach((string Path, bool IsPublic) r in result)
|
|
{
|
|
Information($" Found:");
|
|
Information($" Path: {r.Path}");
|
|
Information($" IsPublic: {r.IsPublic}");
|
|
if (r.IsPublic)
|
|
{
|
|
throw new Exception("Preventing exposing/surfacing interfaces with default package accessibility as public");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
private IEnumerable<(string Path, bool IsPublic)> GetXmlMetadata(string xpath, System.Xml.XmlNamespaceManager xml_namespace)
|
|
{
|
|
System.Xml.XmlNodeList node_list = xmldoc.SelectNodes(xpath, xml_namespace);
|
|
|
|
foreach (System.Xml.XmlNode node in node_list)
|
|
{
|
|
string name = node.Attributes["name"].Value;
|
|
string inner_text = node.InnerText; //.Value;
|
|
string path = node.Attributes["path"].Value;
|
|
|
|
Information($" path = {path}");
|
|
|
|
if (path.Contains("MediaRouteProvider.DynamicGroupRouteController"))
|
|
{
|
|
Information($" Found:");
|
|
Information($" Name: {name}");
|
|
Information($" Visibility: {inner_text}");
|
|
throw new Exception("MediaRouteProvider.DynamicGroupRouteController");
|
|
}
|
|
|
|
if (string.Equals(name, "visibility") && inner_text.Contains("public"))
|
|
{
|
|
Information($" Visibility = {inner_text}");
|
|
|
|
bool is_public = inner_text.Contains("public") ? true : false;
|
|
|
|
yield return (Path: path, IsPublic: is_public);
|
|
}
|
|
}
|
|
}
|
|
|
|
Task("libs")
|
|
.IsDependentOn("metadata-verify")
|
|
.IsDependentOn("libs-native")
|
|
.Does(() =>
|
|
{
|
|
DotNetMSBuildSettings settings = new DotNetMSBuildSettings()
|
|
.SetConfiguration(CONFIGURATION)
|
|
.SetMaxCpuCount(0)
|
|
.EnableBinaryLogger($"./output/libs.{CONFIGURATION}.binlog")
|
|
.WithProperty("MigrationPackageVersion", MIGRATION_PACKAGE_VERSION)
|
|
.WithProperty("Verbosity", VERBOSITY.ToString())
|
|
.WithProperty("DesignTimeBuild", "false")
|
|
.WithProperty("AndroidSdkBuildToolsVersion", $"{AndroidSdkBuildTools}");
|
|
|
|
if (!string.IsNullOrEmpty(ANDROID_HOME))
|
|
settings.WithProperty("AndroidSdkDirectory", $"{ANDROID_HOME}");
|
|
|
|
DotNetRestore("./generated/AndroidX.sln", new DotNetRestoreSettings
|
|
{
|
|
MSBuildSettings = settings.EnableBinaryLogger("./output/restore.binlog")
|
|
});
|
|
|
|
DotNetBuild
|
|
(
|
|
"./generated/AndroidX.sln",
|
|
new DotNetBuildSettings
|
|
{
|
|
MSBuildSettings = settings
|
|
}
|
|
);
|
|
});
|
|
|
|
Task("libs-native")
|
|
.Does(() =>
|
|
{
|
|
string root = "./source/com.google.android.material/material.extensions/";
|
|
|
|
RunGradle(root, "build");
|
|
|
|
string outputDir = "./externals/com.xamarin.google.android.material.extensions/";
|
|
EnsureDirectoryExists(outputDir);
|
|
CleanDirectories(outputDir);
|
|
|
|
CopyFileToDirectory($"{root}/extensions-aar/build/outputs/aar/extensions-aar-release.aar", outputDir);
|
|
Unzip($"{outputDir}/extensions-aar-release.aar", outputDir);
|
|
});
|
|
|
|
Task("nuget")
|
|
.IsDependentOn("libs")
|
|
.Does(() =>
|
|
{
|
|
var settings = new DotNetMSBuildSettings()
|
|
.SetConfiguration(CONFIGURATION)
|
|
.SetMaxCpuCount(0)
|
|
.EnableBinaryLogger($"./output/nuget.{CONFIGURATION}.binlog")
|
|
.WithProperty("MigrationPackageVersion", MIGRATION_PACKAGE_VERSION)
|
|
.WithProperty("NoBuild", "true")
|
|
.WithProperty("PackageRequireLicenseAcceptance", "true")
|
|
.WithProperty("PackageOutputPath", MakeAbsolute ((DirectoryPath)"./output/").FullPath)
|
|
.WithTarget("Pack");
|
|
|
|
if (!string.IsNullOrEmpty(ANDROID_HOME))
|
|
settings.WithProperty("AndroidSdkDirectory", $"{ANDROID_HOME}");
|
|
|
|
DotNetBuild
|
|
(
|
|
"./generated/AndroidX.sln",
|
|
new DotNetBuildSettings
|
|
{
|
|
MSBuildSettings = settings
|
|
}
|
|
);
|
|
});
|
|
|
|
Task("samples-generate-all-targets")
|
|
.Does(() =>
|
|
{
|
|
// 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").OrderBy(fp => fp.FullPath)) {
|
|
Information($"NuGet package = {nupkg}");
|
|
|
|
// Skip Wear as it has special implications requiring more packages to be used properly in an app
|
|
if (nupkg.FullPath.Contains(".Wear."))
|
|
continue;
|
|
// Skip the migration packages as that is not meant forto be used here
|
|
if (nupkg.FullPath.Contains("Xamarin.AndroidX.Migration"))
|
|
continue;
|
|
// Skip Guava.ListenableFuture as it cannot be used in the same project as Guava itself
|
|
if (nupkg.FullPath.Contains("Xamarin.Google.Guava.ListenableFuture"))
|
|
continue;
|
|
// Skip XBD because packages do not automatically reference the in-tree version
|
|
if (nupkg.FullPath.Contains("Xamarin.Build.Download"))
|
|
continue;
|
|
// Skip Binderator because it is not a binding package
|
|
if (nupkg.FullPath.Contains("Xamarin.AndroidBinderator"))
|
|
continue;
|
|
// skip because of multiple classes
|
|
if
|
|
(
|
|
nupkg.FullPath.Contains("Xamarin.AndroidX.DataStore.")
|
|
&&
|
|
( nupkg.FullPath.Contains(".Jvm") || nupkg.FullPath.Contains(".Android") )
|
|
)
|
|
continue;
|
|
|
|
var filename = nupkg.GetFilenameWithoutExtension();
|
|
var match = Regex.Match(filename.ToString(), @"(.+?)\.(\d+[\.0-9\-a-zA-Z]+)");
|
|
|
|
if ( match.Groups[1].Value == "Xamarin.AndroidX.Security.SecurityCrypto" )
|
|
{
|
|
// MAUI uses pinned/locked/exact preview version 1.1.0-alpha03 - skipit
|
|
continue;
|
|
}
|
|
|
|
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");
|
|
|
|
// ... and Directory.packages.props for central package management
|
|
//
|
|
string content_original = System.IO.File.ReadAllText("./output/AllPackages.targets");
|
|
string content_new = content_original.Replace("PackageReference", "PackageVersion");
|
|
System.IO.File.WriteAllText("./output/Directory.packages.props", content_new);
|
|
});
|
|
|
|
Task("samples-dotnet")
|
|
.IsDependentOn("nuget")
|
|
.IsDependentOn("samples-only-dotnet");
|
|
|
|
Task("samples-only-dotnet")
|
|
.IsDependentOn("samples-generate-all-targets")
|
|
.Does(() =>
|
|
{
|
|
// clear the packages folder so we always use the latest
|
|
var packagesPath = MakeAbsolute((DirectoryPath)"./samples/packages-dotnet").FullPath;
|
|
EnsureDirectoryExists(packagesPath);
|
|
CleanDirectories(packagesPath);
|
|
|
|
var settings = new DotNetMSBuildSettings()
|
|
.SetConfiguration("Debug") // We don't need to run linking
|
|
.WithProperty("Verbosity", VERBOSITY.ToString())
|
|
.WithProperty("RestorePackagesPath", packagesPath)
|
|
.WithProperty("AndroidSdkBuildToolsVersion", $"{AndroidSdkBuildTools}");
|
|
|
|
if (!string.IsNullOrEmpty(ANDROID_HOME))
|
|
settings.WithProperty("AndroidSdkDirectory", $"{ANDROID_HOME}");
|
|
|
|
string[] solutions = new string[]
|
|
{
|
|
"./samples/dotnet/BuildAllDotNet.sln",
|
|
"./samples/dotnet/BuildAllMauiApp.sln",
|
|
};
|
|
|
|
foreach(string solution in solutions)
|
|
{
|
|
FilePath fp_solution = new FilePath(solution);
|
|
string filename = fp_solution.GetFilenameWithoutExtension().ToString();
|
|
Information($"=====================================================================================================");
|
|
Information($"DotNetBuild {solution} / {filename}");
|
|
DotNetBuild(solution, new DotNetBuildSettings
|
|
{
|
|
MSBuildSettings = settings.EnableBinaryLogger($"./output/samples-dotnet-dotnet-msbuild-{filename}.binlog")
|
|
});
|
|
}
|
|
});
|
|
|
|
Task("tools-executive-order")
|
|
.Does
|
|
(
|
|
() =>
|
|
{
|
|
CakeExecuteScript
|
|
(
|
|
"./utilities.cake",
|
|
new CakeSettings
|
|
{
|
|
Arguments = new Dictionary<string, string>()
|
|
{
|
|
{ "target", "tools-executive-order" }
|
|
}
|
|
}
|
|
);
|
|
}
|
|
);
|
|
|
|
Task("api-diff")
|
|
.Does
|
|
(
|
|
() =>
|
|
{ /*
|
|
// https://github.com/Redth/Cake.MonoApiTools/
|
|
MonoApiDiff(API_INFO_OLD_MIGRATED, API_INFO_NEW, "./output/api-info-diff.xml");
|
|
string[] lines_xml = FileReadLines("./output/api-info-diff.xml");
|
|
List<string> lines_xml_new = new List<string>();
|
|
foreach(string line in lines_xml)
|
|
{
|
|
if (line.Contains(@"Java.Interop.IJavaPeerable"))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
lines_xml_new.Add(line);
|
|
}
|
|
FileWriteLines("./output/api-info-diff.cleaned.xml", lines_xml_new.ToArray());
|
|
|
|
|
|
MonoApiHtmlColorized(API_INFO_OLD_MIGRATED, API_INFO_NEW, "./output/api-info-diff.html");
|
|
string[] lines_html = FileReadLines("./output/api-info-diff.html");
|
|
|
|
List<string> lines_html_new = new List<string>();
|
|
List<(string Class, string ClassFullyQualified)> removed_types = new List<(string Class, string ClassFullyQualified)>();
|
|
List<(string Class, string ClassFullyQualified)> new_types = new List<(string Class, string ClassFullyQualified)>();
|
|
|
|
foreach(string line in lines_html)
|
|
{
|
|
if (line.Contains(@"Java.Interop.IJavaPeerable"))
|
|
{
|
|
continue;
|
|
}
|
|
if (line.Contains("<h3>Removed Type <span class='breaking' data-is-breaking>"))
|
|
{
|
|
string t = line.Replace("<h3>Removed Type <span class='breaking' data-is-breaking>", "");
|
|
t = t.Replace("</span></h3>",",");
|
|
t = Regex.Replace(t, ",</div> <!-- (.*?) -->", "");
|
|
t = Regex.Replace(t, ",<div> <!-- (.*?) -->", "");
|
|
string[] types = t.Split( new string[] { "," }, StringSplitOptions.RemoveEmptyEntries );
|
|
foreach(string t1 in types)
|
|
{
|
|
string c = t1.Substring(t1.LastIndexOf(".") + 1);
|
|
removed_types.Add((Class: c, ClassFullyQualified: t1));
|
|
}
|
|
}
|
|
if (line.Contains("<h3>New Type "))
|
|
{
|
|
string t = line.Replace("<h3>New Type ", "");
|
|
t = t.Replace("</h3>", "");
|
|
Information($"{t}");
|
|
string c = t.Substring(t.LastIndexOf(".") + 1);
|
|
new_types.Add((Class: c, ClassFullyQualified:t));
|
|
}
|
|
lines_html_new.Add(line);
|
|
}
|
|
|
|
FileWriteLines("./output/api-info-diff.cleaned.html", lines_html_new.ToArray());
|
|
FileWriteLines("./output/removed-types.csv", removed_types.Select(i => $"{i.Class},{i.ClassFullyQualified}").ToArray());
|
|
FileWriteLines("./output/new-types.csv", new_types.Select(i => $"{i.Class},{i.ClassFullyQualified}").ToArray());
|
|
|
|
List<int> indices_new = new List<int>();
|
|
List<int> indices_removed = new List<int>();
|
|
List<string> moved_types = new List<string>();
|
|
moved_types.Add($"# Class,ClassFullyQualified Removed, ClassFullyQualified New");
|
|
|
|
for( int idx1 = 0; idx1 < removed_types.Count; idx1++)
|
|
{
|
|
(string Class, string ClassFullyQualified) tr = removed_types[idx1];
|
|
int idx2 = new_types.FindIndex(tn => tn.Class == tr.Class);
|
|
if (idx2 < 0)
|
|
{
|
|
continue;
|
|
}
|
|
indices_removed.Add(idx1);
|
|
indices_new.Add(idx2);
|
|
string c = removed_types[idx1].Class;
|
|
string cr_fq = removed_types[idx1].ClassFullyQualified;
|
|
string cn_fq = new_types[idx2].ClassFullyQualified;
|
|
moved_types.Add($"{c},{cr_fq},{cn_fq}");
|
|
}
|
|
|
|
var indices_new_sorted = indices_new.OrderByDescending(t => t);
|
|
for (int i = 0; i < indices_new_sorted.Count(); i++)
|
|
{
|
|
new_types.RemoveAt(indices_new_sorted.ElementAt(i));
|
|
}
|
|
var indices_removed_sorted = indices_removed.OrderByDescending(t => t);
|
|
for (int i = 0; i < indices_removed_sorted.Count(); i++)
|
|
{
|
|
removed_types.RemoveAt(indices_removed_sorted.ElementAt(i));
|
|
}
|
|
|
|
FileWriteLines("./output/removed-types.final.csv", removed_types.Select(i => $"{i.Class},{i.ClassFullyQualified}").ToArray());
|
|
FileWriteLines("./output/new-types.final.csv", new_types.Select(i => $"{i.Class},{i.ClassFullyQualified}").ToArray());
|
|
FileWriteLines("./output/moved-types.final.csv", moved_types.ToArray());
|
|
|
|
return;
|
|
*/
|
|
}
|
|
);
|
|
|
|
var MONODROID_BASE_PATH = (DirectoryPath)"/Library/Frameworks/Xamarin.Android.framework/Versions/Current/lib/xbuild-frameworks/MonoAndroid/";
|
|
if (IsRunningOnWindows ()) {
|
|
var vsInstallPath = VSWhereLatest (new VSWhereLatestSettings { Requires = "Component.Xamarin", IncludePrerelease = true });
|
|
MONODROID_BASE_PATH = vsInstallPath.Combine ("Common7/IDE/ReferenceAssemblies/Microsoft/Framework/MonoAndroid/");
|
|
}
|
|
var MONODROID_PATH = MONODROID_BASE_PATH.Combine(ANDROID_SDK_VERSION);
|
|
|
|
Task ("diff")
|
|
.Does (() =>
|
|
{
|
|
var SEARCH_DIRS = new DirectoryPath [] {
|
|
MONODROID_BASE_PATH.Combine("v1.0"),
|
|
MONODROID_PATH,
|
|
};
|
|
|
|
EnsureDirectoryExists("./output/");
|
|
MonoApiInfo ("./output/AndroidX.Merged.dll", "./output/api-info.xml", new MonoApiInfoToolSettings {
|
|
SearchPaths = SEARCH_DIRS
|
|
});
|
|
|
|
//DownloadFile (BASE_API_INFO_URL, "./output/api-info.previous.xml");
|
|
|
|
// Now diff against current released api info
|
|
MonoApiDiff ("./output/api-info.previous.xml", "./output/api-info.xml", "./output/api-diff.xml");
|
|
|
|
// Now let's make pretty files
|
|
MonoApiHtml ("./output/api-info.previous.xml", "./output/api-info.xml", "./output/api-diff.html");
|
|
MonoApiMarkdown ("./output/api-info.previous.xml", "./output/api-info.xml", "./output/api-diff.md");
|
|
});
|
|
|
|
Task ("clean")
|
|
.Does (() =>
|
|
{
|
|
if (DirectoryExists ("./externals"))
|
|
DeleteDirectory ("./externals", new DeleteDirectorySettings { Recursive = true, Force = true });
|
|
|
|
if (DirectoryExists ("./generated"))
|
|
DeleteDirectory ("./generated", new DeleteDirectorySettings { Recursive = true, Force = true });
|
|
|
|
CleanDirectories ("./**/packages");
|
|
});
|
|
|
|
Task ("packages")
|
|
.IsDependentOn ("binderate")
|
|
.IsDependentOn ("nuget");
|
|
|
|
Task ("full-run")
|
|
.IsDependentOn ("binderate")
|
|
.IsDependentOn ("nuget")
|
|
.IsDependentOn ("samples-dotnet")
|
|
.IsDependentOn ("tools-executive-order")
|
|
;
|
|
|
|
Task ("ci")
|
|
.IsDependentOn ("ci-build")
|
|
.IsDependentOn ("ci-samples")
|
|
;
|
|
|
|
// Builds packages but does not run samples
|
|
Task ("ci-build")
|
|
.IsDependentOn ("check-tools")
|
|
.IsDependentOn ("inject-variables")
|
|
.IsDependentOn ("binderate")
|
|
.IsDependentOn ("nuget")
|
|
.IsDependentOn ("tools-executive-order")
|
|
;
|
|
|
|
// Runs samples without building packages
|
|
Task ("ci-samples")
|
|
.IsDependentOn ("samples-only-dotnet")
|
|
;
|
|
|
|
// for local builds, conditionally do the first binderate
|
|
if (FileExists ("./generated/AndroidX.sln")) {
|
|
Task ("Default")
|
|
.IsDependentOn ("nuget");
|
|
} else {
|
|
Task ("Default")
|
|
.IsDependentOn ("binderate")
|
|
.IsDependentOn ("nuget");
|
|
}
|
|
|
|
RunTarget (TARGET);
|