Merge "Scudo minimal runtime support for Soong"
diff --git a/android/neverallow.go b/android/neverallow.go
index 217a8d4..d3a2801 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -56,7 +56,9 @@
without("vendor", "true").
without("owner", "").
because("a VNDK module can never have an owner."),
- neverallow().notIn("libcore", "development", "external/bouncycastle", "external/conscrypt", "external/okhttp").with("no_standard_libs", "true"),
+ neverallow().
+ notIn("libcore", "development", "external/apache-harmony", "external/apache-xml", "external/bouncycastle", "external/conscrypt", "external/icu", "external/okhttp", "external/wycheproof").
+ with("no_standard_libs", "true"),
// TODO(b/67974785): always enforce the manifest
neverallow().
diff --git a/cc/builder.go b/cc/builder.go
index d16efd0..d9a6cae 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -169,7 +169,7 @@
// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
sAbiDump = pctx.AndroidStaticRule("sAbiDump",
blueprint.RuleParams{
- Command: "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem ${config.RSIncludePath}",
+ Command: "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
CommandDeps: []string{"$sAbiDumper"},
},
"cFlags", "exportDirs")
diff --git a/cc/config/global.go b/cc/config/global.go
index 29dca9f..330cb10 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -125,8 +125,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r339409"
- ClangDefaultShortVersion = "8.0.1"
+ ClangDefaultVersion = "clang-r339409b"
+ ClangDefaultShortVersion = "8.0.2"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 988ba03..6300a1b 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -47,18 +47,11 @@
"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include",
}
- windowsClangCppflags = []string{
- "-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3",
- "-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/backward",
- }
+ windowsClangCppflags = []string{}
- windowsX86ClangCppflags = []string{
- "-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/${WindowsGccTriple}/32",
- }
+ windowsX86ClangCppflags = []string{}
- windowsX8664ClangCppflags = []string{
- "-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/${WindowsGccTriple}",
- }
+ windowsX8664ClangCppflags = []string{}
windowsLdflags = []string{
"--enable-stdcall-fixup",
@@ -80,24 +73,18 @@
"-m32",
"-Wl,--large-address-aware",
"-L${WindowsGccRoot}/${WindowsGccTriple}/lib32",
- "-static-libgcc",
}
windowsX86ClangLdflags = append(ClangFilterUnknownCflags(windowsX86Ldflags), []string{
"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
"-B${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
"-B${WindowsGccRoot}/${WindowsGccTriple}/lib32",
- "-pthread",
- // Bug: http://b/109759970 - WAR until issue with ld.bfd's
- // inability to handle Clang-generated section names is fixed.
- "-Wl,--allow-multiple-definition",
}...)
windowsX86ClangLldflags = ClangFilterUnknownLldflags(windowsX86ClangLdflags)
windowsX8664Ldflags = []string{
"-m64",
"-L${WindowsGccRoot}/${WindowsGccTriple}/lib64",
- "-static-libgcc",
"-Wl,--high-entropy-va",
}
windowsX8664ClangLdflags = append(ClangFilterUnknownCflags(windowsX8664Ldflags), []string{
@@ -105,7 +92,6 @@
"-B${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
"-B${WindowsGccRoot}/${WindowsGccTriple}/lib64",
- "-pthread",
}...)
windowsX8664ClangLldflags = ClangFilterUnknownLldflags(windowsX8664ClangLdflags)
diff --git a/cc/gen_stub_libs.py b/cc/gen_stub_libs.py
index 8c99bbf..c49d197 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/gen_stub_libs.py
@@ -20,6 +20,7 @@
import logging
import os
import re
+import sys
ALL_ARCHITECTURES = (
@@ -107,22 +108,33 @@
return version.endswith('_PRIVATE') or version.endswith('_PLATFORM')
-def should_omit_version(name, tags, arch, api, vndk):
+def should_omit_version(version, arch, api, vndk):
"""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
stub library. Sections that contain entirely future symbols or only symbols
for certain architectures.
"""
- if version_is_private(name):
+ if version_is_private(version.name):
return True
- if 'platform-only' in tags:
+ if 'platform-only' in version.tags:
return True
- if 'vndk' in tags and not vndk:
+ if 'vndk' in version.tags and not vndk:
return True
- if not symbol_in_arch(tags, arch):
+ if not symbol_in_arch(version.tags, arch):
return True
- if not symbol_in_api(tags, arch, api):
+ if not symbol_in_api(version.tags, arch, api):
+ return True
+ return False
+
+
+def should_omit_symbol(symbol, arch, api, vndk):
+ """Returns True if the symbol should be omitted."""
+ if not vndk and 'vndk' in symbol.tags:
+ return True
+ if not symbol_in_arch(symbol.tags, arch):
+ return True
+ if not symbol_in_api(symbol.tags, arch, api):
return True
return False
@@ -189,6 +201,15 @@
pass
+class MultiplyDefinedSymbolError(RuntimeError):
+ """A symbol name was multiply defined."""
+ def __init__(self, multiply_defined_symbols):
+ super(MultiplyDefinedSymbolError, self).__init__(
+ 'Version script contains multiple definitions for: {}'.format(
+ ', '.join(multiply_defined_symbols)))
+ self.multiply_defined_symbols = multiply_defined_symbols
+
+
class Version(object):
"""A version block of a symbol file."""
def __init__(self, name, base, tags, symbols):
@@ -221,9 +242,12 @@
class SymbolFileParser(object):
"""Parses NDK symbol files."""
- def __init__(self, input_file, api_map):
+ def __init__(self, input_file, api_map, arch, api, vndk):
self.input_file = input_file
self.api_map = api_map
+ self.arch = arch
+ self.api = api
+ self.vndk = vndk
self.current_line = None
def parse(self):
@@ -235,8 +259,36 @@
else:
raise ParseError(
'Unexpected contents at top level: ' + self.current_line)
+
+ self.check_no_duplicate_symbols(versions)
return versions
+ def check_no_duplicate_symbols(self, versions):
+ """Raises errors for multiply defined symbols.
+
+ This situation is the normal case when symbol versioning is actually
+ used, but this script doesn't currently handle that. The error message
+ will be a not necessarily obvious "error: redefition of 'foo'" from
+ stub.c, so it's better for us to catch this situation and raise a
+ better error.
+ """
+ symbol_names = set()
+ multiply_defined_symbols = set()
+ for version in versions:
+ if should_omit_version(version, self.arch, self.api, self.vndk):
+ continue
+
+ for symbol in version.symbols:
+ if should_omit_symbol(symbol, self.arch, self.api, self.vndk):
+ continue
+
+ if symbol.name in symbol_names:
+ multiply_defined_symbols.add(symbol.name)
+ symbol_names.add(symbol.name)
+ if multiply_defined_symbols:
+ raise MultiplyDefinedSymbolError(
+ sorted(list(multiply_defined_symbols)))
+
def parse_version(self):
"""Parses a single version section and returns a Version object."""
name = self.current_line.split('{')[0].strip()
@@ -274,7 +326,8 @@
elif global_scope and not cpp_symbols:
symbols.append(self.parse_symbol())
else:
- # We're in a hidden scope or in 'extern "C++"' block. Ignore everything.
+ # We're in a hidden scope or in 'extern "C++"' block. Ignore
+ # everything.
pass
raise ParseError('Unexpected EOF in version block.')
@@ -324,20 +377,14 @@
def write_version(self, version):
"""Writes a single version block's data to the output files."""
- name = version.name
- tags = version.tags
- if should_omit_version(name, tags, self.arch, self.api, self.vndk):
+ if should_omit_version(version, self.arch, self.api, self.vndk):
return
- section_versioned = symbol_versioned_in_api(tags, self.api)
+ section_versioned = symbol_versioned_in_api(version.tags, self.api)
version_empty = True
pruned_symbols = []
for symbol in version.symbols:
- if not self.vndk and 'vndk' in symbol.tags:
- continue
- if not symbol_in_arch(symbol.tags, self.arch):
- continue
- if not symbol_in_api(symbol.tags, self.arch, self.api):
+ if should_omit_symbol(symbol, self.arch, self.api, self.vndk):
continue
if symbol_versioned_in_api(symbol.tags, self.api):
@@ -432,7 +479,11 @@
logging.basicConfig(level=verbose_map[verbosity])
with open(args.symbol_file) as symbol_file:
- versions = SymbolFileParser(symbol_file, api_map).parse()
+ try:
+ versions = SymbolFileParser(symbol_file, api_map, args.arch, api,
+ args.vndk).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:
diff --git a/cc/stl.go b/cc/stl.go
index f44902e..8eee612 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -81,9 +81,9 @@
}
} else if ctx.Windows() {
switch s {
- case "libc++", "libc++_static", "libstdc++", "":
- // libc++ is not supported on mingw
- return "libstdc++"
+ case "libc++", "libc++_static", "":
+ // Only use static libc++ for Windows.
+ return "libc++_static"
case "none":
return ""
default:
@@ -177,6 +177,20 @@
} else {
flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...)
}
+ if ctx.Windows() {
+ // Use SjLj exceptions for 32-bit. libgcc_eh implements SjLj
+ // exception model for 32-bit.
+ if ctx.Arch().ArchType == android.X86 {
+ flags.CppFlags = append(flags.CppFlags, "-fsjlj-exceptions")
+ }
+ flags.CppFlags = append(flags.CppFlags,
+ // Disable visiblity annotations since we're using static
+ // libc++.
+ "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+ "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+ // Use Win32 threads in libc++.
+ "-D_LIBCPP_HAS_THREAD_API_WIN32")
+ }
} else {
if ctx.Arch().ArchType == android.Arm {
flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,libunwind_llvm.a")
@@ -213,9 +227,10 @@
hostDynamicGccLibs = map[android.OsType][]string{
android.Linux: []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"},
android.Darwin: []string{"-lc", "-lSystem"},
- android.Windows: []string{"-lmingw32", "-lgcc", "-lmoldname", "-lmingwex", "-lmsvcr110",
- "-lmsvcrt", "-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lmingw32",
- "-lgcc", "-lmoldname", "-lmingwex", "-lmsvcrt"},
+ android.Windows: []string{"-Wl,--start-group", "-lmingw32", "-lgcc", "-lgcc_eh",
+ "-lmoldname", "-lmingwex", "-lmsvcr110", "-lmsvcrt", "-lpthread",
+ "-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lpsapi",
+ "-Wl,--end-group"},
}
hostStaticGccLibs = map[android.OsType][]string{
android.Linux: []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"},
diff --git a/cc/test_gen_stub_libs.py b/cc/test_gen_stub_libs.py
index b20a5c7..3b5585a 100755
--- a/cc/test_gen_stub_libs.py
+++ b/cc/test_gen_stub_libs.py
@@ -15,7 +15,7 @@
# limitations under the License.
#
"""Tests for gen_stub_libs.py."""
-import cStringIO
+import io
import textwrap
import unittest
@@ -163,51 +163,106 @@
class OmitVersionTest(unittest.TestCase):
def test_omit_private(self):
- self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
-
- self.assertTrue(gsl.should_omit_version(
- 'foo_PRIVATE', [], 'arm', 9, False))
- self.assertTrue(gsl.should_omit_version(
- 'foo_PLATFORM', [], 'arm', 9, False))
-
- self.assertTrue(gsl.should_omit_version(
- 'foo', ['platform-only'], 'arm', 9, False))
-
- def test_omit_vndk(self):
- self.assertTrue(gsl.should_omit_version(
- 'foo', ['vndk'], 'arm', 9, False))
-
- self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, True))
- self.assertFalse(gsl.should_omit_version(
- 'foo', ['vndk'], 'arm', 9, True))
-
- def test_omit_arch(self):
- self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
- self.assertFalse(gsl.should_omit_version(
- 'foo', ['arm'], 'arm', 9, False))
-
- self.assertTrue(gsl.should_omit_version(
- 'foo', ['x86'], 'arm', 9, False))
-
- def test_omit_api(self):
- self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
self.assertFalse(
- gsl.should_omit_version('foo', ['introduced=9'], 'arm', 9, False))
+ gsl.should_omit_version(
+ gsl.Version('foo', None, [], []), 'arm', 9, False))
self.assertTrue(
- gsl.should_omit_version('foo', ['introduced=14'], 'arm', 9, False))
+ gsl.should_omit_version(
+ gsl.Version('foo_PRIVATE', None, [], []), 'arm', 9, False))
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo_PLATFORM', None, [], []), 'arm', 9, False))
+
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['platform-only'], []), 'arm', 9,
+ False))
+
+ def test_omit_vndk(self):
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['vndk'], []), 'arm', 9, False))
+
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, [], []), 'arm', 9, True))
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['vndk'], []), 'arm', 9, True))
+
+ def test_omit_arch(self):
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, [], []), 'arm', 9, False))
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['arm'], []), 'arm', 9, False))
+
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['x86'], []), 'arm', 9, False))
+
+ def test_omit_api(self):
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, [], []), 'arm', 9, False))
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['introduced=9'], []), 'arm', 9,
+ False))
+
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['introduced=14'], []), 'arm', 9,
+ False))
+
+
+class OmitSymbolTest(unittest.TestCase):
+ def test_omit_vndk(self):
+ self.assertTrue(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['vndk']), 'arm', 9, False))
+
+ self.assertFalse(
+ gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, True))
+ self.assertFalse(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['vndk']), 'arm', 9, True))
+
+ def test_omit_arch(self):
+ self.assertFalse(
+ gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False))
+ self.assertFalse(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['arm']), 'arm', 9, False))
+
+ self.assertTrue(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['x86']), 'arm', 9, False))
+
+ def test_omit_api(self):
+ self.assertFalse(
+ gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False))
+ self.assertFalse(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['introduced=9']), 'arm', 9, False))
+
+ self.assertTrue(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['introduced=14']), 'arm', 9, False))
class SymbolFileParseTest(unittest.TestCase):
def test_next_line(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
foo
bar
# baz
qux
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
self.assertIsNone(parser.current_line)
self.assertEqual('foo', parser.next_line().strip())
@@ -223,7 +278,7 @@
self.assertEqual('', parser.current_line)
def test_parse_version(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 { # foo bar
baz;
qux; # woodly doodly
@@ -232,7 +287,7 @@
VERSION_2 {
} VERSION_1; # asdf
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
version = parser.parse_version()
@@ -253,31 +308,31 @@
self.assertEqual([], version.tags)
def test_parse_version_eof(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
with self.assertRaises(gsl.ParseError):
parser.parse_version()
def test_unknown_scope_label(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
foo:
}
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
with self.assertRaises(gsl.ParseError):
parser.parse_version()
def test_parse_symbol(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
foo;
bar; # baz qux
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
symbol = parser.parse_symbol()
@@ -290,47 +345,47 @@
self.assertEqual(['baz', 'qux'], symbol.tags)
def test_wildcard_symbol_global(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
*;
};
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
with self.assertRaises(gsl.ParseError):
parser.parse_version()
def test_wildcard_symbol_local(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
local:
*;
};
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
version = parser.parse_version()
self.assertEqual([], version.symbols)
def test_missing_semicolon(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
foo
};
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
with self.assertRaises(gsl.ParseError):
parser.parse_version()
def test_parse_fails_invalid_input(self):
with self.assertRaises(gsl.ParseError):
- input_file = cStringIO.StringIO('foo')
- parser = gsl.SymbolFileParser(input_file, {})
+ input_file = io.StringIO('foo')
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.parse()
def test_parse(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
local:
hidden1;
@@ -347,7 +402,7 @@
qwerty;
} VERSION_1;
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
versions = parser.parse()
expected = [
@@ -368,8 +423,8 @@
def test_omit_version(self):
# Thorough testing of the cases involved here is handled by
# OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
version = gsl.Version('VERSION_PRIVATE', None, [], [
@@ -396,8 +451,8 @@
def test_omit_symbol(self):
# Thorough testing of the cases involved here is handled by
# SymbolPresenceTest.
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
version = gsl.Version('VERSION_1', None, [], [
@@ -422,8 +477,8 @@
self.assertEqual('', version_file.getvalue())
def test_write(self):
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
versions = [
@@ -475,7 +530,7 @@
'P': 9001,
}
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
global:
foo; # var
@@ -505,11 +560,11 @@
wobble;
} VERSION_4;
"""))
- parser = gsl.SymbolFileParser(input_file, api_map)
+ parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9, False)
versions = parser.parse()
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
generator.write(versions)
@@ -545,7 +600,7 @@
'Q': 9002,
}
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
global:
foo; # introduced=O
@@ -555,11 +610,11 @@
*;
};
"""))
- parser = gsl.SymbolFileParser(input_file, api_map)
+ parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9001, False)
versions = parser.parse()
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9001, False)
generator.write(versions)
@@ -578,6 +633,38 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
+ def test_multiple_definition(self):
+ input_file = io.StringIO(textwrap.dedent("""\
+ VERSION_1 {
+ global:
+ foo;
+ foo;
+ bar;
+ baz;
+ qux; # arm
+ local:
+ *;
+ };
+
+ VERSION_2 {
+ global:
+ bar;
+ qux; # arm64
+ } VERSION_1;
+
+ VERSION_PRIVATE {
+ global:
+ baz;
+ } VERSION_2;
+
+ """))
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
+
+ with self.assertRaises(gsl.MultiplyDefinedSymbolError) as cm:
+ parser.parse()
+ self.assertEquals(['bar', 'foo'],
+ cm.exception.multiply_defined_symbols)
+
def main():
suite = unittest.TestLoader().loadTestsFromName(__name__)
diff --git a/java/java.go b/java/java.go
index c5414f4..e5218bb 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1757,7 +1757,7 @@
// solution to get the Import name.
name := j.Name()
if strings.HasPrefix(name, removedPrefix) {
- name = strings.Trim(name, removedPrefix)
+ name = strings.TrimPrefix(name, removedPrefix)
}
return name
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index c1b8880..e513a59 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -128,6 +128,11 @@
// Defaults to "android.annotation".
Srcs_lib_whitelist_pkgs []string
+ // if set to true, create stubs through Metalava instead of Doclava. Javadoc/Doclava is
+ // currently still used for documentation generation, and will be replaced by Dokka soon.
+ // Defaults to true.
+ Metalava_enabled *bool
+
// TODO: determines whether to create HTML doc or not
//Html_doc *bool
}
@@ -417,7 +422,6 @@
props := struct {
Name *string
Srcs []string
- Custom_template *string
Installable *bool
Srcs_lib *string
Srcs_lib_whitelist_dirs []string
@@ -436,11 +440,13 @@
Local_include_dirs []string
}
}{}
+ droiddocProps := struct {
+ Custom_template *string
+ }{}
props.Name = proptools.StringPtr(module.docsName(apiScope))
props.Srcs = append(props.Srcs, module.properties.Srcs...)
props.Srcs = append(props.Srcs, module.properties.Api_srcs...)
- props.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
props.Installable = proptools.BoolPtr(false)
// A droiddoc module has only one Libs property and doesn't distinguish between
// shared libs and static libs. So we need to add both of these libs to Libs property.
@@ -449,10 +455,26 @@
props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
- droiddocArgs := " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128" +
- " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
- " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, "-hidePackage ") +
- " " + android.JoinWithPrefix(module.properties.Droiddoc_options, "-") + " -nodocs"
+ if module.properties.Metalava_enabled == nil {
+ module.properties.Metalava_enabled = proptools.BoolPtr(true)
+ }
+
+ droiddocArgs := ""
+ if Bool(module.properties.Metalava_enabled) == true {
+ droiddocArgs = " --stub-packages " + strings.Join(module.properties.Api_packages, ":") +
+ " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " --hide-package ") +
+ " " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
+ " --hide MissingPermission --hide BroadcastBehavior " +
+ "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+ "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
+ } else {
+ droiddocProps.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
+ droiddocArgs = " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
+ " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " -hidePackage ") +
+ " " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
+ " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128 -nodocs"
+ }
+
switch apiScope {
case apiScopeSystem:
droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
@@ -484,36 +506,40 @@
// check against the not-yet-release API
props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
- // any change is reported as error
- props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
- "-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
- "-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
- "-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
// check against the latest released API
props.Check_api.Last_released.Api_file = proptools.StringPtr(
module.latestApiFilegroupName(apiScope))
props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
module.latestRemovedApiFilegroupName(apiScope))
- // backward incompatible changes are reported as error
- props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
- "-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
- "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
- "-error 15 -error 16 -error 17 -error 18")
+ if Bool(module.properties.Metalava_enabled) == false {
+ // any change is reported as error
+ props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
+ "-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
+ "-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
+ "-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
- // Include the part of the framework source. This is required for the case when
- // API class is extending from the framework class. In that case, doclava needs
- // to know whether the base class is hidden or not. Since that information is
- // encoded as @hide string in the comment, we need source files for the classes,
- // not the compiled ones.
- props.Srcs_lib = proptools.StringPtr("framework")
- props.Srcs_lib_whitelist_dirs = []string{"core/java"}
- // Add android.annotation package to give access to the framework-defined
- // annotations such as SystemApi, NonNull, etc.
- if module.properties.Srcs_lib_whitelist_pkgs != nil {
- props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
- } else {
- props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
+ // backward incompatible changes are reported as error
+ props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
+ "-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
+ "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
+ "-error 15 -error 16 -error 17 -error 18")
+
+ // Include the part of the framework source. This is required for the case when
+ // API class is extending from the framework class. In that case, doclava needs
+ // to know whether the base class is hidden or not. Since that information is
+ // encoded as @hide string in the comment, we need source files for the classes,
+ // not the compiled ones.
+ props.Srcs_lib = proptools.StringPtr("framework")
+ props.Srcs_lib_whitelist_dirs = []string{"core/java"}
+
+ // Add android.annotation package to give access to the framework-defined
+ // annotations such as SystemApi, NonNull, etc.
+ if module.properties.Srcs_lib_whitelist_pkgs != nil {
+ props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
+ } else {
+ props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
+ }
}
// These libs are required by doclava to parse the framework sources add via
// Src_lib and Src_lib_whitelist_* properties just above.
@@ -521,7 +547,11 @@
// though they don't break the build.
props.Libs = append(props.Libs, "framework")
- mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props)
+ if Bool(module.properties.Metalava_enabled) == true {
+ mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
+ } else {
+ mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props, &droiddocProps)
+ }
}
// Creates the runtime library. This is not directly linkable from other modules.