blob: 60749ef3d2a6dda92ac535619be6c59ad50fa320 [file] [log] [blame]
Junxiao Shi48ada892021-11-04 09:02:21 -06001# -*- Mode:bash; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2#
Junxiao Shi1e720872022-07-19 10:24:12 -06003# Copyright (C) 2015-2022, The University of Memphis,
Junxiao Shi48ada892021-11-04 09:02:21 -06004# 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 Shi1e720872022-07-19 10:24:12 -060024# needed by Python version detection logic in Mininet install script
Junxiao Shi48ada892021-11-04 09:02:21 -060025export 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)
34declare -A DEP_INFO
35DEP_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
49declare -A DEP_DETECT
50DEP_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
63build_INFOEDIT() {
64 make -j${NJOBS}
65 $SUDO make install
66}
67build_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}
77build_MNWIFI() {
Junxiao Shi1e720872022-07-19 10:24:12 -060078 # 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 Shi48ada892021-11-04 09:02:21 -060082 # issue: util/install.sh attempts to patch hostap every time, causing "Assume -R?" prompt
83 # during reinstalls
Junxiao Shi1e720872022-07-19 10:24:12 -060084 # workaround: revert hostap submodule to clean state
Junxiao Shi48ada892021-11-04 09:02:21 -060085 $SUDO git -C hostap clean -fdx || true
86 $SUDO git -C hostap checkout -- . || true
87
Junxiao Shi1e720872022-07-19 10:24:12 -060088 # 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;
94EOT
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 Shi48ada892021-11-04 09:02:21 -0600100
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 Shi1e720872022-07-19 10:24:12 -0600111
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 Shi48ada892021-11-04 09:02:21 -0600119}
120
121# Waf configure options
122declare -A DEP_WAFOPTS
123DEP_WAFOPTS=(
124 ["NFD"]="--without-websocket"
125 ["PSYNC"]="--with-examples"
126)
127
128# return whether dep is installed
129dep_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
141declare -A NEED_DL
142
143# display prompt on what to do with dep, populate NEED_DL
144dep_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
173dep_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
209dep_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
231if [[ $PPA_AVAIL -ne 1 ]] || [[ $NO_PPA -eq 1 ]]; then
232 PREFER_FROM=source
233fi
234
235# dep install order, excluding ndn-cxx
236DEPLIST=(NFD PSYNC NLSR TOOLS TRAFFIC INFOEDIT MININET)
237if [[ $NO_WIFI -ne 1 ]]; then
238 DEPLIST+=(MNWIFI)
239fi
240
241echo "Will download to ${CODEROOT}"
242echo 'Will install compiler and build tools'
243dep_prompt CXX
244if [[ $CXX_DUMMY_KEYCHAIN -eq 1 ]]; then
245 echo 'Will patch ndn-cxx to use dummy KeyChain'
246fi
247for DEP in "${DEPLIST[@]}"; do
248 dep_prompt $DEP
249done
250if [[ $DL_ONLY -ne 1 ]]; then
251 echo "Will compile with ${NJOBS} parallel jobs"
252 echo "Will install Mini-NDN package"
253fi
254
255if [[ $CONFIRM -ne 1 ]]; then
256 read -p 'Press ENTER to continue or CTRL+C to abort '
257fi
258
259install_pkgs
260
261if [[ -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
266In your system, '${PYTHON}' is ${PYTHON_VERSION} and '$SUDO ${PYTHON}' is ${SUDO_PYTHON_VERSION}
267You must manually resolve the conflict, e.g. delete excess Python installation or change $PATH
268To bypass this check, set the environment variable SKIPPYTHONCHECK=1
269EOT
270 exit 1
271 fi
272fi
273
274if ! mkdir -p "${CODEROOT}" 2>/dev/null; then
275 $SUDO mkdir -p "${CODEROOT}"
276 $SUDO chown $(id -u) "${CODEROOT}"
277fi
278dep_checkout CXX
279if [[ $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
284fi
285for DEP in "${DEPLIST[@]}"; do
286 dep_checkout $DEP
287done
288
289if [[ $DL_ONLY -eq 1 ]]; then
290 cat <<EOT
291Source code has been downloaded to ${CODEROOT}
292You may make changes or checkout different versions
293Run this script again without --dl-only to install from local checkout
294EOT
295 exit 0
296fi
297
298prepare_ld
299for DEP in CXX "${DEPLIST[@]}"; do
300 dep_install $DEP
301done
302$SUDO ldconfig
303
304DESTDIR=/usr/local/etc/mini-ndn
305$SUDO install -d -m0755 "$DESTDIR"
306find topologies/ -name '*.conf' | xargs $SUDO install -m0644 -t "$DESTDIR/"
307$SUDO $PYTHON setup.py develop
308
309echo 'MiniNDN installation completed successfully'