Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul Python structure, better support Python 2+3 builds #404

Merged
merged 1 commit into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 145 additions & 79 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

13 changes: 0 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,8 @@ add_subdirectory(docs)
########################################################################
# Python support (optional)
########################################################################
message(STATUS "")
message(STATUS "#############################################")
message(STATUS "## Begin configuration for Python support...")
message(STATUS "#############################################")
message(STATUS "Enabling optional Python bindings if possible...")
add_subdirectory(python)

message(STATUS "")
message(STATUS "#############################################")
message(STATUS "## Begin configuration for Python3 support...")
message(STATUS "#############################################")
message(STATUS "Enabling optional Python3 bindings if possible...")
add_subdirectory(python3)


########################################################################
# uninstall target
########################################################################
Expand Down
225 changes: 92 additions & 133 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
########################################################################
# Project setup
########################################################################
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.3)
project(SoapySDRPython CXX)
enable_testing()

Expand All @@ -14,81 +14,14 @@ find_package(SWIG)
message(STATUS "SWIG_FOUND: ${SWIG_FOUND} - ${SWIG_VERSION}")

########################################################################
# Find python interp
# Find Python
########################################################################
find_package(PythonInterp)
message(STATUS "PYTHONINTERP_FOUND: ${PYTHONINTERP_FOUND} - ${PYTHON_VERSION_STRING}")
message(STATUS "PYTHON_EXECUTABLE: ${PYTHON_EXECUTABLE}")

#help find_package(PythonLibs) by setting Python_ADDITIONAL_VERSIONS from PYTHON_VERSION_STRING
if(PYTHONINTERP_FOUND AND DEFINED PYTHON_VERSION_STRING AND NOT DEFINED Python_ADDITIONAL_VERSIONS)
string(SUBSTRING "${PYTHON_VERSION_STRING}" 0 3 Python_ADDITIONAL_VERSIONS)
endif()

########################################################################
# Determine install directory
########################################################################
execute_process(
COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/get_python_lib.py" "${CMAKE_INSTALL_PREFIX}"
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE PYTHON_INSTALL_DIR_SYSCONF
)
set(PYTHON_INSTALL_DIR "${PYTHON_INSTALL_DIR_SYSCONF}" CACHE STRING "python install prefix")
message(STATUS "PYTHON_INSTALL_DIR: \${prefix}/${PYTHON_INSTALL_DIR}")

########################################################################
# Find Python libs
########################################################################
option(USE_PYTHON_CONFIG "use python-config to locate development files" TRUE)
set(PYTHON_CONFIG_EXECUTABLE ${PYTHON_EXECUTABLE}-config
CACHE FILEPATH "Path to python-config executable")
if (USE_PYTHON_CONFIG AND EXISTS ${PYTHON_CONFIG_EXECUTABLE})
execute_process(
COMMAND ${PYTHON_CONFIG_EXECUTABLE} --includes
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE PYTHON_INCLUDE_DIRS)
string(REGEX REPLACE "^[-I]" "" PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS}")
string(REGEX REPLACE "[ ]-I" " " PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS}")
separate_arguments(PYTHON_INCLUDE_DIRS)
execute_process(
COMMAND ${PYTHON_CONFIG_EXECUTABLE} --ldflags
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE PYTHON_LIBRARIES)
string(STRIP "${PYTHON_LIBRARIES}" PYTHON_LIBRARIES)
set(PYTHONLIBS_VERSION_STRING ${PYTHON_VERSION_STRING})
set(PYTHONLIBS_FOUND TRUE)
else()
find_package(PythonLibs)
endif()

message(STATUS "PYTHONLIBS_FOUND: ${PYTHONLIBS_FOUND} - ${PYTHONLIBS_VERSION_STRING}")
message(STATUS "PYTHON_INCLUDE_DIRS: ${PYTHON_INCLUDE_DIRS}")
message(STATUS "PYTHON_LIBRARIES: ${PYTHON_LIBRARIES}")

#on windows, we require a pythonxx_d.lib in debug mode
#require that the PYTHON_DEBUG_LIBRARY flag is set
#or the build assumes that the debug library DNE
set(PYTHON_DEBUG_OK TRUE)
if(WIN32 AND NOT PYTHON_DEBUG_LIBRARY AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
message(WARNING "WIN32 Debug mode requires PYTHON_DEBUG_LIBRARY")
set(PYTHON_DEBUG_OK FALSE)
endif()

########################################################################
# Python version check
########################################################################
set(PYTHON_VERSION_MATCH TRUE)
if (PYTHON_VERSION_STRING AND PYTHONLIBS_VERSION_STRING)
if(NOT "${PYTHON_VERSION_STRING}" VERSION_EQUAL "${PYTHONLIBS_VERSION_STRING}")
message(WARNING "Python interp and library version mismatch")
set(PYTHON_VERSION_MATCH FALSE)
endif()
endif()
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

########################################################################
## set the swig flags - shared with python3 build
## set the swig flags
########################################################################
set(CMAKE_SWIG_FLAGS -c++ -threads -I${SoapySDR_INCLUDE_DIRS})
set(CMAKE_SWIG_FLAGS -threads -I${SoapySDR_INCLUDE_DIRS})

#check for size_t issue on arm 32-bit platforms
include(CheckCXXSourceCompiles)
Expand All @@ -102,80 +35,106 @@ if (SIZE_T_IS_UNSIGNED_INT)
list(APPEND CMAKE_SWIG_FLAGS -DSIZE_T_IS_UNSIGNED_INT)
endif (SIZE_T_IS_UNSIGNED_INT)

########################################################################
## Export variables for python3 subdirectory
########################################################################

#this directory used as a stand-alone build since the library is pulled in externally
#set ENABLE_LIBRARY for cmake_dependent_option() used in the feature setup below
if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
set(ENABLE_LIBRARY ${SoapySDR_FOUND})

#otherwise export enable and swig variables used in the python3 directory
else ()

#set once we know that executable and libs are found and match
#this tells the parent scope to build python3 when this is python2
if(PYTHON_VERSION_STRING AND "${PYTHON_VERSION_STRING}" VERSION_LESS "3.0")
set(BUILD_PYTHON3 TRUE PARENT_SCOPE)
endif()

#or enable search for python3 when this directory failed to find
#a full set of python interpreter and devel files of any version
if(NOT PYTHONINTERP_FOUND OR NOT PYTHONLIBS_FOUND)
set(BUILD_PYTHON3 TRUE PARENT_SCOPE)
endif()

set(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} PARENT_SCOPE)

endif ()

########################################################################
## Feature registration
########################################################################
include(FeatureSummary)
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_PYTHON "Enable python bindings" ON "ENABLE_LIBRARY;SWIG_FOUND;PYTHONINTERP_FOUND;PYTHONLIBS_FOUND;PYTHON_DEBUG_OK;PYTHON_VERSION_MATCH" OFF)
add_feature_info(Python ENABLE_PYTHON "python bindings v${PYTHON_VERSION_STRING}")
if (NOT ENABLE_PYTHON)
return()

# Note: for build script compatibility, still use ENABLE_PYTHON for Python 2
message(STATUS "")
message(STATUS "#############################################")
message(STATUS "## Begin configuration for Python 2 support...")
message(STATUS "#############################################")
message(STATUS "Enabling optional Python 2 bindings if possible...")
find_package(Python2 COMPONENTS Interpreter Development)
if(${Python2_FOUND})
message(STATUS " * Interpreter: ${Python2_EXECUTABLE} (${Python2_INTERPRETER_ID})")
message(STATUS " * Include: ${Python2_INCLUDE_DIRS}")
message(STATUS " * Library: ${Python2_LIBRARIES}")
endif()
cmake_dependent_option(ENABLE_PYTHON "Enable Python2 bindings" ON "ENABLE_LIBRARY;SWIG_FOUND;Python2_FOUND" OFF)
add_feature_info(Python2 ENABLE_PYTHON "Python2 bindings v${Python2_VERSION}")

message(STATUS "")
message(STATUS "#############################################")
message(STATUS "## Begin configuration for Python 3 support...")
message(STATUS "#############################################")
message(STATUS "Enabling optional Python 3 bindings if possible...")
find_package(Python3 COMPONENTS Interpreter Development)
if(${Python3_FOUND})
message(STATUS " * Interpreter: ${Python3_EXECUTABLE} (${Python3_INTERPRETER_ID})")
message(STATUS " * Include: ${Python3_INCLUDE_DIRS}")
message(STATUS " * Library: ${Python3_LIBRARIES}")
endif()
cmake_dependent_option(ENABLE_PYTHON3 "Enable Python3 bindings" ON "ENABLE_LIBRARY;SWIG_FOUND;Python3_FOUND" OFF)
add_feature_info(Python3 ENABLE_PYTHON3 "Python3 bindings v${Python3_VERSION}")

########################################################################
# Build Module
# Build and install module
########################################################################
include(UseSWIG)
set(SOAPYSDR_PYTHON_DIR ${CMAKE_CURRENT_SOURCE_DIR})

configure_file(
SoapySDR.in.i
${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.i
@ONLY)
function(BUILD_PYTHON_MODULE PYTHON_VERSION)
configure_file(
${SOAPYSDR_PYTHON_DIR}/SoapySDR.in.i
${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.i
@ONLY)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.i PROPERTIES CPLUSPLUS ON)

message(STATUS "CMAKE_SWIG_FLAGS=${CMAKE_SWIG_FLAGS}")
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.i PROPERTIES CPLUSPLUS ON)
if(MINGW)
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -static-libgcc -static-libstdc++")
endif()

if(${CMAKE_VERSION} VERSION_LESS "3.8")
SWIG_ADD_MODULE(SoapySDR python ${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.i)
else()
SWIG_ADD_LIBRARY(SoapySDR LANGUAGE python SOURCES ${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.i)
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.8")
SWIG_ADD_MODULE(SoapySDR${PYTHON_VERSION} python ${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.i)
else()
SWIG_ADD_LIBRARY(SoapySDR${PYTHON_VERSION} LANGUAGE python SOURCES ${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.i)
endif()

if(APPLE)
list(APPEND PYTHON_LIBRARIES "-undefined dynamic_lookup")
endif()
set(python_includes ${SoapySDR_INCLUDE_DIRS})
set(python_libraries SoapySDR Python${PYTHON_VERSION}::Module)

target_include_directories(${SWIG_MODULE_SoapySDR_REAL_NAME} PRIVATE ${PYTHON_INCLUDE_DIRS})
SWIG_LINK_LIBRARIES(SoapySDR SoapySDR ${PYTHON_LIBRARIES})
set_target_properties(${SWIG_MODULE_SoapySDR${PYTHON_VERSION}_REAL_NAME} PROPERTIES OUTPUT_NAME _SoapySDR)

########################################################################
# Install Module
########################################################################
install(
TARGETS ${SWIG_MODULE_SoapySDR_REAL_NAME}
DESTINATION ${PYTHON_INSTALL_DIR}
)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.py
DESTINATION ${PYTHON_INSTALL_DIR}
)
if(MINGW)
# https://stackoverflow.com/a/50792585
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
target_compile_definitions(${SWIG_MODULE_SoapySDR${PYTHON_VERSION}_REAL_NAME} PRIVATE -DMS_WIN64=1)
else()
target_compile_definitions(${SWIG_MODULE_SoapySDR${PYTHON_VERSION}_REAL_NAME} PRIVATE -DMS_WIN32=1)
endif()
endif()

target_include_directories(${SWIG_MODULE_SoapySDR${PYTHON_VERSION}_REAL_NAME} PRIVATE ${python_includes})
SWIG_LINK_LIBRARIES(SoapySDR${PYTHON_VERSION} ${python_libraries})

execute_process(
COMMAND ${Python${PYTHON_VERSION}_EXECUTABLE} ${SOAPYSDR_PYTHON_DIR}/get_python_lib.py ${CMAKE_INSTALL_PREFIX}
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE PYTHON_INSTALL_DIR)

install(
TARGETS ${SWIG_MODULE_SoapySDR${PYTHON_VERSION}_REAL_NAME}
DESTINATION ${PYTHON_INSTALL_DIR}
)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/SoapySDR.py
DESTINATION ${PYTHON_INSTALL_DIR}
)
endfunction()

# TODO: Windows has full Python installations in different directories, so all Python
# versions install file in the same subpaths. CMake doesn't catch this for some reason,
# so should we error out if both Python versions are detected or prioritize one over the
# other with a warning?

if(ENABLE_PYTHON)
add_subdirectory(python2)
endif()

if(ENABLE_PYTHON3)
add_subdirectory(python3)
endif()
2 changes: 1 addition & 1 deletion python/apps/SimpleSiggen.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def siggen_app(
sdr = SoapySDR.Device(args)
#set clock rate first
if clock_rate is not None:
sdr.setMasterclock_rate(clock_rate)
sdr.setMasterClockRate(clock_rate)

#set sample rate
sdr.setSampleRate(SOAPY_SDR_TX, tx_chan, rate)
Expand Down
Loading
Loading