pybind11_add_module(): OPT_SIZE target

This commit is contained in:
Wenzel Jakob 2020-09-04 23:31:05 +02:00
parent 3bd0d7a8d5
commit 36c666f027
5 changed files with 53 additions and 6 deletions

View File

@ -11,6 +11,12 @@ v2.6.0 (IN PROGRESS)
See :ref:`upgrade-guide-2.6` for help upgrading to the new version. See :ref:`upgrade-guide-2.6` for help upgrading to the new version.
* ``pybind11_add_module()`` now accepts an optional ``OPT_SIZE`` flag that
switches the binding target to size-based optimization regardless global
CMake build type (except in debug mode, where optimizations remain disabled).
This reduces binary size quite substantially (~25%).
`#2463 <https://github.com/pybind/pybind11/pull/2463>`_
* Keyword-only argument supported in Python 2 or 3 with ``py::kw_only()``. * Keyword-only argument supported in Python 2 or 3 with ``py::kw_only()``.
`#2100 <https://github.com/pybind/pybind11/pull/2100>`_ `#2100 <https://github.com/pybind/pybind11/pull/2100>`_

View File

@ -62,7 +62,7 @@ function with the following signature:
.. code-block:: cmake .. code-block:: cmake
pybind11_add_module(<name> [MODULE | SHARED] [EXCLUDE_FROM_ALL] pybind11_add_module(<name> [MODULE | SHARED] [EXCLUDE_FROM_ALL]
[NO_EXTRAS] [THIN_LTO] source1 [source2 ...]) [NO_EXTRAS] [THIN_LTO] [OPT_SIZE] source1 [source2 ...])
This function behaves very much like CMake's builtin ``add_library`` (in fact, 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 it's a wrapper function around that command). It will add a library target
@ -96,6 +96,19 @@ regular LTO if ``-flto=thin`` is not available. If
``CMAKE_INTERPROCEDURAL_OPTIMIZATION`` is set (either ON or OFF), then that ``CMAKE_INTERPROCEDURAL_OPTIMIZATION`` is set (either ON or OFF), then that
will be respected instead of the built-in flag search. will be respected instead of the built-in flag search.
The ``OPT_SIZE`` flag enables size-based optimization equivalent to the
standard ``/Os`` or ``-Os`` compiler flags and the ``MinSizeRel`` build type,
which avoid optimizations that that can substantially increase the size of the
resulting binary. This flag is particularly useful in projects that are split
into performance-critical parts and associated bindings. In this case, we can
compile the project in release mode (and hence, optimize performance globally),
and specify ``OPT_SIZE`` for the binding target, where size might be the main
concern as performance is often less critical here. A ~25% size reduction has
been observed in practice. This flag only changes the optimization behavior at
a per-target level and takes precedence over the global CMake build type
(``Release``, ``RelWithDebInfo``) except for ``Debug`` builds, where
optimizations remain disabled.
.. _ThinLTO: http://clang.llvm.org/docs/ThinLTO.html .. _ThinLTO: http://clang.llvm.org/docs/ThinLTO.html
Configuration variables Configuration variables
@ -245,6 +258,9 @@ available in all modes. The targets provided are:
``pybind11::windows_extras`` ``pybind11::windows_extras``
``/bigobj`` and ``/mp`` for MSVC. ``/bigobj`` and ``/mp`` for MSVC.
``pybind11::opt_size``
``/Os`` for MSVC, ``-Os`` for other compilers. Does nothing for debug builds.
Two helper functions are also provided: Two helper functions are also provided:
``pybind11_strip(target)`` ``pybind11_strip(target)``

View File

@ -10,6 +10,7 @@ Adds the following targets::
pybind11::python_link_helper - Adds link to Python libraries pybind11::python_link_helper - Adds link to Python libraries
pybind11::python2_no_register - Avoid warning/error with Python 2 + C++14/7 pybind11::python2_no_register - Avoid warning/error with Python 2 + C++14/7
pybind11::windows_extras - MSVC bigobj and mp for building multithreaded pybind11::windows_extras - MSVC bigobj and mp for building multithreaded
pybind11::opt_size - avoid optimizations that increase code size
Adds the following functions:: Adds the following functions::
@ -133,6 +134,23 @@ if(MSVC)
endif() endif()
endif() endif()
# ----------------------- Optimize binary size --------------------------
add_library(pybind11::opt_size IMPORTED INTERFACE ${optional_global})
if(MSVC)
set(PYBIND11_OPT_SIZE /Os)
else()
set(PYBIND11_OPT_SIZE -Os)
endif()
set_property(
TARGET pybind11::opt_size
APPEND
PROPERTY INTERFACE_COMPILE_OPTIONS $<$<CONFIG:Release>:${PYBIND11_OPT_SIZE}>
$<$<CONFIG:MinSizeRel>:${PYBIND11_OPT_SIZE}>
$<$<CONFIG:RelWithDebInfo>:${PYBIND11_OPT_SIZE}>)
# ----------------------- Legacy option -------------------------- # ----------------------- Legacy option --------------------------
# Warn or error if old variable name used # Warn or error if old variable name used

View File

@ -138,8 +138,8 @@ endif()
# WITHOUT_SOABI and WITH_SOABI will disable the custom extension handling used by pybind11. # WITHOUT_SOABI and WITH_SOABI will disable the custom extension handling used by pybind11.
# WITH_SOABI is passed on to python_add_library. # WITH_SOABI is passed on to python_add_library.
function(pybind11_add_module target_name) function(pybind11_add_module target_name)
cmake_parse_arguments(PARSE_ARGV 1 ARG "STATIC;SHARED;MODULE;THIN_LTO;NO_EXTRAS;WITHOUT_SOABI" cmake_parse_arguments(PARSE_ARGV 1 ARG
"" "") "STATIC;SHARED;MODULE;THIN_LTO;OPT_SIZE;NO_EXTRAS;WITHOUT_SOABI" "" "")
if(ARG_ADD_LIBRARY_STATIC) if(ARG_ADD_LIBRARY_STATIC)
set(type STATIC) set(type STATIC)
@ -204,6 +204,10 @@ function(pybind11_add_module target_name)
if(MSVC) if(MSVC)
target_link_libraries(${target_name} PRIVATE pybind11::windows_extras) target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
endif() endif()
if(ARG_OPT_SIZE)
target_link_libraries(${target_name} PRIVATE pybind11::opt_size)
endif()
endfunction() endfunction()
function(pybind11_extension name) function(pybind11_extension name)

View File

@ -1,6 +1,6 @@
# tools/pybind11Tools.cmake -- Build system for the pybind11 modules # tools/pybind11Tools.cmake -- Build system for the pybind11 modules
# #
# Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch> # Copyright (c) 2020 Wenzel Jakob <wenzel.jakob@epfl.ch>
# #
# All rights reserved. Use of this source code is governed by a # All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file. # BSD-style license that can be found in the LICENSE file.
@ -124,10 +124,10 @@ endfunction()
# Build a Python extension module: # Build a Python extension module:
# pybind11_add_module(<name> [MODULE | SHARED] [EXCLUDE_FROM_ALL] # pybind11_add_module(<name> [MODULE | SHARED] [EXCLUDE_FROM_ALL]
# [NO_EXTRAS] [THIN_LTO] source1 [source2 ...]) # [NO_EXTRAS] [THIN_LTO] [OPT_SIZE] source1 [source2 ...])
# #
function(pybind11_add_module target_name) function(pybind11_add_module target_name)
set(options MODULE SHARED EXCLUDE_FROM_ALL NO_EXTRAS SYSTEM THIN_LTO) set(options "MODULE;SHARED;EXCLUDE_FROM_ALL;NO_EXTRAS;SYSTEM;THIN_LTO;OPT_SIZE")
cmake_parse_arguments(ARG "${options}" "" "" ${ARGN}) cmake_parse_arguments(ARG "${options}" "" "" ${ARGN})
if(ARG_MODULE AND ARG_SHARED) if(ARG_MODULE AND ARG_SHARED)
@ -185,4 +185,7 @@ function(pybind11_add_module target_name)
target_link_libraries(${target_name} PRIVATE pybind11::windows_extras) target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
endif() endif()
if(ARG_OPT_SIZE)
target_link_libraries(${target_name} PRIVATE pybind11::opt_size)
endif()
endfunction() endfunction()