slycelote / caide-cpp-inliner

Transform a C++ program consisting of multiple source files and headers into a single self-contained source file without any external dependencies (except for standard system headers). Unused code is not included in the resulting file.
Other
32 stars 12 forks source link
amalgamation clang cpp dead-code-removal

Caide C++ inliner

Build
status

Caide C++ inliner transforms a C++ program consisting of multiple source files and headers into a single self-contained source file without any external dependencies (except for standard system headers). Unused code is not included in the resulting file.

This project is available at the following mirrors:

Demo

The directory doc/demo contains a small sample application. We will write a program using caideInliner library that processes the source code of this application:

#include "caideInliner.hpp"
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

int main() {
    using namespace std;
    try {
        // (1)
        const string tempDirectory = "/tmp";
        caide::CppInliner inliner(tempDirectory);
        // (2)
        inliner.clangCompilationOptions.push_back("-std=c++11");
        inliner.clangCompilationOptions.push_back("-I");
        inliner.clangCompilationOptions.push_back(".");
        // (3)
        inliner.clangCompilationOptions.push_back("-isystem");
#ifdef _WIN32
        inliner.clangCompilationOptions.push_back("C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.10150.0\\ucrt");
#else
        inliner.clangCompilationOptions.push_back("../../src/llvm-project/clang/lib/Headers");
#endif

        // (4)
        vector<string> files;
        files.push_back("main.cpp");
        files.push_back("ascii_graphics.cpp");

        // (5)
        inliner.inlineCode(files, "result.cpp");
    } catch (const exception& e) {
        cerr << e.what() << endl;
        return 1;
    }
    return 0;
}

The above code, after including the caideInliner header:

  1. specifies a directory for temporary files (it must already exist)
  2. sets up compilation options (they may vary depending on the application)
  3. adds additional directories containing system header files. It's either a hardcoded path for VS 2015, or a path to built-in clang headers (available in clang source tree included in this repository). You may need to tweak these options further depending on your system.
  4. lists all c++ source files of the application.
  5. finally, runs the inliner and outputs the result in a single c++ file.

Compile and run this code. (You will need to link against caideInliner library and several clang and LLVM static libraries.) Alternatively, a simple command-line utility is included that you can run like this: ./cmd -std=c++11 -I . -isystem ../../src/clang/lib/Headers/ -- main.cpp ascii_graphics.cpp.

Inspect the resulting code in the file result.cpp. Note how unused parts of the code (e.g. one of the constructors of CommandLineParserException or inactive preprocessor blocks from main.cpp) were eliminated.

Now add a preprocessor definition OPT_FRAME:

        inliner.clangCompilationOptions.push_back("-DOPT_FRAME");

and rerun the program. Observe how the output file changes accordingly.

Build

clang library is a required dependency. You can either build it from scratch, or use a version installed in your system.

Replace the last argument with the full path to src directory. Replace "Unix Makefiles" with "Visual Studio 16 2019" or another generator suitable for your platform. Refer to cmake documentation for details.

Once build files are generated, build as usual (run make, open the VS solution etc.)

When the build is done, run ctest to execute the test suite.

Documentation

Refer to Doxygen comments in caideInliner header.

Known issues