Added a tool to merge the assemblies and generate the map

This commit is contained in:
Matthew Leibowitz 2019-03-08 18:08:16 +02:00
Родитель 6aa085069d
Коммит ecb34ce1a5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 3650EBE4AA155AF9
15 изменённых файлов: 3254 добавлений и 19 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -9,6 +9,7 @@ docs/
generated/
**/scriptcs_packages/
tmp/
util/binderator/
*.xam
*.DS_Store
@ -33,5 +34,3 @@ Details.md
*.commit
cake.sh
**/.mfractor/**
util/

Просмотреть файл

@ -1,7 +1,5 @@
// Tools needed by cake addins
#tool nuget:?package=ILRepack&version=2.0.13
#tool nuget:?package=Cake.MonoApiTools&version=3.0.1
//#tool nuget:?package=Microsoft.DotNet.BuildTools.GenAPI&version=1.0.0-beta-00081
#tool nuget:?package=vswhere
// Cake Addins
@ -46,6 +44,8 @@ if (IsRunningOnWindows ()) {
}
var MONODROID_PATH = MONODROID_BASE_PATH.Combine(ANDROID_SDK_VERSION);
var ANDROIDX_MAPPER_EXE = $"util/AndroidXMapper/AndroidXMapper/bin/{BUILD_CONFIG}/net47/AndroidXMapper.exe";
Information ("MONODROID_BASE_PATH: {0}", MONODROID_BASE_PATH);
Information ("MONODROID_PATH: {0}", MONODROID_PATH);
@ -160,8 +160,6 @@ Task("samples")
});
});
Task("nuget-fat");
Task("nuget-validation")
.Does(() =>
{
@ -202,6 +200,18 @@ Task("nuget-validation")
});
Task ("androidxmapper")
.Does (() =>
{
MSBuild (
"./util/AndroidXMapper/AndroidXMapper.sln", c => {
c.Configuration = BUILD_CONFIG;
c.MaxCpuCount = 0;
c.Verbosity = VERBOSITY;
c.Restore = true;
});
});
Task ("diff")
.IsDependentOn ("merge")
.Does (() =>
@ -225,15 +235,29 @@ Task ("diff")
MonoApiMarkdown ("./output/api-info.previous.xml", "./output/api-info.xml", "./output/api-diff.md");
});
Task ("generate-mapping")
.IsDependentOn ("androidxmapper")
.IsDependentOn ("merge")
.Does (() =>
{
DownloadFile (BASE_API_INFO_URL, "./output/api-info.previous.xml");
StartProcess(ANDROIDX_MAPPER_EXE,
$"generate -v " +
$" -s output/api-info.previous.xml " +
$" -x output/api-info.xml " +
$" -j util/AndroidXMapper/Resources/androidx-class-mapping.csv " +
$" -m util/AndroidXMapper/Resources/override-mapping.csv " +
$" -o output/androidx-mapping.csv");
});
Task ("merge")
.IsDependentOn ("androidxmapper")
.IsDependentOn ("libs")
.Does (() =>
{
EnsureDirectoryExists("./output/");
if (FileExists ("./output/AndroidX.Merged.dll"))
DeleteFile ("./output/AndroidX.Merged.dll");
var allDlls = GetFiles ($"./generated/*/bin/{BUILD_CONFIG}/{TF_MONIKER}/Xamarin.*.dll");
var mergeDlls = allDlls
@ -241,16 +265,12 @@ Task ("merge")
.Select(g => g.FirstOrDefault())
.ToList();
Information("Merging: \n - {0}", string.Join("\n - ", mergeDlls));
ILRepack ("./output/AndroidX.Merged.dll", mergeDlls.First(), mergeDlls.Skip(1), new ILRepackSettings {
CopyAttrs = true,
AllowMultiple = true,
//TargetKind = ILRepack.TargetKind.Dll,
Libs = new List<DirectoryPath> {
MONODROID_PATH
},
});
StartProcess(ANDROIDX_MAPPER_EXE,
$"merge" +
$" -a {string.Join(" -a ", mergeDlls)} " +
$" -o output/AndroidX.Merged.dll " +
$" -s \"{MONODROID_PATH}\" " +
$" --inject-assemblyname");
});
Task ("ci-setup")
@ -301,6 +321,7 @@ Task ("ci")
.IsDependentOn ("binderate")
.IsDependentOn ("nuget")
.IsDependentOn ("nuget-validation")
.IsDependentOn ("generate-mapping")
.IsDependentOn ("diff")
.IsDependentOn ("samples");

288
util/AndroidXMapper/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,288 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
## Other
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint
## Obj-C/Swift specific
*.hmap
*.ipa
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
fastlane/report.xml
fastlane/screenshots
.vscode/

Просмотреть файл

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28606.126
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidXMapper", "AndroidXMapper\AndroidXMapper.csproj", "{FC5A597E-B645-4F7A-994B-639787F92FA0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FC5A597E-B645-4F7A-994B-639787F92FA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC5A597E-B645-4F7A-994B-639787F92FA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC5A597E-B645-4F7A-994B-639787F92FA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC5A597E-B645-4F7A-994B-639787F92FA0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6B1166B4-0102-495F-B720-E755FA917EC8}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net47</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ILRepack.Lib" Version="2.0.16" />
<PackageReference Include="Mono.Cecil" Version="0.10.3" />
<PackageReference Include="Mono.Options" Version="5.3.0.1" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,198 @@
using ILRepacking;
using Mono.Cecil;
using Mono.Cecil.Cil;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace AndroidXMapper
{
public class TestAttribute : Attribute
{
private readonly string assemblyName;
public TestAttribute(string assemblyName)
{
this.assemblyName = assemblyName;
}
public string AssemblyName => assemblyName;
}
[TestAttribute("the anme")]
public class AssemblyMerger
{
private const string InjectedAttributeNamespace = "Xamarin.AndroidX.Internal";
private const string InjectedAttributeTypeName = "InjectedAssemblyNameAttribute";
public AssemblyMerger(List<string> assemblies, List<string> searchDirectories, bool injectAssemblyNames)
{
Assemblies = assemblies ?? throw new ArgumentNullException(nameof(assemblies));
SearchDirectories = searchDirectories ?? new List<string>();
InjectAssemblyNames = injectAssemblyNames;
}
public List<string> Assemblies { get; }
public List<string> SearchDirectories { get; }
public bool InjectAssemblyNames { get; }
public void Merge(string outputPath)
{
var assemblies = Assemblies;
if (Program.Verbose)
{
Console.WriteLine("Merging:");
foreach (var include in assemblies)
Console.WriteLine($" - {include}");
}
var tempRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
if (InjectAssemblyNames)
{
assemblies = assemblies.ToList();
if (!Directory.Exists(tempRoot))
Directory.CreateDirectory(tempRoot);
for (int i = 0; i < assemblies.Count; i++)
{
var ass = assemblies[i];
var temp = Path.Combine(tempRoot, Guid.NewGuid().ToString() + ".dll");
InjectAssemblyName(ass, temp);
assemblies[i] = temp;
}
if (Program.Verbose)
{
Console.WriteLine("Temporary assemblies:");
foreach (var include in assemblies)
Console.WriteLine($" - {include}");
}
}
var options = new RepackOptions
{
InputAssemblies = assemblies.ToArray(),
OutputFile = outputPath,
SearchDirectories = SearchDirectories.ToArray(),
CopyAttributes = true,
AllowMultipleAssemblyLevelAttributes = true,
LogVerbose = Program.Verbose
};
var repacker = new ILRepack(options);
repacker.Repack();
if (InjectAssemblyNames)
{
MergeAssemblyNameAttributes(outputPath);
if (Directory.Exists(tempRoot))
Directory.Delete(tempRoot, true);
}
}
private void InjectAssemblyName(string assemblyPath, string outputPath)
{
var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
using (var assembly = AssemblyDefinition.ReadAssembly(assemblyPath))
{
var module = assembly.MainModule;
var mscorlibName = module.AssemblyReferences.FirstOrDefault(a => a.Name == "mscorlib");
var mscorlib = module.AssemblyResolver.Resolve(mscorlibName);
var attributeType = mscorlib.MainModule.GetType("System.Attribute");
var baseCtor = attributeType.Methods.FirstOrDefault(m => m.Name == ".ctor");
var iana = new TypeDefinition(InjectedAttributeNamespace, InjectedAttributeTypeName, TypeAttributes.Class);
iana.BaseType = module.ImportReference(attributeType);
var field = new FieldDefinition("assemblyName", FieldAttributes.Private | FieldAttributes.InitOnly, module.TypeSystem.String);
var getterAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName;
var getter = new MethodDefinition("get_AssemblyName", getterAttributes, module.TypeSystem.String);
getter.DeclaringType = iana;
getter.HasThis = true;
getter.IsGetter = true;
getter.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
getter.Body.Instructions.Add(Instruction.Create(OpCodes.Ldfld, field));
getter.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
var property = new PropertyDefinition("AssemblyName", PropertyAttributes.None, module.TypeSystem.String);
property.HasThis = true;
property.GetMethod = getter;
var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
var ctor = new MethodDefinition(".ctor", methodAttributes, module.TypeSystem.Void);
var param = new ParameterDefinition("assemblyName", ParameterAttributes.None, module.TypeSystem.String);
ctor.Parameters.Add(param);
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, module.ImportReference(baseCtor)));
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Nop));
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Nop));
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_1));
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Stfld, field));
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
iana.Fields.Add(field);
iana.Properties.Add(property);
iana.Methods.Add(ctor);
iana.Methods.Add(getter);
module.Types.Add(iana);
foreach (var type in module.Types)
{
type.CustomAttributes.Add(new CustomAttribute(ctor)
{
ConstructorArguments = { new CustomAttributeArgument(module.TypeSystem.String, assemblyName) }
});
}
assembly.Write(outputPath);
}
}
private void MergeAssemblyNameAttributes(string assemblyPath)
{
using (var assembly = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters { ReadWrite = true }))
{
var correct = assembly.MainModule.GetType(InjectedAttributeNamespace + "." + InjectedAttributeTypeName);
correct.Attributes |= TypeAttributes.Public;
correct.CustomAttributes.Clear();
foreach (var type in assembly.MainModule.Types.ToArray())
{
var attribute = type.CustomAttributes.FirstOrDefault(a => IsRandomType(a.AttributeType));
if (attribute != null && attribute.Constructor.DeclaringType != correct)
{
type.CustomAttributes.Add(new CustomAttribute(correct.Methods[0])
{
ConstructorArguments = { attribute.ConstructorArguments[0] }
});
type.CustomAttributes.Remove(attribute);
}
}
foreach (var type in assembly.MainModule.Types.Where(IsRandomType).ToArray())
{
assembly.MainModule.Types.Remove(type);
}
assembly.Write();
}
bool IsRandomType(TypeReference attr)
{
return
attr.Namespace == InjectedAttributeNamespace &&
attr.Name.EndsWith(InjectedAttributeTypeName) &&
attr.Name != InjectedAttributeTypeName;
}
}
}
}

Просмотреть файл

@ -0,0 +1,41 @@
using System.Collections.Generic;
namespace AndroidXMapper
{
public struct BindingType
{
public static BindingType Empty = new BindingType(FullType.Empty, FullType.Empty);
public FullType NetType;
public FullType JavaType;
public BindingType(FullType netType, FullType javaType)
{
NetType = netType;
JavaType = javaType;
}
public override bool Equals(object obj) =>
obj is BindingType other &&
EqualityComparer<FullType>.Default.Equals(NetType, other.NetType) &&
EqualityComparer<FullType>.Default.Equals(JavaType, other.JavaType);
public override int GetHashCode() =>
(NetType, JavaType).GetHashCode();
public override string ToString() =>
$"{NetType} ({JavaType})";
public void Deconstruct(out FullType netType, out FullType javaType)
{
netType = NetType;
javaType = JavaType;
}
public static implicit operator (FullType NetType, FullType JavaType) (BindingType value) =>
(value.NetType, value.JavaType);
public static implicit operator BindingType((FullType NetType, FullType JavaType) value) =>
new BindingType(value.NetType, value.JavaType);
}
}

Просмотреть файл

@ -0,0 +1,53 @@
namespace AndroidXMapper
{
public struct FullType
{
public static FullType Empty = new FullType(string.Empty, string.Empty, string.Empty);
public string Container;
public string Namespace;
public string Name;
public FullType(string ns, string n)
{
Container = string.Empty;
Namespace = ns;
Name = n;
}
public FullType(string container, string ns, string n)
{
Container = container;
Namespace = ns;
Name = n;
}
public string FullName =>
$"{Namespace}.{Name}";
public bool IsEmpty =>
Namespace == string.Empty || Name == string.Empty;
public override bool Equals(object obj) =>
obj is FullType other && Container == other.Container && Namespace == other.Namespace && Name == other.Name;
public override int GetHashCode() =>
(Container, Namespace, Name).GetHashCode();
public override string ToString() =>
FullName;
public void Deconstruct(out string c, out string ns, out string n)
{
c = Container;
ns = Namespace;
n = Name;
}
public static implicit operator (string Container, string Namespace, string Name) (FullType value) =>
(value.Container, value.Namespace, value.Name);
public static implicit operator FullType((string Container, string Namespace, string Name) value) =>
new FullType(value.Container, value.Namespace, value.Name);
}
}

Просмотреть файл

@ -0,0 +1,141 @@
using Mono.Options;
using System;
using System.Collections.Generic;
using System.IO;
namespace AndroidXMapper
{
public class GenerateCommand : Command
{
public GenerateCommand()
: base("generate", "Generates the mapping file.")
{
Options = new OptionSet
{
$"usage: {Program.Name} {Name} [OPTIONS]",
"",
Help,
"",
{ "s|support=", "The path to the merged Android.Support api-info.xml", v => AndroidSupportApi = v },
{ "x|androidx=", "The path to the merged AndroidX api-info.xml", v => AndroidXApi = v },
{ "j|java=", "The path to the Java mapping csv", v => JavaTypeMapping = v },
{ "m|override=", "The path to the mapping overides csv", v => OverrideMapping = v },
{ "o|output=", "The output path to use for the generated mapping", v => SetOutputPath(v) },
{ "exclude-warnings", "Include warnings in the output", v => ExcludeWarnings = v != null },
{ "?|h|help", "Show this message and exit", _ => ShowHelp = true },
};
}
private void SetOutputPath(string path)
{
if (string.IsNullOrWhiteSpace(path))
return;
if (path.EndsWith("/") || path.EndsWith("\\"))
path += "androidx-mapping.csv";
var dir = Path.GetDirectoryName(path);
if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);
OutputPath = path;
}
public bool ShowHelp { get; private set; }
public bool ExcludeWarnings { get; private set; }
public string AndroidSupportApi { get; private set; }
public string AndroidXApi { get; private set; }
public string JavaTypeMapping { get; private set; }
public string OverrideMapping { get; private set; }
public string OutputPath { get; private set; }
public override int Invoke(IEnumerable<string> args)
{
StreamWriter writer = null;
try
{
var extra = Options.Parse(args);
if (ShowHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
if (!ValidateArguments())
return 1;
var outputWriter = string.IsNullOrWhiteSpace(OutputPath)
? Console.Out
: (writer = new StreamWriter(OutputPath));
var generator = new MappingGenerator(AndroidSupportApi, AndroidXApi, OverrideMapping, JavaTypeMapping);
generator.Generate(outputWriter, !ExcludeWarnings);
return 0;
}
catch (Exception ex)
{
Console.Error.WriteLine($"{Program.Name}: An error occurred: `{ex.Message}`.");
if (Program.Verbose)
Console.Error.WriteLine(ex);
return 1;
}
finally
{
writer?.Dispose();
}
}
private bool ValidateArguments()
{
var hasError = false;
if (string.IsNullOrEmpty(AndroidSupportApi))
{
Console.Error.WriteLine($"{Program.Name}: Missing required argument `--support=PATH`.");
hasError = true;
}
else if (!File.Exists(AndroidSupportApi))
{
Console.Error.WriteLine($"{Program.Name}: File does not exist: `{AndroidSupportApi}`.");
hasError = true;
}
if (string.IsNullOrEmpty(AndroidXApi))
{
Console.Error.WriteLine($"{Program.Name}: Missing required argument `--androidx=PATH`.");
hasError = true;
}
else if (!File.Exists(AndroidXApi))
{
Console.Error.WriteLine($"{Program.Name}: File does not exist: `{AndroidXApi}`.");
hasError = true;
}
if (!string.IsNullOrEmpty(JavaTypeMapping) && !File.Exists(JavaTypeMapping))
{
Console.Error.WriteLine($"{Program.Name}: File does not exist: `{JavaTypeMapping}`.");
hasError = true;
}
if (!string.IsNullOrEmpty(OverrideMapping) && !File.Exists(OverrideMapping))
{
Console.Error.WriteLine($"{Program.Name}: File does not exist: `{OverrideMapping}`.");
hasError = true;
}
if (hasError)
Console.Error.WriteLine($"{Program.Name}: Use `{Program.Name} help {Name}` for details.");
return !hasError;
}
}
}

Просмотреть файл

@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace AndroidXMapper
{
public class MappingGenerator
{
private readonly Dictionary<BindingType, BindingType> typeMappings = new Dictionary<BindingType, BindingType>();
public string SupportApiPath { get; }
public string AndroidXApiPath { get; }
public string OverridesPath { get; }
public string JavaMappingPath { get; }
public MappingGenerator(string supportApiPath, string androidXApiPath, string overridesPath, string javaMappingPath)
{
SupportApiPath = supportApiPath ?? throw new ArgumentNullException(nameof(supportApiPath));
AndroidXApiPath = androidXApiPath ?? throw new ArgumentNullException(nameof(androidXApiPath));
OverridesPath = overridesPath;
JavaMappingPath = javaMappingPath;
}
public void Generate(TextWriter writer, bool includeWarnings)
{
var supportTypes = GetAllTypes(SupportApiPath);
var xTypes = GetAllTypes(AndroidXApiPath);
var overrideMappings = LoadMapping(OverridesPath);
var javaMappings = LoadMapping(JavaMappingPath);
const string Prefix = ",,,,,,,,,";
writer.WriteLine(
"Support .NET namespace," +
"Support .NET type name," +
"AndroidX .NET namespace," +
"AndroidX .NET type name," +
"AndroidX .NET assembly," +
"Support Java package," +
"Support Java class," +
"AndroidX Java package," +
"AndroidX Java class," +
"Messages");
foreach (var supportType in supportTypes)
{
var useJavaType = !supportType.JavaType.IsEmpty && javaMappings.Count > 0;
if (TryGetMapping(overrideMappings, supportType.NetType, out var overrideType))
{
var matched = xTypes.Where(t => t.NetType.FullName == overrideType).ToList();
if (matched.Count == 1)
{
typeMappings[supportType] = matched[0];
}
else if (matched.Count > 1)
{
if (includeWarnings)
writer.WriteLine($"{Prefix}WARNING: Too many override types found for type {overrideType}: {string.Join(", ", matched)}.");
}
else
{
if (includeWarnings)
writer.WriteLine($"{Prefix}WARNING: Unable to find override type for type {overrideType}.");
}
}
else if (TryGetExactMatch(xTypes, supportType, out var exactMatch))
{
typeMappings[supportType] = exactMatch;
}
else if (useJavaType && TryGetMapping(javaMappings, supportType.JavaType, out var androidx))
{
var matched = xTypes.Where(t => t.JavaType.FullName == androidx).ToList();
// a special case for the XxxConsts types
const string ConstsSuffix = "Consts";
if (matched.Count == 2 && matched.Any(m => m.NetType.Name.EndsWith(ConstsSuffix)))
{
matched.RemoveAll(m => m.NetType.Name.EndsWith(ConstsSuffix) != supportType.NetType.Name.EndsWith(ConstsSuffix));
}
if (matched.Count == 1)
{
typeMappings[supportType] = matched[0];
}
else if (matched.Count > 1)
{
if (includeWarnings)
writer.WriteLine($"{Prefix}WARNING: Too many AndroidX types found for Java type {androidx}: {string.Join(", ", matched)}.");
}
else
{
if (includeWarnings)
writer.WriteLine($"{Prefix}WARNING: Unable to find AndroidX type for Java type {androidx}.");
}
}
else
{
if (includeWarnings && useJavaType)
writer.WriteLine($"{Prefix}WARNING: Unable to find a Java mapping for {supportType}. Trying managed mapping...");
var matched = xTypes.Where(xt => xt.NetType.Name == supportType.NetType.Name).ToList();
if (matched.Count == 1)
{
typeMappings[supportType] = matched[0];
if (includeWarnings && useJavaType)
writer.WriteLine($"{Prefix}WARNING: Found a type that appears to match {matched[0]}.");
}
else if (matched.Count > 1)
{
if (includeWarnings)
writer.WriteLine($"{Prefix}WARNING: Too many AndroidX types found for .NET type {supportType.NetType}: {string.Join(", ", matched)}.");
}
else
{
if (includeWarnings)
writer.WriteLine($"{Prefix}WARNING: Unable to find AndroidX type for .NET type {supportType.NetType}.");
}
}
if (typeMappings.TryGetValue(supportType, out var androidXType))
{
writer.WriteLine(
$"{supportType.NetType.Namespace}," +
$"{supportType.NetType.Name}," +
$"{androidXType.NetType.Namespace}," +
$"{androidXType.NetType.Name}," +
$"{androidXType.NetType.Container}," +
$"{supportType.JavaType.Namespace}," +
$"{supportType.JavaType.Name}," +
$"{androidXType.JavaType.Namespace}," +
$"{androidXType.JavaType.Name},");
}
}
}
private bool TryGetExactMatch(IEnumerable<BindingType> xTypes, BindingType supportType, out BindingType exactMatch)
{
var netMatches = xTypes.Where(t => t.NetType.FullName == supportType.NetType.FullName).ToList();
if (netMatches.Count == 1)
{
exactMatch = netMatches[0];
return true;
}
var javaMatches = xTypes.Where(t => t.JavaType.FullName == supportType.JavaType.FullName).ToList();
if (javaMatches.Count == 1)
{
exactMatch = javaMatches[0];
return true;
}
exactMatch = BindingType.Empty;
return false;
}
private bool TryGetMapping(Dictionary<string, string> mappings, FullType type, out string androidx)
{
if (mappings.TryGetValue(type.FullName, out androidx))
return true;
string nested = "";
while (type.Name.Contains("."))
{
nested = type.Name.Substring(type.Name.LastIndexOf(".")) + nested;
type.Name = type.Name.Substring(0, type.Name.LastIndexOf("."));
if (mappings.TryGetValue(type.FullName, out androidx))
{
androidx += nested;
return true;
}
}
return false;
}
private Dictionary<string, string> LoadMapping(string mapping)
{
var dic = new Dictionary<string, string>();
if (!string.IsNullOrWhiteSpace(mapping) && File.Exists(mapping))
{
var lines = File.ReadAllLines(mapping);
foreach (var line in lines)
{
var parts = line.Split(',');
dic.Add(parts[0], parts[1]);
}
}
return dic;
}
private List<BindingType> GetAllTypes(string api)
{
if (string.IsNullOrWhiteSpace(api))
throw new ArgumentException($"Invalid api.xml path: {api}", nameof(api));
if (!File.Exists(api))
throw new FileNotFoundException($"The api.xml does not exist: {api}");
var xdoc = XDocument.Load(api);
var classes = xdoc.Descendants("class");
return classes.Select(GetFullType).ToList();
}
private BindingType GetFullType(XElement element)
{
var assembly = GetAttributeValue(element, "Xamarin.AndroidX.Internal.InjectedAssemblyNameAttribute", "AssemblyName");
var ns = "";
var name = element.Attribute("name").Value;
var java = GetJavaType(element);
var parent = element.Parent?.Parent;
while (parent != null)
{
if (parent.Name == "class")
{
name = parent.Attribute("name").Value + "." + name;
assembly = GetAttributeValue(parent, "Xamarin.AndroidX.Internal.InjectedAssemblyNameAttribute", "AssemblyName");
}
else if (parent.Name == "namespace")
{
ns = parent.Attribute("name").Value;
}
parent = parent.Parent?.Parent;
}
return new BindingType(new FullType(assembly, ns, name), java);
}
private static string GetAttributeValue(XElement element, string attributeType, string propertyName)
{
var attributeElement = element
?.Element("attributes")
?.Elements("attribute")
?.FirstOrDefault(e => e.Attribute("name")?.Value == attributeType);
var value = attributeElement
?.Element("properties")
?.Elements("property")
?.FirstOrDefault(e => e.Attribute("name")?.Value == propertyName)
?.Attribute("value")?.Value ?? string.Empty;
return value;
}
private FullType GetJavaType(XElement element)
{
var javaType = GetAttributeValue(element, "Android.Runtime.RegisterAttribute", "Name");
var parts = javaType?.Split('/');
var type = parts?.LastOrDefault()?.Split('$');
if (parts?.Length > 0 && type?.Length > 0)
return new FullType(string.Join(".", parts.Take(parts.Length - 1)), string.Join(".", type));
else
return FullType.Empty;
}
}
}

Просмотреть файл

@ -0,0 +1,113 @@
using Mono.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace AndroidXMapper
{
public class MergeCommand : Command
{
public MergeCommand()
: base("merge", "Merges the various AndroidX libraries.")
{
Options = new OptionSet
{
$"usage: {Program.Name} {Name} [OPTIONS]",
"",
Help,
"",
{ "a|assembly=", "One or more assemblies to merge", v => Assemblies.Add(v) },
{ "o|output=", "The output path to use for the merged assembly", v => SetOutputPath(v) },
{ "s|search=", "One or more search directories", v => SearchDirectories.Add(v) },
{ "inject-assemblyname", "Add the assembly names to the types", _ => InjectAssemblyNames = true },
{ "?|h|help", "Show this message and exit", _ => ShowHelp = true },
};
}
private void SetOutputPath(string path)
{
if (string.IsNullOrWhiteSpace(path))
return;
if (path.EndsWith("/") || path.EndsWith("\\"))
path += "AndroidX.Merged.dll";
var dir = Path.GetDirectoryName(path);
if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);
OutputPath = path;
}
public bool ShowHelp { get; private set; }
public List<string> Assemblies { get; } = new List<string>();
public string OutputPath { get; private set; }
public List<string> SearchDirectories { get; } = new List<string>();
public bool InjectAssemblyNames { get; private set; }
public override int Invoke(IEnumerable<string> args)
{
try
{
var extra = Options.Parse(args);
if (ShowHelp)
{
Options.WriteOptionDescriptions(CommandSet.Out);
return 0;
}
if (!ValidateArguments())
return 1;
var merger = new AssemblyMerger(Assemblies, SearchDirectories, InjectAssemblyNames);
merger.Merge(OutputPath);
return 0;
}
catch (Exception ex)
{
Console.Error.WriteLine($"{Program.Name}: An error occurred: `{ex.Message}`.");
if (Program.Verbose)
Console.Error.WriteLine(ex);
return 1;
}
}
private bool ValidateArguments()
{
var hasError = false;
if (string.IsNullOrWhiteSpace(OutputPath))
{
Console.Error.WriteLine($"{Program.Name}: An output path is required `--output=PATH`.");
hasError = true;
}
if (Assemblies.Count == 0)
{
Console.Error.WriteLine($"{Program.Name}: At least one assembly is required `--assembly=PATH`.");
hasError = true;
}
var missing = Assemblies.Where(i => !File.Exists(i));
if (missing.Any())
{
foreach (var file in missing)
Console.Error.WriteLine($"{Program.Name}: File does not exist: `{file}`.");
hasError = true;
}
if (hasError)
Console.Error.WriteLine($"{Program.Name}: Use `{Program.Name} help {Name}` for details.");
return !hasError;
}
}
}

Просмотреть файл

@ -0,0 +1,29 @@
using Mono.Options;
namespace AndroidXMapper
{
public class Program
{
public const string Name = "androidxmapper";
public static bool Verbose;
static int Main(string[] args)
{
var commands = new CommandSet(Name)
{
$"usage: {Name} COMMAND [OPTIONS]",
"",
"A utility that helps create the Android.Support to AndroidX mapping file.",
"",
"Global options:",
{ "v|verbose", "Use a more verbose output", _ => Verbose = true },
"",
"Available commands:",
new GenerateCommand(),
new MergeCommand(),
};
return commands.Run(args);
}
}
}

Просмотреть файл

@ -0,0 +1,104 @@
Old build artifact,AndroidX build artifact
android.arch.core:common,androidx.arch.core:core-common:2.0.0-rc01
android.arch.core:core,androidx.arch.core:core:2.0.0-rc01
android.arch.core:core-testing,androidx.arch.core:core-testing:2.0.0-rc01
android.arch.core:runtime,androidx.arch.core:core-runtime:2.0.0-rc01
android.arch.lifecycle:common,androidx.lifecycle:lifecycle-common:2.0.0-rc01
android.arch.lifecycle:common-java8,androidx.lifecycle:lifecycle-common-java8:2.0.0-rc01
android.arch.lifecycle:compiler,androidx.lifecycle:lifecycle-compiler:2.0.0-rc01
android.arch.lifecycle:extensions,androidx.lifecycle:lifecycle-extensions:2.0.0-rc01
android.arch.lifecycle:livedata,androidx.lifecycle:lifecycle-livedata:2.0.0-rc01
android.arch.lifecycle:livedata-core,androidx.lifecycle:lifecycle-livedata-core:2.0.0-rc01
android.arch.lifecycle:reactivestreams,androidx.lifecycle:lifecycle-reactivestreams:2.0.0-rc01
android.arch.lifecycle:runtime,androidx.lifecycle:lifecycle-runtime:2.0.0-rc01
android.arch.lifecycle:viewmodel,androidx.lifecycle:lifecycle-viewmodel:2.0.0-rc01
android.arch.paging:common,androidx.paging:paging-common:2.0.0-rc01
android.arch.paging:runtime,androidx.paging:paging-runtime:2.0.0-rc01
android.arch.paging:rxjava2,androidx.paging:paging-rxjava2:2.0.0-rc01
android.arch.persistence.room:common,androidx.room:room-common:2.0.0-rc01
android.arch.persistence.room:compiler,androidx.room:room-compiler:2.0.0-rc01
android.arch.persistence.room:guava,androidx.room:room-guava:2.0.0-rc01
android.arch.persistence.room:migration,androidx.room:room-migration:2.0.0-rc01
android.arch.persistence.room:runtime,androidx.room:room-runtime:2.0.0-rc01
android.arch.persistence.room:rxjava2,androidx.room:room-rxjava2:2.0.0-rc01
android.arch.persistence.room:testing,androidx.room:room-testing:2.0.0-rc01
android.arch.persistence:db,androidx.sqlite:sqlite:2.0.0-rc01
android.arch.persistence:db-framework,androidx.sqlite:sqlite-framework:2.0.0-rc01
com.android.support.constraint:constraint-layout,androidx.constraintlayout:constraintlayout:1.1.2
com.android.support.constraint:constraint-layout-solver,androidx.constraintlayout:constraintlayout-solver:1.1.2
com.android.support.test.espresso.idling:idling-concurrent,androidx.test.espresso.idling:idling-concurrent:3.1.0
com.android.support.test.espresso.idling:idling-net,androidx.test.espresso.idling:idling-net:3.1.0
com.android.support.test.espresso:espresso-accessibility,androidx.test.espresso:espresso-accessibility:3.1.0
com.android.support.test.espresso:espresso-contrib,androidx.test.espresso:espresso-contrib:3.1.0
com.android.support.test.espresso:espresso-core,androidx.test.espresso:espresso-core:3.1.0
com.android.support.test.espresso:espresso-idling-resource,androidx.test.espresso:espresso-idling-resource:3.1.0
com.android.support.test.espresso:espresso-intents,androidx.test.espresso:espresso-intents:3.1.0
com.android.support.test.espresso:espresso-remote,androidx.test.espresso:espresso-remote:3.1.0
com.android.support.test.espresso:espresso-web,androidx.test.espresso:espresso-web:3.1.0
com.android.support.test.janktesthelper:janktesthelper,androidx.test.jank:janktesthelper:1.0.1
com.android.support.test.services:test-services,androidx.test:test-services:1.1.0
com.android.support.test.uiautomator:uiautomator,androidx.test.uiautomator:uiautomator:2.2.0
com.android.support.test:monitor,androidx.test:monitor:1.1.0
com.android.support.test:orchestrator,androidx.test:orchestrator:1.1.0
com.android.support.test:rules,androidx.test:rules:1.1.0
com.android.support.test:runner,androidx.test:runner:1.1.0
com.android.support:animated-vector-drawable,androidx.vectordrawable:vectordrawable-animated:1.0.0
com.android.support:appcompat-v7,androidx.appcompat:appcompat:1.0.0
com.android.support:asynclayoutinflater,androidx.asynclayoutinflater:asynclayoutinflater:1.0.0
com.android.support:car,androidx.car:car:1.0.0-alpha5
com.android.support:cardview-v7,androidx.cardview:cardview:1.0.0
com.android.support:collections,androidx.collection:collection:1.0.0
com.android.support:coordinatorlayout,androidx.coordinatorlayout:coordinatorlayout:1.0.0
com.android.support:cursoradapter,androidx.cursoradapter:cursoradapter:1.0.0
com.android.support:customtabs,androidx.browser:browser:1.0.0
com.android.support:customview,androidx.customview:customview:1.0.0
com.android.support:design,com.google.android.material:material:1.0.0-rc01
com.android.support:documentfile,androidx.documentfile:documentfile:1.0.0
com.android.support:drawerlayout,androidx.drawerlayout:drawerlayout:1.0.0
com.android.support:exifinterface,androidx.exifinterface:exifinterface:1.0.0
com.android.support:gridlayout-v7,androidx.gridlayout:gridlayout:1.0.0
com.android.support:heifwriter,androidx.heifwriter:heifwriter:1.0.0
com.android.support:interpolator,androidx.interpolator:interpolator:1.0.0
com.android.support:leanback-v17,androidx.leanback:leanback:1.0.0
com.android.support:loader,androidx.loader:loader:1.0.0
com.android.support:localbroadcastmanager,androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
com.android.support:media2,androidx.media2:media2:1.0.0-alpha03
com.android.support:media2-exoplayer,androidx.media2:media2-exoplayer:1.0.0-alpha01
com.android.support:mediarouter-v7,androidx.mediarouter:mediarouter:1.0.0
com.android.support:multidex,androidx.multidex:multidex:2.0.0
com.android.support:multidex-instrumentation,androidx.multidex:multidex-instrumentation:2.0.0
com.android.support:palette-v7,androidx.palette:palette:1.0.0
com.android.support:percent,androidx.percentlayout:percentlayout:1.0.0
com.android.support:preference-leanback-v17,androidx.leanback:leanback-preference:1.0.0
com.android.support:preference-v14,androidx.legacy:legacy-preference-v14:1.0.0
com.android.support:preference-v7,androidx.preference:preference:1.0.0
com.android.support:print,androidx.print:print:1.0.0
com.android.support:recommendation,androidx.recommendation:recommendation:1.0.0
com.android.support:recyclerview-selection,androidx.recyclerview:recyclerview-selection:1.0.0
com.android.support:recyclerview-v7,androidx.recyclerview:recyclerview:1.0.0
com.android.support:slices-builders,androidx.slice:slice-builders:1.0.0
com.android.support:slices-core,androidx.slice:slice-core:1.0.0
com.android.support:slices-view,androidx.slice:slice-view:1.0.0
com.android.support:slidingpanelayout,androidx.slidingpanelayout:slidingpanelayout:1.0.0
com.android.support:support-annotations,androidx.annotation:annotation:1.0.0
com.android.support:support-compat,androidx.core:core:1.0.0
com.android.support:support-content,androidx.contentpager:contentpager:1.0.0
com.android.support:support-core-ui,androidx.legacy:legacy-support-core-ui:1.0.0
com.android.support:support-core-utils,androidx.legacy:legacy-support-core-utils:1.0.0
com.android.support:support-dynamic-animation,androidx.dynamicanimation:dynamicanimation:1.0.0
com.android.support:support-emoji,androidx.emoji:emoji:1.0.0
com.android.support:support-emoji-appcompat,androidx.emoji:emoji-appcompat:1.0.0
com.android.support:support-emoji-bundled,androidx.emoji:emoji-bundled:1.0.0
com.android.support:support-fragment,androidx.fragment:fragment:1.0.0
com.android.support:support-media-compat,androidx.media:media:1.0.0
com.android.support:support-tv-provider,androidx.tvprovider:tvprovider:1.0.0
com.android.support:support-v13,androidx.legacy:legacy-support-v13:1.0.0
com.android.support:support-v4,androidx.legacy:legacy-support-v4:1.0.0
com.android.support:support-vector-drawable,androidx.vectordrawable:vectordrawable:1.0.0
com.android.support:swiperefreshlayout,androidx.swiperefreshlayout:swiperefreshlayout:1.0.0
com.android.support:textclassifier,androidx.textclassifier:textclassifier:1.0.0
com.android.support:transition,androidx.transition:transition:1.0.0
com.android.support:versionedparcelable,androidx.versionedparcelable:versionedparcelable:1.0.0
com.android.support:viewpager,androidx.viewpager:viewpager:1.0.0
com.android.support:wear,androidx.wear:wear:1.0.0
com.android.support:webkit,androidx.webkit:webkit:1.0.0
1 Old build artifact AndroidX build artifact
2 android.arch.core:common androidx.arch.core:core-common:2.0.0-rc01
3 android.arch.core:core androidx.arch.core:core:2.0.0-rc01
4 android.arch.core:core-testing androidx.arch.core:core-testing:2.0.0-rc01
5 android.arch.core:runtime androidx.arch.core:core-runtime:2.0.0-rc01
6 android.arch.lifecycle:common androidx.lifecycle:lifecycle-common:2.0.0-rc01
7 android.arch.lifecycle:common-java8 androidx.lifecycle:lifecycle-common-java8:2.0.0-rc01
8 android.arch.lifecycle:compiler androidx.lifecycle:lifecycle-compiler:2.0.0-rc01
9 android.arch.lifecycle:extensions androidx.lifecycle:lifecycle-extensions:2.0.0-rc01
10 android.arch.lifecycle:livedata androidx.lifecycle:lifecycle-livedata:2.0.0-rc01
11 android.arch.lifecycle:livedata-core androidx.lifecycle:lifecycle-livedata-core:2.0.0-rc01
12 android.arch.lifecycle:reactivestreams androidx.lifecycle:lifecycle-reactivestreams:2.0.0-rc01
13 android.arch.lifecycle:runtime androidx.lifecycle:lifecycle-runtime:2.0.0-rc01
14 android.arch.lifecycle:viewmodel androidx.lifecycle:lifecycle-viewmodel:2.0.0-rc01
15 android.arch.paging:common androidx.paging:paging-common:2.0.0-rc01
16 android.arch.paging:runtime androidx.paging:paging-runtime:2.0.0-rc01
17 android.arch.paging:rxjava2 androidx.paging:paging-rxjava2:2.0.0-rc01
18 android.arch.persistence.room:common androidx.room:room-common:2.0.0-rc01
19 android.arch.persistence.room:compiler androidx.room:room-compiler:2.0.0-rc01
20 android.arch.persistence.room:guava androidx.room:room-guava:2.0.0-rc01
21 android.arch.persistence.room:migration androidx.room:room-migration:2.0.0-rc01
22 android.arch.persistence.room:runtime androidx.room:room-runtime:2.0.0-rc01
23 android.arch.persistence.room:rxjava2 androidx.room:room-rxjava2:2.0.0-rc01
24 android.arch.persistence.room:testing androidx.room:room-testing:2.0.0-rc01
25 android.arch.persistence:db androidx.sqlite:sqlite:2.0.0-rc01
26 android.arch.persistence:db-framework androidx.sqlite:sqlite-framework:2.0.0-rc01
27 com.android.support.constraint:constraint-layout androidx.constraintlayout:constraintlayout:1.1.2
28 com.android.support.constraint:constraint-layout-solver androidx.constraintlayout:constraintlayout-solver:1.1.2
29 com.android.support.test.espresso.idling:idling-concurrent androidx.test.espresso.idling:idling-concurrent:3.1.0
30 com.android.support.test.espresso.idling:idling-net androidx.test.espresso.idling:idling-net:3.1.0
31 com.android.support.test.espresso:espresso-accessibility androidx.test.espresso:espresso-accessibility:3.1.0
32 com.android.support.test.espresso:espresso-contrib androidx.test.espresso:espresso-contrib:3.1.0
33 com.android.support.test.espresso:espresso-core androidx.test.espresso:espresso-core:3.1.0
34 com.android.support.test.espresso:espresso-idling-resource androidx.test.espresso:espresso-idling-resource:3.1.0
35 com.android.support.test.espresso:espresso-intents androidx.test.espresso:espresso-intents:3.1.0
36 com.android.support.test.espresso:espresso-remote androidx.test.espresso:espresso-remote:3.1.0
37 com.android.support.test.espresso:espresso-web androidx.test.espresso:espresso-web:3.1.0
38 com.android.support.test.janktesthelper:janktesthelper androidx.test.jank:janktesthelper:1.0.1
39 com.android.support.test.services:test-services androidx.test:test-services:1.1.0
40 com.android.support.test.uiautomator:uiautomator androidx.test.uiautomator:uiautomator:2.2.0
41 com.android.support.test:monitor androidx.test:monitor:1.1.0
42 com.android.support.test:orchestrator androidx.test:orchestrator:1.1.0
43 com.android.support.test:rules androidx.test:rules:1.1.0
44 com.android.support.test:runner androidx.test:runner:1.1.0
45 com.android.support:animated-vector-drawable androidx.vectordrawable:vectordrawable-animated:1.0.0
46 com.android.support:appcompat-v7 androidx.appcompat:appcompat:1.0.0
47 com.android.support:asynclayoutinflater androidx.asynclayoutinflater:asynclayoutinflater:1.0.0
48 com.android.support:car androidx.car:car:1.0.0-alpha5
49 com.android.support:cardview-v7 androidx.cardview:cardview:1.0.0
50 com.android.support:collections androidx.collection:collection:1.0.0
51 com.android.support:coordinatorlayout androidx.coordinatorlayout:coordinatorlayout:1.0.0
52 com.android.support:cursoradapter androidx.cursoradapter:cursoradapter:1.0.0
53 com.android.support:customtabs androidx.browser:browser:1.0.0
54 com.android.support:customview androidx.customview:customview:1.0.0
55 com.android.support:design com.google.android.material:material:1.0.0-rc01
56 com.android.support:documentfile androidx.documentfile:documentfile:1.0.0
57 com.android.support:drawerlayout androidx.drawerlayout:drawerlayout:1.0.0
58 com.android.support:exifinterface androidx.exifinterface:exifinterface:1.0.0
59 com.android.support:gridlayout-v7 androidx.gridlayout:gridlayout:1.0.0
60 com.android.support:heifwriter androidx.heifwriter:heifwriter:1.0.0
61 com.android.support:interpolator androidx.interpolator:interpolator:1.0.0
62 com.android.support:leanback-v17 androidx.leanback:leanback:1.0.0
63 com.android.support:loader androidx.loader:loader:1.0.0
64 com.android.support:localbroadcastmanager androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
65 com.android.support:media2 androidx.media2:media2:1.0.0-alpha03
66 com.android.support:media2-exoplayer androidx.media2:media2-exoplayer:1.0.0-alpha01
67 com.android.support:mediarouter-v7 androidx.mediarouter:mediarouter:1.0.0
68 com.android.support:multidex androidx.multidex:multidex:2.0.0
69 com.android.support:multidex-instrumentation androidx.multidex:multidex-instrumentation:2.0.0
70 com.android.support:palette-v7 androidx.palette:palette:1.0.0
71 com.android.support:percent androidx.percentlayout:percentlayout:1.0.0
72 com.android.support:preference-leanback-v17 androidx.leanback:leanback-preference:1.0.0
73 com.android.support:preference-v14 androidx.legacy:legacy-preference-v14:1.0.0
74 com.android.support:preference-v7 androidx.preference:preference:1.0.0
75 com.android.support:print androidx.print:print:1.0.0
76 com.android.support:recommendation androidx.recommendation:recommendation:1.0.0
77 com.android.support:recyclerview-selection androidx.recyclerview:recyclerview-selection:1.0.0
78 com.android.support:recyclerview-v7 androidx.recyclerview:recyclerview:1.0.0
79 com.android.support:slices-builders androidx.slice:slice-builders:1.0.0
80 com.android.support:slices-core androidx.slice:slice-core:1.0.0
81 com.android.support:slices-view androidx.slice:slice-view:1.0.0
82 com.android.support:slidingpanelayout androidx.slidingpanelayout:slidingpanelayout:1.0.0
83 com.android.support:support-annotations androidx.annotation:annotation:1.0.0
84 com.android.support:support-compat androidx.core:core:1.0.0
85 com.android.support:support-content androidx.contentpager:contentpager:1.0.0
86 com.android.support:support-core-ui androidx.legacy:legacy-support-core-ui:1.0.0
87 com.android.support:support-core-utils androidx.legacy:legacy-support-core-utils:1.0.0
88 com.android.support:support-dynamic-animation androidx.dynamicanimation:dynamicanimation:1.0.0
89 com.android.support:support-emoji androidx.emoji:emoji:1.0.0
90 com.android.support:support-emoji-appcompat androidx.emoji:emoji-appcompat:1.0.0
91 com.android.support:support-emoji-bundled androidx.emoji:emoji-bundled:1.0.0
92 com.android.support:support-fragment androidx.fragment:fragment:1.0.0
93 com.android.support:support-media-compat androidx.media:media:1.0.0
94 com.android.support:support-tv-provider androidx.tvprovider:tvprovider:1.0.0
95 com.android.support:support-v13 androidx.legacy:legacy-support-v13:1.0.0
96 com.android.support:support-v4 androidx.legacy:legacy-support-v4:1.0.0
97 com.android.support:support-vector-drawable androidx.vectordrawable:vectordrawable:1.0.0
98 com.android.support:swiperefreshlayout androidx.swiperefreshlayout:swiperefreshlayout:1.0.0
99 com.android.support:textclassifier androidx.textclassifier:textclassifier:1.0.0
100 com.android.support:transition androidx.transition:transition:1.0.0
101 com.android.support:versionedparcelable androidx.versionedparcelable:versionedparcelable:1.0.0
102 com.android.support:viewpager androidx.viewpager:viewpager:1.0.0
103 com.android.support:wear androidx.wear:wear:1.0.0
104 com.android.support:webkit androidx.webkit:webkit:1.0.0

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,6 @@
Old type,AndroidX type
Android.Support.V4.Media.MediaSessionManager,AndroidX.Media.MediaSessionManager
Android.Support.V4.App.ActionBarDrawerToggle.IDelegate,AndroidX.Legacy.App.ActionBarDrawerToggle.IDelegate
Android.Support.V4.App.ActionBarDrawerToggle.IDelegateProvider,AndroidX.Legacy.App.ActionBarDrawerToggle.IDelegateProvider
Android.Support.V7.App.ActionBarDrawerToggle.IDelegate,AndroidX.AppCompat.App.ActionBarDrawerToggle.IDelegate
Android.Support.V7.App.ActionBarDrawerToggle.IDelegateProvider,AndroidX.AppCompat.App.ActionBarDrawerToggle.IDelegateProvider
1 Old type AndroidX type
2 Android.Support.V4.Media.MediaSessionManager AndroidX.Media.MediaSessionManager
3 Android.Support.V4.App.ActionBarDrawerToggle.IDelegate AndroidX.Legacy.App.ActionBarDrawerToggle.IDelegate
4 Android.Support.V4.App.ActionBarDrawerToggle.IDelegateProvider AndroidX.Legacy.App.ActionBarDrawerToggle.IDelegateProvider
5 Android.Support.V7.App.ActionBarDrawerToggle.IDelegate AndroidX.AppCompat.App.ActionBarDrawerToggle.IDelegate
6 Android.Support.V7.App.ActionBarDrawerToggle.IDelegateProvider AndroidX.AppCompat.App.ActionBarDrawerToggle.IDelegateProvider