[Enhancement] build sdk python api in standard-alone manner (#810)

* build sdk python api in standard-alone manner

* enable MMDEPLOY_BUILD_SDK_MONOLITHIC and MMDEPLOY_BUILD_EXAMPLES in prebuild config

* link mmdeploy to python target when monolithic option is on

* checkin README to describe precompiled package build procedure

* use packaging.version.parse(python_version) instead of list(python_version)

* fix according to review results

* rebase master

* rollback cmake.in and apis/python/CMakeLists.txt

* reorganize files in install/example

* let cmake detect visual studio instead of specifying 2019

* rename whl name of precompiled package

* fix according to review results
pull/852/head
lvhan028 2022-08-01 19:23:48 -07:00 committed by GitHub
parent 1d3ce15e35
commit a15365e93f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 156 additions and 46 deletions

View File

@ -13,4 +13,4 @@ make -j$(nproc) && make install
cd install/example
mkdir -p build
cd build
cmake .. -DMMDeploy_DIR="$MMDEPLOY_DIR"/build/install/lib/cmake/MMDeploy "${ARGS[@]:2}" && make -j$(nproc)
cmake ../cpp -DMMDeploy_DIR="$MMDEPLOY_DIR"/build/install/lib/cmake/MMDeploy "${ARGS[@]:2}" && make -j$(nproc)

View File

@ -225,7 +225,7 @@ jobs:
cd install/example
mkdir build -ErrorAction SilentlyContinue
cd build
cmake .. -G "Visual Studio 16 2019" -A x64 -T v142 `
cmake ../cpp -G "Visual Studio 16 2019" -A x64 -T v142 `
-DMMDeploy_DIR="$env:MMDEPLOY_DIR/build/install/lib/cmake/MMDeploy" `
-DOpenCV_DIR="$env:OPENCV_PACKAGE_DIR"
cmake --build . --config Release -- /m

View File

@ -52,7 +52,7 @@ jobs:
make install
pushd install/example
mkdir build && pushd build
cmake .. -DMMDeploy_DIR=${PWD}/../../lib/cmake/MMDeploy
cmake ../cpp -DMMDeploy_DIR=${PWD}/../../lib/cmake/MMDeploy
make -j2
ls ./*
popd

View File

@ -166,8 +166,6 @@ if (MMDEPLOY_BUILD_SDK)
DESTINATION lib/cmake/MMDeploy
)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/demo/csrc/ DESTINATION example)
if (${CMAKE_VERSION} VERSION_LESS "3.17.0")
install(SCRIPT cmake/post-install.cmake)
endif ()

View File

@ -16,7 +16,7 @@ set(MMDEPLOY_VERSION_MAJOR @MMDEPLOY_VERSION_MAJOR@)
set(MMDEPLOY_VERSION_MINOR @MMDEPLOY_VERSION_MINOR@)
set(MMDEPLOY_VERSION_PATCH @MMDEPLOY_VERSION_PATCH@)
if (NOT MMDEPLOY_BUILD_SHARED AND NOT MMDEPLOY_BUILD_SDK_MONOLITHIC)
if (NOT MMDEPLOY_BUILD_SHARED)
if ("cuda" IN_LIST MMDEPLOY_TARGET_DEVICES)
find_package(CUDA REQUIRED)
if(MSVC)

View File

@ -55,6 +55,12 @@ foreach (TASK ${TASK_LIST})
DESTINATION include/mmdeploy)
endforeach ()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/demo/csrc/ DESTINATION example/cpp
FILES_MATCHING
PATTERN "*.cpp"
PATTERN "CMakeLists.txt"
)
if (MMDEPLOY_BUILD_SDK_CSHARP_API OR MMDEPLOY_BUILD_SDK_MONOLITHIC)
add_library(mmdeploy SHARED)
mmdeploy_load_static(mmdeploy MMDeployStaticModules)

View File

@ -21,4 +21,8 @@ if (MMDEPLOY_BUILD_SDK_CXX_API)
mmdeploy_export(${PROJECT_NAME})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mmdeploy/common.hpp
DESTINATION include/mmdeploy)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/demo/csrc/ DESTINATION example/cpp
FILES_MATCHING
PATTERN "*.cxx"
)
endif ()

View File

@ -21,6 +21,7 @@ endforeach ()
pybind11_add_module(${PROJECT_NAME} ${MMDEPLOY_PYTHON_SRCS})
mmdeploy_load_static(${PROJECT_NAME} MMDeployStaticModules)
mmdeploy_load_dynamic(${PROJECT_NAME} MMDeployDynamicModules)
target_link_libraries(${PROJECT_NAME} PRIVATE MMDeployLibs)
@ -28,3 +29,4 @@ target_link_libraries(${PROJECT_NAME} PRIVATE MMDeployLibs)
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/..
${CMAKE_CURRENT_SOURCE_DIR})
install(DIRECTORY ${CMAKE_SOURCE_DIR}/demo/python/ DESTINATION example/python)

View File

@ -0,0 +1,47 @@
# Precompiled package
This document is going to describe the way to build MMDeploy package.
## Prerequisites
- Download and install Miniconda from the [official website](https://docs.conda.io/en/latest/miniconda.html).
- Create conda environments for python 3.6, 3.7, 3.8 and 3.9, respectively.
```shell
for PYTHON_VERSION in 3.6 3.7 3.8 3.9
do
conda create --name mmdeploy-$PYTHON_VERSION python=$PYTHON_VERSION -y
done
```
- Prepare MMDeploy dependencies
Please follow the [build-on-Linux guide](../../docs/en/01-how-to-build/linux-x86_64.md) or [build-on-Windows guide](../../docs/en/01-how-to-build/linux-x86_64.md) to install dependencies of MMDeploy,
including PyTorch, MMCV, OpenCV, ppl.cv, ONNX Runtime and TensorRT.
Make sure the environment variables `pplcv_DIR`, `ONNXRUNTIME_DIR`, `TENSORRT_DIR`, `CUDNN_DIR` and `CUDA_TOOLKIT_ROOT_DIR` are exported.
## Run precompiled command
- On Linux platform,
```shell
conda activate mmdeploy-3.6
pip install pyyaml
cd the/root/path/of/mmdeploy
python tools/package_tools/mmdeploy_builder.py tools/package_tools/configs/linux_x64.yaml .
```
You will get the precompiled packages `mmdeploy-{version}-linux-x86_64-cuda11.1-tensorrt8.2.3.0` and `mmdeploy-{version}-linux-x86_64-onnxruntime1.8.1` in the current directory if everything's going well.
- On Windows platform, open `Anaconda Powershell Prompt` from the start menu and execute:
```shell
conda activate mmdeploy-3.6
pip install pyyaml
cd the/root/path/of/MMDeploy
python tools/package_tools/mmdeploy_builder.py tools/package_tools/configs/windows_x64.yaml .
```
When the build procedure finishes successfully, you will find `mmdeploy-{version}-windows-amd64-cuda11.1-tensorrt8.2.3.0` and `mmdeploy-{version}-windows-amd64-onnxruntime1.8.1` precompiled packages in the current directory.

View File

@ -2,7 +2,11 @@ global_config:
cmake_envs:
CMAKE_CXX_COMPILER: "g++-7"
MMDEPLOY_BUILD_SDK: "ON"
MMDEPLOY_BUILD_SDK_PYTHON_API: "ON"
MMDEPLOY_BUILD_SDK_MONOLITHIC: "ON"
MMDEPLOY_BUILD_SDK_CXX_API: "ON"
MMDEPLOY_BUILD_EXAMPLES: "ON"
MMDEPLOY_SHARED_LIBS: "OFF"
OpenCV_DIR: "${OpenCV_DIR}"
local_configs:
- BUILD_NAME: "mmdeploy-{mmdeploy_v}-{system}-{machine}-onnxruntime{ort_v}"
@ -15,6 +19,6 @@ local_configs:
MMDEPLOY_TARGET_DEVICES: '"cuda"'
MMDEPLOY_TARGET_BACKENDS: "trt"
TENSORRT_DIR: "${TENSORRT_DIR}"
CUDA_TOOLKIT_ROOT_DIR: "/usr/local/cuda-11.3"
CUDA_TOOLKIT_ROOT_DIR: "${CUDA_TOOLKIT_ROOT_DIR}"
CUDNN_DIR: "${CUDNN_DIR}"
pplcv_DIR: ${pplcv_DIR}/cuda-build/install/lib/cmake/ppl

View File

@ -1,11 +1,13 @@
global_config:
cmake_flags: ['-G "Visual Studio 16 2019" -A x64 -T v142']
cmake_flags: ['-A x64 -T v142']
cmake_envs:
MMDEPLOY_BUILD_SDK: "ON"
MMDEPLOY_BUILD_SDK_PYTHON_API: "ON"
MMDEPLOY_BUILD_SDK_MONOLITHIC: "ON"
MMDEPLOY_BUILD_SDK_CXX_API: "ON"
MMDEPLOY_BUILD_EXAMPLES: "ON"
MMDEPLOY_SHARED_LIBS: "OFF"
MMDEPLOY_CODEBASES: "all"
OpenCV_DIR: "%OpenCV_DIR%"
spdlog_DIR: '"%spdlog_DIR%"'
local_configs:
- BUILD_NAME: "mmdeploy-{mmdeploy_v}-{system}-{machine}-onnxruntime{ort_v}"

View File

@ -15,6 +15,7 @@ from subprocess import CalledProcessError, check_output, run
from typing import Dict
import yaml
from packaging import version
logger = logging.getLogger()
logger.setLevel(logging.INFO)
@ -94,8 +95,8 @@ def _create_bdist_cmd(cfg, c_ext=False, dist_dir=None):
bdist_cmd += f' --plat-name {PLATFORM_TAG} '
# python tag
py_flag = 'cp' if c_ext else 'py'
python_tag = f'{py_flag}{sys.version_info.major}{sys.version_info.minor}'
python_tag = f'cp{sys.version_info.major}{sys.version_info.minor}'\
if c_ext else 'py3'
if 'python_tag' in bdist_tags:
python_tag = bdist_tags['python_tag']
bdist_cmd += f' --python-tag {python_tag} '
@ -173,6 +174,41 @@ def build_mmdeploy(cfg, mmdeploy_dir, dist_dir=None):
_call_command(bdist_cmd, mmdeploy_dir)
def build_mmdeploy_python(python_executable, cfg, mmdeploy_dir):
cmake_flags = cfg.get('cmake_flags', [])
cmake_envs = cfg.get('cmake_envs', dict())
args = [f'-D{k}={v}' for k, v in cmake_envs.items()]
args.append(
f'-DMMDeploy_DIR={mmdeploy_dir}/build/install/lib/cmake/MMDeploy')
args.append(f'-DPYTHON_EXECUTABLE={python_executable}')
if sys.platform == 'win32':
build_cmd = 'cmake --build . --config Release -- /m'
pass
else:
build_cmd = 'cmake --build . -- -j$(nproc)'
cmake_cmd = ' '.join(['cmake ../csrc/mmdeploy/apis/python'] + cmake_flags +
args)
build_dir = osp.join(mmdeploy_dir, 'build_python')
_remove_if_exist(build_dir)
os.mkdir(build_dir)
_call_command(cmake_cmd, build_dir)
_call_command(build_cmd, build_dir)
python_api_lib_path = []
lib_patterns = ['*mmdeploy_python*.so', '*mmdeploy_python*.pyd']
for pattern in lib_patterns:
python_api_lib_path.extend(
glob(
osp.join(mmdeploy_dir, 'build_python/**', pattern),
recursive=True,
))
return python_api_lib_path[0]
def get_dir_name(cfg, tag, default_name):
if tag not in cfg:
logging.warning(f'{tag} not found, use `{default_name}` as default.')
@ -197,8 +233,8 @@ def check_env(cfg: Dict):
CUDA_TOOLKIT_ROOT_DIR = cmake_envs.get('CUDA_TOOLKIT_ROOT_DIR', '')
CUDA_TOOLKIT_ROOT_DIR = osp.expandvars(CUDA_TOOLKIT_ROOT_DIR)
nvcc_cmd = 'nvcc' if len(CUDA_TOOLKIT_ROOT_DIR) <= 0 else osp.join(
CUDA_TOOLKIT_ROOT_DIR, 'bin', 'nvcc')
nvcc_cmd = ('nvcc' if len(CUDA_TOOLKIT_ROOT_DIR) <= 0 else osp.join(
CUDA_TOOLKIT_ROOT_DIR, 'bin', 'nvcc'))
try:
nvcc = check_output(f'"{nvcc_cmd}" -V', shell=True)
@ -242,10 +278,9 @@ def check_env(cfg: Dict):
patch = re.search(r'#define NV_TENSORRT_PATCH (\d+)', data)
build = re.search(r'#define NV_TENSORRT_BUILD (\d+)', data)
if major is not None and minor is not None and patch is not None:
tensorrt_version = f'{major.group(1)}.' +\
f'{minor.group(1)}.' +\
f'{patch.group(1)}.' +\
f'{build.group(1)}'
tensorrt_version = (f'{major.group(1)}.' +
f'{minor.group(1)}.' +
f'{patch.group(1)}.' + f'{build.group(1)}')
env_info['trt_v'] = tensorrt_version
@ -259,7 +294,7 @@ def create_package(cfg: Dict, mmdeploy_dir: str):
# load flags
cfg, build_dir = get_dir_name(cfg, 'BUILD_NAME', build_dir)
cmake_envs = cfg.get('cmake_envs', dict())
build_sdk_flag = cmake_envs.get('MMDEPLOY_BUILD_SDK', False)
build_sdk_flag = cmake_envs.get('MMDEPLOY_BUILD_SDK', 'OFF')
if 'TAR_NAME' in cfg:
cfg, sdk_tar_name = get_dir_name(cfg, 'TAR_NAME', sdk_tar_name)
@ -283,42 +318,54 @@ def create_package(cfg: Dict, mmdeploy_dir: str):
dist_dir = osp.join(build_dir, 'dist')
build_mmdeploy(cfg, mmdeploy_dir, dist_dir=dist_dir)
if build_sdk_flag:
if build_sdk_flag == 'ON':
sdk_tar_dir = osp.join(build_dir, sdk_tar_name)
# copy lib and install into sdk dir
install_dir = osp.join(mmdeploy_dir, 'build/install/')
_copy(install_dir, sdk_tar_dir)
_copy(f'{mmdeploy_dir}/demo/python',
f'{sdk_tar_dir}/example/python')
_remove_if_exist(osp.join(sdk_tar_dir, 'example', 'build'))
# create sdk python api wheel
# for linux
python_api_lib_path = glob(
osp.join(mmdeploy_dir, 'build/lib/mmdeploy_python.*.so'))
# for windows
python_api_lib_path += glob(
osp.join(mmdeploy_dir, 'build/bin/*/mmdeploy_python.*.pyd'))
num_libs = len(python_api_lib_path)
if num_libs != 1:
logging.info('find multiple mmdeploy_python libraries.')
python_api_lib_path = python_api_lib_path[0]
# build SDK Python API according to different python version
for python_version in ['3.6', '3.7', '3.8', '3.9']:
_version = version.parse(python_version)
python_major, python_minor = _version.major, _version.minor
sdk_python_package_dir = osp.join(build_dir, '.mmdeploy_python')
_copy(PACKAGING_DIR, sdk_python_package_dir)
_copy(
osp.join(mmdeploy_dir, 'mmdeploy', 'version.py'),
osp.join(sdk_python_package_dir, 'mmdeploy_python',
'version.py'))
_copy(python_api_lib_path,
osp.join(sdk_python_package_dir, 'mmdeploy_python'))
sdk_wheel_dir = osp.abspath(osp.join(sdk_tar_dir, 'python'))
bdist_cmd = _create_bdist_cmd(
cfg, c_ext=True, dist_dir=sdk_wheel_dir)
_call_command(bdist_cmd, sdk_python_package_dir)
# create sdk python api wheel
sdk_python_package_dir = osp.join(build_dir,
'.mmdeploy_python')
_copy(PACKAGING_DIR, sdk_python_package_dir)
_copy(
osp.join(mmdeploy_dir, 'mmdeploy', 'version.py'),
osp.join(sdk_python_package_dir, 'mmdeploy_python',
'version.py'),
)
# remove temp package dir
_remove_if_exist(sdk_python_package_dir)
# build mmdeploy sdk python api
python_executable = shutil.which('python')\
.replace('mmdeploy-3.6', f'mmdeploy-{python_version}')
python_api_lib_path = build_mmdeploy_python(
python_executable, cfg, mmdeploy_dir)
_copy(
python_api_lib_path,
osp.join(sdk_python_package_dir, 'mmdeploy_python'),
)
_remove_if_exist(osp.join(mmdeploy_dir, 'build_python'))
sdk_wheel_dir = osp.abspath(osp.join(sdk_tar_dir, 'python'))
bdist_cmd = (f'{python_executable} '
f'setup.py bdist_wheel --plat-name '
f'{PLATFORM_TAG} --python-tag '
f'cp{python_major}{python_minor} '
f'--dist-dir {sdk_wheel_dir}')
_call_command(bdist_cmd, sdk_python_package_dir)
# remove temp package dir
_remove_if_exist(sdk_python_package_dir)
logging.info('build finish.')