Bug 1579523 - fix visibility definition for future NDKs on Android; r=nalexander
authorNathan Froyd <froydnj@mozilla.com>
Wed, 11 Sep 2019 15:13:36 +0000
changeset 492714 26711f10f5f45471b5856fb5cef08948f0e5bc21
parent 492713 c31093a3a7576d89184d1a5549d0764ce62618c1
child 492715 a9baaa3c4e739a5e9f451564e90afa182799278a
child 492716 9ef1dd77e6b24a408aaac059537ffcf6fa268450
push id114070
push usercbrindusan@mozilla.com
push dateWed, 11 Sep 2019 21:55:52 +0000
treeherdermozilla-inbound@a9baaa3c4e73 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1579523
milestone71.0a1
first release with
nightly linux32
26711f10f5f4 / 71.0a1 / 20190911215306 / files
nightly linux64
26711f10f5f4 / 71.0a1 / 20190911215306 / files
nightly mac
26711f10f5f4 / 71.0a1 / 20190911215306 / files
nightly win32
26711f10f5f4 / 71.0a1 / 20190911215306 / files
nightly win64
26711f10f5f4 / 71.0a1 / 20190911215306 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1579523 - fix visibility definition for future NDKs on Android; r=nalexander A previous patch defined `_LIBCPP_HIDE_FROM_ABI` to the empty string. This definition worked for normal (opt/debug) builds, but PGO-instrumented builds fell over with some linker errors. A closer look at the definition of `_LIBCPP_HIDE_FROM_ABI`: ``` #ifndef _LIBCPP_HIDE_FROM_ABI_PER_TU # ifndef _LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT # define _LIBCPP_HIDE_FROM_ABI_PER_TU 0 # else # define _LIBCPP_HIDE_FROM_ABI_PER_TU 1 # endif #endif #ifndef _LIBCPP_HIDE_FROM_ABI # if _LIBCPP_HIDE_FROM_ABI_PER_TU # define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_INTERNAL_LINKAGE # else # define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION # endif #endif ``` says that there are two macros involved there: one to set hidden visibility (which we don't want), and another to exclude the function definition from explicit instantiation. The semantics of this are not obvious (the clang documentation only documents this attribute in terms of C++ templates; the particular case we're interested in sets the attribute on normal function definitions). But roughly, what this does is that it forces the compiler to see that an equivalent function definition is provided external to the compilation unit, so it doesn't have to keep the annotated function definition around. Differential Revision: https://phabricator.services.mozilla.com/D45073
build/moz.configure/toolchain.configure
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -1360,33 +1360,44 @@ set_config('COLOR_CFLAGS', color_cflags)
 # and the compiler complains about the mismatched visibility declarations.
 #
 # However, libc++ will only define _LIBCPP_INLINE_VISIBILITY if there is no
 # existing definition.  We can therefore define it to the empty string (since
 # we are properly managing visibility ourselves) and avoid this whole mess.
 # Note that we don't need to do this with gcc, as libc++ detects gcc and
 # effectively does the same thing we are doing here.
 #
-# _LIBCPP_ALWAYS_INLINE and _LIBCPP_HIDE_FROM_ABI need similar workarounds,
-# since they too declare hidden visibility.
+# _LIBCPP_ALWAYS_INLINE needs a similar workarounds, since it too declares
+# hidden visibility.
+#
+# _LIBCPP_HIDE_FROM_ABI is a macro in libc++ versions in NDKs >=r19.  It too
+# declares hidden visibility, but it also declares functions as excluded from
+# explicit instantiation (roughly: the function can be unused in the current
+# compilation, but does not then trigger an actual definition of the function;
+# it is assumed the real definition comes from elsewhere).  We need to replicate
+# this setup.
 
 
 @depends(c_compiler, target)
 def libcxx_override_visibility(c_compiler, target):
     if c_compiler.type == 'clang' and target.os == 'Android':
-        return ''
-
-
-set_define('_LIBCPP_INLINE_VISIBILITY', libcxx_override_visibility)
+        return namespace(
+            empty='',
+            hide_from_abi='__attribute__((__exclude_from_explicit_instantiation__))',
+        )
+
+
+set_define('_LIBCPP_INLINE_VISIBILITY', libcxx_override_visibility.empty)
 set_define('_LIBCPP_INLINE_VISIBILITY_EXCEPT_GCC49',
-           libcxx_override_visibility)
-set_define('_LIBCPP_ALWAYS_INLINE', libcxx_override_visibility)
-set_define('_LIBCPP_ALWAYS_INLINE_EXCEPT_GCC49', libcxx_override_visibility)
-
-set_define('_LIBCPP_HIDE_FROM_ABI', libcxx_override_visibility)
+           libcxx_override_visibility.empty)
+set_define('_LIBCPP_ALWAYS_INLINE', libcxx_override_visibility.empty)
+set_define('_LIBCPP_ALWAYS_INLINE_EXCEPT_GCC49',
+           libcxx_override_visibility.empty)
+
+set_define('_LIBCPP_HIDE_FROM_ABI', libcxx_override_visibility.hide_from_abi)
 
 @depends(target, check_build_environment)
 def visibility_flags(target, env):
     if target.os != 'WINNT':
         if target.kernel == 'Darwin':
             return ('-fvisibility=hidden', '-fvisibility-inlines-hidden')
         return ('-I%s/system_wrappers' % os.path.join(env.dist),
                 '-include',