3

I'm developing a collection of C++ classes and am struggling with how to share the code in a way that maintains organization without compromising ease of compilation for a user of the collection.

Options that I have seen include:

  • Distribute compiled library file
  • Put the source in the header file (with implicit inline as discussed in this answer)
  • Use symbolic links to allow the compiler to find the files.

I'm currently using the third option where, for each class the I want to include I symbolic link each classess headers and source files (e.g. ln -s <path_to_class folder>/myclass.cpp) This works well except that I can't move the project folder location (it breaks all the symlinks) and I have to have all those symlinked files hanging around.

I like the second option (it has the appearance of Java), but I'm worried about code size bloat if everything is declared inline.

A user of the collection will create a project folder somewhere, and somehow include the collection into their compilation process.

I'd like a few things to be possible:

  1. Easy compilation (something like gcc *.cpp from the project folder)
  2. Easy distribution of library in uncompiled form.
  3. Library organization by module.
  4. Compiled code size is not bloated.

I'm not worried about documentation (Doxygen takes care of that) or compile time: the overall modules are small and even the largest projects on the slowest machines won't take more than a few seconds to compile.

I'm using the GCC compiler, if it makes any difference.

Community
  • 1
  • 1
srlm
  • 3,186
  • 2
  • 27
  • 40
  • library files are basically the standard. If you have reservations about building the libraries, consider scons. It's easier to use than make, and won't tie your code to the configure/make path. It also makes ports to Windows easier. – Jiminion Jul 30 '13 at 19:57

3 Answers3

0

A library is the best option (in my opinion) of the three you raised. Then provide the header file(s) in the include path and the library in the linker path.

Since you also want to distribute the library in source code form, I would be inclined to provide a compressed archive (gzip, 7-zip, tarball, or other preferred format) in a central repository.

Codes with Hammer
  • 788
  • 3
  • 16
  • 47
0

If I understand correctly, you do not want users to have to include the .cpp files in their build, but instead just want them to use either: (i) the headers directly, (ii) use a compiled form of the lib.

Your requirements are a bit unusual, but they can be achieved. It seems to me like you could organize your code in the following manner. First, have a global define that dictates whether or not you are compiling the library:

// global.h
// ...
#define LIB_SOURCE
// ...

Then in every header file, you check whether that define is set: if the library is distributed as a static/shared lib, the definitions are not included, otherwise, the '.cpp' file is included from the header file.

// A.h
#ifndef _A_H
#include "global.h"
    #ifdef LIB_SOURCE
    #include "A.cpp"
#endif
// ...
#endif

where 'A.cpp' would contain the actual implementation.

Again, this is a very strange way of doing things and I would actually advise against such practice. A better way (but one which requires more work) is to always distribute a shared library. But to keep things independent of the compiler, write a C layer around it. This way, you have a portable, maintainable library.

As for some of the other requirements:

  • Keep the build process simple by providing a Makefile
  • If you worry about the code size of the compiled library, look into gcc's optimization options (-Os). If you worry about the code size of the library when distributed in source-form in the headers, this is more tricky. Since the (inlined) code will actually be in the headers, the code will obviously grow with each inclusion in a .cpp file by the user.
dgrine
  • 702
  • 6
  • 15
0

I ended up using inline headers for all of the code. You can see the library here:

https://github.com/libpropeller/libpropeller/tree/master/libpropeller

The library is structured as:

  • library folder
    • class A
      • classA.h
      • classA.test.h
    • class B
      • classB.h
      • classB.test.h
    • class C
    • ...

With this structure I can distribute the library as source, and all the user has to do is include -I/path/to/library in their makefile, and #include "library/classA/classA.h" in their source files.

And, as it turns out, having inline headers actually reduces the code size. I've done a full analysis of this, and it turns out that inline code in the headers allows the compiler to make the final binary roughly 5% smaller.

srlm
  • 3,186
  • 2
  • 27
  • 40