CXXCTP

Add custom features to C++ language, like metaclasses, Rust-like traits, reflection and many more

A fully open source, powerful solution for modification and generation of C++ source code. Reduce the amount of boilerplate code in your C++ projects.


Open Source Love First Timers Only Up For Grabs GitHub GitHub forks GitHub issues GitHub pull requests GitHub contributors GitHub commit activity the past week, 4 weeks, year GitHub last commit GitHub top language GitHub language count Project Status: WIP - Initial development is in progress, but there has not yet been a stable, usable release suitable for the public. license Total alerts Lines of Code Average time to resolve an issue Percentage of issues still open

NOTE

This repo will be migrated to https://github.com/blockspacer/flextool as soon as possible

CXXCTP will be deprecated. Prefer flextool

🔗 Navigation

📚 About CXXCTP (CXX compile-time programming)

CXXCTP is a transpiler that extends C++ for new introspection, reflection and compile-time execution.

CXXCTP doesn't aim to create a predefined set of source code transformations. Users can share C++ scripts for source code transformation.

Suppose someone shared useful scripts like interface.cxx and enum_to_json.cxx to the open-source community. You can use them in your project just by placing them into the ctp_scripts folder.

Metaprogramming is an “art” of writing programs to treat other programs as their data. This means that a program could generate, read, analyse, and transform code or even itself to achieve a certain solution.

Note: This project is provided as it is, without any warranty (see License).

Features

  • C++ as compile-time scripting language (https://github.com/derofim/cling-cmake)
  • Template engine with full C++ power (transpiles template to valid C++ code, supports Cling, etc.). https://github.com/blockspacer/CXTPL
  • Ability to modify source files (implement metaclasses, transpile from C++X to C++Y etc.)
  • Ability to create new files (separate generated class to .hpp and .cpp, etc.)
  • Ability to check source files (implement style checks, design patterns, etc.)
  • Ability to compile scripts (rules for code transformations) for maximum performance, not only interpret them in Cling.

Motivation

Why wouldn't you just extend clang since it also provides some experimental features (modules for instance)?

Clang is a compiler while this project is a transpiler, that transforms code to standardized c++ code without the need to modify llvm/assembly.

Because the tool's output is C++ code, you can compile transpiled code using emscripten, use static code analyzers, run code inside cling etc.

CXXCTP allows you to create and share scripts for

  • source code check (like codestyle validation)
  • source code transformation (like alphabetical sort of all public functions inside some class)
  • compile-time programming (like retrieve source code modification rules from remote server and save them in some folder) etc.

Project status

In development, see examples. Currently supports only Linux.

Note that you can run Linux containers under Windows/Mac/etc.

⚙️ Usage examples

  • enum_gen_hpp.cxtpl - (codegen) enum to string + reflection metadata.
// usage example from ReflShapeKind.hpp
enum class
$apply(
  reflect_enum
)
ReflShapeKind0 : uint32_t {
  Box = 3,
  Sphere = 6,
};
  • typeclass_gen_cpp.cxtpl - (codegen) typeclasses. Supports combinations of multiple typeclasses and out-of-source method definitions (data and logic separation). Supports combinations of multiple typeclasses and out-of-source method definition (data and logic separation). See examples and https://twitter.com/TartanLlama/status/1159457033441165313
// Usage example. NOTE: no inheritance & definition outside lib.
// in lib .h
struct drawable {
  virtual void draw(const char* arg1) const noexcept = 0;
};
struct printable {
  virtual void print(const char* arg1, const char* arg2) const noexcept = 0;
};
struct canvas3D {
  std::string name3D;
};
struct canvas4D {
  std::string name4D;
};
// in app .cpp
void draw<drawable>(const canvas3D& data, const char* arg1){
  std::cout << "drawing to canvas3D name = " << data.name3D << std::endl;
}
void draw<drawable>(const canvas4D& data, const char* arg1){
  std::cout << "drawing to canvas4D name = " << data.name4D << std::endl;
}
void print<printable>(const canvas3D& data, const char* arg1, const char* arg2){
  std::cout << "printing to canvas3D name = " << data.name3D << std::endl;
}
void print<printable>(const canvas4D& data, const char* arg1, const char* arg2){
  std::cout << "printing to canvas4D name = " << data.name4D << std::endl;
}
std::vector<_tc_combined_t<drawable>> vec {
 canvas3D{},
 canvas4D{},
};
_tc_combined_t<drawable, printable> CVS = canvas4D{};
CVS.draw("");
CVS.print("", "");

canvas3D cvs3D;
CVS = std::move(cvs3D);

canvas4D cvs4D;
CVS = cvs4D; // copy

CVS = vec.at(0); // <drawable> to <drawable, printable>
  • parse-time/compile-time code execution (see examples)
$export (
static int resultSomeInt = 2345;
)
$eval("#include <optional>")
$exec(
  printf("execkjljlk\n");
  printf("execasdasd\n");
)
$set_embed("set_embed103",
  printf("set_embed101\n");
  printf("set_embed102\n");
)
$embed(
  [&clangMatchResult, &clangRewriter, &clangDecl]() {
    printf("embed01\n");
    printf("embed02\n");
    return new llvm::Optional<std::string>{"embed03"};
  }();
)
  • metaclasses. Supports combinations of multiple metaclasses (see examples).
class
$apply(make_interface;make_removefuncbody;make_reflect)
SomeInterfaceName {
  virtual ~SomeInterfaceName() = 0;
  /*int    f   (   )   {     // {}
    int i = 6;
    {
      // {
      // }
    }
    return i;
  };*/
  int foo();
  virtual void foobar(int& arg1) = 0;
  virtual inline void zoobar(int& arg2);
  //int m_bar;
  //int m_bar2 = 2;
};

🖥️ Cloning and setup

git submodule sync --recursive
git fetch --recurse-submodules
git submodule update --init --recursive --depth 100 --progress
# or
git submodule update --force --recursive --init --remote

Install & use with Docker

Install and configure Docker: https://medium.com/@saniaky/configure-docker-to-use-a-host-proxy-e88bd988c0aa

Clone code (as above) and cd into cloned dir.

NOTE: You may want to build Docker image with --build-arg NO_SSL="False". Read comments in Dockerfile.

# Give docker the rights to access X-server
sudo -E xhost +local:docker

# build Dockerfile
sudo -E docker build --no-cache \
  --build-arg GIT_WITH_OPENSSL="" \
  --build-arg NO_SSL="False" \
  -t cpp-docker-cxxctp .

# Now let’s check if our image has been created.
sudo -E docker images

# Run in container without leaving host terminal
sudo -E docker run -v "$PWD":/home/u/cxxctp -w /home/u/cxxctp cpp-docker-cxxctp CXXCTP_tool -version --version

# Run a terminal in container
sudo -E docker run --rm -v "$PWD":/home/u/cxxctp -w /home/u/cxxctp  -it  -e DISPLAY         -v /tmp/.X11-unix:/tmp/.X11-unix  cpp-docker-cxxctp

# type in container terminal
CXXCTP_tool -version --version

Develop with Docker

# Run a terminal in container
sudo -E docker run --rm -v "$PWD":/home/u/cxxctp -w /home/u/cxxctp  -it  -e DISPLAY         -v /tmp/.X11-unix:/tmp/.X11-unix  cpp-docker-cxxctp

# An example of how to build (with Makefile generated from cmake) inside the container
# Mounts $PWD to /home/u/cxxctp and runs command
mkdir build
sudo -E docker run --rm -v "$PWD":/home/u/cxxctp -w /home/u/cxxctp/build cpp-docker-cxxctp cmake -DCONAN_AUTO_INSTALL=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE ..

# Run resulting app in host OS:
# ./build/<app>

Install conan - a crossplatform dependency manager for C++

pip install --index-url=https://pypi.python.org/simple/ --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel \
  && \
  pip install --index-url=https://pypi.python.org/simple/ --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org virtualenv \
  && \
  pip install --index-url=https://pypi.python.org/simple/ --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org conan \
  && \
  pip install --index-url=https://pypi.python.org/simple/ --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org conan_package_tools

conan profile new default --detect
# conan profile update settings.compiler.libcxx=libstdc++11 default

conan remote list

conan search *boost* -r all

Configure Proxies & cacert_path in ~/.conan/conan.conf, see https://docs.conan.io/en/latest/reference/config_files/conan.conf.html#proxies

Configure conan clang profile to then use --profile clang:

/usr/bin/clang-6.0 -v
/usr/bin/clang++-6.0 -v

nano ~/.conan/profiles/clang

[settings]
# We are building in Ubuntu Linux
os_build=Linux
os=Linux
arch_build=x86_64
arch=x86_64

compiler=clang
compiler.version=6.0
compiler.libcxx=libstdc++11

[env]
CC=/usr/bin/clang-6.0
CXX=/usr/bin/clang++-6.0

And then conan install ***** --profile clang

/usr/bin/gcc -v
/usr/bin/g++ -v

nano ~/.conan/profiles/gcc

[settings]
# We are building in Ubuntu Linux
os_build=Linux
os=Linux
arch_build=x86_64
arch=x86_64

compiler=gcc
compiler.version=7
compiler.libcxx=libstdc++11

[env]
CC=/usr/bin/gcc
CXX=/usr/bin/g++

If you want to disable ssl (under proxy, etc.):

# see https://docs.conan.io/en/latest/reference/commands/misc/remote.html#conan-remote
conan remote update conan-center https://conan.bintray.com False
conan search boost* -r=conan-center

conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
conan remote update bincrafters https://api.bintray.com/conan/bincrafters/public-conan False
conan search boost* -r=bincrafters

If you want to set corp. cacert:

CONAN_CACERT_PATH=/path/to/ca-bundle.crt
file $CONAN_CACERT_PATH

Useful links:

Add conan remotes

To be able to add the list of dependency remotes please type the following command:

cmake -E time conan config install conan/remotes/
# OR:
# cmake -E time conan config install conan/remotes_disabled_ssl/

Dependencies

# NOTE: don't forget to re-run `conan install` after command below
# NOTE: change `build_type=Debug` to `build_type=Release` in production
cmake -DEXTRA_CONAN_OPTS="--profile;clang;-s;build_type=Debug;--build;missing" -P tools/buildConanThirdparty.cmake
  • type_safe
conan remote add Manu343726 https://api.bintray.com/conan/manu343726/conan-packages False

git clone http://github.com/foonathan/type_safe.git -b v0.2.1

cd type_safe

# NOTE: change `build_type=Debug` to `build_type=Release` in production
CONAN_REVISIONS_ENABLED=1 \
    CONAN_VERBOSE_TRACEBACK=1 \
    CONAN_PRINT_RUN_COMMANDS=1 \
    CONAN_LOGGING_LEVEL=10 \
    GIT_SSL_NO_VERIFY=true \
    conan create . conan/stable -s build_type=Debug --profile clang --build missing
  • corrade
# NOTE: change `build_type=Debug` to `build_type=Release` in production
git clone http://github.com/mosra/corrade.git && cd corrade
CONAN_REVISIONS_ENABLED=1 \
    CONAN_VERBOSE_TRACEBACK=1 \
    CONAN_PRINT_RUN_COMMANDS=1 \
    CONAN_LOGGING_LEVEL=10 \
    GIT_SSL_NO_VERIFY=true \
    conan create . magnum/stable -s build_type=Debug --profile clang --build missing -tf package/conan/test_package
  • MPI
sudo apt-get install openmpi-bin openmpi-common libopenmpi-dev
  • CMake
sudo -E apt-get purge -y cmake
bash scripts/install_cmake.sh

Install CXTPL library https://github.com/blockspacer/CXTPL

Install CXTPL_tool https://github.com/blockspacer/CXTPL#how-to-build

How to build

BEFORE install_cling.sh:
sudo apt-get update && sudo apt-get upgrade
sudo apt-get install clang-6.0 libstdc++6 libstdc++-6-dev
sudo update-alternatives --config c++
sudo update-alternatives --config cc
sudo ldconfig
export CC=clang-6.0
export CXX=clang++-6.0
# Build Cling into `cling-build` folder
cd scripts
bash install_cling.sh

Install deps as in CXTPL https://github.com/blockspacer/CXTPL#how-to-build

export CC=clang-6.0
export CXX=clang++-6.0
cmake -E remove_directory build
cmake -E make_directory build
cmake -E remove_directory resources/cxtpl/generated
cmake -E make_directory resources/cxtpl/generated
# NOTE: change `build_type=Debug` to `build_type=Release` in production
CONAN_REVISIONS_ENABLED=1 \
  CONAN_VERBOSE_TRACEBACK=1 \
  CONAN_PRINT_RUN_COMMANDS=1 \
  CONAN_LOGGING_LEVEL=10 \
  GIT_SSL_NO_VERIFY=true \
  cmake -E chdir build  \
    cmake -E time \
      conan install \
        -s build_type=Debug \
        --build=missing \
        --profile clang \
        -o enable_tests=False \
        -o openssl:shared=True \
        ..
cmake -E chdir build cmake -E time cmake -DCONAN_AUTO_INSTALL=OFF -DENABLE_CLING=TRUE -DBUILD_SHARED_LIBS=FALSE -DBUILD_EXAMPLES=FALSE -DALLOW_PER_PROJECT_CTP_SCRIPTS=TRUE  -DBUNDLE_EXAMPLE_SCRIPTS=FALSE -DCMAKE_BUILD_TYPE=Debug -DENABLE_CXXCTP=TRUE ..
cmake -E chdir build cmake -E time cmake --build . -- -j6

# you can install CXXCTP_tool:
sudo cmake -E chdir build make install

# NOTE: You can also use the “-p” flag with CMAKE_EXPORT_COMPILE_COMMANDS. See https://variousburglarious.com/2018/02/18/include-paths-for-clang-tools/
# cmake -E chdir build ./tool/CXXCTP_tool -p=../example_compile_commands/

# NOTE: runs CXXCTP_tool on multiple files and adds include paths by `-extra-arg=-I`
cmake -E chdir build ./tool/CXXCTP_tool -L .=DBG9 -extra-arg=-I$PWD/include -extra-arg=-I../resources ../examples/built_in/for_codegen/example_make_reflect.cpp

# check generator output
file build/example_make_reflect.cpp.generated.cpp

OR under gdb:

rm -rf *generated* ; clear && clear ; gdb ./CXXCTP -ex "run" -ex "bt" -ex "q"

How to build with Cling support

Use shared CXXCTP_core as SHARED library -DBUILD_SHARED_LIBS=TRUE.

Run bash scripts/install_folly.sh from https://github.com/blockspacer/CXTPL or patch folly manually for clang support (replace FOLLY_USE_JEMALLOC with FOLLY_ASSUME_NO_JEMALLOC) https://github.com/facebook/folly/issues/976

Use clang (NOT GCC!) before build and -DENABLE_CLING=TRUE:

export CC=clang-6.0
export CXX=clang++-6.0
sudo rm -rf examples/*/ctp_scripts/*/*/generated/
cmake -E remove_directory build
cmake -E make_directory build
cmake -E remove_directory resources/cxtpl/generated
cmake -E make_directory resources/cxtpl/generated
# NOTE: clang profile!
# NOTE: change `build_type=Debug` to `build_type=Release` in production
CONAN_REVISIONS_ENABLED=1 \
  CONAN_VERBOSE_TRACEBACK=1 \
  CONAN_PRINT_RUN_COMMANDS=1 \
  CONAN_LOGGING_LEVEL=10 \
  GIT_SSL_NO_VERIFY=true \
  cmake -E chdir build  \
    cmake -E time \
      conan install \
        -s build_type=Debug \
        --build=missing \
        --profile clang \
        -o enable_tests=False \
        -o openssl:shared=True \
        ..
cmake -E chdir build cmake -E time cmake -DCONAN_AUTO_INSTALL=OFF -DENABLE_CLING=TRUE -DBUILD_SHARED_LIBS=TRUE -DALLOW_PER_PROJECT_CTP_SCRIPTS=TRUE -DBUILD_EXAMPLES=FALSE -DBUNDLE_EXAMPLE_SCRIPTS=FALSE -DCLEAN_CXXCTP_GEN=TRUE -DCMAKE_BUILD_TYPE=Debug -DENABLE_CXXCTP=TRUE ..
# OR cmake -E chdir build cmake -E time cmake -DCONAN_AUTO_INSTALL=OFF -DENABLE_CLING=TRUE -DBUILD_SHARED_LIBS=TRUE -DALLOW_PER_PROJECT_CTP_SCRIPTS=FALSE -DBUILD_EXAMPLES=FALSE -DBUNDLE_EXAMPLE_SCRIPTS=TRUE -DCLEAN_CXXCTP_GEN=TRUE -DCMAKE_BUILD_TYPE=Debug -DENABLE_CXXCTP=TRUE ..
cmake -E chdir build cmake -E time cmake --build . -- -j6
# you can install CXXCTP_tool:
sudo cmake -E chdir build make install
# check supported plugins
/usr/local/bin/CXXCTP_tool --plugins

If you installed CXXCTP_tool - you can run examples:

# requires CXXCTP_tool
sudo cmake -E chdir build make install

# use -DBUILD_EXAMPLES=TRUE
rm ./build/examples/simple/CXXCTP_tool_for_CXXCTP_example.log
cmake -E chdir build cmake -E time cmake -DCONAN_AUTO_INSTALL=OFF -DENABLE_CLING=TRUE -DBUILD_SHARED_LIBS=TRUE -DBUILD_EXAMPLES=TRUE -DBUNDLE_EXAMPLE_SCRIPTS=FALSE -DALLOW_PER_PROJECT_CTP_SCRIPTS=TRUE -DCMAKE_BUILD_TYPE=Debug -DENABLE_CXXCTP=TRUE ..
cmake -E chdir build cmake -E time cmake --build . -- -j6
cat ./build/examples/simple/CXXCTP_tool_for_CXXCTP_example.log

Check that `.log` find doesn`t contain errors

# run examples
build/bin/CXXCTP_example

Don't forget to set Cling include paths by-extra-arg=-I\$PWD/includeand library paths by-extra-arg=-L\$PWD/buildand .so/.dll libs by-extra-arg=-lCXXCTP_core:

# NOTE: runs CXXCTP_tool on multiple files and adds include paths by `-extra-arg=-I`
cmake -E chdir build ./tool/CXXCTP_tool --ctp_scripts_paths=$PWD -L .=DBG9 -extra-arg=-I$PWD/include -extra-arg=-L$PWD/build -extra-arg=-lCXXCTP_core -extra-arg=-I../resources ../resources/ReflShapeKind.hpp ../resources/test_typeclass_base1.hpp ../resources/test_typeclass_instance1.hpp ../resources/test.cpp

How to add include paths or definitions for Cling

Use -extra-arg option of CXXCTP_tool:

-extra-arg=-I$PWD/include -extra-arg=-I$PWD/include/foo -extra-arg=-DMY_DEFINITION=1 -extra-arg=-DONE_MORE_DEFINITION=1

Example:

cmake -E chdir build ./tool/CXXCTP_tool --ctp_scripts_paths=$PWD -L .=DBG9 -extra-arg=-I$PWD/include -extra-arg=-I../resources ../resources/ReflShapeKind.hpp ../resources/test_typeclass_base1.hpp ../resources/test_typeclass_instance1.hpp ../resources/test.cpp

⌨️ Developing with CXXCTP

The following sections cover usage, custom rules and debugging for CXXCTP.

Writing code that writes code

You can write custom C++ scripts for source code transformation or use existing ones.

CXXCTP loads all C++ scripts from ctp_scripts folder in lexicographical order.

Example contents of ctp_scripts:

  • 1_utils
    • CXTPL_STD
      • CXTPL_STD.hpp
      • CXTPL_STD.cpp
    • CXXCTP_STD
      • CXXCTP_STD.hpp
      • CXXCTP_STD.cpp
  • 2_scripts
    • make_interface
      • make_interface.hpp
      • make_interface.cpp
    • typeclass
      • typeclass.hpp
      • typeclass.cpp

Utils must load before scripts (Cling related), so we added 1_, 2_, ... before folder names (see above).

You can use #include, use filesystem, access the internet, etc. in C++ scripts.

Got error `libcling.so.5: cannot open shared object file: No such file or

directory`

Install with -DENABLE_CLING=TRUE -DINSTALL_CLING=TRUE and set LD_LIBRARY_PATH

export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH
sudo ldconfig

About CXXCTP code annotations

You can use C++ annotations to tell CXXCTP what actions it must execute.

Suppose we want to morph class into interface:

// Source
class SomeInterfaceName {
  int foo1() {
    // ...
  };
  int foo();
  virtual void foobar(int& arg1) = 0;
  virtual void zoobar(int& arg2);
  virtual ~SomeInterfaceName() = 0;
};

// <== will be changed into ==>

// Result
class SomeInterfaceName {
  virtual int foo1() = 0;
  virtual int foo() = 0;
  virtual void foobar(int& arg1) = 0;
  virtual void zoobar(int& arg2) = 0;
  virtual ~SomeInterfaceName() = 0;
};

We can use funccall action to run C++ scripts for source code transformation. Let's suppose that script names are make_interface and make_removefuncbody (name as you want).

__attribute__((annotate("{gen};{funccall};make_interface;make_removefuncbody")))

{gen}; - keyword used in every CXXCTP annotation.

{funccall}; - keyword used to tell CXXCTP what it must execute C++ scripts with cling.

make_interface;make_removefuncbody - two scripts what CXXCTP will execute.

Scripts will be executed from left (make_interface) to right (make_removefuncbody).

Usually you don't need to write long C++ annotations, just use C++ #define (or include built-in header with common defines):

#define $apply(...) \
  __attribute__((annotate("{gen};{funccall};" #__VA_ARGS__)))

class
$apply(make_interface;
  make_removefuncbody)
SomeInterfaceName {
  virtual ~SomeInterfaceName() = 0;
  int foo();
  virtual void foobar(int& arg1) = 0;
  virtual void zoobar(int& arg2);
};

Using a similar approach you can apply multiple source code transformation steps to the same class / struct / etc.

How to add custom code transformation rules

Create files with your function in ctp_scripts

Copy custom_plugins.cmake.example as custom_plugins.cmake

Append your script paths to custom_plugins.cmake via add_ctp_plugin:

# first arg - typeclass_instance - script function name
# second arg - script source file
# third arg - script header file
# last arg - path to CMakeLists.txt used to generate script-related files
add_ctp_plugin(
  "typeclass_instance"
  ${CMAKE_CURRENT_SOURCE_DIR}/examples/simple/ctp_scripts/2_scripts/typeclass_instance/typeclass_instance.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/examples/simple/ctp_scripts/2_scripts/typeclass_instance/typeclass_instance.hpp
  ${CMAKE_CURRENT_SOURCE_DIR}/examples/simple/ctp_scripts/2_scripts/typeclass_instance
)

Check that your function name exists in generated file ctp_registry.cpp (may be skipped in Cling / dev-mode)

Function signature for code transformation must be compatible with cxxctp_callback:

typedef std::function<const char*(
    const cxxctp::parsed_func& func_with_args,
    const clang::ast_matchers::MatchFinder::MatchResult& matchResult,
    clang::Rewriter& rewriter,
    const clang::Decl* decl,
    const std::vector<cxxctp::parsed_func>& all_funcs_with_args)> cxxctp_callback;

Detailed function signature:

Think about function name as one of __VA_ARGS__ from

#define $apply(...) \
  __attribute__((annotate("{gen};{funccall};" #__VA_ARGS__)))

Example where make_interface and make_removefuncbody - two function names:

$apply(make_interface;
  make_removefuncbody)

If you need code generation:

  • Create template file (.cxtpl). Build your file using CXTPL_tool https://github.com/blockspacer/CXTPL
  • Create all needed template arguments inside of your function. Names, types, etc. for arguments must be the same as in template (cause generated template is valid C++ code).
  • Create variable std::string cxtpl_output, that will store result of template rendering with some arguments.
  • Include file generation from template file (.cxtpl) inside of your function.

What is .cxtpl

.cxtpl is the file extension for the C++ template engine https://github.com/blockspacer/CXTPL

How to add .cxtpl at compile-time (CMake)

Add your .cxtpl file into Codegen_files.cmake

NOTE: In dev mode (like cling mode) it may be a good idea to generate files from templates using CXTPL_tool https://github.com/blockspacer/CXTPL You can add generation rules into Codegen_files.cmake later in the release build.

NOTE: Don't forget to provide both .cxtpland.cxtpl.h files with shared codegen rules (add to version control system).

How to use .cxtpl at runtime with Cling

You have two options:

  • Generate a file from your .cxtpl, then include it into Cling C++ script. Similar to compile-time, but you can re-generate or change files without program recompilation. Note that it is possible to generate files and include them in your script; just split script into multiple includes.
  • Generate a string from your .cxtpl, then run it in a separate Cling interpreter. In most cases you will use the first option.

How to use .cxtpl with CXXCTP

Pass reflection data into template engine.

Generate files from templates using CXTPL_tool https://github.com/blockspacer/CXTPL

In CXXCTP script (.cpp):

// see ReflectAST.cpp
reflection::NamespacesTree m_namespaces;
// `node` from AST parser (libtooling)
reflection::ClassInfoPtr structInfo = reflector.ReflectClass(node, &m_namespaces);

// ...

stuct Arguments {
  // any custom arguments here ...
  std::string arg1 = "arg1...";
  std::string arg2 = "arg2...";
  // reflection data here (ClassInfoPtr) ...
};

// ...

std::map<std::string, std::any> cxtpl_params;
{
    cxtpl_params["Arguments"] =
        std::make_any<Arguments>(Arguments{});
    cxtpl_params["generator_path"] =
        std::make_any<std::string>("enum_gen_hpp.cxtpl");
    cxtpl_params["generator_includes"] =
        std::make_any<std::vector<std::string>>(
            std::vector<std::string>{});

    std::string cxtpl_output;

#include "../../resources/cxtpl/generated/enum_gen_hpp.cxtpl.cpp"

    writeToFile(cxtpl_output, gen_hpp_name);
}

In .cxtpl template:

const auto arguments = std::any_cast<Arguments>(cxtpl_params.at("Arguments"));
std::cout << arguments.arg1;

See resources/cxtpl/enum_gen_hpp.cxtpl as an example.

How to use CXXCTP_tool

CXXCTP_tool wraps libtooling to add custom command-line options.

Options related to libtooling (type -help or --help):

Generic Options:

  -help                      - Display available options (-help-hidden for more)
  -help-list                 - Display list of available options (-help-list-hidden for more)
  -version                   - Display the version of this program

Use override options:

  -extra-arg=<string>        - Additional argument to append to the compiler command line
  -extra-arg-before=<string> - Additional argument to prepend to the compiler command line
  -p=<string>                - Build path

Options related to CXXCTP_tool (type --help, not -help):

ctp_scripts_paths - list of paths where toll will search for ctp_scripts subfolder

NOTE: ctp_scripts_paths requires -DENABLE_CLING=TRUE

-L .=DBG9 is log configuration in format https://github.com/facebook/folly/blob/master/folly/logging/docs/Config.md

Example of log configuration that writes both into the file and console stream:

./build/bin/CXXCTP_tool -L ".:=INFO:default:console; default=file:path=y.log,async=true,sync_level=DBG9;console=stream:stream=stderr"

--srcdir to change current filesystem path for input files.

--resdir to change current filesystem path for output files.

Example (custom output dir):

# Remove old generated files
rm -rf gen
rm -rf build/*generated*

`--version` to get tool version

`-version` to get clang version

# Build files to `gen/out` dir
mkdir -p gen/out
cmake -E chdir gen ../build/bin/CXXCTP_tool --resdir=$PWD/gen/out --ctp_scripts_paths=$PWD -L .=DBG9 -extra-arg=-I$PWD/include -extra-arg=-I../resources ../resources/ReflShapeKind.hpp ../resources/test_typeclass_base1.hpp ../resources/test_typeclass_instance1.hpp ../resources/test.cpp

How to debug ctp_scripts

Remove old build artifacts and generated files.

Bundle your scripts with CXXCTP_tool via -DBUNDLE_EXAMPLE_SCRIPTS=TRUE.

Make sure that your scripts (plugins) are added to CXXCTP_tool via custom_plugins.cmake.example.

Disable per-project scripts -DALLOW_PER_PROJECT_CTP_SCRIPTS=FALSE.

Check that your scripts (plugins) are in build/tool/CXXCTP_tool --plugins

Check that the system-installed version of CXXCTP_tool is the same as build/tool/CXXCTP_tool (by date/file hash)

Run CXXCTP_tool manually under gdb:

gdb -ex "r" -ex "bt" --args build/tool/CXXCTP_tool .........

Check that all needed paths are in -extra-arg=.

Make a log to file in DBG9 mode and check .log files.

🔧 Tools used by CXXCTP

About libtooling

CXXCTP uses LibTooling to parse and modify C++.

LibTooling is a library to support writing standalone tools based on Clang.

Useful links:

About cling

CXXCTP uses cling to execute C++ at compile-time.

You can use cling for hot code reload / REPL / Fast C++ prototyping / Scripting engine / JIT / etc.

Useful links:

clang-format

sudo apt install clang-format

Run based on .clang-format file:

find . -regex '.*\.\(cpp\|hpp\|cu\|c\|h\)' -exec clang-format -style=file -i {} \;

Useful links:

⭐️ How to Contribute

Please read our contributing guidelines before making your pull request.

Code of Conduct

Please note that this project is released with a Code of Conduct. By participating in this project, you agree to abide by its terms.

Contributors List: Example Profile

  • I'm an example that you can copy, if you want :)
  • I work on many things like...
  • My hobbies include...
  • twitter-alt facebook-alt google-img tumblr-alt dribbble-alt github-alt freeCodeCamp

Contributors List 👌

A

Anindita Basu
  • Technical writer
  • twitter-alt github-alt
Anna Hayhurst
  • Junior Developer
  • github-alt

C

Cássio Espíndola
  • Analyst Developer
  • github-alt

D

Denis trofimov
  • C++ Developer
  • github-alt
  • github-alt

M

Mohib Qureshi
  • Software Development Enthusiast
  • github-alt

Y

Yousif Alebyary
  • Web/Mobile Developer.
  • github-alt
Yves Mancera
  • Software Engineer
  • github-alt

Standing on the Shoulders of Giants

That project possible because of flexferrum's autoprogrammer.

Articles about flexferrum's autoprogrammer in media:

LICENSE for open source components

All the open source components are used under their associated open source licences.

Used open source components:

  • icu
  • ced
  • boost
  • harfbuzz
  • boost.outcome
  • chromium (base)
  • libevent
  • modp_b64
  • tcmalloc
  • xdg_mime
  • xdg_user_dirs
  • dynamic_annotations
  • (Facebook) Folly
  • (Microsoft) GSL

See LICENSE files

CMake Code style

CMake files pass style checks, can be fixed by running run-cmake-format.py from the root of the repository. This requires Python 3 and cmake_format (note: this currently does not work on Windows)

Use autoformatter cmake-format.py and run-cmake-format.py

pip3 install cmake_format
python3 run-cmake-format.py

To use cmake-format on a specific CMakeLists.txt file in the command line run

python3 -m cmake_format -c cmake-format.py -i CMakeLists.txt

There is an official Visual Studio extension, details of which can be found here.

Follow CMake StyleGuide https://github.com/ruslo/0

Projects that use .cxtpl

  • SKG C++ HTML/CSS UI.

📋 Similar projects

Cxxctp

DEPRECATED. USE INSTEAD github.com/blockspacer/flextool

Cxxctp Info

⭐ Stars 58
🔗 Source Code github.com
🕒 Last Update 9 months ago
🕒 Created 2 years ago
🐞 Open Issues 0
➗ Star-Issue Ratio Infinity
😎 Author blockspacer