Junxiao Shi | 48ada89 | 2021-11-04 09:02:21 -0600 | [diff] [blame] | 1 | # -*- Mode:bash; c-file-style:"gnu"; indent-tabs-mode:nil -*- */ |
| 2 | # |
Junxiao Shi | 1e72087 | 2022-07-19 10:24:12 -0600 | [diff] [blame] | 3 | # Copyright (C) 2015-2022, The University of Memphis, |
Junxiao Shi | 48ada89 | 2021-11-04 09:02:21 -0600 | [diff] [blame] | 4 | # Arizona Board of Regents, |
| 5 | # Regents of the University of California. |
| 6 | # |
| 7 | # This file is part of Mini-NDN. |
| 8 | # See AUTHORS.md for a complete list of Mini-NDN authors and contributors. |
| 9 | # |
| 10 | # Mini-NDN is free software: you can redistribute it and/or modify |
| 11 | # it under the terms of the GNU General Public License as published by |
| 12 | # the Free Software Foundation, either version 3 of the License, or |
| 13 | # (at your option) any later version. |
| 14 | # |
| 15 | # Mini-NDN is distributed in the hope that it will be useful, |
| 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | # GNU General Public License for more details. |
| 19 | # |
| 20 | # You should have received a copy of the GNU General Public License |
| 21 | # along with Mini-NDN, e.g., in COPYING.md file. |
| 22 | # If not, see <http://www.gnu.org/licenses/>. |
| 23 | |
Junxiao Shi | 1e72087 | 2022-07-19 10:24:12 -0600 | [diff] [blame] | 24 | # needed by Python version detection logic in Mininet install script |
Junxiao Shi | 48ada89 | 2021-11-04 09:02:21 -0600 | [diff] [blame] | 25 | export PYTHON=python3 |
| 26 | |
| 27 | # DEP_INFO key should match *_VERSION variable name. |
| 28 | # DEP_INFO entry should have these comma separated fields: |
| 29 | # [0] local directory name |
| 30 | # [1] dep name |
| 31 | # [2] PPA package name |
| 32 | # [3] GitHub repository (HTTPS) |
| 33 | # [4] Gerrit repository (repo name only) |
| 34 | declare -A DEP_INFO |
| 35 | DEP_INFO=( |
| 36 | ["CXX"]="ndn-cxx,ndn-cxx,libndn-cxx-dev,https://github.com/named-data/ndn-cxx.git,ndn-cxx" |
| 37 | ["NFD"]="NFD,NFD,nfd,https://github.com/named-data/NFD.git,NFD" |
| 38 | ["PSYNC"]="PSync,PSync,libpsync-dev,https://github.com/named-data/PSync.git,PSync" |
| 39 | ["NLSR"]="NLSR,NLSR,nlsr,https://github.com/named-data/NLSR.git,NLSR" |
| 40 | ["TOOLS"]="ndn-tools,NDN Essential Tools,ndn-tools,https://github.com/named-data/ndn-tools.git,ndn-tools" |
| 41 | ["TRAFFIC"]="ndn-traffic-generator,NDN Traffic Generator,ndn-traffic-generator,https://github.com/named-data/ndn-traffic-generator.git,ndn-traffic-generator" |
| 42 | ["INFOEDIT"]="infoedit,infoedit,,https://github.com/NDN-Routing/infoedit.git," |
| 43 | ["MININET"]="mininet,Mininet,,https://github.com/mininet/mininet.git," |
| 44 | ["MNWIFI"]="mininet-wifi,Mininet-WiFi,,https://github.com/intrig-unicamp/mininet-wifi.git," |
| 45 | ) |
| 46 | |
| 47 | # command to detect dependency existence |
| 48 | # if not specified, dependency is assumed to not exist |
| 49 | declare -A DEP_DETECT |
| 50 | DEP_DETECT=( |
| 51 | ["CXX"]="pkg-config libndn-cxx" |
| 52 | ["NFD"]="command -v nfd" |
| 53 | ["PSYNC"]="pkg-config PSync" |
| 54 | ["NLSR"]="command -v nlsr" |
| 55 | ["TOOLS"]="command -v ndnping && command -v ndncatchunks" |
| 56 | ["TRAFFIC"]="command -v ndn-traffic-client" |
| 57 | ["INFOEDIT"]="command -v infoedit" |
| 58 | ["MININET"]="command -v mn && command -v ofdatapath && $PYTHON -m pip show mininet" |
| 59 | ["MNWIFI"]="$PYTHON -m pip show mininet-wifi" |
| 60 | ) |
| 61 | |
| 62 | # non-Waf build & install command |
| 63 | build_INFOEDIT() { |
| 64 | make -j${NJOBS} |
| 65 | $SUDO make install |
| 66 | } |
| 67 | build_MININET() { |
| 68 | ./util/install.sh -s ${CODEROOT} -nv |
| 69 | if ! command -v ofdatapath >/dev/null; then |
| 70 | rm -rf ${CODEROOT}/openflow |
| 71 | ./util/install.sh -s ${CODEROOT} -f |
| 72 | fi |
| 73 | |
| 74 | $SUDO $PYTHON setup.py develop |
| 75 | $SUDO cp /usr/local/bin/mn /usr/local/bin/mn.mininet |
| 76 | } |
| 77 | build_MNWIFI() { |
Junxiao Shi | 1e72087 | 2022-07-19 10:24:12 -0600 | [diff] [blame] | 78 | # issue: git repository is not owned by root, causing "unsafe repository" error |
| 79 | # workaround: chown the git repository to root |
| 80 | $SUDO chown -R 0:0 . |
| 81 | |
Junxiao Shi | 48ada89 | 2021-11-04 09:02:21 -0600 | [diff] [blame] | 82 | # issue: util/install.sh attempts to patch hostap every time, causing "Assume -R?" prompt |
| 83 | # during reinstalls |
Junxiao Shi | 1e72087 | 2022-07-19 10:24:12 -0600 | [diff] [blame] | 84 | # workaround: revert hostap submodule to clean state |
Junxiao Shi | 48ada89 | 2021-11-04 09:02:21 -0600 | [diff] [blame] | 85 | $SUDO git -C hostap clean -fdx || true |
| 86 | $SUDO git -C hostap checkout -- . || true |
| 87 | |
Junxiao Shi | 1e72087 | 2022-07-19 10:24:12 -0600 | [diff] [blame] | 88 | # issue: util/install.sh is not setting noninteractive mode for apt-get |
| 89 | # workaround: temporarily disable needrestart |
| 90 | if [[ -d /etc/needrestart/conf.d ]]; then |
| 91 | $SUDO tee /etc/needrestart/conf.d/99-disabled-by-minindn.conf > /dev/null <<'EOT' |
| 92 | $nrconf{restart} = 'l'; |
| 93 | $nrconf{kernelhints} = 0; |
| 94 | EOT |
| 95 | fi |
| 96 | |
| 97 | # issue: util/install.sh is not using 'sudo' where needed such as 'make install' |
| 98 | # workaround: run whole script in 'sudo' |
| 99 | $SUDO env PYTHON=$PYTHON ./util/install.sh -Wl |
Junxiao Shi | 48ada89 | 2021-11-04 09:02:21 -0600 | [diff] [blame] | 100 | |
| 101 | # issue: setup.py reports "Cannot load backend 'TkAgg' which requires the 'tk' interactive |
| 102 | # framework, as 'headless' is currently running" when running over SSH |
| 103 | # workaround: pretend to have X11 display |
| 104 | $SUDO env DISPLAY=:0 $PYTHON setup.py develop |
| 105 | $SUDO cp /usr/local/bin/mn /usr/local/bin/mn.wifi |
| 106 | |
| 107 | # make 'mn' command refer to Mininet's version, which does not require X11 |
| 108 | if [[ -x /usr/local/bin/mn.mininet ]]; then |
| 109 | $SUDO cp /usr/local/bin/mn.mininet /usr/local/bin/mn |
| 110 | fi |
Junxiao Shi | 1e72087 | 2022-07-19 10:24:12 -0600 | [diff] [blame] | 111 | |
| 112 | # chown the git repository to current user, so that user can modify code without root |
| 113 | if [[ $(id -u) -ne 0 ]]; then |
| 114 | $SUDO chown -R $(id -u):$(id -g) . |
| 115 | fi |
| 116 | |
| 117 | # re-enable needrestart |
| 118 | $SUDO rm -f /etc/needrestart/conf.d/99-disabled-by-minindn.conf |
Junxiao Shi | 48ada89 | 2021-11-04 09:02:21 -0600 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | # Waf configure options |
| 122 | declare -A DEP_WAFOPTS |
| 123 | DEP_WAFOPTS=( |
| 124 | ["NFD"]="--without-websocket" |
| 125 | ["PSYNC"]="--with-examples" |
| 126 | ) |
| 127 | |
| 128 | # return whether dep is installed |
| 129 | dep_exists() { |
| 130 | if [[ $IGNORE_EXISTING -eq 1 ]]; then |
| 131 | return 2 |
| 132 | fi |
| 133 | local DETECT="${DEP_DETECT[$1]}" |
| 134 | if [[ -n $DETECT ]] && bash -c "$DETECT" &>/dev/null; then |
| 135 | return 0 |
| 136 | fi |
| 137 | return 1 |
| 138 | } |
| 139 | |
| 140 | # set to 1 if dep needs downloading |
| 141 | declare -A NEED_DL |
| 142 | |
| 143 | # display prompt on what to do with dep, populate NEED_DL |
| 144 | dep_prompt() { |
| 145 | local INFO=() |
| 146 | IFS=',' read -a INFO <<< "${DEP_INFO[$1]}" |
| 147 | local VERSION_VAR="$1_VERSION" |
| 148 | local VERSION="${!VERSION_VAR}" |
| 149 | if [[ -z $VERSION ]]; then |
| 150 | VERSION='(default branch)' |
| 151 | fi |
| 152 | local DLDIR="${CODEROOT}/${INFO[0]}" |
| 153 | if dep_exists $1; then |
| 154 | echo "Will use existing ${INFO[1]}" |
| 155 | elif [[ $PREFER_FROM == ppa ]] && [[ -n ${INFO[2]} ]]; then |
| 156 | echo "Will install ${INFO[1]} from named-data PPA" |
| 157 | PPA_PKGS+=("${INFO[2]}") |
| 158 | elif [[ -d "$DLDIR" ]]; then |
| 159 | if [[ $DL_ONLY -ne 1 ]]; then |
| 160 | echo "Will install ${INFO[1]} from local checkout ${DLDIR}" |
| 161 | fi |
| 162 | else |
| 163 | NEED_DL[$1]=1 |
| 164 | if [[ $DL_ONLY -eq 1 ]]; then |
| 165 | echo "Will checkout ${INFO[1]} ${VERSION} to ${DLDIR}" |
| 166 | else |
| 167 | echo "Will download and install ${INFO[1]} ${VERSION}" |
| 168 | fi |
| 169 | fi |
| 170 | } |
| 171 | |
| 172 | # download dep source code |
| 173 | dep_checkout() { |
| 174 | if [[ ${NEED_DL[$1]} -ne 1 ]]; then |
| 175 | return |
| 176 | fi |
| 177 | local INFO=() |
| 178 | IFS=',' read -a INFO <<< "${DEP_INFO[$1]}" |
| 179 | local VERSION_VAR="$1_VERSION" |
| 180 | local VERSION="${!VERSION_VAR}" |
| 181 | local DLDIR="${CODEROOT}/${INFO[0]}" |
| 182 | |
| 183 | if [[ -n ${INFO[4]} ]] && [[ "$VERSION" =~ ^[0-9]+,[0-9]+$ ]]; then |
| 184 | local REPO="https://gerrit.named-data.net/${INFO[4]}" |
| 185 | local GERRIT_CHANGE=${VERSION%,*} |
| 186 | local GERRIT_PATCHSET=${VERSION#*,} |
| 187 | echo "Downloading ${INFO[2]} from Gerrit (patchset ${GERRIT_CHANGE},${GERRIT_PATCHSET})" |
| 188 | git clone "$REPO" "$DLDIR" |
| 189 | git -C "$DLDIR" fetch origin "refs/changes/${GERRIT_CHANGE:(-2)}/${GERRIT_CHANGE}/${GERRIT_PATCHSET}" |
| 190 | git -C "$DLDIR" -c advice.detachedHead=false checkout FETCH_HEAD |
| 191 | elif [[ -z $VERSION ]]; then |
| 192 | echo "Downloading ${INFO[1]} from GitHub (default branch)" |
| 193 | git clone "${INFO[3]}" "$DLDIR" |
| 194 | elif [[ "$VERSION" =~ @ ]]; then |
| 195 | local REPO=${VERSION%@*} |
| 196 | local BRANCH=${VERSION#*@} |
| 197 | echo "Downloading ${INFO[1]} from ${REPO} (branch ${BRANCH})" |
| 198 | git clone "$REPO" "$DLDIR" |
| 199 | git -C "$DLDIR" -c advice.detachedHead=false checkout "$BRANCH" |
| 200 | else |
| 201 | echo "Downloading ${INFO[1]} from GitHub (branch ${VERSION})" |
| 202 | git clone "${INFO[3]}" "$DLDIR" |
| 203 | git -C "$DLDIR" -c advice.detachedHead=false checkout "$VERSION" |
| 204 | fi |
| 205 | git submodule update --init --recursive --progress |
| 206 | } |
| 207 | |
| 208 | # install dep from source code |
| 209 | dep_install() { |
| 210 | local INFO=() |
| 211 | IFS=',' read -a INFO <<< "${DEP_INFO[$1]}" |
| 212 | local DLDIR="${CODEROOT}/${INFO[0]}" |
| 213 | if dep_exists $1 || ! [[ -d "$DLDIR" ]]; then |
| 214 | return |
| 215 | fi |
| 216 | pushd "$DLDIR" |
| 217 | |
| 218 | local FN="build_$1" |
| 219 | if declare -F $FN >/dev/null; then |
| 220 | echo "Installing ${INFO[1]} with custom command" |
| 221 | $FN |
| 222 | elif [[ -x waf ]]; then |
| 223 | echo "Installing ${INFO[1]} with Waf" |
| 224 | $PYTHON ./waf configure ${DEP_WAFOPTS[$1]} |
| 225 | $PYTHON ./waf -j${NJOBS} |
| 226 | $SUDO $PYTHON ./waf install |
| 227 | fi |
| 228 | popd |
| 229 | } |
| 230 | |
| 231 | if [[ $PPA_AVAIL -ne 1 ]] || [[ $NO_PPA -eq 1 ]]; then |
| 232 | PREFER_FROM=source |
| 233 | fi |
| 234 | |
| 235 | # dep install order, excluding ndn-cxx |
| 236 | DEPLIST=(NFD PSYNC NLSR TOOLS TRAFFIC INFOEDIT MININET) |
| 237 | if [[ $NO_WIFI -ne 1 ]]; then |
| 238 | DEPLIST+=(MNWIFI) |
| 239 | fi |
| 240 | |
| 241 | echo "Will download to ${CODEROOT}" |
| 242 | echo 'Will install compiler and build tools' |
| 243 | dep_prompt CXX |
| 244 | if [[ $CXX_DUMMY_KEYCHAIN -eq 1 ]]; then |
| 245 | echo 'Will patch ndn-cxx to use dummy KeyChain' |
| 246 | fi |
| 247 | for DEP in "${DEPLIST[@]}"; do |
| 248 | dep_prompt $DEP |
| 249 | done |
| 250 | if [[ $DL_ONLY -ne 1 ]]; then |
| 251 | echo "Will compile with ${NJOBS} parallel jobs" |
| 252 | echo "Will install Mini-NDN package" |
| 253 | fi |
| 254 | |
| 255 | if [[ $CONFIRM -ne 1 ]]; then |
| 256 | read -p 'Press ENTER to continue or CTRL+C to abort ' |
| 257 | fi |
| 258 | |
| 259 | install_pkgs |
| 260 | |
| 261 | if [[ -z $SKIPPYTHONCHECK ]]; then |
| 262 | PYTHON_VERSION=$($PYTHON --version) |
| 263 | SUDO_PYTHON_VERSION=$($SUDO $PYTHON --version) |
| 264 | if [[ "$PYTHON_VERSION" != "$SUDO_PYTHON_VERSION" ]]; then |
| 265 | cat <<EOT |
| 266 | In your system, '${PYTHON}' is ${PYTHON_VERSION} and '$SUDO ${PYTHON}' is ${SUDO_PYTHON_VERSION} |
| 267 | You must manually resolve the conflict, e.g. delete excess Python installation or change $PATH |
| 268 | To bypass this check, set the environment variable SKIPPYTHONCHECK=1 |
| 269 | EOT |
| 270 | exit 1 |
| 271 | fi |
| 272 | fi |
| 273 | |
| 274 | if ! mkdir -p "${CODEROOT}" 2>/dev/null; then |
| 275 | $SUDO mkdir -p "${CODEROOT}" |
| 276 | $SUDO chown $(id -u) "${CODEROOT}" |
| 277 | fi |
| 278 | dep_checkout CXX |
| 279 | if [[ $CXX_DUMMY_KEYCHAIN -eq 1 ]]; then |
| 280 | echo 'Patching ndn-cxx to use dummy KeyChain' |
| 281 | if ! git -C "${CODEROOT}/ndn-cxx" apply --index < "${PKGDEPDIR}/../patches/ndn-cxx-dummy-keychain.patch"; then |
| 282 | echo 'Cannot patch ndn-cxx to use dummy KeyChain (possibly already patched)' |
| 283 | fi |
| 284 | fi |
| 285 | for DEP in "${DEPLIST[@]}"; do |
| 286 | dep_checkout $DEP |
| 287 | done |
| 288 | |
| 289 | if [[ $DL_ONLY -eq 1 ]]; then |
| 290 | cat <<EOT |
| 291 | Source code has been downloaded to ${CODEROOT} |
| 292 | You may make changes or checkout different versions |
| 293 | Run this script again without --dl-only to install from local checkout |
| 294 | EOT |
| 295 | exit 0 |
| 296 | fi |
| 297 | |
| 298 | prepare_ld |
| 299 | for DEP in CXX "${DEPLIST[@]}"; do |
| 300 | dep_install $DEP |
| 301 | done |
| 302 | $SUDO ldconfig |
| 303 | |
| 304 | DESTDIR=/usr/local/etc/mini-ndn |
| 305 | $SUDO install -d -m0755 "$DESTDIR" |
| 306 | find topologies/ -name '*.conf' | xargs $SUDO install -m0644 -t "$DESTDIR/" |
| 307 | $SUDO $PYTHON setup.py develop |
| 308 | |
| 309 | echo 'MiniNDN installation completed successfully' |