Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 49 additions & 16 deletions external/Java.Interop/tools/class-parse/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ public static void Main (string[] args)
int verbosity = 0;
bool autorename = false;
var outputFile = (string) null;
var referenceOutputFile = (string) null;
string platform = null;
var docsPaths = new List<string> ();
var referenceFiles = new List<string> ();
var p = new OptionSet () {
"usage: class-dump [-dump] FILES [@RESPONSE-FILES]",
"",
Expand All @@ -37,6 +39,12 @@ public static void Main (string[] args)
{ "o=",
"Write output to {PATH}.",
v => outputFile = v },
{ "reference=",
"Reference .class or .jar {FILE}.",
v => referenceFiles.Add (v) },
{ "reference-output=",
"Write the reference API to {PATH}.",
v => referenceOutputFile = v },
{ "docspath=",
"Documentation {PATH} for parameter fixup",
doc => docsPaths.Add (doc) },
Expand Down Expand Up @@ -67,18 +75,32 @@ public static void Main (string[] args)
}
if (docsType)
Console.WriteLine ("class-parse: --docstype is obsolete and no longer a valid option.");
var output = outputFile == null
? Console.Out
: (TextWriter) new StreamWriter (outputFile, append: false, encoding: new UTF8Encoding (encoderShouldEmitUTF8Identifier: false));
Log.OnLog = (t, v, m, a) => {
Console.Error.WriteLine(m, a);
};
var globalClassPath = CreateClassPath (platform, docsPaths, autorename);
var globalClassPath = LoadClassPath (files, platform, docsPaths, autorename, dump, verbosity);
WriteOutput (globalClassPath, outputFile, dump);
if (referenceFiles.Count > 0) {
if (referenceOutputFile == null) {
Console.Error.WriteLine ("class-parse: --reference-output is required when using --reference.");
Environment.ExitCode = 1;
return;
}
var referenceClassPath = LoadClassPath (referenceFiles, platform, new List<string> (), autoRename: false, dump: false, verbosity: verbosity);
WriteOutput (referenceClassPath, referenceOutputFile, dump: false);
} else if (referenceOutputFile != null && File.Exists (referenceOutputFile)) {
File.Delete (referenceOutputFile);
}
}

static ClassPath LoadClassPath (IEnumerable<string> files, string platform, List<string> docsPaths, bool autoRename, bool dump, int verbosity)
{
var globalClassPath = CreateClassPath (platform, docsPaths, autoRename);
var classPaths = new List<ClassPath> ();
foreach (var file in files) {
try {
if (ClassPath.IsJmodFile (file) || ClassPath.IsJarFile (file)) {
var cp = CreateClassPath (platform, docsPaths, autorename);
var cp = CreateClassPath (platform, docsPaths, autoRename);
cp.Load (file);
classPaths.Add (cp);
continue;
Expand All @@ -102,20 +124,31 @@ public static void Main (string[] args)
foreach (var cp in classPaths) {
globalClassPath.Add (cp, removeModules: !dump);
}
if (!dump) {
globalClassPath.SaveXmlDescription (output);
} else {
bool first = true;
foreach (var c in globalClassPath.GetClassFiles ()) {
if (!first) {
output.WriteLine ();
return globalClassPath;
}

static void WriteOutput (ClassPath classPath, string outputFile, bool dump)
{
var output = outputFile == null
? Console.Out
: (TextWriter) new StreamWriter (outputFile, append: false, encoding: new UTF8Encoding (encoderShouldEmitUTF8Identifier: false));
try {
if (!dump) {
classPath.SaveXmlDescription (output);
} else {
bool first = true;
foreach (var c in classPath.GetClassFiles ()) {
if (!first) {
output.WriteLine ();
}
first = false;
DumpClassFile (c, output);
}
first = false;
DumpClassFile (c, output);
}
} finally {
if (outputFile != null)
output.Close ();
}
if (outputFile != null)
output.Close ();
}

static ClassPath CreateClassPath (string platform, List<string> docsPaths, bool autoRename)
Expand Down
13 changes: 12 additions & 1 deletion external/Java.Interop/tools/generator/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
// Resolve types using Java.Interop.Tools.JavaTypeSystem
if (is_classparse) {
var output_xml = api_xml_adjuster_output ?? Path.Combine (Path.GetDirectoryName (filename), Path.GetFileName (filename) + ".adjusted");
JavaTypeResolutionFixups.Fixup (filename, output_xml, resolver, references.Distinct ().ToArray (), resolverCache, options);
JavaTypeResolutionFixups.Fixup (filename, output_xml, resolver, references.Distinct ().ToArray (), options.JavaReferenceApiXml.ToArray (), resolverCache, options);

if (only_xml_adjuster)
return;
Expand All @@ -120,6 +120,17 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
apiXmlFile = filename;
}

foreach (var javaReference in options.JavaReferenceApiXml) {
var referenceApi = ApiXmlDocument.Load (javaReference, api_level, product_version);
if (referenceApi is null)
continue;
var referenceGens = XmlApiImporter.Parse (referenceApi.ApiDocument, opt);
if (referenceGens is null)
continue;
foreach (var referenceGen in referenceGens)
AddTypeToTable (opt, referenceGen);
}

foreach (var reference in references.Distinct ()) {
try {
Report.Verbose (0, "resolving assembly {0}.", reference);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public CodeGeneratorOptions ()
LibraryPaths = new Collection<string> ();
AnnotationsZipFiles = new Collection<string> ();
JavadocXmlFiles = new Collection<string> ();
JavaReferenceApiXml = new Collection<string> ();
}

public string ApiLevel {get; set;}
Expand All @@ -30,6 +31,7 @@ public CodeGeneratorOptions ()
public Collection<string> FixupFiles {get; private set;}
public Collection<string> LibraryPaths {get; private set;}
public Collection<string> JavadocXmlFiles {get; private set;}
public Collection<string> JavaReferenceApiXml {get; private set;}
public bool GlobalTypeNames {get; set;}
public bool OnlyBindPublicTypes {get; set;}
public string ApiDescriptionFile {get; set;}
Expand Down Expand Up @@ -100,6 +102,9 @@ public static CodeGeneratorOptions Parse (string[] args)
{ "r|ref=",
"{ASSEMBLY} to reference.",
v => opts.AssemblyReferences.Add (v) },
{ "java-reference=",
"Java API XML {FILE} containing reference-only types.",
v => opts.JavaReferenceApiXml.Add (v) },
{ "sdk-platform|api-level=",
"SDK Platform {VERSION}/API level.",
v => opts.ApiLevel = v },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@ public static class JavaTypeResolutionFixups

// This fixup ensures all referenced Java types can be resolved, and
// removes types and members that rely on unresolvable Java types.
public static void Fixup (string xmlFile, string outputXmlFile, DirectoryAssemblyResolver resolver, string [] references, TypeDefinitionCache cache, CodeGeneratorOptions opt)
public static void Fixup (string xmlFile, string outputXmlFile, DirectoryAssemblyResolver resolver, string [] references, string [] javaReferences, TypeDefinitionCache cache, CodeGeneratorOptions opt)
{
// Parse api.xml
var type_collection = JavaXmlApiImporter.Parse (xmlFile);
var options = new ApiImporterOptions ();

foreach (var javaReference in javaReferences) {
var referenceTypes = JavaXmlApiImporter.Parse (javaReference);
foreach (var type in referenceTypes.TypesFlattened.Values)
type_collection.AddReferencedType (type);
}

if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) {
options.SupportedTypeMapAttributes.Clear ();
options.SupportedTypeMapAttributes.Add ("Java.Interop.JniTypeSignatureAttribute");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ This item group populates the Build Action drop-down in IDEs.
<ItemGroup Condition=" '$(AndroidApplication)' != 'true' ">
<EmbeddedNativeLibrary Include="@(AndroidNativeLibrary)" />
<AndroidAarLibrary Include="@(AndroidLibrary)" Condition=" '%(AndroidLibrary.Extension)' == '.aar' and '%(AndroidLibrary.Bind)' != 'true' " />
<_AndroidReferenceLibraryProjectZip Include="@(AndroidLibrary)" Condition=" '%(AndroidLibrary.Extension)' == '.aar' and '%(AndroidLibrary.Bind)' != 'true' " />
<AndroidJavaLibrary Include="@(AndroidLibrary)" Condition=" '%(AndroidLibrary.Extension)' == '.jar' and '%(AndroidLibrary.Bind)' != 'true' " />
<ReferenceJar Include="@(AndroidLibrary)" Condition=" '%(AndroidLibrary.Extension)' == '.jar' and '%(AndroidLibrary.Bind)' != 'true' " />
<EmbeddedJar Include="@(AndroidLibrary)" Condition=" '%(AndroidLibrary.Extension)' == '.jar' and '%(AndroidLibrary.Bind)' == 'true' " />
<!-- .aar files should be copied to $(OutputPath) in .NET 6+ -->
<None Include="@(AndroidLibrary)" Condition=" '%(AndroidLibrary.Extension)' == '.aar' " TfmSpecificPackageFile="%(AndroidLibrary.Pack)" Pack="false" CopyToOutputDirectory="PreserveNewest" Link="%(Filename)%(Extension)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,26 @@ This file is only used by binding projects.

<UsingTask TaskName="Xamarin.Android.Tasks.ClassParse" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />

<Target Name="_ExportJarToXmlInputs">
<ItemGroup>
<_ExportJarToXmlOutputs Remove="@(_ExportJarToXmlOutputs)" />
<_JavaReferenceApiXml Remove="@(_JavaReferenceApiXml)" />
<_ExportJarToXmlOutputs Include="$(ApiOutputFile)" />
<_ExportJarToXmlOutputs
Include="$(ApiOutputFile).reference.class-parse"
Condition=" '@(EmbeddedReferenceJar->Count())' != '0' or '@(ReferenceJar->Count())' != '0' "
/>
<_JavaReferenceApiXml
Include="$(ApiOutputFile).reference.class-parse"
Condition=" '@(EmbeddedReferenceJar->Count())' != '0' or '@(ReferenceJar->Count())' != '0' "
/>
</ItemGroup>
</Target>

<Target Name="_ExportJarToXml"
DependsOnTargets="_ExtractJavadocsFromJavaSourceJars"
DependsOnTargets="_ExtractJavadocsFromJavaSourceJars;_ExportJarToXmlInputs"
Inputs="@(EmbeddedJar);@(EmbeddedReferenceJar);@(InputJar);@(ReferenceJar);@(_AndroidMSBuildAllProjects)"
Outputs="$(ApiOutputFile)">
Outputs="@(_ExportJarToXmlOutputs)">

<PropertyGroup>
<!-- Allow $(_BindingsToolsLocation) to override where to find class-parse/generator -->
Expand All @@ -35,6 +51,8 @@ This file is only used by binding projects.
<ClassParse
OutputFile="$(ApiOutputFile).class-parse"
SourceJars="@(EmbeddedJar);@(InputJar)"
ReferenceOutputFile="$(ApiOutputFile).reference.class-parse"
ReferenceJars="@(EmbeddedReferenceJar);@(ReferenceJar)"
Comment thread
jonathanpeppers marked this conversation as resolved.
DocumentationPaths="@(_AndroidDocumentationPath)"
NetCoreRoot="$(NetCoreRoot)"
ToolPath="$(_BindingsToolsLocation)"
Expand All @@ -46,6 +64,7 @@ This file is only used by binding projects.
OutputDirectory="$(GeneratedOutputPath)src"
AndroidApiLevel="$(_AndroidApiLevel)"
ApiXmlInput="$(ApiOutputFile).class-parse"
JavaReferenceApiXml="@(_JavaReferenceApiXml)"
ReferencedManagedLibraries="@(ReferencePath);@(ReferenceDependencyPaths)"
MonoAndroidFrameworkDirectories="$(_XATargetFrameworkDirectories)"
NetCoreRoot="$(NetCoreRoot)"
Expand All @@ -57,6 +76,7 @@ This file is only used by binding projects.
<ItemGroup>
<!-- Created by <ClassParse /> -->
<FileWrites Include="$(IntermediateOutputPath)class-parse.rsp" />
<FileWrites Condition="Exists ('$(ApiOutputFile).reference.class-parse')" Include="$(ApiOutputFile).reference.class-parse" />
<!-- Created by <BindingGenerator /> -->
<FileWrites Condition="Exists ('$(IntermediateOutputPath)java-resolution-report.log')" Include="$(IntermediateOutputPath)java-resolution-report.log" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ It is shared between "legacy" binding projects and .NET 5 projects.
CodegenTarget="$(AndroidCodegenTarget)"
AndroidApiLevel="$(_AndroidApiLevel)"
ApiXmlInput="$(ApiOutputFile)"
JavaReferenceApiXml="@(_JavaReferenceApiXml)"
AnnotationsZipFiles="@(AnnotationsZip)"
AssemblyName="$(AssemblyName)"
JavadocVerbosity="$(AndroidJavadocVerbosity)"
Expand Down Expand Up @@ -154,6 +155,7 @@ It is shared between "legacy" binding projects and .NET 5 projects.
<Target Name="AddLibraryJarsToBind" DependsOnTargets="ResolveLibraryProjects">
<ItemGroup>
<InputJar Include="$(IntermediateOutputPath)library_project_jars\**\*.jar" />
<ReferenceJar Include="$(IntermediateOutputPath)reference_library_project_jars\**\*.jar" />
</ItemGroup>
</Target>

Expand Down Expand Up @@ -181,6 +183,8 @@ It is shared between "legacy" binding projects and .NET 5 projects.
<Delete Files="$(_AndroidLibraryProjectImportsCache)" />
<Delete Files="$(_AndroidLibrayProjectAssemblyMapFile)" />
<RemoveDirFixed Directories="$(IntermediateOutputPath)library_project_jars" />
<RemoveDirFixed Directories="$(IntermediateOutputPath)reference_library_project_jars" />
<RemoveDirFixed Directories="$(IntermediateOutputPath)reference_library_project_annotations" />
<RemoveDirFixed Directories="$(IntermediateOutputPath)library_project_annotations" />
<RemoveDirFixed Directories="$(IntermediateOutputPath)$(_LibraryProjectImportsDirectoryName)" />
<RemoveDirFixed Directories="$(IntermediateOutputPath)__library_projects__" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,16 @@ projects.
</Target>

<Target Name="_ExtractAar"
Inputs="@(LibraryProjectZip)"
DependsOnTargets="_CategorizeAndroidLibraries"
Inputs="@(LibraryProjectZip);@(_AndroidReferenceLibraryProjectZip);@(_AndroidMSBuildAllProjects)"
Outputs="$(_AndroidStampDirectory)_ExtractAar.stamp">
<ExtractJarsFromAar
OutputJarsDirectory="$(IntermediateOutputPath)library_project_jars"
OutputAnnotationsDirectory="$(IntermediateOutputPath)library_project_annotations"
Libraries="@(LibraryProjectZip)"
OutputReferenceJarsDirectory="$(IntermediateOutputPath)reference_library_project_jars"
OutputReferenceAnnotationsDirectory="$(IntermediateOutputPath)reference_library_project_annotations"
ReferenceLibraries="@(_AndroidReferenceLibraryProjectZip)"
/>
<Touch Files="$(_AndroidStampDirectory)_ExtractAar.stamp" AlwaysCreate="true" />
</Target>
Expand Down
13 changes: 12 additions & 1 deletion src/Xamarin.Android.Build.Tasks/Tasks/ClassParse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ public class ClassParse : AndroidDotnetToolTask
[Required]
public ITaskItem[] SourceJars { get; set; } = [];

public string? ReferenceOutputFile { get; set; }

public ITaskItem []? ReferenceJars { get; set; }

public ITaskItem []? DocumentationPaths { get; set; }

protected override string GenerateCommandLineCommands ()
{
var cmd = GetCommandLineBuilder ();

var responseFile = Path.Combine (Path.GetDirectoryName (OutputFile), "class-parse.rsp");
var responseFile = Path.Combine (Path.GetDirectoryName (Path.GetFullPath (OutputFile)) ?? "", "class-parse.rsp");
Log.LogDebugMessage ("[class-parse] response file: {0}", responseFile);

using (var sw = new StreamWriter (responseFile, append: false, encoding: Files.UTF8withoutBOM)) {
Expand All @@ -34,6 +38,13 @@ protected override string GenerateCommandLineCommands ()
foreach (var doc in DocumentationPaths)
WriteLine (sw, $"--docspath=\"{doc}\"");

if (!ReferenceOutputFile.IsNullOrEmpty ())
WriteLine (sw, $"--reference-output=\"{ReferenceOutputFile}\"");

if (ReferenceJars != null)
foreach (var reference in ReferenceJars)
Comment thread
jonathanpeppers marked this conversation as resolved.
WriteLine (sw, $"--reference=\"{reference}\"");

foreach (var doc in SourceJars)
WriteLine (sw, $"\"{doc}\"");
}
Expand Down
41 changes: 27 additions & 14 deletions src/Xamarin.Android.Build.Tasks/Tasks/ExtractJarsFromAar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,36 @@ public class ExtractJarsFromAar : AndroidTask

public string []? Libraries { get; set; }

[Required]
public string OutputReferenceJarsDirectory { get; set; } = "";

[Required]
public string OutputReferenceAnnotationsDirectory { get; set; } = "";

public string []? ReferenceLibraries { get; set; }

public override bool RunTask ()
{
if (Libraries == null || Libraries.Length == 0)
return true;

var memoryStream = MemoryStreamPool.Shared.Rent ();
try {
var jars = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
var annotations = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
foreach (var library in Libraries) {
ExtractLibraries (Libraries, OutputJarsDirectory, OutputAnnotationsDirectory, memoryStream);
ExtractLibraries (ReferenceLibraries, OutputReferenceJarsDirectory, OutputReferenceAnnotationsDirectory, memoryStream);
} finally {
MemoryStreamPool.Shared.Return (memoryStream);
}

return !Log.HasLoggedErrors;
}

void ExtractLibraries (string []? libraries, string outputJarsDirectory, string outputAnnotationsDirectory, MemoryStream memoryStream)
{
var jars = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
var annotations = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
if (libraries != null) {
foreach (var library in libraries) {
bool isAar = library.EndsWith (".aar", StringComparison.OrdinalIgnoreCase);
var jarOutputDirectory = Path.Combine (OutputJarsDirectory, Path.GetFileName (library));
var annotationOutputDirectory = Path.Combine (OutputAnnotationsDirectory, Path.GetFileName (library));
var jarOutputDirectory = Path.Combine (outputJarsDirectory, Path.GetFileName (library));
var annotationOutputDirectory = Path.Combine (outputAnnotationsDirectory, Path.GetFileName (library));
using (var zip = MonoAndroidHelper.ReadZipFile (library)) {
foreach (var entry in zip) {
if (entry.IsDirectory)
Expand All @@ -63,13 +80,9 @@ public override bool RunTask ()
}
}
}
DeleteUnknownFiles (OutputJarsDirectory, jars);
DeleteUnknownFiles (OutputAnnotationsDirectory, annotations);
} finally {
MemoryStreamPool.Shared.Return (memoryStream);
}

return !Log.HasLoggedErrors;
DeleteUnknownFiles (outputJarsDirectory, jars);
DeleteUnknownFiles (outputAnnotationsDirectory, annotations);
}

bool IsUnderDirectory (string resolvedPath, string targetDirectory, string entryName, string archivePath)
Expand Down
4 changes: 4 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class BindingsGenerator : AndroidDotnetToolTask

public ITaskItem[]? JavadocXml { get; set; }
public string? JavadocVerbosity { get; set; }
public ITaskItem []? JavaReferenceApiXml { get; set; }

private List<Tuple<string, string>> transform_files = new List<Tuple<string,string>> ();

Expand Down Expand Up @@ -187,6 +188,9 @@ protected override string GenerateCommandLineCommands ()
if (ReferencedManagedLibraries != null)
foreach (var lib in ReferencedManagedLibraries)
WriteLine (sw, $"--ref=\"{Path.GetFullPath (lib.ItemSpec)}\"");
if (JavaReferenceApiXml != null)
foreach (var reference in JavaReferenceApiXml)
WriteLine (sw, $"--java-reference=\"{Path.GetFullPath (reference.ItemSpec)}\"");
if (AnnotationsZipFiles != null)
foreach (var zip in AnnotationsZipFiles)
WriteLine (sw, $"--annotations=\"{Path.GetFullPath (zip.ItemSpec)}\"");
Expand Down
Loading