Menu

Trying to build with cmake, getting "No Module named PythonQt" error when trying to run Python code

Help
2020-12-02
2020-12-03
  • Flower lady

    Flower lady - 2020-12-02

    So, I will say that I have PythonQt working beautifully with a qmake build. However, times are changing, and so must I. I've ported pretty much everything over into CMake. However, Python is the one thing that is not working quite right. As I said, I'm getting the ModuleNotFoundError: No module named \PythonQt\. So, something is not quite right. I would very much appreciate help in either 1) figuring out what is wrong with my cmake, or 2) figuring out where PythonQt actually defines itself on the Python side so I can debug the code at runtime.

    I'm honestly surprised to be running into a bug right this, since it seems like Python and everything linked correctly (I'm not getting any library errors), but I may have lost some dependency that would make PythonQt unhappy (but not raise a compile error? It's weird).

    # Project-level setup ====================================================
    project( project_name )
    cmake_minimum_required( VERSION 3.10 )
    set(TARGET_NAME "project_name")
    
    
    # Find includes in corresponding build directories
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    
    # Instruct CMake to run moc automatically when needed.
    set(CMAKE_AUTOMOC ON) # Saves having to usue QT5_WRAP_CPP
    set(CMAKE_AUTORCC ON) # Saves having to use QT5_ADD_RESOURCES
    set(CMAKE_AUTOUIC ON) # Saves having to use QT5_WRAP_UI
    
    
    # Set compiler flags =====================================================
    # Use C++20
    set(CMAKE_CXX_STANDARD 20)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    # Multiprocess compiler
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
    
    # Set paths to find Qt ===================================================
    # Find Qt itself
    if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
        set(CMAKE_PREFIX_PATH "C:\\Qt\\5.12.2\\msvc2017")
    else()
        message (WARNING "-------- System not supported ---------")
    endif()
    
    # Find UI files
    set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/ui")
    
    # Find Required Qt Libraries =============================================
    find_package(Qt5 COMPONENTS Core REQUIRED)# Core stuff
    find_package(Qt5 COMPONENTS Concurrent REQUIRED) # For threading
    find_package(Qt5 COMPONENTS Gamepad REQUIRED) # Controller support
    find_package(Qt5 COMPONENTS Gui REQUIRED) # For OpenGL integration
    find_package(Qt5 COMPONENTS OpenGLExtensions REQUIRED)
    find_package(Qt5 COMPONENTS Multimedia REQUIRED) # Multimedia capabilities
    find_package(Qt5 COMPONENTS MultimediaWidgets REQUIRED)
    find_package(Qt5 COMPONENTS Widgets REQUIRED) # For widgets
    
    # Set build mode directory options ========================================
    # add_definitions(-DAPPLETTUTORIAL1_LIBRARY)
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/debug)
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/release)
    
    # Set directories to find libraries, need to do this before add_executable for desired target
    file(TO_CMAKE_PATH "$ENV{PYTHON_LIB}" ENV_PYTHON_LIB)
    message(STATUS "Setting link directory ${ENV_PYTHON_LIB}")
    link_directories(${ENV_PYTHON_LIB})
    
    # Build EXE ===============================================================
    message (STATUS "-------- Finding source, header, resource, UI files relative to  ${CMAKE_SOURCE_DIR} ---------")
    file(GLOB_RECURSE MY_SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "src/*.cpp"  "src/*.h"
    "resources/*.qrc" "ui/*.ui")
    
    message (STATUS "=========== FOUND FILES =============")
    message (STATUS "${MY_SOURCES}")
    message (STATUS "=========== END FILES ===============")
    
    # Add an executable to be built from sources variable
    add_executable(${TARGET_NAME} ${MY_SOURCES})
    
    # Add compile definitions to the target ===================================
    set(DEBUG_DEFINITIONS "DEBUG_MODE")
    set(RELEASE_DEFINITIONS "QT_NO_DEBUG_OUTPUT")
    target_compile_definitions(${TARGET_NAME} PUBLIC
        $<$<CONFIG:DEBUG>:${DEBUG_DEFINITIONS}>
        $<$<CONFIG:RELEASE>:${RELEASE_DEFINITIONS}>
    )
    
    # Pre-processor Defines ===================================================
    add_definitions(-D_UNICODE -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DLL -DQT_OPENGL_LIB)
    add_definitions(-DDEVELOP_MODE)
    add_definitions(-DLINALG_USE_EIGEN)
    
    # Disable warnings about deprecated things, like using strcpy (sorry, not sorry)
    if(MSVC)
        add_definitions(-D_CRT_SECURE_NO_WARNINGS)
    endif()
    
    # Add compile options to the target =======================================
    target_link_libraries(${TARGET_NAME} opengl32 glu32)
    target_link_libraries(${TARGET_NAME} Qt5::Core)
    target_link_libraries(${TARGET_NAME} Qt5::Concurrent) 
    target_link_libraries(${TARGET_NAME} Qt5::Gamepad)
    target_link_libraries(${TARGET_NAME} Qt5::Gui)
    target_link_libraries(${TARGET_NAME} Qt5::OpenGLExtensions) # TODO: Probably unnecessary, remove
    target_link_libraries(${TARGET_NAME} Qt5::Multimedia)
    target_link_libraries(${TARGET_NAME} Qt5::MultimediaWidgets)
    target_link_libraries(${TARGET_NAME} Qt5::Widgets)
    
    # Add additional libraries ================================================
    message(STATUS "Default library search directories: ${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/lib/assimp")
    
    # PythonQt
    message (STATUS "=========== Including PythonQt =============")
    # add_definitions(-DPYTHONQT_USE_RELEASE_PYTHON_FALLBACK)
    
    # For system versions, see: 
    # https://stackoverflow.com/questions/9160335/os-specific-instructions-in-cmake-how-to
    if(DEFINED ENV{PYTHON_VERSION})
        set(PYTHON_VERSION $ENV{PYTHON_VERSION})
    else()
        if(WIN32)
            # for Windows operating system in general
            # if(MSVC OR MSYS OR MINGW) # for detecting Windows compilers
            set(PYTHON_VERSION 38)
        elseif(APPLE)
            # for MacOS X or iOS, watchOS, tvOS (since 3.10.3)
        elseif(UNIX AND NOT APPLE)
            # For Linux, BSD, Solaris, Minix
            set(PYTHON_VERSION 3.8)
        else()
            message( WARNING "Unrecognized operating system")
        endif()
    endif()
    message (STATUS "PYTHON VERSION $ENV{PYTHON_VERSION}")
    
    # Set up include paths and libraries for Python itself
    if(WIN32)
        # for Windows operating system in general
        # if(MSVC OR MSYS OR MINGW) # for detecting Windows compilers
    
        # Convert paths to CMAKE-friendly versions
        file(TO_CMAKE_PATH "$ENV{PYTHON_PATH}" ENV_PYTHON_PATH)
    
        # Link Python
        target_include_directories(${TARGET_NAME} PRIVATE "${ENV_PYTHON_PATH}/include")
        message(STATUS "Python include path for windows is ${ENV_PYTHON_PATH}/include")
        message(STATUS "Python path is ${ENV_PYTHON_PATH}")
        find_library(PYTHON_DEBUG_LIB NAMES "python${PYTHON_VERSION}_d" HINTS ${ENV_PYTHON_LIB})
        find_library(PYTHON_RELEASE_LIB NAMES "python${PYTHON_VERSION}" HINTS ${ENV_PYTHON_LIB})
        message(STATUS "Linking Python with debug path ${PYTHON_DEBUG_LIB} and release path ${PYTHON_RELEASE_LIB}")
        target_link_libraries(${TARGET_NAME}
            debug ${PYTHON_DEBUG_LIB} optimized ${PYTHON_RELEASE_LIB}
        )
    elseif(APPLE)
        # for MacOS X or iOS, watchOS, tvOS (since 3.10.3)
        message (STATUS "BUILDING FOR APPLE")
        # Include library directory
        target_include_directories(${TARGET_NAME} PRIVATE "/System/Library/Frameworks/Python.framework/Headers")
    
        # Find library with name Python, and link
        find_library(PYTHON_LIBRARY_PATH NAMES "Python")
        target_link_libraries(${TARGET_NAME}
            ${PYTHON_LIBRARY_PATH}
        )
    elseif(UNIX AND NOT APPLE)
        # For Linux, BSD, Solaris, Minix
        message (STATUS "BUILDING FOR UNIX")
        execute_process(COMMAND python${PYTHON_VERSION}-config --embed --libs
            OUTPUT_VARIABLE PYTHON_LIBRARY_PATH
            RESULT_VARIABLE FAILED_TO_DETECT_PYTHON
        )
        if(FAILED_TO_DETECT_PYTHON)
            message (WARNING "Failed to detect Python")
        else()
            # Set library path
            target_link_libraries(${TARGET_NAME} ${PYTHON_LIBRARY_PATH})
        endif()
    else()
        message( WARNING "Unrecognized operating system")
    endif()
    
    # Include and link PythonQt
    set(PYTHON_QT_PATH "${CMAKE_SOURCE_DIR}/../third_party/PythonQt")
    set(PYTHON_QT_LIB_PATH "${PYTHON_QT_PATH}/lib")
    set(PYTHON_QT_DEBUG_LIB_PATH ${PYTHON_QT_LIB_PATH}/PythonQt-Qt5-Python${PYTHON_VERSION}_d.lib)
    set(PYTHON_QT_RELEASE_LIB_PATH ${PYTHON_QT_LIB_PATH}/PythonQt-Qt5-Python${PYTHON_VERSION}.lib)
    message(STATUS "Linking PythonQt with debug path ${PYTHON_QT_DEBUG_LIB_PATH} and release path ${PYTHON_QT_RELEASE_LIB_PATH}")
    target_include_directories(${TARGET_NAME} PRIVATE "${PYTHON_QT_PATH}/src")
    target_link_libraries(${TARGET_NAME} 
        debug "${PYTHON_QT_DEBUG_LIB_PATH}" optimized "${PYTHON_QT_RELEASE_LIB_PATH}")
    
     
  • Flower lady

    Flower lady - 2020-12-03

    I've done a bit of digging, and noticed that PythonQt simply isn't initializing at all, which is upsetting. I'm reexamining my library paths and seeing if there's a way to figure this out.

    Edit: I was wrong, PythonQt::self() looks fine, at least from what I can tell. It exists at least.

    Edit 2: It looks like I'm not getting any errors on PythonQt::init(), and Py_Initialize() is getting called from PythonQt. However, Py_IsInitialized() returns false after initializing PythonQt, which I guess means that something is going wrong? I'm going to compare against my working qmake build to see if this is the case there as well.

    Edit 3: My qmake build does NOT return false after initializing PythonQt, which means that something is amiss. I'm suspecting that PythonQt might not be getting access to Python like it needs. Although that'd be weird, since I'm using the same statically compiled library for both builds. It's very strange.

     

    Last edit: Flower lady 2020-12-03

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.