setup_pkgmgr(): Make the 'build' use flag passed in
[catalyst.git] / targets / support / chroot-functions.sh
1 #!/bin/bash
2
3 # Set the profile
4 eselect profile set ${clst_target_profile}
5
6 # Trap these signals and kill ourselves if recieved
7 # Force ourselves to die if any of these signals are recieved
8 # most likely our controlling terminal is gone
9 trap "echo SIGTERM signal recieved killing $0 with pid $$;kill -9 $$" SIGTERM
10 trap "echo SIGHUP signal recieved killing $0 with pid $$;kill -9 $$" SIGHUP
11 trap "echo SIGKILL signal recieved killing $0 with pid $$;kill -9 $$" SIGKILL
12
13 #SIGINT interrupt character (usually Ctrl-C)
14 #       * example: high-level sequence of events
15 #       * my process (call it "P") is running
16 #       * user types ctrl-c
17 #       * kernel recognizes this and generates SIGINT signal
18 trap "echo SIGINT signal recieved killing $0 with pid $$;kill -9 $$" SIGINT
19
20 check_genkernel_version(){
21         if [ -x /usr/bin/genkernel ]
22         then
23                 genkernel_version=$(genkernel --version)
24                 genkernel_version_major=${genkernel_version%%.*}
25                 genkernel_version_minor_sub=${genkernel_version#${genkernel_version_major}.}
26                 genkernel_version_minor=${genkernel_version_minor_sub%%.*}
27                 genkernel_version_sub=${genkernel_version##*.}
28                 if [ -n "${genkernel_version}" -a "${genkernel_version_major}" -eq '3' -a "${genkernel_version_minor}" -ge '3' ]
29                 then
30                         echo "Genkernel version ${genkernel_version} found ... continuing"
31                 else
32                         echo "ERROR: Your genkernel version is too low in your seed stage.  genkernel version 3.3.0"
33                         echo "or greater is required."
34                         exit 1
35                 fi
36         else
37                 exit 1
38         fi
39 }
40
41 get_libdir() {
42         ABI=$(portageq envvar ABI)
43         DEFAULT_ABI=$(portageq envvar DEFAULT_ABI)
44         LIBDIR_default=$(portageq envvar LIBDIR_default)
45
46         local abi
47         if [ $# -gt 0 ]
48         then
49                 abi=${1}
50         elif [ -n "${ABI}" ]
51         then
52                 abi=${ABI}
53         elif [ -n "${DEFAULT_ABI}" ]
54         then
55                 abi=${DEFAULT_ABI}
56         else
57                 abi="default"
58         fi
59
60         local var="LIBDIR_${abi}"
61         var=$(portageq envvar ${var})
62         echo ${var}
63 }
64
65 setup_myfeatures(){
66         setup_myemergeopts
67         export FEATURES="-news clean-logs"
68         if [ -n "${clst_CCACHE}" ]
69         then
70                 export clst_myfeatures="${clst_myfeatures} ccache"
71                 clst_root_path=/ run_merge --oneshot --noreplace dev-util/ccache || exit 1
72         fi
73
74         if [ -n "${clst_DISTCC}" ]
75         then
76                 export clst_myfeatures="${clst_myfeatures} distcc"
77                 export DISTCC_HOSTS="${clst_distcc_hosts}"
78                 [ -e /etc/portage/make.conf ] && \
79                         echo 'USE="${USE} -avahi -gtk -gnome"' >> /etc/portage/make.conf
80                 # We install distcc to / on stage1, then use --noreplace, so we need to
81                 # have some way to check if we need to reinstall distcc without being
82                 # able to rely on USE, so we check for the distcc user and force a
83                 # reinstall if it isn't found.
84                 if [ "$(getent passwd distcc | cut -d: -f1)" != "distcc" ]
85                 then
86                         clst_root_path=/ run_merge --oneshot sys-devel/distcc || exit 1
87                 else
88                         clst_root_path=/ run_merge --oneshot --noreplace sys-devel/distcc || exit 1
89                 fi
90                 sed -i '/USE="${USE} -avahi -gtk -gnome"/d' /etc/portage/make.conf
91                 mkdir -p /etc/distcc
92                 echo "${clst_distcc_hosts}" > /etc/distcc/hosts
93
94                 # This sets up automatic cross-distcc-fu according to
95                 # http://www.gentoo.org/doc/en/cross-compiling-distcc.xml
96                 CHOST=$(portageq envvar CHOST)
97                 LIBDIR=$(get_libdir)
98                 cd /usr/${LIBDIR}/distcc/bin
99                 rm cc gcc g++ c++ 2>/dev/null
100                 echo -e '#!/bin/bash\nexec /usr/'${LIBDIR}'/distcc/bin/'${CHOST}'-g${0:$[-2]} "$@"' > ${CHOST}-wrapper
101                 chmod a+x /usr/${LIBDIR}/distcc/bin/${CHOST}-wrapper
102                 for i in cc gcc g++ c++; do ln -s ${CHOST}-wrapper ${i}; done
103         fi
104
105         if [ -n "${clst_ICECREAM}" ]
106         then
107                 clst_root_path=/ run_merge --oneshot --noreplace sys-devel/icecream || exit 1
108
109                 # This sets up automatic cross-icecc-fu according to
110                 # http://gentoo-wiki.com/HOWTO_Setup_An_ICECREAM_Compile_Cluster#Icecream_and_cross-compiling
111                 CHOST=$(portageq envvar CHOST)
112                 LIBDIR=$(get_libdir)
113                 cd /usr/${LIBDIR}/icecc/bin
114                 rm cc gcc g++ c++ 2>/dev/null
115                 echo -e '#!/bin/bash\nexec /usr/'${LIBDIR}'/icecc/bin/'${CHOST}'-g${0:$[-2]} "$@"' > ${CHOST}-wrapper
116                 chmod a+x ${CHOST}-wrapper
117                 for i in cc gcc g++ c++; do ln -s ${CHOST}-wrapper ${i}; done
118                 export PATH="/usr/lib/icecc/bin:${PATH}"
119                 export PREROOTPATH="/usr/lib/icecc/bin"
120         fi
121         export FEATURES="${clst_myfeatures} -news"
122 }
123
124 setup_myemergeopts(){
125         if [ -n "${clst_VERBOSE}" ]
126         then
127                 clst_myemergeopts="--verbose"
128         else
129                 clst_myemergeopts="--quiet"
130                 bootstrap_opts="${bootstrap_opts} -q"
131         fi
132         if [ -n "${clst_FETCH}" ]
133         then
134                 export bootstrap_opts="${bootstrap_opts} -f"
135                 export clst_myemergeopts="${clst_myemergeopts} -f"
136         # if we have PKGCACHE, and either update_seed is empty or 'no', make and use binpkgs
137         elif [ -n "${clst_PKGCACHE}" ] && [ -z "${clst_update_seed}" -o "${clst_update_seed}" = "no" ]
138         then
139                 export clst_myemergeopts="${clst_myemergeopts} --usepkg --buildpkg --newuse"
140                 export bootstrap_opts="${bootstrap_opts} -r"
141         fi
142 }
143
144 setup_binutils(){
145         if [ -x /usr/bin/binutils-config ]
146         then
147                 my_binutils=$( cd /etc/env.d/binutils; ls ${clst_CHOST}-* | head -n 1 )
148                 if [ -z "${my_binutils}" ]
149                 then
150                         my_binutils=1
151                 fi
152                 binutils-config ${my_binutils}; update_env_settings
153         fi
154 }
155
156 setup_gcc(){
157         if [ -x /usr/bin/gcc-config ]
158         then
159                 my_gcc=$( cd /etc/env.d/gcc; ls ${clst_CHOST}-* | head -n 1 )
160                 if [ -z "${my_gcc}" ]
161                 then
162                         my_gcc=1
163                 fi
164                 gcc-config ${my_gcc}; update_env_settings
165         fi
166 }
167
168 setup_pkgmgr(){
169         # We need to merge our package manager with USE="build" set in case it is
170         # portage to avoid frying our /etc/portage/make.conf file.  Otherwise, we could
171         # just let emerge @system could merge it.
172         # Use --update or portage might just waste time/cycles and reinstall the same version.
173         if [ -n "$1" ];then
174                 echo "Adding USE='${USE} $1' to make.conf for portage build"
175                 [ -e /etc/portage/make.conf ] && echo 'USE="${USE} $1"' >> /etc/portage/make.conf
176                 run_merge --oneshot --update sys-apps/portage
177                 sed -i '/USE="${USE} $1"/d' /etc/portage/make.conf
178         else
179                 echo "Updating portage with USE='${USE}'"
180                 run_merge --oneshot --update sys-apps/portage
181         fi
182 }
183
184 cleanup_distcc() {
185         LIBDIR=$(get_libdir)
186         rm -rf /etc/distcc/hosts
187         for i in cc gcc c++ g++; do
188                 rm -f /usr/${LIBDIR}/distcc/bin/${i}
189                 ln -s /usr/bin/distcc /usr/${LIBDIR}/distcc/bin/${i}
190         done
191         rm -f /usr/${LIBDIR}/distcc/bin/*-wrapper
192 }
193
194 cleanup_icecream() {
195         LIBDIR=$(get_libdir)
196         for i in cc gcc c++ g++; do
197                 rm -f /usr/${LIBDIR}/icecc/bin/${i}
198                 ln -s /usr/bin/icecc /usr/${LIBDIR}/icecc/bin/${i}
199         done
200         rm -f /usr/${LIBDIR}/icecc/bin/*-wrapper
201 }
202
203 cleanup_stages() {
204         make_destpath
205         if [ -n "${clst_DISTCC}" ]
206         then
207                 cleanup_distcc
208         fi
209         if [ -n "${clst_ICECREAM}" ]
210         then
211                 cleanup_icecream
212         fi
213         case ${clst_target} in
214                 stage3|system)
215                         run_merge --depclean --with-bdeps=y
216                         ;;
217                 *)
218                         echo "Skipping depclean operation for ${clst_target}"
219                         ;;
220         esac
221         case ${clst_target} in
222                 stage1|stage2|stage3|system)
223                         rm -f /var/lib/portage/world
224                         touch /var/lib/portage/world
225                         ;;
226                 *)
227                         echo "Skipping removal of world file for ${clst_target}"
228                         ;;
229         esac
230
231         rm -f /var/log/emerge.log /var/log/portage/elog/*
232 }
233
234 update_env_settings(){
235         [ -x /usr/sbin/env-update ] && /usr/sbin/env-update
236         source /etc/profile
237         [ -f /tmp/envscript ] && source /tmp/envscript
238 }
239
240 die() {
241         echo "$1"
242         exit 1
243 }
244
245 make_destpath() {
246         # ROOT is / by default, so remove any ROOT= settings from make.conf
247         sed -i '/ROOT=/d' /etc/portage/make.conf
248         export ROOT=/
249         if [ "${1}" != "/" -a -n "${1}" ]
250         then
251                 echo "ROOT=\"${1}\"" >> /etc/portage/make.conf
252                 export ROOT=${1}
253         fi
254         if [ ! -d ${ROOT} ]
255         then
256                 install -d ${ROOT}
257         fi
258 }
259
260 run_merge() {
261         # Sets up the ROOT= parameter
262         # with no options ROOT=/
263         make_destpath ${clst_root_path}
264
265         export EMERGE_WARNING_DELAY=0
266         export CLEAN_DELAY=0
267         export EBEEP_IGNORE=0
268         export EPAUSE_IGNORE=0
269         export CONFIG_PROTECT="-*"
270
271         if [ -n "${clst_VERBOSE}" ]
272         then
273                 echo "ROOT=${ROOT} emerge ${clst_myemergeopts} -pt $@" || exit 1
274                 emerge ${clst_myemergeopts} -pt $@ || exit 3
275                 echo "Press any key within 15 seconds to pause the build..."
276                 read -s -t 15 -n 1
277                 if [ $? -eq 0 ]
278                 then
279                         echo "Press any key to continue..."
280                         read -s -n 1
281                 fi
282         fi
283
284         echo "emerge ${clst_myemergeopts} $@" || exit 1
285
286         emerge ${clst_myemergeopts} $@ || exit 1
287 }
288
289 show_debug() {
290         if [ "${clst_DEBUG}" = "1" ]
291         then
292                 unset PACKAGES
293                 echo "DEBUG:"
294                 echo "Profile/target info:"
295                 echo "Profile inheritance:"
296                 python -c 'import portage; print(portage.settings.profiles)'
297                 echo
298                 # TODO: make this work on non-portage
299                 emerge --info
300                 # TODO: grab our entire env
301                 # <zmedico> to get see the ebuild env you can do something like:
302                 # `set > /tmp/env_dump.${EBUILD_PHASE}` inside /etc/portage/bashrc
303                 # XXX: Also, portageq does *not* source profile.bashrc at any time.
304                 echo
305                 echo "BOOTSTRAP_USE:            $(portageq envvar BOOTSTRAP_USE)"
306                 echo
307                 echo "USE (profile):         $(portageq envvar USE)"
308                 echo "FEATURES (profile):    $(portageq envvar FEATURES)"
309                 echo
310                 echo "ARCH:                  $(portageq envvar ARCH)"
311                 echo "CHOST:                 $(portageq envvar CHOST)"
312                 echo "CFLAGS:                $(portageq envvar CFLAGS)"
313                 echo
314                 echo "These should be blank on non-multilib profiles."
315                 echo "ABI:                   $(portageq envvar ABI)"
316                 echo "DEFAULT_ABI:           $(portageq envvar DEFAULT_ABI)"
317                 echo "KERNEL_ABI:            $(portageq envvar KERNEL_ABI)"
318                 echo "LIBDIR:                $(get_libdir)"
319                 echo "MULTILIB_ABIS:         $(portageq envvar MULTILIB_ABIS)"
320                 echo "PROFILE_ARCH:          $(portageq envvar PROFILE_ARCH)"
321                 echo
322         fi
323 }
324
325 run_default_funcs() {
326         if [ "${RUN_DEFAULT_FUNCS}" != "no" ]
327         then
328                 update_env_settings
329                 setup_myfeatures
330                 show_debug
331         fi
332 }
333
334 # Functions
335 # Copy libs of a executable in the chroot
336 function copy_libs() {
337         # Check if it's a dynamix exec
338         ldd ${1} > /dev/null 2>&1 || return
339
340         for lib in `ldd ${1} | awk '{ print $3 }'`
341         do
342                 echo ${lib}
343                 if [ -e ${lib} ]
344                 then
345                         if [ ! -e ${clst_root_path}/${lib} ]
346                         then
347                                 copy_file ${lib}
348                                 [ -e "${clst_root_path}/${lib}" ] && \
349                                 strip -R .comment -R .note ${clst_root_path}/${lib} \
350                                 || echo "WARNING : Cannot strip lib ${clst_root_path}/${lib} !"
351                         fi
352                 else
353                         echo "WARNING : Some library was not found for ${lib} !"
354                 fi
355         done
356 }
357
358 function copy_symlink() {
359         STACK=${2}
360         [ "${STACK}" = "" ] && STACK=16 || STACK=$((${STACK} - 1 ))
361
362         if [ ${STACK} -le 0 ]
363         then
364                 echo "WARNING : ${TARGET} : too many levels of symbolic links !"
365                 return
366         fi
367
368         [ ! -e ${clst_root_path}/`dirname ${1}` ] && \
369                 mkdir -p ${clst_root_path}/`dirname ${1}`
370         [ ! -e ${clst_root_path}/${1} ] && \
371                 cp -vfdp ${1} ${clst_root_path}/${1}
372
373         if [[ -n $(type -p realpath) ]]; then
374                 TARGET=`realpath ${1}`
375         else
376                 TARGET=`readlink -f ${1}`
377         fi
378         if [ -h ${TARGET} ]
379         then
380                 copy_symlink ${TARGET} ${STACK}
381         else
382                 copy_file ${TARGET}
383         fi
384 }
385
386 function copy_file() {
387         f="${1}"
388
389         if [ ! -e "${f}" ]
390         then
391                 echo "WARNING : File not found : ${f}"
392                 continue
393         fi
394
395         [ ! -e ${clst_root_path}/`dirname ${f}` ] && \
396                 mkdir -p ${clst_root_path}/`dirname ${f}`
397         [ ! -e ${clst_root_path}/${f} ] && \
398                 cp -vfdp ${f} ${clst_root_path}/${f}
399         if [ -x ${f} -a ! -h ${f} ]
400         then
401                 copy_libs ${f}
402                 strip -R .comment -R .note ${clst_root_path}/${f} > /dev/null 2>&1
403         elif [ -h ${f} ]
404         then
405                 copy_symlink ${f}
406         fi
407 }
408
409 create_handbook_icon() {
410         # This function creates a local icon to the Gentoo Handbook
411         echo "[Desktop Entry]
412 Encoding=UTF-8
413 Version=1.0
414 Type=Link
415 URL=file:///mnt/cdrom/docs/handbook/html/index.html
416 Terminal=false
417 Name=Gentoo Linux Handbook
418 GenericName=Gentoo Linux Handbook
419 Comment=This is a link to the local copy of the Gentoo Linux Handbook.
420 Icon=text-editor" > /usr/share/applications/gentoo-handbook.desktop
421 }
422
423 # We do this everywhere, so why not put it in this script
424 run_default_funcs