-
Notifications
You must be signed in to change notification settings - Fork 104
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
Require minimim GCC version (i.e. GCC 13) #3472
Conversation
…added a check for GCC version
The most recent release of Mir (2.17.0) builds on 22.04, it is only the current development |
I can already see that a pair of the check scripts have failed, but that seems to be because they were running GCC 11 (possibly Ubuntu 22.04). |
Ah, that's good to know! 😅 It hadn't occurred to me that |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3472 +/- ##
=======================================
Coverage 77.35% 77.35%
=======================================
Files 1076 1076
Lines 68922 68922
=======================================
+ Hits 53317 53318 +1
+ Misses 15605 15604 -1 ☔ View full report in Codecov by Sentry. |
…using 'AND' in CMakeFiles.txt
Pushed some potential fixes for the check failures. According to this: The The error in the build appears to be the |
While this has the potential to offer a better message when building with an old version of g++, I'm not sure that this is a good solution:
I'll wait and see what other opinions exist |
Fair points. For what its worth, this doesn't negatively affect non-GCC compilers. Adding a Clang check is easy enough too, once a desirable Clang version is known, and any unknown compilers just wont see these messages. On that note, if the goal is to make Ubuntu 24.04 the recommended build environment, best I can tell 24.04 ships with GCC 13 and Clang 18. I don't yet know if Mir builds on Clang 18, but in my quick test it doesn't build on Clang 14 (Ubuntu 22.04) or Clang 17 (a newer version I had handy). For reference Clang 14 dies right away attempting to build googletest, and Clang 17 gets about 50% done before choking on some
I don't think they are. As long as we're not talking about having to clean and re-run Ideally I'd chosen a subset of C++ language features supported by both GCC 13 and Clang 18. If this is already the case then awesome, I just don't have Clang 18 handy so I can't verify. Tangentially I do wish there was a better way to do this than looking at compiler versions, especially since in some cases it looks like it's the standard libraries at fault. GCC 11 got to about 70% before it needed |
No, I'm talking about two years time when we switch our development base to 26.04. There's the potential of failing to update |
Gotcha. 👍 I just stumbled across a "compiler features" feature of cmake. On paper it sounds like this might work better, avoiding the need to specify specific compilers by release version. |
Instead, why not use |
So, I'm in favour of giving a warning when we suspect that the toolchain is too old. I don't think it should be a To make it a fatal error, I'd want these to be feature checks, rather than version checks. But I'm ambivalent on feature checks, as they're (marginally) more effort to maintain and the benefit is somewhat better compile failure messages. On the other hand, since the goal is just marginally better build failures, maybe we could take the feature checks and just update them when we remember or when someone else hits a missing check? |
That does look like a more robust approach, but it isn't immediately clear to me that it can check library features. But, if that isn't the case, checking library features (in this case "is However, it is not easy to know which features are used in code without actually building against a toolchain (or multiple toolchains) that doesn't support them. And even then, features arrive in bunches which make it easy to miss some. (Were we to attempt to "do it right" I think we'd create of more work than simply supporting those older toolchains directly.) In practice, I suspect, feature checks are only going to be added when someone encounters a problem building on an older buildchain than we target. And by the time they report the problem they will have likely identified the cause and resolution. I remain concerned about the maintenance burden for a small improvement in error reporting. So far as I recall, this is the first time in more than a decade of this project that this has been an issue for anyone, and I suspect that in a few months (after 24.04.1) it will fade in importance. |
Ha, I'm glad that you're for the idea of checking The hiccup of For checking the standard library, include (CheckCXXSymbolExists)
check_cxx_symbol_exists(__cpp_lib_format "version" LIB_FORMAT_EXISTS) Arg1 is the define/symbol to look for, arg2 the header file to check, and arg3 a variable to set equal to include (CheckCXXSymbolExists)
check_cxx_symbol_exists(__cpp_lib_format "version" LIB_FORMAT_EXISTS)
if (NOT ${LIB_FORMAT_EXISTS})
message(FATAL_ERROR "std::format isn't available")
endif() Currently I'm experimenting with writing cmake macros to make writing this less ugly. |
I'm not "for" that, just saying that that would be a way to test for the specific case you encountered. But the general case is problematic. If anything, I'm against adding complexity that needs to be maintained for very little benefit. |
My apologies, poor choice of words.
Fair enough. That said, choosing C++20 as a feature cap over say C++17 does invite this complexity due to the lag of compiler versions paired with supported Linux distros like Ubuntu 22.04 LTS. It's frustrating that a Rust developer only has to lag a few months, or a JavaScript developer 1-2 years, but that's the nature of how Linux is so closely tied to its compiler. Still I agree. If maintaining this requires anything but the tiniest amount of effort, it becomes a burden. I've only ever met one other developer that didn't hate managing build scripts and tooling. When you're not coding you're not coding. Again this could be avoided entirely if C++17 was declared the feature cap. Still, I think taking the effort to clarify what C++20 features are required would benefit all contributors. Even listing older features like An example of what I think this should (could) look like. # Required C++ features. Reference: https://en.cppreference.com/w/cpp/feature_test
require_cxx_feature(__cpp_constexpr)
require_cxx_feature(__cpp_consteval)
require_cxx_feature(__cpp_decltype_auto)
require_cxx_feature(__cpp_generic_lambdas)
...
# Required C++ standard libraries. Reference: https://en.cppreference.com/w/cpp/feature_test
require_cxx_standard_lib(__cpp_lib_format)
require_cxx_standard_lib(__cpp_lib_coroutine)
check_cxx_standard_lib(__cpp_lib_modules HAS_LIB_MODULES)
... |
It turns out I was able to use the same syntax for both compiler features and library features. You can find a new separate PR over here: #3479. |
Closing as #3479 has more buy-in |
Context
I ran into issues trying to build Mir on Pop!_OS, which is currently still based on Ubuntu 22.04 LTS. The reason was twofold:
For this initial PR I'll only be focused on the GCC issue.
Details
Cmake has a flag
CMAKE_CXX_STANDARD
that is used to specify the required C++ specification, but incomplete GCC versions will still pass that test even if they don't fully conform to the specification. For example, you can enable C++20 and C++23 support in GCC 11 withg++ -std=c++20
andg++ -std=c++23
respectfully, even if though they aren't feature complete.The problem I ran into was that GCC 11 was missing certain Standard Library headers, specifically
<format>
. From what I can gather from the GCC changelog, GCC 13 was the first version that includedstd::format
support.My workaround
I eventually had success by adding some PPA repositories with a newer GCC and newer library versions.
NOTE: I don't specifically recommend these, I'm just sharing how I got it working.
Once GCC 13 was installed, I configured
update-alternatives
so I could easily switch GCC and G++ versions withsudo update-alternatives --config gcc
.For testing I installed GCC 9, GCC 11, and GCC 13.
-std=c++20
-std=c++20
and-std=c++23
, but is missing key standard librariesSolution
I added a "minimum GXX version" constant and a check to the
CMakeLists.txt
file that halts the build script if you're not running at least GCC 13. The check is only done if we know for sure that compiler is GCC (i.e.GNU
to cmake).Sample output:
Other options explored
Originally I wanted to see if I could impose a requirement in
debian/control
for a minimum GCC version, but that didn't seem like the best idea as you might want to use Clang instead.Future work
It's very possible that other compilers like Clang and MSVC may have similar discrepancies (i.e. the C++20 standard can be enabled even if it's not fully supported).
Also, the minimum google-mock version in
debian/control
should be updated. To what version requires a bit more research.Feedback is welcome. If I missed a contributions guide or reference, let me know and I'll update this accordingly.