-
Notifications
You must be signed in to change notification settings - Fork 254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
system STL is not useful and should be removed #744
Comments
since we don't seem to have any plans to remove the "system STL", i'll take a look through and try to make sure all the |
I don't think this is written down anywhere, and it might be useful for people trying to figure out what to do in their apps, so here's basically my view on the NDK's system STL: If I had my way I'd just remove the system "STL". It's really only there because it's always been there and I'd break a bunch of builds by removing it. If people actually want C++ support they should use libc++.
The best way to do that is actually "none".
It does... and I can never settle on whether I should change this. Since the system STL is almost the same as "none", it feels strange to me to switch ndk-build's default behavior from none-ish to libc++. The main reason I think that's change is too invasive is that we have to either pick the default of libc++_static, which is probably a harmful default since using the static STL requires rather careful use, or libc++ shared, which means that your app is now bundling and STL that may or may not use, increasing APK size compared to when it was using the system STL. When we some day reach the point where 21 is the minimum supported API level in the NDK (I don't suspect this day will come for quite some time), then using libc++ won't mean that your app must include libandroid_support, and we could probably work out something with |
Is I wasn't aware of I'd suggest switching to |
I'm always hesitant to add something like this because since "the header only part of the STL" isn't something that libc++ makes any attempt to support, so there are no guarantees about what is and what isn't header-only in any given release. It would be entirely possible for the header-only part of libc++ to be the entire library sans key functions in one release and nothing at all the release after. Having such a configuration just feels like laying a bunch of migration landmines to me.
I forgot to document this when I added it. I'm not sure this is something anyone wants though. It got added because we use ndk-build to build the STL itself, and that's one of the few corner cases where this is needed. CMake and ndk-build are both smart enough to not include/link the STL for a C code (CMake gets this right per-file; ndk-build will still give you the STL include dirs for a module with mixed C and C++ files), and if you're using C++ you might as well just use the STL since it's going to make your life a lot easier. Anyone that disagrees with that assessment, please speak up :)
Yeah... Especially given that ndk-build and CMake will do the right thing when you have a C only module maybe I should just get over my worries and switch the default to one of c++_static or c++_shared... |
This is not fixed even within a release. For instance, Clang my choose to inline (or not inline) functions based on optimization flags. |
https://android-review.googlesource.com/c/platform/ndk/+/718562 modernizes the "system" STL a little. it's untested, and definitely missing the more i think about this, though, the more i think -- regardless of whether "none" or "libc++" becomes the default -- we should just remove "system". i'm highly skeptical anyone's using it in its current state. i'm also skeptical that anyone would use an "STL" that's just the |
Makes sense. Outside of a std::abs test case I can see very few uses for it in the real world anyway.
Yup I'd be for that. Even for code not using the STL, it isn't really an option as the basic c++ headers provided are not standards compliant. Definitely seems like a poor default that may actually compile but then just have subtly broken behaviour. I've never actually used "system" on purpose, just stumbled onto this bug due to it being the default with ndk-build. Given the "single runtime per app" caveat, it seems "c++_shared" is the sensible default, whilst users can opt-in to c++_static if they know they only have one .so using it and want to get the benefits of smaller binary size and potentially better optimisations. The downside of the _shared approach is the need to do a |
i tried to convince @DanAlbert yesterday but i'm not sure i succeeded. i'll try again today :-) i think one specific concern was "we've always had one release with a deprecation notice, another release where the default is switched, and then a final release to actually remove the feature". and since as of today the docs still mention "system" but not "none", that ought to make r18 the deprecation release and r21 the removal release. i'll try to get the documentation fixed today, at least. as for ReLinker, the "you need a reverse topological sort" bug was fixed in JB-MR2 -- |
Yeah, I'm convinced. I think it's okay for us to skip the "we're changing the default next release" past and just so that in r18. I'm considering just removing it straight away in beta 1 and seeing if anyone cares. The decision we have to make is whether we use shared or static. As has been discussed, shared is a safer default, but it would be inconsistent with cmake. It would be consistent with standalone toolchain, but that's a much smaller set of users. Maybe we should change the cmake default too... I think the libstdc++.so binary itself will remain in the sysroot for r18 since removing it may break other build systems if they haven't yet started passing |
The other thing we'll need to decide is whether we maintain the support for new/delete, exceptions, and RTTI when STL is none. I'm inclined to opt for no, especially since you won't have full support without |
Aside: The The typeinfo symbols for built-in types (e.g. It looks like selecting the system STL with ndk-build links in |
to be fair, the docs claim that RTTI doesn't work with "system", so we're under-promising and over-delivering :-) |
(also, we've updated https://developer.android.com/ndk/guides/cpp-support to talk about deprecation and explicitly mention "none". though it looks like i fucked up a link. will fix...) |
We've settled on libc++_shared as a new default for ndk-build, and I'm hoping to bring CMake in line with that (only thing that will prevent it is if that will cause issues for the gradle plugin, as I'm not sure how it decides whether to include the library in the APK or not). Given that the docs claimed that the system STL didn't support RTTI/exceptions (technically it doesn't, but if you request it the build system will include libc++abi for you) and that the system's typeinfo header was broken, I've also chosen to drop that support along with the system STL rather than try to apply the same support for "none". If the user requests none then we ought to honor it completely (plus I'd need to add a no-really-i-mean-none "STL" for building libc++ itself if I did that). The new default will be in NDK r18, and the system STL will be removed in r19. Taking over this bug for this purpose since it contains all the useful discussion and we won't be fixing the originally reported issue anyway. Thanks for filing it and kicking off the discussion 👍 |
I think switching cmake would break the gradle plugin: A new project defaults to empty cmake args:
The plugin doesn't hard-code a particular default STL, but instead it assumes the default is some static STL, and it only looks for a shared STL setting. The equivalent code for ndk-build returns an empty container. I can't remember how the plugin packages the solib. I'll keep looking. |
(i've abandoned the partial cleanup of "system".) |
Bug: android/ndk#744 Test: ran tests Change-Id: Iad9514946e06d55b6a3aa0f945d9a63bff900881
POSIX says it's unspecified whether setjmp is a macro or a function, but C11 says it's a macro, and the C standard always wins. Bug: android/ndk#744 Test: ran tests Change-Id: I4a1abc37724f8e9d9498f2093ef3c1f3b8253949
For ndk-build, gradle parses However, the generated JSON file doesn't list the STL solib, only the app/user's solibs. By experimentation, it looks like Gradle packages any file matching *.so from one of the external build tool's output directories:
(This is obj/local/$ABI, not libs/$ABI...) When I sync (Refresh Linked C++ Projects), Gradle removes solibs from this directory that it doesn't recognize. For ndk-build, it always removes STL solibs (probably this code). Building an ndk-build project copies the STL solib into obj/local, but building a CMake project doesn't, so Gradle uses I think we could change ndk-build to c++_shared, but changing CMake would break gradle. |
For CMake, it looks like Gradle copies the STL solib into |
I think the best option for us is to punt this out to r19 so we can give the gradle folks time to prepare for the change. |
* Update bionic from branch 'master' to 76221401ed68c668ba6081c45aff11d975a1f9bd - Merge "Add C11 timespec_get." - Add C11 timespec_get. Bug: android/ndk#744 Test: ran tests Change-Id: Iad9514946e06d55b6a3aa0f945d9a63bff900881
* Update bionic from branch 'master' to ad596bf4fc406c0940d0f76f6b7c4ff22ecee7ac - Merge "setjmp is a macro." - setjmp is a macro. POSIX says it's unspecified whether setjmp is a macro or a function, but C11 says it's a macro, and the C standard always wins. Bug: android/ndk#744 Test: ran tests Change-Id: I4a1abc37724f8e9d9498f2093ef3c1f3b8253949
This one still depends on having AGP always specify an STL. Triaging to r23 as a reminder to myself to see if we can make that change, but it'll then get punted a few releases past that to give a few versions of compatibility. |
Fixes: dotnet#4949 Context: dotnet#4952 Context: android/ndk#744 Xamarin.Android uses the "system" version of the C++ standard library (which is, in reality, a very basic stub containing only weak definitions of the `new` and `delete` operator functions) in order to avoid possible conflicts with Xamarin.Android applications which could make use of their own version of the C++ standard library. The conflict would arise from the fact that the `libc++` library shipped with the current versions of Android NDK is built in a way that would expose a large number of its symbols which would conflict with any other `libc++` used by the application. Additionally, linking `libc++` into Xamarin.Android runtime would result in a binary 4-6 times bigger than what we currently ship (when linking statically) or by 6.2MB if the shared library version of `libc++` were used. The "system" version of `libstdc++` is deprecated in favor of `libc++` and may be removed from the NDK in a near future. In order to prepare for this we need to switch to one of the supported STL implementations. The static and dynamic linking options are not viable, as described above, which leaves us with the `none` STL option. However, using this variety causes Android NDK's cmake toolchain to pass the `-nostdlib++ -nostdinc++` options to the compiler. The first of them doesn't affect us, since we don't use any types from the `libc++` library, but the second of them causes the standard C++ files, which we do use, to not be found. This commit enables the `none` STL variety and works around the `-nostdinc++` flag by detecting and specifying the include path to the standard C++ headers manually on the command line.
Fixes: #4949 Context: #4952 Context: android/ndk#744 Xamarin.Android uses the "system" version of the C++ standard library (which is, in reality, a very basic stub containing only weak definitions of the `new` and `delete` operator functions) in order to avoid possible conflicts with Xamarin.Android applications which could make use of their own version of the C++ standard library. The conflict would arise from the fact that the `libc++` library shipped with the current versions of Android NDK is built in a way that would expose a large number of its symbols which would conflict with any other `libc++` used by the application. Additionally, linking `libc++` into Xamarin.Android runtime would result in a binary 4-6 times bigger than what we currently ship (when linking statically) or by 6.2MB if the shared library version of `libc++` were used. The "system" version of `libstdc++` is deprecated in favor of `libc++` and may be removed from the NDK in a near future. In order to prepare for this we need to switch to one of the supported STL implementations. The static and dynamic linking options are not viable, as described above, which leaves us with the `none` STL option. However, using this variety causes Android NDK's `cmake` toolchain to pass the `-nostdlib++ -nostdinc++` options to the compiler. The first of them doesn't affect us, since we don't use any types from the `libc++` library, but the second of them causes the standard C++ files, which we do use, to not be found. Use the `none` STL variety and work around the `-nostdinc++` flag by detecting and specifying the include path to the standard C++ headers manually on the command line. This allows us to no longer link against `libstdc++.so`, while continuing to use "header-file only" functionality.
Fixes: #4949 Context: #4952 Context: android/ndk#744 Xamarin.Android uses the "system" version of the C++ standard library (which is, in reality, a very basic stub containing only weak definitions of the `new` and `delete` operator functions) in order to avoid possible conflicts with Xamarin.Android applications which could make use of their own version of the C++ standard library. The conflict would arise from the fact that the `libc++` library shipped with the current versions of Android NDK is built in a way that would expose a large number of its symbols which would conflict with any other `libc++` used by the application. Additionally, linking `libc++` into Xamarin.Android runtime would result in a binary 4-6 times bigger than what we currently ship (when linking statically) or by 6.2MB if the shared library version of `libc++` were used. The "system" version of `libstdc++` is deprecated in favor of `libc++` and may be removed from the NDK in a near future. In order to prepare for this we need to switch to one of the supported STL implementations. The static and dynamic linking options are not viable, as described above, which leaves us with the `none` STL option. However, using this variety causes Android NDK's `cmake` toolchain to pass the `-nostdlib++ -nostdinc++` options to the compiler. The first of them doesn't affect us, since we don't use any types from the `libc++` library, but the second of them causes the standard C++ files, which we do use, to not be found. Use the `none` STL variety and work around the `-nostdinc++` flag by detecting and specifying the include path to the standard C++ headers manually on the command line. This allows us to no longer link against `libstdc++.so`, while continuing to use "header-file only" functionality.
Still would really like to do this, but haven't had the time to fix AGP. |
Description
CppReference suggests
<cmath>
should overloadstd::abs
with versions taking (and returning) various floating-point types:https://en.cppreference.com/w/cpp/numeric/math/fabs
With the
system
STL, this doesn't happen.The latest NDK default compiler does generate a warning for this [though the suggested fix in the note clearly doesn't work for this STL]:
Minimal test project:
https://github.com/tangobravo/ndk-abs-test
Commenting out the following block in app/build.gradle to show it working in with the default STL implementations:
There are probably other cmath functions that should have overloads, but it was the
abs()
one that I was testing at the time when I noticed it. I realise the gnustl and stlport options are being removed, but I believe the system one is still supported as a reasonable "no STL" option (and remains the default with ndkBuild I think) so thought it worthwhile to file a bug.Environment Details
OS X 10.12.6, Android Studio 3.0.1 [probably not important for this bug]
Using NDK bundle from Android Studio: 17.1.4828580
The text was updated successfully, but these errors were encountered: