| 1 | #!/bin/sh |
| 2 | |
| 3 | program_version=@VERSION@ |
| 4 | sysconfdir=@sysconfdir@ |
| 5 | abuildrepo=/var/lib/buildlab/result |
| 6 | sharedir=${ABUILD_SHAREDIR:-@sharedir@} |
| 7 | |
| 8 | BUILD_BASE="build-base" |
| 9 | SUDO=${SUDO:-"sudo"} |
| 10 | FAKEROOT=${FAKEROOT:-"fakeroot"} |
| 11 | APK=${APK:-apk} |
| 12 | |
| 13 | # read config |
| 14 | ABUILD_CONF=${ABUILD_CONF:-"$sysconfdir/abuild.conf"} |
| 15 | [ -f "$ABUILD_CONF" ] && . "$ABUILD_CONF" |
| 16 | |
| 17 | default_colors() { |
| 18 | NORMAL="\033[1;0m" |
| 19 | STRONG="\033[1;1m" |
| 20 | RED="\033[1;31m" |
| 21 | GREEN="\033[1;32m" |
| 22 | YELLOW="\033[1;33m" |
| 23 | BLUE="\033[1;34m" |
| 24 | } |
| 25 | |
| 26 | default_colors |
| 27 | |
| 28 | is_local() { |
| 29 | case "$1" in |
| 30 | http://*|ftp://*|https://*|saveas-*://*) |
| 31 | return 1;; |
| 32 | esac |
| 33 | return 0 |
| 34 | } |
| 35 | |
| 36 | msg() { |
| 37 | local prompt="$GREEN>>>${NORMAL}" |
| 38 | [ -z "$quiet" ] && printf "${prompt} $@\n" >&2 |
| 39 | } |
| 40 | |
| 41 | error() { |
| 42 | local prompt="$RED>>>${NORMAL}" |
| 43 | printf "${prompt} $@\n" >&2 |
| 44 | } |
| 45 | |
| 46 | die() { |
| 47 | error "$@" |
| 48 | exit 1 |
| 49 | } |
| 50 | |
| 51 | runpart() { |
| 52 | local part=$1 |
| 53 | msg "Running part $part" |
| 54 | $part || die "$part failed" |
| 55 | } |
| 56 | |
| 57 | is_vserver() { |
| 58 | egrep -q '^VxID:[[:space:]]*[0-9]+' /proc/self/status |
| 59 | } |
| 60 | |
| 61 | do_chroot_open() { |
| 62 | local path="$1" |
| 63 | if is_vserver; then |
| 64 | # vserver does not allow us mount or create devices |
| 65 | # but we can create hard links as long as chroot is |
| 66 | # on same filesystem as real root |
| 67 | rmdir "$path"/proc "$path"/sys "$path"/dev 2>/dev/null |
| 68 | ln /dev "$path"/dev |
| 69 | ln /proc "$path"/proc |
| 70 | ln /sys "$path"/sys |
| 71 | |
| 72 | else |
| 73 | mkdir -p "$path"/dev "$path"/proc "$path"/sys |
| 74 | mount -o bind /dev "$path"/dev || return 1 |
| 75 | mount -o bind /proc "$path"/proc |
| 76 | mount -o bind /sys "$path"/sys |
| 77 | fi |
| 78 | } |
| 79 | |
| 80 | do_chroot_close() { |
| 81 | local path="$1" |
| 82 | if is_vserver; then |
| 83 | rmdir "$path"/dev "$path"/proc "$path"/sys |
| 84 | else |
| 85 | umount "$path"/dev "$path"/proc "$path"/sys |
| 86 | fi |
| 87 | } |
| 88 | |
| 89 | do_chroot_action() { |
| 90 | local path="$1" |
| 91 | local command="$2" |
| 92 | |
| 93 | msg "Doing chroot action '$command' in '$path'..." |
| 94 | |
| 95 | do_chroot_open "$path" || return 1 |
| 96 | shift; |
| 97 | |
| 98 | # XXX: we have to do this because busybox clobbers us, bleah. |
| 99 | echo $* > "$path"/.chroot-action.sh |
| 100 | chroot "$path" /bin/sh /.chroot-action.sh |
| 101 | rm "$path"/.chroot-action.sh |
| 102 | |
| 103 | do_chroot_close |
| 104 | } |
| 105 | |
| 106 | update_chroot() { |
| 107 | local path="$1" |
| 108 | |
| 109 | apk --root $path --repositories "$path"/etc/apk/repositories update |
| 110 | apk --root $path --repositories "$path"/etc/apk/repositories upgrade -a |
| 111 | } |
| 112 | |
| 113 | prepare_chroot() { |
| 114 | local path="$1" |
| 115 | local version="$2" |
| 116 | local mirror="$3" |
| 117 | local arch="$4" |
| 118 | local enablecache="$5" |
| 119 | |
| 120 | msg "Setting up repositories for mirror $mirror with version $version at $path..." |
| 121 | |
| 122 | mkdir -p "$path"/etc/apk |
| 123 | echo "http://$mirror/alpine/$version/main" >> "$path"/etc/apk/repositories |
| 124 | echo "http://$mirror/alpine/$version/testing" >> "$path"/etc/apk/repositories |
| 125 | |
| 126 | if [ ! -z "$enablecache" ]; then |
| 127 | mkdir -p "$path"/var/cache/apk |
| 128 | ln -s /var/cache/apk "$path"/etc/apk/cache |
| 129 | fi |
| 130 | |
| 131 | echo "alpine-base" > "$path"/etc/apk/world |
| 132 | mkdir -p "$path"/lib/apk/db |
| 133 | mkdir -p "$path"/var/lock |
| 134 | mkdir -p "$path"/var/cache/apk |
| 135 | mkdir -p "$path"/tmp |
| 136 | |
| 137 | mkdir -p "$path"/etc |
| 138 | cp /etc/resolv.conf "$path"/etc/resolv.conf |
| 139 | |
| 140 | msg "Updating package lists..." |
| 141 | |
| 142 | apk --arch $buildarch --root $path --repositories "$path"/etc/apk/repositories update |
| 143 | |
| 144 | msg "Installing alpine-base..." |
| 145 | |
| 146 | apk --arch $buildarch --root $path --repositories "$path"/etc/apk/repositories add --initdb alpine-base |
| 147 | |
| 148 | msg "Installing abuild..." |
| 149 | |
| 150 | apk --arch $buildarch --root $path --repositories "$path"/etc/apk/repositories add --initdb abuild |
| 151 | |
| 152 | msg "Installing build-base..." |
| 153 | |
| 154 | apk --arch $buildarch --root $path --repositories "$path"/etc/apk/repositories add --initdb build-base |
| 155 | |
| 156 | msg "Adding abuild user..." |
| 157 | |
| 158 | do_chroot_action "$path" adduser -D -G abuild abuild |
| 159 | echo "abuild ALL=NOPASSWD: ALL" >> "$path"/etc/sudoers |
| 160 | chmod 440 "$path"/etc/sudoers |
| 161 | |
| 162 | msg "Generating buildlab signing keys..." |
| 163 | do_chroot_action "$path" su abuild -c "'abuild-keygen -ai'" |
| 164 | |
| 165 | msg "Setting up repository symlink..." |
| 166 | mkdir -p "$path"/home/abuild/.cache/apks |
| 167 | do_chroot_action "$path" chown abuild:abuild /home/abuild/${src} |
| 168 | do_chroot_action "$path" ln -sf .cache/apks /home/abuild/repo |
| 169 | |
| 170 | msg "Build chroot is ready!" |
| 171 | } |
| 172 | |
| 173 | build_package() { |
| 174 | local path="$1" |
| 175 | local apkbuild="$2" |
| 176 | srcdir="$(dirname $apkbuild)" |
| 177 | |
| 178 | msg "Parsing $apkbuild..." |
| 179 | . "$apkbuild" |
| 180 | |
| 181 | msg "Copying local sources..." |
| 182 | |
| 183 | mkdir -p "$path"/home/abuild/src |
| 184 | chmod 666 "$path"/home/abuild/src |
| 185 | |
| 186 | for src in $source $install; do |
| 187 | is_local $src || continue |
| 188 | |
| 189 | msg "${srcdir}/${src} -> ${path}/home/abuild/src/${src} ..." |
| 190 | cp ${srcdir}/${src} "${path}"/home/abuild/${src} |
| 191 | do_chroot_action "$path" chown abuild:abuild /home/abuild/${src} |
| 192 | done |
| 193 | |
| 194 | for i in $triggers; do |
| 195 | src=${i%=*} |
| 196 | is_local $src || continue |
| 197 | |
| 198 | msg "${srcdir}/${src} -> ${path}/home/abuild/src/${src} ..." |
| 199 | cp ${srcdir}/${src} "${path}"/home/abuild/${src} |
| 200 | do_chroot_action "$path" chown abuild:abuild /home/abuild/${src} |
| 201 | done |
| 202 | |
| 203 | cp $apkbuild "$path"/home/abuild |
| 204 | do_chroot_action "$path" chown abuild:abuild /home/abuild/$(basename $apkbuild) |
| 205 | |
| 206 | msg "Invoking abuild..." |
| 207 | do_chroot_action "$path" su abuild -c "'cd /home/abuild; abuild -r'" |
| 208 | |
| 209 | msg "Copying back results to ${abuildrepo}..." |
| 210 | mkdir -p ${abuildrepo} |
| 211 | for papk in "${path}"/home/abuild/*.apk; do |
| 212 | apk=$(basename $papk) |
| 213 | msg "$papk -> ${abuildrepo}/${apk}" |
| 214 | cp $papk ${abuildrepo}/${apk} |
| 215 | done |
| 216 | |
| 217 | msg "Cleaning up..." |
| 218 | rm -rf "$path"/home/abuild/src |
| 219 | rm -rf "$path"/home/abuild/pkg |
| 220 | rm -f "$path"/home/abuild/APKBUILD |
| 221 | } |
| 222 | |
| 223 | usage() { |
| 224 | cat <<-EOF |
| 225 | buildlab $program_version |
| 226 | |
| 227 | Common options: |
| 228 | |
| 229 | -q Quiet operation |
| 230 | -p Path to buildroot |
| 231 | |
| 232 | Creating build roots (buildlab -C): |
| 233 | |
| 234 | -m APK repository mirror |
| 235 | -v APK distribution version |
| 236 | -a APK repository architecture |
| 237 | -k Enable APK caching |
| 238 | |
| 239 | Updating build roots (buildlab -u): |
| 240 | |
| 241 | No special options. |
| 242 | |
| 243 | Building packages (buildlab -b): |
| 244 | |
| 245 | -b APKBUILD file |
| 246 | |
| 247 | Examples: |
| 248 | |
| 249 | sudo ./buildlab -C -p /home/nenolod/buildroot -m dl-3.alpinelinux.org -v edge -a x86_64 |
| 250 | sudo ./buildlab -b /home/nenolod/aports/main/gnome-panel/APKBUILD -p /home/nenolod/buildroot |
| 251 | sudo ./buildlab -u -p /home/nenolod/buildroot |
| 252 | EOF |
| 253 | } |
| 254 | |
| 255 | unset force |
| 256 | unset recursive |
| 257 | while getopts "chqCkp:v:m:a:b:u" opt; do |
| 258 | case $opt in |
| 259 | 'c') default_colors |
| 260 | color_opt="-c";; |
| 261 | 'h') usage;; |
| 262 | 'q') quiet="-q";; |
| 263 | 'C') create="-c";; |
| 264 | 'p') buildpath="$OPTARG";; |
| 265 | 'm') buildmirror="$OPTARG";; |
| 266 | 'v') buildver="$OPTARG";; |
| 267 | 'a') buildarch="$OPTARG";; |
| 268 | 'k') enablecache=1;; |
| 269 | 'b') buildpkg="$OPTARG";; |
| 270 | 'u') update="-u";; |
| 271 | esac |
| 272 | done |
| 273 | shift $(( $OPTIND - 1 )) |
| 274 | |
| 275 | if [ ! -z "$create" ]; then |
| 276 | msg "Creating new chroot at $buildpath..." |
| 277 | prepare_chroot $buildpath $buildver $buildmirror $buildarch $enablecache |
| 278 | exit 0 |
| 279 | fi |
| 280 | |
| 281 | if [ ! -z "$buildpkg" ]; then |
| 282 | msg "Building APKBUILD $buildpkg in chroot $buildpath..." |
| 283 | build_package $buildpath $buildpkg |
| 284 | exit 0 |
| 285 | fi |
| 286 | |
| 287 | if [ ! -z "$update" ]; then |
| 288 | msg "Updating chroot at $buildpath..." |
| 289 | update_chroot $buildpath |
| 290 | exit 0 |
| 291 | fi |