-
Couldn't load subscription status.
- Fork 139
Added cxx_standard package for defining cxxopts
#412
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
base: main
Are you sure you want to change the base?
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
65c7743 to
e65e431
Compare
82db89d to
1719794
Compare
|
CI appears to be failing for an issue unrelated to this change. |
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.
This is just a drive-by review by someone interested in this topic in response to your request on Slack.
Could you describe why you went with select instead of well-known toolchain features?
I like that this introduces a way to override the standard from the command line. How should this interact with target-level settings though? If my target requires c++14 and I enable c++17 globally, c++17 should be picked and everything is fine. But if my target requires c++17 and I only enable c++14 globally, wouldn't the ideal experience be an analysis failure when that particular target is requested?
| ] | ||
|
|
||
| def _flag(version, compiler): | ||
| if compiler.startswith("msvc"): |
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.
Could this be an exact match?
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.
Yeah, no that also works. I'm no expert in the MSVC ecosystem, I just wanted to make sure the "windows-y" flags made it to the windows compilers so opted for the prefix.
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.
Is this what you're thinking?
| if compiler.startswith("msvc"): | |
| if compiler == "msvc-cl": |
| "20", | ||
| "23", | ||
| "26", | ||
| "2c", |
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.
What's the backwards compatibility story here? Could we ever delete this constant once we have added 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.
Since the rules are semantically versioned I figured a value could be dropped from release to release but I also think keeping a large list here is low cost.
| Note that the `--@rules_cc//cc/cxx_standard` flag can be used to override specified `default` value. | ||
|
|
||
| Args: | ||
| default (str, optional): The default version of the C++ standard to use. |
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.
What's the use case for not specifying this parameter vs. not using cxxopts at all?
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.
you could still use the --@rules_cc//cc/cxx_standard flag to globally affect just this value. This is a slight convenience over explicitly specifying --copt or something as it would only affect targets that used the macro (as not all targets may be compatible with that version of C++). Though I would not be opposed to making default mandatory as it'd cleanup the awkward none value.
tests/cxx_std_macro/BUILD
Outdated
| cc_binary( | ||
| name = "main", | ||
| srcs = ["main.cc"], | ||
| copts = cxxopts(default = "17"), |
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.
This won't apply transitively. Could that become a usability issue when dealing with ABI-breaking standards changes (11 vs. 14)
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.
This wasn't intended to apply transitively. Yes it does mean you might specify this a lot, but in all the projects I've worked on when we get to a critical mass of cc targets folks have written macros to wrap this kind of boilerplate. But the intent was for this to be applied granularly.
|
@fmeum Thanks for the review!
I don't trust toolchain authors to implement a common feature for cxx standard. Unless there's some guidance somewhere I don't know about, in which case that would also be good. I opted to go for a select model since what I ultimately want is targets that require a cxx version to be able to specify that. Take Instead of transitioning like this at the top level, if the target is genuinely un-buildable without these cxxopts then I would assert the target should have them but I also don't want that to come at the cost of easily toggling the version to try upgrading to new versions or implementing a similar transition to toggle the desired version (in more nuanced situations). Can you expand on what you mean by "well-known toolchain features"? Is there something I'm missing? |
Maybe there should be a way to specify a version independent of the global toggle, that's something I can definitely add. But I only envisioned the global flag to be used for development when you're transitioning a specific library, then you might update the default and move. This workflow had less thought than just providing a way to specify a default without breaking use-cases I see in projects where folks rely on |
|
@fmeum friendly ping here 😄 |
c74e5ec to
2b31ab4
Compare
|
@fmeum hey, I have some renewed interest in this. Is there any movement toward another solution? |
|
@UebelAndre Sorry for the silence on this. I haven't gotten to think about this again. You are definitely more qualified to decide which approach works best in practice. How can I help? |
@fmeum I still think this approach is good. There will always be tradeoffs for solutions here but I think this has an easy means to disable the use of the cxxopts if users run into a tradeoff they don't like. |
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.
I generally like the macro approach, but I wonder whether this composes safely. If one dep specifies C++14 for a target and another dep specifies C++17 for another target, couldn't that result in ABI breakages if the user doesn't explicitly set a default version (at least C++ 17)?
It seems like this macro approach would work well if the default version was the maximum encountered across all deps. Otherwise it looks like users would pretty much always have to set a standard explicitly to avoid breakages.
|
Yes, that's absolutely a potential problem. I remember a while back I was working in a project where some libraries did exactly this (specify an explicit standard version, and let the rest of the system use something different), and things did NOT work harmoniously. Aside from the fact that headers may have It's only safe to mix C++ compile units across C API boundaries. I do not believe this approach is safe. |
|
I don't see how this is any different than linking a prebuilt binary into your library (e.g. boost). Yes you can create a scenario where you have a bad library interface and then compile with different stdcxx and break your builds. But I don't see how that's anything other than user error. Again, my core desire for this feature is to use it in external dependencies so I don't have to author transitions or beg consumers to set |
|
I've added additional testing to demonstrate that any use of this macro can be disabled by setting |
|
ping @fmeum @armandomontanez |
I fully agree with this. I would like to understand why explicit If that's done the project would still build in its own repo and would pick up any explicit standard set by the root project, either via the toolchain or similar The missing part would then be to ensure that the root module builds everything with a consistent standard even if it doesn't declare one of its own. I think that this necessarily requires a module extension that collects this information from all Bazel modules and exposes this minimum standard as a constant. It could then be embedded by toolchains or used as the default value of a flag like the one introduced by your PR. |
No, using Ultimately the goal is to have the necessary configuration needed to build a target on the target itself. Unfortunately with features, there's no way to guarantee all toolchains have some subset of common features so the likelihood that they're useful at all is fairly diminished. So far, most teams I've worked with have simply added My proposal here gives for the most common issue that requires edits in
This change is largely an ergonomics improvement for folks who don't want to spend tons of time configuring the their build system. Having come from CMake, I rarely had to think about flags needed for any external project for a number of reasons:
Correct me if I'm wrong but it seems 3 is the primary issue here and if so I'd love to know how common of an issue this is for external dependencies to your org. In my limited C++ experience, this issue would only occur in libraries authored and maintained internally which is a scenario that doesn't really have anything to do with this proposal as those same users could (and I've seen this) just hard-code |
|
ping @fmeum @armandomontanez |
This change allows users to specify default
-std=c++(or/std:c++with MSVC) for targets that can still be overridden via the command line. This accounts for the scenario where libraries which require a min version of std set via.bazelrcflags become unbuildable in external repositories without also specifying this global flag or authoring a complicated transition. Instead, projects like these can specify a default value using thecxxoptsmacro but still benefit from a command line flag that affects all targets.closes #406