Skip to content

C++ template engine that generates C++ code from template (approach similar to Jinja2 that translates template into Python), so you will gain VERY good performance and full power of C++.

License

Notifications You must be signed in to change notification settings

ThirumlaDevi/CXTPL

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

 

cxtpl

C++ Template engine

Transpiles template into valid C++ code


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

📚 About CXTPL (C++ template engine)

Template engine with full C++ power (transpiles template into valid C++ code, supports Cling, etc.).

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

What is .cxtpl

.cxtpl is a file extension for C++ template engine.

Example (more below):

<div> some template string here </div>
[[~ int valid_cpp_code_block_here = 0; ~]]
[[~]] int and_valid_cpp_code_line_here = 0;
<div> another template string here </div>
<div> C++ from template = [[* valid_cpp_code_block_here *]] </div>

You can pass C++ variables by pointers into cxtpl, this is very useful if you want to use complex data structures as template parameters.

C++ template engine transpiles template into C++ code, so you will gain VERY good performance and full power of C++.

C++ template engine may run in two modes:

  • compile-mode: compiles cxtpl code into C++ file or std::string, then #include generated code & compiled app as usual. Best performance.
  • cling-mode (C++ JIT executed at runtime): compiles cxtpl code into C++ file or std::string, then run generated code in Cling interpreter (no need to recompile app, useful in dev-mode or for php-style apps). See as example https://github.com/blockspacer/CXXCTP

How to use C++ file generated by .cxptl

Again: Think about .cxtpl as lambda-function returning std::string. Prefer not to use #include from .cxtpl, just create .cxtpl.h file. Then #include both generated .cxtpl.cpp and created .cxtpl.h in your app code.

Code generated from .cxtpl must create a variable with the name cxtpl_output, so the structure of your code is as shown below:

/// \Note that header is NOT generated, it includes stuff for other generated file
#include "../../resources/cxtpl/typeclass_instance_gen_hpp.cxtpl.h"

// ...

void somefunc() {
  std::string cxtpl_output;

  /// \Note this is a generated .cpp file, it must not use #include
  #include "../../resources/cxtpl/generated/typeclass_instance_gen_hpp.cxtpl.cpp"

  writeToFile(cxtpl_output, gen_hpp_name);
}

You need to #include all headers used by template generator in your app code. It is a good practice to create separate .cxtpl.h file near your .cxtpl. Separation of included files makes it possible to use same includes/logic both in compile-mode (just #include your .cxtpl.h) and cling-mode (pass contents of your .cxtpl.h as function argument). See enum_gen_hpp.cxtpl.h and CXTPL_STD.h as an example.

Template syntax

.cxtpl uses approach similar to How to write a template engine in less than 30 lines of code from https://bits.theorem.co/how-to-write-a-template-library/

  • [[~ means start execution of C++ code while parsing template. Requires ~]] as closing tag.
  • ~]] means end execution of C++ code while parsing template
  • [[~]] means start execution of C++ code while parsing template. Requires newline (\n) as closing tag.
  • [[+ means add result of execution of C++ code to output while parsing template. Result must be string. Requires +]] as closing tag.
  • [[* means add result of execution of C++ code to output while parsing template. Result will be converted to string (just wrapped in std::to_string). Requires *]] as closing tag.
  • [[include file/path/here include]] - include some .cxtpl file inside another .cxtpl file

Example before template parsing/transpiling:

[[~ // parameters begin

const std::string generator_path = "somepath";

std::vector<std::string> generator_includes{"someinclude"};

// parameters end
/* no newline, see CX=l */ ~]][[~]]
// This is a generated file. Do not modify directly.
// Path to the code generator: [[+ generator_path +]].

[[~]] for(const auto& fileName: generator_includes) {
[[+ fileName /* CX=r used to append to cxtpl_output */ +]]
[[~]] } // end for

Example after template parsing/transpiling:

// This is a generated file. Do not modify directly.
// Path to the code generator: somepath.

someinclude

useful links:

Clone code

# git submodule deinit --all -f
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 under 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-cxtpl .

# 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/cxtpl -w /home/u/cxtpl cpp-docker-cxtpl CXTPL_tool -version --version

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

# type in container terminal
CXTPL_tool -version --version

Develop under Docker

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

# An example of how to build (with Makefile generated from cmake) inside the container
# Mounts $PWD to /home/u/cxtpl and runs command
mkdir build
sudo -E docker run --rm -v "$PWD":/home/u/cxtpl -w /home/u/cxtpl/build cpp-docker-cxtpl 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
  • g3log
bash scripts/install_g3log.sh
  • gtest
bash scripts/install_gtest.sh
  • gflags
bash scripts/install_gflags.sh

NOTE: need libunwind with -fPIC (POSITION_INDEPENDENT_CODE) support

bash scripts/install_libunwind.sh
  • Folly

deps from https://github.com/facebook/folly#ubuntu-1604-lts

sudo apt-get install \
    libevent-dev \
    libdouble-conversion-dev \
    libgoogle-glog-dev \
    libgflags-dev \
    libiberty-dev \
    liblz4-dev \
    liblzma-dev \
    libsnappy-dev \
    zlib1g-dev \
    binutils-dev \
    libjemalloc-dev \
    libssl-dev \
    pkg-config

NOTE: we patched folly for clang support facebook/folly#976

bash scripts/install_folly.sh

How to build

export CC=clang-6.0
export CXX=clang++-6.0
# create build dir
cmake -E remove_directory build
cmake -E make_directory build
# 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 openssl:shared=True \
        -o enable_tests=False \
        ..
# configure
cmake -E chdir build cmake -E time cmake -DCONAN_AUTO_INSTALL=OFF -DBUILD_EXAMPLES=FALSE -DENABLE_CLING=FALSE -DINSTALL_CLING=FALSE -DCMAKE_BUILD_TYPE=Debug ..
# build
cmake -E chdir build cmake -E time cmake --build . -- -j6
# install lib and CXTPL_tool
sudo cmake -E chdir build make install
CXTPL_tool --help
# run CXTPL_tool
cmake -E time cmake -E chdir build/tool CXTPL_tool --help
# example input
echo "file1.cxtpl" >> build/file1.cxtpl
echo "file2.cxtpl" >> build/file2.cxtpl
echo "file3.cxtpl" >> build/file3.cxtpl
echo "file4.cxtpl" >> build/file4.cxtpl
cmake -E time ./build/bin/CXTPL_tool --threads 6 --input_files build/file1.cxtpl build/file2.cxtpl --output_files build/file1.cxtpl.generated.cpp build/file2.cxtpl.generated.cpp
# (optional) check examples. Requires -DBUILD_EXAMPLES=TRUE
# configure
cmake -E chdir build cmake -E time cmake -DCONAN_AUTO_INSTALL=OFF -DBUILD_EXAMPLES=TRUE -DENABLE_CLING=FALSE -DINSTALL_CLING=FALSE -DCMAKE_BUILD_TYPE=Debug ..
# build
cmake -E chdir build cmake -E time cmake --build . -- -j6
# examples
cmake -E time ./build/bin/CXTPL_examples_simple
cmake -E time ./build/bin/CXTPL_examples_cmake_integration

How to use CXTPL_tool

--help for list of available command line options

--input_files for input files.

--output_files for output files. If not set, than output file names will generated based on input file names.

Number of input files must be equal to the number of output files. File order is important.

./build/bin/CXTPL_tool --threads 6 --input_files build/file1.cxtpl build/file2.cxtpl build/file3.cxtpl build/file4.cxtpl --output_files build/file1.cxtpl.generated.cpp build/file2.cxtpl.generated.cpp build/file3.cxtpl.generated.cpp build/file4.cxtpl.generated.cpp -L ".=DBG9"

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

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

./build/bin/CXTPL_tool --threads 6 --input_files build/file1.cxtpl build/file2.cxtpl --output_files build/file1.cxtpl.generated.cpp build/file2.cxtpl.generated.cpp j -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.

--global_timeout_ms to limit execution time for input files (performs check after task completion to stop other tasks from running).

--single_task_timeout_ms to limit execution time for singe input file (performs check after task completion to stop other tasks from running).

--version to get tool version

How to use with CMake project

Suppose you need to generate code based on template files before building TARGET_NAME_HERE.

Add path to cmake/exports to your CMAKE_MODULE_PATH:

# replace path/to/CXTPL with yours
list(APPEND CMAKE_MODULE_PATH path/to/CXTPL/cmake/exports)

Specify files for code generation:

set(cxtpl_in_dir "${CMAKE_CURRENT_SOURCE_DIR}/resources/cxtpl")
set(cxtpl_out_dir "${CMAKE_CURRENT_SOURCE_DIR}/resources/cxtpl/generated")

list(APPEND cxtpl_inputs "${cxtpl_in_dir}/enum_gen_hpp.cxtpl")
list(APPEND cxtpl_inputs "${cxtpl_in_dir}/enum_gen_cpp.cxtpl")

list(APPEND cxtpl_outputs "${cxtpl_out_dir}/enum_gen_hpp.cxtpl.cpp")
list(APPEND cxtpl_outputs "${cxtpl_out_dir}/enum_gen_cpp.cxtpl.cpp")

Macro target_add_CXTPL_tool will invoke CXTPL_tool on TARGET_NAME_HERE:

find_package(CXTPL_tool REQUIRED)

# Use `target_add_CXTPL_tool`
# See examples

See examples/cmake_integration

Projects that use .cxtpl

  • CXXCTP is a transpiler that extends C++ for new introspection, reflection and compile-time execution.
  • SKG C++ HTML/CSS UI.

Project status

In development

Currently supports only linux.

Note that you can run linux containers under windows, mac, etc.

About cling

You can use cling to execute C++ at compile-time/run-time, for hot code reload / REPL / Fast C++ prototyping / Scripting engine / JIT / etc.

useful links:

RTTI

RTTI enabled only in command line tool (CXTPL_tool), RTTI required by boost.po.

CXTPL library disabled RTTI and uses BOOST_NO_RTTI/BOOST_NO_TYPEID (as private cmake config).

How to build with support for custom generators (uses Cling)

By default CXTPL outputs C++ code into .cpp files.

You create custom generator to process C++ code produced by CXTPL.

Using custom generator you can:

  • output any file format (for example: valid .html file).
  • add predefined variables.

Generator path must be valid .cpp file that will be executed by Cling.

You can set generator path via --generator_path=YOUR_PATH_TO_CPP_FILE_HERE

Use install_cling.sh and build CXTPL with Cling support -DENABLE_CLING=TRUE -DINSTALL_CLING=TRUE.

# 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

NOTE:

  • Custom generators created for fast prototyping. You can create custom command-line tool (see sources of CXTPL_tool) to do more than custom generators and without Cling performance overhead. Chain outputs of tools like so: CXTPL outputs cpp files with result stored in C++ variable -> Custom tool outputs any file format based on result stored in C++ variable.

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

⭐️ 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 👌

FarzanHosseini

  • github-alt

D

Denis trofimov

  • C++ Developer
  • github-alt
  • github-alt

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

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

Similar projects

About

C++ template engine that generates C++ code from template (approach similar to Jinja2 that translates template into Python), so you will gain VERY good performance and full power of C++.

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • CMake 36.0%
  • C++ 26.0%
  • Python 24.4%
  • Dockerfile 9.3%
  • Shell 4.3%