Merge pull request #19 from movidius/ncsdk2-v2.05
[platform/adaptation/npu/intel-libmvnc.git] / install.sh
1 #!/bin/bash
2 #
3 # Movidius Neural Compute Toolkit installation script.
4
5 # The file ncsdk.conf contains the user configuration options and these
6 # override the defaults set in this script.  The function print_ncsdk_config()
7 # is called if ${VERBOSE} = "yes" to print user config variables and documents what they do.
8 #
9 # Function main at the bottom calls all of the other functions required to install.
10 #
11 # Function check_prerequisites lists the prerequisites required to install
12 #  
13 # Please provide feedback in our support forum if you encountered difficulties.
14 ################################################################################
15 # read in functions shared by installer and uninstaller
16 source $(dirname "$0")/install-utilities.sh
17
18
19 # check_supported_os - require install to be running on a supported OS
20 function check_supported_os()
21 {
22     ### Checking OS and version...
23     # install package lsb-release if application lsb_release isn't installed 
24     RC=0
25     command -v lsb_release > /dev/null || RC=$?
26     [ $RC -ne 0 ] && exec_and_search_errors "$SUDO_PREFIX apt-get $APT_QUIET install -y lsb-release"
27     
28     DISTRO="$(lsb_release -i 2>/dev/null | cut -f 2)"
29     VERSION="$(lsb_release -r 2>/dev/null | awk '{ print $2 }' | sed 's/[.]//')"
30     OS_DISTRO="${DISTRO:-INVALID}"
31     OS_VERSION="${VERSION:-255}"
32     if [ "${OS_DISTRO,,}" = "ubuntu" ] && [ ${OS_VERSION} = 1604 ]; then
33         [ "${VERBOSE}" = "yes" ] && echo "Installing on Ubuntu 16.04"
34     elif [ "${OS_DISTRO,,}" = "raspbian" ] && [ ${OS_VERSION} -ge 91 ]; then
35         [ "${VERBOSE}" = "yes" ] && echo "Installing on Raspbian Stretch"
36     elif [ "${OS_DISTRO,,}" = "raspbian" ] && [ ${OS_VERSION} -ge 80 ] && [ ${OS_VERSION} -lt 90 ]; then
37         echo -e "${RED} You are running Raspbian Jessie, which is not supported by NCSDK."
38         echo -e "Please upgrade to Raspbian Stretch and then install NCSDK."
39         echo -e "Error on line $LINENO${NC}"
40         exit 1
41     else
42         echo "Your current combination of Linux distribution and distribution version is not officially supported! Error on line $LINENO.  Will exit"
43         exit 1
44     fi
45     return 0
46 }
47
48
49 # check_prerequisites - tests the prerequisites required to install
50 function check_prerequisites()
51 {
52     prerequisites="sudo sed udevadm tar"
53     for i in $prerequisites; do
54         RC=0
55         # command is a bash builtin to run a command ($i in this case)
56         command -v $i > /dev/null || RC=$?
57         if [ $RC -ne 0 ] ; then
58             echo -e "${RED}Installation prerequisite $i not available on this system.  Error on line $LINENO.  Will exit${NC}"
59             exit 1
60         fi
61     done
62     
63     check_supported_os
64 }
65
66
67 # create_install_logfile - Save a log file of the install in $DIR/setup-logs
68 function create_install_logfile()
69 {
70     # Print stdout and stderr to screen and in logfile
71     d=$(date +%y-%m-%d-%H-%M)
72     LOGFILE="setup_"$d".log"
73     ${SUDO_PREFIX} mkdir -p $DIR/setup-logs
74     ${SUDO_PREFIX} chown $(id -un):$(id -gn) $DIR/setup-logs
75     echo "Saving installation log file in $DIR/setup-logs/$LOGFILE"
76     exec &> >(tee -a "$DIR/setup-logs/$LOGFILE")    
77 }
78
79
80 # print_ncsdk_config - prints out the definition and values of user configurable options
81 function print_ncsdk_config()
82 {
83     echo ""
84     echo "print_ncsdk_config()"
85     echo "INSTALL_DIR - Main installation directory"
86     echo "INSTALL_CAFFE - Flag to install TensorFlow"
87     echo "CAFFE_FLAVOR - Specific 'flavor' of caffe to install"
88     echo "CAFFE_USE_CUDA - Use CUDA enabled version of caffe"
89     echo "INSTALL_TENSORFLOW - Flag to install TensorFlow"
90     echo "INSTALL_TOOLKIT - Flag to install Neural Compute Toolkit"
91     echo "PIP_SYSTEM_INSTALL - Globally install pip packages via sudo -H"
92     echo "VERBOSE - Flag to enable more verbose installation"
93     echo "USE_VIRTUALENV - Flag to enable python virtualenv"
94     echo "MAKE_NJOBS - Number of processes to use for parallel build (i.e. make -j MAKE_NJOBS)"
95     echo ""
96     echo "INSTALL_DIR=${INSTALL_DIR}"
97     echo "INSTALL_CAFFE=${INSTALL_CAFFE}"
98     echo "CAFFE_FLAVOR=${CAFFE_FLAVOR}"
99     echo "CAFFE_USE_CUDA=${CAFFE_USE_CUDA}"
100     echo "INSTALL_TENSORFLOW=${INSTALL_TENSORFLOW}"
101     echo "INSTALL_TOOLKIT=${INSTALL_TOOLKIT}"    
102     echo "PIP_SYSTEM_INSTALL=${PIP_SYSTEM_INSTALL}"
103     echo "VERBOSE=${VERBOSE}"
104     echo "USE_VIRTUALENV=${USE_VIRTUALENV}"
105     echo "MAKE_NJOBS=${MAKE_NJOBS}"
106     echo ""
107 }
108
109
110 # init_installer - 
111 #   sets up installer including error handling, verbosity level, sudo privileges,
112 #   reads ncsdk.conf via read_ncsdk_config function, creates dirs for installation,
113 #   sets global variables CONF_FILE, DIR and NCSDK_VERSION.
114 function init_installer()
115 {
116     # trap errors (function is in install-utilities.sh) 
117     set_error_handling
118
119     ### get constants (function is in install-utilities.sh) 
120     initialize_constants
121     
122     ### check if file exist 
123     VERSION_FILE=version.txt
124     if [ ! -f ${VERSION_FILE} ] ; then
125         echo -e "${RED}Couldn't find file ${VERSION_FILE}. Error on line $LINENO  Will exit${NC}"
126         exit 1
127     fi
128     NCSDK_VERSION=`cat ${VERSION_FILE}`
129     echo "Installer NCSDK version: $NCSDK_VERSION"
130     echo ""
131     
132     ### read config file (function is in install-utilities.sh) 
133     read_ncsdk_config
134
135     ### Ask for sudo priviledges (function is in install-utilities.sh)
136     ask_sudo_permissions
137
138     ### Set installer verbosity level
139     APT_QUIET=-qq
140     PIP_QUIET=--quiet
141     GIT_QUIET=-q
142     STDOUT_QUIET='>/dev/null'
143     if [ "${VERBOSE}" = "yes" ]; then
144         APT_QUIET=
145         PIP_QUIET=
146         GIT_QUIET=
147         STDOUT_QUIET=
148     fi
149
150     # Install location for sdk and API 
151     DIR=${INSTALL_DIR}/NCSDK
152     SDK_DIR=$DIR/ncsdk-$(eval uname -m)
153     if [ -d /usr/local/lib ]; then
154         SYS_INSTALL_DIR=/usr/local
155     else
156         SYS_INSTALL_DIR=/usr
157     fi
158
159     ### make sure system has required prerequisites
160     check_prerequisites
161
162     if [ "${VERBOSE}" = "yes" ] ; then
163         print_ncsdk_config
164     fi
165 }
166
167
168 # make_installer_dirs - creates directories that the install uses
169 function make_installer_dirs()
170 {
171     ### Create Required installation dirs.  
172     ${SUDO_PREFIX} mkdir -p ${INSTALL_DIR}
173     ${SUDO_PREFIX} chown $(id -un):$(id -gn) "$INSTALL_DIR"
174     # Get absolute dir
175     INSTALL_DIR="$( cd ${INSTALL_DIR} && pwd )"
176
177     
178     # Create directories if needed
179     $SUDO_PREFIX mkdir -p $SYS_INSTALL_DIR/include/mvnc2
180     $SUDO_PREFIX mkdir -p $SYS_INSTALL_DIR/lib/mvnc
181 }
182
183
184 # download_and_copy_files - download tarball and copy to install dir
185 function download_and_copy_files()
186 {
187     download_filename="NCSDK-${NCSDK_VERSION}.tar.gz"
188     if [ ! -f ${download_filename} ] ; then
189         echo "Downloading ${download_filename}"
190         ncsdk_link="https://downloadmirror.intel.com/27839/eng/NCSDK-2.05.00.02.tar.gz"
191         exec_and_search_errors "wget --no-cache -O ${download_filename} $ncsdk_link"
192     fi
193     # ncsdk_pkg is the filename without the .tar.gz extension
194     ncsdk_pkg=${download_filename%%.tar.gz}
195
196     # copy files
197     ${SUDO_PREFIX} cp ./$download_filename ${INSTALL_DIR}/ncsdk.tar.gz
198     ${SUDO_PREFIX} cp ./uninstall.sh ${INSTALL_DIR}/
199     ${SUDO_PREFIX} cp ./install-utilities.sh ${INSTALL_DIR}/
200     ${SUDO_PREFIX} cp ./ncsdk.conf ${INSTALL_DIR}/
201
202     # save current dir
203     FROM_DIR=$PWD
204
205     # untar in INSTALL_DIR 
206     cd ${INSTALL_DIR}
207     if [ "${VERBOSE}" = "yes" ] ; then  
208         TAR_OPTIONS="--no-same-owner -vzxf"
209     else
210         TAR_OPTIONS="--no-same-owner -zxf"
211     fi
212     ${SUDO_PREFIX} tar ${TAR_OPTIONS} ./ncsdk.tar.gz
213     ${SUDO_PREFIX} rm -rf NCSDK
214     ${SUDO_PREFIX} mv $ncsdk_pkg* NCSDK
215     cd ${INSTALL_DIR}/NCSDK
216
217     ${SUDO_PREFIX} cp ${FROM_DIR}/version.txt ${INSTALL_DIR}
218     ${SUDO_PREFIX} cp ${FROM_DIR}/ncsdk.conf ${INSTALL_DIR}/NCSDK 
219     ${SUDO_PREFIX} cp ${FROM_DIR}/uninstall.sh ${INSTALL_DIR}/NCSDK 
220     ${SUDO_PREFIX} cp ${FROM_DIR}/requirements.txt ${INSTALL_DIR}/NCSDK 
221     ${SUDO_PREFIX} cp ${FROM_DIR}/requirements_apt.txt ${INSTALL_DIR}/NCSDK 
222     ${SUDO_PREFIX} cp ${FROM_DIR}/requirements_apt_raspbian.txt ${INSTALL_DIR}/NCSDK 
223 }
224
225
226 # compare_versions - sets global VERCOMP_RETVAL 
227 function compare_versions()
228 {
229     VERCOMP_RETVAL=-1
230     if [ $1 = $2 ]; then
231         VERCOMP_RETVAL=0
232     else
233         if [[ $1 = `echo -e "$1\n$2" | sort -V | head -n1` ]]; then
234             VERCOMP_RETVAL=1
235         else
236             VERCOMP_RETVAL=2
237         fi
238     fi
239 }
240
241
242 # print_previous_ncsdk_install_info - if previous valid install found, print version number
243 function print_previous_ncsdk_install_info()
244 {
245     if [ "${PREV_INSTALL_INFO}" != "unknown" ]; then
246
247         # compare_versions sets VERCOMP_RETVAL to 0, 1 or 2
248         compare_versions ${PREV_NCSDK_VER} ${NCSDK_VERSION}
249         
250         if [ ${VERCOMP_RETVAL} -eq 0 ]; then
251             echo "Previously installed version is the same as installer version, overwriting..."
252         elif [ ${VERCOMP_RETVAL} -eq 1 ]; then
253             echo "Previously installed version is older than installer version, upgrading..."
254         else
255             echo "Previously installed version is more recent than installer version, downgrading..."
256         fi
257     fi
258 }
259
260
261 # install_apt_dependencies - installs dependencies using apt 
262 function install_apt_dependencies()
263 {
264     exec_and_search_errors "$SUDO_PREFIX apt-get $APT_QUIET update"
265     exec_and_search_errors "$SUDO_PREFIX apt-get $APT_QUIET install -y $(cat "$DIR/requirements_apt.txt")"
266     exec_and_search_errors "$SUDO_PREFIX apt-get $APT_QUIET install -y --no-install-recommends libboost-all-dev"
267
268     # Make sure pip2 and pip3 installed correctly
269     RC=0
270     command -v pip2 > /dev/null || RC=$?
271     if [ $RC -ne 0 ] ; then
272         echo -e "${RED} pip2 command not found.  Will exit${NC}"
273         exit 1
274     fi    
275     RC=0
276     command -v pip3 > /dev/null || RC=$?
277     if [ $RC -ne 0 ] ; then
278         echo -e "${RED} pip3 command not found.  Will exit${NC}"
279         exit 1
280     fi
281
282     $SUDO_PREFIX ldconfig
283 }
284
285
286 # setup_virtualenv - Use python virtualenv 
287 function setup_virtualenv()
288 {
289     echo ""
290     echo "USE_VIRTUALENV=${USE_VIRTUALENV} - will use python virtualenv"
291     [ "${VERBOSE}" = "yes" ] && echo "Installing prerequisites for virtualenv"
292     ${SUDO_PREFIX} apt-get $APT_QUIET install python-virtualenv -y
293     echo ""
294     
295     VIRTUALENV_DIR=${INSTALL_DIR}/virtualenv-python
296     # if virtualenv dir exists, try to activate it
297     if [ -d ${VIRTUALENV_DIR} ] ; then
298         RC=0
299         # disable trapping for unset variables due to activate script 
300         set +u
301         source ${VIRTUALENV_DIR}/bin/activate || RC=$?
302         set -u
303         if [ ${RC} -ne 0 ] ; then
304             echo "source ${VIRTUALENV_DIR}/bin/activate gave an error=${RC}"
305             echo "You need to investigate: 1) Either figure out why virtualenv is not activating correctly or"
306             echo "                         2) edit ncsdk.conf to set USE_VIRTUALENV=no to disable virtualenv.  Will exit"
307             exit 1
308             echo ""
309         else
310             echo "virtualenv ${INSTALL_DIR}/virtualenv-python exists, and successfully activated it"
311         fi
312     else
313         # Create new virtualenv and activate it
314         echo "Creating new virtualenv in ${VIRTUALENV_DIR}"
315         ${SUDO_PREFIX} mkdir -p ${VIRTUALENV_DIR}
316         ${SUDO_PREFIX} virtualenv --system-site-packages -p python3 ${VIRTUALENV_DIR}
317         # disable trapping for unset variables due to activate script
318         set +u
319         RC=0        
320         source ${VIRTUALENV_DIR}/bin/activate || RC=$?
321         set -u        
322         if [ ${RC} -ne 0 ] ; then
323             echo "source ${VIRTUALENV_DIR}/bin/activate gave an error=${RC}"
324             echo "This is unexpected and needs to be investigated."
325             echo "virtualenv can be disabled via edit ncsdk.conf to set USE_VIRTUALENV=no.  Will exit"
326             exit 1
327         else
328             echo "Created virtualenv in ${VIRTUALENV_DIR}, and successfully activated it"
329         fi
330     fi
331     echo ""
332     echo "   To activate this virtualenv in the future enter"
333     echo "   source ${VIRTUALENV_DIR}/bin/activate "
334     echo ""
335
336
337 }
338
339
340 # install_python_dependencies - install dependencies using pip2/pip3 
341 function install_python_dependencies()
342 {
343     # Note: If sudo is used and PIP_SYSTEM_INSTALL=yes (set in ncsdk.conf), pip packages
344     #       will be installed in the systems directory, otherwise installed per user
345     echo "Installing python dependencies"
346
347     if [ "${OS_DISTRO,,}" = "ubuntu" ] ; then
348         exec_and_search_errors "$PIP_PREFIX pip3 install $PIP_QUIET --trusted-host files.pythonhosted.org -r $DIR/requirements.txt"
349         # Install packages for python 2.x, required for NCSDK python API
350         exec_and_search_errors "$PIP_PREFIX pip2 install $PIP_QUIET --trusted-host files.pythonhosted.org Enum34>=1.1.6"
351         exec_and_search_errors "$PIP_PREFIX pip2 install $PIP_QUIET --trusted-host files.pythonhosted.org --upgrade numpy>=1.13.0,<=1.13.3"
352
353         # verify python3 import scipy._lib.decorator working, a potential problem on Ubuntu only.  First check python3 import scipy.  
354         RC=0
355         python3 -c "import scipy" >& /dev/null || RC=$?
356         if [ ${RC} -ne 0 ] ; then
357             echo -e "${RED}Error, cannot import scipy into python3.  Error on line $LINENO.  Will exit${NC}"
358             exit 1
359         fi
360         RC=0
361         python3 -c "import scipy._lib.decorator" >& /dev/null || RC=$?
362         if [ ${RC} -ne 0 ] ; then
363             echo -e "${YELLOW}Problem importing scipy._lib.decorator into python3.  Attempting to fix${NC}"
364             # Get the location of scipy to get the location of decorator.py 
365             RC=0
366             SCIPY_FILE=$(python3 -c "import scipy; print(scipy.__file__)") || RC=$?
367             if [ ${RC} -eq 0 ] ; then
368                 # Get directory decorator.py is in from SCIPY_FILE. If decorator.py isn't a readable file, i.e. from a broken softlink, reinstall via apt
369                 [ ! -f $(dirname $SCIPY_FILE)/decorator.py ] && $SUDO_PREFIX apt install --reinstall python*-decorator
370                 RC=0
371                 python3 -c "import scipy._lib.decorator" >& /dev/null || RC=$?
372                 if [ ${RC} -ne 0 ] ; then
373                     echo -e "${RED}Error, cannot import scipy._lib.decorator even after trying to fix this problem.  Error on line $LINENO.  Will exit${NC}"
374                     exit 1
375                 else
376                     echo "Resolved problem importing scipy._lib.decorator into python3."
377                     echo ""
378                 fi
379             else
380                 echo -e "${RED}Error in python3 importing scipy / printing scipy.__file__.  Error on line $LINENO.  Will exit${NC}"
381                 exit 1
382             fi  
383         fi
384         
385     elif [ "${OS_DISTRO,,}" = "raspbian" ] ; then
386         # for Raspian, use apt with python3-* if available
387         exec_and_search_errors "$SUDO_PREFIX apt-get $APT_QUIET install -y $(cat "$DIR/requirements_apt_raspbian.txt")"
388         exec_and_search_errors "$PIP_PREFIX pip3 install $PIP_QUIET --trusted-host files.pythonhosted.org Cython graphviz scikit-image"
389         exec_and_search_errors "$PIP_PREFIX pip3 install $PIP_QUIET --trusted-host files.pythonhosted.org --upgrade numpy==1.13.1"
390         exec_and_search_errors "$PIP_PREFIX pip3 install $PIP_QUIET --trusted-host files.pythonhosted.org pygraphviz Enum34>=1.1.6 networkx>=2.1,<=2.1"
391         # Install packages for python 2.x, required for NCSDK python API
392         exec_and_search_errors "$PIP_PREFIX pip2 install $PIP_QUIET --trusted-host files.pythonhosted.org Enum34>=1.1.6"
393         exec_and_search_errors "$PIP_PREFIX pip2 install $PIP_QUIET --trusted-host files.pythonhosted.org --upgrade numpy==1.13.1"
394     fi
395 }
396
397
398 # find_tensorflow - Test if tensorflow is installed and if it's the supported version
399 #                   function arg1 - package name - tensorflow or tensorflow-gpu
400 #                   sets FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION=0 when supported version of TensorFlow is installed
401 #                   sets FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION=1 when an unsupported version of TensorFlow is installed
402 #                   sets FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION=2 when TensorFlow isn't installed
403 function find_tensorflow()
404 {
405     SUPPORTED_TENSORFLOW_VERSION=1.7.0
406     RC=0
407     $PIP_PREFIX pip3 show $1 1> /dev/null || RC=$?
408     if [ $RC -eq 0 ]; then
409         tf_ver_string=$($PIP_PREFIX pip3 show $1 | grep "^Version:")
410         tf_ver=${tf_ver_string##* }
411         if echo "$1" | grep -q "gpu"; then
412             hw="GPU"
413         else
414             hw="CPU"
415         fi
416         echo "Found tensorflow $hw version $tf_ver"
417         if [ $tf_ver = "$SUPPORTED_TENSORFLOW_VERSION" ]; then
418             FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION=0
419         else
420             FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION=1
421         fi
422     else
423         FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION=2
424     fi
425 }
426
427
428 # install_tensorflow - install supported version of tensorflow on system
429 function install_tensorflow()
430 {
431     if [ "${OS_DISTRO,,}" = "raspbian" ] && [ "${INSTALL_TENSORFLOW}" = "yes" ]; then
432         echo -e "${YELLOW}NOTE: TensorFlow is not officially supported on Raspbian Stretch."
433         echo -e "      We are installing a specific nightly TensorFlow build from http://ci.tensorflow.org/view/Nightly/job/nightly-pi-python3/"
434         echo -e "      for code development and testing. ${NC}"
435
436         echo "Checking if tensorflow is installed..."
437         # find_tensorflow sets FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION to 0, 1 or 2 depending if correct version installed, incorrect version installed or not installed, respectively
438         find_tensorflow "tensorflow" 
439         tf=${FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION}
440         INSTALL_TF="no"
441         [ $tf -eq 0 ] && echo "Installed TensorFlow is the correct version, not re-installing"
442         if [ $tf -eq 1 ] ; then
443             exec_and_search_errors "$PIP_PREFIX pip3 uninstall --quiet -y tensorflow"
444             INSTALL_TF="yes"
445         fi
446         [ $tf -eq 2 ] && INSTALL_TF="yes"
447
448         # install TensorFlow if needed
449         if [ "${INSTALL_TF}" = "yes" ] ; then
450             echo "Couldn't find a supported tensorflow version, downloading TensorFlow $SUPPORTED_TENSORFLOW_VERSION"
451             # rename wheel for python 3.5
452             WHEEL_DOWNLOAD=tensorflow-1.7.0-cp34-none-any.whl
453             WHEEL=tensorflow-1.7.0-cp35-none-any.whl
454             [ -f "${WHEEL_DOWNLOAD}" ] && sudo mv -f ${WHEEL_DOWNLOAD} ${WHEEL_DOWNLOAD}.save
455             $SUDO_PREFIX wget https://storage.googleapis.com/download.tensorflow.org/deps/pi/2018_05_21/${WHEEL_DOWNLOAD}
456             [ -f "${WHEEL}" ] && $SUDO_PREFIX mv -f ${WHEEL} ${WHEEL}.save
457             $SUDO_PREFIX mv ${WHEEL_DOWNLOAD} ${WHEEL}
458             echo "Installing TensorFlow"
459             exec_and_search_errors "$PIP_PREFIX pip3 install --quiet ${WHEEL}"
460             echo "Finished installing TensorFlow"
461         fi              
462         
463     elif [ "${OS_DISTRO,,}" = "ubuntu" ] ; then
464         echo "Checking whether tensorflow CPU version is installed..."
465         # find_tensorflow sets FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION to 0, 1 or 2 depending if correct version installed, incorrect version installed or not installed, respectively
466         find_tensorflow "tensorflow" 
467         tf=${FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION}
468         if [ $tf -ne 0 ]; then
469             echo "Checking whether tensorflow GPU version is installed..."
470             find_tensorflow tensorflow-gpu 
471             tf_gpu=${FIND_TENSORFLOW__FOUND_SUPPORTED_VERSION}
472         fi      
473         if [[ $tf -ne 0 && $tf_gpu -ne 0 ]]; then
474             echo "Couldn't find a supported tensorflow version, installing tensorflow $SUPPORTED_TENSORFLOW_VERSION"
475             exec_and_search_errors "$PIP_PREFIX pip3 install $PIP_QUIET --trusted-host files.pythonhosted.org tensorflow==$SUPPORTED_TENSORFLOW_VERSION"
476         else
477             echo "tensorflow already at latest supported version...skipping."
478         fi
479     fi
480 }
481
482
483 # download_caffe - download caffe sources via git
484 function download_caffe()
485 {
486     if [ -h "caffe" ]; then
487         $SUDO_PREFIX rm caffe
488     fi
489     if [ ! -d $CAFFE_DIR ]; then
490         echo "Downloading Caffe..."
491         eval git clone $GIT_QUIET $CAFFE_SRC $STDOUT_QUIET $CAFFE_DIR
492     fi
493     ln -sf $CAFFE_DIR caffe
494 }
495
496
497 # configure_caffe_options - customize caffe options
498 function configure_caffe_options()
499 {
500     # TODO: Make this configurable. Supports only python3 for now.
501     sed -i 's/python_version "2"/python_version "3"/' CMakeLists.txt
502     # Use/don't use CUDA
503     if [ "$CAFFE_USE_CUDA" = "no" ]; then
504         sed -i 's/CPU_ONLY  "Build Caffe without CUDA support" OFF/CPU_ONLY  "Build Caffe without CUDA support" ON/' CMakeLists.txt
505     fi
506 }
507
508
509 # find_and_try_adjusting_caffe_symlinks - Create caffe soft link to point to specific caffe flavor that was installed
510 function find_and_try_adjusting_caffe_symlinks()
511 {
512     cd ${INSTALL_DIR}
513     if [[ -h "caffe" && -d "$CAFFE_DIR" ]]; then
514         readlink -f caffe | grep -q "$CAFFE_DIR"
515         if [ $? -eq 0 ]; then
516             echo "$CAFFE_DIR present and we're currently pointing to it"
517             FIND_AND_TRY_ADJUSTING_CAFFE_SYMLINKS_FOUND=0
518         else
519             if [ -d "${CAFFE_DIR}" ]; then
520                 echo "$CAFFE_DIR present, but we're not currently using it. Use it."
521             fi
522             $SUDO_PREFIX rm -f caffe
523             $SUDO_PREFIX ln -sf $CAFFE_DIR caffe
524             FIND_AND_TRY_ADJUSTING_CAFFE_SYMLINKS_FOUND=0
525         fi
526     else
527         echo "Possibly stale caffe install, starting afresh"
528         FIND_AND_TRY_ADJUSTING_CAFFE_SYMLINKS_FOUND=1
529     fi
530 }
531
532 # check_opencv_caffe_conflict - Avoid known problem with OpenCV library linking with libprotobuf-lite when using ssd-caffe
533 function check_opencv_caffe_conflict()
534 {
535     # Problem seen with ssd-caffe if built with OpenCV that links with GTK libraries which uses libprotobuf-lite.so.9
536     # Building OpenCV from source on Ubuntu by default has this problem.  OpenCV defaults to linking with GTK libs which use libprotobuf-lite.so
537     # and this causes a conflict as caffe links against libprotobuf.so, and using libprotobuf-lite.so and libprotobuf.so in the same app can cause problems.
538     # Building OpenCV with QT vs. GTK avoids this problems.
539     # Running make install runs ./uninstall-opencv.sh which attempts to remove OpenCV built from source for this reason.
540     # Note: The OpenCV version apt-get installs in /usr/lib doesn't link against libprotobuf-lite.so, so doesn't have this problem.
541     if [ "${CAFFE_FLAVOR}" = "ssd" ]; then
542         LIBOPENCV_HIGHGUI=/usr/local/lib/libopencv_highgui.so.?.?.?
543         RC=0
544         [ -f  ${LIBOPENCV_HIGHGUI} ] && ldd ${LIBOPENCV_HIGHGUI} | grep libprotobuf-lite >& /dev/null || RC=$?
545         if [ $RC -eq 0 ]; then
546             echo ""
547             echo ""
548             echo "**********************************************************************"
549             echo "          ERROR - Compatibility Issue Detected with OpenCV"
550             echo ""
551             echo "The OpenCV library" ${LIBOPENCV_HIGHGUI} "links against libprotobuf-lite"
552             echo "This causes an error with ssd-caffe as it links against libprotobuf (non-lite version)"
553             echo "and these libraries cannot be used together and can cause a crash when deallocating memory."
554             echo "Note building OpenCV with QT vs. the default GTK avoids this issue"
555             echo ""
556             echo "To avoid this, uninstall OpenCV libraries built from sources."
557             echo "The script, uninstall-opencv.sh, attempts to do this and is called by make install"
558             echo "If you have run make install or uninstall-opencv.sh and see this, try uninstalling OpenCV installed in /usr/local/ manually"
559             echo "Will exit"
560             exit 1
561         fi
562     fi
563 }
564
565
566 # install_caffe - test if caffe installed, if not download, configure and build
567 function install_caffe()
568 {
569     # look for potential conflict with OpenCV library
570     check_opencv_caffe_conflict
571
572     CAFFE_SRC="https://github.com/BVLC/caffe.git"
573     CAFFE_VER="1.0"
574     CAFFE_DIR=bvlc-caffe
575     CAFFE_BRANCH=master
576     if [ "${CAFFE_FLAVOR}" = "intel" ] && [ "${OS_DISTRO,,}" = "ubuntu" ]; then
577         CAFFE_SRC="https://github.com/intel/caffe.git"
578         CAFFE_VER="1.0.3"
579         CAFFE_DIR=intel-caffe
580     elif [ "${CAFFE_FLAVOR}" = "ssd" ]; then
581         CAFFE_SRC="https://github.com/weiliu89/caffe.git"
582         CAFFE_VER=""
583         CAFFE_DIR=ssd-caffe
584         CAFFE_BRANCH=ssd
585     fi
586
587     # check if caffe is already installed
588     RC=0
589     python3 -c "import caffe" 2> /dev/null || RC=$?
590     if [ $RC -eq 1 ]; then
591         echo "Caffe not found, installing caffe..."
592     else
593         if [ "${CAFFE_FLAVOR}" = "intel" ] && [ "${OS_DISTRO,,}" = "ubuntu" ]; then
594             # find_and_try_adjusting_caffe_symlinks sets FIND_AND_TRY_ADJUSTING_CAFFE_SYMLINKS_FOUND to 0 or 1
595             find_and_try_adjusting_caffe_symlinks
596             RC=$FIND_AND_TRY_ADJUSTING_CAFFE_SYMLINKS_FOUND
597             # Look for intel caffe specific operation to determine the version of caffe currently running
598             if [[ $RC -eq 0 && -d "caffe" ]]; then
599                 cd caffe
600                 ./build/tools/caffe time -model models/bvlc_googlenet/deploy.prototxt -engine "MKLDNN" -iterations 1 &> /dev/null
601                 if [ $? -eq 1 ]; then
602                     echo "Intel caffe requested but not found, installing Intel caffe..."
603                 else
604                     echo "Intel caffe already installed, skipping..."
605                     return
606                 fi
607             fi
608         else
609             # find_and_try_adjusting_caffe_symlinks sets FIND_AND_TRY_ADJUSTING_CAFFE_SYMLINKS_FOUND to 0 or 1
610             find_and_try_adjusting_caffe_symlinks
611             RC=$FIND_AND_TRY_ADJUSTING_CAFFE_SYMLINKS_FOUND
612             if [ $RC -eq 0 ]; then
613                 echo "Caffe already installed, skipping..."
614                 return
615             fi
616         fi
617     fi
618
619     ### Install caffe
620     cd ${INSTALL_DIR}
621     if [[ -h "caffe" && -d `readlink -f caffe` ]]; then
622         echo `readlink -f caffe`
623         cd `readlink -f caffe`
624         # grep returns 1 if no lines are matched, causing the script to
625         # think that installation failed, so append "true"
626         is_caffe_dir=`git remote show origin 2>&1 | grep -c -i $CAFFE_SRC` || true
627         if [ "$is_caffe_dir" -eq 0 ]; then
628             cd ..
629             echo -e "${YELLOW}The repo $INSTALL_DIR/caffe does not match the caffe project specified"
630             echo -e "in this installation. Installing caffe from $CAFFE_SRC.\n${NC}"
631             download_caffe
632             cd caffe
633         fi
634
635         eval git reset --hard HEAD $STDOUT_QUIET
636         eval git checkout $GIT_QUIET $CAFFE_BRANCH $STDOUT_QUIET
637         eval git branch -D fathom_branch &>/dev/null || true
638         eval git pull $STDOUT_QUIET
639     elif [ -d "caffe" ]; then
640         echo -e "${YELLOW}Found an old version of caffe, removing it to install the version"
641         echo -e "specified in this installer from $CAFFE_SRC.\n${NC}"
642         $SUDO_PREFIX rm -r caffe
643         download_caffe
644     else
645         download_caffe
646     fi
647
648     cd ${INSTALL_DIR}
649     # disable trapping for unset variables in case PYTHONPATH not set
650     set +u
651     if [ -z "${PYTHONPATH}" ] ; then
652         export PYTHONPATH="$INSTALL_DIR/caffe/python"
653     else
654         export PYTHONPATH="$INSTALL_DIR/caffe/python":$PYTHONPATH
655     fi
656     set -u
657
658     # At this point, caffe *must* be a symlink
659     cd `readlink -f caffe`
660
661     if [ "$CAFFE_BRANCH" != "master" ]; then
662         eval git checkout $GIT_QUIET $CAFFE_BRANCH $STDOUT_QUIET
663     fi
664
665     if [ "$CAFFE_VER" != "" ]; then
666         eval git checkout $GIT_QUIET $CAFFE_VER -b fathom_branch $STDOUT_QUIET
667     fi
668
669     configure_caffe_options
670
671     # If you get an error compiling caffe, one possible potential issue is if you
672     # previously compiled an older version of opencv from sources and it is installed into /usr/local.
673     # In that case the compiler will pick up the older version from /usr/local, not the version
674     # this installer installed.  Please provide feedback in our support forum if you encountered difficulties. 
675     echo "Compiling Caffe..."
676     mkdir -p build
677     cd build
678     eval cmake .. $STDOUT_QUIET
679     eval make -j $MAKE_NJOBS all $STDOUT_QUIET
680
681     echo "Installing caffe..."
682     eval make install $STDOUT_QUIET
683     # You can use 'make runtest' to test this stage manually :)
684     
685     # Add PYTHONPATH if not already there
686     printf "Removing previous references to previous caffe installation..."
687     # Remove older references
688     sed -i "\#export PYTHONPATH=\""${INSTALL_DIR}"/caffe/python\":\$PYTHONPATH#d" $HOME/.bashrc
689     printf "done\n"
690     echo "Adding caffe to PYTHONPATH"
691     grep "^export PYTHONPATH=\"\${PYTHONPATH}:$INSTALL_DIR\/caffe\/python\"" $HOME/.bashrc || echo "export PYTHONPATH=\"\${PYTHONPATH}:$INSTALL_DIR/caffe/python\"" >> $HOME/.bashrc
692 }
693
694
695 # install_sdk - installs SDK to $SYS_INSTALL_DIR/bin
696 function install_sdk()
697 {
698     # copy toolkit 
699     $SUDO_PREFIX cp -r $SDK_DIR/tk $SYS_INSTALL_DIR/bin/ncsdk
700
701     check_and_remove_file $SYS_INSTALL_DIR/bin/mvNCCompile
702     check_and_remove_file $SYS_INSTALL_DIR/bin/mvNCCheck
703     check_and_remove_file $SYS_INSTALL_DIR/bin/mvNCProfile
704     $SUDO_PREFIX ln -s $SYS_INSTALL_DIR/bin/ncsdk/mvNCCompile.py $SYS_INSTALL_DIR/bin/mvNCCompile
705     $SUDO_PREFIX ln -s $SYS_INSTALL_DIR/bin/ncsdk/mvNCCheck.py $SYS_INSTALL_DIR/bin/mvNCCheck
706     $SUDO_PREFIX ln -s $SYS_INSTALL_DIR/bin/ncsdk/mvNCProfile.py $SYS_INSTALL_DIR/bin/mvNCProfile
707     echo "NCS Toolkit binaries have been installed in $SYS_INSTALL_DIR/bin"
708 }
709
710
711 # install_api - installs firmware & API 
712 function install_api()
713 {
714     # Copy firmware(FW) to destination
715     $SUDO_PREFIX cp $SDK_DIR/fw/MvNCAPI-*.mvcmd $SYS_INSTALL_DIR/lib/mvnc/
716
717     # Copy C API to destination
718     $SUDO_PREFIX cp $SDK_DIR/api/c/mvnc.h $SYS_INSTALL_DIR/include/mvnc2
719     $SUDO_PREFIX cp $SDK_DIR/api/c/libmvnc.so.0 $SYS_INSTALL_DIR/lib/mvnc/
720
721     if [ -f $SDK_DIR/api/c/libmvnc_highclass.so.0 ] ; then
722         $SUDO_PREFIX cp $SDK_DIR/api/c/ncHighClass.h $SYS_INSTALL_DIR/include/mvnc2
723         $SUDO_PREFIX cp $SDK_DIR/api/c/libmvnc_highclass.so.0 $SYS_INSTALL_DIR/lib/mvnc/
724     fi
725     echo "NCS Include files have been installed in $SYS_INSTALL_DIR/include"
726
727     check_and_remove_file $SYS_INSTALL_DIR/include/mvnc.h
728     check_and_remove_file $SYS_INSTALL_DIR/include/ncHighClass.h
729     $SUDO_PREFIX ln -s $SYS_INSTALL_DIR/include/mvnc2/mvnc.h $SYS_INSTALL_DIR/include/mvnc.h
730     
731     check_and_remove_file $SYS_INSTALL_DIR/lib/libmvnc.so.0
732     check_and_remove_file $SYS_INSTALL_DIR/lib/libmvnc.so
733     check_and_remove_file $SYS_INSTALL_DIR/lib/libmvnc_highclass.so 
734     $SUDO_PREFIX ln -s $SYS_INSTALL_DIR/lib/mvnc/libmvnc.so.0 $SYS_INSTALL_DIR/lib/libmvnc.so.0
735     $SUDO_PREFIX ln -s $SYS_INSTALL_DIR/lib/mvnc/libmvnc.so.0 $SYS_INSTALL_DIR/lib/libmvnc.so
736     if [ -f $SYS_INSTALL_DIR/lib/mvnc/libmvnc_highclass.so.0 ] ; then
737         $SUDO_PREFIX ln -s $SYS_INSTALL_DIR/include/mvnc2/ncHighClass.h $SYS_INSTALL_DIR/include/ncHighClass.h
738         $SUDO_PREFIX ln -s $SYS_INSTALL_DIR/lib/mvnc/libmvnc_highclass.so.0 $SYS_INSTALL_DIR/lib/libmvnc_highclass.so
739     fi
740
741     $SUDO_PREFIX ldconfig
742
743     # Copy other collaterals to destination
744     $SUDO_PREFIX cp -r $DIR/version.txt $INSTALL_DIR/
745     $SUDO_PREFIX cp -r $SDK_DIR/LICENSE $INSTALL_DIR/
746
747     # Install python API
748     exec_and_search_errors "$PIP_PREFIX pip3 install $PIP_QUIET --upgrade --force-reinstall $SDK_DIR/api"
749     exec_and_search_errors "$PIP_PREFIX pip2 install $PIP_QUIET --upgrade --force-reinstall $SDK_DIR/api"
750     echo "NCS Python API has been installed in $INSTALL_DIR, and PYTHONPATH environment variable updated"
751 }
752
753
754 # finalize_installer - complete install
755 #    create $INSTALL_INFO_FILE file with info on installed files locations
756 #    Update udev rules, add user to 'users' group and remove tarball
757 function finalize_installer()
758 {
759     echo "NCS Libraries have been installed in $SYS_INSTALL_DIR/lib"
760
761     INSTALL_INFO_FILE=$INSTALL_DIR/$INSTALL_INFO_FILENAME
762     touch $INSTALL_INFO_FILE
763     echo "ncsdk_path=$INSTALL_DIR" > $INSTALL_INFO_FILE
764     echo "ncs_lib_path=$SYS_INSTALL_DIR/lib" >> $INSTALL_INFO_FILE
765     echo "ncs_inc_path=$SYS_INSTALL_DIR/include" >> $INSTALL_INFO_FILE
766     if [ "${INSTALL_TOOLKIT}" = 'yes' ]; then
767         echo "ncs_bin_path=$SYS_INSTALL_DIR/bin" >> $INSTALL_INFO_FILE
768     fi
769
770     # Update udev rules
771     echo "Updating udev rules..."
772     $SUDO_PREFIX cp $SDK_DIR/udev/97-usbboot.rules /etc/udev/rules.d/
773     RC=0 
774     $SUDO_PREFIX udevadm control --reload-rules || RC=$?
775     if [ $RC -ne 0 ] ; then
776         echo "Warning udevadm control --reload-rules reported an return code = ${RC}"
777     fi
778     RC=0 
779     $SUDO_PREFIX udevadm trigger || RC=$?
780     if [ $RC -ne 0 ] ; then
781         echo "Warning udevadm trigger return code = ${RC}"
782     fi
783     
784     # Final touch up
785     CURRENT_USER=$(id -u -n)    
786     echo "Adding user '$CURRENT_USER' to 'users' group"
787     $SUDO_PREFIX usermod -a -G users ${CURRENT_USER}
788
789     # cleanup
790     if [ -f ${INSTALL_DIR}/ncsdk.tar.gz ] ; then
791         $SUDO_PREFIX rm ${INSTALL_DIR}/ncsdk.tar.gz
792     fi
793
794     if [ "${INSTALL_CAFFE}" = "yes" ] ; then
795         RC=0
796         grep "export PYTHONPATH=" $HOME/.bashrc > /dev/null  2>&1 || RC=$?
797         if [ $RC -eq 0 ] ; then
798             UPDATED_PYTHONPATH_MSG=$(grep "export PYTHONPATH=" $HOME/.bashrc || RC=$?)
799         else
800             echo -e "${RED}Error, cannot find PYTHONPATH= in $HOME/.bashrc.  Error on line $LINENO.  Will exit${NC}"
801             exit 1
802         fi
803     fi
804     
805     echo ""
806     echo -e "${GREEN}Installation is complete.${NC}"
807     echo "Please provide feedback in our support forum if you encountered difficulties."
808
809     if [ "${MOVED_NCAPI1}" == 'yes' ]; then
810         echo ""
811         echo -e "${YELLOW}Installed NCSDK version: $NCSDK_VERSION"
812         echo -e "Moved existing NCSDK 1.x files to ${NCSDK1_ARCHIVE_DIR}${NC}"
813         echo " You need to either"
814         echo "  - Manually update projects to use NCAPI v2."
815         echo "  - Manually configure your projects to use the old NCAPI v1 files which were "
816         echo "    moved to ${NCSDK1_ARCHIVE_DIR}" 
817         echo ""        
818     fi
819
820     if [ "${INSTALL_CAFFE}" = "yes" ] ; then
821         echo ""
822         echo "The PYTHONPATH environment variable was added to your .bashrc as described in the Caffe documentation."
823         echo -e "${YELLOW} New bash processes including new terminals will use the updated value of PYTHONPATH."
824         echo ""
825         echo "To use the NCSDK in this shell, set PYTHONPATH now:"
826         echo ${UPDATED_PYTHONPATH_MSG}
827         echo -e ${NC}
828     fi
829
830     if [ "${USE_VIRTUALENV}" == 'yes' ]; then
831         echo ""
832         echo "USE_VIRTUALENV=${USE_VIRTUALENV} - used virtualenv in ${VIRTUALENV_DIR}"
833         echo "You must activate this virtualenv to use the NCSDK with python"
834         echo -e "${YELLOW} Activate this virtualenv by entering this command now:"
835         echo "   source ${VIRTUALENV_DIR}/bin/activate "
836         echo -e ${NC}
837     fi
838 }
839
840
841 # main - this is the main function that runs the install
842 function main()
843 {
844     echo "Movidius Neural Compute Toolkit Installation"
845     ### initialization phase
846     init_installer
847
848     # If previous install was from NCSDK 1.x release, move them
849     detect_and_move_ncsdk1
850     
851     # Find old installs, if found, print old version and remove it
852     # find_previous_install and remove_previous_install are in install-utilities.sh
853     find_previous_install
854     print_previous_ncsdk_install_info
855     remove_previous_install
856     
857     ### installation phase
858     make_installer_dirs
859     download_and_copy_files
860     install_apt_dependencies
861     create_install_logfile
862     # Optionally use python virtualenv, USE_VIRTUALENV set in ncsdk.conf
863     [ "${USE_VIRTUALENV}" == 'yes' ] && setup_virtualenv
864     install_python_dependencies
865
866     ### Install tensorflow and caffe based on settings in ncsdk.conf
867     [ "${INSTALL_TENSORFLOW}" = "yes" ] && install_tensorflow
868     [ "${INSTALL_CAFFE}" = "yes" ] && install_caffe
869
870     # install SDK based on settings in ncsdk.conf and C/C++ and Python API
871     [ "${INSTALL_TOOLKIT}" = "yes" ] && install_sdk
872     install_api
873
874     finalize_installer
875 }
876 main
877 exit 0