-
Notifications
You must be signed in to change notification settings - Fork 409
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
Drop wrong template specialization #1926
Conversation
minimal example: https://paste.debian.net/1240487/ |
bde63f5
to
ca45f6e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. I'm not sure why @wjwwood felt the need to template this
Not sure why TestNodeGraph.construct_from_node fails, that seems unrelated to this change. Can you retest this? |
Rpr job seems to be unrelated. I will run CI to verify. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Was probably a typo that was previously allowed by the compiler.
Why does it pass on this one?
SubscriptionOptionsWithAllocator<Allocator>() {} |
Also, generally it is helpful to paste the compiler output of the failure. I had to go to compiler explorer to try and understand what the root cause was. |
I would think that it would be sufficient to paste compiler explorer links moving forward? |
@wjwwood is your buildfarm building against C++20? |
That's fine, but honestly if you have your local stdout from the compiler that's usually enough to go on.
We use the standard compiler that comes with the target platforms. In CMake we request the minimum C++ version for the ROS distribution, e.g.: Lines 25 to 28 in 491475f
Both questions depend on the target platform and the ROS distribution, which are defined in REP-2000, e.g. for Humble: https://www.ros.org/reps/rep-2000.html#humble-hawksbill-may-2022-may-2027 If you assume Ubuntu, we're using 22.04, and require C++17 only. So we're not requesting C++20, at least on Linux. However, other platforms and compilers may up the standard above that, but we don't explicitly test that. |
So then that probably answer's your question |
The code before this pr's change also passed, so yeah I expected it to work with C++17 (our CI). I was more asking why this pr isn't also changing that line? I assume this pr was created because it failed for one of you two? |
This comment was marked as resolved.
This comment was marked as resolved.
ah, yes, correct. Technically it was from one of our coworkers that was porting code that I wrote and @jspricke solved |
Right, that's ok, but I guess what I'm asking is if this pr should include a change for subscription options too? Or failing that, why does that not fail in your system (using I'm hesitant to merge this until we fix the other instances too, or explain them. |
This fails with g++ -std=gnu++20. Signed-off-by: Jochen Sprickerhof <git@jochen.sprickerhof.de>
ca45f6e
to
9e73982
Compare
Good point, I simply did not test that file. Fixed as well now.
Note that this selects exactly the version not the minimum version. I would recommend not to do it as it will bite you in future if other parts want to use newer versions. |
If you don't do that then you get C++14 on some compilers. Also it prevents the user from trying to use a compiler which does not support C++17. You can override it due to the "if not set" logic. The "other parts", as you put it (I took it to mean downstream packages), can still use newer C++ standards by setting their own value for So, I don't see any problem with setting the |
It depends on how you include this project into other projects and where you set what standard. The better way to do it is to use https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html But that could be quiet some work to retrofit. Btw. Do you plan to drop it now that Rolling is on Jammy with GCC 11 and C++17 as default? |
Do you have a situation in mind? I can't think of a situation where you're building rclcpp in which you could not override this to a higher C++ standard. Also, according to the CMake docs, it isn't a requirement so much as a request:
https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_STANDARD.html?highlight=cmake_cxx_standard
https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html#prop_tgt:CXX_STANDARD So I don't think we're forcing it, as you could with
We could use @jspricke Are you basing this recommendation off of some guidelines some where?
No, I don't think so, because we need to assert that the compiler being used supports C++17 (in lieu of specifically depending on each feature of C++ that we use). We build ROS 2 on a lot more platforms than Jammy, and in fact we will still have some users building it from source on 20.04, not to mention users building from source on other kinds of platforms/compilers, e.g. QNX's qcc. So it's important to declare what we require in a portable way, rather than assume the underlying compiler supports C++17's feature set. |
* William Woodall ***@***.***> [2022-05-12 14:49]:
> It depends on how you include this project into other projects and where you set what standard.
Do you have a situation in mind? I can't think of a situation where you're building rclcpp in which you could not override this to a higher C++ standard.
This is open source so you can always work around it, sure :).
Also, according to the CMake docs, it isn't a requirement so much as a request:
> Default value for [CXX_STANDARD](https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html#prop_tgt:CXX_STANDARD) target property if set when a target is created.
https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_STANDARD.html?highlight=cmake_cxx_standard
> The C++ standard whose features are *requested* to build this target.
> ...
> a compiler which does not support -std=gnu++11 or an equivalent flag will not result in an error or warning, but will instead add the -std=gnu++98 flag if supported. This "decay" behavior may be controlled with the [CXX_STANDARD_REQUIRED](https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD_REQUIRED.html#prop_tgt:CXX_STANDARD_REQUIRED) target property.
https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html#prop_tgt:CXX_STANDARD
So I don't think we're forcing it, as you could with `CXX_STANDARD_REQUIRED`.
I've just tested a minimal project with:
project(foo)
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
add_executable(foo foo.cpp)
and gcc 11 (defaults to C++17) and cmake adds -std=gnu++11 to the
compiler flags which forces gcc to C++11.
***@***.*** Are you basing this recommendation off of some guidelines some where?
I don't have guidelines at hand, just general rule to use system
defaults and not enforce versions. Also I just went through a lot of ROS
1 code to get the C++11 enforcement dropped ;).
Anyway, this starts to get off topic for this PR and dropping
CMAKE_CXX_STANDARD is not really urgent, so feel free to merge and
postpone the discussion.
|
So, no? I'm just trying to understand why it's a problem, because if it is, I'd like to pursue fixing it. It's written into the CMake in such a way as to encourage overriding it, so I was asking for a situation where you'd need to edit the source before building it.
Unfortunately, that's also how I made a little example too, which shows that despite that, if one of your dependencies exports something like Example
Files and output:
The other direction, where your dependency uses Example
Files and output:
So I don't see the failure mode. If the second project (the dependent one) doesn't declare what they use c++ standard wise, then yes they will inherit the requirement from their dependency, which I would say is an issue with that project being under-defined.
Why did you have to do that? Was there a build failure or did you just assume that it was out of date and therefore should be removed? (not an unreasonable assumption)
Sure, I will merge this pr as soon as CI is ready, but the conversation will die here most likely unless someone pushes on it. I can see that we might want to switch to |
Thanks for fixing it up :) We're a little closer to being ready for C++20 I guess. |
I made a little example too, which shows that despite that, if one of your dependencies exports something like `target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)`, but you use `target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)` on your target, it will upgrade to C++17 anyway (overriding what you used on your target), which might be a problem if you're using something that has been removed since.
From my understanding upgrading is the correct behaviour. How should the
compiler compile something that needs a newer standard?
> Also I just went through a lot of ROS 1 code to get the C++11 enforcement dropped ;).
Why did you have to do that? Was there a build failure or did you just assume that it was out of date and therefore should be removed? (not an unreasonable assumption)
Because log4cxx in Debian testing and Ubuntu jammy needs C++17 and the
way it is used in rosconsole results in all downstream projects to also
need C++17.
>> Do you have a situation in mind?
> This is open source so you can always work around it, sure :).
So, no? I'm just trying to understand why it's a problem, because if it is, I'd like to pursue fixing it.
It's written into the CMake in such a way as to encourage overriding it, so I was asking for a situation where you'd need to edit the source before building it.
CMAKE_CXX_STANDARD does different things depending on the compiler
version and other components in the project.
- for compilers that don't support the standard set by
CMAKE_CXX_STANDARD it depends on CXX_STANDARD_REQUIRED.
- With CXX_STANDARD_REQUIRED set to on it will fail.
- With CXX_STANDARD_REQUIRED set to off if depends on if the compiler
can compile the given project. There are cases where the compiler is
fine with the code either because non of the newer language features
are actually used or because the compiler happen to implement them
or optimize them away.
So not setting CXX_STANDARD_REQUIRED could result in success whereas
setting it will always fail.
- for compilers that support the new language standard but don't use it
by default it is changed to compile with the new version. This is
probably the reason it is used here in the first place but note that
compilers have reasons not to enable it by default, for example
because the implementation is not complete or well tested. This is the
use case for target_compile_features.
- for compilers defaulting to the requested standard it should not
matter.
- for compilers defaulting to newer standards it restricts the
compilation to the older standard. If the project compiles with the
new standard, CMAKE_CXX_STANDARD restricts the compiler without need.
If the project is not valid with the new standard and can't be made to
comply with it, setting CMAKE_CXX_STANDARD is maybe a valid option.
From my experience this is not needed in open source projects. For
most cases where I had to adopt code to a new standard the changes
where tiny (except the ABI change in C++11, maybe).
Also note that restricting CMAKE_CXX_STANDARD will exclude you from
tests with newer compilers. For example in Debian we regularly
integrate new compilers, test all packages against them and fix bugs
(in the compiler and in the packages).
|
From what I understood, if you used |
I guess that assumes the use of exported targets... But you could also have used an extra file to ensure the |
From what I understood, if you used `target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)` in `rosconsole`, then you wouldn't need to change anything else downstream (or upstream) of `rosconsole`.
Not so easy. Some projects set CMAKE_CXX_STANDARD without testing if it
was set before, others directly added -std=c++11 to the compiler flags.
Anyway, I think the right way here was/is to just drop it and a lot of
projects accepted it already.
|
I mean that is why we're using it, and as I said, due to so many different people building it in so many different scenarios, it behooves us to set that as a low water mark. There's likely always a compiler in this situation. You can't just think about the latest Ubuntu or Debian version. From my limited testing and reading the docs, I suppose we could check what version of C++ the compiler being used defaults to and only set
I don't really see that as a downside. If your software is not using anything from the newer standards then there's no need to use the newer standard. It might be nice to notice what has changed, but until you start using it, you don't need it. However, it would be great if CMake had a "
You could (and probably should) set the Plus you are being tested with new compilers, what you mean to say is the implementation of new C++ standards with the new compiler. If the new compiler stops supporting
We're going to have to just disagree about that. I think projects should declare what features of C++ they require, or at least which version of C++ they require. Furthermore, I think removing those declarations in the ROS 1 packages without replacing them with similar (but maybe more flexible or better) logic was a step backwards. I could be convinced that there is a better way to do this, or that doing it based on features rather than standards is better (even if it's a lot more work), but I do not agree that hoping the underlying compiler is configured correctly to build your software is preferable. 🤷♂️ |
I mean that is why we're using it, and as I said, due to so many different people building it in so many different scenarios, it behooves us to set that as a low water mark. There's likely always a compiler in this situation. You can't just think about the latest Ubuntu or Debian version.
Sure, and those with an old compiler probably have old versions of other
libraries as well so they should probably use an old version of ROS. I
don't think they should block ROS from moving forward.
Software changes and the only way to cope with it is to adopt and move
forward.
I suppose we could check what version of C++ the compiler being used defaults to and only set `target_compile_features` if it is older than what we need, but that's a lot more complexity that honestly should be done by CMake...
However, it would be great if CMake had a "`CMAKE_CXX_MINIMUM_STANDARD`" or something like that (equivalent for use in `target_compile_features`).
This is what target_compile_features does.
From my limited testing and reading the docs, `target_compile_features` and `CMAKE_CXX_STANDARD` work exactly the same, the only difference is that `target_compile_features` also supports `PUBLIC`/`PRIVATE`/`INTERFACE` style representation in exported targets.
How did you test it that you think it does not?
Plus you are being tested with new compilers, what you mean to say is the implementation of new C++ standards with the new compiler. If the new compiler stops supporting `-std=gnu++14` (or whatever), then I believe CMake will upgrade you to the next lowest one. Or maybe it refuses to build and you need to update the software. But I think that's a perfectly reasonable evolution of software.
I guess you would need to update the software and that's what I did :).
We're going to have to just disagree about that. I think projects should declare what features of C++ they require, or at least which version of C++ they require. Furthermore, I think removing those declarations in the ROS 1 packages without replacing them with similar (but maybe more flexible or better) logic was a step backwards.
I could be convinced that there is a better way to do this, or that doing it based on features rather than standards is better (even if it's a lot more work), but I do not agree that hoping the underlying compiler is configured correctly to build your software is preferable. 🤷♂️
Yes, let's agree to disagree.
|
@Mergifyio backport humble |
✅ Backports have been created
|
This fails with g++ -std=gnu++20. Signed-off-by: Jochen Sprickerhof <git@jochen.sprickerhof.de> (cherry picked from commit 02802bc)
This fails with g++ -std=gnu++20.