a rust command line utility to generate portable C/C++ single header file
This Rust program is designed to convert C/C++ files into portable single-header files.
- It processes C/C++ files by running the C preprocessor on it
- Call the C preprocessor with the
-fdirectives-onlyoption to limit system specific macros / includes - Undoes the
#includeexpansion of all system headers - does so by relying on gcc preprocessor output documentation as the expected proprocessor output
- replaces them with
#includedirectives that are as close to the original as possible. - Offers protection against multiple inclusions with either
#ifndefor#pragma once.
Limitations:
- all preprocessor conditions (
#if/#else/#endif) that occurs outside system headers will be evaluated. Only way to prevent this would be to implement a custom mock C-preprocessor. - if the input file contains non-inlined definitions the header will not be safe to include in multiple translation units. #5
for the following project
// test.hpp
#pragma once
#include "first.hpp"
void test() {}
// first.hpp
#pragma once
#include "second.hpp"
#include <cstddef>
void second_function() {}
// second.hpp
#pragma once
#include <type_traits>
void first_function() {}will produce:
$> single-header test.hpp
#ifndef TEST_HPP_SINGLE_HEADER
# define TEST_HPP_SINGLE_HEADER
#include <type_traits>
void first_function() {}
#include <cstddef>
void second_function() {}
void test() {}
#endif // TEST_HPP_SINGLE_HEADERUsing cargo via crates.io:
cargo install single-headerManually:
git clone git@github.com:DaemonSnake/single-header.git
cd single-header
cargo install --path .Usage: single-header [OPTIONS] <FILE> [-- <CPP_OPTS>...]
Arguments:
<FILE>
path to c/c++ header file
[CPP_OPTS]...
additional parameters for the preprocessor
Options:
-p, --preprocessor <PREPROCESSOR>
[default: cpp]
[possible values: cpp, gcc, clang]
--cmake <CMAKE>
path to build folder to find the compile_commands.json file that contains how to compile <FILE>
-i, --inline <INLINE_PATH>
path / file that must allways be `#include` expanded (can be provided multiple times)
-x, --lang <LANG>
[default: c++]
[possible values: c, c++]
--protect <PROTECTION>
protect against multiple includes with `#ifndef` or `#pragma once`
[default: ifndef]
[possible values: ifndef, once]
-h, --help
Print help (see a summary with '-h')- Rust
- at least one C Preprocessor
cpp,gccorclang