-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
subprojects always inherit c_std and cpp_std from the parent project #1889
Comments
The language version is a global option that is shared by every target. There are languages (such as C++) where combining different language versions fails. |
But it only fails in some fairly limited cases. I feel like it should be respected but you can print a warning something like:
If you really don't want to allow this then at the very least it should print a warning like this:
|
I am having exactly the same problem but with another variation. I have a project, the default_options is c++14 or c++1z depending on wether my build is for ios or desktop due to this bug: https://bugreports.qt.io/browse/QTBUG-63747 I do something like this (@jpakkane correct me if I am wrong in the way to approach this): project('myproject', 'cpp', version : '0.5')
if host_machine.system() == 'darwin' and meson.is_cross_build()
# Workaround exactly this bug: https://bugreports.qt.io/browse/QTBUG-63747
add_project_arguments(['-std=c++14'], language : 'cpp')
add_project_link_arguments(['-std=c++14'], language : 'cpp')
else
add_project_arguments(['-std=c++1z'], language : 'cpp')
add_project_link_arguments(['-std=c++1z'], language : 'cpp')
endif So the net result of this is that now, due to project not having default options (since it is conditional), my subproject gets no c++11/14 flag and cannot be compiled. Can I define default_options conditionally? I tried but meson complained that project must be the first thing in the project. |
Setting aside cpp_std, I think c_std should never be inherited by subprojects. |
I think it is ok that config options (build type, warning options...) are inherited from the parent project. The problem here is that c_std shouldn't be a config option at all. It does not make sense that the user can set the C standard version via meson configure - it is not a preference by the user who is compiling the project, but determined by authors of the project, similar to dependencies. So instead of abusing default_options, there should be a method in the meson or compiler object to set the language dialect and version (mininum/maximum or exact) in a compiler-agnostic way, and a way to override it for individual build targets. |
There are other people who have the exact opposite opinion. Do not assume that "the way I personally want to do something" is is global truth shared by all. Other people have other needs, requirements and preferences.
This is already possible with the A more general overrider mechanism will eventually be done as #3001. |
He's right though. If you have a dependency or sub-project whose code requires |
In C++ mixing different language versions is UB and not guaranteed to work. For example in stdlibc++ there are two different implementations of |
True, but that is a separate problem. There's no reason you can't have a subproject that requires C++17 to compile that exposes a C API that is consumed by a C++11 super-project. Printing a warning is probably a good idea anyway. |
(Sub)projects that build libraries which are usable only from certain language versions could simply provide different dependency objects for the different language versions. |
If I may add my two cents: readline-6.3 won't compile without gnu11 (or a similarly "relaxed" version of the standard), but I'd like to wrap it from a project that prefers c11. Now, if I link readline from whatever my distribution's package manager provides, the used dialect won't be checked at all, hence I don't understand why meson cares. (@dpirch's solution does not appeal to me…) |
This could be fixed by a PR similar to #4157, I agree it's debatable that One use-case I can imagine is a parent project that wants to keep C89 compat and has an optional subproject that requires C11. That means that if user builds with |
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
@jpakkane this doesn't work for compiler checks like I definitely agree that the standard should not be a user option at all, but if you must keep it that way, please at least make it per-project, or provide a more complete overriding mechanism. |
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Does loading a C++11 dynamic library that exposes a C API into a C++17 program really cause UB? If so, why? How? And how are we able to have a Linux ecosystem full of libraries written in C++ at all if so? If that was the case, you would be forced to require that a C++ compiler on that system must only support the langauge that all the libraries on the system use, and by extension that the entire system would need to be reinstalled if the programmer wants to upgrade to the next C++ standard. This kind of restriction makes a lot more sense for a static library, but then you have the problem of subprojects from other developers: my current library project will complain if the standard is not C99/C++11 because that's the target version I want to compile with, but I should be able to allow overriding that for a higher version if and only if this is a subproject...? Otherwise we would all have to write for the lowest common denominator ( Also this kind of restriction only makes sense if meson projects could only be consumed by other meson projects. I wouldn't be able to enforce this restriction on a project that doesn't use meson at all, such as the Go bindings to my library =P |
I see a couple possible solutions to this.
|
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
Meson propagates c_std to all subprojects, including those that require gnu99 or c11, etc. mesonbuild/meson#1889
But that is not true though? It's not UB for every C++ compiler, and I don't know anything about C , but at least three major C++ compilers (gcc, msvc, clang) maintain a strict ABI compatibility between various C++ versions (when built with the same compiler obviously). And they go a long way to keep it (e.g. like not approving features for C++20). Yes, there might be some C++ compilers that do not provide any guarantees about ABI compatibility, but there a lot of other ways how the compiler might not be fully functional (e.g. some compilers have broken library grouping in linker, despite providing and accepting such a flag). |
I recently ran into a case where I had to use a gnu++ library that exposes a small C wrapper, in a c++11 parent project. So as far as I understand, both parts uses different C++ ABI but could still be working together. AFAIK, it's pretty common to wrap a C++ implementation into a C API, to avoid all those ABI issues, no? |
It's not that simple. If you have liba that internally uses one version of the C++ standard library and libb that internally uses a different version and you bring them in the same process, things explode. If you need to static link them, things explode even worse. (This is what has been reported to me, I have not tested it myself.) |
Well, in my case it seems to be working, currently with horrible hand written build scripts that I wanted to port to Meson, but I have to admit I have no idea if it generally works, or if they's are doing evil stuff and are just lucky. |
Note that this ties into #3001. Now that we have the native file, adding per project configuration overrides to that is feasible. |
It would be good to find an actual example of this happening, because I have since researched this and found what TheQwertiest said to be true. Things have a right to explode, but in reality all the major compiler vendors arrange things so that they don't, exactly because limitations like the one that Meson is currently imposing are really inconvenient. |
Well yeah, some even provide a C++ header-only wrapper to avoid using the C interface directly =)
I thought we were talking about building from sources though? Using random C++ libraries together is UB (IMO) (and should not be performed without consulting your doctor first), building them with the same compiler (but different FWIW, I had successfully built various projects with mismatched std versions (C+03/C+11/C++14) on msvs and gcc. And there were no problems (apart from having to ressurect std::auto_ptr in one of the projects...).
It all depends on the compiler you are using. |
If you're using the same compiler and version, across any of the major compilers, there will not be an issue, assuming that you don't pull an abseil and change your ABI in different C++ versions. This is the same for Rust and C. It'd be really nice if we could pull the C++ standard out of the options.
This is not true, see the documentation. libstdc++ uses a macro, and it's independent of the C++ version. Also, as long as we're complaining about things being options, warning level should not be an option. That doesn't have anything to do with ABI, but if I want to use a library that doesn't compile under /W4 /Wx, I should be able to turn off both warnings-as-errors and set the warning_level lower, just for that library. |
We should probably keep things to the C++ spec, if anything. I should have rephrased my earlier comment to be asking for specific documentation, because even though "it works as you would want it to" does fall under "undefined behavior", the fact that this indeed is undefined behavior is news to all of us says something. That being said, I have been mulling about this some more, and I suppose that yes, parent projects that link directly to subprojects should be able to have the child inherit all the predefined built-in options, for maximum safety. I therefore concede that ideally we should have a situation where the minimum version is specified, and by default it will use the minimum version when building standalone, but inherit the actual version from the parent. If there's an incompatibility, that incompatibility should be reported by meson itself. And yes, I am extending it to all the builtin variables, not just |
Uhm, no. That would be mostly the same as we have right now. The problem is that parent settings can not always be applied on it's subprojects. A scenario when parent project is built with C++17 (which can't be built with any other) and linked against subproject built with C++03 (which can't be built with any other) with the same compiler is a valid scenario and supported by compiler vendors (as discussed above). I don't have an universal solution though: sometimes project supports multiple At the minimum what should be possible is to use different
^ this!!! I'm using VERY ugly hacks right now to avoid warning errors in subprojects... |
I would be very surprised if the C++ spec has anything to say about this at all. |
It's not undefined behavior, to be clear. The behavior is not specified by the C++ standard; that doesn't mean it's undefined behavior, and the behavior is very well specified by all implementations (the ones that matter, anyways). For different versions of the same compilers, GCC guarantees ABI compatibility back to the beginning of architectures, and MSVC guarantees ABI compatibility for one major version, generally (i.e., VS2015 is ABI compatible with VS2015), and has guaranteed ABI compatibility across 2019, 2017, and 2015 (although I don't think we've every actually broken ABI). clang, depending on the triplet one uses, is either compatible with GCC or with MSVC. There are zero compilers that I know of which change ABI across standard flags; GCC and clang don't change ABI across standard flags, and MSVC has only had them for two major versions now, but it doesn't change ABI across the three standard versions it has ( |
This is now fixed in master. All compiler options, including c_std/cpp_std, are per-subproject. That means they inherit the value from main project, but if they define another value in |
FTR, this was fixed in #10170 which went into the 0.63.0 release. |
If you have a main project that uses c11 for example, and then a subproject needs gnu99 for example, the subproject will actually be compiled with c11.
I'm not sure meson pays any attention to language versions in subprojects.
The text was updated successfully, but these errors were encountered: