Hi, We have just released a C++ object-relational mapping (ORM) system, called ODB, that uses the new GCC plugin architecture. I thought I would report back to the GCC community on how the plugin part worked out.
In a nutshell, the ODB compiler parses a C++ header with class declarations (and some custom #pragma's that control the mapping) and generates C++ code that performs the conversion between these classes and their database representation. I have included some more information on ODB at the end of this email for those interested. What worked well: - Access to pretty much all of the GCC functions, macros, and internal data structures. - Ability to register custom pragmas and attributes. - The tree contains information about typedef aliases. Given the following code: class c {}; typedef c c_t; c_t x; One can discover that 'x' was declared as 'c_t', not just that its type is 'c'. This is very useful when performing the source-to-source translation. What didn't work so well: - The plugin header inclusion is a mess. You have to include the right set of headers in the right order to get things to compile. Plus, the GCC headers poison some declarations, so, for example, you cannot use std::abort. Maybe there is a good reason for this. - If the plugin needs to generate something other than assembly (C++ in our case), then the code that suppresses the opening of the assembly file is quite hackish. - There is no callback point after the tree has been constructed and before any other transformations have been performed. We use the first gate callback (PLUGIN_OVERRIDE_GATE) and do all our work there. There is also no well-defined way to stop the compilation process at this point. We simply use exit(). - Working with the GCC tree is not for the faint of heart. Generating code from it is particularly hard. In fact, we have created our own C++ classes (called "semantics graph") to represent the translation unit being compiled. It is not as complete as the GCC's tree but it is a lot easier to traverse. We have built and tested the ODB plugin with GCC 4.5.1 on the following platforms: GNU/Linux Predictably, everything works out of the box. Solaris Had to add OBJDUMP=gobjdump (or /usr/sfw/bin/gobjdump) when configuring GCC. Otherwise, the -rdynamic test will fail. Tested both x86 and SPARC. Mac OS X Had to apply a backported patch for PR 43715. Windows Well, this one was fun. There is no dlopen/dlsym so no plugin support. What we did was this: we linked in the ODB plugin statically to the cc1plus binary. This required a small patch to the GCC plugin loading code. The patch is small instead of being large thanks to the way the plugin support is implemented in GCC. Even if plugin support is not enabled, most of the code (callback points, etc.) are still there. It's just there is no way to load a plugin. This way it was fairly straight- forward to add another method of "loading" a plugin. Kudos to whoever designed this. I can share the patch/build instructions with anyone interested. Overall, I think, the GCC plugin architecture is a great addition. The amount of flexibility it affords you is quite amazing. Some more information on ODB: ODB is an open-source, compiler-based object-relational mapping (ORM) system for C++. It allows you to persist C++ objects to a relational database without having to deal with tables, columns, or SQL and without manually writing any mapping code. For example: #pragma db object class person { ... private: friend class odb::access; person (); #pragma db id auto unsigned long id_; string first_; string last_; unsigned short age_; }; ODB is not a framework. It does not dictate how you should write your application. Rather, it is designed to fit into your style and architecture by only handling C++ object persistence and not interfering with any other functionality. As you can see, existing classes can be made persistent with only a few modifications. Given the above class, we can perform various database operations with its objects: person john ("John", "Doe", 31); person jane ("Jane", "Doe", 29); transaction t (db.begin ()); db.persist (john); db.persist (jane); result r (db.query<person> (query::last == "Doe" && query::age < 30)); copy (r.begin (), r.end (), ostream_iterator<person> (cout, "\n")); jane.age (jane.age () + 1); db.update (jane); t.commit (); The ODB compiler uses the GCC compiler frontend for C++ parsing and is implemented using the new GCC plugin architecture. While ODB uses GCC internally, its output is standard C++ which means that you can use any C++ compiler to build your application. ODB is written in portable C++ and you should be able to use it with any modern C++ compiler. In particular, we have tested this release on GNU/Linux (x86/x86-64), Windows (x86/x86-64), Mac OS X, and Solaris (x86/x86-64/SPARC) with GNU g++ 4.2.x-4.5.x, MS Visual C++ 2008 and 2010, and Sun Studio 12. The dependency-free ODB compiler binaries are available for all of the above platforms. The initial release supports MySQL as the underlying database. Support for other database systems is in the works. More information, documentation, source code, and pre-compiled binaries are available from: http://www.codesynthesis.com/products/odb/ Boris