From bb4e13536ec188ad3e5623b004703071dea8d4c6 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Fri, 7 Dec 2018 15:54:52 +0900 Subject: [PATCH 1/2] APEX-specific symbols can be tagged as # apex If a symbol is tagged as # apex, then it is exported when gen_stub_libs is invoked with --apex. Bug: 120638081 Test: python3 cc/test_gen_stub_libs.py Change-Id: I190bca35d1a4fb422b37d1be41a34de1ad64de6b --- cc/gen_stub_libs.py | 29 +++--- cc/test_gen_stub_libs.py | 206 +++++++++++++++++++++++++++++++-------- 2 files changed, 184 insertions(+), 51 deletions(-) diff --git a/cc/gen_stub_libs.py b/cc/gen_stub_libs.py index c49d19777..4906ea243 100755 --- a/cc/gen_stub_libs.py +++ b/cc/gen_stub_libs.py @@ -108,7 +108,7 @@ def version_is_private(version): return version.endswith('_PRIVATE') or version.endswith('_PLATFORM') -def should_omit_version(version, arch, api, vndk): +def should_omit_version(version, arch, api, vndk, apex): """Returns True if the version section should be ommitted. We want to omit any sections that do not have any symbols we'll have in the @@ -121,6 +121,8 @@ def should_omit_version(version, arch, api, vndk): return True if 'vndk' in version.tags and not vndk: return True + if 'apex' in version.tags and not apex: + return True if not symbol_in_arch(version.tags, arch): return True if not symbol_in_api(version.tags, arch, api): @@ -128,10 +130,12 @@ def should_omit_version(version, arch, api, vndk): return False -def should_omit_symbol(symbol, arch, api, vndk): +def should_omit_symbol(symbol, arch, api, vndk, apex): """Returns True if the symbol should be omitted.""" if not vndk and 'vndk' in symbol.tags: return True + if not apex and 'apex' in symbol.tags: + return True if not symbol_in_arch(symbol.tags, arch): return True if not symbol_in_api(symbol.tags, arch, api): @@ -239,15 +243,15 @@ class Symbol(object): def __eq__(self, other): return self.name == other.name and set(self.tags) == set(other.tags) - class SymbolFileParser(object): """Parses NDK symbol files.""" - def __init__(self, input_file, api_map, arch, api, vndk): + def __init__(self, input_file, api_map, arch, api, vndk, apex): self.input_file = input_file self.api_map = api_map self.arch = arch self.api = api self.vndk = vndk + self.apex = apex self.current_line = None def parse(self): @@ -275,11 +279,11 @@ class SymbolFileParser(object): symbol_names = set() multiply_defined_symbols = set() for version in versions: - if should_omit_version(version, self.arch, self.api, self.vndk): + if should_omit_version(version, self.arch, self.api, self.vndk, self.apex): continue for symbol in version.symbols: - if should_omit_symbol(symbol, self.arch, self.api, self.vndk): + if should_omit_symbol(symbol, self.arch, self.api, self.vndk, self.apex): continue if symbol.name in symbol_names: @@ -363,12 +367,13 @@ class SymbolFileParser(object): class Generator(object): """Output generator that writes stub source files and version scripts.""" - def __init__(self, src_file, version_script, arch, api, vndk): + def __init__(self, src_file, version_script, arch, api, vndk, apex): self.src_file = src_file self.version_script = version_script self.arch = arch self.api = api self.vndk = vndk + self.apex = apex def write(self, versions): """Writes all symbol data to the output files.""" @@ -377,14 +382,14 @@ class Generator(object): def write_version(self, version): """Writes a single version block's data to the output files.""" - if should_omit_version(version, self.arch, self.api, self.vndk): + if should_omit_version(version, self.arch, self.api, self.vndk, self.apex): return section_versioned = symbol_versioned_in_api(version.tags, self.api) version_empty = True pruned_symbols = [] for symbol in version.symbols: - if should_omit_symbol(symbol, self.arch, self.api, self.vndk): + if should_omit_symbol(symbol, self.arch, self.api, self.vndk, self.apex): continue if symbol_versioned_in_api(symbol.tags, self.api): @@ -447,6 +452,8 @@ def parse_args(): help='Architecture being targeted.') parser.add_argument( '--vndk', action='store_true', help='Use the VNDK variant.') + parser.add_argument( + '--apex', action='store_true', help='Use the APEX variant.') parser.add_argument( '--api-map', type=os.path.realpath, required=True, @@ -481,14 +488,14 @@ def main(): with open(args.symbol_file) as symbol_file: try: versions = SymbolFileParser(symbol_file, api_map, args.arch, api, - args.vndk).parse() + args.vndk, args.apex).parse() except MultiplyDefinedSymbolError as ex: sys.exit('{}: error: {}'.format(args.symbol_file, ex)) with open(args.stub_src, 'w') as src_file: with open(args.version_script, 'w') as version_file: generator = Generator(src_file, version_file, args.arch, api, - args.vndk) + args.vndk, args.apex) generator.write(versions) diff --git a/cc/test_gen_stub_libs.py b/cc/test_gen_stub_libs.py index 3b5585a02..594c1bc74 100755 --- a/cc/test_gen_stub_libs.py +++ b/cc/test_gen_stub_libs.py @@ -165,92 +165,115 @@ class OmitVersionTest(unittest.TestCase): def test_omit_private(self): self.assertFalse( gsl.should_omit_version( - gsl.Version('foo', None, [], []), 'arm', 9, False)) + gsl.Version('foo', None, [], []), 'arm', 9, False, False)) self.assertTrue( gsl.should_omit_version( - gsl.Version('foo_PRIVATE', None, [], []), 'arm', 9, False)) + gsl.Version('foo_PRIVATE', None, [], []), 'arm', 9, False, False)) self.assertTrue( gsl.should_omit_version( - gsl.Version('foo_PLATFORM', None, [], []), 'arm', 9, False)) + gsl.Version('foo_PLATFORM', None, [], []), 'arm', 9, False, False)) self.assertTrue( gsl.should_omit_version( gsl.Version('foo', None, ['platform-only'], []), 'arm', 9, - False)) + False, False)) def test_omit_vndk(self): self.assertTrue( gsl.should_omit_version( - gsl.Version('foo', None, ['vndk'], []), 'arm', 9, False)) + gsl.Version('foo', None, ['vndk'], []), 'arm', 9, False, False)) self.assertFalse( gsl.should_omit_version( - gsl.Version('foo', None, [], []), 'arm', 9, True)) + gsl.Version('foo', None, [], []), 'arm', 9, True, False)) self.assertFalse( gsl.should_omit_version( - gsl.Version('foo', None, ['vndk'], []), 'arm', 9, True)) + gsl.Version('foo', None, ['vndk'], []), 'arm', 9, True, False)) + + def test_omit_apex(self): + self.assertTrue( + gsl.should_omit_version( + gsl.Version('foo', None, ['apex'], []), 'arm', 9, False, False)) + + self.assertFalse( + gsl.should_omit_version( + gsl.Version('foo', None, [], []), 'arm', 9, False, True)) + self.assertFalse( + gsl.should_omit_version( + gsl.Version('foo', None, ['apex'], []), 'arm', 9, False, True)) def test_omit_arch(self): self.assertFalse( gsl.should_omit_version( - gsl.Version('foo', None, [], []), 'arm', 9, False)) + gsl.Version('foo', None, [], []), 'arm', 9, False, False)) self.assertFalse( gsl.should_omit_version( - gsl.Version('foo', None, ['arm'], []), 'arm', 9, False)) + gsl.Version('foo', None, ['arm'], []), 'arm', 9, False, False)) self.assertTrue( gsl.should_omit_version( - gsl.Version('foo', None, ['x86'], []), 'arm', 9, False)) + gsl.Version('foo', None, ['x86'], []), 'arm', 9, False, False)) def test_omit_api(self): self.assertFalse( gsl.should_omit_version( - gsl.Version('foo', None, [], []), 'arm', 9, False)) + gsl.Version('foo', None, [], []), 'arm', 9, False, False)) self.assertFalse( gsl.should_omit_version( gsl.Version('foo', None, ['introduced=9'], []), 'arm', 9, - False)) + False, False)) self.assertTrue( gsl.should_omit_version( gsl.Version('foo', None, ['introduced=14'], []), 'arm', 9, - False)) + False, False)) class OmitSymbolTest(unittest.TestCase): def test_omit_vndk(self): self.assertTrue( gsl.should_omit_symbol( - gsl.Symbol('foo', ['vndk']), 'arm', 9, False)) + gsl.Symbol('foo', ['vndk']), 'arm', 9, False, False)) self.assertFalse( - gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, True)) + gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, True, False)) self.assertFalse( gsl.should_omit_symbol( - gsl.Symbol('foo', ['vndk']), 'arm', 9, True)) + gsl.Symbol('foo', ['vndk']), 'arm', 9, True, False)) + + def test_omit_apex(self): + self.assertTrue( + gsl.should_omit_symbol( + gsl.Symbol('foo', ['apex']), 'arm', 9, False, False)) + + self.assertFalse( + gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False, True)) + self.assertFalse( + gsl.should_omit_symbol( + gsl.Symbol('foo', ['apex']), 'arm', 9, False, True)) def test_omit_arch(self): self.assertFalse( - gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False)) + gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False, False)) self.assertFalse( gsl.should_omit_symbol( - gsl.Symbol('foo', ['arm']), 'arm', 9, False)) + gsl.Symbol('foo', ['arm']), 'arm', 9, False, False)) self.assertTrue( gsl.should_omit_symbol( - gsl.Symbol('foo', ['x86']), 'arm', 9, False)) + gsl.Symbol('foo', ['x86']), 'arm', 9, False, False)) def test_omit_api(self): self.assertFalse( - gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False)) + gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False, False)) self.assertFalse( gsl.should_omit_symbol( - gsl.Symbol('foo', ['introduced=9']), 'arm', 9, False)) + gsl.Symbol('foo', ['introduced=9']), 'arm', 9, False, False)) self.assertTrue( gsl.should_omit_symbol( - gsl.Symbol('foo', ['introduced=14']), 'arm', 9, False)) + gsl.Symbol('foo', ['introduced=14']), 'arm', 9, False, False)) class SymbolFileParseTest(unittest.TestCase): @@ -262,7 +285,7 @@ class SymbolFileParseTest(unittest.TestCase): # baz qux """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) self.assertIsNone(parser.current_line) self.assertEqual('foo', parser.next_line().strip()) @@ -287,7 +310,7 @@ class SymbolFileParseTest(unittest.TestCase): VERSION_2 { } VERSION_1; # asdf """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) parser.next_line() version = parser.parse_version() @@ -311,7 +334,7 @@ class SymbolFileParseTest(unittest.TestCase): input_file = io.StringIO(textwrap.dedent("""\ VERSION_1 { """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) parser.next_line() with self.assertRaises(gsl.ParseError): parser.parse_version() @@ -322,7 +345,7 @@ class SymbolFileParseTest(unittest.TestCase): foo: } """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) parser.next_line() with self.assertRaises(gsl.ParseError): parser.parse_version() @@ -332,7 +355,7 @@ class SymbolFileParseTest(unittest.TestCase): foo; bar; # baz qux """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) parser.next_line() symbol = parser.parse_symbol() @@ -350,7 +373,7 @@ class SymbolFileParseTest(unittest.TestCase): *; }; """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) parser.next_line() with self.assertRaises(gsl.ParseError): parser.parse_version() @@ -362,7 +385,7 @@ class SymbolFileParseTest(unittest.TestCase): *; }; """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) parser.next_line() version = parser.parse_version() self.assertEqual([], version.symbols) @@ -373,7 +396,7 @@ class SymbolFileParseTest(unittest.TestCase): foo }; """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) parser.next_line() with self.assertRaises(gsl.ParseError): parser.parse_version() @@ -381,7 +404,7 @@ class SymbolFileParseTest(unittest.TestCase): def test_parse_fails_invalid_input(self): with self.assertRaises(gsl.ParseError): input_file = io.StringIO('foo') - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) parser.parse() def test_parse(self): @@ -402,7 +425,7 @@ class SymbolFileParseTest(unittest.TestCase): qwerty; } VERSION_1; """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) versions = parser.parse() expected = [ @@ -418,6 +441,30 @@ class SymbolFileParseTest(unittest.TestCase): self.assertEqual(expected, versions) + def test_parse_vndk_apex_symbol(self): + input_file = io.StringIO(textwrap.dedent("""\ + VERSION_1 { + foo; + bar; # vndk + baz; # vndk apex + qux; # apex + }; + """)) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, True) + + parser.next_line() + version = parser.parse_version() + self.assertEqual('VERSION_1', version.name) + self.assertIsNone(version.base) + + expected_symbols = [ + gsl.Symbol('foo', []), + gsl.Symbol('bar', ['vndk']), + gsl.Symbol('baz', ['vndk', 'apex']), + gsl.Symbol('qux', ['apex']), + ] + self.assertEqual(expected_symbols, version.symbols) + class GeneratorTest(unittest.TestCase): def test_omit_version(self): @@ -425,7 +472,7 @@ class GeneratorTest(unittest.TestCase): # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest. src_file = io.StringIO() version_file = io.StringIO() - generator = gsl.Generator(src_file, version_file, 'arm', 9, False) + generator = gsl.Generator(src_file, version_file, 'arm', 9, False, False) version = gsl.Version('VERSION_PRIVATE', None, [], [ gsl.Symbol('foo', []), @@ -453,7 +500,7 @@ class GeneratorTest(unittest.TestCase): # SymbolPresenceTest. src_file = io.StringIO() version_file = io.StringIO() - generator = gsl.Generator(src_file, version_file, 'arm', 9, False) + generator = gsl.Generator(src_file, version_file, 'arm', 9, False, False) version = gsl.Version('VERSION_1', None, [], [ gsl.Symbol('foo', ['x86']), @@ -476,10 +523,17 @@ class GeneratorTest(unittest.TestCase): self.assertEqual('', src_file.getvalue()) self.assertEqual('', version_file.getvalue()) + version = gsl.Version('VERSION_1', None, [], [ + gsl.Symbol('foo', ['apex']), + ]) + generator.write_version(version) + self.assertEqual('', src_file.getvalue()) + self.assertEqual('', version_file.getvalue()) + def test_write(self): src_file = io.StringIO() version_file = io.StringIO() - generator = gsl.Generator(src_file, version_file, 'arm', 9, False) + generator = gsl.Generator(src_file, version_file, 'arm', 9, False, False) versions = [ gsl.Version('VERSION_1', None, [], [ @@ -554,18 +608,19 @@ class IntegrationTest(unittest.TestCase): VERSION_4 { # versioned=9 wibble; wizzes; # vndk + waggle; # apex } VERSION_2; VERSION_5 { # versioned=14 wobble; } VERSION_4; """)) - parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9, False) + parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9, False, False) versions = parser.parse() src_file = io.StringIO() version_file = io.StringIO() - generator = gsl.Generator(src_file, version_file, 'arm', 9, False) + generator = gsl.Generator(src_file, version_file, 'arm', 9, False, False) generator.write(versions) expected_src = textwrap.dedent("""\ @@ -610,12 +665,12 @@ class IntegrationTest(unittest.TestCase): *; }; """)) - parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9001, False) + parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9001, False, False) versions = parser.parse() src_file = io.StringIO() version_file = io.StringIO() - generator = gsl.Generator(src_file, version_file, 'arm', 9001, False) + generator = gsl.Generator(src_file, version_file, 'arm', 9001, False, False) generator.write(versions) expected_src = textwrap.dedent("""\ @@ -658,13 +713,84 @@ class IntegrationTest(unittest.TestCase): } VERSION_2; """)) - parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False) + parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False, False) with self.assertRaises(gsl.MultiplyDefinedSymbolError) as cm: parser.parse() self.assertEquals(['bar', 'foo'], cm.exception.multiply_defined_symbols) + def test_integration_with_apex(self): + api_map = { + 'O': 9000, + 'P': 9001, + } + + input_file = io.StringIO(textwrap.dedent("""\ + VERSION_1 { + global: + foo; # var + bar; # x86 + fizz; # introduced=O + buzz; # introduced=P + local: + *; + }; + + VERSION_2 { # arm + baz; # introduced=9 + qux; # versioned=14 + } VERSION_1; + + VERSION_3 { # introduced=14 + woodly; + doodly; # var + } VERSION_2; + + VERSION_4 { # versioned=9 + wibble; + wizzes; # vndk + waggle; # apex + } VERSION_2; + + VERSION_5 { # versioned=14 + wobble; + } VERSION_4; + """)) + parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9, False, True) + versions = parser.parse() + + src_file = io.StringIO() + version_file = io.StringIO() + generator = gsl.Generator(src_file, version_file, 'arm', 9, False, True) + generator.write(versions) + + expected_src = textwrap.dedent("""\ + int foo = 0; + void baz() {} + void qux() {} + void wibble() {} + void waggle() {} + void wobble() {} + """) + self.assertEqual(expected_src, src_file.getvalue()) + + expected_version = textwrap.dedent("""\ + VERSION_1 { + global: + foo; + }; + VERSION_2 { + global: + baz; + } VERSION_1; + VERSION_4 { + global: + wibble; + waggle; + } VERSION_2; + """) + self.assertEqual(expected_version, version_file.getvalue()) def main(): suite = unittest.TestLoader().loadTestsFromName(__name__) From 3fd0baf6517a317d89be00be7f9be6df29e3a779 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Fri, 7 Dec 2018 16:25:39 +0900 Subject: [PATCH 2/2] When a stub is built for APEX, it is generated with --apex Now, symbols that are only to be visible to across APEXes can be tagged as # vndk. Then when generating the stubs library, the tagged symbol is included. The symbol is NOT included in other cases; build NDK stubs, etc. Bug: 120638081 Test: m (apex_test updated.) Change-Id: Idb2b552badddfc26af113cc8d4b984788f478813 --- apex/apex_test.go | 3 +++ cc/library.go | 2 +- cc/ndk_library.go | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apex/apex_test.go b/apex/apex_test.go index 88c57bc0d..acc895fe9 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -321,6 +321,9 @@ func TestApexWithStubs(t *testing.T) { // Ensure that stubs libs are built without -include flags mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"] ensureNotContains(t, mylib2Cflags, "-include ") + + // Ensure that genstub is invoked with --apex + ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_3_myapex").Rule("genStubSrc").Args["flags"]) } func TestApexWithExplicitStubsDependency(t *testing.T) { diff --git a/cc/library.go b/cc/library.go index 524b88626..86cd5da96 100644 --- a/cc/library.go +++ b/cc/library.go @@ -395,7 +395,7 @@ func extractExportIncludesFromFlags(flags []string) []string { func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects { if library.buildStubs() { - objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "") + objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex") library.versionScriptPath = versionScript return objs } diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 53fe314b7..1b09f88c2 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -31,9 +31,9 @@ var ( genStubSrc = pctx.AndroidStaticRule("genStubSrc", blueprint.RuleParams{ Command: "$toolPath --arch $arch --api $apiLevel --api-map " + - "$apiMap $vndk $in $out", + "$apiMap $flags $in $out", CommandDeps: []string{"$toolPath"}, - }, "arch", "apiLevel", "apiMap", "vndk") + }, "arch", "apiLevel", "apiMap", "flags") ndkLibrarySuffix = ".ndk" @@ -271,7 +271,7 @@ func (stub *stubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps Pa return addStubLibraryCompilerFlags(flags) } -func compileStubLibrary(ctx ModuleContext, flags Flags, symbolFile, apiLevel, vndk string) (Objects, android.ModuleGenPath) { +func compileStubLibrary(ctx ModuleContext, flags Flags, symbolFile, apiLevel, genstubFlags string) (Objects, android.ModuleGenPath) { arch := ctx.Arch().ArchType.String() stubSrcPath := android.PathForModuleGen(ctx, "stub.c") @@ -288,7 +288,7 @@ func compileStubLibrary(ctx ModuleContext, flags Flags, symbolFile, apiLevel, vn "arch": arch, "apiLevel": apiLevel, "apiMap": apiLevelsJson.String(), - "vndk": vndk, + "flags": genstubFlags, }, })