Browse Source

Add --no-ndk to ndkstubgen

By default, ndkstubgen does not omit NDK symbols as long as they
satisfy the API version and the CPU architecture requirements. This
change adds a new flag --no-ndk to ndkstubgen which is used to
override the default behavior. If the flag is set, NDK symbols are
omitted leaving only the annotated symbols (e.g. #apex, #systemapi,
etc.).

This will be used for stub libraries that are not part of NDK. So far,
symbols in such libraries haven't needed to be annotated as #apex, and
that has caused a confusion that those symbols belong to NDK. The
follow-up change will ensure that those symbols are always annoated as
either #apex or #systemapi so that their roles are clearly visible.

Bug: 184712170
Test: atest test_ndkstubgen
Test: atest test_symbolfile
Change-Id: Ic8d2c7d0b32bdef79f7563621035e60f406e4131
Jiyong Park 1 year ago
parent
commit
4ecbdb6dfd

+ 6 - 1
cc/ndkstubgen/__init__.py

@@ -111,6 +111,11 @@ def parse_args() -> argparse.Namespace:
         action='store_true',
         dest='systemapi',
         help='Use the SystemAPI variant.')
+    parser.add_argument(
+        '--no-ndk',
+        action='store_false',
+        dest='ndk',
+        help='Do not include NDK APIs.')
 
     parser.add_argument('--api-map',
                         type=resolved_path,
@@ -147,7 +152,7 @@ def main() -> None:
         verbosity = 2
     logging.basicConfig(level=verbose_map[verbosity])
 
-    filt = symbolfile.Filter(args.arch, api, args.llndk, args.apex, args.systemapi)
+    filt = symbolfile.Filter(args.arch, api, args.llndk, args.apex, args.systemapi, args.ndk)
     with args.symbol_file.open() as symbol_file:
         try:
           versions = symbolfile.SymbolFileParser(symbol_file, api_map, filt).parse()

+ 39 - 0
cc/ndkstubgen/test_ndkstubgen.py

@@ -424,6 +424,45 @@ class IntegrationTest(unittest.TestCase):
         """)
         self.assertEqual(expected_version, version_file.getvalue())
 
+    def test_integration_with_nondk(self) -> None:
+        input_file = io.StringIO(textwrap.dedent("""\
+            VERSION_1 {
+                global:
+                    foo;
+                    bar; # apex
+                local:
+                    *;
+            };
+        """))
+        f = copy(self.filter)
+        f.apex = True
+        f.ndk = False   # ndk symbols should be excluded
+        parser = symbolfile.SymbolFileParser(input_file, {}, f)
+        versions = parser.parse()
+
+        src_file = io.StringIO()
+        version_file = io.StringIO()
+        symbol_list_file = io.StringIO()
+        f = copy(self.filter)
+        f.apex = True
+        f.ndk = False   # ndk symbols should be excluded
+        generator = ndkstubgen.Generator(src_file,
+                                         version_file, symbol_list_file, f)
+        generator.write(versions)
+
+        expected_src = textwrap.dedent("""\
+            void bar() {}
+        """)
+        self.assertEqual(expected_src, src_file.getvalue())
+
+        expected_version = textwrap.dedent("""\
+            VERSION_1 {
+                global:
+                    bar;
+            };
+        """)
+        self.assertEqual(expected_version, version_file.getvalue())
+
     def test_empty_stub(self) -> None:
         """Tests that empty stubs can be generated.
 

+ 9 - 2
cc/symbolfile/__init__.py

@@ -208,12 +208,14 @@ class Filter:
     symbol should be omitted or not
     """
 
-    def __init__(self, arch: Arch, api: int, llndk: bool = False, apex: bool = False, systemapi: bool = False):
+    def __init__(self, arch: Arch, api: int, llndk: bool = False, apex: bool = False, systemapi:
+                 bool = False, ndk: bool = True):
         self.arch = arch
         self.api = api
         self.llndk = llndk
         self.apex = apex
         self.systemapi = systemapi
+        self.ndk = ndk
 
     def _should_omit_tags(self, tags: Tags) -> bool:
         """Returns True if the tagged object should be omitted.
@@ -253,8 +255,13 @@ class Filter:
 
     def should_omit_symbol(self, symbol: Symbol) -> bool:
         """Returns True if the symbol should be omitted."""
-        return self._should_omit_tags(symbol.tags)
+        if not symbol.tags.has_mode_tags and not self.ndk:
+            # Symbols that don't have mode tags are NDK. They are usually
+            # included, but have to be omitted if NDK symbols are explicitly
+            # filtered-out
+            return True
 
+        return self._should_omit_tags(symbol.tags)
 
 def symbol_in_arch(tags: Tags, arch: Arch) -> bool:
     """Returns true if the symbol is present for the given architecture."""

+ 14 - 0
cc/symbolfile/test_symbolfile.py

@@ -308,6 +308,20 @@ class OmitSymbolTest(unittest.TestCase):
     def assertInclude(self, f: Filter, s: Symbol) -> None:
         self.assertFalse(f.should_omit_symbol(s))
 
+    def test_omit_ndk(self) -> None:
+        f_ndk = self.filter
+        f_nondk = copy(f_ndk)
+        f_nondk.ndk = False
+        f_nondk.apex = True
+
+        s_ndk = Symbol('foo', Tags())
+        s_nonndk = Symbol('foo', Tags.from_strs(['apex']))
+
+        self.assertInclude(f_ndk, s_ndk)
+        self.assertOmit(f_ndk, s_nonndk)
+        self.assertOmit(f_nondk, s_ndk)
+        self.assertInclude(f_nondk, s_nonndk)
+
     def test_omit_llndk(self) -> None:
         f_none = self.filter
         f_llndk = copy(f_none)