File: pbuilder-buildpackage-funcs

package info (click to toggle)
pbuilder 0.231.1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 3,864 kB
  • sloc: sh: 5,726; xml: 1,755; makefile: 248; ansic: 11
file content (316 lines) | stat: -rw-r--r-- 11,416 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#! /bin/bash
#   pbuilder -- personal Debian package builder
#   Copyright © 2001-2007 Junichi Uekawa <dancer@debian.org>
#               2015-2016 Mattia Rizzolo <mattia@debian.org>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
###############################################################################

# functions local to pbuilder-buildpackage

. "${BASH_SOURCE%/*}/pbuilder-modules"

get822files () {
    # get list of files listed in the Files field of a .changes or .dsc (to
    # be specified in the first parameter) and output them one file per line
    local type="$1"
    local input="$2"
    case $type in
        changes) local field=5 ;;
        dsc) local field=3 ;;
        *) log.e "unexpected error in get822files()" ; exit 1 ;;
    esac
    echo "$input"
    cat "$input" | awk -v dir="$(dirname "$input")" '
        BEGIN {p=0}
        ! /^[ \t]/ {p=0}
        /^[ \t]*$/ {p=0}
        /^Files:/ {p=1}
        /^ / && p {print dir "/" $'${field}'}
    '
}

function copydsc () {
    local DSCFILE=$(get822files "dsc" "$1")
    local TARGET="$2"
    local FILE
    while read -r FILE ; do
        log.i "copying [$FILE]"
        cp -p "$FILE" "$TARGET"
        chmod u+rw "$TARGET/$(basename "$FILE")"
    done <<< "$DSCFILE"
}

function dsc_get_basename() {
    local dscfile="$1"
    local with_revision="$2"

    local src=$(get822field "Source" "$dscfile")
    local source_version=$(get822field "Version" "$dscfile")

    # Parse version string
    local epoch
    local version
    local revision
    case "$source_version" in
        *:*)
            epoch=${source_version%%:*}
            source_version=${source_version#*:}
            ;;
        *)
            ;;
    esac
    case "$source_version" in
        *-*)
            version=${source_version%-*}
            revision=${source_version##*-}
            ;;
        *)
            version=$source_version
            ;;
    esac

    local vs
    if [ "$with_revision" = "yes" -a -z "${revision:-}" ]; then
        with_revision=no
    fi
    # Epoch always omitted
    case "$with_revision" in
        yes) vs="${version}-${revision}" ;;
        no)  vs="${version}" ;;
        *)   log.error "unexpected with_revision: $with_revision" ; exit 1 ;;
    esac

    echo "${src}_${vs}"
}

function checkbuilddep () {
    # call satisfydepends
    local BUILDOPT="--binary-all"
    case "${BINARY_ARCH}" in
        binary) BUILDOPT="--binary-arch";;
        all) BUILDOPT="--binary-indep";;
        *) ;;
    esac
    case "$(readlink -e "$PBUILDERSATISFYDEPENDSCMD")" in
        *-apt) local control="$BUILDDIR/$(basename "$1")" ;;
        *) local control="$1" ;;
    esac
    if \
        ("$PBUILDERSATISFYDEPENDSCMD" \
            --build-arch "$ARCHITECTURE" \
            --host-arch "$HOST_ARCH" \
            --control "$control" \
            --chroot "${BUILDPLACE}" \
            --internal-chrootexec "${CHROOTEXEC}" \
            "${BUILDOPT}" \
            "${PBUILDERSATISFYDEPENDSOPT[@]}"); \
    then
        :
    else
        # If asked to preserve the build place, and pbuilder-satisfydepends
        # didn't taint it, then don't clean it when exiting.
        if [ $? -eq 2 -a "${PRESERVE_BUILDPLACE}" = "yes" ]; then
            trap umountproc_trap exit sighup
        fi
        log.e "pbuilder-satisfydepends failed."
        exit 2
    fi
    # install extra packages to the chroot
    if [ -n "$EXTRAPACKAGES" ]; then 
        $CHROOTEXEC apt-get -q -y "${APTGETOPT[@]}" install ${EXTRAPACKAGES}
    fi
}

function showbuildbanner () {
    # show some banners for building
    log.i "pbuilder-buildpackage/"$(dpkg --print-architecture) 
    log.i "$1"
}

function cowprotect () {
    # a hack for cowdancer, used when a file is edited in-place;
    # Copy the file to create a new i-node so that hardlinked original is intact
    for A in "$@"; do
        if readlink -f "$A" > /dev/null; then
            A=$(readlink -f "$A")
            mv "$A" "$A"~
            cp -a "$A"~ "$A"
            rm -f "$A"~
        fi
    done
}

function addgrsecgroup () {
    # if grsecurity with TPE (Trusted Path Execution) is active, add user to allowed group
    [ "$(sysctl -ne kernel.grsecurity.tpe)" = "1" ] || return 0
    [ "$(sysctl -ne kernel.grsecurity.tpe_invert)" = "1" ] || return 0

    local TPEGID=$(sysctl -n kernel.grsecurity.tpe_gid)
    log.i "Adding build user to grsec-tpe group"
    sed -i "/\(^grsec-tpe:\|:$TPEGID:\)/d" "$BUILDPLACE/etc/group"
    echo "grsec-tpe:x:$TPEGID:$BUILDUSERNAME" >> "$BUILDPLACE/etc/group"
}

function createbuilduser () {
    # create the build user, if it is necessary and specified.
    if [ -n "$BUILDUSERNAME" -a -n "$BUILDUSERID" ]; then
        if [ -e $BUILDPLACE/etc/shadow ]; then p='x'; else p='*'; fi
        if [ -e $BUILDPLACE/etc/gshadow ]; then g='x'; else g='*'; fi
        if ! grep -q ^$BUILDUSERNAME: $BUILDPLACE/etc/passwd; then
            cowprotect $BUILDPLACE/etc/passwd
            echo "$BUILDUSERNAME:$p:$BUILDUSERID:$BUILDUSERID:,,,:$BUILD_HOME:/bin/sh" >> $BUILDPLACE/etc/passwd
        fi
        if ! grep -q ^$BUILDUSERNAME: $BUILDPLACE/etc/group; then
            cowprotect $BUILDPLACE/etc/group
            echo "$BUILDUSERNAME:$g:$BUILDUSERID:" >> $BUILDPLACE/etc/group
            addgrsecgroup
        fi
        if [ -e $BUILDPLACE/etc/shadow ] && ! grep -q ^$BUILDUSERNAME: $BUILDPLACE/etc/shadow; then
            cowprotect $BUILDPLACE/etc/shadow
            echo "$BUILDUSERNAME:!:::::::" >> $BUILDPLACE/etc/shadow
        fi
        if [ -e $BUILDPLACE/etc/gshadow ] && ! grep -q ^$BUILDUSERNAME: $BUILDPLACE/etc/gshadow; then
            cowprotect $BUILDPLACE/etc/gshadow
            echo "$BUILDUSERNAME:!::" >> $BUILDPLACE/etc/gshadow
        fi
        unset LOGNAME || true
    else
        unset LOGNAME || true
    fi
}

function setup_ccache() {
    if [ -n "$CCACHEDIR" ]; then
        log.i "Setting up ccache"
        if ! [ -d "$BUILDPLACE/$CCACHEDIR" ]; then
            mkdir -p "$BUILDPLACE/$CCACHEDIR"
        fi
        chown -R $BUILDUSERID:$BUILDUSERID "$BUILDPLACE/$CCACHEDIR"
        CCACHE_ENV="CCACHE_DIR=$CCACHEDIR"
        unset CCACHE_DIR
    fi
}

function binNMU() {
    if [ "$BIN_NMU" == "no" ]; then
        return
    fi
    if [ -z "$BINNMU_MESSAGE" ]; then
        log.e "No changelog message provided for binNMU entry."
        exit 1
    fi
    if [ -z "$BINNMU_VERSION" ]; then
        log.w "No version provided for binNMU entry, fall back to 1."
        BINNMU_VERSION=1
    fi
    local arch=$($CHROOTEXEC dpkg-architecture -qDEB_HOST_ARCH)
    local date=$(date -R ${BINNMU_TIMESTAMP:+-d "${BINNMU_TIMESTAMP}"})
    log.i "Doing a binNMU, version $BINNMU_VERSION for $DISTRIBUTION/$arch to '$BINNMU_MESSAGE'"
    local cl=$(ls "$BUILDPLACE/$BUILDDIR/$BUILDSUBDIR"/debian/changelog)
    local tmpcl=$(mktemp pbuilder.tmpchangelog.XXXXXXXXXXX)
    if [ ! -f "$cl" ]; then
        log.e "Cannot open debian/changelog for binNMU version handling."
        exit 1
    fi
    mv "$cl" "$tmpcl"
    local package=$(dpkg-parsechangelog -l "$tmpcl" -c 1 --show-field Source)
    local version=$(dpkg-parsechangelog -l "$tmpcl" -c 1 --show-field Version)
    if [ -z "$BINNMU_MAINTAINER" ]; then
        log.w "No maintainer provided for binNMU entry, fall back to last uploader."
        BINNMU_MAINTAINER=$(dpkg-parsechangelog -l $tmpcl -c 1 --show-field Maintainer)
    fi
    if [ -z "$DISTRIBUTION" ]; then
        log.w "No distribution provided, using the field from the last upload"
        DISTRIBUTION=$(dpkg-parsechangelog -l "$tmpcl" -c 1 --show-field Distribution)
    fi
    CHANGES_BASENAME="$CHANGES_BASENAME+b$BINNMU_VERSION"
    DEBBUILDOPTS="${DEBBUILDOPTS} -e\"$BINNMU_MAINTAINER\" -m\"$BINNMU_MAINTAINER\""
    cat > "$cl" << EOF
$package ($version+b$BINNMU_VERSION) $DISTRIBUTION; urgency=low, binary-only=yes

  * Binary-only non-maintainer upload for $arch; no source changes.
  * $BINNMU_MESSAGE

 -- $BINNMU_MAINTAINER  $date

EOF
    cat "$tmpcl" >> "$cl"
    rm "$tmpcl"
}

cross_build_setup () {
    if [[ "$ARCHITECTURE" = "$HOST_ARCH" ]]; then
        # native build, nothing interesting to do here
        return
    fi
    log.i "Doing a cross-architecture build"
    log.i "Build architecture: $ARCHITECTURE"
    log.i "Host architecture: $HOST_ARCH"

    if [ "${NO_AUTO_CROSS:-}" != "really-dont-mess-with-me" ]; then
        log.i "Setting up the environment for a cross build..."
        if [[ "$(readlink -e "$PBUILDERSATISFYDEPENDSCMD")" != *-apt ]]; then
            log.e "Cross building is possible only with the APT dependency resolver"
            exit 1
        fi
        $CHROOTEXEC dpkg --add-architecture "$HOST_ARCH"
        $CHROOTEXEC apt-get -q "${APTGETOPT[@]}" update
        # preinstall libc-dev and libstdc++-dev 'cause https://bugs.debian.org/815172
        # also, we end need to figure a versioned libstdc++-dev because the unversioned
        # variant is a virtual package, and often there are more than one, and apt can't
        # pick one for us
        local gcc_ver
        gcc_ver="$($CHROOTEXEC dpkg-query -W --showformat='${Depends}\n' gcc | sed -n 's/^.*gcc-\([0-9.]\+\)\([ ,].*\|$\)/\1/p')"
        if [ -z "$gcc_ver" ]; then
            log.e "Failed to determine default GCC version for installing cross build dependencies"
            exit 1
        fi
        EXTRAPACKAGES="${EXTRAPACKAGES:+"$EXTRAPACKAGES" }crossbuild-essential-$HOST_ARCH libc-dev:$HOST_ARCH libstdc++${gcc_ver:+-"$gcc_ver"}-dev:$HOST_ARCH"
        DEBBUILDOPTS="${DEBBUILDOPTS:+"$DEBBUILDOPTS" }--host-arch $HOST_ARCH"
        if [ "${NO_AUTO_CROSS:-}" != "yes" ]; then
            export DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS:+"$DEB_BUILD_OPTIONS" }nocheck"
            export DEB_BUILD_PROFILES="${DEB_BUILD_PROFILES:+"$DEB_BUILD_PROFILES" }nocheck cross"
        fi
    else
        log.w "Doing a cross build, but not setting up the environment as instructed"
        return
    fi
}

function _find_additional_buildresults() {
    local file f
    local root="${BUILDPLACE}${BUILDDIR}/${BUILDSUBDIR}"
    for file in "${ADDITIONAL_BUILDRESULTS[@]}"; do
        log.d "checking [$file]..."
        echo "$root/$file" | perl -ne 'print "$_\n" foreach glob($_)' | \
        while read f ; do
            if [ -e "$f" ]; then
                echo "$f"
            else
                log.w "file [$file] not found"
            fi
        done
    done
}

function export_additional_buildresults() {
    local file
    for file in $(_find_additional_buildresults); do
        log.i "Trying to save additional result '${file}'"
        chown -R "${BUILDRESULTUID}:${BUILDRESULTGID}" "${file}"
        cp -a "${file}" "${BUILDRESULT}" || true
    done
}