Archive for August, 2012

ODB License Exception

Wednesday, August 22nd, 2012

ODB is dual-licensed under the GPL and a proprietary license (there is both a free and a commercial version of the latter). As discussed in the ODB Licensing FAQ this model caters fairly well to other open source projects that use the GPL (or a similar license), private closed source projects, as well as commercial closed source projects. However, there is a significant drawback in this dual-licensing model when it comes to other open source projects that use a more liberal (than the GPL) license. In this post I would like to discuss the nature of this problem in more detail as well as explain what we did to allow more liberally-licensed projects to still use and benefit from ODB.

In case you are not familiar with ODB, it is an 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 manually writing any of the mapping code. ODB natively supports SQLite, PostgreSQL, MySQL, Oracle, and Microsoft SQL Server. Pre-built packages are available for GNU/Linux, Windows, Mac OS X, and Solaris and were tested with GNU g++, MS Visual C++, Sun CC, and Clang.

Before we go into the details of the ODB situation, let’s first get a quick overview of the state of the open source software licensing. All open source software licenses can be broadly divided into two categories, the so-called copyleft and non-copyleft licenses. Copyleft licenses give us the right to distribute copies and derivative works of software but require that the same rights be preserved in the derivative works. In other words, it is not possible to take a copyleft-licensed project, say a library, use it in our own project (thus forming a derivative work) and then release our project as closed source. In contrast, non-copyleft licenses allow us to base proprietary, closed source works on the non-copyleft software. The most popular copyleft license is the GNU General Public License (GPL). For non-copyleft, several licenses are widely used, including BSD, MIT, and the Apache License.

A quick note on the term derivative used in the preceding paragraph. Many people mistakenly assume it to mean only modifications to the original software. In reality, derivative work is a much broader concept. In our context, it is more useful to think of it as covering any functional dependency between two pieces of software. For example, if we use a GUI library in our application to display some information, then our application is a derivative work of that GUI library.

It is also useful to understand philosophical grounds of the copyleft vs non-copyleft debate. Proponents of the copyleft licenses want to preserve the freedom of every end-user to be able to distribute and modify the software. And if derivative works can be released closed source, then such a freedom would be denied. In contrast, the non-copyleft camp believes that the choice to release derivative works open or closed source is as essential a freedom as any other. There is also a third group, let’s call them the quid pro quo camp, which prefers the copyleft licenses because they ensure that those who benefit from their work are also required to give something back (i.e., make their work open source). Dual-licensing software under a copyleft license as well as a proprietary license on the commercial basis is then a natural extension of the quid pro quo idea. This way, companies that are unable or unwilling to make their derivative works open source have the option to instead pay a fee for a proprietary license. These fees can then be used to fund further development of the original project.

A copyleft project, say GPL-licensed, can normally use non-copyleft software, say BSD-licensed, without imposing any further restrictions on its users. This is not the case, however, in the other direction, for example, a BSD-licensed project using GPL-licensed software. While releasing the derivative work under BSD will satisfy the requirements of the GPL, the resulting whole now carries the restrictions of both BSD and the GPL. And that means that the users of the project no longer have the freedom to use it in proprietary derivative works.

If we are proponents of the copyleft licenses for the sake of preserving the end-user freedoms, then this outcome is exactly what we would want. However, if we use a copyleft license as a way to implement the quid pro quo principle, then this is not quite what we had in mind. After all, the author of the project is giving something back by releasing his software under an open source license. Further restricting what others can do with this software is not something that we should probably attempt.

And that’s exactly the problem that we faced with ODB. We are happy to let everyone use ODB in their projects as long as they make them open source under any open source license, copyleft or non-copyleft. However, as we have just discussed, the standard terms of the GPL make ODB really unattractive to non-copyleft projects.

So what we decided to do is to offer to grant a GPL license exception to any specific open source project that uses any of the common non-copyleft licenses (BSD, MIT, Apache License, etc). This exception would allow the project to use ODB without any of the GPL copyleft restrictions. Specifically, the users of such a project would still be able to use it in their closed source works even though the result would depend on ODB.

You may be wondering why didn’t we just grant a generic license exception that covers all the open source projects? Why do we need to issue exceptions on the project-by-project basis? The reason for this is because a simple generic exception would be easy to abuse. For example, a company wishing to use ODB in a closed source application could just package and release the generated database support code without any additional functionality as an open source project. It could then go ahead and use that code in a closed source application without any of the GPL restrictions. While it is possible to prevent such abuse using clever legal language, we found that a complex license exception text will only confuse things. Instead we decided to go with a very straightforward license exception text and to offer it to any open source project that looks legitimate.

In fact, the other day we granted our first exception. It was for the POLARIS Transportation Modelling Framework developed by Argonne National Laboratory (U.S. Department of Energy) and released under the BSD license.

So what do you need to do if you want an ODB license exception for your project? The process is actually very easy. Simply email us at the following information about your project:

  1. Project name
  2. Project URL
  3. License used (e.g., BSD, MIT, etc)
  4. Copyright holder(s)

Once we receive this, we will send you the license exception text that will be specific to your project. You can then add this text as a separate file to your source code distribution along with the LICENSE, COPYING, or a similar file. Or you can incorporate the exception text directly into one of these files. We also store each exception granted in our publicly-accessible ODB source code repository.

Should destructors be allowed to throw?

Tuesday, August 21st, 2012

Just a quick note on a post called “Evil, or Just Misunderstood?” by Jon Kalb and Dave Abrahams over at C++Next. While the article itself is quite thought-provoking, what I found really insightful is the discussion in the comments that followed. Some really good stuff if you are interested in software design. Check it out.

Using C++11 auto and decltype

Tuesday, August 14th, 2012

I am sure by now you’ve heard of C++11 type deduction from initializer (aka auto). Probably also seen a few examples or, maybe, even wrote some code that uses it. There is also another similar, yet different, new feature in C++11: an operator that returns the declaration type of an expression (aka decltype). In this post I am going to discuss a few thoughts and guidelines on using these new features in C++ applications.

But first let’s quickly recap what auto and decltype are all about. C++11 auto instructs the compiler to automatically deduce the type of a variable from its initializer. Here is an example:

auto x = f ();

When I first saw a code fragment like this, two thoughts immediately crossed my mind: I now have no idea what the type of x is and This is a code readability and maintenance nightmare waiting to happen. But as I started learning more about auto’s semantics, I began to realize that perhaps my scepticism was not justified. To see why, let’s consider what type we get for a few different declarations of f(). First, if f() returns by value, things are pretty straightforward:

int f ();
auto x = f (); // x is of type int

Things get more interesting when f() returns a reference. Does x also become a reference or does it remain a value? The answer is, it remains a value:

int& f ();
auto x = f (); // x is of type int, not int&

This is probably the most important point to keep in mind when using auto: the type that it “substituted” for auto always has its top-level reference removed. When I understood this point, again, my first thought was: This is bizarre. Now, besides not knowing what we get, we also don’t get exactly the same type. My mind promptly envisioned all these cases where a function returns by reference but an unnecessary copy is made because auto stripped the reference. But, again, as I had more time to think about it, I realized that my fears are probably ungrounded. To understand why, think about the type of the local variable (x in our example) as having two parts: the core type (int in our case) and its const-ness/reference-ness. The core type can be naturally determined from the initializer expression. However, const/reference-ness is really determined by what we plan to do with the object further down within our code. Are we just accessing it? Then our variable should probably be a const reference. Are we planning to modify it? If so, then do we want to modify a shared object or our own copy? If it is shared, then our variable should be a reference. Otherwise, it should be a value. Here are the signatures for each case:

const auto& x = f (); // x is not modified
auto& x = f ();       // x is modified, shared
auto x = f ();        // x is modified, private

In a sense, by choosing to strip the top-level reference, auto forces us to specify our intentions. Plus, if we use the above signatures for each use-case, we get an additional safety net in case the type of an initializer changes. For example, if we are expecting to modify a shared reference and the signature of f() changes to return, say, by-value instead of by-reference, we will get a compile error.

If you have to stop reading right now and need a single takeaway from this post, then it will be this: whenever you find yourself writing auto x, stop and ask if you plan to modify x? If the answer is No, then change that to const auto& x.

Now that we understand auto, it is easy to define decltype. This operator evaluates to the exact declaration type of an expression, including references and all. Here is an example that contrasts the two:

int f1 ();
int& f2 ();
const int& f3 ();
auto a1 = f1 (); // a1 is int
auto a2 = f2 (); // a1 is int
auto a3 = f3 (); // a1 is int
decltype (f1 ()) d1 = f1 (); // d1 is int
decltype (f2 ()) d2 = f2 (); // d2 is int&
decltype (f3 ()) d3 = f3 (); // d3 is const int&

You may have noticed that the top-level const/reference stripping semantics of auto mimics that of automatic template argument deduction. In fact, in the standard, auto is defined in terms of template argument deduction. By now many people have developed a pretty good intuition about what the deduced template argument will be. We can easily extend this intuition to auto by mentally re-writing a statement like this:

const int& f ();
auto& x = f (); // auto -> const int, x is const int&

To something like this

template <typename auto>
void g (auto& x);
g (f ()); // auto -> const int, x is const int&

One interesting consequence of this equivalence is that auto also uses the special perfect forwarding deduction rules when we have just auto&&. Consider this example:

struct s {};
s        f1 ();
const s  f2 ();
      s& f3 ();
const s& f4 ();
auto&& r1 (f1 ()); //       s&&
auto&& r2 (f2 ()); // const s&&
auto&& r3 (f3 ()); //       s&
auto&& r4 (f4 ()); // const s&

While probably not very useful in ordinary code, this can be handy in generic code, if, for example, we need to forward an unknown return value to another function:

template <typename F1, typename F2, typename F3>
void compose (F1 f1, F2 f2, F3 f3)
  auto&& r = f1 ();
  f2 ();
  f3 (std::forward<decltype (f1 ())> (r));