Skip to content

Targeting multiple Python versions at once #748

Closed
@thorink

Description

@thorink

Hi guys, I want to build a Python extension for different Python versions (2.7 and 3.5 for the moment) in one CMake run. The goal is to have multiple targets, one for each Python version.

In the main CMakeLists.txt I have the following:

set(bindings_python_version 2.7)
add_subdirectory(pythonbinding pythonbindings27)
set(bindings_python_version 3.5)
add_subdirectory(pythonbinding pythonbindings35)

I include my pythonbindings source directory two times. Inside I unset some cache variables, include pybind11 and add the extension target:

unset(PYTHONINTERP_FOUND CACHE)
unset(PYTHON_EXECUTABLE CACHE)
unset(PYTHON_VERSION_STRING CACHE)
unset(PYTHON_VERSION_MAJOR CACHE)
unset(PYTHON_VERSION_MINOR CACHE)
unset(PYTHON_VERSION_PATCH CACHE)

find_package(PythonInterp ${preonpy_python_version})

unset(PYBIND11_INCLUDE_DIR CACHE)
unset(PYTHON_INCLUDE_DIRS CACHE)
unset(PYTHON_LIBRARIES CACHE)
unset(PYTHON_MODULE_PREFIX CACHE)
unset(PYTHON_MODULE_EXTENSION CACHE)

unset(PYTHON_LIBRARY CACHE)

set(PYBIND11_PYTHON_VERSION ${preonpy_python_version} CACHE STRING "" FORCE)

add_subdirectory(pybind11 ${CMAKE_CURRENT_BINARY_DIR}/pybind11)

set(_target_name "_pyexttarget${bindings_python_version}")

add_library(${_target_name} MODULE main.cpp)
target_include_directories(${_target_name} PRIVATE ${PYBIND11_INCLUDE_DIR})
target_include_directories(${_target_name} PRIVATE ${PYTHON_INCLUDE_DIRS})
set_target_properties(${_target_name} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
                                                 SUFFIX "${PYTHON_MODULE_EXTENSION}"
                                                 OUTPUT_NAME "_pyexttarget")

For this to work I changed some code in the CMakeLists.txt of pybind11:

if (NOT (CMAKE_VERSION VERSION_LESS 3.0))  # CMake >= 3.0
    set(target_name "module${PYBIND11_PYTHON_VERSION}")
    # Build an interface library target:
    add_library(${target_name} INTERFACE)
    target_include_directories(${target_name} INTERFACE $<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}>
            $<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>
            $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
    if (WIN32 OR CYGWIN)
        target_link_libraries(${target_name} INTERFACE $<BUILD_INTERFACE:${PYTHON_LIBRARIES}>)
    elseif (APPLE)
        target_link_libraries(${target_name} INTERFACE "-undefined dynamic_lookup")
    endif ()
    target_compile_options(${target_name} INTERFACE $<BUILD_INTERFACE:${PYBIND11_CPP_STANDARD}>)

    add_library(pybind11::module ALIAS ${target_name})  # to match exported target
endif ()

Instead of creating a target named module I name it module2.7 or module3.5, depending on the targeted Python version.

This allows me to build my extension two times with a single make.

It now works for me, but actually I don't like it very much. I would like to have your opinions on this. Do you know some better ideas to archive the same? Would you like to have support for this use case in pybind11?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions