Coder Social home page Coder Social logo

blockspacer / flex_pimpl_plugin Goto Github PK

View Code? Open in Web Editor NEW
5.0 4.0 0.0 314 KB

C++ pimpl code generator. Fast pimpl without overhead! No dynamic memory allocation! Cache-friendly! Auto-detects storage size! Generates methods based on implementation!

Home Page: https://blockspacer.github.io/flex_docs/

CMake 52.38% Python 9.98% C++ 37.07% C 0.57%
pimpl conan cmake cpp cpp11 cpp14 cpp17 libtooling llvm clang

flex_pimpl_plugin's Introduction

About

Plugin for https://github.com/blockspacer/flextool

Plugin provides support for pimpl pattern also known as 'Pointer to Implementation'.

According to this pattern C++ developer divides the class into two parts: public (interface) part and private (implementation).

Both parts are C++ classes, but only interface is visible to the class users, and implementation is hidden behind pointer.

Source file with public class implementation contains a lot of boilerplate code.

We use flextool (libtooling) to generate code and reduce the amount of boilerplate code.

Note that plugin output is valid C++ code: you can open generated files and debug them as usual.

If you do not know why to use C++ pimpl see https://www.bfilipek.com/2018/01/pimpl.html

See for details about flextool https://blockspacer.github.io/flex_docs/

How it works

See https://blockspacer.github.io/flex_docs/tutorial/

Usage

See flex_pimpl_plugin/tests for example code.

i.e. tests/Foo.hpp and tests/FooImpl.hpp

// will replace itself with generated code like:
// std::string foo() { return impl_->foo(); }
template<
  typename impl = FooImpl
  , typename interface = Foo
>
class _injectPimplMethodCalls()
  PimplMethodCallsInjector
{};

// Proxy method calls based on PImpl implementation.
// Will replace itself with generated code like:
// std::string foo();
// int bar(int&& arg1, const int& arg2) const noexcept;
template<typename impl = FooImpl>
class
  _injectPimplMethodCalls(
    "without_method_body"
  )
PimplMethodDeclsInjector
{};

// Storage used by PImpl.
// Will replace itself with generated code like:
// pimpl::FastPimpl<FooImpl, /*Size*/ 64, /*Alignment*/ 12> impl_;
/// \note sizePadding adds extra bytes
/// to aligned_storage used by fast PImpl
template<
  typename impl = FooImpl
>
class
  _injectPimplStorage(
    "sizePadding = 8"
  )
PimplStorageInjector
{};

/// \note you must reflect PImpl implementation
/// before using it by code generator.
template<typename impl = FooImpl>
class _reflectForPimpl()
  PimplReflector
{};

How to skip injection of some methods from implementation

You can annotate methods with "skip_pimpl":

#define _skipForPimpl() \
  __attribute__((annotate("skip_pimpl")))

Code generator processes flextool_input_files from tests/CMakeLists.txt

Before installation

Installation

export CXX=clang++-10
export CC=clang-10

export VERBOSE=1
export CONAN_REVISIONS_ENABLED=1
export CONAN_VERBOSE_TRACEBACK=1
export CONAN_PRINT_RUN_COMMANDS=1
export CONAN_LOGGING_LEVEL=10
export GIT_SSL_NO_VERIFY=true

# NOTE: change `build_type=Debug` to `build_type=Release` in production
# NOTE: use --build=missing if you got error `ERROR: Missing prebuilt package`
cmake -E time \
  conan create . conan/stable \
  -s build_type=Debug -s cling_conan:build_type=Release \
  --profile clang \
      -o flex_pimpl_plugin:enable_clang_from_conan=False \
      -e flex_pimpl_plugin:enable_tests=True

# clean build cache
conan remove "*" --build --force

CMake and conan integration

Example code can be found in flex_pimpl_plugin/tests directory.

Development flow (for contributors)

Commands below may be used to build project locally, without system-wide installation.

export CXX=clang++-10
export CC=clang-10

cmake -E remove_directory build

cmake -E make_directory build

# NOTE: change `build_type=Debug` to `build_type=Release` in production
build_type=Debug

# install conan requirements
cmake -E chdir build cmake -E time \
  conan install \
  -s build_type=${build_type} -s cling_conan:build_type=Release \
  --build=missing \
  --profile clang \
      -e enable_tests=True \
      ..

# optional: remove generated files (change paths to yours)
rm build/*generated*
rm build/generated/ -rf
rm build/bin/${build_type}/ -rf

# configure via cmake
cmake -E chdir build \
  cmake -E time cmake .. \
  -DENABLE_TESTS=TRUE \
  -DCONAN_AUTO_INSTALL=OFF \
  -DCMAKE_BUILD_TYPE=${build_type}

# build code
cmake -E chdir build \
  cmake -E time cmake --build . \
  --config ${build_type} \
  -- -j8

# run unit tests
cmake -E chdir build \
  cmake -E time cmake --build . \
  --config ${build_type} \
  --target flex_pimpl_plugin_run_all_tests

For contibutors: conan editable mode

With the editable packages, you can tell Conan where to find the headers and the artifacts ready for consumption in your local working directory. There is no need to run conan create or conan export-pkg.

See for details https://docs.conan.io/en/latest/developing_packages/editable_packages.html

Build locally:

export VERBOSE=1
export CONAN_REVISIONS_ENABLED=1
export CONAN_VERBOSE_TRACEBACK=1
export CONAN_PRINT_RUN_COMMANDS=1
export CONAN_LOGGING_LEVEL=10
export GIT_SSL_NO_VERIFY=true

cmake -E time \
  conan install . \
  --install-folder local_build \
  -s build_type=Debug -s cling_conan:build_type=Release \
  --profile clang \
    -o flex_pimpl_plugin:enable_clang_from_conan=False \
    -e flex_pimpl_plugin:enable_tests=True

cmake -E time \
  conan source . \
  --source-folder local_build \
  --install-folder local_build

conan build . \
  --build-folder local_build

conan package . \
  --build-folder local_build \
  --package-folder local_build/package_dir \
  --source-folder local_build \
  --install-folder local_build

Set package to editable mode:

conan editable add local_build/package_dir \
  flex_pimpl_plugin/master@conan/stable

Note that conanfile.py modified to detect local builds via self.in_local_cache

After change source in folder local_build (run commands in source package folder):

conan build . \
  --build-folder local_build

conan package . \
  --build-folder local_build \
  --package-folder local_build/package_dir \
  --source-folder local_build \
  --install-folder local_build

Build your test project

In order to revert the editable mode just remove the link using:

conan editable remove \
  flex_pimpl_plugin/master@conan/stable

Similar projects

flex_pimpl_plugin's People

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.