build_linux_nvidia.sh 13.4 KB
Newer Older
limm's avatar
limm committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
#!/bin/bash
# build_linux_nvidia.sh
#   Date: 08-03-2022, 24-04-2022
#
#   Run this script to build MMDeploy SDK and install necessary prerequisites.
#   This script will also setup python venv and generate prebuild binaries if requested.
#

#####
# Build vars
BUILD_TYPE="Release"
ARCH=$(uname -i)
PROC_NUM=$(nproc)
# Default GCC
GCC_COMPILER="g++"

#####
# Directories
# WORKING_DIR must correspond to MMDeploy root dir
WORKING_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
PPLCV_DIR=${WORKING_DIR}/ppl.cv
MMDEPLOY_DIR=${WORKING_DIR}

#####
# Versions
PPLCV_VER="0.7.0"
CMAKE_VER="3.23.0"

#####
# Flags
# WITH_PYTHON: Install misc. dependencies in the active venv
WITH_PYTHON=1
# WITH_CLEAN: Remove build output dirs
WITH_CLEAN=1
# WITH_PREBUILD: Generate prebuild archives
WITH_PREBUILD=0
# WITH_UNATTENDED: Unattended install, skip/use default options
WITH_UNATTENDED=0

#####
# Prefix: Set install prefix for ppl.cv, mmdeploy SDK depending on arch
if [[ "$ARCH" == aarch64 ]]; then
  INSTALL_PREFIX="/usr/local/aarch64-linux-gnu"
else
  INSTALL_PREFIX="/usr/local"
fi
PYTHON_VENV_DIR=${WORKING_DIR}/venv-mmdeploy

appargument1=$1
appargument2=$2

#####
# helper functions
echo_green() {
  if [ -n "$1" ]; then
    echo "$(tput setaf 10)$1$(tput sgr 0)"
  fi
}
echo_red() {
  if [ -n "$1" ]; then
    echo "$(tput setaf 1)$1$(tput sgr 0)"
  fi
}
echo_blue() {
  if [ -n "$1" ]; then
    echo "$(tput setaf 4)$1$(tput sgr 0)"
  fi
}
contains_element () {
  local e match="$1"
  shift
  for e; do [[ "$e" == "$match" ]] && return 0; done
  return 1
}
function version {
  echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }';
}
prompt_yesno() {
  if [ -n "$1" ]; then
    echo_blue "$1"
  fi
  if [[ $WITH_UNATTENDED -eq 1 ]]
  then
    echo_green "Unattended install, selecting default option"
    return 2
  else
    echo_blue "(y/n/q) or press [ENTER] to select default option"
    read -p "?" -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]
    then
      return 1
    elif [[ $REPLY =~ ^[Nn]$ ]]
    then
      return 0
    elif [[ $REPLY = "" ]]
    then
      echo "Selecting default option..."
      return 2
    elif [[ $REPLY =~ ^[Qq]$ ]]
    then
      echo_green "Quitting!"
      exit
    else
      echo_red "Invalid argument. Try again"
      prompt_yesno
    fi
  fi
}

prereqs() {
  echo_green "Installing prerequisites..."

  # cmake check & install
  echo_green "Checking your cmake version..."
  CMAKE_DETECT_VER=$(cmake --version | grep -oP '(?<=version).*')
  if [ $(version $CMAKE_DETECT_VER) -ge $(version "3.14.0") ]; then
    echo "Cmake version $CMAKE_DETECT_VER is up to date"
  else
    echo "CMake too old, purging existing cmake and installing ${CMAKE_VER}..."
    # purge existing
    sudo apt-get purge cmake
    sudo snap remove cmake
    # install prebuild
    wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-linux-${ARCH}.sh
    chmod +x cmake-${CMAKE_VER}-linux-${ARCH}.sh
    sudo ./cmake-${CMAKE_VER}-linux-${ARCH}.sh --prefix=/usr --skip-license
  fi

  # gcc-7 check
  echo_green "Checking your gcc version..."
  GCC_DETECT_VER=$(gcc --version | grep -oP '(?<=\)).*' -m1)
  if [ $(version $GCC_DETECT_VER) -ge $(version "7.0.0") ]; then
    echo "GCC version $GCC_DETECT_VER is up to date"
  else
    echo "gcc version too old, installing ${CMAKE_VER}..."
    echo "Purge existing cmake and install ${GCC_DETECT_VER}..."
    # Add repository if ubuntu < 18.04
    sudo add-apt-repository ppa:ubuntu-toolchain-r/test
    sudo apt-get update
    sudo apt-get install gcc-7
    sudo apt-get install g++-7
    GCC_COMPILER="g++-7"
  fi

  # spdlog
  echo_green "Checking spdlog version..."
  prompt_yesno "Install latest spdlog from source? (Default:no)"
  local res=$?
  if [[ $res -eq 1 ]] # || [ $res -eq 2 ]
  then
    echo_green "Building and installing latest spdlog from source"

    # remove libspdlog, as it might be an old version
    sudo apt-get remove libspdlog-dev -y

    git clone https://github.com/gabime/spdlog.git spdlog
    cd spdlog
    git pull
    git checkout tags/v1.8.1
    mkdir build -p && cd build
    # we must build spdlog with -fPIC enabled
    cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON && make -j${PROC_NUM}
    sudo make install
    sudo ldconfig
  fi

  # tensorrt check
  echo_green "Check your TensorRT version:"
  ## Check if ${TENSORRT_DIR} env variable has been set
  if [ -d "${TENSORRT_DIR}" ]; then
    echo "TENSORRT_DIR env. variable has been set ${TENSORRT_DIR}"
  else
    echo_red "TENSORRT_DIR env. variable has NOT been set."
    if [[ "$ARCH" == aarch64 ]]; then
      echo "Added TENSORRT_DIR, CUDNN_DIR to env."
      echo 'export TENSORRT_DIR="/usr/include/'${ARCH}'-linux-gnu/"' >> ${HOME}/.bashrc
      echo 'export CUDNN_DIR="/usr/include/'${ARCH}'-linux-gnu/"' >> ${HOME}/.bashrc
      echo 'export LD_LIBRARY_PATH="/usr/lib/'${ARCH}'-linux-gnu/:$LD_LIBRARY_PATH"' >> ${HOME}/.bashrc
      #source ${HOME}/.bashrc
      # sourcing in bash script won't set the env. variables so we will set them temporarily
      export TENSORRT_DIR="/usr/include/'${ARCH}'-linux-gnu/"
      export CUDNN_DIR="/usr/include/'${ARCH}'-linux-gnu/"
      export LD_LIBRARY_PATH="/usr/lib/'${ARCH}'-linux-gnu/:$LD_LIBRARY_PATH"
    else
      echo_red "Please Install TensorRT, CUDNN and add TENSORRT_DIR, CUDNN_DIR to environment variables before running this script!"
      exit
    fi
  fi

  # Determine TensorRT version and set paths accordingly
  echo "Checking TensorRT version...Please verify the detected versions below:"
  if [[ "$ARCH" == aarch64 ]]; then
    cat /usr/include/${ARCH}-linux-gnu/NvInferVersion.h | grep NV_TENSORRT
  else
    cat ${TENSORRT_DIR}/include/NvInferVersion.h | grep NV_TENSORRT
  fi
  prompt_yesno "Is TensorRT >=8.0.1.6 installed? (Always installed on Jetson) (Default:yes)"
  local res=$?
  if [[ $res -eq 1 ]] || [ $res -eq 2 ]
  then
    echo "TensorRT appears to be installed..."
  else
    echo_red "Error: You must install TensorRT before installing MMDeploy!"
    exit
  fi

  prompt_yesno "Install OpenCV? (Always installed on Jetson) (Default:no)"
  local res=$?
  if [[ $res -eq 1 ]] # || [ $res -eq 2 ]
  then
    echo "Installing libopencv-dev..."
    # opencv
    sudo apt-get install libopencv-dev
  fi
}

py_venv() {
  ## python venv
  echo_green "Installing python venv..."

  #check for python installed version
  pyv="$(python3 -V 2>&1)"
  pyv_old="Python 3.6"

  if echo "$pyv" | grep -q "$pyv_old"; then
      # use python 3.6
      curl https://bootstrap.pypa.io/pip/3.6/get-pip.py -o get-pip.py
  else
      # use python >=3.7
      curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
  fi

  # dependencies
  sudo apt-get install protobuf-compiler libprotoc-dev libssl-dev curl ninja-build -y
  sudo apt-get install libopenblas-dev python3-venv python3-dev python3-setuptools -y
  sudo python3 get-pip.py
  pip3 install testresources
  pip3 install --upgrade setuptools wheel

  if [ -d "${PYTHON_VENV_DIR}" ]; then
    prompt_yesno "Reinstall existing Python venv ${PYTHON_VENV_DIR}? (Default:no)"
    local res=$?
    if [[ $res -eq 1 ]]
    then
      rm -r ${PYTHON_VENV_DIR}
      python3 -m venv ${PYTHON_VENV_DIR} --system-site-packages #system site packages to keep trt from system installation
    fi
  else
    python3 -m venv ${PYTHON_VENV_DIR} --system-site-packages #system site packages to keep trt from system installation
  fi

  source ${PYTHON_VENV_DIR}/bin/activate
  python3 get-pip.py
  pip3 install testresources
  pip3 install --upgrade setuptools wheel

  # Latest PIL is not compatible with mmcv=1.4.1
  pip3 install Pillow==7.0.0

  if [[ "$ARCH" == aarch64 ]]
  then
    # protofbuf on jetson is quite old - must be upgraded
    pip3 install --upgrade protobuf
    # Install numpy >1.19.4 might give "Illegal instruction (core dumped)" on Jetson/aarch64
    # To solve it, we should set OPENBLAS_CORETYPE
    echo 'export OPENBLAS_CORETYPE=ARMV8' >> ~/.bashrc
    #source ${HOME}/.bashrc
    # sourcing in bash script won't set the env. variables so we will set them temporarily
    export OPENBLAS_CORETYPE=ARMV8
  fi
  pip3 install numpy
  pip3 install opencv-python
  pip3 install matplotlib

  prompt_yesno "Install PyTorch, Torchvision, mmcv in the active venv? (Default:no)"
  local res=$?
  if [[ $res -eq 1 ]]
  then
    # pytorch, torchvision, torchaudio
    if [[ "$ARCH" == aarch64 ]]
    then
      # pytorch
      wget https://nvidia.box.com/shared/static/fjtbno0vpo676a25cgvuqc1wty0fkkg6.whl -O torch-1.10.0-cp36-cp36m-linux_aarch64.whl
      pip3 install torch-1.10.0-cp36-cp36m-linux_aarch64.whl
      # torchvision
      sudo apt-get install libjpeg-dev zlib1g-dev libpython3-dev libavcodec-dev libavformat-dev libswscale-dev -y
      sudo rm -r torchvision
      git clone --branch v0.11.1 https://github.com/pytorch/vision torchvision
      cd torchvision
      export BUILD_VERSION=0.11.1  # where 0.x.0 is the torchvision version
      python3 setup.py install
      cd ../
      # torchaudio
      #sudo apt-get install -y sox libsox-dev libsox-fmt-all
      #sudo rm -r torchaudio
      #git clone -b v0.10.0 https://github.com/pytorch/audio torchaudio
      #cd torchaudio
      #git submodule update --init --recursive
      #python3 setup.py install
      #cd ../
      # mmcv
      pip3 uninstall mmcv-full
      pip3 install mmcv-full==1.4.1 -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.10.0/index.html
    else
      pip3 install torch==1.10.0+cu113 torchvision==0.11.1+cu113 torchaudio==0.10.0+cu113 -f https://download.pytorch.org/whl/cu113/torch_stable.html
      # mmcv
      pip3 uninstall mmcv-full
      pip3 install mmcv-full==1.4.1 -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.10.0/index.html
    fi
  fi

  # cleanup
  rm get-pip.py
}

pplcv() {
  ## ppl.cv
  echo_green "Building and installing ppl.cv..."

  cd ${WORKING_DIR}
  echo_blue "checking out '${PPLCV_DIR}' pkg..."
  if [ -d "${PPLCV_DIR}" ]; then
      echo "Already exists! Checking out the requested version..."
  else
      git clone https://github.com/openppl-public/ppl.cv.git ${PPLCV_DIR}
  fi
  cd ${PPLCV_DIR}
  git pull
  git checkout tags/v${PPLCV_VER}

  # remove all build files
  if [[ $WITH_CLEAN -eq 1 ]]
  then
    sudo rm -r ${PPLCV_DIR}/build
  fi

  # build
  mkdir build -p && cd build
  cmake -DPPLCV_USE_CUDA=ON -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} .. && make -j${processor_num} && sudo make install
  sudo ldconfig

  # generate prebuild and pack into .tar.gz
  if [[ $WITH_PREBUILD -eq 1 ]]
  then
    sudo make DESTDIR=./prebuild install
    tar -zcvf ${WORKING_DIR}/pplcv_${PPLCV_VER}_cuda-${ARCH}-build.tar.gz -C ./prebuild/ .
  fi
}

mmdeploy(){
  ## mmdeploy SDK
  echo_green "Building and installing mmdeploysdk..."

  cd ${MMDEPLOY_DIR}

  MMDEPLOY_DETECT_VER=$(cat mmdeploy/version.py | grep -Eo '[0-9]\.[0-9].[0-9]+')

  # reinit submodules
  git submodule update --init --recursive

  # python dependencies
  if [[ $WITH_PYTHON -eq 1 ]]
  then
    source ${PYTHON_VENV_DIR}/bin/activate

    ## h5py (Required by mmdeploy)
    ## h5py not directly supported by jetson and must be built/installed manually
    sudo apt-get install pkg-config libhdf5-10* libhdf5-dev -y
    sudo pip3 install Cython
    sudo env H5PY_SETUP_REQUIRES=0 pip3 install -U h5py==2.9.0

    pip install -e .
  fi

  # remove all build files
  if [[ $WITH_CLEAN -eq 1 ]]
  then
    sudo rm -r ${MMDEPLOY_DIR}/build
  fi

  # build
  mkdir build -p && cd build
  cmake .. \
    -DMMDEPLOY_BUILD_SDK=ON \
    -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \
    -DCMAKE_CXX_COMPILER=${GCC_COMPILER} \
    -Dpplcv_DIR=${INSTALL_PREFIX}/lib/cmake/ppl \
    -DMMDEPLOY_TARGET_DEVICES="cuda;cpu" \
    -DMMDEPLOY_TARGET_BACKENDS=trt \
    -DMMDEPLOY_CODEBASES=all \
    -DMMDEPLOY_BUILD_SDK_PYTHON_API=ON \
    -DTENSORRT_DIR=${TENSORRT_DIR} \
    -DCUDNN_DIR=${CUDNN_DIR}
  cmake --build . -- -j${PROC_NUM} && sudo make install
  sudo ldconfig

  # generate prebuild and pack into .tar.gz
  if [[ $WITH_PREBUILD -eq 1 ]]
  then
    sudo make DESTDIR=./prebuild install
    tar -zcvf ${WORKING_DIR}/mmdeploysdk_${MMDEPLOY_VER}_${ARCH}-build.tar.gz -C ./prebuild/ .
  fi

  ## build mmdeploy examples
  cp -r ${MMDEPLOY_DIR}/demo/csrc ${MMDEPLOY_DIR}/build/example
  cd ${MMDEPLOY_DIR}/build/example
  rm -r build
  mkdir build -p && cd build
  cmake -DMMDeploy_DIR=${INSTALL_PREFIX} ..
  make all
}

all() {
  # build all
  prereqs
  py_venv
  pplcv
  mmdeploy
}

#####
# supported package
package_list=(
  "all"
  "prereqs"
  "py_venv"
  "pplcv"
  "mmdeploy"
)

#####
# check input argument
if contains_element "$appargument1" "${package_list[@]}"; then
  echo_green "Build and install '$appargument1'..."
else
  echo_red "Unsupported argument '$appargument1'. Use one of the following:"
  for i in ${package_list[@]}
  do
    echo $i
  done
  exit
fi

#####
# Unattended/auto install
if [[ $appargument2 == "auto" ]]
then
  WITH_UNATTENDED=1
fi

#####
# Install dependencies in venv?
prompt_yesno "Install misc. dependencies in the active venv? (Default:${WITH_PYTHON})"
res=$?
if [[ $res -eq 1 ]]
then
  WITH_PYTHON=1
elif [[ $res -eq 0 ]]
then
  WITH_PYTHON=0
fi

#####
# Clean previous build dirs?
prompt_yesno "Clean previous build dirs? (Default:${WITH_CLEAN})"
res=$?
if [[ $res -eq 1 ]]
then
  WITH_CLEAN=1
elif [[ $res -eq 0 ]]
then
  WITH_CLEAN=0
fi

#####
# Generate prebuild dirs?
prompt_yesno "Generate prebuild dirs? (Default:${WITH_PREBUILD})"
res=$?
if [[ $res -eq 1 ]]
then
  WITH_PREBUILD=1
elif [[ $res -eq 0 ]]
then
  WITH_PREBUILD=0
fi

$appargument1

cd ${WORKING_DIR}

# update env. variables
exec bash