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