Skip to content

Commit 0faa99e

Browse files
committed
CMake: Expose Python LTO Control
Before, LTO/IPO was default-enabled for the Python bindings. This can sometimes, e.g. on PPC64le with GCC 6.4.0 on Summit, cause problems in complex enough scenarios and fail to link. We now expose control via the standardized CMake variable `CMAKE_INTERPROCEDURAL_OPTIMIZATION`. This variable populates the `INTERPROCEDURAL_OPTIMIZATION` property of targets but only works really reliably with CMake 3.18+. We keep the default logic to use LTO, use the `pybind11::lto` target for older CMake but let the user deactivate the Python LTO by setting the `CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable to false.
1 parent 5c6480a commit 0faa99e

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Other
2525

2626
- ADIOS2: require version 2.7.0+ #927
2727
- pybind11: require version 2.6.2+ #977
28+
- CMake: Expose Python LTO Control #980
2829

2930

3031
0.13.4

CMakeLists.txt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,24 @@ if(openPMD_HAVE_PYTHON)
606606
src/binding/python/UnitDimension.cpp
607607
)
608608
target_link_libraries(openPMD.py PRIVATE openPMD)
609-
target_link_libraries(openPMD.py PRIVATE pybind11::module pybind11::lto pybind11::windows_extras)
609+
target_link_libraries(openPMD.py PRIVATE pybind11::module pybind11::windows_extras)
610+
611+
# LTO/IPO: CMake target properties work well for 3.18+ and are buggy before
612+
set(_USE_PY_LTO ON) # default shall be ON
613+
if(DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION) # overwrite default if defined
614+
if(NOT CMAKE_INTERPROCEDURAL_OPTIMIZATION)
615+
set(_USE_PY_LTO OFF)
616+
endif()
617+
endif()
618+
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
619+
set_target_properties(openPMD.py PROPERTIES
620+
INTERPROCEDURAL_OPTIMIZATION ${_USE_PY_LTO})
621+
else()
622+
if(_USE_PY_LTO)
623+
target_link_libraries(openPMD.py PRIVATE pybind11::lto)
624+
endif()
625+
endif()
626+
unset(_USE_PY_LTO)
610627

611628
pybind11_extension(openPMD.py)
612629
pybind11_strip(openPMD.py)

setup.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ def build_extension(self, ext):
6969
# Windows: has no RPath concept, all `.dll`s must be in %PATH%
7070
# or same dir as calling executable
7171
]
72+
if CMAKE_INTERPROCEDURAL_OPTIMIZATION is not None:
73+
cmake_args.append('-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=' +
74+
CMAKE_INTERPROCEDURAL_OPTIMIZATION)
7275
if sys.platform == "darwin":
7376
cmake_args.append('-DCMAKE_INSTALL_RPATH=@loader_path')
7477
else:
@@ -133,6 +136,8 @@ def build_extension(self, ext):
133136
BUILD_TESTING)
134137
BUILD_EXAMPLES = os.environ.get('openPMD_BUILD_EXAMPLES',
135138
BUILD_EXAMPLES)
139+
CMAKE_INTERPROCEDURAL_OPTIMIZATION = os.environ.get(
140+
'CMAKE_INTERPROCEDURAL_OPTIMIZATION', None)
136141

137142
# https://cmake.org/cmake/help/v3.0/command/if.html
138143
if openPMD_USE_MPI.upper() in ['1', 'ON', 'TRUE', 'YES']:

0 commit comments

Comments
 (0)