Skip to content

Commit

Permalink
some information about alternative build systems
Browse files Browse the repository at this point in the history
  • Loading branch information
wjakob committed Mar 18, 2024
1 parent 4148deb commit dce91b4
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
13 changes: 13 additions & 0 deletions docs/api_cmake.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ modules. This is needed because quite a few steps are involved: nanobind must
build the module, a library component, link the two together, and add a
different set of compilation and linker flags depending on the target platform.

If you prefer another build system, then you have the following options:

- `Nicholas Junge <https://github.com/nicholasjng>`__ has created a `Bazel
interface <https://github.com/nicholasjng/nanobind-Bazel>`__ to nanobind.
Please report Bazel-specific issues there.

- You could create a new build system from scratch that takes care of these
steps. See `this file
<https://github.com/wjakob/nanobind/blob/master/src/nb_combined.cpp>`__ for
inspiration on how to do this on Linux. Note that you will be on your own if
you choose to go this route---I unfortunately do not have the time to respond
to GitHub tickets related to custom build systems.

The section on :ref:`building extensions <building>` provided an introductory
example of how to set up a basic build system via the
:cmake:command:`nanobind_add_module` command, which is the :ref:`high level
Expand Down
2 changes: 2 additions & 0 deletions docs/building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ This section assumes that you have followed the instructions to :ref:`install
<installing>` nanobind. The easiest way to compile a nanobind-based extension
involves a CMake-based build system. Other build systems can likely be used as
well, but they are not officially supported.
(The first section of the :ref:`CMake API reference <api_cmake>` mentions
some alternatives.)

Here, we will create a new package from scratch. If you already have an
existing CMake build system, it should be straightforward to merge some of the
Expand Down
71 changes: 71 additions & 0 deletions src/nb_combined.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* You can use this file to compile bindings using alternative build systems in
case the dependence on CMake is problematic. The following instructions
illustrate how to do this Linux. The commands will need to be updated to
target other operating systems, but that is beyond the scope of this writeup.
To investigate platform-dependent subtleties, read the CMake build system
or run it and examine the commands it generates.
Step 1: compile libnanobind
$ NB_DIR=<path to nanobind directory>
$ CXXFLAGS="-std=c++17 -fvisibility=hidden \
-DNDEBUG -DNB_COMPACT_ASSERTIONS \
`python3-config --includes` -fPIC \
-I $NB_DIR/include \
-I $NB_DIR/ext/robin_map/include"
$ g++ src/nb_combined.cpp $CXXFLAGS -O3 -fno-strict-aliasing \
-ffunction-sections -fdata-sections -c -o libnanobind.o
Step 2: compile the extension code
$ g++ my_ext.cpp $CXXFLAGS -Os -c -o my_ext.o
Step 3: link the extension code with libnanobind
$ g++ -shared -Wl,-s -Wl,--gc-sections my_ext.o libnanobind.o \
-o my_ext.cpython-310-x86_64-linux-gnu.so
A few comments about these compilation parameters:
- the '-ffunction-sections/-fdata-sections/--gc-sections' parameter ensure
that unused parts of libnanobind are removed from the compiled extension.
- the '-fno-strict-aliasing' part is needed by the libnanobind part. This
flag generally applies to code that uses significant amounts of 'raw'
CPython API code. You should ensure that libnanobind isn't merged with
other code via link time optimization (LTO), otherwise you may need to
specify '-fno-strict-aliasing' at the project level.
- The '-Wl,-s' parameter strips debug information from the generated shared
library. Similarly, '-DNDEBUG' and '-DNB_COMPACT_ASSERTIONS' are parameters
that improve performance and reduce binary size in release builds, but
which would be omitted in debug builds.
- here, the libnanobind part uses -O3 (optimization for highest peformance),
while the bindings use -Os (optimization for the smallest size). The
assumption here is that the code in 'my_ext.cpp' is glue code that isn't
performance sensitive but which can become very big in a size-optimized
build. I generally this to be a good default, but you may have other
preferences. If in doubt, benchmark to see what works best.
- The suffix of the final shared library depends on the Python version and
platform. You can ask a specific Python build about the right extension via
"import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"
- Some of the above details change if you want to create a limited API /
stable ABI build, which is possible starting with Python 3.12. See the
CMake build system for reference.
*/

#include "nb_internals.cpp"
#include "nb_func.cpp"
#include "nb_type.cpp"
#include "nb_enum.cpp"
#include "nb_ndarray.cpp"
#include "nb_static_property.cpp"
#include "error.cpp"
#include "common.cpp"
#include "implicit.cpp"
#include "trampoline.cpp"

0 comments on commit dce91b4

Please sign in to comment.