Generating a single include file from a hierarchy of includes

Viewed 296

I have a C++ repository for a header-only library (built via CMake, although that's not critical). Its structure is roughly:

include/
  mylib.hpp
  mylib/
    foo.hpp
    bar.hpp

Now, I know some popular C++ libraries are maintained as single-header files. I don't like dumping everything into a kitchen-sink file; but at the same time I can well appreciate the convenience of being able to utilize a library by just downloading a single file.

So, I was thinking - maybe I can just generate the single header file as part of the installation process?

Supposedly this is a "simple matter of prerocessing"; but - it's not actually quite that simple:

  • I don't want to fully preprocess the C++ files, just #include directives.
  • Not all include files are relevant - only the files under a certain source tree.
  • During actual compilation, the same file is included multiple times (ignoring potential compiler optimizations against doing so), with the second-and-later copies typically removed later using include guards or #pragma once; in my case one would need to watch out and prevent double includes.

So, my question: How do I go about doing this?

Note:

  • A CMake-based method would be nice, but anything reasonable goes.
2 Answers

You could just code yourself a parser. You give it the beginning file. It replaces all #includes with the actual file. If the file to be included was already included, skip it (similar to how compiler behaves towards include guards)

Building on @uIM7AI9S's suggestion - such a mechanism must surely exist in other libraries which want development to happen with multiple files but still offer a single-include-file convenience. One example is Lyra, a command-line argument parsing library; it uses a Python-based include file fuser/joiner, which you can find here.

I could nitpick at the code of that thing, but - hey, it works and it's FOSS - distributed with the Boost license.

Unfortunately, it seems the Lyra developers pre-generate the single header, and that process is not part of a CMake-based build (despite there being a CMakeLists.txt file in the repository's root)

Related