-
Notifications
You must be signed in to change notification settings - Fork 848
Meta: Add conditional compilation case meta structures. #4140
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
Conversation
|
Looks reasonable and I prefer this style than detecting APIs by m4 macro. |
|
The idea is interesting and I'm not going to stop this for now, however, I'm not so sure this can be used widely so far. I understand OpenSSL vs BoringSSL is just an example and their old APIs can be wrapped with this, but I don't think it can cover all cases. For example, some cases may need extra function calls at other places and usage may completely different (sync/async), which means we would need If above was true, it would make inconsistency like "To do A, you can use meta (TS_SSL_x), but to do B, you need ifdef SSL_y_init and SSL_y_fin". This doesn't sound great. Another concern is that it's not feature oriented. Let's say we need 3 APIs to achieve a feature. What will happen if a platform / library supports only 2 of them? In this case, we need to check the all availability and define one flag to indicate that all the APIs are available and we can achieve the feature. It would be great if you could show me more examples. Especially, examples that make existing code great (but not OpenSSL vs BoringSSL). |
|
@maskit - I think it's a rather unreasonable requirement that any new utility be able to handle every possible case. My view is every reduction of using the C preprocessor is a good thing and therefore a utility that enables that in many cases is valuable, even if it doesn't cover all such uses. As for the inconsistency, that's only a style issue. You could just as easily wrap the Handling the multiple feature case turns out to be easy in most cases as well. Because of the abuse of the comma operator in the This utility originally came from work I am doing on upgrading the IP address support code in |
Partially agreed. It doesn't have to cover all use cases. I wanted to point out the inconsistency issue.
I was talking about a case that we cannot easily provide a wrapper. When I tried to support BoringSSL on QUIC code, I found a case that we cannot simply replace OpenSSL function calls. I haven't figured out the case, but I would probably need to call BoringSSL functions from different places and the logics for each libraries would be pretty different. I don't think this case has to be covered by this utility but it suggests that making TS_SSL_x doesn't work every cases, and I think ifdef is suitable in this case. So, this would lead the same issue as I can live with it but I wanted to know how many places (and how much) we can improve with this.
Alright, sounds like it's possible. But again, I want to see how much it makes code readable and beautiful. Can you make separate PRs that use this utility so that I can see the improvements? |
|
Not in the near future. This is here because Masaori asked to see it. I'm using it in another project, as noted, having to do with refreshing the IP address support, but that won't be ready for a while. I suppose I could separate out the use of this as a PR, it's relatively independent. |
cbf595e to
5067574
Compare
|
I get what you are doing... I think we can clean up the code to make it more obvious. ( this was not completely obvious... there are limits :-) ) I will try to see what I can add to this |
5067574 to
204a9e9
Compare
204a9e9 to
76f0e0d
Compare
|
I used this in several places in the Canned-YAML work, sometimes new but at least once to replace |
7feb3d1 to
562e388
Compare
562e388 to
3c30906
Compare
This enables conditional compilation checks in pure C++ code, without support from
configure.acor#define. It is a bit more verbose but has the advantage of being self contained - the code does not depend on external tools in order to compile correctly. It is also more robust because it does its checks with the exact compiler and library environment. Therefore changing the environment and recompiling will change the output without other rebuilding.The basic structure is a wrapper function is created to cover the conditional code. A set of "case" functions, analogous to
switch/case, are created as overloads. These are called from the wrapper, and checked by the compiler in order and the first one that successfully compiles is chosen. The checking involves attempting to compile an expression - if the expression compiles successfully that is a success. It is not a visible error if the expression does not compile, except for the base case because at least one of the overloads must be a success. It is not an error if multiple overloads succeed, the highest ranked will be used. This is a critical difference fromstd::enable_if, which requires disjoint success that can be very challenging to achieve.An example of its use in a real life situation is here in #4040. This creates a wrapper function for an
openSSLcall that compiles to the underlying call if present, and nothing if not. In that case, the conditional compilation check isThis compiles if there is an
SSL_CTX_set1_groups_listfunction that takes aT(in this case anSSL_CTXbecause the wrapper function forces that) and achar *. If not, that case is not used. Note that if BoringSSL has something similar but with a different name, another case could be added (withCaseArg_2) to check for that and provide a shim to call it correctly.