Validate monolithic and modular hidden API flags are consistent
This makes sure that where there is overlap between the hidden API flags generated for a module and the monolithic flags that they are identical. That ensures that the modular hidden API flags will be compatible with previous releases that relied on the monolithic flags. Bug: 179354495 Test: m out/soong/.intermediates/art/build/boot/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/all-flags.csv m out/soong/hiddenapi/hiddenapi-flags.csv - Create some inconsistencies between the above two files. m out/soong/hiddenapi/hiddenapi-flags.csv.valid Change-Id: Iaf9e23cef63e221608955d89dc8d496bcc70c86e
This commit is contained in:
parent
2fef136885
commit
dfa1083fee
|
@ -15,6 +15,8 @@
|
|||
package java
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"android/soong/android"
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
@ -378,6 +380,16 @@ func (i *hiddenAPIFlagFileInfo) append(other hiddenAPIFlagFileInfo) {
|
|||
|
||||
var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})
|
||||
|
||||
// pathForValidation creates a path of the same type as the supplied type but with a name of
|
||||
// <path>.valid.
|
||||
//
|
||||
// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
|
||||
// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
|
||||
func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
|
||||
extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
|
||||
return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
|
||||
}
|
||||
|
||||
// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
|
||||
// the flags from all the modules, the stub flags, augmented with some additional configuration
|
||||
// files.
|
||||
|
@ -392,6 +404,30 @@ var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{
|
|||
// augmentationInfo is a struct containing paths to files that augment the information provided by
|
||||
// the moduleSpecificFlagsPaths.
|
||||
func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, baseFlagsPath android.Path, moduleSpecificFlagsPaths android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
|
||||
|
||||
// The file which is used to record that the flags file is valid.
|
||||
var validFile android.WritablePath
|
||||
|
||||
// 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 allFlagsPaths := flagFileInfo.AllFlagsPaths; len(allFlagsPaths) > 0 {
|
||||
// The flags file generated by the rule created by this method needs to be validated to ensure
|
||||
// that it is consistent with the flag files generated by the individual fragments.
|
||||
|
||||
validFile = pathForValidation(ctx, outputPath)
|
||||
|
||||
// Create a rule to validate the output from the following rule.
|
||||
rule := android.NewRuleBuilder(pctx, ctx)
|
||||
rule.Command().
|
||||
BuiltTool("verify_overlaps").
|
||||
Input(outputPath).
|
||||
Inputs(allFlagsPaths).
|
||||
// If validation passes then update the file that records that.
|
||||
Text("&& touch").Output(validFile)
|
||||
rule.Build(name+"Validation", desc+" validation")
|
||||
}
|
||||
|
||||
// Create the rule that will generate the flag files.
|
||||
tempPath := tempPathForRestat(ctx, outputPath)
|
||||
rule := android.NewRuleBuilder(pctx, ctx)
|
||||
command := rule.Command().
|
||||
|
@ -410,6 +446,14 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
|
|||
|
||||
commitChangeForRestat(rule, tempPath, outputPath)
|
||||
|
||||
if validFile != nil {
|
||||
// Add the file that indicates that the file generated by this is valid.
|
||||
//
|
||||
// This will cause the validation rule above to be run any time that the output of this rule
|
||||
// changes but the validation will run in parallel with other rules that depend on this file.
|
||||
command.Validation(validFile)
|
||||
}
|
||||
|
||||
rule.Build(name, desc)
|
||||
}
|
||||
|
||||
|
|
|
@ -47,3 +47,18 @@ python_binary_host {
|
|||
},
|
||||
},
|
||||
}
|
||||
|
||||
python_binary_host {
|
||||
name: "verify_overlaps",
|
||||
main: "verify_overlaps.py",
|
||||
srcs: ["verify_overlaps.py"],
|
||||
version: {
|
||||
py2: {
|
||||
enabled: false,
|
||||
},
|
||||
py3: {
|
||||
enabled: true,
|
||||
embedded_launcher: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2018 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.
|
||||
"""
|
||||
Verify that one set of hidden API flags is a subset of another.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
|
||||
args_parser = argparse.ArgumentParser(description='Verify that one set of hidden API flags is a subset of another.')
|
||||
args_parser.add_argument('all', help='All the flags')
|
||||
args_parser.add_argument('subsets', nargs=argparse.REMAINDER, help='Subsets of the flags')
|
||||
args = args_parser.parse_args()
|
||||
|
||||
|
||||
def dict_reader(input):
|
||||
return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature'])
|
||||
|
||||
# Read in all the flags into a dict indexed by signature
|
||||
allFlagsBySignature = {}
|
||||
with open(args.all, 'r') as allFlagsFile:
|
||||
allFlagsReader = dict_reader(allFlagsFile)
|
||||
for row in allFlagsReader:
|
||||
signature = row['signature']
|
||||
allFlagsBySignature[signature]=row
|
||||
|
||||
failed = False
|
||||
for subsetPath in args.subsets:
|
||||
mismatchingSignatures = []
|
||||
with open(subsetPath, 'r') as subsetFlagsFile:
|
||||
subsetReader = dict_reader(subsetFlagsFile)
|
||||
for row in subsetReader:
|
||||
signature = row['signature']
|
||||
if signature in allFlagsBySignature:
|
||||
allFlags = allFlagsBySignature.get(signature)
|
||||
if allFlags != row:
|
||||
mismatchingSignatures.append((signature, row[None], allFlags[None]))
|
||||
else:
|
||||
mismatchingSignatures.append((signature, row[None], []))
|
||||
|
||||
|
||||
if mismatchingSignatures:
|
||||
failed = True
|
||||
print("ERROR: Hidden API flags are inconsistent:")
|
||||
print("< " + subsetPath)
|
||||
print("> " + args.all)
|
||||
for mismatch in mismatchingSignatures:
|
||||
print()
|
||||
print("< " + mismatch[0] + "," + ",".join(mismatch[1]))
|
||||
if mismatch[2] != None:
|
||||
print("> " + mismatch[0] + "," + ",".join(mismatch[2]))
|
||||
else:
|
||||
print("> " + mismatch[0] + " - missing")
|
||||
|
||||
if failed:
|
||||
sys.exit(1)
|
Loading…
Reference in New Issue