diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ce8872d036c5..f794b27d63854 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,6 +178,8 @@ core_optional_dep(${optional_deps}) core_optional_dyload_dep(${dyload_optional}) core_require_dep(${required_deps}) +SET(PYTHON_VERSION 3.7) + if(ENABLE_MARIADBCLIENT AND NOT ENABLE_MARIADBCLIENT STREQUAL AUTO AND ENABLE_MYSQLCLIENT AND NOT ENABLE_MYSQLCLIENT STREQUAL AUTO) MESSAGE(FATAL_ERROR "You can not use MySql and MariaDB at the same time. Disable one by adding -DENABLE_MYSQLCLIENT=OFF or -DENABLE_MARIADBCLIENT=OFF.") elseif(ENABLE_MYSQLCLIENT AND NOT ENABLE_MYSQLCLIENT STREQUAL AUTO) diff --git a/addons/repository.xbmc.org/addon.xml b/addons/repository.xbmc.org/addon.xml index c431c0fbca9ed..c6128a4ba5402 100644 --- a/addons/repository.xbmc.org/addon.xml +++ b/addons/repository.xbmc.org/addon.xml @@ -8,10 +8,10 @@ - http://mirrors.kodi.tv/addons/leia/addons.xml.gz - http://mirrors.kodi.tv/addons/leia/addons.xml.gz?sha256 - https://mirrors.kodi.tv/addons/leia - http://mirrors.kodi.tv/addons/leia + http://mirrors.kodi.tv/addons/migration/addons.xml.gz + http://mirrors.kodi.tv/addons/migration/addons.xml.gz?sha256 + https://mirrors.kodi.tv/addons/migration + http://mirrors.kodi.tv/addons/migration sha256 diff --git a/cmake/cpack/deb/packages/kodi.txt.in b/cmake/cpack/deb/packages/kodi.txt.in index 4776622206ac3..78df46ae47d05 100644 --- a/cmake/cpack/deb/packages/kodi.txt.in +++ b/cmake/cpack/deb/packages/kodi.txt.in @@ -15,7 +15,7 @@ PACKAGE_ARCHITECTURE all PACKAGE_SECTION video PACKAGE_PRIORITY optional PACKAGE_SHLIBDEPS -PACKAGE_DEPENDS @APP_NAME_LC@-bin (>= @CPACK_DEBIAN_PACKAGE_VERSION@), @APP_NAME_LC@-bin (<< @CPACK_DEBIAN_PACKAGE_VERSION@.1~), curl, libcurl4 | libcurl3, mesa-utils, x11-utils, fonts-liberation | ttf-liberation, fonts-dejavu-core | ttf-dejavu-core, python-bluez | python-lightblue, python-imaging | python-pil, python-simplejson, libass9 | libass5 | libass4, libgif5 | libgif7, libnfs8 | libnfs4 | libnfs1, libbluray1 | libbluray2, libshairplay0, libvorbisfile3, libaacs0, libcec4, libgnutls30 | libgnutls-deb0-28 | libgnutls28 | libgnutls26, libxslt1.1 +PACKAGE_DEPENDS @APP_NAME_LC@-bin (>= @CPACK_DEBIAN_PACKAGE_VERSION@), @APP_NAME_LC@-bin (<< @CPACK_DEBIAN_PACKAGE_VERSION@.1~), curl, libcurl4 | libcurl3, mesa-utils, x11-utils, fonts-liberation | ttf-liberation, fonts-dejavu-core | ttf-dejavu-core, python3-pil, python3-simplejson, libass9 | libass5 | libass4, libgif5 | libgif7, libnfs8 | libnfs4 | libnfs1, libbluray1 | libbluray2, libshairplay0, libvorbisfile3, libaacs0, libcec4, libgnutls30 | libgnutls-deb0-28 | libgnutls28 | libgnutls26, libxslt1.1 PACKAGE_RECOMMENDS libvdpau1, libva-intel-vaapi-driver, libva1 PACKAGE_SUGGESTS @APP_NAME_LC@-pvr-mythtv, @APP_NAME_LC@-pvr-vuplus, @APP_NAME_LC@-pvr-vdr-vnsi, @APP_NAME_LC@-pvr-njoy, @APP_NAME_LC@-pvr-nextpvr, @APP_NAME_LC@-pvr-mediaportal-tvserver, @APP_NAME_LC@-pvr-tvheadend-hts, @APP_NAME_LC@-pvr-dvbviewer, @APP_NAME_LC@-pvr-argustv, @APP_NAME_LC@-pvr-iptvsimple, @APP_NAME_LC@-audioencoder-vorbis, @APP_NAME_LC@-audioencoder-flac, @APP_NAME_LC@-audioencoder-lame PACKAGE_BREAKS xbmc (<< 2:14.0~git20141019), xbmc-data, xbmc-standalone diff --git a/cmake/modules/FindPython.cmake b/cmake/modules/FindPython.cmake index 213b17c629378..6c78a77cbc6d3 100644 --- a/cmake/modules/FindPython.cmake +++ b/cmake/modules/FindPython.cmake @@ -6,12 +6,12 @@ # PYTHON_LIBRARIES - The python libraries if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_PYTHON python>=2.7 QUIET) + pkg_check_modules(PC_PYTHON python3>=3.5 QUIET) endif() -find_program(PYTHON_EXECUTABLE python ONLY_CMAKE_FIND_ROOT_PATH) -find_library(PYTHON_LIBRARY NAMES python2.7 PATHS ${PC_PYTHON_LIBDIR}) -find_path(PYTHON_INCLUDE_DIR NAMES Python.h PATHS ${PC_PYTHON_INCLUDE_DIRS} ${DEPENDS_PATH}/include/python2.7) +find_program(PYTHON_EXECUTABLE python3 ONLY_CMAKE_FIND_ROOT_PATH) +find_library(PYTHON_LIBRARY NAMES python3.7 python3.6 python3.5 PATHS ${PC_PYTHON_LIBDIR}) +find_path(PYTHON_INCLUDE_DIR NAMES Python.h PATHS ${PC_PYTHON_INCLUDE_DIRS}) if(KODI_DEPENDSBUILD) find_library(FFI_LIBRARY ffi REQUIRED) @@ -25,7 +25,7 @@ if(KODI_DEPENDSBUILD) set(PYTHON_LIBRARIES ${PYTHON_LIBRARY} ${FFI_LIBRARY} ${EXPAT_LIBRARY} ${INTL_LIBRARY} ${GMP_LIBRARY} ${PYTHON_DEP_LIBRARIES}) else() - find_package(PythonLibs 2.7 REQUIRED) + find_package(PythonLibs 3.5 REQUIRED) list(APPEND PYTHON_LIBRARIES ${PC_PYTHON_STATIC_LIBRARIES}) endif() diff --git a/cmake/scripts/android/Install.cmake b/cmake/scripts/android/Install.cmake index a121295f31055..a17f73bfa74c9 100644 --- a/cmake/scripts/android/Install.cmake +++ b/cmake/scripts/android/Install.cmake @@ -107,7 +107,7 @@ add_custom_target(bundle ${CMAKE_BINARY_DIR}/tools/android/packaging/media COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/tools/android/packaging/xbmc/res ${CMAKE_BINARY_DIR}/tools/android/packaging/xbmc/res - COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPENDS_PATH}/lib/python2.7 ${libdir}/python2.7 + COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPENDS_PATH}/lib/python${PYTHON_VERSION} ${libdir}/python${PYTHON_VERSION} COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPENDS_PATH}/share/${APP_NAME_LC} ${datadir}/${APP_NAME_LC} COMMAND ${CMAKE_COMMAND} -E copy $ ${libdir}/${APP_NAME_LC}/$) diff --git a/cmake/scripts/ios/Install.cmake b/cmake/scripts/ios/Install.cmake index 7d8de72b9c922..f7ffd6712a297 100644 --- a/cmake/scripts/ios/Install.cmake +++ b/cmake/scripts/ios/Install.cmake @@ -74,6 +74,7 @@ add_custom_command(TARGET ${APP_NAME_LC} POST_BUILD "FULL_PRODUCT_NAME=${APP_NAME}.app" "WRAPPER_EXTENSION=app" "SRCROOT=${CMAKE_BINARY_DIR}" + "PYTHON_VERSION=${PYTHON_VERSION}" ${CMAKE_SOURCE_DIR}/tools/darwin/Support/copyframeworks-ios.command COMMAND "XBMC_DEPENDS=${DEPENDS_PATH}" "NATIVEPREFIX=${NATIVEPREFIX}" diff --git a/cmake/scripts/osx/Install.cmake b/cmake/scripts/osx/Install.cmake index 77c771c9e1485..aca31b47c9b85 100644 --- a/cmake/scripts/osx/Install.cmake +++ b/cmake/scripts/osx/Install.cmake @@ -22,6 +22,7 @@ add_custom_target(bundle "APP_NAME=${APP_NAME}" "FULL_PRODUCT_NAME=${APP_NAME}.app" "SRCROOT=${CMAKE_BINARY_DIR}" + "PYTHON_VERSION=${PYTHON_VERSION}" ${CMAKE_SOURCE_DIR}/tools/darwin/Support/copyframeworks-osx.command) set_target_properties(bundle PROPERTIES FOLDER "Build Utilities") add_dependencies(bundle ${APP_NAME_LC}) diff --git a/cmake/scripts/windows/ArchSetup.cmake b/cmake/scripts/windows/ArchSetup.cmake index 032632c6a943c..3572371949a4e 100644 --- a/cmake/scripts/windows/ArchSetup.cmake +++ b/cmake/scripts/windows/ArchSetup.cmake @@ -35,7 +35,6 @@ set(MINGW_LIBS_DIR ${CMAKE_SOURCE_DIR}/${DEPS_FOLDER_RELATIVE}/mingwlibs/${ARCH} list(APPEND CMAKE_PREFIX_PATH ${MINGW_LIBS_DIR}) list(APPEND CMAKE_LIBRARY_PATH ${MINGW_LIBS_DIR}/bin) list(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}) -set(PYTHON_INCLUDE_DIR ${DEPENDENCIES_DIR}/include/python) # -------- Compiler options --------- @@ -74,7 +73,7 @@ link_directories(${DEPENDENCIES_DIR}/lib) # Additional libraries list(APPEND DEPLIBS bcrypt.lib d3d11.lib DInput8.lib DSound.lib winmm.lib Mpr.lib Iphlpapi.lib WS2_32.lib - PowrProf.lib setupapi.lib Shlwapi.lib dwmapi.lib dxguid.lib DelayImp.lib) + PowrProf.lib setupapi.lib Shlwapi.lib dwmapi.lib dxguid.lib DelayImp.lib Mincore.lib) # NODEFAULTLIB option set(_nodefaultlibs_RELEASE libcmt) diff --git a/project/BuildDependencies/downloads/python3-3.7.1-Win32-v141.7z b/project/BuildDependencies/downloads/python3-3.7.1-Win32-v141.7z new file mode 100644 index 0000000000000..ab614cb7d23c7 Binary files /dev/null and b/project/BuildDependencies/downloads/python3-3.7.1-Win32-v141.7z differ diff --git a/project/BuildDependencies/downloads/python3-3.7.1-x64-v141.7z b/project/BuildDependencies/downloads/python3-3.7.1-x64-v141.7z new file mode 100644 index 0000000000000..2b49ee4dddfc6 Binary files /dev/null and b/project/BuildDependencies/downloads/python3-3.7.1-x64-v141.7z differ diff --git a/project/BuildDependencies/scripts/0_package.target-win10-arm.list b/project/BuildDependencies/scripts/0_package.target-win10-arm.list index 3b3ebc4bee9b5..952c2c0ab6de9 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-arm.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-arm.list @@ -31,9 +31,6 @@ mini_wdk-10.0.14393.0-win32.7z mysql-connector-c-6.1.9-win10-ARM-v141.7z openssl-1.0.2o-win10-ARM-v141.7z pcre-8.40-win10-ARM-v141.7z -pillow-4.2.1-v1-win10-ARM-v141.7z -pycryptodome-3.4.7-v1-win10-ARM-v140.7z -python-2.7.14-v2-win10-ARM-v141.7z rapidjson-1.1.0-win32.7z shairplay-ce80e00-win10-ARM-v140.7z sqlite-3170000-win10-ARM-v140.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win10-win32.list b/project/BuildDependencies/scripts/0_package.target-win10-win32.list index d4a5115d08156..80f6a9e9ab872 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-win32.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-win32.list @@ -31,9 +31,6 @@ mini_wdk-10.0.14393.0-win32.7z mysql-connector-c-6.1.9-win10-Win32-v141.7z openssl-1.0.2o-win10-Win32-v141.7z pcre-8.40-win10-Win32-v141.7z -pillow-4.2.1-v1-win10-Win32-v141.7z -pycryptodome-3.4.7-v1-win10-Win32-v140.7z -python-2.7.14-v2-win10-Win32-v141.7z rapidjson-1.1.0-win32.7z shairplay-ce80e00-win10-Win32-v140.7z sqlite-3170000-win10-Win32-v140.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win10-x64.list b/project/BuildDependencies/scripts/0_package.target-win10-x64.list index 9642427c14a4e..f6363617c0b88 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-x64.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-x64.list @@ -31,9 +31,6 @@ mini_wdk-10.0.14393.0-win32.7z mysql-connector-c-6.1.9-win10-x64-v141.7z openssl-1.0.2o-win10-x64-v141.7z pcre-8.40-win10-x64-v141.7z -pillow-4.2.1-v1-win10-x64-v141.7z -pycryptodome-3.4.7-v1-win10-x64-v140.7z -python-2.7.14-v2-win10-x64-v141.7z rapidjson-1.1.0-win32.7z shairplay-ce80e00-win10-x64-v140.7z sqlite-3170000-win10-x64-v140.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win32.list b/project/BuildDependencies/scripts/0_package.target-win32.list index 1abe21cd5b794..b9306e07f2e8f 100644 --- a/project/BuildDependencies/scripts/0_package.target-win32.list +++ b/project/BuildDependencies/scripts/0_package.target-win32.list @@ -36,9 +36,7 @@ mini_wdk-10.0.14393.0-win32.7z mysql-connector-c-6.1.6-win32-vc140-v2.7z openssl-1.0.2g-win32-vc140-v2.7z pcre-8.37-win32-vc140-v3.7z -pillow-3.1.0-win32-vc140.7z -pycryptodome-3.4.3-win32.7z -python-2.7.13-win32-vc140-v3.7z +python3-3.7.1-Win32-v141.7z rapidjson-1.1.0-win32.7z shairplay-0.9.0-win32-vc140-v2.7z sqlite-3.10.2-win32-vc140.7z diff --git a/project/BuildDependencies/scripts/0_package.target-x64.list b/project/BuildDependencies/scripts/0_package.target-x64.list index 0811a07218f8d..2805de38f79eb 100644 --- a/project/BuildDependencies/scripts/0_package.target-x64.list +++ b/project/BuildDependencies/scripts/0_package.target-x64.list @@ -33,9 +33,7 @@ mini_wdk-10.0.14393.0-x64.7z mariadb-connector-c-3.0.6-x64-v141.7z openssl-1.1.1-x64-v141.7z pcre-8.40-x64-vc140.7z -pillow-4.2.1-x64-vc140.zip -pycryptodome-3.4.7-x64-vc140.zip -python-2.7.13-x64-vc140-v3.7z +python3-3.7.1-x64-v141.7z rapidjson-1.1.0-win32.7z shairplay-ce80e00-x64-vc140.7z sqlite-3.17.0-x64-vc140.7z diff --git a/tools/android/packaging/Makefile.in b/tools/android/packaging/Makefile.in index 07776ce320a83..046cad3d8c50b 100644 --- a/tools/android/packaging/Makefile.in +++ b/tools/android/packaging/Makefile.in @@ -115,9 +115,9 @@ sharedobb: shared @echo "$(CMAKE_SOURCE_DIR)/main.@APP_NAME_LC@.obb created" python: | xbmc/assets - mkdir -p xbmc/assets/python2.7/lib/ - cp -rfp $(PREFIX)/lib/python2.7 xbmc/assets/python2.7/lib/ - cd xbmc/assets/python2.7/lib/python2.7/; rm -rf test config lib-dynload + mkdir -p xbmc/assets/python@PYTHON_VERSION@/lib/ + cp -rfp $(PREFIX)/lib/python@PYTHON_VERSION@ xbmc/assets/python@PYTHON_VERSION@/lib/ + cd xbmc/assets/python@PYTHON_VERSION@/lib/python@PYTHON_VERSION@/; rm -rf test config lib-dynload res: mkdir -p xbmc/res xbmc/res/raw xbmc/res/values images @@ -138,7 +138,7 @@ res: libs: $(PREFIX)/lib/@APP_NAME_LC@/lib@APP_NAME_LC@.so rm -rf xbmc/lib/$(CPU) xbmc/obj/local/$(CPU) - mkdir -p xbmc/lib/$(CPU) xbmc/assets/python2.7/lib/ xbmc/obj/local/$(CPU) + mkdir -p xbmc/lib/$(CPU) xbmc/assets/python@PYTHON_VERSION@/lib/ xbmc/obj/local/$(CPU) cp -fpL $(SRCLIBS) xbmc/obj/local/$(CPU)/ cp -fp $(PREFIX)/lib/@APP_NAME_LC@/lib@APP_NAME_LC@.so xbmc/obj/local/$(CPU)/ find $(PREFIX)/lib/@APP_NAME_LC@/addons -name "*.so" -exec cp -fp {} xbmc/obj/local/$(CPU)/ \; || true @@ -146,7 +146,7 @@ libs: $(PREFIX)/lib/@APP_NAME_LC@/lib@APP_NAME_LC@.so find $(DEPENDS_PATH)/share/kodi/addons -name "*.so" -exec cp -fp {} xbmc/obj/local/$(CPU)/ \; || true find $(DEPENDS_PATH)/lib/kodi/addons -name "*.so" -exec cp -fp {} xbmc/obj/local/$(CPU)/ \; || true find $(PREFIX)/lib/@APP_NAME_LC@/system -name "*.so" -exec cp -fp {} xbmc/obj/local/$(CPU)/ \; - DIR=${CURDIR}; cd $(PREFIX)/lib/python2.7/site-packages; for i in `find Cryptodome -name \*.so` ; do FN=`echo $$i | cut -c1- | tr "/" "_"` ; mv $$i $$DIR/xbmc/obj/local/$(CPU)/$$FN ; done + DIR=${CURDIR}; cd $(PREFIX)/lib/python@PYTHON_VERSION@/site-packages; for i in `find Cryptodome -name \*.so` ; do FN=`echo $$i | cut -c1- | tr "/" "_"` ; mv $$i $$DIR/xbmc/obj/local/$(CPU)/$$FN ; done cd xbmc/obj/local/$(CPU)/; find . -name "*.so" -not -name "lib*.so" | sed "s/\.\///" | xargs -I@ mv @ lib@ cp -fp xbmc/obj/local/$(CPU)/*.so xbmc/lib/$(CPU)/ $(STRIP) --strip-unneeded xbmc/lib/$(CPU)/*.so diff --git a/tools/android/packaging/xbmc/src/Splash.java.in b/tools/android/packaging/xbmc/src/Splash.java.in index 4cf3345b711f8..6b0ec1a4967f3 100644 --- a/tools/android/packaging/xbmc/src/Splash.java.in +++ b/tools/android/packaging/xbmc/src/Splash.java.in @@ -416,7 +416,7 @@ public class Splash extends Activity if (!(sName.startsWith("assets/") || (mInstallLibs && sName.startsWith("lib/")))) continue; - if (sName.startsWith("assets/python2.7")) + if (sName.startsWith("assets/python")) continue; String sFullPath = null; diff --git a/tools/darwin/Support/copyframeworks-ios.command b/tools/darwin/Support/copyframeworks-ios.command index d52033ebf931a..6fe7245eac307 100755 --- a/tools/darwin/Support/copyframeworks-ios.command +++ b/tools/darwin/Support/copyframeworks-ios.command @@ -74,14 +74,14 @@ for a in $(otool -L "$TARGET_BINARY" | grep "$EXTERNAL_LIBS\|$DYLIB_NAMEPATH" | install_name_tool -change "$a" "$DYLIB_NAMEPATH/$(basename $a)" "$TARGET_BINARY" done -echo "Package $EXTERNAL_LIBS/lib/python2.7" +echo "Package $EXTERNAL_LIBS/lib/python$PYTHON_VERSION" mkdir -p "$TARGET_CONTENTS/Frameworks/lib" PYTHONSYNC="rsync -aq --exclude .DS_Store --exclude *.a --exclude *.exe --exclude test --exclude tests" -${PYTHONSYNC} "$EXTERNAL_LIBS/lib/python2.7" "$TARGET_FRAMEWORKS/lib/" -rm -rf "$TARGET_FRAMEWORKS/lib/python2.7/config" +${PYTHONSYNC} "$EXTERNAL_LIBS/lib/python$PYTHON_VERSION" "$TARGET_FRAMEWORKS/lib/" +rm -rf "$TARGET_FRAMEWORKS/lib/python$PYTHON_VERSION/config" echo "Checking python *.so for dylib dependencies" -check_xbmc_dylib_depends "$TARGET_FRAMEWORKS"/lib/python2.7 "*.so" +check_xbmc_dylib_depends "$TARGET_FRAMEWORKS"/lib/python$PYTHON_VERSION "*.so" echo "Checking system *.so for dylib dependencies" check_xbmc_dylib_depends "$XBMC_HOME"/system "*.so" diff --git a/tools/darwin/Support/copyframeworks-osx.command b/tools/darwin/Support/copyframeworks-osx.command index 7f1e6a510cc87..9ef7d28fc8abf 100755 --- a/tools/darwin/Support/copyframeworks-osx.command +++ b/tools/darwin/Support/copyframeworks-osx.command @@ -81,14 +81,14 @@ for a in $(otool -LX "$TARGET_BINARY" | grep "$EXTERNAL_LIBS" | awk ' { print $ install_name_tool -change "$a" "$DYLIB_NAMEPATH/$(basename $a)" "$TARGET_BINARY" done -echo "Package $EXTERNAL_LIBS/lib/python2.7" +echo "Package $EXTERNAL_LIBS/lib/python$PYTHON_VERSION" mkdir -p "$TARGET_CONTENTS/Libraries/lib" PYTHONSYNC="rsync -aq --exclude .DS_Store --exclude *.a --exclude *.exe --exclude test --exclude tests" -${PYTHONSYNC} "$EXTERNAL_LIBS/lib/python2.7" "$TARGET_FRAMEWORKS/lib/" -rm -rf "$TARGET_FRAMEWORKS/lib/python2.7/config" +${PYTHONSYNC} "$EXTERNAL_LIBS/lib/python$PYTHON_VERSION" "$TARGET_FRAMEWORKS/lib/" +rm -rf "$TARGET_FRAMEWORKS/lib/python$PYTHON_VERSION/config" -echo "Checking $TARGET_FRAMEWORKS/lib/python2.7 *.so for dylib dependencies" -check_xbmc_dylib_depends "$TARGET_FRAMEWORKS"/lib/python2.7 "*.so" +echo "Checking $TARGET_FRAMEWORKS/lib/python$PYTHON_VERSION *.so for dylib dependencies" +check_xbmc_dylib_depends "$TARGET_FRAMEWORKS"/lib/python$PYTHON_VERSION "*.so" echo "Checking $XBMC_HOME/system *.so for dylib dependencies" check_xbmc_dylib_depends "$XBMC_HOME"/system "*.so" diff --git a/tools/depends/native/Makefile b/tools/depends/native/Makefile index ba5b8eba8d4d7..42131704dbd55 100644 --- a/tools/depends/native/Makefile +++ b/tools/depends/native/Makefile @@ -6,7 +6,7 @@ endif NATIVE= m4-native gettext-native autoconf-native automake-native \ libtool-native pkg-config-native yasm-native cmake-native \ - gas-preprocessor-native python27-native zlib-native \ + gas-preprocessor-native libffi-native python3-native zlib-native \ pcre-native swig-native \ libpng-native libjpeg-turbo-native liblzo2-native giflib-native \ distribute-native distutilscross-native JsonSchemaBuilder TexturePacker \ @@ -23,7 +23,7 @@ endif ifeq ($(OS),linux) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),raspberry-pi aml gbm)) - NATIVE += meson-native ninja-native python3-native + NATIVE += meson-native ninja-native endif endif @@ -46,11 +46,10 @@ libpng-native: zlib-native meson-native: python3-native ninja-native: python3-native swig-native: pcre-native -distribute-native: python27-native -distutilscross-native: python27-native distribute-native +distribute-native: python3-native +distutilscross-native: python3-native distribute-native tar-native: xz-native automake-native -python27-native: zlib-native -python3-native: $(EXPAT) zlib-native +python3-native: $(EXPAT) libffi-native zlib-native wayland-scanner-native: expat-native waylandpp-scanner-native: cmake-native diff --git a/tools/depends/native/distribute-native/Makefile b/tools/depends/native/distribute-native/Makefile index e9aced11d21f7..ee7ea71a59d07 100644 --- a/tools/depends/native/distribute-native/Makefile +++ b/tools/depends/native/distribute-native/Makefile @@ -19,7 +19,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) .installed-$(PLATFORM): $(PLATFORM) - cd $(PLATFORM); $(PREFIX)/bin/python setup.py install --prefix=$(PREFIX) + cd $(PLATFORM); $(PREFIX)/bin/python3 setup.py install --prefix=$(PREFIX) touch $@ clean: diff --git a/tools/depends/native/distutilscross-native/Makefile b/tools/depends/native/distutilscross-native/Makefile index 987b43b37c565..9ed0478d93756 100644 --- a/tools/depends/native/distutilscross-native/Makefile +++ b/tools/depends/native/distutilscross-native/Makefile @@ -1,7 +1,7 @@ include ../../Makefile.include PREFIX=$(NATIVEPREFIX) PLATFORM=$(NATIVEPLATFORM) -DEPS= ../../Makefile.include Makefile +DEPS= ../../Makefile.include Makefile python3.patch # lib name, version LIBNAME=distutilscross @@ -17,9 +17,10 @@ $(TARBALLS_LOCATION)/$(ARCHIVE): $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 -i ../python3.patch .installed-$(PLATFORM): $(PLATFORM) - cd $(PLATFORM); $(PREFIX)/bin/python setup.py install --prefix=$(PREFIX) + cd $(PLATFORM); $(PREFIX)/bin/python3 setup.py install --prefix=$(PREFIX) touch $@ clean: diff --git a/tools/depends/native/distutilscross-native/python3.patch b/tools/depends/native/distutilscross-native/python3.patch new file mode 100644 index 0000000000000..6e1059d223e2f --- /dev/null +++ b/tools/depends/native/distutilscross-native/python3.patch @@ -0,0 +1,11 @@ +--- a/distutilscross/crosscompile.py ++++ b/distutilscross/crosscompile.py +@@ -32,7 +32,7 @@ + _get_python_lib = sysconfig.get_python_lib + def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): + if os.environ.has_key('PYTHONXCPREFIX'): +- print "Setting prefix" ++ print("Setting prefix") + prefix = os.environ['PYTHONXCPREFIX'] + + return _get_python_lib(plat_specific, standard_lib, prefix) diff --git a/tools/depends/native/expat-native/Makefile b/tools/depends/native/expat-native/Makefile index c6574b606631a..8a0ad30070855 100644 --- a/tools/depends/native/expat-native/Makefile +++ b/tools/depends/native/expat-native/Makefile @@ -10,7 +10,7 @@ SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.bz2 # configuration settings -CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) ./conftools; ./configure --prefix=$(PREFIX) --disable-shared +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) ./conftools; CFLAGS="-fPIC" ./configure --prefix=$(PREFIX) --disable-shared LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).a diff --git a/tools/depends/native/python27-native/Makefile b/tools/depends/native/libffi-native/Makefile similarity index 51% rename from tools/depends/native/python27-native/Makefile rename to tools/depends/native/libffi-native/Makefile index 1854dac7307a8..462bc6e4c7923 100644 --- a/tools/depends/native/python27-native/Makefile +++ b/tools/depends/native/libffi-native/Makefile @@ -1,21 +1,19 @@ include ../../Makefile.include +PREFIX=$(NATIVEPREFIX) PLATFORM=$(NATIVEPLATFORM) DEPS= ../../Makefile.include Makefile # lib name, version -LIBNAME=Python -VERSION=2.7.15 +LIBNAME=libffi +VERSION=3.2.1 SOURCE=$(LIBNAME)-$(VERSION) -ARCHIVE=$(SOURCE).tar.xz -CWD=$(shell pwd) -HOSTPYTHONDIR=$(CWD)/$(PLATFORM)/hostpython +ARCHIVE=$(SOURCE).tar.gz -CONFIGURE=./configure --prefix=$(NATIVEPREFIX) --disable-shared --disable-toolbox-glue --disable-framework +# configuration settings +CONFIGURE= CFLAGS="-fPIC" ./configure --prefix=$(NATIVEPREFIX) --disable-shared --disable-builddir -LIBDYLIB=$(PLATFORM)/python -ifeq ($(NATIVE_OS), osx) - LIBDYLIB=$(PLATFORM)/python.exe -endif + +LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME).a all: .installed-$(PLATFORM) @@ -23,22 +21,23 @@ $(TARBALLS_LOCATION)/$(ARCHIVE): cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) - rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) cd $(PLATFORM); $(CONFIGURE) $(LIBDYLIB): $(PLATFORM) - cd $(PLATFORM); $(MAKE) regen-grammar - cd $(PLATFORM); $(MAKE) + $(MAKE) -j 1 -C $(PLATFORM) + touch $@ .installed-$(PLATFORM): $(LIBDYLIB) - cd $(PLATFORM); $(MAKE) install - install $(PLATFORM)/Parser/pgen $(NATIVEPREFIX)/bin - touch $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + mkdir -p $(NATIVEPREFIX)/include/ffi + cp $(NATIVEPREFIX)/lib/$(SOURCE)/include/* $(NATIVEPREFIX)/include/ffi/ touch $@ clean: - rm -rf $(PLATFORM) .installed-$(PLATFORM) + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) distclean:: rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/depends/native/python3-native/Makefile b/tools/depends/native/python3-native/Makefile index 5902fb8692d4f..50570ca8bb260 100644 --- a/tools/depends/native/python3-native/Makefile +++ b/tools/depends/native/python3-native/Makefile @@ -4,15 +4,19 @@ DEPS= ../../Makefile.include Makefile # lib name, version LIBNAME=Python -VERSION=3.6.4 +VERSION=3.7.2 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.xz +CWD=$(shell pwd) +HOSTPYTHONDIR=$(CWD)/$(PLATFORM)/hostpython +BASE_URL=https://www.python.org/ftp/python/$(VERSION) -CONFIGURE=./configure --prefix=$(NATIVEPREFIX) --disable-shared --disable-framework --without-ensurepip --without-pymalloc +CONFIGURE=./configure --prefix=$(NATIVEPREFIX) --disable-shared --disable-framework --without-pymalloc ifeq ($(TARGET_PLATFORM),wayland) CONFIGURE += --with-system-expat endif + LIBDYLIB=$(PLATFORM)/python ifeq ($(NATIVE_OS), osx) LIBDYLIB=$(PLATFORM)/python.exe @@ -29,10 +33,12 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) cd $(PLATFORM); $(CONFIGURE) $(LIBDYLIB): $(PLATFORM) + cd $(PLATFORM); $(MAKE) regen-grammar cd $(PLATFORM); $(MAKE) .installed-$(PLATFORM): $(LIBDYLIB) cd $(PLATFORM); $(MAKE) install + install $(PLATFORM)/Parser/pgen $(NATIVEPREFIX)/bin touch $(LIBDYLIB) touch $@ diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile index 9c8d7dd361ae0..3cd7d94665e91 100644 --- a/tools/depends/target/Makefile +++ b/tools/depends/target/Makefile @@ -10,7 +10,7 @@ DEPENDS = \ openssl gmp nettle gnutls curl nghttp2 \ libjpeg-turbo libpng fribidi libass \ libxml2 rapidjson libmicrohttpd mariadb libffi \ - python27 libshairplay libfmt \ + python3 libshairplay libfmt \ libplist libcec libbluray tinyxml \ taglib libusb libnfs \ pythonmodule-pil pythonmodule-pycryptodome pythonmodule-setuptools \ @@ -93,7 +93,7 @@ fontconfig: freetype2 expat $(ICONV) curl: openssl nghttp2 libass: fontconfig fribidi libpng freetype2 expat $(ICONV) libmicrohttpd: gnutls libgcrypt libgpg-error -python27: expat gettext libxml2 sqlite3 openssl libffi +python3: expat gettext libxml2 sqlite3 openssl libffi libcdio: $(ICONV) libcdio-gplv3: $(ICONV) libplist: $(ZLIB) @@ -104,9 +104,9 @@ libpng: $(ZLIB) openssl: $(ZLIB) gnutls: nettle $(ZLIB) nettle: gmp -pythonmodule-pycryptodome: $(PYMODULE_DEPS) python27 pythonmodule-setuptools -pythonmodule-pil: bzip2 $(PYMODULE_DEPS) $(ZLIB) libjpeg-turbo libpng freetype2 python27 pythonmodule-setuptools -pythonmodule-setuptools: $(PYMODULE_DEPS) python27 +pythonmodule-pycryptodome: $(PYMODULE_DEPS) python3 pythonmodule-setuptools +pythonmodule-pil: bzip2 $(PYMODULE_DEPS) $(ZLIB) libjpeg-turbo libpng freetype2 python3 pythonmodule-setuptools +pythonmodule-setuptools: $(PYMODULE_DEPS) python3 libxslt: libgcrypt libxml2 ffmpeg: $(ICONV) $(ZLIB) bzip2 $(FFMPEG_DEPENDS) libcec: p8-platform diff --git a/tools/depends/target/config.site.in b/tools/depends/target/config.site.in index 36bf2fced25c2..2842797425bc3 100644 --- a/tools/depends/target/config.site.in +++ b/tools/depends/target/config.site.in @@ -34,7 +34,7 @@ LIBGCRYPT_CONFIG=@prefix@/@deps_dir@/bin/libgcrypt-config PATH=@prefix@/@tool_dir@/bin:@use_toolchain@/usr/bin:@use_toolchain@/bin:$PATH LD_LIBRARY_PATH=@prefix@/@tool_dir@/lib:$LD_LIBRARY_PATH -PYTHON_VERSION=2.7 +PYTHON_VERSION=3.7 PYTHON_LDFLAGS="-L@prefix@/@deps_dir@/lib -L@prefix@/@deps_dir@/lib64 -lpython${PYTHON_VERSION} -lc -ldl -lm -lexpat -lffi -lintl -lutil -lssl -lcrypto" PYTHON_CPPFLAGS=-I@prefix@/@deps_dir@/include/python${PYTHON_VERSION} PYTHON_SITE_PKG=@prefix@/@deps_dir@/lib/python${PYTHON_VERSION}/site-packages @@ -151,7 +151,10 @@ if test "@platform_os@" = "ios"; then # in 10.12 but will get wrongly detected if building on 10.11 ac_cv_search_clock_gettime=no ac_cv_func_clock_gettime=no + ac_cv_func_clock_settime=no + ac_cv_func_futimens=no ac_cv_func_getentropy=no + ac_cv_func_utimensat=no # tweaks for libffi if test "${PACKAGE_NAME}" = "libffi" ; then diff --git a/tools/depends/target/python27/android-binmodule.patch b/tools/depends/target/python27/android-binmodule.patch deleted file mode 100644 index ec767a2ac1bb2..0000000000000 --- a/tools/depends/target/python27/android-binmodule.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/Python/dynload_shlib.c -+++ b/Python/dynload_shlib.c -@@ -112,10 +112,6 @@ - dlopenflags = PyThreadState_GET()->interp->dlopenflags; - #endif - -- if (Py_VerboseFlag) -- PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname, -- dlopenflags); -- - #ifdef __VMS - /* VMS currently don't allow a pathname, use a logical name instead */ - /* Concatenate 'python_module_' and shortname */ -@@ -125,8 +121,17 @@ - PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s", - shortname); - pathname = pathbuf; -+#elif defined(ANDROID) -+ /* Android does not allow a pathname and wants lib*.so */ -+ PyOS_snprintf(pathbuf, sizeof(pathbuf), "lib%-.200s.so", -+ shortname); -+ pathname = pathbuf; - #endif - -+ if (Py_VerboseFlag) -+ PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname, -+ dlopenflags); -+ - handle = dlopen(pathname, dlopenflags); - - if (handle == NULL) { diff --git a/tools/depends/target/python27/android-nl_langinfo.patch b/tools/depends/target/python27/android-nl_langinfo.patch deleted file mode 100644 index e3fec4a8d7ea1..0000000000000 --- a/tools/depends/target/python27/android-nl_langinfo.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/Python/pythonrun.c -+++ b/Python/pythonrun.c -@@ -301,7 +301,7 @@ - overridden = 1; - } - --#if defined(Py_USING_UNICODE) && defined(HAVE_LANGINFO_H) && defined(CODESET) -+#if defined(Py_USING_UNICODE) && defined(HAVE_LANGINFO_H) && defined(HAVE_NL_LANGINFO) && defined(CODESET) - /* On Unix, set the file system encoding according to the - user's preference, if the CODESET names a well-known - Python codec, and Py_FileSystemDefaultEncoding isn't ---- a/configure.ac -+++ b/configure.ac -@@ -3114,7 +3114,7 @@ - getentropy \ - getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ - initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime mmap \ -- mremap nice pathconf pause plock poll pthread_init \ -+ mremap nice nl_langinfo pathconf pause plock poll pthread_init \ - putenv readlink realpath \ - select sem_open sem_timedwait sem_getvalue sem_unlink setegid seteuid \ - setgid \ diff --git a/tools/depends/target/python27/android.patch b/tools/depends/target/python27/android.patch deleted file mode 100644 index 6c0386f5e4e97..0000000000000 --- a/tools/depends/target/python27/android.patch +++ /dev/null @@ -1,59 +0,0 @@ ---- a/Modules/posixmodule.c -+++ b/Modules/posixmodule.c -@@ -3991,7 +3991,7 @@ - slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ - if (slave_fd < 0) - return posix_error(); --#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) -+#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) && !defined(ANDROID) - ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ - ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ - #ifndef __hpux ---- a/Modules/pwdmodule.c -+++ b/Modules/pwdmodule.c -@@ -68,14 +68,14 @@ - #define SETS(i,val) sets(v, i, val) - - SETS(setIndex++, p->pw_name); --#ifdef __VMS -+#if defined __VMS || defined(ANDROID) - SETS(setIndex++, ""); - #else - SETS(setIndex++, p->pw_passwd); - #endif - PyStructSequence_SET_ITEM(v, setIndex++, _PyInt_FromUid(p->pw_uid)); - PyStructSequence_SET_ITEM(v, setIndex++, _PyInt_FromGid(p->pw_gid)); --#ifdef __VMS -+#if defined __VMS || defined(ANDROID) - SETS(setIndex++, ""); - #else - SETS(setIndex++, p->pw_gecos); ---- a/Modules/termios.c -+++ b/Modules/termios.c -@@ -230,6 +230,7 @@ - return Py_None; - } - -+#if !defined(ANDROID) - PyDoc_STRVAR(termios_tcdrain__doc__, - "tcdrain(fd) -> None\n\ - \n\ -@@ -249,6 +250,7 @@ - Py_INCREF(Py_None); - return Py_None; - } -+#endif - - PyDoc_STRVAR(termios_tcflush__doc__, - "tcflush(fd, queue) -> None\n\ -@@ -304,8 +306,10 @@ - METH_VARARGS, termios_tcsetattr__doc__}, - {"tcsendbreak", termios_tcsendbreak, - METH_VARARGS, termios_tcsendbreak__doc__}, -+#if !defined(ANDROID) - {"tcdrain", termios_tcdrain, - METH_VARARGS, termios_tcdrain__doc__}, -+#endif - {"tcflush", termios_tcflush, - METH_VARARGS, termios_tcflush__doc__}, - {"tcflow", termios_tcflow, diff --git a/tools/depends/target/python27/crosscompile.patch b/tools/depends/target/python27/crosscompile.patch deleted file mode 100644 index 5e33c1e8290b1..0000000000000 --- a/tools/depends/target/python27/crosscompile.patch +++ /dev/null @@ -1,138 +0,0 @@ ---- a/Makefile.pre.in -+++ b/Makefile.pre.in -@@ -240,6 +240,7 @@ - ########################################################################## - # Parser - PGEN= Parser/pgen$(EXE) -+PGEN_FOR_BUILD=$(NATIVE_PGEN) - - PSRCS= \ - Parser/acceler.c \ -@@ -523,9 +524,9 @@ - *\ -s*|s*) quiet="-q";; \ - *) quiet="";; \ - esac; \ -- $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ -+ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ -- $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build -+ PYTHONXCPREFIX='$(DESTDIR)$(prefix)' $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build - - # Build static library - # avoid long command lines, same as LIBRARY_OBJS -@@ -1131,12 +1132,12 @@ - $(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \ - $(DESTDIR)$(LIBDEST)/distutils/tests ; \ - fi -- PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ -+ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - $(PYTHON_FOR_BUILD) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ - -d $(LIBDEST) -f \ - -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ - $(DESTDIR)$(LIBDEST) -- PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ -+ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - $(PYTHON_FOR_BUILD) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ - -d $(LIBDEST) -f \ - -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ -@@ -1264,11 +1265,13 @@ - # Install the dynamically loadable modules - # This goes into $(exec_prefix) - sharedinstall: sharedmods -+ CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ -+ --skip-build \ - --prefix=$(prefix) \ -- --install-scripts=$(BINDIR) \ -- --install-platlib=$(DESTSHARED) \ -- --root=$(DESTDIR)/ -+ --install-scripts=$(DESTDIR)$(BINDIR) \ -+ --install-platlib=$(DESTDIR)$(DESTSHARED) \ -+ --root=/ - -rm $(DESTDIR)$(DESTSHARED)/_sysconfigdata.py* - - # Here are a couple of targets for MacOSX again, to install a full ---- a/configure.ac -+++ b/configure.ac -@@ -343,7 +343,6 @@ - *) - # for now, limit cross builds to known configurations - MACHDEP="unknown" -- AC_MSG_ERROR([cross build not supported for $host]) - esac - ac_sys_release= - else -@@ -389,7 +388,6 @@ - *) - # for now, limit cross builds to known configurations - MACHDEP="unknown" -- AC_MSG_ERROR([cross build not supported for $host]) - esac - _PYTHON_HOST_PLATFORM="$MACHDEP${_host_cpu:+-$_host_cpu}" - fi ---- a/setup.py -+++ b/setup.py -@@ -17,7 +17,7 @@ - from distutils.command.install_lib import install_lib - from distutils.spawn import find_executable - --cross_compiling = "_PYTHON_HOST_PLATFORM" in os.environ -+cross_compiling = ("_PYTHON_HOST_PLATFORM" in os.environ) or ('CROSS_COMPILE_TARGET' in os.environ) - - def get_platform(): - # cross build -@@ -178,6 +178,7 @@ - - def build_extensions(self): - -+ return - # Detect which modules should be compiled - missing = self.detect_modules() - -@@ -342,6 +343,9 @@ - - # Don't try to load extensions for cross builds - if cross_compiling: -+ self.announce( -+ 'WARNING: skipping import check for cross-compiled: "%s"' % -+ ext.name) - return - - try: -@@ -496,7 +500,7 @@ - for directory in reversed(options.dirs): - add_dir_to_list(dir_list, directory) - -- if os.path.normpath(sys.prefix) != '/usr' \ -+ if os.path.normpath(sys.prefix) != '/usr' and not cross_compiling \ - and not sysconfig.get_config_var('PYTHONFRAMEWORK'): - # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework - # (PYTHONFRAMEWORK is set) to avoid # linking problems when -@@ -572,6 +576,11 @@ - if host_platform in ['darwin', 'beos']: - math_libs = [] - -+ # Insert libraries and headers from embedded root file system (RFS) -+ #if 'CROSS_COMPILE_TARGET' in os.environ: -+ # lib_dirs += [os.environ['RFS'] + '/usr/lib'] -+ # inc_dirs += [os.environ['RFS'] + '/usr/include'] -+ - # XXX Omitted modules: gl, pure, dl, SGI-specific modules - - # -@@ -2043,8 +2052,13 @@ - - # Pass empty CFLAGS because we'll just append the resulting - # CFLAGS to Python's; -g or -O2 is to be avoided. -- cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \ -- % (ffi_builddir, ffi_srcdir, " ".join(config_args)) -+ if cross_compiling: -+ cmd = "cd %s && env CFLAGS='' '%s/configure' --host=%s --build=%s %s" \ -+ % (ffi_builddir, ffi_srcdir, os.environ.get('HOSTARCH'), -+ os.environ.get('BUILDARCH'), " ".join(config_args)) -+ else: -+ cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \ -+ % (ffi_builddir, ffi_srcdir, " ".join(config_args)) - - res = os.system(cmd) - if res or not os.path.exists(ffi_configfile): diff --git a/tools/depends/target/python27/no-export-path.patch b/tools/depends/target/python27/no-export-path.patch deleted file mode 100644 index 95e295240aece..0000000000000 --- a/tools/depends/target/python27/no-export-path.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/Makefile.pre.in -+++ b/Makefile.pre.in -@@ -1159,8 +1159,6 @@ - $(srcdir)/Lib/$(PLATDIR): - mkdir $(srcdir)/Lib/$(PLATDIR) - cp $(srcdir)/Lib/plat-generic/regen $(srcdir)/Lib/$(PLATDIR)/regen -- export PATH; PATH="`pwd`:$$PATH"; \ -- export PYTHONPATH; PYTHONPATH="$(srcdir)/Lib:$(abs_builddir)/`cat pybuilddir.txt`"; \ - export DYLD_FRAMEWORK_PATH; DYLD_FRAMEWORK_PATH="`pwd`"; \ - export EXE; EXE="$(BUILDEXE)"; \ - if [ -n "$(MULTIARCH)" ]; then export MULTIARCH; MULTIARCH=$(MULTIARCH); fi; \ diff --git a/tools/depends/target/python27/Makefile b/tools/depends/target/python3/Makefile similarity index 61% rename from tools/depends/target/python27/Makefile rename to tools/depends/target/python3/Makefile index 5016342cc7686..56ac9175b713b 100644 --- a/tools/depends/target/python27/Makefile +++ b/tools/depends/target/python3/Makefile @@ -1,12 +1,13 @@ include ../../Makefile.include -DEPS= ../../Makefile.include Makefile crosscompile.patch android.patch no-export-path.patch android-nl_langinfo.patch \ - setup.patch fix-datetime.patch fix-ffi.patch android-binmodule.patch no-abort.patch urllib.patch modules.setup make-fork-optional.patch +DEPS= ../../Makefile.include Makefile apple.patch crosscompile.patch android.patch \ + fix-datetime.patch modules.setup make-fork-optional.patch android-nl_langinfo.patch # lib name, version LIBNAME=Python -VERSION=2.7.15 +VERSION=3.7.2 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.xz +BASE_URL=https://www.python.org/ftp/python/$(VERSION) ifeq ($(OS),osx) HOSTPLATFORM=_PYTHON_HOST_PLATFORM="darwin" @@ -20,9 +21,9 @@ endif CONFIGURE=OPT="$(CFLAGS)" \ LIBS=-lm \ ./configure --prefix=$(PREFIX) --host=$(HOST) \ - --disable-toolbox-glue --disable-framework --with-system-expat --with-system-ffi --without-pymalloc --enable-ipv6 + --disable-framework --with-system-expat --with-system-ffi --without-pymalloc --enable-ipv6 -LIBDYLIB=$(PLATFORM)/libpython2.7.a +LIBDYLIB=$(PLATFORM)/libpython3.7.a all: .installed-$(PLATFORM) @@ -34,17 +35,13 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) cd $(PLATFORM); patch -p1 < ../crosscompile.patch - cd $(PLATFORM); patch -p1 < ../setup.patch cd $(PLATFORM); patch -p1 < ../fix-datetime.patch cd $(PLATFORM); patch -p1 < ../android.patch - cd $(PLATFORM); patch -p1 < ../no-export-path.patch cd $(PLATFORM); patch -p1 < ../fix-ffi.patch - cd $(PLATFORM); patch -p1 < ../android-binmodule.patch - cd $(PLATFORM); patch -p1 < ../no-abort.patch - cd $(PLATFORM); patch -p1 < ../android-nl_langinfo.patch + cd $(PLATFORM); patch -p1 -i ../android-nl_langinfo.patch + cd $(PLATFORM); patch -p1 -i ../apple.patch ifeq ($(OS),ios) cd $(PLATFORM); patch -p1 < ../make-fork-optional.patch - cd $(PLATFORM); patch -p1 < ../urllib.patch cd $(PLATFORM); sed -ie 's|MACHDEP="unknown"|MACHDEP="darwin"|' configure.ac endif cp modules.setup $(PLATFORM)/Modules/Setup.dist @@ -52,13 +49,13 @@ endif #Add -liconv as needed, and add the _scproxy module for darwin # disable locale altogether for Android ifeq ($(OS),android) - cd $(PLATFORM); sed -ie 's|_locale _localemodule.c -lintl|#_locale _localemodule.c -lintl|' Modules/Setup.dist + cd $(PLATFORM); sed -ie 's|_locale _localemodule.c -lintl|#_locale _localemodule.c -lintl $(LINK_ICONV)|' Modules/Setup.dist else - cd $(PLATFORM); sed -ie 's|_locale _localemodule.c -lintl|_locale _localemodule.c -lintl $(LINK_ICONV) |' Modules/Setup.dist + cd $(PLATFORM); sed -ie 's|_locale _localemodule.c -lintl|_locale _localemodule.c -lintl $(LINK_ICONV)|' Modules/Setup.dist endif ifeq ($(OS),osx) cd $(PLATFORM); sed -ie 's|MACHDEP="unknown"|MACHDEP="darwin"|' configure.ac - echo "_scproxy \$$(srcdir)/Mac/Modules/_scproxy.c -framework SystemConfiguration -framework CoreFoundation" >> $(PLATFORM)/Modules/Setup.dist + echo "_scproxy \$$(srcdir)/Modules/_scproxy.c -framework SystemConfiguration -framework CoreFoundation" >> $(PLATFORM)/Modules/Setup.dist endif ifeq ($(OS),android) @@ -69,13 +66,13 @@ endif cd $(PLATFORM); $(CONFIGURE) $(LIBDYLIB): $(PLATFORM) - $(MAKE) -C $(PLATFORM) $(HOSTPLATFORM) PYTHON_FOR_BUILD=$(NATIVEPREFIX)/bin/python NATIVE_PGEN=$(NATIVEPREFIX)/bin/pgen CROSS_COMPILE_TARGET=yes libpython2.7.a + $(MAKE) -C $(PLATFORM) $(HOSTPLATFORM) PYTHON_FOR_BUILD=$(NATIVEPREFIX)/bin/python3 NATIVE_PGEN=$(NATIVEPREFIX)/bin/pgen CROSS_COMPILE_TARGET=yes libpython3.7.a touch $@ .installed-$(PLATFORM): $(LIBDYLIB) - $(MAKE) -C $(PLATFORM) $(HOSTPLATFORM) PYTHON_FOR_BUILD=$(NATIVEPREFIX)/bin/python NATIVE_PGEN=$(NATIVEPREFIX)/bin/pgen CROSS_COMPILE_TARGET=yes install - find $(PREFIX)/lib/python2.7 -type f -name "*.py" -delete - find $(PREFIX)/lib/python2.7 -type f -name "*.pyc" -delete + $(MAKE) -C $(PLATFORM) $(HOSTPLATFORM) PYTHON_FOR_BUILD=$(NATIVEPREFIX)/bin/python3 NATIVE_PGEN=$(NATIVEPREFIX)/bin/pgen CROSS_COMPILE_TARGET=yes install + # find $(PREFIX)/lib/python3.7 -type f -name "*.py" -delete + find $(PREFIX)/lib/python3.7 -type f -name "*.pyc" -delete touch $(LIBDYLIB) touch $@ diff --git a/tools/depends/target/python3/android-nl_langinfo.patch b/tools/depends/target/python3/android-nl_langinfo.patch new file mode 100644 index 0000000000000..0f25f219dd719 --- /dev/null +++ b/tools/depends/target/python3/android-nl_langinfo.patch @@ -0,0 +1,60 @@ +--- a/Modules/_localemodule.c ++++ b/Modules/_localemodule.c +@@ -424,7 +424,7 @@ + } + #endif + +-#ifdef HAVE_LANGINFO_H ++#if defined(HAVE_LANGINFO_H) && defined(HAVE_NL_LANGINFO) + #define LANGINFO(X) {#X, X} + static struct langinfo_constant{ + char* name; +@@ -690,7 +690,7 @@ + #if defined(MS_WINDOWS) + {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, METH_NOARGS}, + #endif +-#ifdef HAVE_LANGINFO_H ++#if defined(HAVE_LANGINFO_H) && defined(HAVE_NL_LANGINFO) + {"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo, + METH_VARARGS, nl_langinfo__doc__}, + #endif +@@ -730,7 +730,7 @@ + PyInit__locale(void) + { + PyObject *m; +-#ifdef HAVE_LANGINFO_H ++#if defined(HAVE_LANGINFO_H) && defined(HAVE_NL_LANGINFO) + int i; + #endif + +@@ -758,7 +758,7 @@ + } + PyModule_AddObject(m, "Error", Error); + +-#ifdef HAVE_LANGINFO_H ++#if defined(HAVE_LANGINFO_H) && defined(HAVE_NL_LANGINFO) + for (i = 0; langinfo_constants[i].name; i++) { + PyModule_AddIntConstant(m, langinfo_constants[i].name, + langinfo_constants[i].value); +--- a/Python/fileutils.c ++++ b/Python/fileutils.c +@@ -56,7 +56,7 @@ + has no console */ + if (cp != 0) + return PyUnicode_FromFormat("cp%u", (unsigned int)cp); +-#elif defined(CODESET) ++#elif defined(HAVE_NL_LANGINFO) && defined(CODESET) + { + char *codeset = nl_langinfo(CODESET); + if (codeset != NULL && codeset[0] != 0) +--- a/configure.ac ++++ b/configure.ac +@@ -3549,7 +3549,7 @@ + if_nameindex \ + initgroups kill killpg lchown lockf linkat lstat lutimes mmap \ + memrchr mbrtowc mkdirat mkfifo \ +- mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ ++ mkfifoat mknod mknodat mktime mremap nice nl_langinfo openat pathconf pause pipe2 plock poll \ + posix_fallocate posix_fadvise posix_spawn pread preadv preadv2 \ + pthread_init pthread_kill putenv pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ + sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \ diff --git a/tools/depends/target/python3/android.patch b/tools/depends/target/python3/android.patch new file mode 100644 index 0000000000000..3b9504256520e --- /dev/null +++ b/tools/depends/target/python3/android.patch @@ -0,0 +1,40 @@ +--- a/Modules/pwdmodule.c ++++ b/Modules/pwdmodule.c +@@ -82,7 +82,7 @@ + #endif + PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromUid(p->pw_uid)); + PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromGid(p->pw_gid)); +-#if defined(HAVE_STRUCT_PASSWD_PW_GECOS) ++#if defined(HAVE_STRUCT_PASSWD_PW_GECOS) && !defined(__ANDROID__) + SETS(setIndex++, p->pw_gecos); + #else + SETS(setIndex++, ""); +--- a/Modules/termios.c ++++ b/Modules/termios.c +@@ -224,6 +224,7 @@ + Py_RETURN_NONE; + } + ++#if !defined(__ANDROID__) + PyDoc_STRVAR(termios_tcdrain__doc__, + "tcdrain(fd) -> None\n\ + \n\ +@@ -242,6 +243,7 @@ + + Py_RETURN_NONE; + } ++#endif + + PyDoc_STRVAR(termios_tcflush__doc__, + "tcflush(fd, queue) -> None\n\ +@@ -295,8 +297,10 @@ + METH_VARARGS, termios_tcsetattr__doc__}, + {"tcsendbreak", termios_tcsendbreak, + METH_VARARGS, termios_tcsendbreak__doc__}, ++ #if !defined(__ANDROID__) + {"tcdrain", termios_tcdrain, + METH_VARARGS, termios_tcdrain__doc__}, ++ #endif + {"tcflush", termios_tcflush, + METH_VARARGS, termios_tcflush__doc__}, + {"tcflow", termios_tcflow, diff --git a/tools/depends/target/python3/apple.patch b/tools/depends/target/python3/apple.patch new file mode 100644 index 0000000000000..bf1fd24c2c426 --- /dev/null +++ b/tools/depends/target/python3/apple.patch @@ -0,0 +1,12 @@ +--- a/Modules/posixmodule.c ++++ b/Modules/posixmodule.c +@@ -113,6 +113,9 @@ + #include + #endif + ++#if defined(__APPLE__) && defined(_POSIX_C_SOURCE) ++#undef _POSIX_C_SOURCE ++#endif + #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) + #ifdef HAVE_SYS_SOCKET_H + #include diff --git a/tools/depends/target/python3/crosscompile.patch b/tools/depends/target/python3/crosscompile.patch new file mode 100644 index 0000000000000..d92177485e028 --- /dev/null +++ b/tools/depends/target/python3/crosscompile.patch @@ -0,0 +1,109 @@ +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -38,7 +38,6 @@ + MAINCC= @MAINCC@ + LINKCC= @LINKCC@ + AR= @AR@ +-READELF= @READELF@ + SOABI= @SOABI@ + LDVERSION= @LDVERSION@ + GITVERSION= @GITVERSION@ +@@ -293,7 +292,7 @@ + ########################################################################## + # Parser + PGEN= Parser/pgen$(EXE) +- ++PGEN_FOR_BUILD=$(NATIVE_PGEN) + POBJS= \ + Parser/acceler.o \ + Parser/grammar1.o \ +@@ -620,7 +619,7 @@ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \ + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ +- $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build ++ PYTHONXCPREFIX='$(DESTDIR)$(prefix)' $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + + + # Build static library +@@ -1524,11 +1523,13 @@ + # Install the dynamically loadable modules + # This goes into $(exec_prefix) + sharedinstall: sharedmods ++ CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ ++ --skip-build \ + --prefix=$(prefix) \ +- --install-scripts=$(BINDIR) \ +- --install-platlib=$(DESTSHARED) \ +- --root=$(DESTDIR)/ ++ --install-scripts=$(DESTDIR)$(BINDIR) \ ++ --install-platlib=$(DESTDIR)$(DESTSHARED) \ ++ --root=/ + -rm $(DESTDIR)$(DESTSHARED)/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py + -rm -r $(DESTDIR)$(DESTSHARED)/__pycache__ + +--- a/configure.ac ++++ b/configure.ac +@@ -382,7 +382,6 @@ + *) + # for now, limit cross builds to known configurations + MACHDEP="unknown" +- AC_MSG_ERROR([cross build not supported for $host]) + esac + ac_sys_release= + else +@@ -426,7 +425,6 @@ + *) + # for now, limit cross builds to known configurations + MACHDEP="unknown" +- AC_MSG_ERROR([cross build not supported for $host]) + esac + _PYTHON_HOST_PLATFORM="$MACHDEP${_host_cpu:+-$_host_cpu}" + fi +@@ -1200,16 +1198,6 @@ + ARFLAGS="rcs" + fi + +-AC_CHECK_TOOLS([READELF], [readelf], [:]) +-if test "$cross_compiling" = yes; then +- case "$READELF" in +- readelf|:) +- AC_MSG_ERROR([readelf for the host is required for cross builds]) +- ;; +- esac +-fi +-AC_SUBST(READELF) +- + + case $MACHDEP in + hp*|HP*) +--- a/setup.py ++++ b/setup.py +@@ -16,7 +16,7 @@ + from distutils.command.build_scripts import build_scripts + from distutils.spawn import find_executable + +-cross_compiling = "_PYTHON_HOST_PLATFORM" in os.environ ++cross_compiling = ("_PYTHON_HOST_PLATFORM" in os.environ) or ('CROSS_COMPILE_TARGET' in os.environ) + + # Set common compiler and linker flags derived from the Makefile, + # reserved for building the interpreter and the stdlib modules. +@@ -229,6 +229,7 @@ + + def build_extensions(self): + ++ return + # Detect which modules should be compiled + missing = self.detect_modules() + +@@ -438,6 +439,9 @@ + + # Don't try to load extensions for cross builds + if cross_compiling: ++ self.announce( ++ 'WARNING: skipping import check for cross-compiled: "%s"' % ++ ext.name) + return + + loader = importlib.machinery.ExtensionFileLoader(ext.name, ext_filename) diff --git a/tools/depends/target/python27/fix-datetime.patch b/tools/depends/target/python3/fix-datetime.patch similarity index 72% rename from tools/depends/target/python27/fix-datetime.patch rename to tools/depends/target/python3/fix-datetime.patch index dafe720f0e62e..3dce1814d8d73 100644 --- a/tools/depends/target/python27/fix-datetime.patch +++ b/tools/depends/target/python3/fix-datetime.patch @@ -1,18 +1,16 @@ --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c -@@ -8,8 +8,14 @@ +@@ -10,7 +10,13 @@ #include "Python.h" #include #include "structmember.h" --#include "datetime.h" - #include "marshal.h" +#ifdef Py_BUILD_CORE +#undef Py_BUILD_CORE -+#include "datetime.h" + #include "datetime.h" +#define Py_BUILD_CORE +#else +#include "datetime.h" +#endif + #include "marshal.h" #include - #ifdef MS_WINDOWS - # include + diff --git a/tools/depends/target/python27/fix-ffi.patch b/tools/depends/target/python3/fix-ffi.patch similarity index 96% rename from tools/depends/target/python27/fix-ffi.patch rename to tools/depends/target/python3/fix-ffi.patch index 8fe55100e2b64..17c43ec40df75 100644 --- a/tools/depends/target/python27/fix-ffi.patch +++ b/tools/depends/target/python3/fix-ffi.patch @@ -1,6 +1,6 @@ --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c -@@ -1735,6 +1735,7 @@ +@@ -1634,6 +1634,7 @@ */ /* align and size are bogus for void, but they must not be zero */ @@ -8,12 +8,12 @@ ffi_type ffi_type_void = { 1, 1, FFI_TYPE_VOID }; ffi_type ffi_type_uint8 = { 1, 1, FFI_TYPE_UINT8 }; -@@ -1751,14 +1752,14 @@ +@@ -1650,14 +1651,15 @@ ffi_type ffi_type_float = { sizeof(float), FLOAT_ALIGN, FFI_TYPE_FLOAT }; ffi_type ffi_type_double = { sizeof(double), DOUBLE_ALIGN, FFI_TYPE_DOUBLE }; -- +*/ + #ifdef ffi_type_longdouble #undef ffi_type_longdouble #endif @@ -24,7 +24,7 @@ ffi_type ffi_type_pointer = { sizeof(void *), VOID_P_ALIGN, FFI_TYPE_POINTER }; - -+*/ ++ */ /*---------------- EOF ----------------*/ --- a/Modules/_ctypes/malloc_closure.c +++ b/Modules/_ctypes/malloc_closure.c diff --git a/tools/depends/target/python27/make-fork-optional.patch b/tools/depends/target/python3/make-fork-optional.patch similarity index 54% rename from tools/depends/target/python27/make-fork-optional.patch rename to tools/depends/target/python3/make-fork-optional.patch index 42b3bc9359c9c..fc103bb610cd6 100644 --- a/tools/depends/target/python27/make-fork-optional.patch +++ b/tools/depends/target/python3/make-fork-optional.patch @@ -1,15 +1,13 @@ --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c -@@ -167,6 +167,12 @@ +@@ -197,6 +197,10 @@ + #endif /* _MSC_VER */ #endif /* ! __WATCOMC__ || __QNX__ */ - #endif /* ! __IBMC__ */ -+ +#undef HAVE_FORK ++#undef HAVE_FORKPTY +#undef HAVE_EXECV +#undef HAVE_SYSTEM -+ -+ - #ifndef _MSC_VER - #if defined(__sgi)&&_COMPILER_VERSION>=700 + /*[clinic input] + # one of the few times we lie about this name! diff --git a/tools/depends/target/python27/modules.setup b/tools/depends/target/python3/modules.setup similarity index 61% rename from tools/depends/target/python27/modules.setup rename to tools/depends/target/python3/modules.setup index fbe47b2513f30..b46576479aed3 100644 --- a/tools/depends/target/python27/modules.setup +++ b/tools/depends/target/python3/modules.setup @@ -11,8 +11,17 @@ # directory.) # Each line in this file describes one or more optional modules. -# Modules enabled here will not be compiled by the setup.py script, +# Modules configured here will not be compiled by the setup.py script, # so the file can be used to override setup.py's behavior. +# Tag lines containing just the word "*static*", "*shared*" or "*disabled*" +# (without the quotes but with the stars) are used to tag the following module +# descriptions. Tag lines may alternate throughout this file. Modules are +# built statically when they are preceded by a "*static*" tag line or when +# there is no tag line between the start of the file and the module +# description. Modules are built as a shared library when they are preceded by +# a "*shared*" tag line. Modules are not built at all, not by the Makefile, +# nor by the setup.py script, when they are preceded by a "*disabled*" tag +# line. # Lines have the following structure: # @@ -34,9 +43,7 @@ # # which defines a Make variable definition inserted into Makefile.in # -# Finally, if a line contains just the word "*shared*" (without the -# quotes but with the stars), then the following modules will not be -# built statically. The build process works like this: +# The build process works like this: # # 1. Build all modules that are declared as static in Modules/Setup, # combine them into libpythonxy.a, combine that into python. @@ -90,18 +97,7 @@ SITEPATH=:site-packages # Standard path components for test modules TESTPATH= -# Path components for machine- or system-dependent modules and shared libraries -MACHDEPPATH=:plat-$(MACHDEP) -EXTRAMACHDEPPATH= - -# Path component for the Tkinter-related modules -# The TKPATH variable is always enabled, to save you the effort. -TKPATH=:lib-tk - -# Path component for old modules. -OLDPATH=:lib-old - -COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH)$(OLDPATH) +COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH) PYTHONPATH=$(COREPYTHONPATH) @@ -112,16 +108,39 @@ PYTHONPATH=$(COREPYTHONPATH) # This only contains the minimal set of modules required to run the # setup.py script in the root of the Python source tree. -posix posixmodule.c # posix (UNIX) system calls -errno errnomodule.c # posix (UNIX) errno values -pwd pwdmodule.c # this is needed to find out the user's home dir - # if $HOME is not set -_sre _sre.c # Fredrik Lundh's new regular expressions -_codecs _codecsmodule.c # access to the builtin codecs and codec registry +posix -DPy_BUILD_CORE posixmodule.c # posix (UNIX) system calls +errno errnomodule.c # posix (UNIX) errno values +pwd pwdmodule.c # this is needed to find out the user's home dir + # if $HOME is not set +_sre _sre.c # Fredrik Lundh's new regular expressions +_codecs _codecsmodule.c # access to the builtin codecs and codec registry +_weakref _weakref.c # weak references +_functools -DPy_BUILD_CORE _functoolsmodule.c # Tools for working with functions and callable objects +_operator _operator.c # operator.add() and similar goodies +_collections _collectionsmodule.c # Container types +_abc _abc.c # Abstract base classes +itertools itertoolsmodule.c # Functions creating iterators for efficient looping +atexit atexitmodule.c # Register functions to be run at interpreter-shutdown +_signal -DPy_BUILD_CORE signalmodule.c +_stat _stat.c # stat.h interface +time -DPy_BUILD_CORE timemodule.c # -lm # time operations and variables +_thread -DPy_BUILD_CORE _threadmodule.c # low-level threading interface + +# access to ISO C locale support +_locale _localemodule.c -lintl + +# Standard I/O baseline +_io -DPy_BUILD_CORE -I$(srcdir)/Modules/_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c # The zipimport module is always imported at startup. Having it as a # builtin module avoids some bootstrapping problems and reduces overhead. -zipimport zipimport.c +zipimport -DPy_BUILD_CORE zipimport.c + +# faulthandler module +faulthandler faulthandler.c + +# debug tool to trace memory blocks allocated by Python +_tracemalloc _tracemalloc.c hashtable.c # The rest of the modules listed in this file are all commented out by # default. Usually they can be detected and built as dynamically @@ -136,21 +155,9 @@ zipimport zipimport.c # The Python symtable module depends on .h files that setup.py doesn't track _symtable symtablemodule.c -# The SGI specific GL module: - -GLHACK=-Dclear=__GLclear -#gl glmodule.c cgensupport.c -I$(srcdir) $(GLHACK) -lgl -lX11 - -# Pure module. Cannot be linked dynamically. -# -DWITH_QUANTIFY, -DWITH_PURIFY, or -DWITH_ALL_PURE -#WHICH_PURE_PRODUCTS=-DWITH_ALL_PURE -#PURE_INCLS=-I/usr/local/include -#PURE_STUBLIBS=-L/usr/local/lib -lpurify_stubs -lquantify_stubs -#pure puremodule.c $(WHICH_PURE_PRODUCTS) $(PURE_INCLS) $(PURE_STUBLIBS) - # Uncommenting the following line tells makesetup that all following # modules are to be built as shared libraries (see above for more -# detail; also note that *static* reverses this effect): +# detail; also note that *static* or *disabled* cancels this effect): #*shared* @@ -162,41 +169,33 @@ GLHACK=-Dclear=__GLclear # it, depending on your system -- see the GNU readline instructions. # It's okay for this to be a shared library, too. -#readline readline.c -lreadline -lncurses +#readline readline.c -lreadline -ltermcap # Modules that should always be present (non UNIX dependent): array arraymodule.c # array objects -cmath cmathmodule.c # -lm # complex math library functions +cmath cmathmodule.c _math.c # -lm # complex math library functions math mathmodule.c _math.c # -lm # math library functions, e.g. sin() +#_contextvars _contextvarsmodule.c # Context Variables _struct _struct.c # binary structure packing/unpacking -time timemodule.c # -lm # time operations and variables -operator operator.c # operator.add() and similar goodies _weakref _weakref.c # basic weak reference support _testcapi _testcapimodule.c # Python C API test module _random _randommodule.c # Random number generator -_collections _collectionsmodule.c # Container types -itertools itertoolsmodule.c # Functions creating iterators for efficient looping -strop stropmodule.c # String manipulations -_functools _functoolsmodule.c # Tools for working with functions and callable objects - -EXPATDEFINES='-DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI' -_elementtree $(EXPATDEFINES) _elementtree.c # elementtree accelerator -#_pickle _pickle.c # pickle accelerator -datetime datetimemodule.c # date/time type +_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c # elementtree accelerator +_pickle _pickle.c # pickle accelerator +_datetime _datetimemodule.c # datetime accelerator _bisect _bisectmodule.c # Bisection algorithms +_heapq _heapqmodule.c # Heap queue algorithm +_asyncio _asynciomodule.c # Fast asyncio Future unicodedata unicodedata.c # static Unicode character database -# access to ISO C locale support -_locale _localemodule.c -lintl - # Modules with some UNIX dependencies -- on by default: # (If you have a really backward UNIX, select and socket may not be # supported...) -# + fcntl fcntlmodule.c # fcntl(2) and ioctl(2) #spwd spwdmodule.c # spwd(3) #grp grpmodule.c # grp(3) @@ -224,10 +223,9 @@ _hashlib _hashopenssl.c \ # The crypt module is now disabled by default because it breaks builds # on many systems (where -lcrypt is needed), e.g. Linux (I believe). -# -# First, look at Setup.config; configure may have set this for you. -#crypt cryptmodule.c -lcrypt # crypt(3); needs -lcrypt on some systems +#_crypt _cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems + # Some more UNIX dependent modules -- off by default, since these # are not supported by all UNIX systems: @@ -236,6 +234,7 @@ _hashlib _hashopenssl.c \ termios termios.c # Steen Lumholt's termios module resource resource.c # Jeremy Hylton's rlimit interface +_posixsubprocess _posixsubprocess.c # POSIX subprocess module helper # Multimedia modules -- off by default. # These don't work for 64-bit platforms!!! @@ -243,77 +242,26 @@ resource resource.c # Jeremy Hylton's rlimit interface # These represent audio samples or images as strings: #audioop audioop.c # Operations on audio samples -#imageop imageop.c # Operations on images # Note that the _md5 and _sha modules are normally only built if the # system does not have the OpenSSL libs containing an optimized version. # The _md5 module implements the RSA Data Security, Inc. MD5 -# Message-Digest Algorithm, described in RFC 1321. The necessary files -# md5.c and md5.h are included here. +# Message-Digest Algorithm, described in RFC 1321. -_md5 md5module.c md5.c +_md5 md5module.c # The _sha module implements the SHA checksum algorithms. # (NIST's Secure Hash Algorithms.) -_sha shamodule.c +_sha1 sha1module.c _sha256 sha256module.c _sha512 sha512module.c +_sha3 _sha3/sha3module.c - -# SGI IRIX specific modules -- off by default. - -# These module work on any SGI machine: - -# *** gl must be enabled higher up in this file *** -#fm fmmodule.c $(GLHACK) -lfm -lgl # Font Manager -#sgi sgimodule.c # sgi.nap() and a few more - -# This module requires the header file -# /usr/people/4Dgifts/iristools/include/izoom.h: -#imgfile imgfile.c -limage -lgutil -lgl -lm # Image Processing Utilities - - -# These modules require the Multimedia Development Option (I think): - -#al almodule.c -laudio # Audio Library -#cd cdmodule.c -lcdaudio -lds -lmediad # CD Audio Library -#cl clmodule.c -lcl -lawareaudio # Compression Library -#sv svmodule.c yuvconvert.c -lsvideo -lXext -lX11 # Starter Video - - -# The FORMS library, by Mark Overmars, implements user interface -# components such as dialogs and buttons using SGI's GL and FM -# libraries. You must ftp the FORMS library separately from -# ftp://ftp.cs.ruu.nl/pub/SGI/FORMS. It was tested with FORMS 2.2a. -# NOTE: if you want to be able to use FORMS and curses simultaneously -# (or both link them statically into the same binary), you must -# compile all of FORMS with the cc option "-Dclear=__GLclear". - -# The FORMS variable must point to the FORMS subdirectory of the forms -# toplevel directory: - -#FORMS=/ufs/guido/src/forms/FORMS -#fl flmodule.c -I$(FORMS) $(GLHACK) $(FORMS)/libforms.a -lfm -lgl - - -# SunOS specific modules -- off by default: - -#sunaudiodev sunaudiodev.c - - -# A Linux specific module -- off by default; this may also work on -# some *BSDs. - -#linuxaudiodev linuxaudiodev.c - - -# George Neville-Neil's timing module: - -timing timingmodule.c - +# _blake module +_blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c # The _tkinter module. # @@ -359,79 +307,30 @@ timing timingmodule.c # -lX11 # Lance Ellinghaus's syslog module -syslog syslogmodule.c # syslog daemon interface +#syslog syslogmodule.c # syslog daemon interface -# Curses support, requring the System V version of curses, often +# Curses support, requiring the System V version of curses, often # provided by the ncurses library. e.g. on Linux, link with -lncurses # instead of -lcurses). -# -# First, look at Setup.config; configure may have set this for you. #_curses _cursesmodule.c -lcurses -ltermcap # Wrapper for the panel library that's part of ncurses and SYSV curses. #_curses_panel _curses_panel.c -lpanel -lncurses -# Generic (SunOS / SVR4) dynamic loading module. -# This is not needed for dynamic loading of Python modules -- -# it is a highly experimental and dangerous device for calling -# *arbitrary* C functions in *arbitrary* shared libraries: - -#dl dlmodule.c - - # Modules that provide persistent dictionary-like semantics. You will # probably want to arrange for at least one of them to be available on # your machine, though none are defined by default because of library -# dependencies. The Python module anydbm.py provides an -# implementation independent wrapper for these; dumbdbm.py provides +# dependencies. The Python module dbm/__init__.py provides an +# implementation independent wrapper for these; dbm/dumb.py provides # similar functionality (but slower of course) implemented in Python. -# The standard Unix dbm module has been moved to Setup.config so that -# it will be compiled as a shared library by default. Compiling it as -# a built-in module causes conflicts with the pybsddb3 module since it -# creates a static dependency on an out-of-date version of db.so. -# -# First, look at Setup.config; configure may have set this for you. - -#dbm -I$(prefix)/include -L$(prefix)/lib dbmmodule.c # dbm(3) may require -lndbm or similar +#_dbm _dbmmodule.c # dbm(3) may require -lndbm or similar # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: -# -# First, look at Setup.config; configure may have set this for you. - -#gdbm gdbmmodule.c -I$(prefix)/include -L$(prefix)/lib -lgdbm - - -# Sleepycat Berkeley DB interface. -# -# This requires the Sleepycat DB code, see http://www.sleepycat.com/ -# The earliest supported version of that library is 3.0, the latest -# supported version is 4.0 (4.1 is specifically not supported, as that -# changes the semantics of transactional databases). A list of available -# releases can be found at -# -# http://www.sleepycat.com/update/index.html -# -# Edit the variables DB and DBLIBVERto point to the db top directory -# and the subdirectory of PORT where you built it. -#DB=/usr/local/BerkeleyDB.4.0 -#DBLIBVER=4.0 -#DBINC=$(DB)/include -#DBLIB=$(DB)/lib -#_bsddb _bsddb.c -I$(DBINC) -L$(DBLIB) -ldb-$(DBLIBVER) - -# Historical Berkeley DB 1.85 -# -# This module is deprecated; the 1.85 version of the Berkeley DB library has -# bugs that can cause data corruption. If you can, use later versions of the -# library instead, available from . - -#DB=/depot/sundry/src/berkeley-db/db.1.85 -#DBPORT=$(DB)/PORT/irix.5.3 -#bsddb185 bsddbmodule.c -I$(DBPORT)/include -I$(DBPORT) $(DBPORT)/libdb.a +#_gdbm _gdbmmodule.c -I/usr/local/include -L/usr/local/lib -lgdbm # Helper module for various ascii-encoders @@ -440,32 +339,11 @@ binascii binascii.c # Fred Drake's interface to the Python parser parser parsermodule.c -# cStringIO and cPickle -cStringIO cStringIO.c -cPickle cPickle.c - - -# Lee Busby's SIGFPE modules. -# The library to link fpectl with is platform specific. -# Choose *one* of the options below for fpectl: - -# For SGI IRIX (tested on 5.3): -#fpectl fpectlmodule.c -lfpe - -# For Solaris with SunPro compiler (tested on Solaris 2.5 with SunPro C 4.2): -# (Without the compiler you don't have -lsunmath.) -#fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm - -# For other systems: see instructions in fpectlmodule.c. -#fpectl fpectlmodule.c ... - -# Test module for fpectl. No extra libraries needed. -#fpetest fpetestmodule.c # Andrew Kuchling's zlib module. # This require zlib 1.1.3 (or later). # See http://www.gzip.org/zlib/ -zlib zlibmodule.c -I$(prefix)/include -L$(prefix)/lib -lz +zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz # Interface to the Expat XML parser # @@ -478,13 +356,12 @@ zlib zlibmodule.c -I$(prefix)/include -L$(prefix)/lib -lz # # More information on Expat can be found at www.libexpat.org. # -pyexpat pyexpat.c $(EXPATDEFINES) -I$(prefix)/include -L$(prefix)/lib -lexpat - +#pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI # Hye-Shik Chang's CJKCodecs # multibytecodec is required for all the other CJK codec modules -_multibytecodec cjkcodecs/multibytecodec.c +#_multibytecodec cjkcodecs/multibytecodec.c _codecs_cn cjkcodecs/_codecs_cn.c _codecs_hk cjkcodecs/_codecs_hk.c @@ -499,14 +376,6 @@ _codecs_tw cjkcodecs/_codecs_tw.c # Another example -- the 'xxsubtype' module shows C-level subtyping in action xxsubtype xxsubtype.c -_lsprof _lsprof.c rotatingtree.c -_json _json.c -#_io/fileio _io/fileio.c -_io _io/bufferedio.c _io/bytesio.c _io/fileio.c _io/iobase.c _io/_iomodule.c _io/stringio.c _io/textio.c -_heapq _heapqmodule.c -_hotshot _hotshot.c -future_builtins future_builtins.c - SQLITEDEFINES='-DMODULE_NAME="sqlite3"' _sqlite3 _sqlite/connection.c \ _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/prepare_protocol.c \ @@ -517,4 +386,12 @@ _ctypes _ctypes/callbacks.c _ctypes/callproc.c _ctypes/cfield.c _ctypes/_ctyp _ctypes/malloc_closure.c _ctypes/stgdict.c \ -I$(prefix)/include/ffi -L$(prefix)/lib -lffi -#bz2 bz2module.c -I$(prefix)/include -L$(prefix)/lib -lbz2 +_queue _queuemodule.c + +# Uncommenting the following line tells makesetup that all following modules +# are not built (see above for more detail). +# +#*disabled* +# +#_sqlite3 _tkinter _curses pyexpat +#_codecs_jp _codecs_kr _codecs_tw unicodedata diff --git a/tools/depends/target/python27/no-abort.patch b/tools/depends/target/python3/no-abort.patch similarity index 68% rename from tools/depends/target/python27/no-abort.patch rename to tools/depends/target/python3/no-abort.patch index 72f82b8332f27..e509c2d1e7bd9 100644 --- a/tools/depends/target/python27/no-abort.patch +++ b/tools/depends/target/python3/no-abort.patch @@ -1,8 +1,8 @@ --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c -@@ -8649,7 +8649,7 @@ - static PyObject * - posix_abort(PyObject *self, PyObject *noargs) +@@ -10365,7 +10365,7 @@ + os_abort_impl(PyObject *module) + /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/ { - abort(); + // abort(); @@ -11,12 +11,12 @@ return NULL; --- a/Python/pythonrun.c +++ b/Python/pythonrun.c -@@ -1706,7 +1706,7 @@ +@@ -1697,7 +1697,7 @@ DebugBreak(); #endif #endif /* MS_WINDOWS */ - abort(); + // abort(); } - + /* Clean up and exit */ diff --git a/tools/depends/target/python27/setup.patch b/tools/depends/target/python3/setup.patch similarity index 94% rename from tools/depends/target/python27/setup.patch rename to tools/depends/target/python3/setup.patch index 565f63e3151a1..64968d413eac3 100644 --- a/tools/depends/target/python27/setup.patch +++ b/tools/depends/target/python3/setup.patch @@ -1,13 +1,13 @@ --- a/Modules/makesetup +++ b/Modules/makesetup @@ -212,6 +212,7 @@ - objs="$objs $obj" - case $src in - glmodule.c) ;; + objs="$objs $obj" + case $src in + glmodule.c) ;; + # _*io.c) src='$(srcdir)/'"$srcdir/_io/$(echo $src| tr -d "_")";; - /*) ;; - \$*) ;; - *) src='$(srcdir)/'"$srcdir/$src";; + /*) ;; + \$*) ;; + *) src='$(srcdir)/'"$srcdir/$src";; --- a/setup.py +++ b/setup.py @@ -337,6 +337,9 @@ @@ -16,7 +16,7 @@ return + #if os.environ.get('CROSS_COMPILE_TARGET') == 'yes': + # return -+ ++ ext_filename = os.path.join( self.build_lib, self.get_ext_filename(self.get_ext_fullname(ext.name))) diff --git a/tools/depends/target/python27/urllib.patch b/tools/depends/target/python3/urllib.patch similarity index 100% rename from tools/depends/target/python27/urllib.patch rename to tools/depends/target/python3/urllib.patch diff --git a/tools/depends/target/pythonmodule-pil/Makefile b/tools/depends/target/pythonmodule-pil/Makefile index addd67498c750..d9f2660180cf2 100644 --- a/tools/depends/target/pythonmodule-pil/Makefile +++ b/tools/depends/target/pythonmodule-pil/Makefile @@ -10,26 +10,26 @@ VERSION=3.0.0 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.gz -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" ifeq ($(OS),android) PILPATH=$(PREFIX)/share/$(APP_NAME)/addons/script.module.pil -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS) -L$(PREFIX)/lib/dummy-lib$(APP_NAME)/ -l$(APP_NAME) -lm" PYTHONPATH="$(PILPATH):$(PREFIX)/lib/python2.7/site-packages/" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS) -L$(PREFIX)/lib/dummy-lib$(APP_NAME)/ -l$(APP_NAME) -lm" PYTHONPATH="$(PILPATH):$(PREFIX)/lib/python3.7/site-packages/" endif ifeq (darwin, $(findstring darwin, $(HOST))) ifeq ($(OS),ios) -PYTHON_O=$(abs_top_srcdir)/target/python27/$(PLATFORM)/Modules/python.o +PYTHON_O=$(abs_top_srcdir)/target/python3/$(PLATFORM)/Programs/python.o endif #ensure that only our target ldflags are passed to the python build LDSHARED:=$(CC) -bundle -undefined dynamic_lookup $(LDFLAGS) -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" CCSHARED="$(CC) $(CFLAGS) $(PYTHON_O)" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" LDSHARED="$(LDSHARED)" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" CCSHARED="$(CC) $(CFLAGS) $(PYTHON_O)" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" LDSHARED="$(LDSHARED)" endif -LIBDYLIB=$(PLATFORM)/dist/Pillow-$(VERSION)-py2.7-$(OS)-$(CPU).egg +LIBDYLIB=$(PLATFORM)/dist/Pillow-$(VERSION)-py3.7-$(OS)-$(CPU).egg ifeq ($(OS),android) LIBDYLIB=$(PREFIX)/share/$(APP_NAME)/addons/script.module.pil/lib/PIL/_imaging.so else ifeq (darwin, $(findstring darwin, $(HOST))) -LIBDYLIB=$(PLATFORM)/dist/Pillow-$(VERSION)-py2.7-macosx-10.4-x86_64.egg +LIBDYLIB=$(PLATFORM)/dist/Pillow-$(VERSION)-py3.7-macosx-10.4-x86_64.egg endif all: .installed-$(PLATFORM) @@ -44,16 +44,16 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) $(LIBDYLIB): $(PLATFORM) mkdir -p $(PLATFORM)/output - cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python setup.py build_ext --plat-name $(OS)-$(CPU) + cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python3 setup.py build_ext --plat-name $(OS)-$(CPU) .installed-$(PLATFORM): $(LIBDYLIB) ifeq ($(OS),android) mkdir -p $(PREFIX)/share/$(APP_NAME)/addons/script.module.pil/lib - cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python setup.py install --install-lib $(PREFIX)/share/$(APP_NAME)/addons/script.module.pil + cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python3 setup.py install --install-lib $(PREFIX)/share/$(APP_NAME)/addons/script.module.pil cd $(PREFIX)/share/$(APP_NAME)/addons/script.module.pil/lib && unzip -o ../Pillow-*.egg cd $(PREFIX)/share/$(APP_NAME)/addons/script.module.pil && rm -rf Pillow-*.egg else - cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python setup.py install --prefix=$(PREFIX) + cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python3 setup.py install --prefix=$(PREFIX) endif touch $@ diff --git a/tools/depends/target/pythonmodule-pil/pillow-crosscompile.patch b/tools/depends/target/pythonmodule-pil/pillow-crosscompile.patch index 86e1a914f7000..97c61a54c208d 100644 --- a/tools/depends/target/pythonmodule-pil/pillow-crosscompile.patch +++ b/tools/depends/target/pythonmodule-pil/pillow-crosscompile.patch @@ -26,7 +26,7 @@ if prefix: _add_directory(library_dirs, os.path.join(prefix, "lib")) _add_directory(include_dirs, os.path.join(prefix, "include")) -+ _add_directory(include_dirs, os.path.join(prefix, "include/python2.7")) ++ _add_directory(include_dirs, os.path.join(prefix, "include/python3.7")) # # add platform directories diff --git a/tools/depends/target/pythonmodule-pycryptodome/Makefile b/tools/depends/target/pythonmodule-pycryptodome/Makefile index 2c53295eb42b3..d6a48a8f5a955 100644 --- a/tools/depends/target/pythonmodule-pycryptodome/Makefile +++ b/tools/depends/target/pythonmodule-pycryptodome/Makefile @@ -10,23 +10,23 @@ VERSION=3.4.3 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.gz -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" ifeq ($(OS),android) -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS) -L$(PREFIX)/lib/dummy-lib$(APP_NAME)/ -l$(APP_NAME) -lm" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS) -L$(PREFIX)/lib/dummy-lib$(APP_NAME)/ -l$(APP_NAME) -lm" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" endif ifeq (darwin, $(findstring darwin, $(HOST))) ifeq ($(OS),ios) -PYTHON_O=$(abs_top_srcdir)/target/python27/$(PLATFORM)/Modules/python.o +PYTHON_O=$(abs_top_srcdir)/target/python3/$(PLATFORM)/Programs/python.o endif #ensure that only our target ldflags are passed to the python build LDSHARED:=$(CC) -bundle -undefined dynamic_lookup $(LDFLAGS) -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" CCSHARED="$(CC) $(CFLAGS) $(PYTHON_O)" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" LDSHARED="$(LDSHARED)" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" CCSHARED="$(CC) $(CFLAGS) $(PYTHON_O)" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" LDSHARED="$(LDSHARED)" endif -LIBDYLIB=$(PLATFORM)/build/lib.$(OS)-$(CPU)-2.7/Cryptodome +LIBDYLIB=$(PLATFORM)/build/lib.$(OS)-$(CPU)-3.7/Cryptodome ifeq ($(NATIVE_OS), osx) - LIBDYLIB=$(PLATFORM)/build/lib.macosx-10.4-x86_64-2.7/Cryptodome + LIBDYLIB=$(PLATFORM)/build/lib.macosx-10.4-x86_64-3.7/Cryptodome endif all: .installed-$(PLATFORM) @@ -45,10 +45,10 @@ endif $(LIBDYLIB): $(PLATFORM) mkdir -p $(PLATFORM)/output - cd $(PLATFORM); touch .separate_namespace && $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python setup.py build_ext --plat-name $(OS)-$(TARGET_ARCH) + cd $(PLATFORM); touch .separate_namespace && $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python3 setup.py build_ext --plat-name $(OS)-$(TARGET_ARCH) .installed-$(PLATFORM): $(LIBDYLIB) - cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python setup.py install --prefix=$(PREFIX) + cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python3 setup.py install --prefix=$(PREFIX) touch $@ clean: diff --git a/tools/depends/target/pythonmodule-setuptools/Makefile b/tools/depends/target/pythonmodule-setuptools/Makefile index 69dba4c7b9386..b65be1d5713d8 100644 --- a/tools/depends/target/pythonmodule-setuptools/Makefile +++ b/tools/depends/target/pythonmodule-setuptools/Makefile @@ -10,20 +10,20 @@ VERSION=18.4 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.gz -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" ifeq ($(OS),android) #PYTHONPATH=$(PREFIX)/share/$(APP_NAME)/addons/script.module.pil -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS) -L$(PREFIX)/lib/dummy-lib$(APP_NAME)/ -l$(APP_NAME) -lm" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS) -L$(PREFIX)/lib/dummy-lib$(APP_NAME)/ -l$(APP_NAME) -lm" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" endif ifeq ($(OS),osx) -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS) -lpython" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC)" LDSHARED="$(CC) -shared" LDFLAGS="$(LDFLAGS) -lpython" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" endif ifeq ($(OS),ios) -PYTHON_O=$(abs_top_srcdir)/target/python27/$(PLATFORM)/Modules/python.o -CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" CCSHARED="$(CC) $(CFLAGS) $(PYTHON_O)" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python2.7/site-packages/" +PYTHON_O=$(abs_top_srcdir)/target/python3/$(PLATFORM)/Programs/python.o +CROSSFLAGS=PYTHONXCPREFIX="$(PREFIX)" CC="$(CC) $(CFLAGS)" CCSHARED="$(CC) $(CFLAGS) $(PYTHON_O)" LDFLAGS="$(LDFLAGS)" PYTHONPATH="$(PREFIX)/lib/python3.7/site-packages/" endif -LIBDYLIB=$(PLATFORM)/dist/$(LIBNAME)-$(VERSION)-py2.7.egg +LIBDYLIB=$(PLATFORM)/dist/$(LIBNAME)-$(VERSION)-py3.7.egg all: .installed-$(PLATFORM) @@ -36,10 +36,10 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) $(LIBDYLIB): $(PLATFORM) mkdir -p $(PLATFORM)/output - cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python setup.py build_ext --plat-name $(OS)-$(CPU) + cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python3 setup.py build_ext --plat-name $(OS)-$(CPU) .installed-$(PLATFORM): $(LIBDYLIB) - cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python setup.py install --prefix=$(PREFIX) + cd $(PLATFORM); $(CROSSFLAGS) $(NATIVEPREFIX)/bin/python3 setup.py install --prefix=$(PREFIX) touch $@ clean: diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index 4d6e27e3d914a..4deb0a565a6bd 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -193,19 +193,12 @@ void CAddonMgr::FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder builder.SetLicense(CServiceBroker::GetAddonMgr().GetExtValue(metadata->configuration, "license")); builder.SetPackageSize(StringUtils::ToUint64(CServiceBroker::GetAddonMgr().GetExtValue(metadata->configuration, "size"), 0)); + std::string language = CServiceBroker::GetAddonMgr().GetExtValue(metadata->configuration, "language"); + if (!language.empty()) { InfoMap extrainfo; - - std::string metaString = CServiceBroker::GetAddonMgr().GetExtValue(metadata->configuration, "language"); - if (!metaString.empty()) - extrainfo.insert(std::make_pair("language", metaString)); - - metaString = CServiceBroker::GetAddonMgr().GetExtValue(metadata->configuration, "reuselanguageinvoker"); - if (!metaString.empty()) - extrainfo.insert(std::make_pair("reuselanguageinvoker", metaString)); - - if (!extrainfo.empty()) - builder.SetExtrainfo(std::move(extrainfo)); + extrainfo.insert(std::make_pair("language",language)); + builder.SetExtrainfo(std::move(extrainfo)); } builder.SetBroken(CServiceBroker::GetAddonMgr().GetExtValue(metadata->configuration, "broken")); diff --git a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp index 5546f6ecdca35..51cb6e5faee57 100644 --- a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp +++ b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp @@ -133,8 +133,8 @@ extern "C" void __stdcall init_emu_environ() // check if we are running as real xbmc.app or just binary if (!CUtil::GetFrameworksPath(true).empty()) { - // using external python, it's build looking for xxx/lib/python2.7 - // so point it to frameworks which is where python2.7 is located + // using external python, it's build looking for xxx/lib/python3.7 + // so point it to frameworks which is where python3.7 is located dll_putenv(("PYTHONPATH=" + CSpecialProtocol::TranslatePath("special://frameworks")).c_str()); dll_putenv(("PYTHONHOME=" + @@ -156,7 +156,7 @@ extern "C" void __stdcall init_emu_environ() #if defined(TARGET_ANDROID) std::string apkPath = getenv("KODI_ANDROID_APK"); - apkPath += "/assets/python2.7"; + apkPath += "/assets/python3.7"; dll_putenv(("PYTHONHOME=" + apkPath).c_str()); dll_putenv("PYTHONOPTIMIZE="); dll_putenv("PYTHONNOUSERSITE=1"); diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp index fcc3a15e1fef9..06de4cde1ab13 100644 --- a/xbmc/filesystem/PluginDirectory.cpp +++ b/xbmc/filesystem/PluginDirectory.cpp @@ -85,12 +85,6 @@ int CPluginDirectory::getNewHandle(CPluginDirectory *cp) return handle; } -void CPluginDirectory::reuseHandle(int handle, CPluginDirectory *cp) -{ - CSingleLock lock(m_handleLock); - globalHandles[handle] = cp; -} - void CPluginDirectory::removeHandle(int handle) { CSingleLock lock(m_handleLock); @@ -129,12 +123,7 @@ bool CPluginDirectory::StartScript(const std::string& strPath, bool retrievingDi std::string basePath(url.Get()); // reset our wait event, and grab a new handle m_fetchComplete.Reset(); - int handle = CScriptInvocationManager::GetInstance().GetReusablePluginHandle(m_addon->LibPath()); - - if (handle < 0) - handle = getNewHandle(this); - else - reuseHandle(handle, this); + int handle = getNewHandle(this); // clear out our status variables m_fileResult->Reset(); @@ -161,11 +150,7 @@ bool CPluginDirectory::StartScript(const std::string& strPath, bool retrievingDi CLog::Log(LOGDEBUG, "%s - calling plugin %s('%s','%s','%s','%s')", __FUNCTION__, m_addon->Name().c_str(), argv[0].c_str(), argv[1].c_str(), argv[2].c_str(), argv[3].c_str()); bool success = false; std::string file = m_addon->LibPath(); - bool reuseLanguageInvoker = false; - if (m_addon->ExtraInfo().find("reuselanguageinvoker") != m_addon->ExtraInfo().end()) - reuseLanguageInvoker = m_addon->ExtraInfo().at("reuselanguageinvoker") == "true"; - - int id = CScriptInvocationManager::GetInstance().ExecuteAsync(file, m_addon, argv, reuseLanguageInvoker, handle); + int id = CScriptInvocationManager::GetInstance().ExecuteAsync(file, m_addon, argv); if (id >= 0) { // wait for our script to finish std::string scriptName = m_addon->Name(); diff --git a/xbmc/filesystem/PluginDirectory.h b/xbmc/filesystem/PluginDirectory.h index d480b2a5206e5..767414f5bb31b 100644 --- a/xbmc/filesystem/PluginDirectory.h +++ b/xbmc/filesystem/PluginDirectory.h @@ -75,8 +75,6 @@ class CPluginDirectory : public IDirectory static std::map globalHandles; static int getNewHandle(CPluginDirectory *cp); - static void reuseHandle(int handle, CPluginDirectory *cp); - static void removeHandle(int handle); static CPluginDirectory *dirFromHandle(int handle); static CCriticalSection m_handleLock; diff --git a/xbmc/interfaces/generic/ILanguageInvocationHandler.h b/xbmc/interfaces/generic/ILanguageInvocationHandler.h index e3912355caef7..3057132cfbdcc 100644 --- a/xbmc/interfaces/generic/ILanguageInvocationHandler.h +++ b/xbmc/interfaces/generic/ILanguageInvocationHandler.h @@ -24,7 +24,7 @@ class ILanguageInvocationHandler virtual bool OnScriptInitialized(ILanguageInvoker *invoker) { return true; } virtual void OnScriptStarted(ILanguageInvoker *invoker) { } virtual void OnScriptAbortRequested(ILanguageInvoker *invoker) { } - virtual void OnExecutionEnded(ILanguageInvoker *invoker) { } + virtual void OnScriptEnded(ILanguageInvoker *invoker) { } virtual void OnScriptFinalized(ILanguageInvoker *invoker) { } virtual ILanguageInvoker* CreateInvoker() = 0; diff --git a/xbmc/interfaces/generic/ILanguageInvoker.cpp b/xbmc/interfaces/generic/ILanguageInvoker.cpp index 4e11cb21a134a..d2a62bf3510c4 100644 --- a/xbmc/interfaces/generic/ILanguageInvoker.cpp +++ b/xbmc/interfaces/generic/ILanguageInvoker.cpp @@ -35,7 +35,7 @@ bool ILanguageInvoker::Stop(bool abort /* = false */) bool ILanguageInvoker::IsActive() const { - return GetState() > InvokerStateUninitialized && GetState() < InvokerStateScriptDone; + return GetState() > InvokerStateUninitialized && GetState() < InvokerStateDone; } bool ILanguageInvoker::IsRunning() const @@ -71,13 +71,13 @@ void ILanguageInvoker::onAbortRequested() void ILanguageInvoker::onExecutionFailed() { if (m_invocationHandler) - m_invocationHandler->OnExecutionEnded(this); + m_invocationHandler->OnScriptEnded(this); } void ILanguageInvoker::onExecutionDone() { if (m_invocationHandler) - m_invocationHandler->OnExecutionEnded(this); + m_invocationHandler->OnScriptEnded(this); } void ILanguageInvoker::onExecutionFinalized() diff --git a/xbmc/interfaces/generic/ILanguageInvoker.h b/xbmc/interfaces/generic/ILanguageInvoker.h index df84b1b9083f0..eeb53280dae31 100644 --- a/xbmc/interfaces/generic/ILanguageInvoker.h +++ b/xbmc/interfaces/generic/ILanguageInvoker.h @@ -22,8 +22,7 @@ typedef enum { InvokerStateInitialized, InvokerStateRunning, InvokerStateStopping, - InvokerStateScriptDone, - InvokerStateExecutionDone, + InvokerStateDone, InvokerStateFailed } InvokerState; @@ -44,7 +43,6 @@ class ILanguageInvoker InvokerState GetState() const { return m_state; } bool IsActive() const; bool IsRunning() const; - void Reset() { m_state = InvokerStateUninitialized; }; protected: friend class CLanguageInvokerThread; diff --git a/xbmc/interfaces/generic/LanguageInvokerThread.cpp b/xbmc/interfaces/generic/LanguageInvokerThread.cpp index c1000e28c65d1..dc9893dfe2bad 100644 --- a/xbmc/interfaces/generic/LanguageInvokerThread.cpp +++ b/xbmc/interfaces/generic/LanguageInvokerThread.cpp @@ -9,12 +9,11 @@ #include "LanguageInvokerThread.h" #include "ScriptInvocationManager.h" -CLanguageInvokerThread::CLanguageInvokerThread(LanguageInvokerPtr invoker, CScriptInvocationManager *invocationManager, bool reuseable) +CLanguageInvokerThread::CLanguageInvokerThread(LanguageInvokerPtr invoker, CScriptInvocationManager *invocationManager) : ILanguageInvoker(NULL), CThread("LanguageInvoker"), m_invoker(invoker), - m_invocationManager(invocationManager), - m_reusable(reuseable) + m_invocationManager(invocationManager) { } CLanguageInvokerThread::~CLanguageInvokerThread() @@ -22,7 +21,7 @@ CLanguageInvokerThread::~CLanguageInvokerThread() Stop(true); } -InvokerState CLanguageInvokerThread::GetState() const +InvokerState CLanguageInvokerThread::GetState() { if (m_invoker == NULL) return InvokerStateFailed; @@ -30,12 +29,6 @@ InvokerState CLanguageInvokerThread::GetState() const return m_invoker->GetState(); } -void CLanguageInvokerThread::Release() -{ - m_bStop = true; - m_condition.notify_one(); -} - bool CLanguageInvokerThread::execute(const std::string &script, const std::vector &arguments) { if (m_invoker == NULL || script.empty()) @@ -44,17 +37,7 @@ bool CLanguageInvokerThread::execute(const std::string &script, const std::vecto m_script = script; m_args = arguments; - if (CThread::IsRunning()) - { - std::unique_lock lck(m_mutex); - m_restart = true; - m_condition.notify_one(); - } - else - Create(); - - //Todo wait until running - + Create(); return true; } @@ -66,16 +49,14 @@ bool CLanguageInvokerThread::stop(bool wait) if (!CThread::IsRunning()) return false; - Release(); - bool result = true; - if (m_invoker->GetState() < InvokerStateExecutionDone) + if (m_invoker->GetState() < InvokerStateDone) { // stop the language-specific invoker result = m_invoker->Stop(wait); + // stop the thread + CThread::StopThread(wait); } - // stop the thread - CThread::StopThread(wait); return result; } @@ -95,17 +76,7 @@ void CLanguageInvokerThread::Process() if (m_invoker == NULL) return; - std::unique_lock lckdl(m_mutex); - do { - m_restart = false; - m_invoker->Execute(m_script, m_args); - - if (m_invoker->GetState() != InvokerStateScriptDone) - m_reusable = false; - - m_condition.wait(lckdl, [this] {return m_bStop || m_restart || !m_reusable; }); - - } while (m_reusable && !m_bStop); + m_invoker->Execute(m_script, m_args); } void CLanguageInvokerThread::OnExit() @@ -114,7 +85,7 @@ void CLanguageInvokerThread::OnExit() return; m_invoker->onExecutionDone(); - m_invocationManager->OnExecutionDone(GetId()); + m_invocationManager->OnScriptEnded(GetId()); } void CLanguageInvokerThread::OnException() @@ -123,5 +94,5 @@ void CLanguageInvokerThread::OnException() return; m_invoker->onExecutionFailed(); - m_invocationManager->OnExecutionDone(GetId()); + m_invocationManager->OnScriptEnded(GetId()); } \ No newline at end of file diff --git a/xbmc/interfaces/generic/LanguageInvokerThread.h b/xbmc/interfaces/generic/LanguageInvokerThread.h index 72ef1a8cdf88a..e7f0d9eb48225 100644 --- a/xbmc/interfaces/generic/LanguageInvokerThread.h +++ b/xbmc/interfaces/generic/LanguageInvokerThread.h @@ -19,15 +19,10 @@ class CScriptInvocationManager; class CLanguageInvokerThread : public ILanguageInvoker, protected CThread { public: - CLanguageInvokerThread(LanguageInvokerPtr invoker, CScriptInvocationManager *invocationManager, bool reuseable); + CLanguageInvokerThread(LanguageInvokerPtr invoker, CScriptInvocationManager *invocationManager); ~CLanguageInvokerThread() override; - virtual InvokerState GetState() const; - - const std::string &GetScript() const { return m_script; }; - LanguageInvokerPtr GetInvoker() const { return m_invoker; }; - bool Reuseable(const std::string &script) const { return !m_bStop && m_reusable && GetState() == InvokerStateScriptDone && m_script == script; }; - virtual void Release(); + virtual InvokerState GetState(); protected: bool execute(const std::string &script, const std::vector &arguments) override; @@ -43,10 +38,4 @@ class CLanguageInvokerThread : public ILanguageInvoker, protected CThread CScriptInvocationManager *m_invocationManager; std::string m_script; std::vector m_args; - - std::mutex m_mutex; - std::condition_variable m_condition; - bool m_restart = false; - bool m_reusable = false; }; - diff --git a/xbmc/interfaces/generic/ScriptInvocationManager.cpp b/xbmc/interfaces/generic/ScriptInvocationManager.cpp index c30add2b25817..391a746cc1d7d 100644 --- a/xbmc/interfaces/generic/ScriptInvocationManager.cpp +++ b/xbmc/interfaces/generic/ScriptInvocationManager.cpp @@ -77,9 +77,6 @@ void CScriptInvocationManager::Uninitialize() // execute Process() once more to handle the remaining scripts Process(); - // it is safe to relese early, thread must be in m_scripts too - m_lastInvokerThread = nullptr; - // make sure all scripts are done std::vector tempList; for (LanguageInvokerThreadMap::iterator script = m_scripts.begin(); script != m_scripts.end(); ++script) @@ -99,11 +96,9 @@ void CScriptInvocationManager::Uninitialize() if (!it->done) it->thread->Stop(true); } - - lock.Enter(); - tempList.clear(); + lock.Enter(); // uninitialize all invocation handlers and then remove them for (LanguageInvocationHandlerMap::iterator it = m_invocationHandlers.begin(); it != m_invocationHandlers.end(); ++it) it->second->Uninitialize(); @@ -180,39 +175,12 @@ bool CScriptInvocationManager::HasLanguageInvoker(const std::string &script) con return it != m_invocationHandlers.end() && it->second != NULL; } -int CScriptInvocationManager::GetReusablePluginHandle(const std::string &script) +LanguageInvokerPtr CScriptInvocationManager::GetLanguageInvoker(const std::string &script) const { - CSingleLock lock(m_critSection); - - if (m_lastInvokerThread) - { - if (m_lastInvokerThread->Reuseable(script)) - return m_lastPluginHandle; - m_lastInvokerThread->Release(); - m_lastInvokerThread = nullptr; - } - return -1; -} - -LanguageInvokerPtr CScriptInvocationManager::GetLanguageInvoker(const std::string &script) -{ - CSingleLock lock(m_critSection); - - if (m_lastInvokerThread) - { - if (m_lastInvokerThread->Reuseable(script)) - { - CLog::Log(LOGDEBUG, "%s - Reusing LanguageInvokerThread %d for script %s", __FUNCTION__, m_lastInvokerThread->GetId(), script.c_str()); - m_lastInvokerThread->GetInvoker()->Reset(); - return m_lastInvokerThread->GetInvoker(); - } - m_lastInvokerThread->Release(); - m_lastInvokerThread = nullptr; - } - std::string extension = URIUtils::GetExtension(script); StringUtils::ToLower(extension); + CSingleLock lock(m_critSection); std::map::const_iterator it = m_invocationHandlers.find(extension); if (it != m_invocationHandlers.end() && it->second != NULL) return LanguageInvokerPtr(it->second->CreateInvoker()); @@ -220,11 +188,7 @@ LanguageInvokerPtr CScriptInvocationManager::GetLanguageInvoker(const std::strin return LanguageInvokerPtr(); } -int CScriptInvocationManager::ExecuteAsync(const std::string &script, - const ADDON::AddonPtr &addon /* = ADDON::AddonPtr() */, - const std::vector &arguments /* = std::vector() */, - bool reuseable /* = false */, - int pluginHandle /* = -1 */) +int CScriptInvocationManager::ExecuteAsync(const std::string &script, const ADDON::AddonPtr &addon /* = ADDON::AddonPtr() */, const std::vector &arguments /* = std::vector() */) { if (script.empty()) return -1; @@ -236,15 +200,10 @@ int CScriptInvocationManager::ExecuteAsync(const std::string &script, } LanguageInvokerPtr invoker = GetLanguageInvoker(script); - return ExecuteAsync(script, invoker, addon, arguments, reuseable, pluginHandle); + return ExecuteAsync(script, invoker, addon, arguments); } -int CScriptInvocationManager::ExecuteAsync(const std::string &script, - LanguageInvokerPtr languageInvoker, - const ADDON::AddonPtr &addon /* = ADDON::AddonPtr() */, - const std::vector &arguments /* = std::vector() */, - bool reuseable /* = false */, - int pluginHandle /* = -1 */) +int CScriptInvocationManager::ExecuteAsync(const std::string &script, LanguageInvokerPtr languageInvoker, const ADDON::AddonPtr &addon /* = ADDON::AddonPtr() */, const std::vector &arguments /* = std::vector() */) { if (script.empty() || languageInvoker == NULL) return -1; @@ -255,47 +214,26 @@ int CScriptInvocationManager::ExecuteAsync(const std::string &script, return -1; } - CSingleLock lock(m_critSection); - - if (m_lastInvokerThread && m_lastInvokerThread->GetInvoker() == languageInvoker) - { - if (addon != NULL) - m_lastInvokerThread->SetAddon(addon); - - // After we leave the lock, m_lastInvokerThread can be released -> copy! - CLanguageInvokerThreadPtr invokerThread = m_lastInvokerThread; - lock.Leave(); - invokerThread->Execute(script, arguments); - - return invokerThread->GetId(); - } - - m_lastInvokerThread = CLanguageInvokerThreadPtr(new CLanguageInvokerThread(languageInvoker, this, reuseable)); - if (m_lastInvokerThread == NULL) + CLanguageInvokerThreadPtr invokerThread = CLanguageInvokerThreadPtr(new CLanguageInvokerThread(languageInvoker, this)); + if (invokerThread == NULL) return -1; if (addon != NULL) - m_lastInvokerThread->SetAddon(addon); + invokerThread->SetAddon(addon); - m_lastInvokerThread->SetId(m_nextId++); - m_lastPluginHandle = pluginHandle; + CSingleLock lock(m_critSection); + invokerThread->SetId(m_nextId++); - LanguageInvokerThread thread = { m_lastInvokerThread, script, false }; - m_scripts.insert(std::make_pair(m_lastInvokerThread->GetId(), thread)); - m_scriptPaths.insert(std::make_pair(script, m_lastInvokerThread->GetId())); - // After we leave the lock, m_lastInvokerThread can be released -> copy! - CLanguageInvokerThreadPtr invokerThread = m_lastInvokerThread; + LanguageInvokerThread thread = { invokerThread, script, false }; + m_scripts.insert(std::make_pair(invokerThread->GetId(), thread)); + m_scriptPaths.insert(std::make_pair(script, invokerThread->GetId())); lock.Leave(); invokerThread->Execute(script, arguments); return invokerThread->GetId(); } -int CScriptInvocationManager::ExecuteSync(const std::string &script, - const ADDON::AddonPtr &addon /* = ADDON::AddonPtr() */, - const std::vector &arguments /* = std::vector() */, - uint32_t timeoutMs /* = 0 */, - bool waitShutdown /* = false */) +int CScriptInvocationManager::ExecuteSync(const std::string &script, const ADDON::AddonPtr &addon /* = ADDON::AddonPtr() */, const std::vector &arguments /* = std::vector() */, uint32_t timeoutMs /* = 0 */, bool waitShutdown /* = false */) { if (script.empty()) return -1; @@ -310,12 +248,7 @@ int CScriptInvocationManager::ExecuteSync(const std::string &script, return ExecuteSync(script, invoker, addon, arguments, timeoutMs, waitShutdown); } -int CScriptInvocationManager::ExecuteSync(const std::string &script, - LanguageInvokerPtr languageInvoker, - const ADDON::AddonPtr &addon /* = ADDON::AddonPtr() */, - const std::vector &arguments /* = std::vector() */, - uint32_t timeoutMs /* = 0 */, - bool waitShutdown /* = false */) +int CScriptInvocationManager::ExecuteSync(const std::string &script, LanguageInvokerPtr languageInvoker, const ADDON::AddonPtr &addon /* = ADDON::AddonPtr() */, const std::vector &arguments /* = std::vector() */, uint32_t timeoutMs /* = 0 */, bool waitShutdown /* = false */) { int scriptId = ExecuteAsync(script, languageInvoker, addon, arguments); if (scriptId < 0) @@ -389,7 +322,7 @@ bool CScriptInvocationManager::IsRunning(const std::string& scriptPath) const return IsRunning(it->second); } -void CScriptInvocationManager::OnExecutionDone(int scriptId) +void CScriptInvocationManager::OnScriptEnded(int scriptId) { if (scriptId < 0) return; diff --git a/xbmc/interfaces/generic/ScriptInvocationManager.h b/xbmc/interfaces/generic/ScriptInvocationManager.h index 63205d5f12cb7..cecb26061df06 100644 --- a/xbmc/interfaces/generic/ScriptInvocationManager.h +++ b/xbmc/interfaces/generic/ScriptInvocationManager.h @@ -32,12 +32,7 @@ class CScriptInvocationManager void RegisterLanguageInvocationHandler(ILanguageInvocationHandler *invocationHandler, const std::set &extensions); void UnregisterLanguageInvocationHandler(ILanguageInvocationHandler *invocationHandler); bool HasLanguageInvoker(const std::string &script) const; - LanguageInvokerPtr GetLanguageInvoker(const std::string &script); - - /*! - * \brief Returns addon_handle if last reusable invoker is ready to use. - */ - int GetReusablePluginHandle(const std::string &script); + LanguageInvokerPtr GetLanguageInvoker(const std::string &script) const; /*! * \brief Executes the given script asynchronously in a separate thread. @@ -47,11 +42,7 @@ class CScriptInvocationManager * \param arguments (Optional) List of arguments passed to the script * \return -1 if an error occurred, otherwise the ID of the script */ - int ExecuteAsync(const std::string &script, - const ADDON::AddonPtr &addon = ADDON::AddonPtr(), - const std::vector &arguments = std::vector(), - bool reuseable = false, - int pluginHandle = -1); + int ExecuteAsync(const std::string &script, const ADDON::AddonPtr &addon = ADDON::AddonPtr(), const std::vector &arguments = std::vector()); /*! * \brief Executes the given script asynchronously in a separate thread. * @@ -61,12 +52,7 @@ class CScriptInvocationManager * \param arguments (Optional) List of arguments passed to the script * \return -1 if an error occurred, otherwise the ID of the script */ - int ExecuteAsync(const std::string &script, - LanguageInvokerPtr languageInvoker, - const ADDON::AddonPtr &addon = ADDON::AddonPtr(), - const std::vector &arguments = std::vector(), - bool reuseable = false, - int pluginHandle = -1); + int ExecuteAsync(const std::string &script, LanguageInvokerPtr languageInvoker, const ADDON::AddonPtr &addon = ADDON::AddonPtr(), const std::vector &arguments = std::vector()); /*! * \brief Executes the given script synchronously. @@ -84,11 +70,7 @@ class CScriptInvocationManager * \param waitShutdown (Optional) Whether to wait when having to forcefully stop the script's execution or not. * \return -1 if an error occurred, 0 if the script terminated or ETIMEDOUT if the given timeout expired */ - int ExecuteSync(const std::string &script, - const ADDON::AddonPtr &addon = ADDON::AddonPtr(), - const std::vector &arguments = std::vector(), - uint32_t timeoutMs = 0, - bool waitShutdown = false); + int ExecuteSync(const std::string &script, const ADDON::AddonPtr &addon = ADDON::AddonPtr(), const std::vector &arguments = std::vector(), uint32_t timeoutMs = 0, bool waitShutdown = false); /*! * \brief Executes the given script synchronously. * @@ -106,12 +88,7 @@ class CScriptInvocationManager * \param waitShutdown (Optional) Whether to wait when having to forcefully stop the script's execution or not. * \return -1 if an error occurred, 0 if the script terminated or ETIMEDOUT if the given timeout expired */ - int ExecuteSync(const std::string &script, - LanguageInvokerPtr languageInvoker, - const ADDON::AddonPtr &addon = ADDON::AddonPtr(), - const std::vector &arguments = std::vector(), - uint32_t timeoutMs = 0, - bool waitShutdown = false); + int ExecuteSync(const std::string &script, LanguageInvokerPtr languageInvoker, const ADDON::AddonPtr &addon = ADDON::AddonPtr(), const std::vector &arguments = std::vector(), uint32_t timeoutMs = 0, bool waitShutdown = false); bool Stop(int scriptId, bool wait = false); bool Stop(const std::string &scriptPath, bool wait = false); @@ -121,7 +98,7 @@ class CScriptInvocationManager protected: friend class CLanguageInvokerThread; - void OnExecutionDone(int scriptId); + void OnScriptEnded(int scriptId); private: CScriptInvocationManager() = default; @@ -141,9 +118,6 @@ class CScriptInvocationManager LanguageInvocationHandlerMap m_invocationHandlers; LanguageInvokerThreadMap m_scripts; - CLanguageInvokerThreadPtr m_lastInvokerThread; - int m_lastPluginHandle; - std::map m_scriptPaths; int m_nextId = 0; mutable CCriticalSection m_critSection; diff --git a/xbmc/interfaces/python/AddonPythonInvoker.cpp b/xbmc/interfaces/python/AddonPythonInvoker.cpp index dbc5918a18dc6..b906f8438ca51 100644 --- a/xbmc/interfaces/python/AddonPythonInvoker.cpp +++ b/xbmc/interfaces/python/AddonPythonInvoker.cpp @@ -36,14 +36,14 @@ #define RUNSCRIPT_SETUPTOOLS_HACK \ "" \ - "import imp,sys\n" \ + "import types,sys\n" \ "pkg_resources_code = \\\n" \ "\"\"\"\n" \ "def resource_filename(__name__,__path__):\n" \ " return __path__\n" \ "\"\"\"\n" \ - "pkg_resources = imp.new_module('pkg_resources')\n" \ - "exec pkg_resources_code in pkg_resources.__dict__\n" \ + "pkg_resources = types.ModuleType('pkg_resources')\n" \ + "exec(pkg_resources_code, pkg_resources.__dict__)\n" \ "sys.modules['pkg_resources'] = pkg_resources\n" \ "" @@ -64,12 +64,12 @@ #endif namespace PythonBindings { - void initModule_xbmcdrm(void); - void initModule_xbmcgui(void); - void initModule_xbmc(void); - void initModule_xbmcplugin(void); - void initModule_xbmcaddon(void); - void initModule_xbmcvfs(void); + PyObject *PyInit_Module_xbmcdrm(void); + PyObject *PyInit_Module_xbmcgui(void); + PyObject *PyInit_Module_xbmc(void); + PyObject *PyInit_Module_xbmcplugin(void); + PyObject *PyInit_Module_xbmcaddon(void); + PyObject *PyInit_Module_xbmcvfs(void); } using namespace PythonBindings; @@ -82,17 +82,24 @@ typedef struct static PythonModule PythonModules[] = { - { "xbmcdrm", initModule_xbmcdrm }, - { "xbmcgui", initModule_xbmcgui }, - { "xbmc", initModule_xbmc }, - { "xbmcplugin", initModule_xbmcplugin }, - { "xbmcaddon", initModule_xbmcaddon }, - { "xbmcvfs", initModule_xbmcvfs } + { "xbmcdrm", PyInit_Module_xbmcdrm }, + { "xbmcgui", PyInit_Module_xbmcgui }, + { "xbmc", PyInit_Module_xbmc }, + { "xbmcplugin", PyInit_Module_xbmcplugin }, + { "xbmcaddon", PyInit_Module_xbmcaddon }, + { "xbmcvfs", PyInit_Module_xbmcvfs } }; CAddonPythonInvoker::CAddonPythonInvoker(ILanguageInvocationHandler *invocationHandler) : CPythonInvoker(invocationHandler) -{ } +{ + PyImport_AppendInittab("xbmcdrm", PyInit_Module_xbmcdrm); + PyImport_AppendInittab("xbmcgui", PyInit_Module_xbmcgui); + PyImport_AppendInittab("xbmc", PyInit_Module_xbmc); + PyImport_AppendInittab("xbmcplugin", PyInit_Module_xbmcplugin); + PyImport_AppendInittab("xbmcaddon", PyInit_Module_xbmcaddon); + PyImport_AppendInittab("xbmcvfs", PyInit_Module_xbmcvfs); +} CAddonPythonInvoker::~CAddonPythonInvoker() = default; diff --git a/xbmc/interfaces/python/ContextItemAddonInvoker.cpp b/xbmc/interfaces/python/ContextItemAddonInvoker.cpp index b40ddd0cdaf04..6165ec710ef1c 100644 --- a/xbmc/interfaces/python/ContextItemAddonInvoker.cpp +++ b/xbmc/interfaces/python/ContextItemAddonInvoker.cpp @@ -31,8 +31,7 @@ void CContextItemAddonInvoker::onPythonModuleInitialization(void* moduleDict) { XBMCAddon::xbmcgui::ListItem* arg = new XBMCAddon::xbmcgui::ListItem(m_item); PyObject* pyItem = PythonBindings::makePythonInstance(arg, true); - //! @bug libpython < 3.0 isn't const correct - if (pyItem == Py_None || PySys_SetObject(const_cast("listitem"), pyItem) == -1) + if (pyItem == Py_None || PySys_SetObject("listitem", pyItem) == -1) { CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): Failed to set sys parameter", GetId(), m_sourceFile.c_str()); //FIXME: we should really abort execution diff --git a/xbmc/interfaces/python/LanguageHook.cpp b/xbmc/interfaces/python/LanguageHook.cpp index 9d2fea240d08b..c54d60ab097be 100644 --- a/xbmc/interfaces/python/LanguageHook.cpp +++ b/xbmc/interfaces/python/LanguageHook.cpp @@ -125,7 +125,7 @@ namespace XBMCAddon // from the global dictionary PyObject* pyid = PyDict_GetItemString(global_dict, "__xbmcaddonid__"); if (pyid) - return PyString_AsString(pyid); + return PyUnicode_AsUTF8(pyid); return ""; } @@ -140,7 +140,7 @@ namespace XBMCAddon // from the global dictionary PyObject* pyversion = PyDict_GetItemString(global_dict, "__xbmcapiversion__"); if (pyversion) - return PyString_AsString(pyversion); + return PyUnicode_AsUTF8(pyversion); return ""; } diff --git a/xbmc/interfaces/python/PythonInvoker.cpp b/xbmc/interfaces/python/PythonInvoker.cpp index f4ec1e3270d99..4f14bd4d8d4b1 100644 --- a/xbmc/interfaces/python/PythonInvoker.cpp +++ b/xbmc/interfaces/python/PythonInvoker.cpp @@ -23,14 +23,14 @@ #include "windowing/GraphicContext.h" #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" +#include "interfaces/legacy/Addon.h" +#include "interfaces/python/LanguageHook.h" #include "interfaces/python/PyContext.h" #include "interfaces/python/pythreadstate.h" #include "interfaces/python/swig.h" #include "interfaces/python/XBPython.h" #include "threads/SingleLock.h" -#if defined(TARGET_WINDOWS) #include "utils/CharsetConverter.h" -#endif // defined(TARGET_WINDOWS) #include "utils/log.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" @@ -56,12 +56,6 @@ extern "C" FILE *fopen_utf8(const char *_Filename, const char *_Mode); using namespace XFILE; using namespace KODI::MESSAGING; -extern "C" -{ - int xbp_chdir(const char *dirname); - char* dll_getenv(const char* szKey); -} - #define PythonModulesSize sizeof(PythonModules) / sizeof(PythonModule) CCriticalSection CPythonInvoker::s_critical; @@ -84,23 +78,23 @@ static const std::string getListOfAddonClassesAsString(XBMCAddon::AddonClass::Re return message; } -static std::vector> storeArgumentsCCompatible(std::vector const & input) +static std::vector> storeArgumentsCCompatible(std::vector const & input) { - std::vector> output; + std::vector> output; std::transform(input.begin(), input.end(), std::back_inserter(output), - [](std::string const & i) { return std::vector(i.c_str(), i.c_str() + i.length() + 1); }); + [](std::wstring const & i) { return std::vector(i.c_str(), i.c_str() + i.length() + 1); }); if (output.empty()) - output.push_back(std::vector(1u, '\0')); + output.push_back(std::vector(1u, '\0')); return output; } -static std::vector getCPointersToArguments(std::vector> & input) +static std::vector getCPointersToArguments(std::vector> & input) { - std::vector output; + std::vector output; std::transform(input.begin(), input.end(), std::back_inserter(output), - [](std::vector & i) { return &i[0]; }); + [](std::vector & i) { return &i[0]; }); return output; } @@ -116,7 +110,7 @@ CPythonInvoker::~CPythonInvoker() if (GetId() < 0) return; - if (GetState() < InvokerStateExecutionDone) + if (GetState() < InvokerStateDone) CLog::Log(LOGDEBUG, "CPythonInvoker(%d): waiting for python thread \"%s\" to stop", GetId(), (!m_sourceFile.empty() ? m_sourceFile.c_str() : "unknown script")); Stop(true); @@ -143,133 +137,135 @@ bool CPythonInvoker::Execute(const std::string &script, const std::vector &arguments) +{ + std::vector w_arguments; + for (auto argument : arguments) + { + std::wstring w_argument; + g_charsetConverter.utf8ToW(argument, w_argument); + w_arguments.push_back(w_argument); + } + return execute(script, w_arguments); +} + +bool CPythonInvoker::execute(const std::string &script, const std::vector &arguments) { // copy the code/script into a local string buffer m_sourceFile = script; - m_pythonPath.clear(); // copy the arguments into a local buffer unsigned int argc = arguments.size(); - std::vector> argvStorage = storeArgumentsCCompatible(arguments); - std::vector argv = getCPointersToArguments(argvStorage); + std::vector> argvStorage = storeArgumentsCCompatible(arguments); + std::vector argv = getCPointersToArguments(argvStorage); CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): start processing", GetId(), m_sourceFile.c_str()); - std::string realFilename(CSpecialProtocol::TranslatePath(m_sourceFile)); - std::string scriptDir = URIUtils::GetDirectory(realFilename); - URIUtils::RemoveSlashAtEnd(scriptDir); - // get the global lock - PyEval_AcquireLock(); - if (!m_threadState) + extern PyThreadState* savestate; + PyEval_RestoreThread(savestate); + PyThreadState* state = Py_NewInterpreter(); + if (state == NULL) { - m_threadState = Py_NewInterpreter(); - if (m_threadState == NULL) - { - PyEval_ReleaseLock(); - CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): FAILED to get thread m_threadState!", GetId(), m_sourceFile.c_str()); - return false; - } - // swap in my thread m_threadState - PyThreadState_Swap(m_threadState); + PyEval_ReleaseLock(); + CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): FAILED to get thread state!", GetId(), m_sourceFile.c_str()); + return false; + } + // swap in my thread state + PyThreadState_Swap(state); - m_languageHook = new XBMCAddon::Python::PythonLanguageHook(m_threadState->interp); - m_languageHook->RegisterMe(); + XBMCAddon::AddonClass::Ref languageHook(new XBMCAddon::Python::PythonLanguageHook(state->interp)); + languageHook->RegisterMe(); - onInitialization(); - setState(InvokerStateInitialized); + onInitialization(); + setState(InvokerStateInitialized); - if (realFilename == m_sourceFile) - CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): the source file to load is \"%s\"", GetId(), m_sourceFile.c_str(), m_sourceFile.c_str()); - else - CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): the source file to load is \"%s\" (\"%s\")", GetId(), m_sourceFile.c_str(), m_sourceFile.c_str(), realFilename.c_str()); + std::string realFilename(CSpecialProtocol::TranslatePath(m_sourceFile)); + if (realFilename == m_sourceFile) + CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): the source file to load is \"%s\"", GetId(), m_sourceFile.c_str(), m_sourceFile.c_str()); + else + CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): the source file to load is \"%s\" (\"%s\")", GetId(), m_sourceFile.c_str(), m_sourceFile.c_str(), realFilename.c_str()); - // get path from script file name and add python path's - // this is used for python so it will search modules from script path first - addPath(scriptDir); + // get path from script file name and add python path's + // this is used for python so it will search modules from script path first + std::string scriptDir = URIUtils::GetDirectory(realFilename); + URIUtils::RemoveSlashAtEnd(scriptDir); + addPath(scriptDir); - // add all addon module dependencies to path - if (m_addon) - { - std::set paths; - getAddonModuleDeps(m_addon, paths); - for (std::set::const_iterator it = paths.begin(); it != paths.end(); ++it) - addPath(*it); - } - else - { // for backwards compatibility. - // we don't have any addon so just add all addon modules installed - CLog::Log(LOGWARNING, "CPythonInvoker(%d): Script invoked without an addon. Adding all addon " + // add all addon module dependencies to path + if (m_addon) + { + std::set paths; + getAddonModuleDeps(m_addon, paths); + for (std::set::const_iterator it = paths.begin(); it != paths.end(); ++it) + addPath(*it); + } + else + { // for backwards compatibility. + // we don't have any addon so just add all addon modules installed + CLog::Log(LOGWARNING, "CPythonInvoker(%d): Script invoked without an addon. Adding all addon " "modules installed to python path as fallback. This behaviour will be removed in future " "version.", GetId()); - ADDON::VECADDONS addons; - CServiceBroker::GetAddonMgr().GetAddons(addons, ADDON::ADDON_SCRIPT_MODULE); - for (unsigned int i = 0; i < addons.size(); ++i) - addPath(CSpecialProtocol::TranslatePath(addons[i]->LibPath())); - } + ADDON::VECADDONS addons; + CServiceBroker::GetAddonMgr().GetAddons(addons, ADDON::ADDON_SCRIPT_MODULE); + for (unsigned int i = 0; i < addons.size(); ++i) + addPath(CSpecialProtocol::TranslatePath(addons[i]->LibPath())); + } - // we want to use sys.path so it includes site-packages - // if this fails, default to using Py_GetPath - PyObject *sysMod(PyImport_ImportModule("sys")); // must call Py_DECREF when finished - PyObject *sysModDict(PyModule_GetDict(sysMod)); // borrowed ref, no need to delete - PyObject *pathObj(PyDict_GetItemString(sysModDict, "path")); // borrowed ref, no need to delete + // we want to use sys.path so it includes site-packages + // if this fails, default to using Py_GetPath + PyObject *sysMod(PyImport_ImportModule("sys")); // must call Py_DECREF when finished + PyObject *sysModDict(PyModule_GetDict(sysMod)); // borrowed ref, no need to delete + PyObject *pathObj(PyDict_GetItemString(sysModDict, "path")); // borrowed ref, no need to delete - if (pathObj != NULL && PyList_Check(pathObj)) + if (pathObj != NULL && PyList_Check(pathObj)) + { + for (int i = 0; i < PyList_Size(pathObj); i++) { - for (int i = 0; i < PyList_Size(pathObj); i++) - { - PyObject *e = PyList_GetItem(pathObj, i); // borrowed ref, no need to delete - if (e != NULL && PyString_Check(e)) - addNativePath(PyString_AsString(e)); // returns internal data, don't delete or modify -#ifdef TARGET_WINDOWS_STORE - // uwp python operates unicodes - else if (e != NULL && PyUnicode_Check(e)) - { - PyObject *utf8 = PyUnicode_AsUTF8String(e); - addNativePath(PyString_AsString(utf8)); - Py_DECREF(utf8); - } -#endif - } + PyObject *e = PyList_GetItem(pathObj, i); // borrowed ref, no need to delete + if (e != NULL && PyUnicode_Check(e)) + addNativePath(PyUnicode_AsUTF8(e)); // returns internal data, don't delete or modify } - else - addNativePath(Py_GetPath()); + } + else + { + std::string GetPath; + g_charsetConverter.wToUTF8(Py_GetPath(), GetPath); + addNativePath(GetPath); + } - Py_DECREF(sysMod); // release ref to sysMod + Py_DECREF(sysMod); // release ref to sysMod + + // set current directory and python's path. + PySys_SetArgv(argc, &argv[0]); #ifdef TARGET_WINDOWS - std::string pyPathUtf8; - g_charsetConverter.systemToUtf8(m_pythonPath, pyPathUtf8, false); - CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): setting the Python path to %s", GetId(), m_sourceFile.c_str(), pyPathUtf8.c_str()); + std::string pyPathUtf8; + g_charsetConverter.systemToUtf8(m_pythonPath, pyPathUtf8, false); + CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): setting the Python path to %s", GetId(), m_sourceFile.c_str(), pyPathUtf8.c_str()); #else // ! TARGET_WINDOWS - CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): setting the Python path to %s", GetId(), m_sourceFile.c_str(), m_pythonPath.c_str()); + CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): setting the Python path to %s", GetId(), m_sourceFile.c_str(), m_pythonPath.c_str()); #endif // ! TARGET_WINDOWS - //! @bug libpython < 3.0 isn't const correct - PySys_SetPath(const_cast(m_pythonPath.c_str())); - } - else - // swap in my thread m_threadState - PyThreadState_Swap(m_threadState); - // set current directory and python's path. - PySys_SetArgv(argc, &argv[0]); + std::wstring pypath; + g_charsetConverter.utf8ToW(m_pythonPath, pypath); + PySys_SetPath(pypath.c_str()); CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): entering source directory %s", GetId(), m_sourceFile.c_str(), scriptDir.c_str()); PyObject* module = PyImport_AddModule("__main__"); PyObject* moduleDict = PyModule_GetDict(module); - // when we are done initing we store thread m_threadState so we can be aborted + // when we are done initing we store thread state so we can be aborted PyThreadState_Swap(NULL); PyEval_ReleaseLock(); // we need to check if we was asked to abort before we had inited bool stopping = false; { CSingleLock lock(m_critical); + m_threadState = state; stopping = m_stop; } - PyEval_AcquireLock(); - PyThreadState_Swap(m_threadState); + PyEval_AcquireThread(state); bool failed = false; std::string exceptionType, exceptionValue, exceptionTraceback; @@ -289,13 +285,11 @@ bool CPythonInvoker::execute(const std::string &script, const std::vector(nativeFilename.c_str()), const_cast("r")); - FILE *fp = PyFile_AsFile(file); + FILE *fp = _Py_fopen(nativeFilename.c_str(), "r"); if (fp != NULL) { - PyObject *f = PyString_FromString(nativeFilename.c_str()); + PyObject *f = PyUnicode_FromString(nativeFilename.c_str()); PyDict_SetItemString(moduleDict, "__file__", f); onPythonModuleInitialization(moduleDict); @@ -303,7 +297,7 @@ bool CPythonInvoker::execute(const std::string &script, const std::vectorinterp->tstate_head, *old = NULL; s;) + { + if (s == state) { - PyThreadState *s = m_threadState->interp->tstate_head; - for (; s && s == m_threadState;) - s = s->next; - - if (!s) - break; + s = s->next; + continue; + } + if (old != s) + { + CLog::Log(LOGINFO, "CPythonInvoker(%d, %s): waiting on thread %" PRIu64, GetId(), m_sourceFile.c_str(), (uint64_t)s->thread_id); + old = s; + } - if (old != s) - { - CLog::Log(LOGINFO, "CPythonInvoker(%d, %s): waiting on thread %" PRIu64, GetId(), m_sourceFile.c_str(), (uint64_t)s->thread_id); - old = s; - } + CPyThreadState pyState; + Sleep(100); + pyState.Restore(); - lock.Leave(); - CPyThreadState pyState; - Sleep(100); - pyState.Restore(); - lock.Enter(); - } + s = state->interp->tstate_head; } // pending calls must be cleared out - XBMCAddon::RetardedAsyncCallbackHandler::clearPendingCalls(m_threadState); + XBMCAddon::RetardedAsyncCallbackHandler::clearPendingCalls(state); PyThreadState_Swap(NULL); PyEval_ReleaseLock(); + // set stopped event - this allows ::stop to run and kill remaining threads + // this event has to be fired without holding m_critical + // also the GIL (PyEval_AcquireLock) must not be held + // if not obeyed there is still no deadlock because ::stop waits with timeout (smart one!) + m_stoppedEvent.Set(); + + { CSingleLock lock(m_critical); + m_threadState = NULL; + } + + PyEval_AcquireThread(state); + + onDeinitialization(); + + // run the gc before finishing + // + // if the script exited by throwing a SystemExit exception then going back + // into the interpreter causes this python bug to get hit: + // http://bugs.python.org/issue10582 + // and that causes major failures. So we are not going to go back in + // to run the GC if that's the case. + if (!m_stop && languageHook->HasRegisteredAddonClasses() && !systemExitThrown && + PyRun_SimpleString(GC_SCRIPT) == -1) + CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failed to run the gc to clean up after running prior to shutting down the Interpreter", GetId(), m_sourceFile.c_str()); + + Py_EndInterpreter(state); + + // If we still have objects left around, produce an error message detailing what's been left behind + if (languageHook->HasRegisteredAddonClasses()) + CLog::Log(LOGWARNING, "CPythonInvoker(%d, %s): the python script \"%s\" has left several " + "classes in memory that we couldn't clean up. The classes include: %s", + GetId(), m_sourceFile.c_str(), m_sourceFile.c_str(), getListOfAddonClassesAsString(languageHook).c_str()); + + // unregister the language hook + languageHook->UnregisterMe(); + + PyEval_ReleaseLock(); + setState(stateToSet); return true; } -void CPythonInvoker::executeScript(void *fp, const std::string &script, void *module, void *moduleDict) +void CPythonInvoker::executeScript(FILE *fp, const std::string &script, PyObject *moduleDict) { - if (fp == NULL || script.empty() || module == NULL || moduleDict == NULL) + if (fp == NULL || script.empty() || moduleDict == NULL) return; int m_Py_file_input = Py_file_input; - PyRun_FileExFlags(static_cast(fp), script.c_str(), m_Py_file_input, static_cast(moduleDict), static_cast(moduleDict), 1, NULL); + PyRun_FileExFlags(fp, script.c_str(), m_Py_file_input, moduleDict, moduleDict, 1, NULL); +} + +FILE* CPythonInvoker::PyFile_AsFileWithMode(PyObject *py_file, const char *mode) +{ + PyObject* ret = PyObject_CallMethod(py_file, "flush", ""); + if (ret == NULL) + return NULL; + Py_DECREF(ret); + + int fd = PyObject_AsFileDescriptor(py_file); + if (fd == -1) + return NULL; + + FILE* f = fdopen(fd, mode); + if (f == NULL) + { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + return f; } bool CPythonInvoker::stop(bool abort) @@ -420,38 +467,28 @@ bool CPythonInvoker::stop(bool abort) CSingleLock lock(m_critical); m_stop = true; - if (!IsRunning() && !m_threadState) + if (!IsRunning()) return false; + setState(InvokerStateStopping); + if (m_threadState != NULL) { - if (IsRunning()) - { - setState(InvokerStateStopping); - - lock.Leave(); + PyEval_AcquireLock(); + PyThreadState* old = PyThreadState_Swap((PyThreadState*)m_threadState); - PyEval_AcquireLock(); - PyThreadState* old = PyThreadState_Swap((PyThreadState*)m_threadState); + //tell xbmc.Monitor to call onAbortRequested() + if (m_addon != NULL) + onAbortRequested(); - //tell xbmc.Monitor to call onAbortRequested() - if (m_addon) - { - CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): trigger Monitor abort request", GetId(), m_sourceFile.c_str()); - onAbortRequested(); - } - - PyObject *m; - m = PyImport_AddModule("xbmc"); - if (m == NULL || PyObject_SetAttrString(m, "abortRequested", PyBool_FromLong(1))) - CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failed to set abortRequested", GetId(), m_sourceFile.c_str()); + PyObject *m; + m = PyImport_AddModule("xbmc"); + if (m == NULL || PyObject_SetAttrString(m, "abortRequested", PyBool_FromLong(1))) + CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failed to set abortRequested", GetId(), m_sourceFile.c_str()); - PyThreadState_Swap(old); - PyEval_ReleaseLock(); - } - else - //Release the lock while waiting for threads to finish - lock.Leave(); + PyThreadState_Swap(old); + old = NULL; + PyEval_ReleaseLock(); XbmcThreads::EndTime timeout(PYTHON_SCRIPT_TIMEOUT); while (!m_stoppedEvent.WaitMSec(15)) @@ -471,22 +508,22 @@ bool CPythonInvoker::stop(bool abort) } } - // grabbing the PyLock while holding the m_critical is asking for a deadlock - PyEval_AcquireLock(); - - lock.Enter(); - - setState(InvokerStateExecutionDone); - // Useful for add-on performance metrics if (!timeout.IsTimePast()) CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): script termination took %dms", GetId(), m_sourceFile.c_str(), PYTHON_SCRIPT_TIMEOUT - timeout.MillisLeft()); + // everything which didn't exit by now gets killed + { + // grabbing the PyLock while holding the m_critical is asking for a deadlock + CSingleExit ex2(m_critical); + PyEval_AcquireLock(); + } + // Since we released the m_critical it's possible that the state is cleaned up // so we need to recheck for m_threadState == NULL if (m_threadState != NULL) { - PyThreadState* old = PyThreadState_Swap((PyThreadState*)m_threadState); + old = PyThreadState_Swap((PyThreadState*)m_threadState); for (PyThreadState* state = ((PyThreadState*)m_threadState)->interp->tstate_head; state; state = state->next) { // Raise a SystemExit exception in python threads @@ -494,71 +531,21 @@ bool CPythonInvoker::stop(bool abort) state->async_exc = PyExc_SystemExit; Py_XINCREF(state->async_exc); } - PyThreadState_Swap(old); // If a dialog entered its doModal(), we need to wake it to see the exception pulseGlobalEvent(); - m_threadState = nullptr; } + + if (old != NULL) + PyThreadState_Swap(old); + lock.Leave(); PyEval_ReleaseLock(); - - setState(InvokerStateFailed); } return true; } -// Always called from Invoker thread -void CPythonInvoker::onExecutionDone() -{ - CSingleLock lock(m_critical); - if (m_threadState != NULL) - { - CLog::Log(LOGDEBUG, "%s(%d, %s)", __FUNCTION__, GetId(), m_sourceFile.c_str()); - - PyEval_AcquireLock(); - PyThreadState_Swap(m_threadState); - - onDeinitialization(); - - // run the gc before finishing - // - // if the script exited by throwing a SystemExit exception then going back - // into the interpreter causes this python bug to get hit: - // http://bugs.python.org/issue10582 - // and that causes major failures. So we are not going to go back in - // to run the GC if that's the case. - if (!m_stop && m_languageHook->HasRegisteredAddonClasses() && !m_systemExitThrown && - PyRun_SimpleString(GC_SCRIPT) == -1) - CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failed to run the gc to clean up after running prior to shutting down the Interpreter", GetId(), m_sourceFile.c_str()); - - Py_EndInterpreter(m_threadState); - - // If we still have objects left around, produce an error message detailing what's been left behind - if (m_languageHook->HasRegisteredAddonClasses()) - CLog::Log(LOGWARNING, "CPythonInvoker(%d, %s): the python script \"%s\" has left several " - "classes in memory that we couldn't clean up. The classes include: %s", - GetId(), m_sourceFile.c_str(), m_sourceFile.c_str(), getListOfAddonClassesAsString(m_languageHook).c_str()); - - // unregister the language hook - m_languageHook->UnregisterMe(); - - PyEval_ReleaseLock(); - - // set stopped event - this allows ::stop to run and kill remaining threads - // this event has to be fired without holding m_critical - // also the GIL (PyEval_AcquireLock) must not be held - // if not obeyed there is still no deadlock because ::stop waits with timeout (smart one!) - m_stoppedEvent.Set(); - - m_threadState = nullptr; - - setState(InvokerStateExecutionDone); - } - ILanguageInvoker::onExecutionDone(); -} - void CPythonInvoker::onExecutionFailed() { PyThreadState_Swap(NULL); @@ -573,12 +560,6 @@ void CPythonInvoker::onExecutionFailed() ILanguageInvoker::onExecutionFailed(); } -std::map CPythonInvoker::getModules() const -{ - static std::map modules; - return modules; -} - void CPythonInvoker::onInitialization() { XBMC_TRACE; @@ -604,11 +585,11 @@ void CPythonInvoker::onPythonModuleInitialization(void* moduleDict) PyObject *moduleDictionary = (PyObject *)moduleDict; - PyObject *pyaddonid = PyString_FromString(m_addon->ID().c_str()); + PyObject *pyaddonid = PyUnicode_FromString(m_addon->ID().c_str()); PyDict_SetItemString(moduleDictionary, "__xbmcaddonid__", pyaddonid); ADDON::AddonVersion version = m_addon->GetDependencyVersion("xbmc.python"); - PyObject *pyxbmcapiversion = PyString_FromString(version.asString().c_str()); + PyObject *pyxbmcapiversion = PyUnicode_FromString(version.asString().c_str()); PyDict_SetItemString(moduleDictionary, "__xbmcapiversion__", pyxbmcapiversion); PyObject *pyinvokerid = PyLong_FromLong(GetId()); @@ -642,11 +623,6 @@ void CPythonInvoker::onError(const std::string &exceptionType /* = "" */, const } } -const char* CPythonInvoker::getInitializationScript() const -{ - return NULL; -} - void CPythonInvoker::initializeModules(const std::map &modules) { for (std::map::const_iterator module = modules.begin(); module != modules.end(); ++module) @@ -661,8 +637,7 @@ bool CPythonInvoker::initializeModule(PythonModuleInitialization module) if (module == NULL) return false; - module(); - return true; + return module() != nullptr; } void CPythonInvoker::getAddonModuleDeps(const ADDON::AddonPtr& addon, std::set& paths) diff --git a/xbmc/interfaces/python/PythonInvoker.h b/xbmc/interfaces/python/PythonInvoker.h index 3dc1dda4b03a4..faa5960d5f5a2 100644 --- a/xbmc/interfaces/python/PythonInvoker.h +++ b/xbmc/interfaces/python/PythonInvoker.h @@ -13,12 +13,10 @@ #include #include "interfaces/generic/ILanguageInvoker.h" -#include "interfaces/python/LanguageHook.h" -#include "interfaces/legacy/Addon.h" #include "threads/CriticalSection.h" #include "threads/Event.h" -struct _ts; +typedef struct _object PyObject; class CPythonInvoker : public ILanguageInvoker { @@ -30,19 +28,18 @@ class CPythonInvoker : public ILanguageInvoker bool IsStopping() const override { return m_stop || ILanguageInvoker::IsStopping(); } - typedef void (*PythonModuleInitialization)(); + typedef PyObject* (*PythonModuleInitialization)(); protected: // implementation of ILanguageInvoker bool execute(const std::string &script, const std::vector &arguments) override; - virtual void executeScript(void *fp, const std::string &script, void *module, void *moduleDict); + virtual void executeScript(FILE *fp, const std::string &script, PyObject* moduleDict); bool stop(bool abort) override; - void onExecutionDone() override; void onExecutionFailed() override; // custom virtual methods - virtual std::map getModules() const; - virtual const char* getInitializationScript() const; + virtual std::map getModules() const = 0; + virtual const char* getInitializationScript() const = 0; virtual void onInitialization(); // actually a PyObject* but don't wanna draw Python.h include into the header virtual void onPythonModuleInitialization(void* moduleDict); @@ -61,14 +58,13 @@ class CPythonInvoker : public ILanguageInvoker void addPath(const std::string& path); // add path in UTF-8 encoding void addNativePath(const std::string& path); // add path in system/Python encoding void getAddonModuleDeps(const ADDON::AddonPtr& addon, std::set& paths); + bool execute(const std::string &script, const std::vector &arguments); + FILE* PyFile_AsFileWithMode(PyObject *py_file, const char *mode); std::string m_pythonPath; - _ts *m_threadState; + void *m_threadState; bool m_stop; CEvent m_stoppedEvent; - XBMCAddon::AddonClass::Ref m_languageHook; - bool m_systemExitThrown = false; - static CCriticalSection s_critical; }; diff --git a/xbmc/interfaces/python/PythonSwig.cpp.template b/xbmc/interfaces/python/PythonSwig.cpp.template index f1d0d91f2645c..9e1e4ddb9962c 100644 --- a/xbmc/interfaces/python/PythonSwig.cpp.template +++ b/xbmc/interfaces/python/PythonSwig.cpp.template @@ -45,8 +45,8 @@ Helper.setup(this,classes, * of the native call to be returned to the python caller. */ [ 'void' : 'Py_INCREF(Py_None);\n ${result} = Py_None;', - 'long': '${result} = PyInt_FromLong(${api});', - 'unsigned long': '${result} = PyInt_FromLong(${api});', + 'long': '${result} = PyLong_FromLong(${api});', + 'unsigned long': '${result} = PyLong_FromLong(${api});', 'bool': '${result} = Py_BuildValue("b", ${api});', 'long long': '${result} = Py_BuildValue("L", ${api});', 'int': '${result} = Py_BuildValue("i", ${api});', @@ -54,7 +54,7 @@ Helper.setup(this,classes, 'double': '${result} = PyFloat_FromDouble(${api});', 'float': '${result} = Py_BuildValue("f", ${api});', 'std::string' : new File('typemaps/python.string.outtm'), - 'p.q(const).char' : '${result} = PyString_FromString(${api});', + 'p.q(const).char' : '${result} = PyUnicode_FromString(${api});', (Pattern.compile('''(p.){0,1}XbmcCommons::Buffer''')) : new File('typemaps/python.buffer.outtm'), (Pattern.compile('''std::shared_ptr<\\(.*\\)>''')) : new File('typemaps/python.smart_ptr.outtm'), (Pattern.compile('''std::unique_ptr<\\(.*\\)>''')) : new File('typemaps/python.smart_ptr.outtm'), @@ -79,15 +79,15 @@ Helper.setup(this,classes, (Pattern.compile('''(p.){0,1}std::map<\\(.*\\)>''')) : new File('typemaps/python.map.intm'), (Pattern.compile('''(r.){0,1}XBMCAddon::Dictionary<\\(.*\\)>''')) : new File('typemaps/python.dict.intm'), (Pattern.compile('''p.void''')) : '${api} = (void*)${slarg};', - 'bool' : '${api} = (PyInt_AsLong(${slarg}) == 0L ? false : true);', - 'long' : '${api} = PyInt_AsLong(${slarg});', + 'bool' : '${api} = (PyLong_AsLong(${slarg}) == 0L ? false : true);', + 'long' : '${api} = PyLong_AsLong(${slarg});', 'unsigned long' : '${api} = PyLong_AsUnsignedLong(${slarg});', 'long long' : '${api} = PyLong_AsLongLong(${slarg});', 'unsigned long long' : '${api} = PyLong_AsUnsignedLongLong(${slarg});', - 'int' : '${api} = (int)PyInt_AsLong(${slarg});', + 'int' : '${api} = (int)PyLong_AsLong(${slarg});', 'double' : '${api} = PyFloat_AsDouble(${slarg});', 'float' : '${api} = (float)PyFloat_AsDouble(${slarg});', - 'XBMCAddon::StringOrInt' : 'if (${slarg}) PyXBMCGetUnicodeString(${api},${slarg},PyInt_Check(${slarg}) || PyLong_Check(${slarg}) || PyFloat_Check(${slarg}),"${api}","${method.@name}");' + 'XBMCAddon::StringOrInt' : 'if (${slarg}) PyXBMCGetUnicodeString(${api},${slarg},PyLong_Check(${slarg}) || PyLong_Check(${slarg}) || PyFloat_Check(${slarg}),"${api}","${method.@name}");' ], '${api} = (${swigTypeParser.SwigType_str(ltype)})retrieveApiInstance(${slarg},"${ltype}","${helper.findNamespace(method)}","${helper.callingName(method)}");') // --------------------------------------------------------- @@ -262,7 +262,7 @@ void doMethod(Node method, MethodType methodType) return result; <% } else { %> - self->ob_type->tp_free((PyObject*)self); + (((PyObject*)(self))->ob_type)->tp_free((PyObject*)self); <% } %> @@ -653,22 +653,13 @@ void doClassMethodInfo(Node clazz, List initTypeCalls) pythonType.tp_name = "${module.@name}.${clazz.@sym_name}"; pythonType.tp_basicsize = sizeof(PyHolder); pythonType.tp_dealloc = (destructor)${module.@name}_${classNameAsVariable}_Dealloc; <% - if (doComparator) { %> - pythonType.tp_compare=${module.@name}_${classNameAsVariable}_cmp;<% - } + if (clazz.@feature_python_rcmp) { %> pythonType.tp_richcompare=(richcmpfunc)${module.@name}_${classNameAsVariable}_rcmp;<% } %> -<% - if (clazz.@feature_iterator) { %> - pythonType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_ITER; -<% - } - else { %> pythonType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; -<% - } %> + pythonType.tp_doc = ${Helper.hasDoc(clazz) ? (classNameAsVariable + '__doc__') : 'NULL' }; pythonType.tp_methods = ${classNameAsVariable}_methods; <% if (properties.size() > 0) { %> @@ -829,8 +820,7 @@ namespace PythonBindings } %> XBMCAddon::Python::PyContext pyContext; - //! @bug libpython < 3.4 isn't const correct - PyObject_CallMethod(self,const_cast("${Helper.callingName(it)}"),const_cast("(${paramFormatStr})")<% + PyObject_CallMethod(self,"${Helper.callingName(it)}","(${paramFormatStr})"<% params.each { %>, py${it.@name} <% } @@ -896,7 +886,16 @@ namespace PythonBindings } } - void initModule_${module.@name}() + static struct PyModuleDef createModule + { + PyModuleDef_HEAD_INIT, + "${module.@name}", + "", + -1, + ${module.@name}_methods + }; + + PyObject *PyInit_Module_${module.@name}() { initTypes(); @@ -907,8 +906,8 @@ namespace PythonBindings Py_INCREF(&(Ty${it}_Type.pythonType));<% }%> - module = Py_InitModule("${module.@name}", ${module.@name}_methods); - if (module == NULL) return; + module = PyModule_Create(&createModule); + if (module == NULL) return NULL; <% classes.each { clazz -> %> PyModule_AddObject(module, "${clazz.@sym_name}", (PyObject*)(&(Ty${PythonTools.getClassNameAsVariable(clazz)}_Type.pythonType)));<% @@ -928,6 +927,7 @@ namespace PythonBindings 'PyModule_AddIntConstant' : 'PyModule_AddStringConstant' %> ${pyCall}(module,"${it.@sym_name}",${it.@value}); <% } %> + return module; } } // end PythonBindings namespace for python type definitions diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp index 81e0d7c55e7d4..93e2043a58ad3 100644 --- a/xbmc/interfaces/python/XBPython.cpp +++ b/xbmc/interfaces/python/XBPython.cpp @@ -35,6 +35,8 @@ #include "interfaces/python/PythonInvoker.h" #include "ServiceBroker.h" +PyThreadState* savestate; + XBPython::XBPython() { m_bInitialized = false; @@ -408,22 +410,6 @@ void XBPython::OnNotification(const std::string &sender, const std::string &meth } } -/** -* Check for file and print an error if needed -*/ -bool XBPython::FileExist(const char* strFile) -{ - if (!strFile) - return false; - - if (!XFILE::CFile::Exists(strFile)) - { - CLog::Log(LOGERROR, "Python: Cannot find '%s'", strFile); - return false; - } - return true; -} - void XBPython::RegisterExtensionLib(LibraryLoader *pLib) { if (!pLib) @@ -482,8 +468,7 @@ void XBPython::Finalize() m_mainThreadState = NULL; // clear the main thread state before releasing the lock { CSingleExit exit(m_critSection); - PyEval_AcquireLock(); - PyThreadState_Swap(curTs); + PyEval_AcquireThread(curTs); Py_Finalize(); PyEval_ReleaseLock(); @@ -499,7 +484,7 @@ void XBPython::Finalize() #endif #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN) && !defined(TARGET_FREEBSD) // we can't release it on windows, as this is done in UnloadPythonDlls() for win32 (see above). - // The implementation for linux needs looking at - UnloadPythonDlls() currently only searches for "python26.dll" + // The implementation for linux needs looking at - UnloadPythonDlls() currently only searches for "python36.dll" // The implementation for osx can never unload the python dylib. DllLoaderContainer::ReleaseModule(m_pDll); #endif @@ -564,21 +549,6 @@ bool XBPython::OnScriptInitialized(ILanguageInvoker *invoker) m_iDllScriptCounter++; if (!m_bInitialized) { - // first we check if all necessary files are installed -#ifndef TARGET_POSIX - if (!FileExist("special://xbmc/system/python/DLLs/_socket.pyd") || - !FileExist("special://xbmc/system/python/DLLs/_ssl.pyd") || - !FileExist("special://xbmc/system/python/DLLs/bz2.pyd") || - !FileExist("special://xbmc/system/python/DLLs/pyexpat.pyd") || - !FileExist("special://xbmc/system/python/DLLs/select.pyd") || - !FileExist("special://xbmc/system/python/DLLs/unicodedata.pyd")) - { - CLog::Log(LOGERROR, "Python: Missing files, unable to execute script"); - Finalize(); - return false; - } -#endif - // Darwin packs .pyo files, we need PYTHONOPTIMIZE on in order to load them. // linux built with unified builds only packages the pyo files so need it #if defined(TARGET_DARWIN) || defined(TARGET_LINUX) @@ -595,8 +565,8 @@ bool XBPython::OnScriptInitialized(ILanguageInvoker *invoker) // check if we are running as real xbmc.app or just binary if (!CUtil::GetFrameworksPath(true).empty()) { - // using external python, it's build looking for xxx/lib/python2.6 - // so point it to frameworks which is where python2.6 is located + // using external python, it's build looking for xxx/lib/python3.7 + // so point it to frameworks which is where python3.7 is located setenv("PYTHONHOME", CSpecialProtocol::TranslatePath("special://frameworks").c_str(), 1); setenv("PYTHONPATH", CSpecialProtocol::TranslatePath("special://frameworks").c_str(), 1); CLog::Log(LOGDEBUG, "PYTHONHOME -> %s", CSpecialProtocol::TranslatePath("special://frameworks").c_str()); @@ -606,7 +576,7 @@ bool XBPython::OnScriptInitialized(ILanguageInvoker *invoker) // because the third party build of python is compiled with vs2008 we need // a hack to set the PYTHONPATH std::string buf; - buf = "PYTHONPATH=" + CSpecialProtocol::TranslatePath("special://xbmc/system/python/DLLs") + ";" + CSpecialProtocol::TranslatePath("special://xbmc/system/python/Lib"); + buf = "PYTHONPATH=" + CSpecialProtocol::TranslatePath("special://xbmc/system/python/Lib"); CEnvironment::putenv(buf); buf = "PYTHONOPTIMIZE=1"; CEnvironment::putenv(buf); @@ -620,25 +590,22 @@ bool XBPython::OnScriptInitialized(ILanguageInvoker *invoker) #endif #endif - if (PyEval_ThreadsInitialized()) - PyEval_AcquireLock(); - else - PyEval_InitThreads(); - Py_Initialize(); - PyEval_ReleaseLock(); // If this is not the first time we initialize Python, the interpreter // lock already exists and we need to lock it as PyEval_InitThreads // would not do that in that case. - PyEval_AcquireLock(); - const char* python_argv[1] = { "" }; + if (PyEval_ThreadsInitialized() && !PyGILState_Check()) + PyEval_AcquireLock(); + else + PyEval_InitThreads(); + const wchar_t* python_argv[1] = { L"" }; //! @bug libpython isn't const correct - PySys_SetArgv(1, const_cast(python_argv)); + PySys_SetArgv(1, const_cast(python_argv)); if (!(m_mainThreadState = PyThreadState_Get())) CLog::Log(LOGERROR, "Python threadstate is NULL."); - PyEval_ReleaseLock(); + savestate = PyEval_SaveThread(); m_bInitialized = true; } @@ -681,7 +648,7 @@ void XBPython::OnScriptAbortRequested(ILanguageInvoker *invoker) } } -void XBPython::OnExecutionEnded(ILanguageInvoker *invoker) +void XBPython::OnScriptEnded(ILanguageInvoker *invoker) { CSingleLock lock(m_vecPyList); PyList::iterator it = m_vecPyList.begin(); @@ -690,9 +657,9 @@ void XBPython::OnExecutionEnded(ILanguageInvoker *invoker) if (it->id == invoker->GetId()) { if (it->pyThread->IsStopping()) - CLog::Log(LOGINFO, "Python interpreter interrupted by user"); + CLog::Log(LOGINFO, "Python script interrupted by user"); else - CLog::Log(LOGINFO, "Python interpreter stopped"); + CLog::Log(LOGINFO, "Python script stopped"); it->bDone = true; } ++it; diff --git a/xbmc/interfaces/python/XBPython.h b/xbmc/interfaces/python/XBPython.h index 0c922fb71181e..41c5757e01901 100644 --- a/xbmc/interfaces/python/XBPython.h +++ b/xbmc/interfaces/python/XBPython.h @@ -91,7 +91,7 @@ class XBPython : bool OnScriptInitialized(ILanguageInvoker *invoker) override; void OnScriptStarted(ILanguageInvoker *invoker) override; void OnScriptAbortRequested(ILanguageInvoker *invoker) override; - void OnExecutionEnded(ILanguageInvoker *invoker) override; + void OnScriptEnded(ILanguageInvoker *invoker) override; void OnScriptFinalized(ILanguageInvoker *invoker) override; ILanguageInvoker* CreateInvoker() override; @@ -105,8 +105,6 @@ class XBPython : void Finalize(); CCriticalSection m_critSection; - bool FileExist(const char* strFile); - void* m_mainThreadState; ThreadIdentifier m_ThreadId; bool m_bInitialized; diff --git a/xbmc/interfaces/python/swig.cpp b/xbmc/interfaces/python/swig.cpp index b9d162566a6f3..a2bb3c1b470ba 100644 --- a/xbmc/interfaces/python/swig.cpp +++ b/xbmc/interfaces/python/swig.cpp @@ -17,7 +17,7 @@ namespace PythonBindings { TypeInfo::TypeInfo(const std::type_info& ti) : swigType(NULL), parentType(NULL), typeIndex(ti) { - static PyTypeObject py_type_object_header = { PyObject_HEAD_INIT(NULL) 0}; + static PyTypeObject py_type_object_header = { PyVarObject_HEAD_INIT(NULL, 0)}; static int size = (long*)&(py_type_object_header.tp_name) - (long*)&py_type_object_header; memcpy(&(this->pythonType), &py_type_object_header, size); } @@ -51,18 +51,14 @@ namespace PythonBindings // Python unicode objects are UCS2 or UCS4 depending on compilation // options, wchar_t is 16-bit or 32-bit depending on platform. // Avoid the complexity by just letting python convert the string. - PyObject *utf8_pyString = PyUnicode_AsUTF8String(pObject); - if (utf8_pyString) - { - buf = PyString_AsString(utf8_pyString); - Py_DECREF(utf8_pyString); + buf = PyUnicode_AsUTF8(pObject); return; } - } - if (PyString_Check(pObject)) + + if (PyBytes_Check(pObject)) // If pobject is of type Bytes { - buf = PyString_AsString(pObject); + buf = PyBytes_AsString(pObject); return; } @@ -166,26 +162,24 @@ namespace PythonBindings // See https://docs.python.org/3/c-api/exceptions.html#c.PyErr_NormalizeException PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback); -#if PY_MAJOR_VERSION > 2 if (exc_traceback != NULL) { PyException_SetTraceback(exc_value, exc_traceback); } -#endif exceptionType.clear(); exceptionValue.clear(); exceptionTraceback.clear(); - if (exc_type != NULL && (pystring = PyObject_Str(exc_type)) != NULL && PyString_Check(pystring)) + if (exc_type != NULL && (pystring = PyObject_Str(exc_type)) != NULL && PyUnicode_Check(pystring)) { - char *str = PyString_AsString(pystring); + const char *str = PyUnicode_AsUTF8(pystring); if (str != NULL) exceptionType = str; pystring = PyObject_Str(exc_value); if (pystring != NULL) { - str = PyString_AsString(pystring); + str = PyUnicode_AsUTF8(pystring); exceptionValue = str; } @@ -198,7 +192,7 @@ namespace PythonBindings if (tbList) { - PyObject *emptyString = PyString_FromString(""); + PyObject *emptyString = PyUnicode_FromString(""); char method[] = "join"; char format[] = "O"; PyObject *strRetval = PyObject_CallMethod(emptyString, method, format, tbList); @@ -206,7 +200,7 @@ namespace PythonBindings if (strRetval) { - str = PyString_AsString(strRetval); + str = PyUnicode_AsUTF8(strRetval); if (str != NULL) exceptionTraceback = str; Py_DECREF(strRetval); diff --git a/xbmc/interfaces/python/typemaps/python.Tuple.intm b/xbmc/interfaces/python/typemaps/python.Tuple.intm index ee6afce9389fd..c426856373ae7 100644 --- a/xbmc/interfaces/python/typemaps/python.Tuple.intm +++ b/xbmc/interfaces/python/typemaps/python.Tuple.intm @@ -17,7 +17,7 @@ bool isTuple = PyObject_TypeCheck(${slarg},&PyTuple_Type); if (!isTuple && !PyObject_TypeCheck(${slarg},&PyList_Type)) throw WrongTypeException("The parameter \"${api}\" must be either a Tuple or a List."); - auto vecSize = (isTuple ? PyTuple_Size(${slarg}) : PyList_Size(${slarg})); + Py_ssize_t vecSize = (isTuple ? PyTuple_Size(${slarg}) : PyList_Size(${slarg})); <% types.eachWithIndex { curType, entryIndex -> %> diff --git a/xbmc/interfaces/python/typemaps/python.buffer.intm b/xbmc/interfaces/python/typemaps/python.buffer.intm index d9bab4560a998..76c09cb783293 100644 --- a/xbmc/interfaces/python/typemaps/python.buffer.intm +++ b/xbmc/interfaces/python/typemaps/python.buffer.intm @@ -7,10 +7,10 @@ * See LICENSES/README.md for more information. */ %> - if (PyString_Check(${slarg})) + if (PyUnicode_Check(${slarg})) { - const char* str = PyString_AsString(${slarg}); - size_t size = (size_t)PyString_Size(${slarg}); + const char* str = PyUnicode_AsUTF8(${slarg}); + size_t size = (size_t)PyUnicode_GetLength(${slarg}); ${api}.allocate(size); ${api}.put(str,size); ${api}.flip(); // prepare the buffer for reading from diff --git a/xbmc/interfaces/python/typemaps/python.string.outtm b/xbmc/interfaces/python/typemaps/python.string.outtm index 6e17f824318fa..93c4971d40dc9 100644 --- a/xbmc/interfaces/python/typemaps/python.string.outtm +++ b/xbmc/interfaces/python/typemaps/python.string.outtm @@ -8,4 +8,4 @@ */ %>${result} = <% if(method.@feature_python_coerceToUnicode) { %>PyUnicode_DecodeUTF8(${api}.c_str(),${api}.size(),"replace");<% } - else { %>PyString_FromStringAndSize(${api}.c_str(), ${api}.length());<% } %> \ No newline at end of file + else { %>PyUnicode_FromStringAndSize(${api}.c_str(), ${api}.length());<% } %> diff --git a/xbmc/interfaces/python/typemaps/python.vector.intm b/xbmc/interfaces/python/typemaps/python.vector.intm index c4b385e8cb5b7..a479d748b1608 100644 --- a/xbmc/interfaces/python/typemaps/python.vector.intm +++ b/xbmc/interfaces/python/typemaps/python.vector.intm @@ -20,7 +20,7 @@ <% if (ispointer) print("${api} = new std::vector<${swigTypeParser.SwigType_str(vectype)}>();") %> PyObject *pyentry${seq} = NULL; - auto vecSize = (isTuple ? PyTuple_Size(${slarg}) : PyList_Size(${slarg})); + Py_ssize_t vecSize = (isTuple ? PyTuple_Size(${slarg}) : PyList_Size(${slarg})); for(Py_ssize_t i = 0; i < vecSize; i++) { pyentry${seq} = (isTuple ? PyTuple_GetItem(${slarg}, i) : PyList_GetItem(${slarg}, i)); diff --git a/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.cpp b/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.cpp index ae487a2d9d362..cb49abec2ac8e 100644 --- a/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.cpp +++ b/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.cpp @@ -6,6 +6,8 @@ * See LICENSES/README.md for more information. */ +#include + #include "HTTPPythonWsgiInvoker.h" #include @@ -40,14 +42,14 @@ #define RUNSCRIPT_SETUPTOOLS_HACK \ "" \ - "import imp,sys\n" \ + "import types,sys\n" \ "pkg_resources_code = \\\n" \ "\"\"\"\n" \ "def resource_filename(__name__,__path__):\n" \ " return __path__\n" \ "\"\"\"\n" \ - "pkg_resources = imp.new_module('pkg_resources')\n" \ - "exec pkg_resources_code in pkg_resources.__dict__\n" \ + "pkg_resources = types.ModuleType('pkg_resources')\n" \ + "exec(pkg_resources_code, pkg_resources.__dict__)\n" \ "sys.modules['pkg_resources'] = pkg_resources\n" \ "" @@ -64,9 +66,9 @@ #endif namespace PythonBindings { - void initModule_xbmc(void); - void initModule_xbmcaddon(void); - void initModule_xbmcwsgi(void); + PyObject* PyInit_Module_xbmc(void); + PyObject* PyInit_Module_xbmcaddon(void); + PyObject* PyInit_Module_xbmcwsgi(void); } using namespace PythonBindings; @@ -79,15 +81,19 @@ typedef struct static PythonModule PythonModules[] = { - { "xbmc", initModule_xbmc }, - { "xbmcaddon", initModule_xbmcaddon }, - { "xbmcwsgi", initModule_xbmcwsgi } + { "xbmc", PyInit_Module_xbmc }, + { "xbmcaddon", PyInit_Module_xbmcaddon }, + { "xbmcwsgi", PyInit_Module_xbmcwsgi } }; CHTTPPythonWsgiInvoker::CHTTPPythonWsgiInvoker(ILanguageInvocationHandler* invocationHandler, HTTPPythonRequest* request) : CHTTPPythonInvoker(invocationHandler, request), m_wsgiResponse(NULL) -{ } +{ + PyImport_AppendInittab("xbmc", PyInit_Module_xbmc); + PyImport_AppendInittab("xbmcaddon", PyInit_Module_xbmcaddon); + PyImport_AppendInittab("xbmcwsgi", PyInit_Module_xbmcwsgi); +} CHTTPPythonWsgiInvoker::~CHTTPPythonWsgiInvoker() { @@ -107,10 +113,10 @@ HTTPPythonRequest* CHTTPPythonWsgiInvoker::GetRequest() return m_request; } -void CHTTPPythonWsgiInvoker::executeScript(void *fp, const std::string &script, void *module, void *moduleDict) +void CHTTPPythonWsgiInvoker::executeScript(FILE* fp, const std::string &script, PyObject* moduleDict) { if (m_request == NULL || m_addon == NULL || m_addon->Type() != ADDON::ADDON_WEB_INTERFACE || - fp == NULL || script.empty() || module == NULL || moduleDict == NULL) + fp == NULL || script.empty() || moduleDict == NULL) return; ADDON::CWebinterface* webinterface = static_cast(m_addon.get()); @@ -134,7 +140,7 @@ void CHTTPPythonWsgiInvoker::executeScript(void *fp, const std::string &script, // get the script std::string scriptName = URIUtils::GetFileName(script); URIUtils::RemoveExtension(scriptName); - pyScript = PyString_FromStringAndSize(scriptName.c_str(), scriptName.size()); + pyScript = PyUnicode_FromStringAndSize(scriptName.c_str(), scriptName.size()); if (pyScript == NULL) { CLog::Log(LOGERROR, "CHTTPPythonWsgiInvoker: failed to convert script \"%s\" to python string", script.c_str()); @@ -187,7 +193,7 @@ void CHTTPPythonWsgiInvoker::executeScript(void *fp, const std::string &script, pyEnviron = PyDict_New(); for (std::map::const_iterator cgiEnv = cgiEnvironment.begin(); cgiEnv != cgiEnvironment.end(); ++cgiEnv) { - PyObject* pyEnvEntry = PyString_FromStringAndSize(cgiEnv->second.c_str(), cgiEnv->second.size()); + PyObject* pyEnvEntry = PyUnicode_FromStringAndSize(cgiEnv->second.c_str(), cgiEnv->second.size()); PyDict_SetItemString(pyEnviron, cgiEnv->first.c_str(), pyEnvEntry); Py_DECREF(pyEnvEntry); } @@ -271,8 +277,7 @@ void CHTTPPythonWsgiInvoker::executeScript(void *fp, const std::string &script, // Call optional close method on iterator if (PyObject_HasAttrString(pyResultIterator, "close") == 1) { - //! @bug libpython < 3.4 isn't const correct - if (PyObject_CallMethod(pyResultIterator, const_cast("close"), NULL) == NULL) + if (PyObject_CallMethod(pyResultIterator, "close", NULL) == NULL) CLog::Log(LOGERROR, "CHTTPPythonWsgiInvoker: failed to close iterator object for WSGI script \"%s\"", script.c_str()); } Py_DECREF(pyResultIterator); @@ -398,7 +403,7 @@ void CHTTPPythonWsgiInvoker::addWsgiEnvironment(HTTPPythonRequest* request, void } { // wsgi.url_scheme - PyObject* pyValue = PyString_FromStringAndSize("http", 4); + PyObject* pyValue = PyUnicode_FromStringAndSize("http", 4); PyDict_SetItemString(pyEnviron, "wsgi.url_scheme", pyValue); Py_DECREF(pyValue); } diff --git a/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.h b/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.h index ae0ab922f238d..ea85f390a36b2 100644 --- a/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.h +++ b/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.h @@ -34,7 +34,7 @@ class CHTTPPythonWsgiInvoker : public CHTTPPythonInvoker protected: // overrides of CPythonInvoker - void executeScript(void *fp, const std::string &script, void *module, void *moduleDict) override; + void executeScript(FILE* fp, const std::string &script, PyObject* moduleDict) override; std::map getModules() const override; const char* getInitializationScript() const override; diff --git a/xbmc/platform/android/activity/XBMCApp.cpp b/xbmc/platform/android/activity/XBMCApp.cpp index 3a6e6f65c57d4..194dffc852f14 100644 --- a/xbmc/platform/android/activity/XBMCApp.cpp +++ b/xbmc/platform/android/activity/XBMCApp.cpp @@ -1297,7 +1297,7 @@ void CXBMCApp::SetupEnv() setenv("HOME", getenv("KODI_TEMP"), 0); std::string apkPath = getenv("KODI_ANDROID_APK"); - apkPath += "/assets/python2.7"; + apkPath += "/assets/python3.7"; setenv("PYTHONHOME", apkPath.c_str(), 1); setenv("PYTHONPATH", "", 1); setenv("PYTHONOPTIMIZE","", 1);