diff --git a/docs/compiling.rst b/docs/compiling.rst index a6bee86ffe..244a94169b 100644 --- a/docs/compiling.rst +++ b/docs/compiling.rst @@ -348,7 +348,8 @@ function with the following signature: .. code-block:: cmake pybind11_add_module( [MODULE | SHARED] [EXCLUDE_FROM_ALL] - [NO_EXTRAS] [THIN_LTO] [OPT_SIZE] source1 [source2 ...]) + [NO_EXTRAS] [THIN_LTO] [OPT_SIZE] [PRECOMPILE | NO_PRECOMPILE] + source1 [source2 ...]) This function behaves very much like CMake's builtin ``add_library`` (in fact, it's a wrapper function around that command). It will add a library target @@ -404,6 +405,64 @@ optimizations remain disabled. .. _ThinLTO: http://clang.llvm.org/docs/ThinLTO.html +.. _precompile-mode: + +Pre-compiling part of pybind11 +------------------------------ + +pybind11 is header-only by default: every translation unit compiles its own +copy of the non-template implementation. The opt-in *precompiled* mode +compiles that implementation once, into a static library that is built inside +your own project with your own flags, which reduces build time (especially +for projects with many translation units or many modules in one build). + +.. code-block:: cmake + + pybind11_add_module(example PRECOMPILE example.cpp) + +The first ``PRECOMPILE`` target creates the library target +``pybind11::precompiled``; further targets reuse it. Set the CMake variable +``PYBIND11_PRECOMPILE`` to make it the default for all +``pybind11_add_module`` calls; use ``NO_PRECOMPILE`` on a target to opt back +out. For targets you create yourself, call the ``pybind11_precompile()`` +function and link ``pybind11::precompiled`` PRIVATE; the target carries the +required ``PYBIND11_PRECOMPILED`` compile definition PUBLIC, so your sources +are compiled correctly automatically. + +Requirements and caveats: + +* The library and every module linking it must agree on the configuration + macros ``PYBIND11_INTERNALS_VERSION``, ``Py_GIL_DISABLED``, + ``PYBIND11_SIMPLE_GIL_MANAGEMENT``, and + ``PYBIND11_DETAILED_ERROR_MESSAGES`` (the last one defaults on in debug + builds). A mismatch produces one readable undefined symbol at link time + referencing ``pybind11_precompiled_config``. +* The library picks up your directory-level flags and C++ standard when it is + first created, so set those before the first ``PRECOMPILE`` target. +* The library is static and per-build-tree by design; it is never installed + or shared between projects. Each extension module links its own copy, + which preserves pybind11's per-module state exactly as in header-only + mode. +* Not available with ``PYBIND11_NOPYTHON`` (the library needs Python + headers). + +For build systems other than CMake, the same sources ship with the pybind11 +package: compile ``pybind11_combined.cpp`` from the directory reported by +``python -m pybind11 --srcdir`` (also available as +``pybind11.get_source_dir()`` and the ``srcdir`` pkg-config variable) into +your extension and define ``PYBIND11_PRECOMPILED`` for every translation +unit. With setuptools, ``Pybind11Extension(..., precompile=True)`` does this +for you. With Meson: + +.. code-block:: meson + + pybind11_dep = dependency('pybind11') + pybind11_src = pybind11_dep.get_variable('srcdir') + py.extension_module('example', + ['example.cpp', pybind11_src / 'pybind11_combined.cpp'], + cpp_args : ['-DPYBIND11_PRECOMPILED'], + dependencies : [pybind11_dep]) + Configuration variables ----------------------- diff --git a/docs/faq.rst b/docs/faq.rst index 2b89d203f3..e5c14bd4d8 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -79,7 +79,11 @@ and the binding code How can I reduce the build time? ================================ -It's good practice to split binding code over multiple files, as in the +First, consider the opt-in precompiled mode: building the non-template part +of pybind11 once per project instead of once per translation unit is the +cheapest large win. See :ref:`precompile-mode`. + +It's also good practice to split binding code over multiple files, as in the following example: :file:`example.cpp`: diff --git a/tools/pybind11Config.cmake.in b/tools/pybind11Config.cmake.in index abcd43e199..d666e9cc96 100644 --- a/tools/pybind11Config.cmake.in +++ b/tools/pybind11Config.cmake.in @@ -18,6 +18,9 @@ This module sets the following variables in your project: Directories where pybind11 and python headers are located. ``pybind11_INCLUDE_DIR`` Directory where pybind11 headers are located. +``pybind11_SRC_DIR`` + Directory where the library sources for the opt-in precompiled mode are + located (used by ``pybind11_precompile``). ``pybind11_DEFINITIONS`` Definitions necessary to use pybind11, namely USING_pybind11. ``pybind11_LIBRARIES`` @@ -147,6 +150,7 @@ This module defines the following commands to assist with creating Python module pybind11_add_module( [STATIC|SHARED|MODULE] [THIN_LTO] [OPT_SIZE] [NO_EXTRAS] [WITHOUT_SOABI] + [PRECOMPILE|NO_PRECOMPILE] ... ) @@ -162,6 +166,22 @@ default is ``MODULE``. There are several options: Disable the SOABI component (``PYBIND11_FINDPYTHON`` mode only). ``NO_EXTRAS`` Disable all extras, exit immediately after making the module. +``PRECOMPILE`` + Link the target against the ``pybind11::precompiled`` static library + (created on first use); ``NO_PRECOMPILE`` opts a target out when the + ``PYBIND11_PRECOMPILE`` variable enables it globally. + +pybind11_precompile +^^^^^^^^^^^^^^^^^^^ + +.. code-block:: cmake + + pybind11_precompile() + +Create the ``pybind11::precompiled`` static library from the shipped sources +(once per build tree). ``pybind11_add_module(... PRECOMPILE)`` calls this for +you; call it directly to link ``pybind11::precompiled`` into your own +targets. pybind11_strip ^^^^^^^^^^^^^^