418336cd1c0f2db2a91f2b7a544be9e21544b9be
[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         if [ -n "${clst_CCACHE}" ]
65         then
66                 export clst_myfeatures="${clst_myfeatures} ccache"
67                 clst_root_path=/ run_merge --oneshot --nodeps --noreplace dev-util/ccache || exit 1
68         fi
69
70         if [ -n "${clst_DISTCC}" ]
71         then
72                 export clst_myfeatures="${clst_myfeatures} distcc"
73                 export DISTCC_HOSTS="${clst_distcc_hosts}"
74                 [ -e /etc/make.conf ] && \
75                         echo 'USE="${USE} -avahi -gtk -gnome"' >> /etc/make.conf
76                 clst_root_path=/ run_merge --oneshot --nodeps --noreplace sys-devel/distcc || exit 1
77                 sed -i '/USE="${USE} -avahi -gtk -gnome"/d' /etc/make.conf
78                 mkdir -p /etc/distcc
79                 echo "${clst_distcc_hosts}" > /etc/distcc/hosts
80
81                 # This sets up automatic cross-distcc-fu according to
82                 # http://www.gentoo.org/doc/en/cross-compiling-distcc.xml
83                 CHOST=$(portageq envvar CHOST)
84                 # TODO: change to use get_libdir
85                 cd /usr/lib/distcc/bin
86                 rm cc gcc g++ c++ 2>/dev/null
87                 echo -e '#!/bin/bash\nexec /usr/lib/distcc/bin/'${CHOST}'-g${0:$[-2]} "$@"' > ${CHOST}-wrapper
88                 chmod a+x /usr/lib/distcc/bin/${CHOST}-wrapper
89                 for i in cc gcc g++ c++; do ln -s ${CHOST}-wrapper ${i}; done
90         fi
91
92         if [ -n "${clst_ICECREAM}" ]
93         then
94                 clst_root_path=/ run_merge --oneshot --nodeps --noreplace sys-devel/icecream || exit 1
95
96                 # This sets up automatic cross-icecc-fu according to
97                 # http://gentoo-wiki.com/HOWTO_Setup_An_ICECREAM_Compile_Cluster#Icecream_and_cross-compiling
98                 CHOST=$(portageq envvar CHOST)
99                 LIBDIR=$(get_libdir)
100                 cd /usr/${LIBDIR}/icecc/bin
101                 rm cc gcc g++ c++ 2>/dev/null
102                 echo -e '#!/bin/bash\nexec /usr/'${LIBDIR}'/icecc/bin/'${CHOST}'-g${0:$[-2]} "$@"' > ${CHOST}-wrapper
103                 chmod a+x ${CHOST}-wrapper
104                 for i in cc gcc g++ c++; do ln -s ${CHOST}-wrapper ${i}; done
105                 export PATH="/usr/lib/icecc/bin:${PATH}"
106                 export PREROOTPATH="/usr/lib/icecc/bin"
107         fi
108         export FEATURES="${clst_myfeatures}"
109 }
110
111 setup_myemergeopts(){
112         if [ -n "${clst_VERBOSE}" ]
113         then
114                 clst_myemergeopts="--verbose"
115         else
116                 clst_myemergeopts="--quiet"
117         fi
118         if [ -n "${clst_FETCH}" ]
119         then
120                 export bootstrap_opts="-f"
121                 export clst_myemergeopts="${clst_myemergeopts} -f"
122         elif [ -n "${clst_PKGCACHE}" ]
123         then
124                 export clst_myemergeopts="${clst_myemergeopts} --usepkg --buildpkg --newuse"
125                 export bootstrap_opts="-r"
126         fi
127 }
128
129 setup_binutils(){
130         if [ -x /usr/bin/binutils-config ]
131         then
132                 mythang=$( cd /etc/env.d/binutils; ls ${clst_CHOST}-* | head -n 1 )
133                 if [ -z "${mythang}" ]
134                 then
135                         mythang=1
136                 fi
137                 binutils-config ${mythang}; update_env_settings
138         fi
139 }
140
141 setup_gcc(){
142         if [ -x /usr/bin/gcc-config ]
143         then
144                 mythang=$( cd /etc/env.d/gcc; ls ${clst_CHOST}-* | head -n 1 )
145                 if [ -z "${mythang}" ]
146                 then
147                         mythang=1
148                 fi
149                 gcc-config ${mythang}; update_env_settings
150         fi
151 }
152
153 setup_pkgmgr(){
154         # We need to merge our package manager with USE="build" set in case it is
155         # portage to avoid frying our /etc/make.conf file.  Otherwise, we could
156         # just let emerge system could merge it.
157         [ -e /etc/make.conf ] && echo 'USE="${USE} build"' >> /etc/make.conf
158         run_merge --oneshot --nodeps virtual/portage
159         sed -i '/USE="${USE} build"/d' /etc/make.conf
160 }
161
162 cleanup_distcc() {
163         rm -rf /etc/distcc/hosts
164         for i in cc gcc c++ g++; do
165                 # TODO: change to use get_libdir
166                 rm -f /usr/lib/distcc/bin/${i}
167                 ln -s /usr/bin/distcc /usr/lib/distcc/bin/${i}
168         done
169         rm -f /usr/lib/distcc/bin/*-wrapper
170 }
171
172 cleanup_icecream() {
173         LIBDIR=$(get_libdir)
174         for i in cc gcc c++ g++; do
175                 rm -f /usr/${LIBDIR}/icecc/bin/${i}
176                 ln -s /usr/bin/icecc /usr/${LIBDIR}/icecc/bin/${i}
177         done
178         rm -f /usr/${LIBDIR}/icecc/bin/*-wrapper
179 }
180
181 cleanup_stages() {
182         make_destpath
183         if [ -n "${clst_DISTCC}" ]
184         then
185                 cleanup_distcc
186         fi
187         if [ -n "${clst_ICECREAM}" ]
188         then
189                 cleanup_icecream
190         fi
191         case ${clst_target} in
192                 stage1|stage2|stage3)
193                         rm -f /var/lib/portage/world
194                         touch /var/lib/portage/world
195                         ;;
196                 *)
197                         echo "Skipping removal of world file for ${clst_target}"
198                         ;;
199         esac
200
201         rm -f /var/log/emerge.log /var/log/portage/elog/*
202         rm -rf /var/tmp/*
203 }
204
205 update_env_settings(){
206         [ -x /usr/sbin/env-update ] && /usr/sbin/env-update
207         source /etc/profile
208         [ -f /tmp/envscript ] && source /tmp/envscript
209 }
210
211 die() {
212         echo "$1"
213         exit 1
214 }
215
216 make_destpath() {
217         # ROOT is / by default, so remove any ROOT= settings from make.conf
218         sed -i '/ROOT=/d' /etc/make.conf
219         export ROOT=/
220         if [ "${1}" != "/" -a -n "${1}" ] 
221         then
222                 echo "ROOT=\"${1}\"" >> /etc/make.conf
223                 export ROOT=${1}
224         fi
225         if [ ! -d ${ROOT} ]
226         then
227                 install -d ${ROOT}
228         fi
229 }
230
231 run_merge() {
232         # Sets up the ROOT= parameter
233         # with no options ROOT=/
234         make_destpath ${clst_root_path}
235         
236         export EMERGE_WARNING_DELAY=0   
237         export CLEAN_DELAY=0
238         export EBEEP_IGNORE=0
239         export EPAUSE_IGNORE=0
240         export CONFIG_PROTECT="-*"
241
242         if [ -n "${clst_VERBOSE}" ]
243         then
244                 echo "ROOT=${ROOT} emerge ${clst_myemergeopts} -pt $@" || exit 1
245                 emerge ${clst_myemergeopts} -pt $@ || exit 3
246                 echo "Press any key within 15 seconds to pause the build..."
247                 read -s -t 15 -n 1
248                 if [ $? -eq 0 ]
249                 then
250                         echo "Press any key to continue..."
251                         read -s -n 1
252                 fi
253         fi
254
255         echo "emerge ${clst_myemergeopts} $@" || exit 1
256
257         emerge ${clst_myemergeopts} $@ || exit 1
258 }
259
260 show_debug() {
261         if [ "${clst_DEBUG}" = "1" ]
262         then
263                 unset PACKAGES
264                 echo "DEBUG:"
265                 echo "Profile/target info:"
266                 echo "Profile inheritance:"
267                 python -c 'import portage; print portage.settings.profiles'
268                 echo
269                 # TODO: make this work on non-portage
270                 emerge --info
271                 # TODO: grab our entire env
272                 # <zmedico> to get see the ebuild env you can do something like:
273                 # `set > /tmp/env_dump.${EBUILD_PHASE}` inside /etc/portage/bashrc
274                 # XXX: Also, portageq does *not* source profile.bashrc at any time.
275                 echo
276                 echo "STAGE1_USE:            $(portageq envvar STAGE1_USE)"
277                 echo
278                 echo "USE (profile):         $(portageq envvar USE)"
279                 echo "FEATURES (profile):    $(portageq envvar FEATURES)"
280                 echo
281                 echo "ARCH:                  $(portageq envvar ARCH)"
282                 echo "CHOST:                 $(portageq envvar CHOST)"
283                 echo "CFLAGS:                $(portageq envvar CFLAGS)"
284                 echo
285                 echo "These should be blank on non-multilib profiles."
286                 echo "ABI:                   $(portageq envvar ABI)"
287                 echo "DEFAULT_ABI:           $(portageq envvar DEFAULT_ABI)"
288                 echo "KERNEL_ABI:            $(portageq envvar KERNEL_ABI)"
289                 echo "LIBDIR:                $(get_libdir)"
290                 echo "MULTILIB_ABIS:         $(portageq envvar MULTILIB_ABIS)"
291                 echo "PROFILE_ARCH:          $(portageq envvar PROFILE_ARCH)"
292                 echo
293         fi
294 }
295
296 run_default_funcs() {
297         if [ "${RUN_DEFAULT_FUNCS}" != "no" ]
298         then
299                 update_env_settings
300                 setup_myfeatures
301                 show_debug
302         fi
303 }
304
305 # Functions
306 # Copy libs of a executable in the chroot
307 function copy_libs() {
308         # Check if it's a dynamix exec
309         ldd ${1} > /dev/null 2>&1 || return
310
311         for lib in `ldd ${1} | awk '{ print $3 }'`
312         do
313                 echo ${lib}
314                 if [ -e ${lib} ]
315                 then
316                         if [ ! -e ${clst_root_path}/${lib} ]
317                         then
318                                 copy_file ${lib}
319                                 [ -e "${clst_root_path}/${lib}" ] && \
320                                 strip -R .comment -R .note ${clst_root_path}/${lib} \
321                                 || echo "WARNING : Cannot strip lib ${clst_root_path}/${lib} !"
322                         fi
323                 else
324                         echo "WARNING : Some library was not found for ${lib} !"
325                 fi
326         done
327 }
328
329 function copy_symlink() {
330         STACK=${2}
331         [ "${STACK}" = "" ] && STACK=16 || STACK=$((${STACK} - 1 ))
332
333         if [ ${STACK} -le 0 ] 
334         then
335                 echo "WARNING : ${TARGET} : too many levels of symbolic links !"
336                 return
337         fi
338
339         [ ! -e ${clst_root_path}/`dirname ${1}` ] && \
340                 mkdir -p ${clst_root_path}/`dirname ${1}`
341         [ ! -e ${clst_root_path}/${1} ] && \
342                 cp -vfdp ${1} ${clst_root_path}/${1}
343         
344         if [[ -n $(type -p realpath) ]]; then
345                 TARGET=`realpath ${1}`
346         else
347                 TARGET=`readlink -f ${1}`
348         fi
349         if [ -h ${TARGET} ]
350         then
351                 copy_symlink ${TARGET} ${STACK}
352         else
353                 copy_file ${TARGET}
354         fi
355 }
356
357 function copy_file() {
358         f="${1}"
359
360         if [ ! -e "${f}" ]
361         then
362                 echo "WARNING : File not found : ${f}"
363                 continue
364         fi
365
366         [ ! -e ${clst_root_path}/`dirname ${f}` ] && \
367                 mkdir -p ${clst_root_path}/`dirname ${f}`
368         [ ! -e ${clst_root_path}/${f} ] && \
369                 cp -vfdp ${f} ${clst_root_path}/${f}
370         if [ -x ${f} -a ! -h ${f} ]
371         then
372                 copy_libs ${f}
373                 strip -R .comment -R .note ${clst_root_path}/${f} > /dev/null 2>&1
374         elif [ -h ${f} ]
375         then
376                 copy_symlink ${f}
377         fi
378 }
379
380 create_handbook_icon() {
381         # This function creates a local icon to the Gentoo Handbook
382         echo "[Desktop Entry]
383 Encoding=UTF-8
384 Version=1.0
385 Type=Link
386 URL=file:///mnt/cdrom/docs/handbook/html/index.html
387 Terminal=false
388 Name=Gentoo Linux Handbook
389 GenericName=Gentoo Linux Handbook
390 Comment=This is a link to the local copy of the Gentoo Linux Handbook.
391 Icon=text-editor" > /usr/share/applications/gentoo-handbook.desktop
392 }
393
394 # We do this everywhere, so why not put it in this script
395 run_default_funcs
396