Skip to content
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

Add flatc '--cpp_std' switch #5656

Merged
merged 8 commits into from
Dec 23, 2019
Merged

Conversation

vglavnyy
Copy link
Contributor

@vglavnyy vglavnyy commented Dec 8, 2019

Add flatc '--cpp_std' switch and sandbox for C++17 code generator:

  • Added 'flac --cpp_std legacy' for compatibility with old compilers (VS2010);
  • Added experimental switch 'flac --cpp_std c++17' for future development;
  • Added C++17 sandbox test_cpp17.cpp;
  • C++ code generator generates enums with explicit underlying type to avoid problems with the forward and backward schema compatibility;
  • Adjusted CMakeLists.txt, CI and generate code scripts to support of introduced '--cpp_std';

This PR will change all already generated C++ code.
By default, generated enums will be declared with an explicit underlying type matched with a schema. For backward compatibility, a flatc switch --cpp_std legacy was added.
For future development an experimental switch --cpp_std c++17 was added.
Indirectly related issues: #5585, #5285, #5626, #5611.

Copy link
Collaborator

@aardappel aardappel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this will allow us to start generating more modern code.

docs/source/Compiler.md Outdated Show resolved Hide resolved
src/flatc.cpp Outdated Show resolved Hide resolved
src/idl_gen_cpp.cpp Show resolved Hide resolved
// There is no way to notify about an error from a code-generator
// except `assert` call.
// TODO: re-design interface to code generators.
static void Warn(const std::string &warn);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these are static, why aren't they simple extern functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They should be extern functions, I will fix it.

The compilers have a non-extensible interface:

struct Generator {
typedef bool (*GenerateFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);

I've tried to replace the pack of args (parser, path, file_name) by reference to struct or class object with additional logging methods but refused due to too big changes in the code.

src/idl_gen_cpp.cpp Outdated Show resolved Hide resolved
@@ -627,12 +627,6 @@ CheckedError Parser::ParseType(Type &type) {
"length of fixed-length array must be positive and fit to "
"uint16_t type");
}
// Check if enum arrays are used in C++ without specifying --scoped-enums
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it better to do this in the code generator?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. When other langs will support arrays this check will block flatc.
  2. The g_only_fixed_enums flag in idl_gen_cpp is a more general flag. It can be set even if --scoped-enums is inactive (C++11 unscoped enum with explicit underlying type).

@aardappel
Copy link
Collaborator

There are CI errors: "src\idl_gen_cpp.cpp(2992): warning C4482: nonstandard extension used: enum 'flatbuffers::cpp::CppStandard' used in qualified name [C:\projects\flatbuffers\flatc.vcxproj]"

It may well be that C++11 cannot be the default for the checked-in generated code, because of our VS2010 and Android CI.

- Added 'flac --cpp_std legacy' for compatibility with old compilers (VS2010);
- Added experimental switch 'flac --cpp_std c++17' for future development;
- Added C++17 sandbox test_cpp17.cpp;
- C++ code generator generates enums with explicit underlying type to avoid problems with the forward and backward schema compatibility;
- Adjusted CMakeLists.txt, CI and generate code scripts to support of introduced '--cpp_std';
@vglavnyy vglavnyy force-pushed the add_modern_cpp_test branch from 472c255 to dfc4c9b Compare December 19, 2019 00:47
@vglavnyy
Copy link
Contributor Author

It may well be that C++11 cannot be the default for the checked-in generated code,

Fixed. PR was rebased to the master for compatibility with the latest changes in cpp-gen.

If code is ok, we can merge it into the master after the next relsease.
This will give time to add --cpp-std c++0x flag into projects with old compilers.

Maybe add more information about C++ compatibility options into support.md ?
Platform: Linux | GCC282
GCC282 should be GCC-4.82?
Problem: there are no links to this file in the documentation.

@aardappel
Copy link
Collaborator

Well, we can merge this now with C++0x as default, and then simply swap default after release?

Sadly I guess there is no automatic way to identify those people that will need --cpp-std c++0x, they will simply run into build errors.

@vglavnyy
Copy link
Contributor Author

Really, this will be better.

Travis failed in a strange way. On my repo with the same commit, Travis passed.
I take the time to check this error.

@aardappel
Copy link
Collaborator

The error appears to be:
TEST FAILED: /Users/travis/build/google/flatbuffers/grpc/tests/message_builder_test.cpp:257, 'true' != 'release_n_verify(mb, m1_name, m1_color)' in void builder_move_ctor_conversion_before_finish_test()

Let me know when you think this is ok to merge.

- Fix dependency declaration of grpctest target
@vglavnyy vglavnyy force-pushed the add_modern_cpp_test branch from 9132786 to d8a3f10 Compare December 22, 2019 16:20
@vglavnyy
Copy link
Contributor Author

vglavnyy commented Dec 22, 2019

@aardappel GRPC-CI fixed, could you review the latest commit?
It was lucky to catch that error before merging.

Conditions:

  1. Target grpctest had declared dependency monster_generated.h instead of monster_test_generated.h.
  2. I forgot to set --cpp_std C++11 for tests in CMakeLists.txt when changed the default from C++11 to C++0x.
  3. Module test_builder.h exported external variables (m1_color, m2_color) instead of functions.
  4. Use parallel build (cmake --build -jN).

Sequence-1 is invalid but could pass CI:

  1. Checkout and configure build. All generated files are files from the repo with --cpp_std C++11.
  2. Build of grpctest before flatc target finished and before all generated files updated.
  3. All observed declarations of MyGame::Example::Color enum were C++11 enum with uint8_t.
  4. Test passed.

Sequence-2, CI failed with error:

  1. Checkout and configure build. All generated files are files from the repo with --cpp_std C++11.
  2. Start compilation of grpctest/test_builder.cpp with monster_test_generated.h before flatc finished. This file will reserve uint_8 for m1_color variable (C3).
  3. Build flatc target and re-generate all headers. Due to C2, all files now C++0x with old-style MyGame::Example::Color enum (underlying type is int).
  4. Start compilation of grpctest.cpp and message_builder_test.cpp with updated monster_test_generated.h (C++0x due to C2).
  5. On test run, message_builder_test.cpp expects that m1_color is int instead of uint8_t and it can read garbage like 513 instead of 1.

Log with failed CI
In this log grpctest was built before monster_test_generated.h was updated:
https://travis-ci.org/google/flatbuffers/jobs/627346280#L2444-L2468.

@no-more-secrets
Copy link
Contributor

Thanks for this; when this is merged then I will submit a PR to add in the new table Create methods that we have discussed (I already sent PR 5674, which you can look at as a preview of what I will send).

@aardappel
Copy link
Collaborator

Thanks for finding what was happening with the CI. So are we able to create explicit dependencies in CMake such that this will always execute in the right order, such that this problem doesn't happen anymore? Or do we need to turn off parallel build?

This PR still seems to default to C++11, I thought we were going to merge it with C++0x default, then change to C++11 after the next release?

@vglavnyy
Copy link
Contributor Author

vglavnyy commented Dec 23, 2019

I think that all the problems with the dependencies were fixed. It will be better if the parallel compilation remains enabled. It speedups the CI and surfaces possible problems with test code.
I wrote todo about custom_target which would call generate_code.sh. This target should depend on flatc. In turn, other targets will depend on this custom target using target_link_libraries().
This solution would stop further problems with dependencies.

The flatc uses C++0x by default but all tests are generated with --cpp_std C++11 expect for Appveyor-CI MSV2010. This CI runs CMake with flag FLATBUFFERS_BUILD_LEGACY.

I have reverted generate_code.sh scripts to the state as they were two commits earlier.
Now, --cpp_std value for tests is controlled by flatc default settings.

P.S. Failure in Appveyor is unrelated. It failed in Rust tests.

@aardappel
Copy link
Collaborator

aardappel commented Dec 23, 2019

Ok, I will merge this then, thanks!

@no-more-secrets
Copy link
Contributor

@vglavnyy Given these changes, could you explain what steps I should take to make a PR with C++17 changes to the C++ generator? Thanks

@aardappel aardappel merged commit 44bf719 into google:master Dec 23, 2019
@vglavnyy
Copy link
Contributor Author

@dpacbach there are no restrictions or right ways, you can do as you wish.

The test_cpp17.cpp has two top-level namespaces: cpp17 and cpp11. The cpp11 namespace added for comparisons if need to check the result with the reference implementation using TEST_EQ as test.cpp does.
A proposed code could be placed inside cpp17 namespace as if it was generated by the generator. After researching, the code can be moved into the generator.
If code looks well you can skip this stage and add it into the generator.
This two-stage procedure without modifying the cpp-generator code at the first stage could simplify researching.

LuckyRu pushed a commit to LuckyRu/flatbuffers that referenced this pull request Oct 2, 2020
* Add flatc '--cpp_std' switch and sandbox for C++17 code generator

- Added 'flac --cpp_std legacy' for compatibility with old compilers (VS2010);
- Added experimental switch 'flac --cpp_std c++17' for future development;
- Added C++17 sandbox test_cpp17.cpp;
- C++ code generator generates enums with explicit underlying type to avoid problems with the forward and backward schema compatibility;
- Adjusted CMakeLists.txt, CI and generate code scripts to support of introduced '--cpp_std';

* Fix --cpp_std values: c++0x, c++11, c++17

* Add 'cpp::CppStandard' enum

* Add testing engine into test_cpp17

* Rebase to upstream/master

* Set default '--cpp-std C++0x'

* Fix code generation (--cpp_std C++11) in CMakeLists.txt

- Fix dependency declaration of grpctest target

* Revert --cpp-std for the tests from explicit C++11 to flatc default value (C++0x)
@vglavnyy vglavnyy deleted the add_modern_cpp_test branch June 19, 2021 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants