Repository navigation
feat: make public headers consumable as C++20 in compat mode - #936
Conversation
|
It seems there are some conflicts, please rebase the main branch. |
|
|
||
| project(example) | ||
|
|
||
| set(CMAKE_CXX_STANDARD 23) |
There was a problem hiding this comment.
Can we make C++23 still as default and let it accept user supplied option so that C++20 can be test manually locally.
There was a problem hiding this comment.
@zhjwpku Thank you for the comments.
Making it configurable is a good idea. Have different thoughts on making C++23 as default though.
With this patch, it changes the minimum supported C++ standard from C++23 to C++20 for downstream consumers. And C++20 is the interface contract between the consumer and iceberg-cpp library, and the contract should be tested continuously.
Setting the default to C++20 ensures the minimum supported standard (contract) is continuously exercised. Defaulting it to C++23 would let C++20 only breakages slip through.
One refinement is that C++23 compatibility should still be tested separately. C++23 should accepts C++20 code, but we can enhance this by provide an optional example configuration for C++23, for example, expose an ICEBERG_EXAMPLE_CXX_STANDARD cache setting that defaults to 20 and accepts 23; then update CI to build both.
And also refine the document to state clearly that the minimum C++ standard is C++20 for public headers. What do you think?
Happy to make changes either way.
There was a problem hiding this comment.
Make sense to me, I think we should build both for compatibility purpose.
797da4f to
4a66df4
Compare
| @@ -0,0 +1,2401 @@ | |||
| /* | |||
There was a problem hiding this comment.
Do we have to put this file here? It will be better to be placed in a third_lib directory and have a README to explain its purpose.
There was a problem hiding this comment.
@manuzhang Thanks.
Wondering which one you mean: <repo_root>/src/iceberg/third_lib or <repo_root>/third_lib?
There was a problem hiding this comment.
I see there's already a thirdparty directory, but I'm not sure that's the best place. @wgtmac should have more background.
There was a problem hiding this comment.
I think it's fine to put expected.h here. We already have murmurhash3_internal.h in src/iceberg/util. Similarly, the thrift idls in thirdparty generate code in src/iceberg/catalog/hive/gen-cpp, and those generated files are also tracked in git.
There was a problem hiding this comment.
I'm worried about long term maintenance. We may forget what it is, where it comes from and when to drop over time.
There was a problem hiding this comment.
Would it help to add a few comments to the file header (after the license) explaining the purpose of this file and providing a brief history?
Or I can update the commit message or separate it to another PR and explain in the PR description.
There was a problem hiding this comment.
@manuzhang @zhjwpku Added comments in expected.h. Let's me know if that works for you.
Happy to make further changes.
There was a problem hiding this comment.
Work for me, I think the zeus-cpp section in LICENSE should tell people the history of expected.h, but no objection for the comments in expected.h.
044b27b to
de7b278
Compare
| ICEBERG_PUBLIC_HEADERS | ||
| CONFIGURE_DEPENDS | ||
| "${ICEBERG_PUBLIC_INCLUDE_DIR}/iceberg/*.h" | ||
| "${ICEBERG_PUBLIC_INCLUDE_DIR}/iceberg/*.hpp") |
There was a problem hiding this comment.
Thanks, checked the source code and no .hpp headers, removed.
| /// | ||
| /// History: | ||
| /// - apache/iceberg-cpp#40 vendored this header, adapted from | ||
| /// https://github.com/zeus-cpp/expected (MIT), while the project targeted |
There was a problem hiding this comment.
Could we pin the vendored source to a specific upstream tag/commit and record the local delta here? The current history only links the repository, so future audits and upstream syncs will not know which version this 2.4k-line file came from.
There was a problem hiding this comment.
Thanks for the suggestion, I cannot find the detail commit ID in #40. My agent compares the code and suggest it is https://github.com/zeus-cpp/expected/releases/tag/v1.2.0. Have a quick check, the timeline match. @zhjwpku not sure if you still remember this.
There was a problem hiding this comment.
I think we can pin the latest v1.4.0, no need to stick to v1.2.0.
There was a problem hiding this comment.
@zhjwpku Thanks, makes sense, updated to v1.4.0.
| ErrorCollector(const ErrorCollector&) = default; | ||
| ErrorCollector& operator=(const ErrorCollector&) = default; | ||
|
|
||
| // C++23 uses deducing `this` so that `return AddError(...)` keeps returning the |
There was a problem hiding this comment.
Both this class and SnapshotUpdate now duplicate the full API and comment blocks across the C++20/C++23 branches. Could we centralize the deducing-this feature test and avoid maintaining two implementations, or at least keep one API shape unless derived-type fluent chaining is a required compatibility guarantee?
There was a problem hiding this comment.
Thanks, this is intended actually as I want to limit the scope to the header only.
But agree with you, there is duplication here.
My latest commit go with one API shape: ErrorCollector and SnapshotUpdate now expose plain member functions returning the base type in both C++20 and C++23. This removes the duplicated blocks, and the class definition no longer differs between C++20 and C++23 translation units.
For derived-type fluent chaining: inside the repo, nothing relies on derived-type fluent chaining. However, this is a breaking API change for C++23 users, so I'd like your call on whether it's acceptable here:
AddError(...) now returns ErrorCollector&. A user builder deriving from ErrorCollector that does return AddError(...); in a method returning its own type no longer compiles.
SnapshotUpdate setters now return SnapshotUpdate&, so a derived-class method can no longer be chained after them.
| CACHE STRING "C++ standard used to build the example (20 or 23)") | ||
| set_property(CACHE ICEBERG_EXAMPLE_CXX_STANDARD PROPERTY STRINGS 20 23) | ||
| if(NOT ICEBERG_EXAMPLE_CXX_STANDARD MATCHES "^(20|23)$") | ||
| message(FATAL_ERROR "ICEBERG_EXAMPLE_CXX_STANDARD must be 20 or 23, got " |
There was a problem hiding this comment.
Do we really need to specify 20 or 23 here? We need to update this file as well when we support C++26.
There was a problem hiding this comment.
Thanks, changed to if(ICEBERG_EXAMPLE_CXX_STANDARD MATCHES "^(98|11|14|17)$") to keep compatitable with future c++ standard.
| **Required:** | ||
|
|
||
| - C++23 compliant compiler (GCC 14+, Clang 18+, MSVC 2022+) | ||
| - C++23 compliant compiler (GCC 14+, Clang 18+, MSVC 2022+) to build iceberg-cpp itself |
There was a problem hiding this comment.
It seems better to keep here unchanged to indicate that we officially support C++23. Then we can add a dedicated section below for the contract of C++20 compatibility.
There was a problem hiding this comment.
Thanks, reversed.
01d07dd to
31e9943
Compare
…expected v1.4.0 Co-authored-by: Junwang Zhao <zhjwpku@gmail.com>
… minimum standard for public headers
31e9943 to
fbfa2f2
Compare
|
Thanks for the work on this, @PingLiuPing! The PR was already largely working, so I went ahead and pushed a revised version directly to the branch to save a few review round trips. The main change is that C++23 stays as the default API, while C++20 is now an explicit opt-in mode via |
Keep C++23 as the default public API and build mode while adding an opt-in ICEBERG_CXX20_COMPAT package for C++20 consumers. - Add compatibility headers and generated build configuration for compiler detection, byteswap, unreachable, and expected. - Preserve the default C++23 fluent API and provide explicit C++20-compatible fallbacks for SnapshotUpdate and ErrorCollector. - Keep one API shape per package so the library and consumers agree at compile time and avoid ODR issues. - Add and simplify the C++20 compatibility compile/API test. - Cover compatibility mode on Linux, macOS, and Windows while retaining a default C++23 Ubuntu RelWithDebInfo job. - Update package configuration, examples, documentation, and CI helper scripts, including named parameters for build scripts.
fbfa2f2 to
79e341e
Compare
| return "off"; | ||
| } | ||
| std::unreachable(); | ||
| ::iceberg::unreachable(); |
There was a problem hiding this comment.
Moving the ToStrings from .h to .cc would let us drop iceberg/compat/unreachable.h and use std::unreachable(), but I'm fine with the current approach.
There was a problem hiding this comment.
Thanks. I checked the remaining uses: not all of them are in non-template functions. Several public templates, such as those in string_util.h and visit_type.h, still need a C++20-compatible unreachable. Also, LogLevel::ToString is constexpr, so moving it to .cc would remove constant evaluation. I would keep the compat wrapper for now and treat this as a possible later cleanup.
| /// | ||
| /// \param reporter The metrics reporter to use. | ||
| /// \return Reference to this for method chaining. | ||
| #if ICEBERG_CXX20_COMPAT |
There was a problem hiding this comment.
Could we use the C++20 approach instead of the macro with C++23 explicit object parameter? cc @wgtmac
There was a problem hiding this comment.
Thanks. Using the C++20 form in C++23 would change these setters to return SnapshotUpdate&, which breaks existing derived fluent calls such as append.ToBranch(...).AppendFile(...). The macro selects a package-level API shape: the default C++23 package keeps deducing this, while the compat package uses base references. I would keep it unless we decide to break the existing C++23 fluent API.
|
Thanks @PingLiuPing for the contribution and @zhjwpku @manuzhang for the review! I'll merge this to move forward. Feel free to create followup PRs if you think worth doing. |
Enable C++20 consumers to include and use iceberg-cpp’s installed public headers when the library is built with ICEBERG_CXX20_COMPAT=ON, while keeping iceberg-cpp implementation code and internal workflows on C++23. C++23 remains the default public API.
Restore the vendored iceberg::expected backport — brings back src/iceberg/compat/expected.h from #40 (removed by #139), with its test and LICENSE entry. unexpected's comparison operators now go through error().
cpp20_compatibility_test compiles all public headers as C++20, and the C++20 example links against an installed compatibility package.
Fix #928