Headers amalgamation#
Litgen processes files individually, and if a subclass is defined in a different file than its parent, inherited members may not be correctly bound.
Sometimes it is worthwhile to first generate an Amalgamation Header
for a library before generating bindings for it.
An amalgamation header is a single header file that includes all the public headers of a library.
Amalgamation utility#
litgen
provides a utility function write_amalgamate_header_file
to generate an Amalgamation header file.
It is available in the codemanip.amalgamated_header
module.
from codemanip import amalgamated_header
And its API is as follows:
@dataclass
class AmalgamationOptions:
base_dir: str # The base directory of the headers
local_includes_startwith: str # Only headers whose name begin with this string should be included
include_subdirs: list[str] # Include only headers in these subdirectories
main_header_file: str # The main header file
dst_amalgamated_header_file: str # The destination file
def write_amalgamate_header_file(options: AmalgamationOptions) -> None:
...
write_amalgamate_header_file
takes an AmalgamationOptions
object as an argument and generates an Amalgamation header file.
It will include all the headers whose name starts with local_includes_startwith
in the base_dir
directory
and its subdirectories given in include_subdirs
.
Note: it will include any file only once: if a file was already included by another file, it will not be included again.
A concrete example#
Let’s take an example with the Hello ImGui library.
This library is a C++ library
that wraps the Dear ImGui library and provides additional functionalities.
Its bindings are generated using the litgen
library, and are available in Dear ImGui Bundle.
It has a directory structure as shown below.
src
├── CMakeLists.txt
├── hello_imgui
│ ├── CMakeLists.txt
│ ├── app_window_params.h
│ ├── hello_imgui.h --> ( hello_imgui.h is the main header, included by users
│ ├── imgui_window_params.h it "#include" all other public API headers )
│ ├── ... (other headers)
│ │
│ ├── internal
│ │ ├── borderless_movable.cpp
│ │ ├── borderless_movable.h
│ │ ├── clock_seconds.cpp
│ │ ├── clock_seconds.h
│ │ ├── ... (other headers and c++ files)
│ │ ├── ... (not part of the public API)
And its main header file hello_imgui.h
looks like this:
#pragma once
#if defined(__ANDROID__) && defined(HELLOIMGUI_USE_SDL2)
// We need to include SDL, so that it can instantiate its main function under Android
#include "SDL.h" // This include should *not* be in the amalgamation header
#endif
#include "hello_imgui/dpi_aware.h" // Only headers whose name begin with
#include "hello_imgui/hello_imgui_assets.h" // "hello_imgui" should be included
#include "hello_imgui/hello_imgui_error.h" // in the amalgamation header
#include "hello_imgui/hello_imgui_logger.h"
#include "hello_imgui/image_from_asset.h"
#include "hello_imgui/imgui_theme.h"
#include "hello_imgui/hello_imgui_font.h"
#include "hello_imgui/runner_params.h"
#include "hello_imgui/hello_imgui_widgets.h"
#include <string> // Other includes can be included as usual
#include <cstddef>
#include <cstdint>
... (other includes)
The code to generate the Amalgamation header file is as follows:
from codemanip import amalgamated_header
options = amalgamated_header.AmalgamationOptions()
options.base_dir = hello_imgui_src_dir # The base directory of the headers
options.local_includes_startwith = "hello_imgui/" # Only headers whose name begin with "hello_imgui" should be included
options.include_subdirs = ["hello_imgui"] # Include only headers in the hello_imgui directory
options.main_header_file = "hello_imgui.h" # The main header file
options.dst_amalgamated_header_file = PYDEF_DIR + "/hello_imgui_amalgamation.h" # The destination file
amalgamated_header.write_amalgamate_header_file(options)
And the generated Amalgamation header file hello_imgui_amalgamation.h
will look like this:
// THIS FILE WAS GENERATED AUTOMATICALLY. DO NOT EDIT.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// hello_imgui.h //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(__ANDROID__) && defined(HELLOIMGUI_USE_SDL2)
// We need to include SDL, so that it can instantiate its main function under Android
#include "SDL.h"
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// hello_imgui/dpi_aware.h included by hello_imgui.h //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "imgui.h"
namespace HelloImGui
{
... (content of hello_imgui/dpi_aware.h)
}
... (other includes)