diff --git a/.circleci/scripts/linux/build.sh b/.circleci/scripts/linux/build.sh index 0a6426dacb..fdd55ca608 100644 --- a/.circleci/scripts/linux/build.sh +++ b/.circleci/scripts/linux/build.sh @@ -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) diff --git a/.circleci/test.yml b/.circleci/test.yml index 4e4161410d..d751ae6a6e 100644 --- a/.circleci/test.yml +++ b/.circleci/test.yml @@ -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 diff --git a/.github/workflows/backend-snpe.yml b/.github/workflows/backend-snpe.yml index 2bd5b5be21..1391bf498e 100644 --- a/.github/workflows/backend-snpe.yml +++ b/.github/workflows/backend-snpe.yml @@ -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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 578faf2882..104cc36cd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 () diff --git a/cmake/MMDeployConfig.cmake.in b/cmake/MMDeployConfig.cmake.in index 88804fa5d3..23e728f7ab 100644 --- a/cmake/MMDeployConfig.cmake.in +++ b/cmake/MMDeployConfig.cmake.in @@ -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) diff --git a/csrc/mmdeploy/apis/c/mmdeploy/CMakeLists.txt b/csrc/mmdeploy/apis/c/mmdeploy/CMakeLists.txt index 1e76399e17..9863976b74 100644 --- a/csrc/mmdeploy/apis/c/mmdeploy/CMakeLists.txt +++ b/csrc/mmdeploy/apis/c/mmdeploy/CMakeLists.txt @@ -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) diff --git a/csrc/mmdeploy/apis/cxx/CMakeLists.txt b/csrc/mmdeploy/apis/cxx/CMakeLists.txt index e14bc66d25..953e5a61e3 100644 --- a/csrc/mmdeploy/apis/cxx/CMakeLists.txt +++ b/csrc/mmdeploy/apis/cxx/CMakeLists.txt @@ -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 () diff --git a/csrc/mmdeploy/apis/python/CMakeLists.txt b/csrc/mmdeploy/apis/python/CMakeLists.txt index 5a6f38ab20..656b20fd1d 100644 --- a/csrc/mmdeploy/apis/python/CMakeLists.txt +++ b/csrc/mmdeploy/apis/python/CMakeLists.txt @@ -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) diff --git a/tools/package_tools/README.md b/tools/package_tools/README.md new file mode 100644 index 0000000000..285bb51b87 --- /dev/null +++ b/tools/package_tools/README.md @@ -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. diff --git a/tools/package_tools/configs/linux_x64.yaml b/tools/package_tools/configs/linux_x64.yaml index a1dc7bc45f..f0e3b07310 100644 --- a/tools/package_tools/configs/linux_x64.yaml +++ b/tools/package_tools/configs/linux_x64.yaml @@ -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 diff --git a/tools/package_tools/configs/windows_x64.yaml b/tools/package_tools/configs/windows_x64.yaml index 47d0ccf597..c104a8c788 100644 --- a/tools/package_tools/configs/windows_x64.yaml +++ b/tools/package_tools/configs/windows_x64.yaml @@ -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}" diff --git a/tools/package_tools/mmdeploy_builder.py b/tools/package_tools/mmdeploy_builder.py index bdf70ed2e3..a4a80aa1a9 100644 --- a/tools/package_tools/mmdeploy_builder.py +++ b/tools/package_tools/mmdeploy_builder.py @@ -15,6 +15,7 @@ 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] - - 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.')