Skip to content

Commit

Permalink
[Enhancement] build sdk python api in standard-alone manner (#810)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
lvhan028 authored Aug 2, 2022
1 parent 1d3ce15 commit a15365e
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .circleci/scripts/linux/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion .circleci/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/backend-snpe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
Expand Down
2 changes: 1 addition & 1 deletion cmake/MMDeployConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions csrc/mmdeploy/apis/c/mmdeploy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions csrc/mmdeploy/apis/cxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
2 changes: 2 additions & 0 deletions csrc/mmdeploy/apis/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ 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)

target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/..
${CMAKE_CURRENT_SOURCE_DIR})
install(DIRECTORY ${CMAKE_SOURCE_DIR}/demo/python/ DESTINATION example/python)
47 changes: 47 additions & 0 deletions tools/package_tools/README.md
Original file line number Diff line number Diff line change
@@ -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.
8 changes: 6 additions & 2 deletions tools/package_tools/configs/linux_x64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand All @@ -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
8 changes: 5 additions & 3 deletions tools/package_tools/configs/windows_x64.yaml
Original file line number Diff line number Diff line change
@@ -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}"
Expand Down
121 changes: 84 additions & 37 deletions tools/package_tools/mmdeploy_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from typing import Dict

import yaml
from packaging import version

logger = logging.getLogger()
logger.setLevel(logging.INFO)
Expand Down Expand Up @@ -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} '
Expand Down Expand Up @@ -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.')
Expand All @@ -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)
Expand Down Expand Up @@ -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

Expand All @@ -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)

Expand All @@ -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]

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)

# remove temp package dir
_remove_if_exist(sdk_python_package_dir)
# 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

# 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'),
)

# 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.')

Expand Down

0 comments on commit a15365e

Please sign in to comment.