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
c++ stdlib assertions mode is weird #12962
Comments
??? Feels like you are disagreeing with the stdlib documentation here. The fact that it controls CXX assertions in your project was the entire reason I figured that PR was a good idea to merge. No, it doesn't control the use of |
I'm fine with it being a separate parameter - just nobody suggested it until now. It's a shame this wasn't reported during the RC period.
See below. We can also change which of the libc++ hardening modes is used as well, as another option to proceed here. I guess my main question is: Why can't these people then disable asserts in general? Is there really a group of people who really want their own asserts, but want absolutely none from anywhere else? They want sanity checking, but not too much sanity checking based on their input? Just their own? I did also bring this up with a C++ stdlib maintainer who didn't raise any concerns.
I'm not sure what you mean here -- do you mean The options we have are at https://libcxx.llvm.org/Hardening.html#using-hardening-modes. Right now, we do
They're not random. We also tried to only apply them when they're likely relevant. |
This is because there are many meson projects that rely on ndebug being false (because that's meson's default for release profile), sometimes to work at all, sometimes to pass tests (as they use assert() to do the testing checks). That means for those projects, it becomes unwieldy. There are several distros that have been contemplating the tradeoff between "set ndebug to true by default and deal with the fallout" and "just leave it alone" and generally everyone has leaned towards the latter.
I'm talking about configuring your toolchain with C++ hardening by default (e.g. compiling LLVM with
For clang it's applying both libc++ and libstdc++ macros at the same time, regardless of which library is in use, as far as i can tell. Funnily, for GCC it does not, even though GCC also supports both. |
What? |
Can you show me where meson makes a decision about the default value returned by If you want to distinguish asserts based on buildtype you can use
Right, the correct solution is to check whether upstream does in fact rely on asserts being always-active, and if not, ask them to set b_ndebug=if-release so that building for release disables asserts.
Disregarding the incidental quotation of the POSIX manual, I would like to reiterate that I understand Given the meson option "b_ndebug" isn't documented to "pass the -DNDEBUG flag to the compiler" but rather is documented to "disable assertions" I don't think it's quite reasonable to say that this change has somehow violated the meson contract. The flag is controlling whether assertions are used. Whether they are the |
Are you configuring your toolchain by default with the debug setting? If so, why? If not, how is your default being overridden -- any more than someone configuring with no hardening at all, is having their default overridden. If you just want MODE_FAST to be used instead of MODE_EXTENSIVE, then @thesamesam has already agreed it may make sense to switch to that. |
There is an inline code comment about that: # XXX: This needs updating if/when GCC starts to support libc++.
# It currently only does so via an experimental configure arg. |
That's not a debug option, it's a legitimate default that can be set and generally should be set. Your stdlib will then default to assertions on without requiring any explicit macros. You can still specify those macros to change it for the current build though. |
GCC has supported |
That's not right:
And then:
|
You are being intentionally obtuse here and I do not appreciate that. Meson's
That's entirely orthogonal to what is being discussed here.
Regardless of how it's documented, the practical semantics changed with the new release, in a bad way. |
Okay, noted. That said, it does not change my point, meson could easily emit the same macros regardless, especially considering you're emitting the libstdc++ one for clang without checking anything. |
assuming you want meson to be helpful in setting the cpp stdlib assert macros, this is best done in a separate variable. but then the issue is that a project can have a legit reason to (for libc++) pick any of the 4 values. for glibcxx, there are also technically 4 values (not set, _GLIBCXX_ASSERTIONS, _GLIBCXX_DEBUG, _GLIBCXX_DEBUG_PEDANTIC). the crux of the issue is summarised by q66:
effectively, this is overloading the previous value to change multiple distinct things at once. for a project that wants any combination of values here, except for the specific one b_ndebug=false or =true gives them now, this attribute is doing something they don't want and has no usable option to choose. you either get overriden stdlib assertions you might not want (what if the project wants =debug specifically for tests?), or a forced DNDEBUG they don't want. there's no opt-out. |
for our downstream distro side, we will default libc++18 to =fast. so in the case where (for some projects) we were setting b_ndebug=true, there is no change, but for the remainder of projects, this is now forcibly changed to =extensive. the only thing we can do is carry a revert (assuming this isn't changed in some way). |
and since it was mentioned above this might be changed to be =fast by default, the same issue would then happen to a downstream that instead wanted to default to =extensive. there's no way to map a simple boolean for the options here, as long as everyone agrees this sort of granular configuration is wanted (which for us it is). if it's not wanted to be granular, then i guess everything i said is moot |
Consider the feeling mutual, then.
Some projects do, yes. It's not because it's the meson default, it's because it's the compiler default. Many of those same projects originally used autotools, and still relied on asserts at runtime. Again, the answer here is to teach best practices and/or review project usage and encourage the use of b_ndebug=if-release. But mostly, the answer here is to teach projects that there is something to be knowledgeable about at all. It's important because meson's default profile is debug and you have no way of knowing whether the project was ever tested with So even if meson changed it to default to if-release, you still cannot really rely on it!
It is certainly true that the practical semantics changed. It is less definite that it did so in a bad way. The change results in the default experience for users being more consistency and code-correctness checks, in ways that you are already doing -- you are merely debating the intensity. Regarding intensity, it has already been agreed that it's reasonable to change that to =fast if people would prefer that. You've also (both) spent a lot of time arguing about how it's important to not override the libcxx configuration / CXXFLAGS / whatnot but mostly managed to drown yourselves out by carrying on as though defaulting to check code to make sure it actually works is the end of the world (despite you yourself doing it too). This is a pity, because the actual core point is indeed a good one and @thesamesam already started work on checking the default mode to avoid trampling on preexisting intensities. We can have our cake and eat it too. You don't need to pretend that the PR has to be reverted and forgotten about forever, to the detriment of all users everywhere. |
i'm not asking to switch the default to fast (that has the same problem, just in a different way - somebody that has their setup configured to default to stricter checks will suddenly find theirs being dehardened), i'm saying that there should be a way to avoid having meson mess with these while still providing the same NDEBUG semantics as before; i'm not even asking for the PR to be reverted, i'm asking for an option (i really don't care how it's done, if it's to be a separate meson option to disable this, so be it, right now there is none except otherwise, i will carry a downstream patch reverting the behavior for as long as it's needed |
Followup to 9009847. I changed my mind on this a few times. libcxx's documentation describes [0] the hardening modes as: """ 1) Unchecked mode/none, which disables all hardening checks. 2) Fast mode, which contains a set of security-critical checks that can be done with relatively little overhead in constant time and are intended to be used in production. We recommend most projects adopt this. 3) Extensive mode, which contains all the checks from fast mode and some additional checks for undefined behavior that incur relatively little overhead but aren’t security-critical. Production builds requiring a broader set of checks than fast mode should consider enabling extensive mode. The additional rigour impacts performance more than fast mode: we recommend benchmarking to determine if that is acceptable for your program. 4) Debug mode, which enables all the available checks in the library, including internal assertions, some of which might be very expensive. This mode is intended to be used for testing, not in production. """ We chose 3) before because it felt like a better fit for what we're trying to do and the most equivalent option to libstdc++'s _GLIBCXX_ASSERTIONS, but on reflection, maybe we're better off picking a default with less overhead and more importantly guarantees constant time checks. [0] https://libcxx.llvm.org/Hardening.html#using-hardening-modes Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
Followup to 9009847. If the compiler already has one of these assertion macros [0] set, then don't interfere. e.g. a Linux distribution might be setting a stricter default than usual. This is a pitfall many fell into with _FORTIFY_SOURCE and it's why AX_ADD_FORTIFY_SOURCE [1] was contributed to autoconf-archive. [0] _GLIBCXX_ASSERTIONS, _LIBCPP_HARDENING_MODE, or _LIBCPP_ENABLE_ASSERTIONS. [1] https://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
We'll need it in a moment for get_base_compile_args -> get_assert_args. Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
We're going to use it in some more places in a minute (for controlling assertions). Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
Now that we have access to Environment in get_assert_args, we can check what the actual C++ stdlib provider is and only set relevant macros rather than all possibly-relevant ones based on the compiler. Also, while we're here, now that's sorted, wire up the GCC experimental libc++ support in the macro emission given it doesn't uglify anything for libstdc++ users now. Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
Followup to 9009847. If the compiler already has one of these assertion macros [0] set, then don't interfere. e.g. a Linux distribution might be setting a stricter default than usual. This is a pitfall many fell into with _FORTIFY_SOURCE and it's why AX_ADD_FORTIFY_SOURCE [1] was contributed to autoconf-archive. [0] _GLIBCXX_ASSERTIONS, _LIBCPP_HARDENING_MODE, or _LIBCPP_ENABLE_ASSERTIONS. [1] https://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
We'll need it in a moment for get_base_compile_args -> get_assert_args. Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
We're going to use it in some more places in a minute (for controlling assertions). Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
Now that we have access to Environment in get_assert_args, we can check what the actual C++ stdlib provider is and only set relevant macros rather than all possibly-relevant ones based on the compiler. Also, while we're here, now that's sorted, wire up the GCC experimental libc++ support in the macro emission given it doesn't uglify anything for libstdc++ users now. Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
Now that we have access to Environment in get_assert_args, we can check what the actual C++ stdlib provider is and only set relevant macros rather than all possibly-relevant ones based on the compiler. Also, while we're here, now that's sorted, wire up the GCC experimental libc++ support in the macro emission given it doesn't uglify anything for libstdc++ users now. Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org>
Followup to 9009847. I changed my mind on this a few times. libcxx's documentation describes [0] the hardening modes as: """ 1) Unchecked mode/none, which disables all hardening checks. 2) Fast mode, which contains a set of security-critical checks that can be done with relatively little overhead in constant time and are intended to be used in production. We recommend most projects adopt this. 3) Extensive mode, which contains all the checks from fast mode and some additional checks for undefined behavior that incur relatively little overhead but aren’t security-critical. Production builds requiring a broader set of checks than fast mode should consider enabling extensive mode. The additional rigour impacts performance more than fast mode: we recommend benchmarking to determine if that is acceptable for your program. 4) Debug mode, which enables all the available checks in the library, including internal assertions, some of which might be very expensive. This mode is intended to be used for testing, not in production. """ We chose 3) before because it felt like a better fit for what we're trying to do and the most equivalent option to libstdc++'s _GLIBCXX_ASSERTIONS, but on reflection, maybe we're better off picking a default with less overhead and more importantly guarantees constant time checks. [0] https://libcxx.llvm.org/Hardening.html#using-hardening-modes Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org> Signed-off-by: Eli Schwartz <eschwartz93@gmail.com>
Followup to 9009847. If the compiler already has one of these assertion macros [0] set, then don't interfere. e.g. a Linux distribution might be setting a stricter default than usual. This is a pitfall many fell into with _FORTIFY_SOURCE and it's why AX_ADD_FORTIFY_SOURCE [1] was contributed to autoconf-archive. [0] _GLIBCXX_ASSERTIONS, _LIBCPP_HARDENING_MODE, or _LIBCPP_ENABLE_ASSERTIONS. [1] https://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org> Signed-off-by: Eli Schwartz <eschwartz93@gmail.com>
We'll need it in a moment for get_base_compile_args -> get_assert_args. Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org> Signed-off-by: Eli Schwartz <eschwartz93@gmail.com>
We're going to use it in some more places in a minute (for controlling assertions). Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org> Signed-off-by: Eli Schwartz <eschwartz93@gmail.com>
Now that we have access to Environment in get_assert_args, we can check what the actual C++ stdlib provider is and only set relevant macros rather than all possibly-relevant ones based on the compiler. Also, while we're here, now that's sorted, wire up the GCC experimental libc++ support in the macro emission given it doesn't uglify anything for libstdc++ users now. Bug: mesonbuild#12962 Signed-off-by: Sam James <sam@gentoo.org> Signed-off-by: Eli Schwartz <eschwartz93@gmail.com>
Describe the bug
The pull request #12683 introduced passing assertion modes when ndebug is not set. IMO this is incorrect behavior as ndebug is supposed to control assertions in the project, not the stdlib. The stdlib assertions have their own default that can be overridden based on the specific toolchain build.
With the new behavior, meson will by default (especially for distributions that use the plain buildtype) override the toolchain's assertions mode, with no way to change this other than forcing ndebug, which in turn breaks intended cases in many projects. This is especially notable for clang libc++ starting from 18, as it forces the extensive assertions which may not be wanted by a lot of people.
It also taints the compiler commandline with a bunch of random new global macros that may or may not apply.
To Reproduce
Compile any C++ with meson after #12683.
Expected behavior
The toolchain assertions mode should be respected by default, and any buildsystem-level control over assertions should be at most a separate parameter.
@thesamesam
The text was updated successfully, but these errors were encountered: