Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] build sdk python api in standalone manner #810

Merged
merged 12 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
49 changes: 49 additions & 0 deletions tools/package_tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Precompiled package

This document is going to describe the way to build MMDeploy package.

MMDeploy supports
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved

## 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/zh_cn/01-how-to-build/linux-x86_64.md) to install dependencies of MMDeploy,
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved
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
127 changes: 91 additions & 36 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 @@ -88,7 +89,7 @@ def _create_bdist_cmd(cfg, c_ext=False, dist_dir=None):
bdist_tags = cfg.get('bdist_tags', {})

# base
bdist_cmd = 'python setup.py bdist_wheel '
bdist_cmd = 'python3 setup.py bdist_wheel '
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved

# platform
bdist_cmd += f' --plat-name {PLATFORM_TAG} '
Expand Down Expand Up @@ -173,6 +174,40 @@ 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_envs = cfg.get('cmake_envs', dict())

lvhan028 marked this conversation as resolved.
Show resolved Hide resolved
args = [f'-D{k}={v}' for k, v in cmake_envs.items()]
args.append(
f'-DMMDeploy_DIR={mmdeploy_dir}/build/install/lib/cmake/MMDeploy')

if sys.platform == 'win32':
build_cmd = 'cmake --build . --config Release -- /m'
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved
pass
else:
args.append(f'-DPYTHON_EXECUTABLE={python_executable}')
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved
build_cmd = 'cmake --build . -- -j$(nproc)'

cmake_cmd = ' '.join(['cmake ../csrc/mmdeploy/apis/python'] + args)
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved

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 +232,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 +277,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 +293,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 +317,63 @@ 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
# 1. get conda env path from python's path.
# We assume python is managed by conda
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we support building on non-conda env in the future?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure. In my opinion, it depends on specific situations.
Currently, we only support precompiling on windows-x64 and linux-x86_64 platforms. So, I think conda is fair enough.

python_executable = shutil.which('python3')
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved
conda_env_path = osp.dirname(
osp.dirname(osp.dirname(python_executable)))
logging.info(conda_env_path)

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_api_lib_path = build_mmdeploy_python(
f'{conda_env_path}/mmdeploy-{python_version}/bin/python3',
cfg,
mmdeploy_dir,
)
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved
_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'{conda_env_path}/mmdeploy-{python_version}/bin/python3 '
f'setup.py bdist_wheel --plat-name '
f'{PLATFORM_TAG} --python-tag '
f'cp{python_major}{python_minor} '
f'--dist-dir {sdk_wheel_dir}')
lvhan028 marked this conversation as resolved.
Show resolved Hide resolved
_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