blob: 5e59f315f23397f5cf90866b08c66aac3a4ee133 [file] [log] [blame] [view]
# Description of the human desugared library configuration file
## Top-level flags
### Identifier
The field `identifier` is the maven-coordinated id for the desugared library
configuration file with the group id, the artifact id and the version number
joined with colon.
### Version
The field `configuration_format_version` encodes a versioning number internal to
R8/D8 in the form of an unsigned integer. It allows R8/D8 to know if the file
given is supported. If the number is between 100 and 200, the file is encoded
using the human flags (by opposition to the legacy and machine flags). Human
flags are not shipped to external users. Human flags can be converted to machine
flags which are shipped to external users. Users internal to Google are allowed
to use directly human flags if we can easily update the file without backward
compatibility issues.
### Required compilation API level
The field `required_compilation_api_level` encodes the minimal Android API level
required for the desugared library to be compiled correctly. If the API of
library used for compilation of the library or a program using the library is
lower than this level, one has to upgrade the SDK version used to be able to use
desugared libraries.
### Synthesize prefix
The field `synthesized_library_classes_package_prefix` is used to prefix type
names of synthetic classes created during the L8 compilation. It is also used
for minification in the `java.` namespace to avoid collisions with platforms.
### Library callbacks
The field `support_all_callbacks_from_library` is set if D8/R8 should generate
extra callbacks, i.e., methods that may be called from specific library
implementations into the program. Setting it to false may lead to invalid
behavior if the library effectively use one of the callbacks, but reduces code
size.
## Common, library and program flags
The fields `common_flags`, `library_flags` and `program_flags` include the set
of rewriting flags required for respectively rewriting both the library and the
program, only the library or only the program.
The flags are in a list, where each list entry specifies up to which min API
level the set of flags should be applied. During compilation, R8/D8 adds up all
the required flags for the min API level specified at compilation.
The following subsections describe each rewriting flag.
### Flag rewrite_prefix
`prefix: rewrittenPrefix`
D8/R8 identifies any class which type matches the prefix, and rewrite such types
with the new prefix. Types not present as class types are not rewritten.
Implicitly, all synthetic types derived from the matching type are also
rewritten (lambdas and backports in the class, etc.). Lastly, types referenced
directly or indirectly from other flags (method retargeting, custom conversions,
emulated interfaces, api generic type conversion) are identified and rewritten.
The exact list of types is computed when generating the machine specification
and the pattern matching never applies to user code, but instead to the
desugared library jar and `android.jar`.
Example:
`foo.: f$.`
A class present with the type foo.Foo will generate a rewrite rule:
foo.Foo -> f$.Foo. A type present foo.Bar, which is not the type of any class,
will not generate any rewrite rule.
### Flag maintain_prefix
`prefix`
D8/R8 identifies any class which type matches the prefix, and maintain such
class in desugared library in the `java` namespace. Using this flag implicitly
means that at runtime, either a class from the bootclasspath with the same name
will take precedence and be used, or this class will be used on lower api
levels.
Using `maintain_prefix` allows desugared library code to work seamlessly with
recent apis (no wrappers or conversions required), at the cost of preventing
some signature changes (the signature in desugared library, even when shrinking,
has to match the library one). This can be done only with classes which behavior
is identical between desugared library and platform. Lastly, derived synthetic
classes from code in such classes (lambdas, etc.) are still moved to the new
namespace to avoid collisions with platform, so one has to be extra careful with
package private access being broken in this set-up.
Example:
`foo.`
A class present with the type `foo.Foo` will be maintained in the output as
`foo.Foo`. If `synthesized_library_classes_package_prefix` is `f$`, then all the
derived synthetic classes such as lambdas inside `foo.Foo` will be generated as
`f$.Foo$lambda-hash`.
### Flag rewrite_derived_prefix
`prefix: { fromPrefix: toPrefix }`
D8/R8 identifies any class type matching the prefix, and rewrite the type with
the fromPrefix to the type with the toPrefix. This can be useful to generate
rewrite rules from types not present in the input.
Example:
`foo.: { f$.: foo. }`
A class present with the type foo.Foo will generate a rewrite rule:
f$.Foo -> foo.Foo.
### Flag dont_rewrite_prefix
`prefix`
D8/R8 identifies any class type matching the prefix, does not rewrite it and
shrinks it away from the input. This flags takes precedence over
`rewrite_prefix` and `rewrite_derived_prefix`, allowing to disable prefix
rewriting on subpatterns.
Example:
`foo.`
No class prefixed with foo. will be rewritten or kept in the output.
### Flag never_outline_api
`method`
D8/R8 tries to outline api calls working only on high api levels and requiring
conversions as much as possible to share the code and avoid soft verification
errors. Methods specified here are never outlined. This is usually worse for the
users, unless the api is expected to introspect the stack, in which case the
extra frame is confusing.
### Flag api_generic_types_conversion
`methodApi: [i0, conversionMethod0, ..., iN, conversionMethodN]`
D8/R8 automatically generates conversions surrounding api calls with rewritten
types which are specified in custom conversions/wrappers. D8/R8 does not
automatically convert types from generic types such as collection items, or
conversion requiring to convert multiple values in general
This flag is used to specify a plateform api (methodApi) which parameters or
return value require a conversion different from the default one. The value is
an array of pair. The pair's key (i0, .., iN) is the parameter index if greater
or equal to 0, or the return type if -1. The pair's value (conversionMethod0,
.., N) is the conversion method to use to convert the value.
Example:
`void bar(foo.Foo): [0, foo.Foo FooConverter#convertFoo(f$.Foo)]`
When generating conversion for the api bar, the parameter 0 foo.Foo will be
converted using FooConverter#convertFoo instead of the default conversion logic.
### Flag retarget_static_field
`field: retargetField`
D8/R8 rewrites all references from the static field to the static retargetField.
Example:
`int Foo#bar: int Zorg#foo`
D8/R8 rewrites all references to the field named bar in Foo to the field named
foo in Zorg.
### Flag retarget_method
`methodToRetarget: retargetType`
D8/R8 identifies all invokes which method resolve to the methodToRetarget, and
rewrite it to an invoke to the same method but with the retargetType as holder.
If the method is virtual, this converts the invoke to an invoke-static and adds
the receiver type as the first parameter.
The retargeting is valid for static methods, private methods and methods
effectively final (methods with the final keyword, methods on final classes,
which do not override any other method).
When using the flag, the method, if virtual, is considered as effectively final.
For retargeting of virtual methods that can be overridden, see
retarget_method_with_emulated_dispatch.
Example:
`Foo Bar#foo(Zorg): DesugarBar`
Any invoke which method resolves into the method with return type Foo, name foo,
parameter Zorg on the holder Bar, is rewritten to an invoke-static to the same
method on DesugarBar. If the method is not static, the rewritten method takes an
extra first parameter of type Bar.
### Flag retarget_method_with_emulated_dispatch
`methodToRetarget: retargetType`
Essentially the same as retarget_method, but for non effectively final virtual
method. The flag fails the compilation if the methodToRetarget is static. D8/R8
generates an emulated dispatch scheme so that the method can be retargeted, but
the virtual dispatch is still valid and will correctly call the overrides if
present.
### Flag covariant_retarget_method
`methodWithCovariantReturnType: alternativeReturnType`
Any invoke to methodWithCovariantReturnType will be rewritten to a call to the
same method with the alternativeReturnType and a checkcast. This is used to deal
with covariant return types which are not present in desugared library.
### Flag amend_library_method
`modifiers method`
For the retarget_method and retarget_method_with_emulated_dispatch flags to
work, resolution has to find the method to retarget to. In some cases, the
method is missing because it's not present on the required compilation level
Android SDK, or because the method is private.
This flag amends the library to introduce the method, so resolution can find it
and retarget it correctly.
### Flag amend_library_field
`modifiers field`
Similar to amend_library_method, adds a field into the library so that field
resolution can find it and it can be retargeted.
### Flag dont_retarget
`type`
In classes with such type, invokes are not retargeted with the retarget_method
and the retarget_method_with_emulated_dispatch flag. In addition, forwarding
methods required for retarget_method_with_emulated_dispatch are not introduced
in such classes.
### Flag emulate_interface
`libraryInterface: desugaredLibraryInterface`
D8/R8 assume the libraryInterface is already in the library, but without the
default and static methods present on it. It generates a companion class holding
the code for the default and static methods, and a dispatch class which hold the
code to support emulated dispatch for the default methods.
### Flag wrapper_conversion
`type`
Generate wrappers for the given type, including methods from the type and all
its super types and interface types. In addition, analyse all invokes resolving
into the library. If the invoke includes the type as return or parameter type,
automatically surround the library call with conversion code using wrappers. The
sequence of instructions with the conversions and the library invoke is outlined
and shared if possible.
### Flag wrapper_conversion_excluding
`type: [methods]`
Similar to wrapper_conversion, generate wrappers for the given type but ignore
the methods listed. This can be used for methods not accessing fields or private
methods, either to reduce code size or to work around final methods.
### Flag custom_conversion
`type: conversionType`
Similar to wrapper_conversion, but instead of generating wrappers, rely on hand
written conversions present on conversionType. The conversions methods must be
of the form:
Type convert(RewrittenType)
RewrittenType convert(Type)
## Shrinker config
The last field is `shrinker_config`, it includes keep rules that are appended by
L8 when shrinking the desugared library. It includes keep rules related to
reflection inside the desugared library, related to enum to have EnumSet working
and to keep the j$ prefix. It also includes various keep rules to suppor common
serializers.
## Copyright
Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file for
details. All rights reserved. Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.