Improving the Project Structure

As mentioned previously, one objective of the GLGeom project was to practice a more organized and complete project structure.  The structuring has been working well enough that I’ve started reorganizing the LxEngine code to do the same.

Note that the GLGeom project structure is largely based on how the GLM project is organized, so thanks to the developers of the GLM project.

Namespacing

A fair bit of reorganization is happening, but I’ll point out one here: namespacing.

The GLGeom code and now the LxEngine code use a namespacing structure as follows:

namespace lx0
{
namespace MODULE_TYPE
{
namespace MODULE_ns
{
namespace detail
{
}
}
}
using namespace lx0::MODULE_TYPE::MODULE_ns;
}

Here are the rationale:

• Everything is put in the lx0 namespace to avoid polluting the global namespace (good common practice)
• Everything module is organized into one of several  ”module types”
• This is borrowed from GLM, which in turn borrows it from the OpenGL extensions convention
• For example, GLGeom defines a “core” module type, which contains all the stable, code that if you’re using GLGeom, you’re likely using these classes and functions.  These all get pulled in if you include “glgeom/glgeom.hpp”. A “extension” module type which is for any module that is stable, but probably not used as commonly or doesn’t fit quite as symmetrically into the design: these are not included by default when glgeom.hpp is included and must be explicitly included via an #include “glgeom/ext/module_name.hpp” statement.  Lastly, GLGeom defines a “prototype” module type for all modules that are work-in-progress or are experimental in nature (and the API is likely to change frequently).  These too require explicit inclusion.
• LxEngine defines core, engine, subsystem, util, and prototype module types.  The core and engine module types are pulled into the main lx0 namespace by default, with the lower-level functionality existing in core.
• The module itself is given its own namespace.  This allows “everything” to still sit in the lx0 namespace while in certain contexts a particular module (and only that module) can be pulled into the global namespace.  This may be useful when writing a particular chunk of code using that module extensively.  For example, the serialization code in a project might have a “using namespace  lx0::subsystem::javascript_ns”.  The “_ns” suffix is used to avoid name collisions.
• A detail namespace is used to hide implementation details that need to be shared across a particular module but are not intended for use outside that module (i.e. another good common practice).
• Lastly on inclusion, the symbols in the module namespace itself are pulled into the outer namespace.  This puts everything public in that single namespace so that the client code isn’t a mess of long namespacing to access objects.  If there were a collision, the full namespacing does still exist to remove all ambiguity.

C++0x on GCC

I’m unfortunately a Windows developer, but wanted to test GLGeom on Linux.  Only a couple tweaks were necessary to get the unit tests building with a gcc 4.7 svn build on Ubuntu 10.10:

• Add the -std=c++0x flag to the compiler definitions in the CMakeFiles.txt
• Include a few headers explicitly (that apparently are implicitly included by VS 2010 via inter-dependencies)
• Flip around a “a.distance < b.distance” comparison to “b.distance > a.distance”: why? I hate to say it, but might be a compiler bug.  That chunk of code was in a template using a lambda function, so maybe that’s a case that confused gcc?  Why else would one work and not the other?

…however, my Linux lack of expertise then kicked in: glgeom_unittest built properly, but wouldn’t run.  The make install on gcc 4.7 properly made “gcc” point to the new compiler, but the built executable could not find the right version of libstdc++.so.  Perhaps I need to read a bit more about how shared libraries work on Ubuntu and Linux in general.

Update: I installed Arch Linux on Virtual Box, which comes with gcc 4.6.  Compilation succeeded. However, the GLGeom unit tests failed.  Why?  At least one problem is GLGeom’s use of classes with constructors in unions (a proposed feature of C++0x, specifically called an “unrestricted union“), which I suspect is cascading into all the more general failures.  I need to spend some more time with gcc to determine why there’s a failure.  For example, glgeom::point3f contains a union of a struct of three named floats and glm::vec3 (that works correctly); however, a glgeom::ray3f then contains a member point3f and when the point argument to the ray3f constructor is passed as a initializer to the point3f member, the values don’t get written and the glm::vec3 constructor seems to zero out the point instead.  Back to the debugger.

Update 2: The fix was to add an explicit copy constructor to the classes using unrestricted unions.  This seems to make sense, though I’d like to feel more confident in understanding specifically whether Visual Studio or gcc’s C++0x implementation is more correct in this regard (i.e. VS not requiring the explicit copy constructor versus gcc requiring it).  I’m tending to think gcc is right: the default point copy constructor should be doing a field-by-field shallow copy, but the unrestricted union proposal says default constructors are implicitly deleted for unions – therefore, the field represented by that union should not be copied by point’s default copy constructor…right?

In any case, GLGeom now builds correctly with gcc 4.6 and all unit tests pass!

Written by arthur

May 16th, 2011 at 12:26 pm

Posted in lxengine