Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake: Generate single header file

Tags:

c++

cmake

I am currently in the process of writing a Utility Library that will ship with a pre-compiled DLL file and the header files of the library. As of now, there are a whole bunch of header files, but I would like to compile all of them into a single header file (somewhat like pre-processing only the #include directives).

I was wondering, if and how such a generation would be possible using CMake.

Sincerely, Lehks

like image 380
Lehks Avatar asked Nov 08 '22 05:11

Lehks


1 Answers

These tools are not specific to CMake, but can be invoked inside CMake.

I recently collected together some links to create a single-header release for ApprovalTests.cpp.

I initially recorded them in a comment on an issue in podsiadly/ImageApprovals: this answer is to make that info easier to share.

C++ - Single-header Release Scripts

Options:

  • Some of these tools only pull together header files, which is fine if your master source code is header-only.
  • Others also have a way to pull in .cpp files, either adding inline to the output, or putting all the code from .cpp files into one location in the output, this is compiled only once.
    • This is how Catch2's CATCH_CONFIG_MAIN works, for example.

Claiming to be general

  • quom
    • Uses Python
    • Does not mention adding inline
  • Heady
    • C++ program
    • Does specifically explain pulling in .cpp files
    • Does acknowledge need to add inline to some functions from .cpp: has a (customisable) convention for putting inline_t in your source code, for where inline should be included in the generated header
  • Corrade Acme
    • Uses Python
    • You create a kind of template file that contains #include lines, and various template mark-up, Pragmas and so-on
    • Does not mention pulling in .cpp files?
    • Does not mention adding inline

Library Specific

  • Catch2
    • scripts/generateSingleHeader.py
    • I think it reads this and expands headers: include/catch.hpp
    • Then looks for this text // ~*~* CATCH_CPP_STITCH_PLACE *~*~ - which it finds in include/internal/catch_impl.hpp, and pastes all .cpp files in, in alphabetical order
  • ImageApprovals
    • single_header.py
    • Has tests: single_header_test.py
    • Should be reusable
    • The script:
      • goes over all headers/sources
      • removes include guards and relative #includes (in preprocess_file)
      • sorts files topologically (if a.hpp includes b.hpp then b.hpp will be processed first, SingleHeaderGen.generate)
      • and finally merges everything into a single header, with public headers first and implementation files inside #ifdef/#endif.
      • code from .cpp files will be compiled only once, when ImageApprovals_IMPLEMENT is defined
  • jfalcou/spy
    • embed.py
    • Removes comments
    • Removes extra include guards
    • Doesn't deal with .cpp files
  • ApprovalTests.cpp
    • Implemented in build/scripts/
    • Doesn't deal with .cpp files
    • Relevant scripts:
    • code_generation.py
    • single_header_file.py
    • embed.py
      • This is a modified version of the jfalcou/spy script above.
      • Retains comments
      • Has option to discard particular patterns of lines ("discardables")
      • Includes names of original files in comments
like image 135
Clare Macrae Avatar answered Nov 14 '22 23:11

Clare Macrae