cmake.rst 6.64 KB
Newer Older
Wenzel Jakob's avatar
Wenzel Jakob committed
1
2
3
4
5
6
7
8
9
10
11
12
13
Build systems
#############

Building with setuptools
========================

For projects on PyPI, building with setuptools is the way to go. Sylvain Corlay
has kindly provided an example project which shows how to set up everything,
including automatic generation of documentation using Sphinx. Please refer to
the [pbtest]_ repository.

.. [pbtest] https://github.com/pybind/pbtest

14
15
16
17
18
.. _cmake:

Building with CMake
===================

Wenzel Jakob's avatar
Wenzel Jakob committed
19
20
21
22
23
For C++ codebases that already have an existing CMake-based build system, the
following snippet should be a good starting point to create bindings across
platforms. It assumes that the code is located in a file named
:file:`example.cpp`, and that the pybind11 repository is located in a
subdirectory named :file:`pybind11`.
24
25
26
27
28
29
30
31

.. code-block:: cmake

    cmake_minimum_required(VERSION 2.8)

    project(example)

    # Add a CMake parameter for choosing a desired Python version
Wenzel Jakob's avatar
Wenzel Jakob committed
32
33
34
    set(EXAMPLE_PYTHON_VERSION "" CACHE STRING
        "Python version to use for compiling the example library")

Ivan Smirnov's avatar
Ivan Smirnov committed
35
    include(CheckCXXCompilerFlag)
36

Wenzel Jakob's avatar
Wenzel Jakob committed
37
38
    # Set a default build configuration if none is specified.
    # 'MinSizeRel' produces the smallest binaries
39
40
41
42
43
44
45
46
47
    if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
      message(STATUS "Setting build type to 'MinSizeRel' as none was specified.")
      set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build." FORCE)
      set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
        "MinSizeRel" "RelWithDebInfo")
    endif()
    string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE)

    # Try to autodetect Python (can be overridden manually if needed)
48
    set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6 3.7)
Wenzel Jakob's avatar
Wenzel Jakob committed
49
50
    if (NOT ${EXAMPLE_PYTHON_VERSION} STREQUAL "")
      find_package(PythonLibs ${EXAMPLE_PYTHON_VERSION} EXACT)
Wenzel Jakob's avatar
Wenzel Jakob committed
51
      if (NOT PythonLibs_FOUND)
Wenzel Jakob's avatar
Wenzel Jakob committed
52
        find_package(PythonLibs ${EXAMPLE_PYTHON_VERSION} REQUIRED)
Wenzel Jakob's avatar
Wenzel Jakob committed
53
      endif()
54
55
56
57
    else()
      find_package(PythonLibs REQUIRED)
    endif()

Wenzel Jakob's avatar
Wenzel Jakob committed
58
59
    # The above sometimes returns version numbers like "3.4.3+";
    # the "+" must be removed for the next lines to work
60
61
    string(REPLACE "+" "" PYTHONLIBS_VERSION_STRING "+${PYTHONLIBS_VERSION_STRING}")

62
63
    # Uncomment the following line if you will also require a matching Python interpreter
    # find_package(PythonInterp ${PYTHONLIBS_VERSION_STRING} EXACT REQUIRED)
64

65
    if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
66
67
68
69
70
71
72
73
74
75
      CHECK_CXX_COMPILER_FLAG("-std=c++14" HAS_CPP14_FLAG)
      CHECK_CXX_COMPILER_FLAG("-std=c++11" HAS_CPP11_FLAG)

      if (HAS_CPP14_FLAG)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
      elseif (HAS_CPP11_FLAG)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
      else()
        message(FATAL_ERROR "Unsupported compiler -- at least C++11 support is needed!")
      endif()
76
77
78
79

      # Enable link time optimization and set the default symbol
      # visibility to hidden (very important to obtain small binaries)
      if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
80
81
82
83
84
85
86
87
        # Default symbol visibility
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")

        # Check for Link Time Optimization support
        CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
        if (HAS_LTO_FLAG)
          set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
        endif()
88
89
90
91
92
93
      endif()
    endif()

    # Include path for Python header files
    include_directories(${PYTHON_INCLUDE_DIR})

Wenzel Jakob's avatar
Wenzel Jakob committed
94
95
    # Include path for pybind11 header files -- this may need to be
    # changed depending on your setup
96
97
98
99
100
101
102
103
104
105
106
107
108
    include_directories(${PROJECT_SOURCE_DIR}/pybind11/include)

    # Create the binding library
    add_library(example SHARED
      example.cpp
      # ... extra files go here ...
    )

    # Don't add a 'lib' prefix to the shared library
    set_target_properties(example PROPERTIES PREFIX "")

    if (WIN32)
      if (MSVC)
109
110
111
112
113
114
115
116
117
118
119
120
121
        # /MP enables multithreaded builds (relevant when there are many files), /bigobj is
        # needed for bigger binding projects due to the limit to 64k addressable sections
        set_property(TARGET example APPEND PROPERTY COMPILE_OPTIONS /MP /bigobj)
        # Enforce size-based optimization and link time code generation on MSVC
        # (~30% smaller binaries in experiments); do nothing in debug mode.
        set_property(TARGET example APPEND PROPERTY COMPILE_OPTIONS
          "$<$<CONFIG:Release>:/Os>" "$<$<CONFIG:Release>:/GL>"
          "$<$<CONFIG:MinSizeRel>:/Os>" "$<$<CONFIG:MinSizeRel>:/GL>"
          "$<$<CONFIG:RelWithDebInfo>:/Os>" "$<$<CONFIG:RelWithDebInfo>:/GL>"
        )
        set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_RELEASE "/LTCG ")
        set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL "/LTCG ")
        set_property(TARGET example APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO "/LTCG ")
122
123
124
125
126
127
128
129
130
131
132
133
134
      endif()

      # .PYD file extension on Windows
      set_target_properties(example PROPERTIES SUFFIX ".pyd")

      # Link against the Python shared library
      target_link_libraries(example ${PYTHON_LIBRARY})
    elseif (UNIX)
      # It's quite common to have multiple copies of the same Python version
      # installed on one's system. E.g.: one copy from the OS and another copy
      # that's statically linked into an application like Blender or Maya.
      # If we link our plugin library against the OS Python here and import it
      # into Blender or Maya later on, this will cause segfaults when multiple
135
136
      # conflicting Python instances are active at the same time (even when they
      # are of the same version).
137

Wenzel Jakob's avatar
Wenzel Jakob committed
138
      # Windows is not affected by this issue since it handles DLL imports
139
140
141
142
143
144
145
146
147
148
149
      # differently. The solution for Linux and Mac OS is simple: we just don't
      # link against the Python library. The resulting shared library will have
      # missing symbols, but that's perfectly fine -- they will be resolved at
      # import time.

      # .SO file extension on Linux/Mac OS
      set_target_properties(example PROPERTIES SUFFIX ".so")

      # Strip unnecessary sections of the binary on Linux/Mac OS
      if(APPLE)
        set_target_properties(example PROPERTIES MACOSX_RPATH ".")
Wenzel Jakob's avatar
Wenzel Jakob committed
150
        set_target_properties(example PROPERTIES LINK_FLAGS "-undefined dynamic_lookup ")
151
        if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
Wenzel Jakob's avatar
Wenzel Jakob committed
152
153
          add_custom_command(TARGET example POST_BUILD
                             COMMAND strip -u -r ${PROJECT_BINARY_DIR}/example.so)
154
155
156
        endif()
      else()
        if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
Wenzel Jakob's avatar
Wenzel Jakob committed
157
158
          add_custom_command(TARGET example POST_BUILD
                             COMMAND strip ${PROJECT_BINARY_DIR}/example.so)
159
160
161
        endif()
      endif()
    endif()