Giter VIP home page Giter VIP logo

objectbox / objectbox-generator Goto Github PK

View Code? Open in Web Editor NEW
35.0 4.0 11.0 3.2 MB

ObjectBox Generator based on FlatBuffers schema files (fbs) for C and C++ (more languages in the future)

Home Page: https://objectbox.io

License: GNU General Public License v3.0

Go 89.60% C++ 9.21% Makefile 0.32% Shell 0.33% C 0.02% Python 0.52%
objectbox database code-generator cross-platform nosql c embedded go golang cpp

objectbox-generator's Introduction


Follow ObjectBox on Twitter

ObjectBox Generator

Current version: 0.14.0

ObjectBox is a superfast cross-platform object-oriented database. ObjectBox Generator produces binding code for ObjectBox C, C++ and Go APIs (more languages to be supported in the future). This greatly simplifies using ObjectBox in your favourite language.

Download

Install the objectbox-generator by downloading the latest binary for your OS from releases. If you want, add it to $PATH for convenience.

Build

If you prefer to build the generator yourself (vs. downloading), clone this repo and simply run make. This will produce an "objectbox-generator" binary in the main project directory.

Build notes:

  • To build yourself, you need Go, Make, CMake and a C++11 tool chain.
  • To run test suite, run make test-depend test.
  • test-depend needs to run only once to download objectbox core library and to build flatcc.
  • A full test cycle can be triggered by make clean all test-depend test.

Getting started

To get started, have a look at the specific language bindings (the approaches differ):

  • C and C++ repository and docs. In summary, you define a FlatBuffers schema file, and the ObjectBox Generator will create plain C++ data classes and helper classes that "glue" the data classes to the ObjectBox runtime library.
  • Go repository and docs. Here, you start with Go data structs, for which the Generator generates the glue code directly.

License

Copyright (C) 2018-2024 ObjectBox Ltd. All rights reserved.
https://objectbox.io
This file is part of ObjectBox Generator.

ObjectBox Generator is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ObjectBox Generator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ObjectBox Generator.  If not, see <https://www.gnu.org/licenses/>.

Note: GPL only applies to the Generator itself and not to generated code. You can regard generated code as "your code", and we impose no limitation on distributing it. And, just to clarify: as the Generator does not include any warranty, there can be no warranty for the code it generates.

Do you ♥️ using ObjectBox?

We want to hear about your project! It will - literally - take just a minute, but help us a lot. Thank you!​ 🙏​

objectbox-generator's People

Contributors

dan-obx avatar greenrobot avatar greenrobot-team avatar vaind avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

objectbox-generator's Issues

Does not support nested tables or structs

This doesn't work (at least not with the .cpp option):
simple.zip

struct TableOne
{
id: ulong;
thisValue: uint;
}

table TableTwo
{
id: ulong;
anotherOne: TableOne;
thisValue: uint;
v:[int];
}

table TableThree
{
id: ulong;
name: string;
finalOne: TableTwo;
}

Am I way off-base here and have missed something obvious?

If we can't nest tables/structs within other tables/structs, how can OB be an Object-Oriented database?

It also doesn't appear to support vectors/lists/arrays. Another critical feature for any OO system.

C++ One to many relationship

The C++ docs are sparse, how do you make a one to many relationship?
I get error: parentid: unsupported vector element type: ULong
Looking at: https://github.com/objectbox/objectbox-generator/blob/main/test/comparison/testdata/fbs/typeful/schema.fbs only string and byte are supported?
`
table Slot {
/// objectbox:id
id : ulong;

defaultlinkoffset : int32;

/// objectbox:relation=Device
parentid : [ulong;] // Does not work
}
table Device {
/// objectbox:id
id : ulong;
hid : string;
}
`

objectbox-go generator can not handle a struct with multiple lazy loaded relations

Hi Guys,
Just messing around with objectbox-go for use as data storage for my app, and I came across the idea
of lazy loading related objects. I found that If I create a struct with more than 1 lazy loaded relation,
the generator breaks badly, to the point that if I remove all but 1 of the lazy defines on a relation, it works fine.

As I'm new to golang, I don't think I'm in the right headspace yet to fix it myself, but that being said, I can
point you in the direction I think needs the fix...
internal/generator/go/templates/binding.go
seems to be the first part to have issues, as with multiple lazy loaded relations, the templated code at line
165 misses a new line in the template, and causes errors in the code.
But then it totally dies somewhere in the templated code after line 193.

Granted those line numbers are from looking at the current source of the repo.

Modules involved:
github.com/objectbox/objectbox-generator v0.13.0
github.com/objectbox/objectbox-go v1.6.1

Golang version:
go version go1.17.9 linux/amd64

Below is my model.go file for the generator to have fun with.

`package model

//go:generate go run github.com/objectbox/objectbox-go/cmd/objectbox-gogen
type Token struct {
Id uint64
Token string
ExpiryDate uint64 objectbox:"date"
}

type Track struct {
Id uint64
path string objectbox:"index:hash64"
artistName string objectbox:"index:hash64"
songName string objectbox:"index:hash64"
albumName string objectbox:"index:hash64"
albumTrackNumber int
}

type Playlist struct {
Id uint64
CurrentTrackId uint16
Elapsed int
Tracks []*Track
}

type Friend struct {
Id uint64
friendId uint64
}
type User struct {
Id uint64 // going to be an internal objectBoxId
FirstName string
LastName string
EmailAddress string objectbox:"index:hash64"
Password string
Enabled bool
Tokens []*Token objectbox:"lazy"
Tracks []*Track objectbox:"lazy"
Playlists []*Playlist objectbox:"lazy"
SharedPlaylists []*Playlist objectbox:"lazy"
Friends []*Friend objectbox:"lazy"
}`

output of command: go generate ./...

Generating ObjectBox bindings for model.go failed to format generated binding file model.obx.go: 1632:8: expected ';', found 'if' (and 3 more errors) exit status 2 internal/model/model.go:3: running "go": exit status 1

C flatcc builder (put) optimization

The generated code currently calls flatcc_builder_finalize_aligned_buffer() which returns a copy of the builder buffer. The returned buffer must be freed by calling flatcc_builder_aligned_free(), in addition to freeing the builder using flatcc_builder_clear(). Have a look at the following sample from README.md

obx_id task_put(OBX_box* box, Task* task) {
    flatcc_builder_t builder;
    flatcc_builder_init(&builder);

    size_t size = 0;
    void* buffer = NULL;

    // Note: Task_to_flatbuffer() is provided by the generated code
    obx_id id = 0;
    if (Task_to_flatbuffer(&builder, task, &buffer, &size)) {
        id = obx_box_put_object(box, buffer, size, OBXPutMode_PUT);  // returns 0 on error
    }

    flatcc_builder_clear(&builder);
    if (buffer) flatcc_builder_aligned_free(buffer);

    if (id == 0) {
        // TODO: won't be able to print the right error if it occurred in Task_to_flatbuffer(), 
        //  i.e. outside objectbox
        print_last_error();
    } else {
        task->id = id;  // Note: we're updating the ID on new objects for convenience
    }

    return id;
}

We should have a look if/how we can optimize this, in terms of performance (avoiding the memory copy if possible) and usability.

C/C++ Integration tests

Create a full integration test - it should contain a schema and "project files" for each langauge (cmakelists, main), excluding the generated code.

  • The test should generate code, compile and execute the compiled code, expecting 0 return value.
  • Catch2 should be used.
  • Actual code should do database operations in a temporary directory and clean up after itself.

Follow up of #1
Depends on #2

"Nullable" annotation support

FlatBuffers supports omitting a field - this is evaluated by ObjectBox as if the field had NULL value. Currently, the generated C/C++ code always expects values to be present.

To bring compatibility with other language bindings as well as extend functionality :

  • the FBS schema parser should support a nullable annotation
  • the generated C/C++ code should handle missing values gracefully when reading.
  • open question - what about writing - should we generate pointer-based code (as in Go)? Or go with "default value" (usually zero) as Flatbuffers do?

Cannot build objectbox-generator

Hello,

I clone the repo and execute make and I get error:

root@beaglebone:/home/debian/objectBox/objectbox-generator# make
./third_party/flatbuffers-c-bridge/build.sh
******** Configuring & building ********
+ cd ./third_party/flatbuffers-c-bridge/cmake-build
+ eval 'cmake "/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge" -DCMAKE_BUILD_TYPE=Release'
++ cmake /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge -DCMAKE_BUILD_TYPE=Release
-- The C compiler identification is GNU 8.3.0
-- The CXX compiler identification is GNU 8.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (6.5s)
-- Generating done (0.2s)
-- Build files have been written to: /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build
+ cd /home/debian/objectBox/objectbox-generator
+ cmake --build ./third_party/flatbuffers-c-bridge/cmake-build --config Release --target flatbuffers-c-bridge-test
make[1]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[2]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[3]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
[  2%] Building CXX object CMakeFiles/flatbuffers.dir/third_party/flatbuffers/src/idl_parser.cpp.o
In file included from /usr/include/c++/8/vector:69,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/third_party/flatbuffers/include/flatbuffers/base.h:43,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/third_party/flatbuffers/include/flatbuffers/idl.h:24,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/third_party/flatbuffers/src/idl_parser.cpp:23:
/usr/include/c++/8/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const flexbuffers::Builder::Value&}; _Tp = flexbuffers::Builder::Value; _Alloc = std::allocator<flexbuffers::Builder::Value>]’:
/usr/include/c++/8/bits/vector.tcc:413:7: note: parameter passing for argument of type ‘std::vector<flexbuffers::Builder::Value>::iterator’ {aka ‘__gnu_cxx::__normal_iterator<flexbuffers::Builder::Value*, std::vector<flexbuffers::Builder::Value> >’} changed in GCC 7.1
       vector<_Tp, _Alloc>::
       ^~~~~~~~~~~~~~~~~~~
/usr/include/c++/8/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {flexbuffers::Builder::Value}; _Tp = flexbuffers::Builder::Value; _Alloc = std::allocator<flexbuffers::Builder::Value>]’:
/usr/include/c++/8/bits/vector.tcc:413:7: note: parameter passing for argument of type ‘std::vector<flexbuffers::Builder::Value>::iterator’ {aka ‘__gnu_cxx::__normal_iterator<flexbuffers::Builder::Value*, std::vector<flexbuffers::Builder::Value> >’} changed in GCC 7.1
/usr/include/c++/8/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {flexbuffers::Builder::Value}; _Tp = flexbuffers::Builder::Value; _Alloc = std::allocator<flexbuffers::Builder::Value>]’:
/usr/include/c++/8/bits/vector.tcc:109:4: note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<flexbuffers::Builder::Value*, std::vector<flexbuffers::Builder::Value> >’ changed in GCC 7.1
    _M_realloc_insert(end(), std::forward<_Args>(__args)...);
    ^~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/vector:64,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/third_party/flatbuffers/include/flatbuffers/base.h:43,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/third_party/flatbuffers/include/flatbuffers/idl.h:24,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/third_party/flatbuffers/src/idl_parser.cpp:23:
/usr/include/c++/8/bits/stl_vector.h: In member function ‘size_t flexbuffers::Builder::EndMap(size_t)’:
/usr/include/c++/8/bits/stl_vector.h:1085:4: note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<flexbuffers::Builder::Value*, std::vector<flexbuffers::Builder::Value> >’ changed in GCC 7.1
    _M_realloc_insert(end(), __x);
    ^~~~~~~~~~~~~~~~~
/usr/include/c++/8/bits/stl_vector.h: In member function ‘flatbuffers::CheckedError flatbuffers::Parser::ParseFlexBufferValue(flexbuffers::Builder*)’:
/usr/include/c++/8/bits/stl_vector.h:1085:4: note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<flexbuffers::Builder::Value*, std::vector<flexbuffers::Builder::Value> >’ changed in GCC 7.1
    _M_realloc_insert(end(), __x);
    ^~~~~~~~~~~~~~~~~
[  5%] Building CXX object CMakeFiles/flatbuffers.dir/third_party/flatbuffers/src/idl_gen_text.cpp.o
[  8%] Building CXX object CMakeFiles/flatbuffers.dir/third_party/flatbuffers/src/reflection.cpp.o
[ 11%] Building CXX object CMakeFiles/flatbuffers.dir/third_party/flatbuffers/src/util.cpp.o
[ 14%] Linking CXX static library libflatbuffers.a
make[4]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
[ 14%] Built target flatbuffers
make[4]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
[ 17%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/src/flatc_main.cpp.o
[ 20%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_cpp.cpp.o
[ 22%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_csharp.cpp.o
[ 25%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_dart.cpp.o
[ 28%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_kotlin.cpp.o
[ 31%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_go.cpp.o
[ 34%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_java.cpp.o
[ 37%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_js_ts.cpp.o
[ 40%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_php.cpp.o
[ 42%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_python.cpp.o
[ 45%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_lobster.cpp.o
[ 48%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_lua.cpp.o
[ 51%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_rust.cpp.o
[ 54%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_fbs.cpp.o
[ 57%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_grpc.cpp.o
[ 60%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_json_schema.cpp.o
[ 62%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/idl_gen_swift.cpp.o
[ 65%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/flatc.cpp.o
[ 68%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/src/code_generators.cpp.o
[ 71%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/grpc/src/compiler/cpp_generator.cc.o
[ 74%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/grpc/src/compiler/go_generator.cc.o
[ 77%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/grpc/src/compiler/java_generator.cc.o
[ 80%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/grpc/src/compiler/python_generator.cc.o
[ 82%] Building CXX object CMakeFiles/flatbuffers-c-bridge-flatc.dir/third_party/flatbuffers/grpc/src/compiler/swift_generator.cc.o
[ 85%] Linking CXX static library libflatbuffers-c-bridge-flatc.a
make[4]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
[ 85%] Built target flatbuffers-c-bridge-flatc
make[4]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
[ 88%] Building CXX object CMakeFiles/flatbuffers-c-bridge.dir/src/flatbuffersc.cpp.o
[ 91%] Linking CXX static library libflatbuffers-c-bridge.a
make[4]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
[ 91%] Built target flatbuffers-c-bridge
make[4]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[4]: Entering directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
[ 94%] Building CXX object CMakeFiles/flatbuffers-c-bridge-test.dir/test/main.cpp.o
In file included from /usr/include/c++/8/vector:69,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/third_party/catch.hpp:570,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/test/main.cpp:2:
/usr/include/c++/8/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const Catch::SectionEndInfo&}; _Tp = Catch::SectionEndInfo; _Alloc = std::allocator<Catch::SectionEndInfo>]’:
/usr/include/c++/8/bits/vector.tcc:413:7: note: parameter passing for argument of type ‘std::vector<Catch::SectionEndInfo>::iterator’ {aka ‘__gnu_cxx::__normal_iterator<Catch::SectionEndInfo*, std::vector<Catch::SectionEndInfo> >’} changed in GCC 7.1
       vector<_Tp, _Alloc>::
       ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/vector:64,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/third_party/catch.hpp:570,
                 from /home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/test/main.cpp:2:
/usr/include/c++/8/bits/stl_vector.h: In member function ‘virtual void Catch::RunContext::sectionEndedEarly(const Catch::SectionEndInfo&)’:
/usr/include/c++/8/bits/stl_vector.h:1085:4: note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<Catch::SectionEndInfo*, std::vector<Catch::SectionEndInfo> >’ changed in GCC 7.1
    _M_realloc_insert(end(), __x);
    ^~~~~~~~~~~~~~~~~
[ 97%] Building CXX object CMakeFiles/flatbuffers-c-bridge-test.dir/test/test.cpp.o
[100%] Linking CXX executable flatbuffers-c-bridge-test
make[4]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
[100%] Built target flatbuffers-c-bridge-test
make[3]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[2]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
make[1]: Leaving directory '/home/debian/objectBox/objectbox-generator/third_party/flatbuffers-c-bridge/cmake-build'
+ set +x
******** Testing ********
flatc error: missing input files
===============================================================================
All tests passed (20 assertions in 3 test cases)

******** Collecting artifacts ********
The compiled libraries can be found here:
-rw-r--r-- 1 root root 644K Mar  8 13:54 ./third_party/flatbuffers-c-bridge/cmake-build/libflatbuffers.a
-rw-r--r-- 1 root root  62K Mar  8 14:20 ./third_party/flatbuffers-c-bridge/cmake-build/libflatbuffers-c-bridge.a
-rw-r--r-- 1 root root 2.8M Mar  8 14:19 ./third_party/flatbuffers-c-bridge/cmake-build/libflatbuffers-c-bridge-flatc.a
CGO_ENABLED=1 go build ./cmd/objectbox-generator/
cmd/objectbox-generator/objectbox-generator.go:32:2: cannot find package "github.com/objectbox/objectbox-generator/cmd" in any of:
        /usr/src/github.com/objectbox/objectbox-generator/cmd (from $GOROOT)
        /home/debian/objectBox/objectbox-generator/src/github.com/objectbox/objectbox-generator/cmd (from $GOPATH)
cmd/objectbox-generator/objectbox-generator.go:33:2: cannot find package "github.com/objectbox/objectbox-generator/internal/generator" in any of:
        /usr/src/github.com/objectbox/objectbox-generator/internal/generator (from $GOROOT)
        /home/debian/objectBox/objectbox-generator/src/github.com/objectbox/objectbox-generator/internal/generator (from $GOPATH)
cmd/objectbox-generator/objectbox-generator.go:34:2: cannot find package "github.com/objectbox/objectbox-generator/internal/generator/c" in any of:
        /usr/src/github.com/objectbox/objectbox-generator/internal/generator/c (from $GOROOT)
        /home/debian/objectBox/objectbox-generator/src/github.com/objectbox/objectbox-generator/internal/generator/c (from $GOPATH)
cmd/objectbox-generator/objectbox-generator.go:35:2: cannot find package "github.com/objectbox/objectbox-generator/internal/generator/flatbuffersc" in any of:
        /usr/src/github.com/objectbox/objectbox-generator/internal/generator/flatbuffersc (from $GOROOT)
        /home/debian/objectBox/objectbox-generator/src/github.com/objectbox/objectbox-generator/internal/generator/flatbuffersc (from $GOPATH)
cmd/objectbox-generator/objectbox-generator.go:36:2: cannot find package "github.com/objectbox/objectbox-generator/internal/generator/go" in any of:
        /usr/src/github.com/objectbox/objectbox-generator/internal/generator/go (from $GOROOT)
        /home/debian/objectBox/objectbox-generator/src/github.com/objectbox/objectbox-generator/internal/generator/go (from $GOPATH)
make: *** [Makefile:14: build] Error 1

Can you help me so I can build objectbox-generator?

Thanks for all your time

Deduplicate annotation parsing

Annotations have slight differences between .go and .fbs sources, have a look at how to unify the algorithm. It'd help with stuff like the new sync(sharedGlobalIds) annotation which is now implemented for C/C++ but not Go...

Conditional test-case compilation based on installed libraries

WRT code compilation: the compiler needs to have objectbox & flatbuffers/flatc headers on include path. Temporarily, I've installed them on my PC to system folders (/usr/local/lib) and the same can be done for the CI, until we decide if/how we're going to integrate those headers with the generator so the generator could output them in along with objectbox headers

The tests would:

  • use flatbuffers headers already present in the repo
  • check whether flatcflatcc is installed (by doing a dummy compilation) to enable/disable per-testcase compilation of generated C code
  • [optional] check whether objectbox is installed, similar to the previous point but for C++ generated code
  • ensure CI does have both flatcc and flatbuffers installed and the compilation steps are executed

Originally posted by @vaind in #1 (comment)

C++ property as a typed argument

Glossary: "property ID" identifies a property inside an Entity, they're assigned automatically during schema analysis/model merging.

Some ObjectBox C++ wrappers take property ID as an argument, e.g. Box<EntityT>::backlinkIds(obx_schema_id propertyId, obx_id objectId). This would be even more prominent if (when) there was a QueryBuilder wrapper - conditions are basically a tuple of property ID, condition type (e.g. between) and one or more values.

The goals to accomplish would be to have a compile-time validation:

  • only allow properties of the matching EntityType in a typed Box/QueryBuilder
  • [optional] only allow calls to QueryBuilder with the matching type, i.e. only string-specific methods when the property type is "string"
  • there should be an easy way to use with the C-APIs which currently expect obx_schema_id

Current state - struct with static const fields doesn't provide this level of "type-safety":

FBS schema:

table RelSource {
    id:uint64;
    typefulId:uint64;
}

Generated C++ binding code:

struct RelSource_ {
    static const obx_schema_id id = 1;
    static const obx_schema_id typefulId = 2;
}

and can be currently used as an argument:

Box<RelSource> box(store);
auto srcIds = boxR.backlinkIds(RelSource_::typefulId, targetId);

Support enums in .fbs

Example FBS that should be supported, with appropriate enum generated in c/c++ code:

enum Flags: uint(bit_flags) {
    FlagA = 0,
    FlagB = 1,
}

table Table {
    id: ulong;
    flags: Flags;
}

Optimization: special null values

In addition to existing "optional" support for C++, there should also be a variant to represent "null" values in FlatBuffers via special values. Why? The current C++11 solution with unique_ptr is heap based and thus comes with an extra indirection with potential cache misses (not to mention additional allocs and deallocs). C++17's optional is much better but still comes with space overhead (one byte plus padding; resulting in 2x space requirements in some cases).

Special values to indicate a null in FlatBuffers could be configurable in the future, but to start with we can only consider the "obvious" ones: empty string, zero for integer types, and NAN for floating points. This requires a new annotation or an addition to the existing one. E.g. /// objectbox:optional="special-value"

Btw, https://cpp.objectbox.io/entity-annotations does not mention optional values at all yet.

C/C++ auxiliary class - split

A generated code currently looks like this

namespace gen {
struct RelSource_;

struct RelSource {
    using _OBX_MetaInfo = RelSource_;
    
    uint64_t id;
    uint64_t typefulId;
};

struct RelSource_ {
    static const obx_schema_id id = 1;
    static const obx_schema_id typefulId = 2;

    static constexpr obx_schema_id entityId() { return 2; }

    static void setObjectId(RelSource& object, obx_id newId) { object.id = newId; }

    /// Write given object to the FlatBufferBuilder
    static void toFlatBuffer(flatbuffers::FlatBufferBuilder& fbb, const RelSource& object);

    /// Read an object from a valid FlatBuffer
    static RelSource fromFlatBuffer(const void* data, size_t size);

    /// Read an object from a valid FlatBuffer
    static std::unique_ptr<RelSource> newFromFlatBuffer(const void* data, size_t size);

    /// Read an object from a valid FlatBuffer
    static void fromFlatBuffer(const void* data, size_t size, RelSource& outObject);
};
}  // namespace gen

Consider splitting out the "binding" methods to a separate class, leaving properties in the "underscore" one.
Reasons:

  • symbol naming overlap (what if anyone wants to name their property entityId?)
  • less mess when writing code: users usually either want to access properties (e.g. for queries) or they want to access FB conversion (for custom handling), either way, the other thing pollutes IDE code completion.

Minimize changes in "expected files"

To reduce the line count of changes in reviews, we should reduce the amount of tests with expected files.

Example: #12

Ideally, when there are changes to generated code, there should be a single file changed with minimal changes.

Side question: which integration tests have to be added to keep coverage up?

Use obx_id for ID

Is that still what's generated?

uint64_t id;

Should be obx_id, right?

Same for relation properties.

cd into a file's dir to make includes work

Let's say we have a file mydir/my.fbs which also contains include "myinclude.fbs";, with myinclude.fbs also in mydir.

The generator should change into the dir containing the processed file (mydir), to make sure the include works.

C++ 14+ output option to use make-unique

E.g. clang-tidy complains about generated code:

error: use std::make_unique instead [modernize-make-unique,-warnings-as-errors]
    auto object = std::unique_ptr<MyEntity>(new MyEntity());

C generated get/put

Having written the C example in README.md, I've realized more useful code could be generated for C users, e.g. get and put operations:

obx_id task_put(OBX_box* box, Task* task);
Task* task_read(OBX_store* store, OBX_box* box, obx_id id);

Deleting an entity from an existing model

When an entity definition is removed (e.g. from a .go file, or the .go file defining an entity is removed altogether), the user might want to delete the entity from the model. Currently, the generator doesn't recognize this situation because it's executed for each individual input file, combining all of them into the same model - therefore it doesn't distinguish between missing entities and the ones that haven't been processed yet.

There are a couple of ways to approach this, the simplest would probably be adding a new CLI argument/action, sth. like --remove=EntityName. Alternatively, we could change the way the generator is launched so that it has the complete list of files to include in the model.

Generated code compatibility check

Once c-api 1.0 is released, the generated code can check semver compatibility with static_assert (C++) or #if & #error macros (C99).
This would ensure, at compile time, that the generated code is compatible with the library used.

Additionally, since objectbox-c is a shared library, a runtime check may make sense for some users. We should probably encourage them to do so in docs?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.