diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 4940fcc..a1360ea 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -2,24 +2,37 @@ name: Build & Test Plugin Python on: push: - branches: master + branches: [master] pull_request: types: [opened, synchronize, reopened] +env: + VCPKG_BINARY_SOURCES: clear;x-azblob,${{ vars.AZ_BLOB_VCPKG_URL }},${{ secrets.AZ_BLOB_SAS }},readwrite + jobs: build: runs-on: windows-2022 steps: - - name: Build Plugin Python - id: build-plugin-python + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Configure Plugin Python + id: configure-plugin-python uses: ModOrganizer2/build-with-mob-action@master with: - mo2-third-parties: gtest python spdlog boost sip pyqt pybind11 - mo2-dependencies: cmake_common uibase - mo2-cmake-command: -DPLUGIN_PYTHON_TESTS=1 .. - - name: Build Plugin Python Tests - run: cmake --build vsbuild --config RelWithDebInfo -j4 --target python-tests --target runner-tests - working-directory: ${{ steps.build-plugin-python.outputs.working-directory }} + mo2-dependencies: uibase + mo2-skip-build: true + + - name: Build Plugin Python + working-directory: ${{ steps.configure-plugin-python.outputs.working-directory }} + run: cmake --build vsbuild --config RelWithDebInfo --verbose ` + --target python-tests --target runner-tests --target proxy + - name: Test Plugin Python + working-directory: ${{ steps.configure-plugin-python.outputs.working-directory }} run: ctest --test-dir vsbuild -C RelWithDebInfo --output-on-failure - working-directory: ${{ steps.build-plugin-python.outputs.working-directory }} + + - name: Install Plugin Python + working-directory: ${{ steps.configure-plugin-python.outputs.working-directory }} + run: cmake --build vsbuild --config RelWithDebInfo --target INSTALL diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..3103a1f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-merge-conflict + - id: check-case-conflict + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v19.1.5 + hooks: + - id: clang-format + 'types_or': [c++, c] + +ci: + autofix_commit_msg: "[pre-commit.ci] Auto fixes from pre-commit.com hooks." + autofix_prs: true + autoupdate_commit_msg: "[pre-commit.ci] Pre-commit autoupdate." + autoupdate_schedule: quarterly + submodules: false diff --git a/CMakeLists.txt b/CMakeLists.txt index e92c331..b3c2726 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,44 +2,32 @@ cmake_minimum_required(VERSION 3.16) cmake_policy(SET CMP0144 NEW) -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) -else() - include(${CMAKE_CURRENT_LIST_DIR}/../cmake_common/mo2.cmake) -endif() - project(plugin_python CXX) -set(PYTHON_BUILD_PATH ${PYTHON_ROOT}/PCBuild/amd64) +set(Python_FIND_VIRTUALENV STANDARD) -# find Python - lots of "Hints" since we have a weird setup -set(Python_USE_STATIC_LIBS False) -set(Python_INCLUDE_DIR ${PYTHON_ROOT}/Include) -set(Python_EXECUTABLE ${PYTHON_BUILD_PATH}/python.exe) -if (EXISTS "${PYTHON_BUILD_PATH}/python_d.exe") - set(Python_EXECUTABLE ${PYTHON_BUILD_PATH}/python_d.exe) -endif() -file(GLOB Python_LIBRARY ${PYTHON_BUILD_PATH}/python[0-9][0-9]*.lib) -find_package(Python COMPONENTS Interpreter Development REQUIRED) +# find Python before include mo2-cmake, otherwise this will trigger a bunch of CMP0111 +# due to the imported configuration mapping variables defined in mo2.cmake +find_package(Python ${MO2_PYTHON_VERSION} COMPONENTS Interpreter Development REQUIRED) +find_package(pybind11 CONFIG REQUIRED) -# pybind11 needs uppercase (at least EXECUTABLE and LIBRARY) -set(PYTHON_EXECUTABLE ${Python_EXECUTABLE}) -set(PYTHON_INCLUDE_DIR ${Python_INCLUDE_DIR}) -set(PYTHON_LIBRARY ${Python_LIBRARY}) +find_package(mo2-cmake CONFIG REQUIRED) + +get_filename_component(Python_HOME ${Python_EXECUTABLE} PATH) +set(Python_DLL_DIR "${Python_HOME}/DLLs") +set(Python_LIB_DIR "${Python_HOME}/Lib") + +mo2_python_install_pyqt() # useful for naming DLL, zip, etc. (3.10 -> 310) set(Python_VERSION_SHORT ${Python_VERSION_MAJOR}${Python_VERSION_MINOR}) -# pybind11 -add_subdirectory(${MO2_BUILD_PATH}/pybind11 ${CMAKE_CURRENT_BINARY_DIR}/pybind11) - # projects add_subdirectory(src) -set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT proxy) # tests (if requested) -set(PLUGIN_PYTHON_TESTS ${PLUGIN_PYTHON_TESTS} CACHE BOOL "build tests for plugin_python") -if (PLUGIN_PYTHON_TESTS) +set(BUILD_TESTING ${BUILD_TESTING} CACHE BOOL "build tests for plugin_python") +if (BUILD_TESTING) enable_testing() add_subdirectory(tests) endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..6293933 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,73 @@ +{ + "configurePresets": [ + { + "errors": { + "deprecated": true + }, + "hidden": true, + "name": "cmake-dev", + "warnings": { + "deprecated": true, + "dev": true + } + }, + { + "cacheVariables": { + "VCPKG_MANIFEST_NO_DEFAULT_FEATURES": { + "type": "BOOL", + "value": "ON" + } + }, + "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "hidden": true, + "name": "vcpkg" + }, + { + "cacheVariables": { + "VCPKG_MANIFEST_FEATURES": { + "type": "STRING", + "value": "testing" + } + }, + "hidden": true, + "inherits": ["vcpkg"], + "name": "vcpkg-dev" + }, + { + "binaryDir": "${sourceDir}/vsbuild", + "architecture": { + "strategy": "set", + "value": "x64" + }, + "cacheVariables": { + "CMAKE_CXX_FLAGS": "/EHsc /MP /W4", + "VCPKG_TARGET_TRIPLET": { + "type": "STRING", + "value": "x64-windows-static-md" + } + }, + "generator": "Visual Studio 17 2022", + "inherits": ["cmake-dev", "vcpkg-dev"], + "name": "vs2022-windows", + "toolset": "v143" + }, + { + "cacheVariables": { + "VCPKG_MANIFEST_FEATURES": { + "type": "STRING", + "value": "standalone;testing" + } + }, + "inherits": "vs2022-windows", + "name": "vs2022-windows-standalone" + } + ], + "buildPresets": [ + { + "name": "vs2022-windows", + "resolvePackageReferences": "on", + "configurePreset": "vs2022-windows" + } + ], + "version": 4 +} diff --git a/src/mobase/CMakeLists.txt b/src/mobase/CMakeLists.txt index 87fd525..72eff01 100644 --- a/src/mobase/CMakeLists.txt +++ b/src/mobase/CMakeLists.txt @@ -1,12 +1,38 @@ cmake_minimum_required(VERSION 3.16) +find_package(Qt6 COMPONENTS Core) +find_package(mo2-uibase CONFIG REQUIRED) + pybind11_add_module(mobase MODULE) -mo2_configure_library(mobase - SOURCE_TREE +mo2_default_source_group() +mo2_configure_target(mobase + NO_SOURCES WARNINGS 4 EXTERNAL_WARNINGS 4 AUTOMOC ON TRANSLATIONS OFF - PRIVATE_DEPENDS uibase Qt::Core ) -target_link_libraries(mobase PRIVATE pybind11::qt pybind11::utils) +mo2_target_sources(mobase + FOLDER src + PRIVATE + deprecation.cpp + deprecation.h + mobase.cpp + pybind11_all.h +) +mo2_target_sources(mobase + FOLDER src/wrappers + PRIVATE + ./wrappers/basic_classes.cpp + ./wrappers/game_features.cpp + ./wrappers/known_folders.h + ./wrappers/pyfiletree.cpp + ./wrappers/pyfiletree.h + ./wrappers/pyplugins.cpp + ./wrappers/pyplugins.h + ./wrappers/utils.cpp + ./wrappers/widgets.cpp + ./wrappers/wrappers.cpp + ./wrappers/wrappers.h +) +target_link_libraries(mobase PRIVATE pybind11::qt pybind11::utils mo2::uibase Qt6::Core) diff --git a/src/mobase/deprecation.cpp b/src/mobase/deprecation.cpp index 2b86eee..958712d 100644 --- a/src/mobase/deprecation.cpp +++ b/src/mobase/deprecation.cpp @@ -7,7 +7,7 @@ #include -#include "log.h" +#include namespace py = pybind11; diff --git a/src/mobase/mobase.cpp b/src/mobase/mobase.cpp index 575e716..b1daa2b 100644 --- a/src/mobase/mobase.cpp +++ b/src/mobase/mobase.cpp @@ -12,23 +12,6 @@ #include "wrappers/pyfiletree.h" #include "wrappers/wrappers.h" -// TODO: remove these include (only for testing) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - using namespace MOBase; namespace py = pybind11; diff --git a/src/mobase/pybind11_all.h b/src/mobase/pybind11_all.h index 019e98d..9a76ad2 100644 --- a/src/mobase/pybind11_all.h +++ b/src/mobase/pybind11_all.h @@ -16,9 +16,9 @@ #include "pybind11_utils/shared_cpp_owner.h" #include "pybind11_utils/smart_variant_wrapper.h" -#include -#include -#include +#include +#include +#include namespace mo2::python { diff --git a/src/mobase/wrappers/basic_classes.cpp b/src/mobase/wrappers/basic_classes.cpp index 99e535f..ca5e8eb 100644 --- a/src/mobase/wrappers/basic_classes.cpp +++ b/src/mobase/wrappers/basic_classes.cpp @@ -4,21 +4,21 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../deprecation.h" #include "pyfiletree.h" @@ -33,6 +33,69 @@ namespace mo2::python { void add_versioninfo_classes(py::module_ m) { + // Version + py::class_ pyVersion(m, "Version"); + + py::enum_(pyVersion, "ReleaseType") + .value("DEVELOPMENT", Version::Development) + .value("ALPHA", Version::Alpha) + .value("BETA", Version::Beta) + .value("RELEASE_CANDIDATE", Version::ReleaseCandidate) + .export_values(); + + py::enum_(pyVersion, "ParseMode") + .value("SEMVER", Version::ParseMode::SemVer) + .value("MO2", Version::ParseMode::MO2); + + py::enum_(pyVersion, "FormatMode", py::arithmetic{}) + .value("FORCE_SUBPATCH", Version::FormatMode::ForceSubPatch) + .value("NO_SEPARATOR", Version::FormatMode::NoSeparator) + .value("SHORT_ALPHA_BETA", Version::FormatMode::ShortAlphaBeta) + .value("NO_METADATA", Version::FormatMode::NoMetadata) + .value("CONDENSED", + static_cast(Version::FormatCondensed.toInt())) + .export_values(); + + pyVersion + .def_static("parse", &Version::parse, "value"_a, + "mode"_a = Version::ParseMode::SemVer) + .def(py::init(), "major"_a, "minor"_a, "patch"_a, + "metadata"_a = "") + .def(py::init(), "major"_a, "minor"_a, + "patch"_a, "subpatch"_a, "metadata"_a = "") + .def(py::init(), "major"_a, + "minor"_a, "patch"_a, "type"_a, "metadata"_a = "") + .def(py::init(), + "major"_a, "minor"_a, "patch"_a, "subpatch"_a, "type"_a, + "metadata"_a = "") + .def(py::init(), + "major"_a, "minor"_a, "patch"_a, "type"_a, "prerelease"_a, + "metadata"_a = "") + .def(py::init(), + "major"_a, "minor"_a, "patch"_a, "subpatch"_a, "type"_a, + "prerelease"_a, "metadata"_a = "") + .def(py::init>, + QString>(), + "major"_a, "minor"_a, "patch"_a, "subpatch"_a, "prereleases"_a, + "metadata"_a = "") + .def("isPreRelease", &Version::isPreRelease) + .def_property_readonly("major", &Version::major) + .def_property_readonly("minor", &Version::minor) + .def_property_readonly("patch", &Version::patch) + .def_property_readonly("subpatch", &Version::subpatch) + .def_property_readonly("prereleases", &Version::preReleases) + .def_property_readonly("build_metadata", &Version::buildMetadata) + .def("string", &Version::string, "mode"_a = Version::FormatCondensed) + .def("__str__", &Version::string) + .def(py::self < py::self) + .def(py::self > py::self) + .def(py::self <= py::self) + .def(py::self >= py::self) + .def(py::self != py::self) + .def(py::self == py::self); + + // VersionInfo py::enum_(m, "ReleaseType") .value("final", MOBase::VersionInfo::RELEASE_FINAL) .value("candidate", MOBase::VersionInfo::RELEASE_CANDIDATE) @@ -453,7 +516,17 @@ namespace mo2::python { .def("overwritePath", &IOrganizer::overwritePath) .def("basePath", &IOrganizer::basePath) .def("modsPath", &IOrganizer::modsPath) - .def("appVersion", &IOrganizer::appVersion) + .def("appVersion", + [](IOrganizer& o) { + mo2::python::show_deprecation_warning( + "appVersion", "IOrganizer::appVersion() is deprecated, use " + "IOrganizer::version() instead."); +#pragma warning(push) +#pragma warning(disable : 4996) + return o.appVersion(); +#pragma warning(pop) + }) + .def("version", &IOrganizer::version) .def("createMod", &IOrganizer::createMod, py::return_value_policy::reference, "name"_a) .def("getGame", &IOrganizer::getGame, py::return_value_policy::reference, diff --git a/src/mobase/wrappers/game_features.cpp b/src/mobase/wrappers/game_features.cpp index 805b093..655334b 100644 --- a/src/mobase/wrappers/game_features.cpp +++ b/src/mobase/wrappers/game_features.cpp @@ -4,19 +4,19 @@ #include "../pybind11_all.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "pyfiletree.h" diff --git a/src/mobase/wrappers/pyfiletree.cpp b/src/mobase/wrappers/pyfiletree.cpp index 4fb1560..4657b8a 100644 --- a/src/mobase/wrappers/pyfiletree.cpp +++ b/src/mobase/wrappers/pyfiletree.cpp @@ -5,8 +5,8 @@ #include "../pybind11_all.h" -#include -#include +#include +#include namespace py = pybind11; using namespace MOBase; diff --git a/src/mobase/wrappers/pyfiletree.h b/src/mobase/wrappers/pyfiletree.h index 25655d2..0e94665 100644 --- a/src/mobase/wrappers/pyfiletree.h +++ b/src/mobase/wrappers/pyfiletree.h @@ -3,7 +3,7 @@ #include "../pybind11_all.h" -#include +#include namespace pybind11 { template <> diff --git a/src/mobase/wrappers/pyplugins.h b/src/mobase/wrappers/pyplugins.h index 9cce1f9..17f7ab5 100644 --- a/src/mobase/wrappers/pyplugins.h +++ b/src/mobase/wrappers/pyplugins.h @@ -3,18 +3,18 @@ #include "../pybind11_all.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // these needs to be defined in a header file for automoc - this file is included only // in pyplugins.cpp diff --git a/src/mobase/wrappers/utils.cpp b/src/mobase/wrappers/utils.cpp index 95cd637..eb3e9e2 100644 --- a/src/mobase/wrappers/utils.cpp +++ b/src/mobase/wrappers/utils.cpp @@ -2,8 +2,8 @@ #include "../pybind11_all.h" -#include -#include +#include +#include #include "known_folders.h" diff --git a/src/mobase/wrappers/widgets.cpp b/src/mobase/wrappers/widgets.cpp index 0abdbe5..e626540 100644 --- a/src/mobase/wrappers/widgets.cpp +++ b/src/mobase/wrappers/widgets.cpp @@ -2,7 +2,7 @@ #include "../pybind11_all.h" -#include +#include namespace py = pybind11; using namespace MOBase; diff --git a/src/mobase/wrappers/wrappers.cpp b/src/mobase/wrappers/wrappers.cpp index 33d5804..10f043d 100644 --- a/src/mobase/wrappers/wrappers.cpp +++ b/src/mobase/wrappers/wrappers.cpp @@ -10,10 +10,10 @@ // IOrganizer must be bring here to properly compile the Python bindings of // plugin requirements -#include -#include -#include -#include +#include +#include +#include +#include using namespace pybind11::literals; namespace py = pybind11; diff --git a/src/mobase/wrappers/wrappers.h b/src/mobase/wrappers/wrappers.h index d4af629..43dd574 100644 --- a/src/mobase/wrappers/wrappers.h +++ b/src/mobase/wrappers/wrappers.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mo2::python { diff --git a/src/proxy/CMakeLists.txt b/src/proxy/CMakeLists.txt index bee4952..c37b219 100644 --- a/src/proxy/CMakeLists.txt +++ b/src/proxy/CMakeLists.txt @@ -1,9 +1,12 @@ cmake_minimum_required(VERSION 3.16) +find_package(mo2-uibase CONFIG REQUIRED) + set(PLUGIN_NAME "plugin_python") -add_library(proxy SHARED) +add_library(proxy SHARED proxypython.cpp proxypython.h) mo2_configure_plugin(proxy + NO_SOURCES WARNINGS 4 EXTERNAL_WARNINGS 4 TRANSLATIONS OFF @@ -11,15 +14,16 @@ mo2_configure_plugin(proxy ${CMAKE_CURRENT_SOURCE_DIR}/../runner ${CMAKE_CURRENT_SOURCE_DIR}/../mobase ${CMAKE_CURRENT_SOURCE_DIR}/../pybind11-qt) -target_link_libraries(proxy PRIVATE runner) +mo2_default_source_group() +target_link_libraries(proxy PRIVATE runner mo2::uibase) set_target_properties(proxy PROPERTIES OUTPUT_NAME ${PLUGIN_NAME}) -mo2_install_target(proxy FOLDER) +mo2_install_plugin(proxy FOLDER) -set(PLUGIN_PYTHON_DIR ${MO2_INSTALL_PATH}/bin/plugins/${PLUGIN_NAME}) +set(PLUGIN_PYTHON_DIR bin/plugins/${PLUGIN_NAME}) # install runner target_link_options(proxy PRIVATE "/DELAYLOAD:runner.dll") -mo2_install_target(runner INSTALLDIR ${PLUGIN_PYTHON_DIR}/dlls) +install(FILES $ DESTINATION ${PLUGIN_PYTHON_DIR}/dlls) # translations (custom location) mo2_add_translations(proxy @@ -33,23 +37,37 @@ mo2_add_translations(proxy # install DLLs files needed set(DLL_DIRS ${PLUGIN_PYTHON_DIR}/dlls) file(GLOB dlls_to_install - ${PYTHON_BUILD_PATH}/libffi*.dll - ${PYTHON_BUILD_PATH}/python${Python_VERSION_SHORT}*.dll) + # ${PYTHON_BUILD_PATH}/libffi*.dll + ${Python_HOME}/python${Python_VERSION_MAJOR}*.dll) install(FILES ${dlls_to_install} DESTINATION ${DLL_DIRS}) -# install Python files +# install Python .pyd files set(PYLIB_DIR ${PLUGIN_PYTHON_DIR}/libs) -file(GLOB libs_to_install ${PYTHON_BUILD_PATH}/pythoncore/*.pyd) +file(GLOB libs_to_install ${Python_DLL_DIR}/*.pyd) install(FILES ${libs_to_install} DESTINATION ${PYLIB_DIR}) -install(FILES ${PYTHON_BUILD_PATH}/pythoncore/python${Python_VERSION_SHORT}.zip - DESTINATION ${PYLIB_DIR} RENAME pythoncore.zip) + +# generate + install standard library +set(pythoncore_zip "${CMAKE_CURRENT_BINARY_DIR}/pythoncore.zip") +add_custom_command( + TARGET proxy POST_BUILD + COMMAND ${Python_EXECUTABLE} + "${CMAKE_CURRENT_SOURCE_DIR}\\build_pythoncore.py" + ${pythoncore_zip} + ) +install(FILES ${pythoncore_zip} DESTINATION ${PYLIB_DIR}) # install mobase install(TARGETS mobase DESTINATION ${PYLIB_DIR}) # install PyQt6 -#file(GLOB PYQT_DIR ${MO2_BUILD_PATH}/PyQt${QT_MAJOR_VERSION}*) -set(PYQT_LIB_DIR ${PYTHON_ROOT}/Lib/site-packages/PyQt${QT_MAJOR_VERSION}) -set(PYQT_TARGET_DIR ${PYLIB_DIR}/PyQt${QT_MAJOR_VERSION}) -file(GLOB pyqt_files ${PYQT_LIB_DIR}/*.py ${PYQT_LIB_DIR}/*.pyd ${PYQT_LIB_DIR}/*.pyi) -install(FILES ${pyqt_files} DESTINATION ${PYQT_TARGET_DIR}) +install( + DIRECTORY ${CMAKE_BINARY_DIR}/pylibs/PyQt${MO2_QT_VERSION_MAJOR} + DESTINATION ${PYLIB_DIR} + PATTERN "*.pyd" + PATTERN "*.pyi" + PATTERN "__pycache__" EXCLUDE + PATTERN "bindings" EXCLUDE + PATTERN "lupdate" EXCLUDE + PATTERN "Qt6" EXCLUDE + PATTERN "uic" EXCLUDE +) diff --git a/src/proxy/build_pythoncore.py b/src/proxy/build_pythoncore.py new file mode 100644 index 0000000..481dec5 --- /dev/null +++ b/src/proxy/build_pythoncore.py @@ -0,0 +1,14 @@ +import sys +import zipfile +from pathlib import Path + +_EXCLUDE_MODULES = ["ensurepip", "idlelib", "test", "tkinter", "turtle_demo", "venv"] + +libdir = Path(sys.executable).parent.joinpath("Lib") +assert libdir.exists() + +with zipfile.PyZipFile(sys.argv[1], optimize=2, mode="w") as fp: + fp.writepy(libdir) # pyright: ignore[reportArgumentType] + for path in libdir.iterdir(): + if path.is_dir() and path.name not in _EXCLUDE_MODULES: + fp.writepy(path) # pyright: ignore[reportArgumentType] diff --git a/src/proxy/proxypython.cpp b/src/proxy/proxypython.cpp index b38dd0c..0ecbfc0 100644 --- a/src/proxy/proxypython.cpp +++ b/src/proxy/proxypython.cpp @@ -28,9 +28,9 @@ along with python proxy plugin. If not, see . #include #include -#include -#include -#include +#include +#include +#include namespace fs = std::filesystem; using namespace MOBase; diff --git a/src/proxy/proxypython.h b/src/proxy/proxypython.h index 5165fae..3d52da5 100644 --- a/src/proxy/proxypython.h +++ b/src/proxy/proxypython.h @@ -23,8 +23,8 @@ along with python proxy plugin. If not, see . #include #include -#include -#include +#include +#include #include diff --git a/src/proxy/resource.h b/src/proxy/resource.h deleted file mode 100644 index 1f33c5c..0000000 --- a/src/proxy/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef RESOURCE_H -#define RESOURCE_H - -#define IDR_LOADER_DLL 100 - -#endif // RESOURCE_H diff --git a/src/pybind11-qt/CMakeLists.txt b/src/pybind11-qt/CMakeLists.txt index b75fbc7..dd9d217 100644 --- a/src/pybind11-qt/CMakeLists.txt +++ b/src/pybind11-qt/CMakeLists.txt @@ -1,18 +1,62 @@ cmake_minimum_required(VERSION 3.16) +find_package(Qt6 REQUIRED COMPONENTS Core Widgets) + +mo2_find_python_executable(PYTHON_EXE) + add_library(pybind11-qt STATIC) -mo2_configure_library(pybind11-qt - SOURCE_TREE +mo2_configure_target(pybind11-qt + NO_SOURCES WARNINGS 4 EXTERNAL_WARNINGS 4 AUTOMOC OFF TRANSLATIONS OFF - PRIVATE_DEPENDS Qt::Core Qt::Widgets ) -target_link_libraries(pybind11-qt PUBLIC pybind11::pybind11) +mo2_default_source_group() +target_sources(pybind11-qt + PRIVATE + ./include/pybind11_qt/pybind11_qt_basic.h + ./include/pybind11_qt/pybind11_qt_containers.h + ./include/pybind11_qt/pybind11_qt_enums.h + ./include/pybind11_qt/pybind11_qt_holder.h + ./include/pybind11_qt/pybind11_qt_objects.h + ./include/pybind11_qt/pybind11_qt_qflags.h + ./include/pybind11_qt/pybind11_qt.h + + pybind11_qt_basic.cpp + pybind11_qt_sip.cpp + pybind11_qt_utils.cpp + +) +mo2_target_sources(pybind11-qt + FOLDER src/details + PRIVATE + ./include/pybind11_qt/details/pybind11_qt_enum.h + ./include/pybind11_qt/details/pybind11_qt_qlist.h + ./include/pybind11_qt/details/pybind11_qt_qmap.h + ./include/pybind11_qt/details/pybind11_qt_sip.h + ./include/pybind11_qt/details/pybind11_qt_utils.h +) +target_link_libraries(pybind11-qt PUBLIC pybind11::pybind11 PRIVATE Qt6::Core Qt6::Widgets) target_include_directories(pybind11-qt PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) # this is kind of broken but it only works with this... target_compile_definitions(pybind11-qt PUBLIC QT_NO_KEYWORDS) +# we need sip.h for pybind11-qt +add_custom_target(PyQt6-siph DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sip.h") +set_target_properties(PyQt6-siph PROPERTIES FOLDER autogen) +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/sip.h" + COMMAND + ${CMAKE_COMMAND} -E env PYTHONPATH=${MO2_PYLIBS_DIR} + ${MO2_PYLIBS_DIR}/bin/sip-module.exe + --sip-h PyQt${MO2_QT_VERSION_MAJOR}.sip + --target-dir ${CMAKE_CURRENT_BINARY_DIR} +) +add_dependencies(PyQt6-siph PyQt6) +add_dependencies(pybind11-qt PyQt6-siph) + +target_include_directories(pybind11-qt PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + add_library(pybind11::qt ALIAS pybind11-qt) diff --git a/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_sip.h b/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_sip.h index 2996c4b..556a980 100644 --- a/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_sip.h +++ b/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_sip.h @@ -4,21 +4,37 @@ #include #include -#include #include #include #include "../pybind11_qt_holder.h" +struct _sipTypeDef; +typedef struct _sipTypeDef sipTypeDef; + +struct _sipSimpleWrapper; +typedef struct _sipSimpleWrapper sipSimpleWrapper; + +struct _sipWrapper; +typedef struct _sipWrapper sipWrapper; + namespace pybind11::detail::qt { - /** - * @brief Retrieve the SIP api. - * - * @return const sipAPIDef* - */ - const sipAPIDef* sipAPI(); + // helper functions to avoid bringing in this header + namespace sip { + + // extract the underlying data if present from the equivalent PyQt object + void* extract_data(PyObject*); + + const sipTypeDef* api_find_type(const char* type); + int api_can_convert_to_type(PyObject* pyObj, const sipTypeDef* td, int flags); + + void api_transfer_to(PyObject* self, PyObject* owner); + void api_transfer_back(PyObject* self); + PyObject* api_convert_from_type(void* cpp, const sipTypeDef* td, + PyObject* transferObj); + } // namespace sip template struct MetaData; @@ -91,12 +107,11 @@ namespace pybind11::detail::qt { } } - const sipTypeDef* type = - qt::sipAPI()->api_find_type(MetaData::class_name); + const auto* type = sip::api_find_type(MetaData::class_name); if (type == nullptr) { return false; } - if (!qt::sipAPI()->api_can_convert_to_type(src.ptr(), type, 0)) { + if (!sip::api_can_convert_to_type(src.ptr(), type, 0)) { return false; } @@ -107,20 +122,14 @@ namespace pybind11::detail::qt { // // sipAPI()->api_transfer_to(objPtr, Py_None); // - void* data = nullptr; - if (PyObject_TypeCheck(src.ptr(), qt::sipAPI()->api_simplewrapper_type)) { - data = reinterpret_cast(src.ptr())->data; - } - else if (PyObject_TypeCheck(src.ptr(), qt::sipAPI()->api_wrapper_type)) { - data = reinterpret_cast(src.ptr())->super.data; - } + void* const data = sip::extract_data(src.ptr()); if (data) { if constexpr (is_pointer) { value = reinterpret_cast(data); // transfer ownership - sipAPI()->api_transfer_to(src.ptr(), Py_None); + sip::api_transfer_to(src.ptr(), Py_None); // tie the py::object to the C++ one new pybind11::detail::qt::qobject_holder_impl(value); @@ -164,8 +173,7 @@ namespace pybind11::detail::qt { } } - const sipTypeDef* type = - qt::sipAPI()->api_find_type(MetaData::class_name); + const sipTypeDef* type = sip::api_find_type(MetaData::class_name); if (type == nullptr) { return Py_None; } @@ -188,7 +196,7 @@ namespace pybind11::detail::qt { sipData = &src; } - sipObj = qt::sipAPI()->api_convert_from_type(sipData, type, 0); + sipObj = sip::api_convert_from_type(sipData, type, 0); if (sipObj == nullptr) { return Py_None; @@ -196,11 +204,11 @@ namespace pybind11::detail::qt { // ensure Python deletes the C++ component if constexpr (!is_pointer) { - qt::sipAPI()->api_transfer_back(sipObj); + sip::api_transfer_back(sipObj); } else { if (policy == return_value_policy::take_ownership) { - qt::sipAPI()->api_transfer_back(sipObj); + sip::api_transfer_back(sipObj); } } diff --git a/src/pybind11-qt/include/pybind11_qt/pybind11_qt.h b/src/pybind11-qt/include/pybind11_qt/pybind11_qt.h index 3edba59..e803e9f 100644 --- a/src/pybind11-qt/include/pybind11_qt/pybind11_qt.h +++ b/src/pybind11-qt/include/pybind11_qt/pybind11_qt.h @@ -59,7 +59,7 @@ namespace pybind11::qt { * simply return the PyQtX object as a QClass* object, while __getattr__ * will delegate to the underlying QClass object when required. * - * This allow access to Qt interface for object exposed using boost::python + * This allow access to Qt interface for object exposed using pybind11 * (e.g., signals, methods from QObject or QWidget, etc.). * * @param pyclass Python class to define the methods on. diff --git a/src/pybind11-qt/pybind11_qt_sip.cpp b/src/pybind11-qt/pybind11_qt_sip.cpp index e3e0a1f..69ad4b8 100644 --- a/src/pybind11-qt/pybind11_qt_sip.cpp +++ b/src/pybind11-qt/pybind11_qt_sip.cpp @@ -4,6 +4,8 @@ #include +#include + namespace py = pybind11; namespace pybind11::detail::qt { @@ -61,4 +63,43 @@ namespace pybind11::detail::qt { return sipApi; } + namespace sip { + const sipTypeDef* api_find_type(const char* type) + { + return sipAPI()->api_find_type(type); + } + + int api_can_convert_to_type(PyObject* pyObj, const sipTypeDef* td, int flags) + { + return sipAPI()->api_can_convert_to_type(pyObj, td, flags); + } + + void api_transfer_to(PyObject* self, PyObject* owner) + { + sipAPI()->api_transfer_to(self, owner); + } + + void api_transfer_back(PyObject* self) + { + sipAPI()->api_transfer_back(self); + } + + PyObject* api_convert_from_type(void* cpp, const sipTypeDef* td, PyObject*) + { + return sipAPI()->api_convert_from_type(cpp, td, 0); + } + + void* extract_data(PyObject* ptr) + { + if (PyObject_TypeCheck(ptr, sipAPI()->api_simplewrapper_type)) { + return reinterpret_cast(ptr)->data; + } + else if (PyObject_TypeCheck(ptr, sipAPI()->api_wrapper_type)) { + return reinterpret_cast(ptr)->super.data; + } + return nullptr; + } + + } // namespace sip + } // namespace pybind11::detail::qt diff --git a/src/pybind11-utils/CMakeLists.txt b/src/pybind11-utils/CMakeLists.txt index 4b2c170..372a9b7 100644 --- a/src/pybind11-utils/CMakeLists.txt +++ b/src/pybind11-utils/CMakeLists.txt @@ -1,13 +1,21 @@ cmake_minimum_required(VERSION 3.16) -add_library(pybind11-utils STATIC) -mo2_configure_library(pybind11-utils - SOURCE_TREE +add_library(pybind11-utils STATIC + ./include/pybind11_utils/functional.h + ./include/pybind11_utils/shared_cpp_owner.h + ./include/pybind11_utils/smart_variant_wrapper.h + ./include/pybind11_utils/smart_variant.h + + functional.cpp +) +mo2_configure_target(pybind11-utils + NO_SOURCES WARNINGS 4 EXTERNAL_WARNINGS 4 AUTOMOC OFF TRANSLATIONS OFF ) +mo2_default_source_group() target_link_libraries(pybind11-utils PUBLIC pybind11::pybind11) target_include_directories(pybind11-utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/src/runner/CMakeLists.txt b/src/runner/CMakeLists.txt index 9457ab6..faee5c6 100644 --- a/src/runner/CMakeLists.txt +++ b/src/runner/CMakeLists.txt @@ -1,15 +1,23 @@ cmake_minimum_required(VERSION 3.16) -add_library(runner SHARED) -mo2_configure_library(runner - SOURCE_TREE +find_package(mo2-uibase CONFIG REQUIRED) + +add_library(runner SHARED + error.h + pythonrunner.cpp + pythonrunner.h + pythonutils.h + pythonutils.cpp +) +mo2_configure_target(runner + NO_SOURCES WARNINGS 4 EXTERNAL_WARNINGS 4 AUTOMOC ON TRANSLATIONS OFF - PUBLIC_DEPENDS uibase Qt::Core ) -target_link_libraries(runner PRIVATE pybind11::embed pybind11::qt) +mo2_default_source_group() +target_link_libraries(runner PUBLIC mo2::uibase PRIVATE pybind11::embed pybind11::qt) target_include_directories(runner PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(runner PRIVATE RUNNER_BUILD) diff --git a/src/runner/error.h b/src/runner/error.h index d38c8af..341c7ea 100644 --- a/src/runner/error.h +++ b/src/runner/error.h @@ -7,7 +7,7 @@ #include -#include +#include namespace pyexcept { diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index 35b2216..3538bb7 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -16,8 +16,8 @@ #include #include -#include -#include +#include +#include #include "error.h" #include "pythonutils.h" diff --git a/src/runner/pythonutils.cpp b/src/runner/pythonutils.cpp index 9cc3a75..c94a50b 100644 --- a/src/runner/pythonutils.cpp +++ b/src/runner/pythonutils.cpp @@ -7,7 +7,7 @@ #include #include -#include "log.h" +#include namespace py = pybind11; @@ -123,7 +123,7 @@ namespace mo2::python { void configure_python_logging(py::module_ mobase) { // most of this is dealing with actual Python objects since it is not - // possible to derive from logging.Handler in C++ using Boost.Python, + // possible to derive from logging.Handler in C++ using pybind11, // and since a lot of this would require extra register only for this. // see also diff --git a/tests/mocks/DummyFileTree.h b/tests/mocks/DummyFileTree.h index 3f1cb01..cf81691 100644 --- a/tests/mocks/DummyFileTree.h +++ b/tests/mocks/DummyFileTree.h @@ -1,7 +1,7 @@ #ifndef DUMMY_TREE_H #define DUMMY_TREE_H -#include +#include // filetree implementation for testing purpose // @@ -19,8 +19,8 @@ class DummyFileTree : public MOBase::IFileTree { return std::make_shared(parent, name); } - bool doPopulate(std::shared_ptr parent, - std::vector>& entries) const override + bool doPopulate(std::shared_ptr, + std::vector>&) const override { return true; } diff --git a/tests/mocks/MockOrganizer.h b/tests/mocks/MockOrganizer.h index 5ef98e8..cdae36a 100644 --- a/tests/mocks/MockOrganizer.h +++ b/tests/mocks/MockOrganizer.h @@ -1,5 +1,5 @@ -#include "imoinfo.h" #include +#include using namespace MOBase; @@ -14,6 +14,7 @@ class MockOrganizer : public IOrganizer { MOCK_METHOD(QString, basePath, (), (const, override)); MOCK_METHOD(QString, modsPath, (), (const, override)); MOCK_METHOD(VersionInfo, appVersion, (), (const, override)); + MOCK_METHOD(Version, version, (), (const, override)); MOCK_METHOD(IModInterface*, createMod, (GuessedValue &name), (override)); MOCK_METHOD(IPluginGame*, getGame, (const QString &gameName), (const, override)); MOCK_METHOD(void, modDataChanged, (IModInterface *mod), (override)); diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 3e80a54..6138c37 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -2,17 +2,28 @@ cmake_minimum_required(VERSION 3.16) # pytest cmake_policy(SET CMP0144 NEW) + +find_package(mo2-uibase CONFIG REQUIRED) find_package(GTest REQUIRED) set(PYLIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/pylibs) -if (TARGET uibase) - set(UIBASE_PATH $) -else() - set(UIBASE_PATH "${MO2_INSTALL_PATH}/bin") -endif() +set(UIBASE_PATH $) add_custom_target(python-tests) +target_sources(python-tests + PRIVATE + conftest.py + test_argument_wrapper.py + test_filetree.py + test_functional.py + test_guessed_string.py + test_organizer.py + test_path_wrappers.py + test_qt_widgets.py + test_qt.py + test_shared_cpp_owner.py +) add_test(NAME pytest COMMAND ${CMAKE_CURRENT_BINARY_DIR}/pylibs/bin/pytest.exe ${CMAKE_CURRENT_SOURCE_DIR} -s @@ -21,18 +32,16 @@ add_test(NAME pytest set_tests_properties(pytest PROPERTIES DEPENDS python-tests - WORKING_DIRECTORY ${MO2_INSTALL_PATH}/bin ENVIRONMENT_MODIFICATION "PYTHONPATH=set:${PYLIB_DIR}\\;$;\ -UIBASE_PATH=set:${UIBASE_PATH};\ -QT_ROOT=set:${QT_ROOT}" +UIBASE_PATH=set:${UIBASE_PATH}" ) mo2_python_pip_install(python-tests DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pylibs PACKAGES pytest - PyQt${QT_MAJOR_VERSION}==${QT_VERSION} - PyQt${QT_MAJOR_VERSION}-Qt${QT_MAJOR_VERSION}==${QT_VERSION}) + PyQt${MO2_QT_VERSION_MAJOR}==${MO2_PYQT_VERSION} + PyQt${MO2_QT_VERSION_MAJOR}-Qt${MO2_QT_VERSION_MAJOR}==${MO2_QT_VERSION}) add_dependencies(python-tests mobase) set_target_properties(python-tests PROPERTIES FOLDER tests/python) @@ -44,6 +53,7 @@ foreach (test_file ${test_files}) pybind11_add_module(${target} EXCLUDE_FROM_ALL THIN_LTO ${test_file}) set_target_properties(${target} PROPERTIES + CXX_STANDARD 20 OUTPUT_NAME ${pymodule} FOLDER tests/python LIBRARY_OUTPUT_DIRECTORY "${PYLIB_DIR}/mobase_tests") @@ -56,8 +66,8 @@ foreach (test_file ${test_files}) endforeach() endif() - mo2_add_dependencies(${target} PRIVATE uibase Qt::Core Qt::Widgets) - target_link_libraries(${target} PRIVATE pybind11::qt pybind11::utils GTest::gmock) + target_link_libraries(${target} PRIVATE + mo2::uibase Qt6::Core Qt6::Widgets pybind11::qt pybind11::utils GTest::gmock) target_include_directories(${target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../mocks) diff --git a/tests/python/conftest.py b/tests/python/conftest.py index 34ca988..99e7800 100644 --- a/tests/python/conftest.py +++ b/tests/python/conftest.py @@ -1,15 +1,12 @@ import os import sys -from pathlib import Path -from typing import cast + +from PyQt6.QtWidgets import QApplication def pytest_configure(): global app - os.add_dll_directory(str(Path(cast(str, os.getenv("QT_ROOT"))).joinpath("bin"))) os.add_dll_directory(str(os.getenv("UIBASE_PATH"))) - from PyQt6.QtWidgets import QApplication - app = QApplication(sys.argv) diff --git a/tests/python/test_filetree.cpp b/tests/python/test_filetree.cpp index 882a0b4..cce43cf 100644 --- a/tests/python/test_filetree.cpp +++ b/tests/python/test_filetree.cpp @@ -3,7 +3,7 @@ #include #include -#include "ifiletree.h" +#include using namespace MOBase; diff --git a/tests/python/test_guessed_string.cpp b/tests/python/test_guessed_string.cpp index 4256989..5e76773 100644 --- a/tests/python/test_guessed_string.cpp +++ b/tests/python/test_guessed_string.cpp @@ -3,7 +3,7 @@ #include #include -#include "guessedvalue.h" +#include using namespace MOBase; diff --git a/tests/python/test_organizer.cpp b/tests/python/test_organizer.cpp index 3f1878d..ea54c0d 100644 --- a/tests/python/test_organizer.cpp +++ b/tests/python/test_organizer.cpp @@ -17,32 +17,30 @@ PYBIND11_MODULE(organizer, m) using ::testing::Eq; using ::testing::Return; - m.def( - "organizer", - []() -> IOrganizer* { - MockOrganizer* mock = new NiceMock(); - ON_CALL(*mock, profileName).WillByDefault([&mock]() { - return "profile"; + m.def("organizer", []() -> IOrganizer* { + MockOrganizer* mock = new NiceMock(); + ON_CALL(*mock, profileName).WillByDefault([&mock]() { + return "profile"; + }); + + const auto handle = (HANDLE)std::uintptr_t{4654}; + ON_CALL(*mock, startApplication) + .WillByDefault([handle](const auto& name, auto&&... args) { + return name == "valid.exe" ? handle : INVALID_HANDLE_VALUE; + }); + ON_CALL(*mock, waitForApplication) + .WillByDefault([&mock, original_handle = handle](HANDLE handle, bool, + LPDWORD exitCode) { + if (handle == original_handle) { + *exitCode = 0; + return true; + } + else { + *exitCode = static_cast(-1); + return false; + } }); - const auto handle = (HANDLE)std::uintptr_t{4654}; - EXPECT_CALL(*mock, startApplication(Eq("valid.exe"), _, _, _, _, _)) - .WillRepeatedly(Return(handle)); - EXPECT_CALL(*mock, startApplication(Eq("invalid.exe"), _, _, _, _, _)) - .WillRepeatedly(Return(INVALID_HANDLE_VALUE)); - ON_CALL(*mock, waitForApplication) - .WillByDefault([&mock, original_handle = handle]( - HANDLE handle, bool refresh, LPDWORD exitCode) { - if (handle == original_handle) { - *exitCode = 0; - return true; - } - else { - *exitCode = -1; - return false; - } - }); - - return mock; - }, - py::return_value_policy::take_ownership); + + return mock; + }); } diff --git a/tests/python/test_qt.cpp b/tests/python/test_qt.cpp index 35b1785..5ef1f00 100644 --- a/tests/python/test_qt.cpp +++ b/tests/python/test_qt.cpp @@ -72,24 +72,26 @@ PYBIND11_MODULE(qt, m) // QVariant m.def("qvariant_from_none", [](QVariant const& variant) { - return std::make_tuple(variant.userType() == QVariant::Invalid, + return std::make_tuple(variant.userType() == QMetaType::UnknownType, variant.isValid()); }); m.def("qvariant_from_int", [](QVariant const& variant) { - return std::make_tuple(variant.userType() == QVariant::Int, variant.toInt()); + return std::make_tuple(variant.userType() == QMetaType::Int, variant.toInt()); }); m.def("qvariant_from_bool", [](QVariant const& variant) { - return std::make_tuple(variant.userType() == QVariant::Bool, variant.toBool()); + return std::make_tuple(variant.userType() == QMetaType::Bool, variant.toBool()); }); m.def("qvariant_from_str", [](QVariant const& variant) { - return std::make_tuple(variant.userType() == QVariant::String, + return std::make_tuple(variant.userType() == QMetaType::QString, variant.toString()); }); m.def("qvariant_from_list", [](QVariant const& variant) { - return std::make_tuple(variant.userType() == QVariant::List, variant.toList()); + return std::make_tuple(variant.userType() == QMetaType::QVariantList, + variant.toList()); }); m.def("qvariant_from_map", [](QVariant const& variant) { - return std::make_tuple(variant.userType() == QVariant::Map, variant.toMap()); + return std::make_tuple(variant.userType() == QMetaType::QVariantMap, + variant.toMap()); }); m.def("qvariant_none", []() { diff --git a/tests/runner/CMakeLists.txt b/tests/runner/CMakeLists.txt index 800b593..ea17438 100644 --- a/tests/runner/CMakeLists.txt +++ b/tests/runner/CMakeLists.txt @@ -5,8 +5,33 @@ cmake_minimum_required(VERSION 3.22) # first we configure the tests as with other tests add_executable(runner-tests EXCLUDE_FROM_ALL) - -mo2_configure_tests(runner-tests WARNINGS OFF) +mo2_default_source_group() +mo2_target_sources(runner-tests + FOLDER src + PRIVATE + test_diagnose.cpp + test_filemapper.cpp + test_game.cpp + test_installer.cpp + test_iplugin.cpp + test_lifetime.cpp +) +mo2_target_sources(runner-tests + FOLDER src/mocks + PRIVATE + ../mocks/DummyFileTree.h + ../mocks/MockOrganizer.h +) +mo2_target_sources(runner-tests + FOLDER src/plugins + PRIVATE + plugins/dummy-diagnose.py + plugins/dummy-filemapper.py + plugins/dummy-game.py + plugins/dummy-installer.py + plugins/dummy-iplugin.py +) +mo2_configure_tests(runner-tests NO_SOURCES WARNINGS 4) set_target_properties(runner-tests PROPERTIES FOLDER tests/runner) @@ -25,16 +50,14 @@ target_include_directories(runner-tests set(PYLIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/pylibs) mo2_python_pip_install(runner-tests DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pylibs - PACKAGES - pytest - PyQt${QT_MAJOR_VERSION}==${QT_VERSION} - PyQt${QT_MAJOR_VERSION}-Qt${QT_MAJOR_VERSION}==${QT_VERSION}) + PACKAGES + pytest + PyQt${MO2_QT_VERSION_MAJOR}==${MO2_PYQT_VERSION} + PyQt${MO2_QT_VERSION_MAJOR}-Qt${MO2_QT_VERSION_MAJOR}==${MO2_QT_VERSION}) add_dependencies(runner-tests mobase) -set(pythoncore "${PYTHON_ROOT}/PCbuild/amd64/pythoncore") -set(pythoncorezip "${pythoncore}/python${Python_VERSION_SHORT}.zip") -set(PYTHONPATH "${PYLIB_DIR}\\;$\\;${pythoncore}\\;${pythoncorezip}") +set(PYTHONPATH "${PYLIB_DIR}\\;$\\;${Python_DLL_DIR}\\;${Python_LIB_DIR}") set_tests_properties(${runner-tests_gtests} PROPERTIES diff --git a/tests/runner/test_diagnose.cpp b/tests/runner/test_diagnose.cpp index b0a6152..467c9cb 100644 --- a/tests/runner/test_diagnose.cpp +++ b/tests/runner/test_diagnose.cpp @@ -5,9 +5,10 @@ #include +#include +#include + #include "MockOrganizer.h" -#include "iplugindiagnose.h" -#include "iplugingame.h" using namespace MOBase; diff --git a/tests/runner/test_filemapper.cpp b/tests/runner/test_filemapper.cpp index 7591177..5044283 100644 --- a/tests/runner/test_filemapper.cpp +++ b/tests/runner/test_filemapper.cpp @@ -5,9 +5,10 @@ #include +#include +#include + #include "MockOrganizer.h" -#include "ipluginfilemapper.h" -#include "iplugingame.h" using namespace MOBase; diff --git a/tests/runner/test_game.cpp b/tests/runner/test_game.cpp index 7e96d42..0d1d718 100644 --- a/tests/runner/test_game.cpp +++ b/tests/runner/test_game.cpp @@ -5,8 +5,9 @@ #include +#include + #include "MockOrganizer.h" -#include "iplugingame.h" using namespace MOBase; diff --git a/tests/runner/test_installer.cpp b/tests/runner/test_installer.cpp index a96ddf6..349c904 100644 --- a/tests/runner/test_installer.cpp +++ b/tests/runner/test_installer.cpp @@ -1,8 +1,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include + #include "MockOrganizer.h" -#include "iplugininstallersimple.h" #include "pythonrunner.h" #include diff --git a/tests/runner/test_iplugin.cpp b/tests/runner/test_iplugin.cpp index cadfa11..27c4829 100644 --- a/tests/runner/test_iplugin.cpp +++ b/tests/runner/test_iplugin.cpp @@ -1,8 +1,9 @@ -#include "gmock/gmock.h" -#include "gtest/gtest.h" +#include +#include + +#include #include "MockOrganizer.h" -#include "iplugin.h" #include "pythonrunner.h" #include @@ -34,7 +35,7 @@ TEST(IPlugin, Basic) EXPECT_EQ(settings.size(), 1); EXPECT_EQ(settings[0].key, "a setting"); EXPECT_EQ(settings[0].description, "the setting description"); - EXPECT_EQ(settings[0].defaultValue.userType(), QVariant::Type::Int); + EXPECT_EQ(settings[0].defaultValue.userType(), QMetaType::Type::Int); EXPECT_EQ(settings[0].defaultValue.toInt(), 12); // no translation, no custom implementation -> name() diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..db9eb08 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,34 @@ +{ + "dependencies": ["pybind11"], + "features": { + "testing": { + "description": "Build Plugin Python tests.", + "dependencies": ["gtest"] + }, + "standalone": { + "description": "Build Standalone.", + "dependencies": ["mo2-cmake", "mo2-uibase"] + } + }, + "vcpkg-configuration": { + "default-registry": { + "kind": "git", + "repository": "https://github.com/Microsoft/vcpkg", + "baseline": "294f76666c3000630d828703e675814c05a4fd43" + }, + "registries": [ + { + "kind": "git", + "repository": "https://github.com/Microsoft/vcpkg", + "baseline": "294f76666c3000630d828703e675814c05a4fd43", + "packages": ["boost*", "boost-*"] + }, + { + "kind": "git", + "repository": "https://github.com/ModOrganizer2/vcpkg-registry", + "baseline": "228cda39fe9d1eeed789c0ef64fd1235dab3b11e", + "packages": ["mo2-*", "pybind11", "spdlog"] + } + ] + } +}