Skip to content

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.

License

Notifications You must be signed in to change notification settings

xxyyzz/caide-cpp-inliner

 
 

Repository files navigation

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.

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/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

You will need CMake and a relatively new compiler (tested with g++ 4.8 and VS 2015). From an empty directory execute the following command: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release /path/to/src. Replace "Unix Makefiles" with "Visual Studio 12 2013" or another generator suitable for your platform. Replace the last argument with the full path to src directory. You can also use cmake-gui.

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

By default all necessary parts of libclang and LLVM will be built from scratch. This may take up to 30 minutes on a weak machine. If you have those libraries installed in the system (in Linux, search for packages libclang-3.6-dev and llvm-3.6-dev or similar), you can use them instead by passing -DCAIDE_USE_SYSTEM_CLANG=ON option to cmake. However, it's not recommended.

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

Documentation

Refer to Doxygen comments in caideInliner header.

Known issues

  • Non-standard features, such as defining a function without return type, are not supported.

  • Defining a class and a variable of the same class simultaneously (struct A {} a;) is not supported.

  • Unused global variables are removed. This is fine, unless you use such a variable for side effects. In that case, mark the variable with a comment /// caide keep or /** caide keep **/ (note the triple slash and the double asterisk). For example,

      struct SideEffect {...};
      /// caide keep
      SideEffect instance;
    

    In general, if you find that a declaration is removed incorrectly, mark this declaration with caide keep (and file an issue :)).

About

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.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 93.3%
  • CMake 5.0%
  • Other 1.7%