@@ -47,6 +47,10 @@ else() | |||||
${MODULE_NAME} PRIVATE megengine_shared -Wl,--version-script=${MGE_VERSION_SCRIPT}) | ${MODULE_NAME} PRIVATE megengine_shared -Wl,--version-script=${MGE_VERSION_SCRIPT}) | ||||
endif() | endif() | ||||
if(ANDROID) | |||||
target_link_libraries(${MODULE_NAME} PRIVATE ${PYTHON_LIBRARIES}) | |||||
endif() | |||||
add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/range-v3 | add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/range-v3 | ||||
${PROJECT_BINARY_DIR}/third_party/range-v3) | ${PROJECT_BINARY_DIR}/third_party/range-v3) | ||||
target_link_libraries(${MODULE_NAME} PRIVATE range-v3) | target_link_libraries(${MODULE_NAME} PRIVATE range-v3) | ||||
@@ -12,6 +12,17 @@ import os | |||||
import platform | import platform | ||||
import sys | import sys | ||||
if os.getenv("TERMUX_VERSION"): | |||||
try: | |||||
import cv2 | |||||
except Exception as exc: | |||||
print("Run MegEngine python interface at Android/Termux env") | |||||
print("!!!You need build opencv-python manually!!!, by run sh:") | |||||
print( | |||||
"https://github.com/MegEngine/MegEngine/blob/master/scripts/whl/android/android_opencv_python.sh" | |||||
) | |||||
raise exc | |||||
if sys.platform == "win32": | if sys.platform == "win32": | ||||
lib_path = os.path.join(os.path.dirname(__file__), "core/lib") | lib_path = os.path.join(os.path.dirname(__file__), "core/lib") | ||||
dll_paths = list(filter(os.path.exists, [lib_path,])) | dll_paths = list(filter(os.path.exists, [lib_path,])) | ||||
@@ -10,6 +10,7 @@ import collections | |||||
import gc | import gc | ||||
import math | import math | ||||
import multiprocessing | import multiprocessing | ||||
import os | |||||
import platform | import platform | ||||
import queue | import queue | ||||
import random | import random | ||||
@@ -150,6 +151,13 @@ class DataLoader: | |||||
"pyarrow.plasma does not support ParallelDataLoader on windows, changing num_workers to be zero" | "pyarrow.plasma does not support ParallelDataLoader on windows, changing num_workers to be zero" | ||||
) | ) | ||||
self.num_workers = 0 | self.num_workers = 0 | ||||
if os.getenv("TERMUX_VERSION"): | |||||
# FIXME: termux install pyarrow will build error now | |||||
# remove this logic after pyarrow fix this issue | |||||
print( | |||||
"pyarrow do not support on termux env now, changing num_workers to be zero" | |||||
) | |||||
self.num_workers = 0 | |||||
if isinstance(self.dataset, StreamDataset): | if isinstance(self.dataset, StreamDataset): | ||||
if not self.num_workers: | if not self.num_workers: | ||||
return _SerialStreamDataLoaderIter(self, self.preload) | return _SerialStreamDataLoaderIter(self, self.preload) | ||||
@@ -2,6 +2,7 @@ | |||||
* Windows build (cpu and gpu) | * Windows build (cpu and gpu) | ||||
* Linux build (cpu and gpu) | * Linux build (cpu and gpu) | ||||
* MacOS build (cpu only) | * MacOS build (cpu only) | ||||
* Android(termux) build (cpu only) | |||||
# Build env prepare | # Build env prepare | ||||
## Linux | ## Linux | ||||
@@ -30,6 +31,15 @@ | |||||
./scripts/whl/macos/macos_whl_env_prepare.sh | ./scripts/whl/macos/macos_whl_env_prepare.sh | ||||
``` | ``` | ||||
## Android | |||||
* install [termux](https://termux.com/) apk on Android Device | |||||
* at least 8G DDR | |||||
* at least Android 7 | |||||
* init wheel build-dependent env by command: | |||||
```bash | |||||
./scripts/whl/android/android_whl_env_prepare.sh | |||||
``` | |||||
## Windows | ## Windows | ||||
* refer to [BUILD_README.md](../cmake-build/BUILD_README.md) Windows section to init base build environment | * refer to [BUILD_README.md](../cmake-build/BUILD_README.md) Windows section to init base build environment | ||||
@@ -43,12 +53,12 @@ commands: | |||||
./scripts/whl/manylinux2014/build_wheel_common.sh -sdk cu101 | ./scripts/whl/manylinux2014/build_wheel_common.sh -sdk cu101 | ||||
``` | ``` | ||||
* And you can find all of the outputs in `output` directory.If you just want to build for a specific Python verison, you can use `ALL_PYTHON` environment variable. eg: | |||||
* And you can find all of the outputs in `output` directory.If you just want to build for a specific Python verison, you can use `ALL_PYTHON` environment variable. such as: | |||||
```bash | ```bash | ||||
ALL_PYTHON="36m" ./scripts/whl/manylinux2014/build_wheel_common.sh -sdk cu101 | ALL_PYTHON="36m" ./scripts/whl/manylinux2014/build_wheel_common.sh -sdk cu101 | ||||
``` | ``` | ||||
* If you just want to build with cpu only version, you can set `-sdk` environment 'cpu'. eg: | |||||
* If you just want to build with cpu only version, you can set `-sdk` environment 'cpu'. such as: | |||||
```bash | ```bash | ||||
ALL_PYTHON="36m" ./scripts/whl/manylinux2014/build_wheel_common.sh -sdk cpu | ALL_PYTHON="36m" ./scripts/whl/manylinux2014/build_wheel_common.sh -sdk cpu | ||||
``` | ``` | ||||
@@ -58,7 +68,7 @@ ALL_PYTHON="36m" ./scripts/whl/manylinux2014/build_wheel_common.sh -sdk cpu | |||||
```bash | ```bash | ||||
./scripts/whl/macos/macos_build_whl.sh | ./scripts/whl/macos/macos_build_whl.sh | ||||
``` | ``` | ||||
* If you just want to build for a specific Python verison, you can use `ALL_PYTHON` environment variable. eg: | |||||
* If you just want to build for a specific Python verison, you can use `ALL_PYTHON` environment variable. such as: | |||||
```bash | ```bash | ||||
ALL_PYTHON="3.7.7" ./scripts/whl/macos/macos_build_whl.sh | ALL_PYTHON="3.7.7" ./scripts/whl/macos/macos_build_whl.sh | ||||
``` | ``` | ||||
@@ -69,12 +79,22 @@ ALL_PYTHON="3.7.7" ./scripts/whl/macos/macos_build_whl.sh | |||||
./scripts/whl/windows/windows_build_whl.sh | ./scripts/whl/windows/windows_build_whl.sh | ||||
``` | ``` | ||||
* If you just want to build for a specific Python verison, you can use `ALL_PYTHON` environment variable. eg: | |||||
* If you just want to build for a specific Python verison, you can use `ALL_PYTHON` environment variable. such as: | |||||
```bash | ```bash | ||||
ALL_PYTHON="3.8.3" ./scripts/whl/windows/windows_build_whl.sh | ALL_PYTHON="3.8.3" ./scripts/whl/windows/windows_build_whl.sh | ||||
``` | ``` | ||||
* If you just want to build with cpu only version, you can set `BUILD_WHL_CPU_ONLY` environment 'ON'. eg: | |||||
* If you just want to build with cpu only version, you can set `BUILD_WHL_CPU_ONLY` environment 'ON'. such as: | |||||
``` | ``` | ||||
BUILD_WHL_CPU_ONLY="ON" ALL_PYTHON="3.8.3" ./scripts/whl/windows/windows_build_whl.sh | BUILD_WHL_CPU_ONLY="ON" ALL_PYTHON="3.8.3" ./scripts/whl/windows/windows_build_whl.sh | ||||
``` | ``` | ||||
## Build for Android | |||||
* commands: | |||||
```bash | |||||
scripts/whl/android/android_build_whl.sh | |||||
``` | |||||
* If you just want to build for a specific Python verison, you can use `ALL_PYTHON` environment variable. such as: | |||||
```bash | |||||
ALL_PYTHON="3.10.1" ./scripts/whl/android/android_build_whl.sh | |||||
``` |
@@ -0,0 +1,164 @@ | |||||
#!/bin/bash -e | |||||
SRC_DIR=$(readlink -f "`dirname $0`/../../../") | |||||
cd ${SRC_DIR} | |||||
source scripts/whl/android/utils.sh | |||||
ANDROID_WHL_HOME=${SRC_DIR}/scripts/whl/android/ANDROID_WHL_HOME | |||||
if [ -e "${ANDROID_WHL_HOME}" ]; then | |||||
echo "remove old android whl file" | |||||
rm -rf ${ANDROID_WHL_HOME} | |||||
fi | |||||
mkdir -p ${ANDROID_WHL_HOME} | |||||
BUILD_DIR=${SRC_DIR}/build_dir/host/MGE_WITH_CUDA_OFF/MGE_INFERENCE_ONLY_OFF/Release/build/ | |||||
# We only handle the case where dnn/src/common/conv_bias.cpp is not in the list of incremental build files. | |||||
INCREMENT_KEY_WORDS="conv_bias.cpp.o is dirty" | |||||
IS_IN_FIRST_LOOP=TRUE | |||||
ORG_EXTRA_CMAKE_FLAG=${EXTRA_CMAKE_FLAG} | |||||
function handle_strip() { | |||||
echo "now handle strip $1" | |||||
objcopy --only-keep-debug $1 $1.dbg | |||||
strip -s $1 | |||||
objcopy --add-gnu-debuglink=$1.dbg $1 | |||||
rm $1.dbg | |||||
} | |||||
function patch_elf_depend_lib_mgb_mge() { | |||||
echo "handle common depend lib for mgb or mge" | |||||
LIBS_DIR=${BUILD_DIR}/staging/megengine/core/lib | |||||
mkdir -p ${LIBS_DIR} | |||||
patchelf --remove-rpath ${BUILD_DIR}/staging/megengine/core/_imperative_rt.so | |||||
patchelf --set-rpath '$ORIGIN/lib' ${BUILD_DIR}/staging/megengine/core/_imperative_rt.so | |||||
handle_strip ${BUILD_DIR}/staging/megengine/core/_imperative_rt.so | |||||
cp ${BUILD_DIR}/src/libmegengine_shared.so ${LIBS_DIR} | |||||
patchelf --remove-rpath ${LIBS_DIR}/libmegengine_shared.so | |||||
patchelf --set-rpath '$ORIGIN/.' ${LIBS_DIR}/libmegengine_shared.so | |||||
# FXIME: third_party LLVM need c++_static > 5.1 | |||||
# but now clang(13) at termux env do not satisfy it | |||||
# may use -static-libstdc++ at CMakeLists.txt after | |||||
# upgrade third_party LLVM | |||||
cp /data/data/com.termux/files/usr/lib/libc++_shared.so ${LIBS_DIR} | |||||
handle_strip ${LIBS_DIR}/libmegengine_shared.so | |||||
} | |||||
function patch_elf_depend_lib_megenginelite() { | |||||
echo "handle common depend lib for megenginelite" | |||||
LIBS_DIR=${BUILD_DIR}/staging/megenginelite/libs | |||||
mkdir -p ${LIBS_DIR} | |||||
cp ${BUILD_DIR}/lite/liblite_shared_whl.so ${LIBS_DIR}/ | |||||
patchelf --remove-rpath ${LIBS_DIR}/liblite_shared_whl.so | |||||
patchelf --set-rpath '$ORIGIN/../../megengine/core/lib' ${LIBS_DIR}/liblite_shared_whl.so | |||||
handle_strip ${LIBS_DIR}/liblite_shared_whl.so | |||||
} | |||||
function do_build() { | |||||
mge_python_env_root="${HOME}/mge_python_env" | |||||
for ver in ${ALL_PYTHON} | |||||
do | |||||
python_install_dir=${mge_python_env_root}/${ver}/install | |||||
# we want to run a full clean build in the first loop | |||||
if [ ${IS_IN_FIRST_LOOP} = "TRUE" ]; then | |||||
# TODO: can all cmake issues be resolved after removing CMakeCache? | |||||
# if YES, remove this logic to use old cache and speed up CI | |||||
echo "warning: remove old build_dir for the first loop" | |||||
rm -rf ${BUILD_DIR} | |||||
fi | |||||
# insert python3_install_dir into head of PATH to enable CMake find it | |||||
if [ -e ${python_install_dir}/bin/python3 ];then | |||||
echo "will use ${python_install_dir}/bin/python3 to build mge wheel" | |||||
export PATH=${python_install_dir}/bin:$PATH | |||||
else | |||||
echo "ERROR: can not find python3 in: ${python_install_dir}/bin" | |||||
echo "please run: %{SRC_DIR}/scripts/whl/android/android_whl_env_prepare.sh to prepare env" | |||||
exit -1 | |||||
fi | |||||
export EXTRA_CMAKE_ARGS="${ORG_EXTRA_CMAKE_FLAG} -DCMAKE_BUILD_TYPE=RelWithDebInfo" | |||||
export EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DMGE_WITH_CUSTOM_OP=ON" | |||||
if [ -d "${BUILD_DIR}" ]; then | |||||
# insure rm have args | |||||
touch ${BUILD_DIR}/empty.so | |||||
touch ${BUILD_DIR}/CMakeCache.txt | |||||
find ${BUILD_DIR} -name "*.so" | xargs rm | |||||
# Force remove CMakeCache.txt to avoid error owing to unknown issue in CMakeLists.txt | |||||
# which comes from using increment build mode when switching python version | |||||
find ${BUILD_DIR} -name CMakeCache.txt | xargs rm | |||||
fi | |||||
HOST_BUILD_ARGS="-t -s" | |||||
# call ninja dry run and check increment is invalid or not | |||||
if [ ${IS_IN_FIRST_LOOP} = "FALSE" ]; then | |||||
ninja_dry_run_and_check_increment "${SRC_DIR}/scripts/cmake-build/host_build.sh" "${HOST_BUILD_ARGS}" "${INCREMENT_KEY_WORDS}" | |||||
fi | |||||
# call real build | |||||
echo "host_build.sh HOST_BUILD_ARGS: ${HOST_BUILD_ARGS}" | |||||
bash ${SRC_DIR}/scripts/cmake-build/host_build.sh ${HOST_BUILD_ARGS} | |||||
# check python api call setup.py | |||||
cd ${BUILD_DIR} | |||||
check_build_ninja_python_api ${ver} | |||||
rm -rf staging | |||||
mkdir -p staging | |||||
cp -a imperative/python/{megengine,setup.py,requires.txt,requires-style.txt,requires-test.txt} staging/ | |||||
cp -a ${SRC_DIR}/src/custom/include staging/megengine/core/include/ | |||||
patch_elf_depend_lib_mgb_mge | |||||
# handle megenginelite | |||||
cd ${BUILD_DIR} | |||||
mkdir -p staging/megenginelite | |||||
cp ${SRC_DIR}/lite/pylite/megenginelite/* staging/megenginelite/ | |||||
patch_elf_depend_lib_megenginelite | |||||
cd ${BUILD_DIR}/staging | |||||
python3 setup.py bdist_wheel | |||||
cd ${BUILD_DIR}/staging/dist/ | |||||
cp ${BUILD_DIR}/staging/dist/Meg*.whl ${ANDROID_WHL_HOME} | |||||
cd ${SRC_DIR} | |||||
echo "" | |||||
echo "##############################################################################################" | |||||
echo "android whl package location: ${ANDROID_WHL_HOME}" | |||||
ls ${ANDROID_WHL_HOME} | |||||
echo "##############################################################################################" | |||||
IS_IN_FIRST_LOOP=FALSE | |||||
done | |||||
} | |||||
function third_party_prepare() { | |||||
echo "init third_party..." | |||||
bash ${SRC_DIR}/third_party/prepare.sh | |||||
# fix flatbuffers build at pure LLVM env(not cross link gcc) | |||||
# TODO: pr to flatbuffers to fix this issue | |||||
sed -i 's/lc++abi/lc/g' ${SRC_DIR}/third_party/flatbuffers/CMakeLists.txt | |||||
} | |||||
function remove_requires() { | |||||
# do not worry about this, we will provide 'scripts/whl/android/android_opencv_python.sh' | |||||
# to build opencv-python from opencv src!! This function may be removed after termux fixes | |||||
# this issue | |||||
cd ${SRC_DIR} | |||||
git checkout imperative/python/requires.txt | |||||
sed -i '/opencv-python/d' imperative/python/requires.txt | |||||
# FIXME: termux install pyarrow will build error now | |||||
# remove this logic after pyarrow fix this issue | |||||
# see imperative/python/megengine/data/dataloader.py | |||||
# for detail, now will use _SerialStreamDataLoaderIter | |||||
sed -i '/pyarrow/d' imperative/python/requires.txt | |||||
cd - | |||||
} | |||||
###################### | |||||
check_termux_env | |||||
third_party_prepare | |||||
remove_requires | |||||
do_build |
@@ -0,0 +1,65 @@ | |||||
#!/bin/bash -e | |||||
# This script is a workaround of installing opencv-python in termux. | |||||
SRC_DIR=$(readlink -f "`dirname $0`/../../../") | |||||
cd ${SRC_DIR} | |||||
source scripts/whl/android/utils.sh | |||||
function install_apt_package() { | |||||
APT_PACKAGE="build-essential cmake libjpeg-turbo libpng python clang" | |||||
echo "try to install: ${APT_PACKAGE}" | |||||
apt install ${APT_PACKAGE} | |||||
} | |||||
function build_opencv_python() { | |||||
python3 -m pip install numpy | |||||
mge_python_env_root="${HOME}/mge_python_env" | |||||
mkdir -p ${mge_python_env_root} | |||||
cd ${mge_python_env_root} | |||||
opencv_repo_dir=${mge_python_env_root}/opencv | |||||
if [ -d ${opencv_repo_dir}/.git ];then | |||||
echo "already find opencv repo" | |||||
cd ${opencv_repo_dir} | |||||
git reset --hard | |||||
git clean -xdf | |||||
git fetch | |||||
else | |||||
cd ${mge_python_env_root} | |||||
rm -rf ${opencv_repo_dir} | |||||
git clone https://github.com/opencv/opencv.git | |||||
fi | |||||
# Build and test latest version by default. You can modify OPENCV_VER to build and test another version!! | |||||
python3_site=`python3 -c 'import site; print(site.getsitepackages()[0])'` | |||||
OPENCV_VER="3.4.15" | |||||
git checkout ${OPENCV_VER} | |||||
if [ -e ${python3_site}/cv2/__init__.py ];then | |||||
echo "python3 already build cv2, skip build it, if you want to rebuild, you can do: rm -rf ${python3_site}/cv2" | |||||
else | |||||
cd ${opencv_repo_dir} | |||||
git checkout ${OPENCV_VE} | |||||
git apply ${SRC_DIR}/scripts/whl/android/cv_patch/*.patch | |||||
mkdir -p build | |||||
cd build | |||||
echo "will install to ${python3_site}" | |||||
PYTHON3_EXECUTABLE=`command -v python3` | |||||
LDFLAGS=" -llog -lpython3" cmake -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_opencv_python3=on \ | |||||
-DBUILD_opencv_python2=off -DWITH_QT=OFF -DWITH_GTK=OFF -DBUILD_ANDROID_PROJECTS=OFF \ | |||||
-DBUILD_ANDROID_EXAMPLES=OFF -DBUILD_FAT_JAVA_LIB=OFF -DBUILD_ANDROID_SERVICE=OFF \ | |||||
-DHAVE_opencv_python3=ON -D__INSTALL_PATH_PYTHON3=${python3_site} \ | |||||
-DPYTHON3_EXECUTABLE=${PYTHON3_EXECUTABLE} \ | |||||
-DOPENCV_PYTHON_INSTALL_PATH=${python3_site} -DCMAKE_INSTALL_PREFIX=${python3_site} .. \ | |||||
&& make -j$(nproc) && make install | |||||
# check if build successfully | |||||
cd ~ | |||||
python3 -c 'import cv2;print(cv2.__version__)' | |||||
fi | |||||
} | |||||
############install env now########### | |||||
echo "run at root dir: ${SRC_DIR}" | |||||
check_termux_env | |||||
install_apt_package | |||||
build_opencv_python |
@@ -0,0 +1,155 @@ | |||||
#!/bin/bash -e | |||||
# Installing package by pkg in termux is unwise because pkg will upgrade | |||||
# package to the latest version which is undesired sometimes. We will | |||||
# use apt as default package tool. If your env is already broken,e.g. | |||||
# clang does not work, you can execute following commands to fix it: | |||||
# pkg update | |||||
# pkg upgrade | |||||
SRC_DIR=$(readlink -f "`dirname $0`/../../../") | |||||
cd ${SRC_DIR} | |||||
source scripts/whl/android/utils.sh | |||||
function install_apt_package() { | |||||
APT_PACKAGE="proot git wget clang cmake libandroid-spawn binutils build-essential ninja texinfo patchelf python" | |||||
echo "try install: ${APT_PACKAGE}" | |||||
apt install ${APT_PACKAGE} | |||||
echo "check termux status by running: clang --version" | |||||
log=`clang --version || true` | |||||
if [[ "${log}" =~ "clang version" ]]; then | |||||
echo "valid env after installing apt package" | |||||
else | |||||
echo "Failed to run clang command, please check termux env!!! You can run: pkg update && pkg upgrade to try to solve it" | |||||
echo "raw log: ${log}" | |||||
exit -1 | |||||
fi | |||||
} | |||||
function patch_termux_env() { | |||||
# do not try to modify other project build files to adapt to only-llvm environment | |||||
echo "many projects can not build without gcc libs, so we create a fake gcc libs linked to librt" | |||||
RT_LIB_TARGET="${PREFIX}/lib/librt.so" | |||||
if [ -e ${RT_LIB_TARGET} ];then | |||||
echo "find librt.so and link it to libgcc.so" | |||||
GCC_LIB_TARGET="${PREFIX}/lib/libgcc.so" | |||||
if [ -e ${GCC_LIB_TARGET} ];then | |||||
echo "already find: ${GCC_LIB_TARGET} skip it" | |||||
else | |||||
create_libgcc_cmd="ln -s ${RT_LIB_TARGET} ${GCC_LIB_TARGET}" | |||||
echo "run cmd: $create_libgcc_cmd" | |||||
${create_libgcc_cmd} | |||||
fi | |||||
else | |||||
echo "broken termux env, can not find librt.so" | |||||
exit -1 | |||||
fi | |||||
} | |||||
function build_python() { | |||||
# Up to now many tools (build multi python3) are not supported in termux so that we have to build them from source. | |||||
# This function will be changed when some tools are supported in termux, e.g. pyenv. | |||||
mge_python_env_root="${HOME}/mge_python_env" | |||||
mkdir -p ${mge_python_env_root} | |||||
cd ${mge_python_env_root} | |||||
if [ -e ${PREFIX}/local/lib/libffi.a ];then | |||||
echo "always find libffi, skip build it" | |||||
else | |||||
echo "build libffi for python module" | |||||
rm -rf libffi | |||||
git clone https://github.com/libffi/libffi.git | |||||
cd libffi | |||||
termux-chroot "./autogen.sh && ./configure && make -j$(nproc) && make install" | |||||
# remove dynamic lib to force python to use static lib | |||||
rm ${PREFIX}/local/lib/libffi.so* | |||||
fi | |||||
if [ -e ${PREFIX}/local/lib/libz.a ];then | |||||
echo "always find libzlib, skip build it" | |||||
else | |||||
echo "build zlib for python module" | |||||
rm -rf zlib | |||||
git clone https://github.com/madler/zlib.git | |||||
cd zlib | |||||
termux-chroot "CFLAGS=\"-O3 -fPIC\" ./configure && make -j$(nproc) && make install" | |||||
# remove dynamic lib to force python to use static lib | |||||
rm ${PREFIX}/local/lib/libz.so* | |||||
fi | |||||
cpython_repo_dir=${mge_python_env_root}/cpython | |||||
if [ -d ${cpython_repo_dir}/.git ];then | |||||
echo "already find cpython repo" | |||||
cd ${cpython_repo_dir} | |||||
git reset --hard | |||||
git clean -xdf | |||||
git fetch | |||||
else | |||||
cd ${mge_python_env_root} | |||||
rm -rf ${cpython_repo_dir} | |||||
git clone https://github.com/python/cpython.git | |||||
fi | |||||
for ver in ${ALL_PYTHON} | |||||
do | |||||
install_dir=${mge_python_env_root}/${ver}/install | |||||
if [ -e ${install_dir}/bin/python3 ];then | |||||
echo "always find python3, skip build it" | |||||
else | |||||
mkdir -p ${install_dir} | |||||
echo "try build python: ${ver} to ${install_dir}" | |||||
cd ${cpython_repo_dir} | |||||
git reset --hard | |||||
git clean -xdf | |||||
git checkout v${ver} | |||||
index=`awk -v a="${ver}" -v b="." 'BEGIN{print index(a,b)}'` | |||||
sub_str=${ver:${index}} | |||||
index_s=`awk -v a="${sub_str}" -v b="." 'BEGIN{print index(a,b)}'` | |||||
((finally_index = ${index} + ${index_s})) | |||||
finally_verson=${ver:0:${finally_index}-1} | |||||
MINOR_VER=${ver:${index}:${finally_index}-${index}-1} | |||||
finally_verson="python${finally_verson}" | |||||
echo "finally_verson is: ${finally_verson}" | |||||
# apply patchs | |||||
git apply ${SRC_DIR}/scripts/whl/android/patchs/*.patch | |||||
if [[ ${MINOR_VER} -gt 8 ]] | |||||
then | |||||
echo "apply more patchs" | |||||
git apply ${SRC_DIR}/scripts/whl/android/up_3_9_patch/*.patch | |||||
fi | |||||
termux-chroot "FLAGS=\"-D__ANDROID_API__=24 -Wno-unused-value -Wno-empty-body -Qunused-arguments -Wno-error\" \ | |||||
./configure CFLAGS=\"${FLAGS}\" CPPFLAGS=\"${FLAGS}\" CC=clang CXX=clang++ --enable-shared --prefix=${install_dir} \ | |||||
&& sed -i 's/-Werror=implicit-function-declaration//g' Makefile && \ | |||||
sed -i 's/\$(LN) -f \$(INSTSONAME)/cp \$(INSTSONAME)/g' Makefile && make -j$(nproc) && make install" | |||||
# after building successfully, patchelf to make python work out of termux-chroot env | |||||
cd ${install_dir}/bin | |||||
# Some python versions won't link to python3 automatically, so we create link manually here' | |||||
rm -rf python3 | |||||
if [[ ${MINOR_VER} -gt 7 ]] | |||||
then | |||||
echo "python3 remove suffix m after 3.8" | |||||
patchelf --add-rpath ${install_dir}/lib ${finally_verson} | |||||
cp ${finally_verson} python3 | |||||
else | |||||
echo "python3 with suffix m before 3.8, add it" | |||||
patchelf --add-rpath ${install_dir}/lib "${finally_verson}m" | |||||
cp "${finally_verson}m" ${finally_verson} | |||||
cp ${finally_verson} python3 | |||||
fi | |||||
echo "finally try run python3" | |||||
./python3 --version | |||||
./python3 -m pip install --upgrade pip | |||||
./python3 -m pip install numpy wheel | |||||
fi | |||||
done | |||||
} | |||||
############install env now########### | |||||
echo "run at root dir: ${SRC_DIR}" | |||||
check_termux_env | |||||
install_apt_package | |||||
patch_termux_env | |||||
build_python |
@@ -0,0 +1,75 @@ | |||||
diff --git a/CMakeLists.txt b/CMakeLists.txt | |||||
index f6a2da5310..10354312c9 100644 | |||||
--- a/CMakeLists.txt | |||||
+++ b/CMakeLists.txt | |||||
@@ -643,7 +643,7 @@ if(UNIX) | |||||
if(NOT APPLE) | |||||
CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD) | |||||
if(ANDROID) | |||||
- set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} dl m log) | |||||
+ set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} dl m log z) | |||||
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD|NetBSD|DragonFly|OpenBSD|Haiku") | |||||
set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} m pthread) | |||||
elseif(EMSCRIPTEN) | |||||
diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake | |||||
index 4ff02a77d3..db1305448f 100644 | |||||
--- a/cmake/OpenCVDetectPython.cmake | |||||
+++ b/cmake/OpenCVDetectPython.cmake | |||||
@@ -123,7 +123,7 @@ if(NOT ${found}) | |||||
if(_found) | |||||
set(_version_major_minor "${_version_major}.${_version_minor}") | |||||
- if(NOT ANDROID AND NOT APPLE_FRAMEWORK) | |||||
+ if(TRUE) | |||||
ocv_check_environment_variables(${library_env} ${include_dir_env}) | |||||
if(NOT ${${library_env}} STREQUAL "") | |||||
set(PYTHON_LIBRARY "${${library_env}}") | |||||
@@ -175,7 +175,7 @@ if(NOT ${found}) | |||||
endif() | |||||
endif() | |||||
- if(NOT ANDROID AND NOT IOS) | |||||
+ if(TRUE) | |||||
if(CMAKE_HOST_UNIX) | |||||
execute_process(COMMAND ${_executable} -c "from distutils.sysconfig import *; print(get_python_lib())" | |||||
RESULT_VARIABLE _cvpy_process | |||||
@@ -240,7 +240,7 @@ if(NOT ${found}) | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE) | |||||
endif() | |||||
endif() | |||||
- endif(NOT ANDROID AND NOT IOS) | |||||
+ endif() | |||||
endif() | |||||
# Export return values | |||||
@@ -285,6 +285,17 @@ find_python("${OPENCV_PYTHON3_VERSION}" "${MIN_VER_PYTHON3}" PYTHON3_LIBRARY PYT | |||||
PYTHON3_INCLUDE_DIR PYTHON3_INCLUDE_DIR2 PYTHON3_PACKAGES_PATH | |||||
PYTHON3_NUMPY_INCLUDE_DIRS PYTHON3_NUMPY_VERSION) | |||||
+message("DEBUG PYTHON3_LIBRARIES: ${PYTHON3_LIBRARIES}") | |||||
+message("DEBUG PYTHON3_INCLUDE_DIR: ${PYTHON3_INCLUDE_DIR}") | |||||
+string(COMPARE EQUAL "${PYTHON3_LIBRARIES}" "" result) | |||||
+if(result) | |||||
+ message(FATAL_ERROR "can not find PYTHON3_LIBRARIES") | |||||
+endif() | |||||
+ | |||||
+string(COMPARE EQUAL "${PYTHON3_INCLUDE_DIR}" "" result) | |||||
+if(result) | |||||
+ message(FATAL_ERROR "can not find PYTHON3_INCLUDE_DIR") | |||||
+endif() | |||||
if(PYTHON_DEFAULT_EXECUTABLE) | |||||
set(PYTHON_DEFAULT_AVAILABLE "TRUE") | |||||
diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt | |||||
index a51acf386e..5605a54a32 100644 | |||||
--- a/modules/python/CMakeLists.txt | |||||
+++ b/modules/python/CMakeLists.txt | |||||
@@ -3,7 +3,7 @@ | |||||
# ---------------------------------------------------------------------------- | |||||
if(DEFINED OPENCV_INITIAL_PASS) # OpenCV build | |||||
-if(ANDROID OR APPLE_FRAMEWORK OR WINRT) | |||||
+ if(False) | |||||
ocv_module_disable_(python2) | |||||
ocv_module_disable_(python3) | |||||
return() |
@@ -0,0 +1,14 @@ | |||||
diff -u -r ../Python-3.7.1/Lib/subprocess.py ./Lib/subprocess.py | |||||
--- ../Python-3.7.1/Lib/subprocess.py 2018-10-20 06:04:19.000000000 +0000 | |||||
+++ ./Lib/subprocess.py 2018-10-20 20:17:50.157206343 +0000 | |||||
@@ -1389,9 +1389,7 @@ | |||||
args = list(args) | |||||
if shell: | |||||
- # On Android the default shell is at '/system/bin/sh'. | |||||
- unix_shell = ('/system/bin/sh' if | |||||
- hasattr(sys, 'getandroidapilevel') else '/bin/sh') | |||||
+ unix_shell = ('@TERMUX_PREFIX@/bin/sh') | |||||
args = [unix_shell, "-c"] + args | |||||
if executable: | |||||
args[0] = executable |
@@ -0,0 +1,13 @@ | |||||
diff --git a/Lib/tempfile.py b/Lib/tempfile.py | |||||
index 531cbf32f1..dae57e22bd 100644 | |||||
--- a/Lib/tempfile.py | |||||
+++ b/Lib/tempfile.py | |||||
@@ -170,7 +170,7 @@ def _candidate_tempdir_list(): | |||||
_os.path.expandvars(r'%SYSTEMROOT%\Temp'), | |||||
r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) | |||||
else: | |||||
- dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) | |||||
+ dirlist.extend([ '@TERMUX_PREFIX@/tmp' ]) | |||||
# As a last resort, the current directory. | |||||
try: |
@@ -0,0 +1,11 @@ | |||||
--- ./Lib/distutils/command/build.py.orig 2019-11-19 23:19:08.878782120 +0000 | |||||
+++ ./Lib/distutils/command/build.py 2019-11-19 23:19:18.410915201 +0000 | |||||
@@ -118,7 +118,7 @@ | |||||
if self.executable is None and sys.executable: | |||||
self.executable = os.path.normpath(sys.executable) | |||||
- | |||||
+ self.parallel = 1 | |||||
if isinstance(self.parallel, str): | |||||
try: | |||||
self.parallel = int(self.parallel) |
@@ -0,0 +1,36 @@ | |||||
diff -uNr Python-3.9.2/Lib/http/server.py Python-3.9.2.mod/Lib/http/server.py | |||||
--- Python-3.9.2/Lib/http/server.py 2021-02-19 14:31:44.000000000 +0200 | |||||
+++ Python-3.9.2.mod/Lib/http/server.py 2021-03-20 16:08:34.173543081 +0200 | |||||
@@ -1165,10 +1165,6 @@ | |||||
return | |||||
# Child | |||||
try: | |||||
- try: | |||||
- os.setuid(nobody) | |||||
- except OSError: | |||||
- pass | |||||
os.dup2(self.rfile.fileno(), 0) | |||||
os.dup2(self.wfile.fileno(), 1) | |||||
os.execve(scriptfile, args, env) | |||||
diff -uNr Python-3.9.2/Lib/smtpd.py Python-3.9.2.mod/Lib/smtpd.py | |||||
--- Python-3.9.2/Lib/smtpd.py 2021-02-19 14:31:44.000000000 +0200 | |||||
+++ Python-3.9.2.mod/Lib/smtpd.py 2021-03-20 16:11:48.785629393 +0200 | |||||
@@ -9,7 +9,8 @@ | |||||
-n | |||||
This program generally tries to setuid `nobody', unless this flag is | |||||
set. The setuid call will fail if this program is not run as root (in | |||||
- which case, use this flag). | |||||
+ which case, use this flag). Ignored in Termux as no setuid done on this | |||||
+ platform. | |||||
--version | |||||
-V | |||||
@@ -863,7 +864,7 @@ | |||||
class Options: | |||||
- setuid = True | |||||
+ setuid = False | |||||
classname = 'PureProxy' | |||||
size_limit = None | |||||
enable_SMTPUTF8 = False |
@@ -0,0 +1,59 @@ | |||||
diff -uNr Python-3.6.2/Lib/aifc.py Python-3.6.2.mod/Lib/aifc.py | |||||
--- Python-3.6.2/Lib/aifc.py 2017-07-08 06:33:27.000000000 +0300 | |||||
+++ Python-3.6.2.mod/Lib/aifc.py 2017-09-15 15:09:08.092797061 +0300 | |||||
@@ -920,7 +920,7 @@ | |||||
if __name__ == '__main__': | |||||
import sys | |||||
if not sys.argv[1:]: | |||||
- sys.argv.append('/usr/demos/data/audio/bach.aiff') | |||||
+ sys.argv.append('@TERMUX_PREFIX@/demos/data/audio/bach.aiff') | |||||
fn = sys.argv[1] | |||||
with open(fn, 'r') as f: | |||||
print("Reading", fn) | |||||
diff -uNr Python-3.6.2/Lib/mailcap.py Python-3.6.2.mod/Lib/mailcap.py | |||||
--- Python-3.6.2/Lib/mailcap.py 2017-07-08 06:33:27.000000000 +0300 | |||||
+++ Python-3.6.2.mod/Lib/mailcap.py 2017-09-15 15:08:41.312797081 +0300 | |||||
@@ -55,7 +55,8 @@ | |||||
# Don't bother with getpwuid() | |||||
home = '.' # Last resort | |||||
mailcaps = [home + '/.mailcap', '/etc/mailcap', | |||||
- '/usr/etc/mailcap', '/usr/local/etc/mailcap'] | |||||
+ '/usr/etc/mailcap', '/usr/local/etc/mailcap', | |||||
+ '@TERMUX_PREFIX@/etc/mailcap'] | |||||
return mailcaps | |||||
diff -uNr Python-3.6.2/Lib/mimetypes.py Python-3.6.2.mod/Lib/mimetypes.py | |||||
--- Python-3.6.2/Lib/mimetypes.py 2017-07-08 06:33:27.000000000 +0300 | |||||
+++ Python-3.6.2.mod/Lib/mimetypes.py 2017-09-15 15:08:05.522797106 +0300 | |||||
@@ -49,6 +49,7 @@ | |||||
"/usr/local/lib/netscape/mime.types", | |||||
"/usr/local/etc/httpd/conf/mime.types", # Apache 1.2 | |||||
"/usr/local/etc/mime.types", # Apache 1.3 | |||||
+ "@TERMUX_PREFIX@/etc/mime.types", # Termux | |||||
] | |||||
inited = False | |||||
diff -uNr Python-3.6.2/Lib/posixpath.py Python-3.6.2.mod/Lib/posixpath.py | |||||
--- Python-3.6.2/Lib/posixpath.py 2017-07-08 06:33:27.000000000 +0300 | |||||
+++ Python-3.6.2.mod/Lib/posixpath.py 2017-09-15 15:07:20.872797138 +0300 | |||||
@@ -32,7 +32,7 @@ | |||||
extsep = '.' | |||||
sep = '/' | |||||
pathsep = ':' | |||||
-defpath = '/bin:/usr/bin' | |||||
+defpath = '@TERMUX_PREFIX@/bin' | |||||
altsep = None | |||||
devnull = '/dev/null' | |||||
diff -uNr Python-3.9.0/Lib/uuid.py Python-3.9.0.mod/Lib/uuid.py | |||||
--- Python-3.9.0/Lib/uuid.py 2020-10-05 20:37:58.000000000 +0530 | |||||
+++ Python-3.9.0.mod/Lib/uuid.py 2020-10-08 18:25:45.565373486 +0530 | |||||
@@ -361,7 +361,6 @@ | |||||
try: | |||||
path_dirs = os.environ.get('PATH', os.defpath).split(os.pathsep) | |||||
- path_dirs.extend(['/sbin', '/usr/sbin']) | |||||
executable = shutil.which(command, path=os.pathsep.join(path_dirs)) | |||||
if executable is None: | |||||
return None |
@@ -0,0 +1,43 @@ | |||||
#!/bin/bash -e | |||||
source ${SRC_DIR}/scripts/whl/utils/utils.sh | |||||
ALL_PYTHON=${ALL_PYTHON} | |||||
# FIXME: now imperative py code do not support 3.10 | |||||
# but megenginelite and megbrain support it, so we | |||||
# config with 3.10.1 now | |||||
FULL_PYTHON_VER="3.8.3 3.9.9 3.10.1" | |||||
if [[ -z ${ALL_PYTHON} ]] | |||||
then | |||||
ALL_PYTHON=${FULL_PYTHON_VER} | |||||
else | |||||
check_python_version_is_valid "${ALL_PYTHON}" "${FULL_PYTHON_VER}" | |||||
fi | |||||
# FIXME python3.10+ self build have some issue, need config env | |||||
# _PYTHON_SYSCONFIGDATA_NAME remove this env after find the build issue | |||||
# do not care about this, apt install python3.10 do not have this issue | |||||
export _PYTHON_SYSCONFIGDATA_NAME="_sysconfigdata__linux_aarch64-linux-android" | |||||
function check_termux_env() { | |||||
echo "check is in termux env or not" | |||||
info=`command -v termux-info || true` | |||||
if [[ "${info}" =~ "com.termux" ]]; then | |||||
echo "find termux-info at: ${info}" | |||||
echo "check env now" | |||||
ENVS="PREFIX HOME" | |||||
for check_env in ${ENVS} | |||||
do | |||||
echo "try check env: ${check_env}" | |||||
if [[ "${!check_env}" =~ "termux" ]]; then | |||||
echo "env ${check_env} is: ${!check_env}" | |||||
else | |||||
echo "invalid ${check_env} env, may broken termux env" | |||||
exit -1 | |||||
fi | |||||
done | |||||
else | |||||
echo "invalid env, only support build android whl at termux env, please refs to: scripts/whl/BUILD_PYTHON_WHL_README.md to init env" | |||||
exit -1 | |||||
fi | |||||
} |
@@ -23,7 +23,7 @@ function ninja_dry_run_and_check_increment() { | |||||
exit -1 | exit -1 | ||||
fi | fi | ||||
${_BUILD_SHELL} ${_BUILD_FLAGS} 2>&1 | tee dry_run.log | |||||
bash ${_BUILD_SHELL} ${_BUILD_FLAGS} 2>&1 | tee dry_run.log | |||||
DIRTY_LOG=`cat dry_run.log` | DIRTY_LOG=`cat dry_run.log` | ||||
if [[ "${DIRTY_LOG}" =~ ${_INCREMENT_KEY_WORDS} ]]; then | if [[ "${DIRTY_LOG}" =~ ${_INCREMENT_KEY_WORDS} ]]; then | ||||
@@ -79,10 +79,23 @@ function check_build_ninja_python_api() { | |||||
PYTHON_API_INCLUDES="3.5.4\\\\include 3.6.8\\\\include 3.7.7\\\\include 3.8.3\\\\include" | PYTHON_API_INCLUDES="3.5.4\\\\include 3.6.8\\\\include 3.7.7\\\\include 3.8.3\\\\include" | ||||
elif [[ $OS =~ "Linux" ]]; then | elif [[ $OS =~ "Linux" ]]; then | ||||
INCLUDE_KEYWORD="include/python3.${ver:1:1}" | INCLUDE_KEYWORD="include/python3.${ver:1:1}" | ||||
PYTHON_API_INCLUDES="include/python3.5 include/python3.6 include/python3.7 include/python3.8" | |||||
info=`command -v termux-info || true` | |||||
if [[ "${info}" =~ "com.termux" ]]; then | |||||
echo "find termux-info at: ${info}" | |||||
is_punctuation=${ver:4:1} | |||||
INCLUDE_KEYWORD="include/python3.${ver:2:1}" | |||||
if [ ${is_punctuation} = "." ]; then | |||||
INCLUDE_KEYWORD="include/python3.${ver:2:2}" | |||||
fi | |||||
fi | |||||
PYTHON_API_INCLUDES="include/python3.5 include/python3.6 include/python3.7 include/python3.8 include/python3.9 include/python3.10" | |||||
elif [[ $OS =~ "Darwin" ]]; then | elif [[ $OS =~ "Darwin" ]]; then | ||||
is_punctuation=${ver:4:1} | |||||
INCLUDE_KEYWORD="include/python3.${ver:2:1}" | INCLUDE_KEYWORD="include/python3.${ver:2:1}" | ||||
PYTHON_API_INCLUDES="include/python3.5 include/python3.6 include/python3.7 include/python3.8" | |||||
if [ ${is_punctuation} = "." ]; then | |||||
INCLUDE_KEYWORD="include/python3.${ver:2:2}" | |||||
fi | |||||
PYTHON_API_INCLUDES="include/python3.5 include/python3.6 include/python3.7 include/python3.8 include/python3.9 include/python3.10" | |||||
else | else | ||||
echo "unknown OS: ${OS}" | echo "unknown OS: ${OS}" | ||||
exit -1 | exit -1 | ||||