-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
[pydrake] Centralize pybind11 includes for ODR safety #19571
[pydrake] Centralize pybind11 includes for ODR safety #19571
Conversation
+@xuchenhan-tri for both reviews per schedule, please. \CC @EricCousineau-TRI in case you'd like to weigh in |
2b5211e
to
463e6d2
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.
Can you clarify the criterion for what includes make the cut to pydrake_pybind.h
? For example, I see that "pybind11/eval.h" is excluded and not sure why. Is it not common enough? Does that undermines ODR-safety goal that we are trying to achieve here?
Reviewed 100 of 100 files at r1, all commit messages.
Reviewable status:complete! all discussions resolved, LGTM from assignee xuchenhan-tri(platform)
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.
Reviewable status: 1 unresolved discussion
a discussion (no related file):
Working
Can you clarify the criterion for what includes make the cut to
pydrake_pybind.h
? For example, I see that "pybind11/eval.h" is excluded and not sure why. Is it not common enough? Does that undermines ODR-safety goal that we are trying to achieve here?
For convenience and easier ODR-safety, consolidate the common pybind11 includes (especially the includes that specialize trait structs) into our central pydrake_pybind header. This avoids hazards where some modules forget to include the proper headers and experience compile- time or runtime failures as a result.
463e6d2
to
ef58f8f
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.
+@rpoyner-tri for platform review of bindings/pydrake/pydrake_pybind.h only, please -(status: single reviewer ok), to check the clarity there with >1 person.
Reviewable status: LGTM missing from assignee rpoyner-tri(platform)
a discussion (no related file):
Previously, jwnimmer-tri (Jeremy Nimmer) wrote…
Working
Can you clarify the criterion for what includes make the cut to
pydrake_pybind.h
? For example, I see that "pybind11/eval.h" is excluded and not sure why. Is it not common enough? Does that undermines ODR-safety goal that we are trying to achieve here?
Done.
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.
Reviewed 2 of 2 files at r2, all commit messages.
Reviewable status: LGTM missing from assignee rpoyner-tri(platform)
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.
Reviewed 98 of 100 files at r1, 2 of 2 files at r2, all commit messages.
Reviewable status: 1 unresolved discussion
bindings/pydrake/pydrake_pybind.h
line 5 at r2 (raw file):
#include <utility> // Here we include a lot of the pybind11 API, to ensure that all code in pydrake
btw I'm satisfied that this patch does the things the comment describes:
- includes
type_caster
headers - includes ADL headers
- does not include headers we don't need (yet?)
- does not include headers that not involved in specializations
It looks then to me like I should verify that this header is seen by every pydrake C++ translation unit.
Are there any correctness invariants that I've missed?
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.
Reviewable status: 1 unresolved discussion
bindings/pydrake/pydrake_pybind.h
line 5 at r2 (raw file):
Are there any correctness invariants that I've missed?
Those seem like the right ones to me.
It looks then to me like I should verify that this header is seen by every pydrake C++ translation unit.
Every TU that includes pybind11
stuff, yes. If there is any C++ code in pydrake that doesn't use pybind11 at all, it would be safe without including this.
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.
Reviewable status: 1 unresolved discussion
bindings/pydrake/pydrake_pybind.h
line 5 at r2 (raw file):
Previously, jwnimmer-tri (Jeremy Nimmer) wrote…
Are there any correctness invariants that I've missed?
Those seem like the right ones to me.
It looks then to me like I should verify that this header is seen by every pydrake C++ translation unit.
Every TU that includes
pybind11
stuff, yes. If there is any C++ code in pydrake that doesn't use pybind11 at all, it would be safe without including this.
There is one TU that might be on the bubble, and maybe has escaped attention so far: bindings/bazel_workaround_4594_libdrake_py.cc
Clearly it's an outlier and maybe doesn't need this header reform. I'm not quite far enough in the headspace to make a judgment. WDYT?
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.
Reviewable status: 1 unresolved discussion
bindings/pydrake/pydrake_pybind.h
line 5 at r2 (raw file):
Previously, rpoyner-tri (Rick Poyner (rico)) wrote…
There is one TU that might be on the bubble, and maybe has escaped attention so far: bindings/bazel_workaround_4594_libdrake_py.cc
Clearly it's an outlier and maybe doesn't need this header reform. I'm not quite far enough in the headspace to make a judgment. WDYT?
Since it doesn't define any types (only a module doc), I think it poses no risk.
My guess is that trying to capture that in a comment somewhere would cause more confusion that help. WDYT?
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.
Reviewable status: 1 unresolved discussion
bindings/pydrake/pydrake_pybind.h
line 5 at r2 (raw file):
Previously, jwnimmer-tri (Jeremy Nimmer) wrote…
Since it doesn't define any types (only a module doc), I think it poses no risk.
My guess is that trying to capture that in a comment somewhere would cause more confusion that help. WDYT?
It's on the bubble -- a pretty trivial module. I was thinking to just use the drake_pybind header for consistency across the board, and not comment on it.
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.
Reviewable status: 1 unresolved discussion
bindings/pydrake/pydrake_pybind.h
line 5 at r2 (raw file):
Previously, rpoyner-tri (Rick Poyner (rico)) wrote…
It's on the bubble -- a pretty trivial module. I was thinking to just use the drake_pybind header for consistency across the board, and not comment on it.
Given that the point of that module is to not be infected with pydrake (see bindings/BUILD.bazel
docs), I am skeptical about using a pydrake header there. The compiler might allow it, but I still come down on more-confusing-than-helpful for that change as well.
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.
Reviewable status:
complete! all discussions resolved, LGTM from assignees rpoyner-tri(platform),xuchenhan-tri(platform)
bindings/pydrake/pydrake_pybind.h
line 5 at r2 (raw file):
Previously, jwnimmer-tri (Jeremy Nimmer) wrote…
Given that the point of that module is to not be infected with pydrake (see
bindings/BUILD.bazel
docs), I am skeptical about using a pydrake header there. The compiler might allow it, but I still come down on more-confusing-than-helpful for that change as well.
I'm good then.
@drake-jenkins-bot linux-focal-clang-bazel-experimental-everything-release please. |
…n#19571) For convenience and easier ODR-safety, consolidate the common pybind11 includes (especially the includes that specialize trait structs) into our central pydrake_pybind header. This avoids hazards where some modules forget to include the proper headers and experience compile- time or runtime failures as a result.
For convenience and easier ODR-safety, consolidate the common pybind11 includes (especially the includes that specialize trait structs) into our central
pydrake_pybind.h
header. This avoids hazards where some modules forget to include the proper headers and experience compile-time or runtime failures as a result.Towards #19250.
Tested locally for possible performance regressions (see below).
Checking for performance regression of a full rebuild:
Build time on master:
git checkout master
bazel build //bindings/...
pybind11/package.BUILD.bazel
to force a bindings rebuild [1]time bazel build //bindings/...
Result:
Build time on pull request:
git checkout pydrake-canonical-includes
bazel build //bindings/...
pybind11/package.BUILD.bazel
to force a bindings rebuild [1]time bazel build //bindings/...
Result:
I believe the critical path changes are just the luck of when
multibody_tree_py.cc
starts compiling.[1] the patch:
Checking performance of a single-file incremental rebuild:
Neither of these two targets show any performance slow-down of a rebuild with the extra included headers:
This change is![Reviewable](https://camo.githubusercontent.com/1541c4039185914e83657d3683ec25920c672c6c5c7ab4240ee7bff601adec0b/68747470733a2f2f72657669657761626c652e696f2f7265766965775f627574746f6e2e737667)