Separate creation of signature patterns from overlap checking am: 67b9d61ac2
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1788091 Change-Id: I8e4158cde756070327458afd5415e03ccda5bd54
This commit is contained in:
@@ -159,11 +159,12 @@ func TestPlatformBootclasspath_Fragments(t *testing.T) {
|
||||
android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category])
|
||||
}
|
||||
|
||||
android.AssertPathsRelativeToTopEquals(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/stub-flags.csv"}, info.StubFlagsPaths)
|
||||
android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
|
||||
android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
|
||||
android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/index.csv"}, info.IndexPaths)
|
||||
android.AssertPathsRelativeToTopEquals(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/all-flags.csv"}, info.AllFlagsPaths)
|
||||
|
||||
android.AssertArrayString(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/stub-flags.csv:out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
|
||||
android.AssertArrayString(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/all-flags.csv:out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
|
||||
}
|
||||
|
||||
func TestPlatformBootclasspathDependencies(t *testing.T) {
|
||||
|
@@ -579,6 +579,14 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.
|
||||
common := ctx.Module().(commonBootclasspathFragment)
|
||||
output := common.produceHiddenAPIOutput(ctx, contents, input)
|
||||
|
||||
// If the source or prebuilts module does not provide a signature patterns file then generate one
|
||||
// from the flags.
|
||||
// TODO(b/192868581): Remove once the source and prebuilts provide a signature patterns file of
|
||||
// their own.
|
||||
if output.SignaturePatternsPath == nil {
|
||||
output.SignaturePatternsPath = buildRuleSignaturePatternsFile(ctx, output.AllFlagsPath)
|
||||
}
|
||||
|
||||
// Initialize a HiddenAPIInfo structure.
|
||||
hiddenAPIInfo := HiddenAPIInfo{
|
||||
// The monolithic hidden API processing needs access to the flag files that override the default
|
||||
@@ -744,9 +752,6 @@ type bootclasspathFragmentSdkMemberProperties struct {
|
||||
// Flag files by *hiddenAPIFlagFileCategory
|
||||
Flag_files_by_category FlagFilesByCategory
|
||||
|
||||
// The path to the generated stub-flags.csv file.
|
||||
Stub_flags_path android.OptionalPath
|
||||
|
||||
// The path to the generated annotation-flags.csv file.
|
||||
Annotation_flags_path android.OptionalPath
|
||||
|
||||
@@ -756,6 +761,9 @@ type bootclasspathFragmentSdkMemberProperties struct {
|
||||
// The path to the generated index.csv file.
|
||||
Index_path android.OptionalPath
|
||||
|
||||
// The path to the generated stub-flags.csv file.
|
||||
Stub_flags_path android.OptionalPath
|
||||
|
||||
// The path to the generated all-flags.csv file.
|
||||
All_flags_path android.OptionalPath
|
||||
}
|
||||
@@ -772,10 +780,11 @@ func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx andro
|
||||
b.Flag_files_by_category = hiddenAPIInfo.FlagFilesByCategory
|
||||
|
||||
// Copy all the generated file paths.
|
||||
b.Stub_flags_path = android.OptionalPathForPath(hiddenAPIInfo.StubFlagsPath)
|
||||
b.Annotation_flags_path = android.OptionalPathForPath(hiddenAPIInfo.AnnotationFlagsPath)
|
||||
b.Metadata_path = android.OptionalPathForPath(hiddenAPIInfo.MetadataPath)
|
||||
b.Index_path = android.OptionalPathForPath(hiddenAPIInfo.IndexPath)
|
||||
|
||||
b.Stub_flags_path = android.OptionalPathForPath(hiddenAPIInfo.StubFlagsPath)
|
||||
b.All_flags_path = android.OptionalPathForPath(hiddenAPIInfo.AllFlagsPath)
|
||||
|
||||
// Copy stub_libs properties.
|
||||
@@ -839,10 +848,10 @@ func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.
|
||||
}
|
||||
|
||||
// Copy all the generated files, if available.
|
||||
copyOptionalPath(b.Stub_flags_path, "stub_flags")
|
||||
copyOptionalPath(b.Annotation_flags_path, "annotation_flags")
|
||||
copyOptionalPath(b.Metadata_path, "metadata")
|
||||
copyOptionalPath(b.Index_path, "index")
|
||||
copyOptionalPath(b.Stub_flags_path, "stub_flags")
|
||||
copyOptionalPath(b.All_flags_path, "all_flags")
|
||||
}
|
||||
|
||||
@@ -852,9 +861,6 @@ var _ android.SdkMemberType = (*bootclasspathFragmentMemberType)(nil)
|
||||
// specific properties.
|
||||
type prebuiltBootclasspathFragmentProperties struct {
|
||||
Hidden_api struct {
|
||||
// The path to the stub-flags.csv file created by the bootclasspath_fragment.
|
||||
Stub_flags *string `android:"path"`
|
||||
|
||||
// The path to the annotation-flags.csv file created by the bootclasspath_fragment.
|
||||
Annotation_flags *string `android:"path"`
|
||||
|
||||
@@ -864,6 +870,9 @@ type prebuiltBootclasspathFragmentProperties struct {
|
||||
// The path to the index.csv file created by the bootclasspath_fragment.
|
||||
Index *string `android:"path"`
|
||||
|
||||
// The path to the stub-flags.csv file created by the bootclasspath_fragment.
|
||||
Stub_flags *string `android:"path"`
|
||||
|
||||
// The path to the all-flags.csv file created by the bootclasspath_fragment.
|
||||
All_flags *string `android:"path"`
|
||||
}
|
||||
|
@@ -297,7 +297,7 @@ func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.
|
||||
//
|
||||
// The rule is initialized but not built so that the caller can modify it and select an appropriate
|
||||
// name.
|
||||
func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, moduleStubFlagsPaths android.Paths) {
|
||||
func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, stubFlagSubsets SignatureCsvSubsets) {
|
||||
// Singleton rule which applies hiddenapi on all boot class path dex files.
|
||||
rule := android.NewRuleBuilder(pctx, ctx)
|
||||
|
||||
@@ -317,7 +317,7 @@ func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name,
|
||||
|
||||
// If no module stub flags paths are provided then this must be being called for a
|
||||
// bootclasspath_fragment and not the whole platform_bootclasspath.
|
||||
if moduleStubFlagsPaths == nil {
|
||||
if stubFlagSubsets == nil {
|
||||
// This is being run on a fragment of the bootclasspath.
|
||||
command.Flag("--fragment")
|
||||
}
|
||||
@@ -342,8 +342,8 @@ func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name,
|
||||
|
||||
// If there are stub flag files that have been generated by fragments on which this depends then
|
||||
// use them to validate the stub flag file generated by the rules created by this method.
|
||||
if len(moduleStubFlagsPaths) > 0 {
|
||||
validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, moduleStubFlagsPaths)
|
||||
if len(stubFlagSubsets) > 0 {
|
||||
validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets)
|
||||
|
||||
// Add the file that indicates that the file generated by this is valid.
|
||||
//
|
||||
@@ -546,6 +546,20 @@ func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragmen
|
||||
}
|
||||
}
|
||||
|
||||
// StubFlagSubset returns a SignatureCsvSubset that contains a path to a stub-flags.csv file and a
|
||||
// path to a signature-patterns.csv file that defines a subset of the monolithic stub flags file,
|
||||
// i.e. out/soong/hiddenapi/hiddenapi-stub-flags.txt, against which it will be compared.
|
||||
func (i *HiddenAPIInfo) StubFlagSubset() SignatureCsvSubset {
|
||||
return SignatureCsvSubset{i.StubFlagsPath, i.SignaturePatternsPath}
|
||||
}
|
||||
|
||||
// FlagSubset returns a SignatureCsvSubset that contains a path to an all-flags.csv file and a
|
||||
// path to a signature-patterns.csv file that defines a subset of the monolithic flags file, i.e.
|
||||
// out/soong/hiddenapi/hiddenapi-flags.csv, against which it will be compared.
|
||||
func (i *HiddenAPIInfo) FlagSubset() SignatureCsvSubset {
|
||||
return SignatureCsvSubset{i.AllFlagsPath, i.SignaturePatternsPath}
|
||||
}
|
||||
|
||||
var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
|
||||
|
||||
// ModuleStubDexJars contains the stub dex jars provided by a single module.
|
||||
@@ -782,6 +796,10 @@ type HiddenAPIFlagOutput struct {
|
||||
|
||||
// The path to the generated all-flags.csv file.
|
||||
AllFlagsPath android.Path
|
||||
|
||||
// The path to the generated signature-patterns.txt file which defines the subset of the
|
||||
// monolithic hidden API files provided in this.
|
||||
SignaturePatternsPath android.Path
|
||||
}
|
||||
|
||||
// bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex
|
||||
@@ -848,7 +866,7 @@ func pathForValidation(ctx android.PathContext, path android.WritablePath) andro
|
||||
// the annotationFlags.
|
||||
func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string,
|
||||
outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
|
||||
flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) {
|
||||
flagFilesByCategory FlagFilesByCategory, flagSubsets SignatureCsvSubsets, generatedRemovedDexSignatures android.OptionalPath) {
|
||||
|
||||
// Create the rule that will generate the flag files.
|
||||
tempPath := tempPathForRestat(ctx, outputPath)
|
||||
@@ -877,8 +895,8 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
|
||||
|
||||
// If there are flag files that have been generated by fragments on which this depends then use
|
||||
// them to validate the flag file generated by the rules created by this method.
|
||||
if len(allFlagsPaths) > 0 {
|
||||
validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, allFlagsPaths)
|
||||
if len(flagSubsets) > 0 {
|
||||
validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets)
|
||||
|
||||
// Add the file that indicates that the file generated by this is valid.
|
||||
//
|
||||
@@ -890,20 +908,66 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
|
||||
rule.Build(name, desc)
|
||||
}
|
||||
|
||||
// SignatureCsvSubset describes a subset of a monolithic flags file, i.e. either
|
||||
// out/soong/hiddenapi/hiddenapi-stub-flags.txt or out/soong/hiddenapi/hiddenapi-flags.csv
|
||||
type SignatureCsvSubset struct {
|
||||
// The path to the CSV file containing hidden API flags.
|
||||
//
|
||||
// It has the dex member signature as the first column, with flags, one per column, in the
|
||||
// subsequent columns.
|
||||
CsvFile android.Path
|
||||
|
||||
// The path to the CSV file containing the signature patterns.
|
||||
//
|
||||
// It is a single column CSV file with the column containing a signature pattern.
|
||||
SignaturePatternsFile android.Path
|
||||
}
|
||||
|
||||
type SignatureCsvSubsets []SignatureCsvSubset
|
||||
|
||||
func (s SignatureCsvSubsets) RelativeToTop() []string {
|
||||
result := []string{}
|
||||
for _, subset := range s {
|
||||
result = append(result, fmt.Sprintf("%s:%s", subset.CsvFile.RelativeToTop(), subset.SignaturePatternsFile.RelativeToTop()))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// buildRuleSignaturePatternsFile creates a rule to generate a file containing the set of signature
|
||||
// patterns that will select a subset of the monolithic flags.
|
||||
func buildRuleSignaturePatternsFile(ctx android.ModuleContext, flagsPath android.Path) android.Path {
|
||||
patternsFile := android.PathForModuleOut(ctx, "modular-hiddenapi", "signature-patterns.csv")
|
||||
// Create a rule to validate the output from the following rule.
|
||||
rule := android.NewRuleBuilder(pctx, ctx)
|
||||
rule.Command().
|
||||
BuiltTool("signature_patterns").
|
||||
FlagWithInput("--flags ", flagsPath).
|
||||
FlagWithOutput("--output ", patternsFile)
|
||||
rule.Build("hiddenAPISignaturePatterns", "hidden API signature patterns")
|
||||
|
||||
return patternsFile
|
||||
}
|
||||
|
||||
// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
|
||||
// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
|
||||
func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, modularFilePaths android.Paths) android.WritablePath {
|
||||
func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, csvSubsets SignatureCsvSubsets) android.WritablePath {
|
||||
// The file which is used to record that the flags file is valid.
|
||||
validFile := pathForValidation(ctx, monolithicFilePath)
|
||||
|
||||
// Create a rule to validate the output from the following rule.
|
||||
rule := android.NewRuleBuilder(pctx, ctx)
|
||||
rule.Command().
|
||||
command := rule.Command().
|
||||
BuiltTool("verify_overlaps").
|
||||
Input(monolithicFilePath).
|
||||
Inputs(modularFilePaths).
|
||||
Input(monolithicFilePath)
|
||||
|
||||
for _, subset := range csvSubsets {
|
||||
command.
|
||||
Textf("%s:%s", subset.CsvFile, subset.SignaturePatternsFile).
|
||||
Implicit(subset.CsvFile).Implicit(subset.SignaturePatternsFile)
|
||||
}
|
||||
|
||||
// If validation passes then update the file that records that.
|
||||
Text("&& touch").Output(validFile)
|
||||
command.Text("&& touch").Output(validFile)
|
||||
rule.Build(name+"Validation", desc+" validation")
|
||||
|
||||
return validFile
|
||||
|
@@ -29,9 +29,6 @@ type MonolithicHiddenAPIInfo struct {
|
||||
// that category.
|
||||
FlagsFilesByCategory FlagFilesByCategory
|
||||
|
||||
// The paths to the generated stub-flags.csv files.
|
||||
StubFlagsPaths android.Paths
|
||||
|
||||
// The paths to the generated annotation-flags.csv files.
|
||||
AnnotationFlagsPaths android.Paths
|
||||
|
||||
@@ -41,8 +38,13 @@ type MonolithicHiddenAPIInfo struct {
|
||||
// The paths to the generated index.csv files.
|
||||
IndexPaths android.Paths
|
||||
|
||||
// The paths to the generated all-flags.csv files.
|
||||
AllFlagsPaths android.Paths
|
||||
// The subsets of the monolithic hiddenapi-stubs-flags.txt file that are provided by each
|
||||
// bootclasspath_fragment modules.
|
||||
StubFlagSubsets SignatureCsvSubsets
|
||||
|
||||
// The subsets of the monolithic hiddenapi-flags.csv file that are provided by each
|
||||
// bootclasspath_fragment modules.
|
||||
FlagSubsets SignatureCsvSubsets
|
||||
|
||||
// The classes jars from the libraries on the platform bootclasspath.
|
||||
ClassesJars android.Paths
|
||||
@@ -80,11 +82,12 @@ func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory F
|
||||
// append appends all the files from the supplied info to the corresponding files in this struct.
|
||||
func (i *MonolithicHiddenAPIInfo) append(other *HiddenAPIInfo) {
|
||||
i.FlagsFilesByCategory.append(other.FlagFilesByCategory)
|
||||
i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPath)
|
||||
i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPath)
|
||||
i.MetadataPaths = append(i.MetadataPaths, other.MetadataPath)
|
||||
i.IndexPaths = append(i.IndexPaths, other.IndexPath)
|
||||
i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPath)
|
||||
|
||||
i.StubFlagSubsets = append(i.StubFlagSubsets, other.StubFlagSubset())
|
||||
i.FlagSubsets = append(i.FlagSubsets, other.FlagSubset())
|
||||
}
|
||||
|
||||
var MonolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{})
|
||||
|
@@ -316,7 +316,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
|
||||
|
||||
// Generate the monolithic stub-flags.csv file.
|
||||
stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
|
||||
buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags", stubFlags, bootDexJarByModule.bootDexJars(), input, monolithicInfo.StubFlagsPaths)
|
||||
buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags", stubFlags, bootDexJarByModule.bootDexJars(), input, monolithicInfo.StubFlagSubsets)
|
||||
|
||||
// Generate the annotation-flags.csv file from all the module annotations.
|
||||
annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags-from-classes.csv")
|
||||
@@ -329,7 +329,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
|
||||
allAnnotationFlagFiles := android.Paths{annotationFlags}
|
||||
allAnnotationFlagFiles = append(allAnnotationFlagFiles, monolithicInfo.AnnotationFlagsPaths...)
|
||||
allFlags := hiddenAPISingletonPaths(ctx).flags
|
||||
buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "monolithic hidden API flags", allFlags, stubFlags, allAnnotationFlagFiles, monolithicInfo.FlagsFilesByCategory, monolithicInfo.AllFlagsPaths, android.OptionalPath{})
|
||||
buildRuleToGenerateHiddenApiFlags(ctx, "hiddenAPIFlagsFile", "monolithic hidden API flags", allFlags, stubFlags, allAnnotationFlagFiles, monolithicInfo.FlagsFilesByCategory, monolithicInfo.FlagSubsets, android.OptionalPath{})
|
||||
|
||||
// Generate an intermediate monolithic hiddenapi-metadata.csv file directly from the annotations
|
||||
// in the source code.
|
||||
|
@@ -104,3 +104,39 @@ python_test_host {
|
||||
unit_test: true,
|
||||
},
|
||||
}
|
||||
|
||||
python_binary_host {
|
||||
name: "signature_patterns",
|
||||
main: "signature_patterns.py",
|
||||
srcs: ["signature_patterns.py"],
|
||||
version: {
|
||||
py2: {
|
||||
enabled: false,
|
||||
},
|
||||
py3: {
|
||||
enabled: true,
|
||||
embedded_launcher: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
python_test_host {
|
||||
name: "signature_patterns_test",
|
||||
main: "signature_patterns_test.py",
|
||||
srcs: [
|
||||
"signature_patterns.py",
|
||||
"signature_patterns_test.py",
|
||||
],
|
||||
version: {
|
||||
py2: {
|
||||
enabled: false,
|
||||
},
|
||||
py3: {
|
||||
enabled: true,
|
||||
embedded_launcher: true,
|
||||
},
|
||||
},
|
||||
test_options: {
|
||||
unit_test: true,
|
||||
},
|
||||
}
|
||||
|
56
scripts/hiddenapi/signature_patterns.py
Executable file
56
scripts/hiddenapi/signature_patterns.py
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2021 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""
|
||||
Generate a set of signature patterns from the modular flags generated by a
|
||||
bootclasspath_fragment that can be used to select a subset of monolithic flags
|
||||
against which the modular flags can be compared.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
|
||||
def dict_reader(input):
|
||||
return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature'])
|
||||
|
||||
def produce_patterns_from_file(file):
|
||||
with open(file, 'r') as f:
|
||||
return produce_patterns_from_stream(f)
|
||||
|
||||
def produce_patterns_from_stream(stream):
|
||||
patterns = []
|
||||
allFlagsReader = dict_reader(stream)
|
||||
for row in allFlagsReader:
|
||||
signature = row['signature']
|
||||
patterns.append(signature)
|
||||
return patterns
|
||||
|
||||
def main(args):
|
||||
args_parser = argparse.ArgumentParser(description='Generate a set of signature patterns that select a subset of monolithic hidden API files.')
|
||||
args_parser.add_argument('--flags', help='The stub flags file which contains an entry for every dex member')
|
||||
args_parser.add_argument('--output', help='Generated signature prefixes')
|
||||
args = args_parser.parse_args(args)
|
||||
|
||||
# Read in all the patterns into a list.
|
||||
patterns = produce_patterns_from_file(args.flags)
|
||||
|
||||
# Write out all the patterns.
|
||||
with open(args.output, 'w') as outputFile:
|
||||
for pattern in patterns:
|
||||
outputFile.write(pattern)
|
||||
outputFile.write("\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
41
scripts/hiddenapi/signature_patterns_test.py
Executable file
41
scripts/hiddenapi/signature_patterns_test.py
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2021 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Unit tests for signature_patterns.py."""
|
||||
import io
|
||||
import unittest
|
||||
|
||||
from signature_patterns import *
|
||||
|
||||
class TestGeneratedPatterns(unittest.TestCase):
|
||||
|
||||
def produce_patterns_from_string(self, csv):
|
||||
with io.StringIO(csv) as f:
|
||||
return produce_patterns_from_stream(f)
|
||||
|
||||
def test_generate(self):
|
||||
patterns = self.produce_patterns_from_string('''
|
||||
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
|
||||
Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
|
||||
''')
|
||||
expected = [
|
||||
"Ljava/lang/Object;->hashCode()I",
|
||||
"Ljava/lang/Object;->toString()Ljava/lang/String;",
|
||||
]
|
||||
self.assertEqual(expected, patterns)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
@@ -24,16 +24,30 @@ from itertools import chain
|
||||
def dict_reader(input):
|
||||
return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature'])
|
||||
|
||||
def extract_subset_from_monolithic_flags_as_dict(monolithicFlagsDict, signatures):
|
||||
def extract_subset_from_monolithic_flags_as_dict_from_file(monolithicFlagsDict, patternsFile):
|
||||
"""
|
||||
Extract a subset of flags from the dict containing all the monolithic flags.
|
||||
|
||||
:param monolithicFlagsDict: the dict containing all the monolithic flags.
|
||||
:param signatures: a list of signature that define the subset.
|
||||
:param patternsFile: a file containing a list of signature patterns that
|
||||
define the subset.
|
||||
:return: the dict from signature to row.
|
||||
"""
|
||||
with open(patternsFile, 'r') as stream:
|
||||
return extract_subset_from_monolithic_flags_as_dict_from_stream(monolithicFlagsDict, stream)
|
||||
|
||||
def extract_subset_from_monolithic_flags_as_dict_from_stream(monolithicFlagsDict, stream):
|
||||
"""
|
||||
Extract a subset of flags from the dict containing all the monolithic flags.
|
||||
|
||||
:param monolithicFlagsDict: the dict containing all the monolithic flags.
|
||||
:param stream: a stream containing a list of signature patterns that define
|
||||
the subset.
|
||||
:return: the dict from signature to row.
|
||||
"""
|
||||
dict = {}
|
||||
for signature in signatures:
|
||||
for signature in stream:
|
||||
signature = signature.rstrip()
|
||||
dict[signature] = monolithicFlagsDict.get(signature, {})
|
||||
return dict
|
||||
|
||||
@@ -102,9 +116,12 @@ def main(argv):
|
||||
# provided by the subset and the corresponding flags from the complete set of
|
||||
# flags and compare them.
|
||||
failed = False
|
||||
for modularFlagsPath in args.modularFlags:
|
||||
for modularPair in args.modularFlags:
|
||||
parts = modularPair.split(":")
|
||||
modularFlagsPath = parts[0]
|
||||
modularPatternsPath = parts[1]
|
||||
modularFlagsDict = read_signature_csv_from_file_as_dict(modularFlagsPath)
|
||||
monolithicFlagsSubsetDict = extract_subset_from_monolithic_flags_as_dict(monolithicFlagsDict, modularFlagsDict.keys())
|
||||
monolithicFlagsSubsetDict = extract_subset_from_monolithic_flags_as_dict_from_file(monolithicFlagsDict, modularPatternsPath)
|
||||
mismatchingSignatures = compare_signature_flags(monolithicFlagsSubsetDict, modularFlagsDict)
|
||||
if mismatchingSignatures:
|
||||
failed = True
|
||||
|
@@ -26,6 +26,10 @@ class TestDetectOverlaps(unittest.TestCase):
|
||||
with io.StringIO(csv) as f:
|
||||
return read_signature_csv_from_stream_as_dict(f)
|
||||
|
||||
def extract_subset_from_monolithic_flags_as_dict_from_string(self, monolithic, patterns):
|
||||
with io.StringIO(patterns) as f:
|
||||
return extract_subset_from_monolithic_flags_as_dict_from_stream(monolithic, f)
|
||||
|
||||
extractInput = '''
|
||||
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
|
||||
Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
|
||||
@@ -36,7 +40,10 @@ Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
|
||||
modular = self.read_signature_csv_from_string_as_dict('''
|
||||
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
|
||||
''')
|
||||
subset = extract_subset_from_monolithic_flags_as_dict(monolithic, modular.keys())
|
||||
|
||||
patterns = 'Ljava/lang/Object;->hashCode()I'
|
||||
|
||||
subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(monolithic, patterns)
|
||||
expected = {
|
||||
'Ljava/lang/Object;->hashCode()I': {
|
||||
None: ['public-api', 'system-api', 'test-api'],
|
||||
|
@@ -134,10 +134,10 @@ prebuilt_bootclasspath_fragment {
|
||||
image_name: "art",
|
||||
contents: ["mybootlib"],
|
||||
hidden_api: {
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
annotation_flags: "hiddenapi/annotation-flags.csv",
|
||||
metadata: "hiddenapi/metadata.csv",
|
||||
index: "hiddenapi/index.csv",
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
all_flags: "hiddenapi/all-flags.csv",
|
||||
},
|
||||
}
|
||||
@@ -161,10 +161,10 @@ prebuilt_bootclasspath_fragment {
|
||||
image_name: "art",
|
||||
contents: ["mysdk_mybootlib@current"],
|
||||
hidden_api: {
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
annotation_flags: "hiddenapi/annotation-flags.csv",
|
||||
metadata: "hiddenapi/metadata.csv",
|
||||
index: "hiddenapi/index.csv",
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
all_flags: "hiddenapi/all-flags.csv",
|
||||
},
|
||||
}
|
||||
@@ -185,10 +185,10 @@ sdk_snapshot {
|
||||
}
|
||||
`),
|
||||
checkAllCopyRules(`
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/all-flags.csv -> hiddenapi/all-flags.csv
|
||||
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
|
||||
`),
|
||||
@@ -332,10 +332,10 @@ prebuilt_bootclasspath_fragment {
|
||||
stub_libs: ["mycoreplatform"],
|
||||
},
|
||||
hidden_api: {
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
annotation_flags: "hiddenapi/annotation-flags.csv",
|
||||
metadata: "hiddenapi/metadata.csv",
|
||||
index: "hiddenapi/index.csv",
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
all_flags: "hiddenapi/all-flags.csv",
|
||||
},
|
||||
}
|
||||
@@ -416,10 +416,10 @@ prebuilt_bootclasspath_fragment {
|
||||
stub_libs: ["mysdk_mycoreplatform@current"],
|
||||
},
|
||||
hidden_api: {
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
annotation_flags: "hiddenapi/annotation-flags.csv",
|
||||
metadata: "hiddenapi/metadata.csv",
|
||||
index: "hiddenapi/index.csv",
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
all_flags: "hiddenapi/all-flags.csv",
|
||||
},
|
||||
}
|
||||
@@ -494,10 +494,10 @@ sdk_snapshot {
|
||||
}
|
||||
`),
|
||||
checkAllCopyRules(`
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/all-flags.csv -> hiddenapi/all-flags.csv
|
||||
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
|
||||
.intermediates/myothersdklibrary.stubs/android_common/javac/myothersdklibrary.stubs.jar -> sdk_library/public/myothersdklibrary-stubs.jar
|
||||
@@ -636,10 +636,10 @@ prebuilt_bootclasspath_fragment {
|
||||
},
|
||||
],
|
||||
hidden_api: {
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
annotation_flags: "hiddenapi/annotation-flags.csv",
|
||||
metadata: "hiddenapi/metadata.csv",
|
||||
index: "hiddenapi/index.csv",
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
all_flags: "hiddenapi/all-flags.csv",
|
||||
},
|
||||
}
|
||||
@@ -838,10 +838,10 @@ prebuilt_bootclasspath_fragment {
|
||||
max_target_o_low_priority: ["hiddenapi/my-max-target-o-low-priority.txt"],
|
||||
blocked: ["hiddenapi/my-blocked.txt"],
|
||||
unsupported_packages: ["hiddenapi/my-unsupported-packages.txt"],
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
annotation_flags: "hiddenapi/annotation-flags.csv",
|
||||
metadata: "hiddenapi/metadata.csv",
|
||||
index: "hiddenapi/index.csv",
|
||||
stub_flags: "hiddenapi/stub-flags.csv",
|
||||
all_flags: "hiddenapi/all-flags.csv",
|
||||
},
|
||||
}
|
||||
@@ -881,10 +881,10 @@ my-max-target-p.txt -> hiddenapi/my-max-target-p.txt
|
||||
my-max-target-o-low-priority.txt -> hiddenapi/my-max-target-o-low-priority.txt
|
||||
my-blocked.txt -> hiddenapi/my-blocked.txt
|
||||
my-unsupported-packages.txt -> hiddenapi/my-unsupported-packages.txt
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
|
||||
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/all-flags.csv -> hiddenapi/all-flags.csv
|
||||
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
|
||||
.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
|
||||
|
Reference in New Issue
Block a user