build.sh revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1#!/bin/bash
2#
3# Copyright (c) 2012 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7# TODO(mmoss) This currently only works with official builds, since non-official
8# builds don't add the "${BUILDDIR}/installer/" files needed for packaging.
9
10set -e
11if [ "$VERBOSE" ]; then
12  set -x
13fi
14set -u
15
16# Create the Debian changelog file needed by dpkg-gencontrol. This just adds a
17# placeholder change, indicating it is the result of an automatic build.
18# TODO(mmoss) Release packages should create something meaningful for a
19# changelog, but simply grabbing the actual 'svn log' is way too verbose. Do we
20# have any type of "significant/visible changes" log that we could use for this?
21gen_changelog() {
22  rm -f "${DEB_CHANGELOG}"
23  process_template "${SCRIPTDIR}/changelog.template" "${DEB_CHANGELOG}"
24  debchange -a --nomultimaint -m --changelog "${DEB_CHANGELOG}" \
25    "Release Notes: ${RELEASENOTES}"
26  GZLOG="${STAGEDIR}/usr/share/doc/${PACKAGE}-${CHANNEL}/changelog.gz"
27  mkdir -p "$(dirname "${GZLOG}")"
28  gzip -9 -c "${DEB_CHANGELOG}" > "${GZLOG}"
29  chmod 644 "${GZLOG}"
30}
31
32# Create the Debian control file needed by dpkg-deb.
33gen_control() {
34  dpkg-gencontrol -v"${VERSIONFULL}" -c"${DEB_CONTROL}" -l"${DEB_CHANGELOG}" \
35  -f"${DEB_FILES}" -p"${PACKAGE}-${CHANNEL}" -P"${STAGEDIR}" \
36  -O > "${STAGEDIR}/DEBIAN/control"
37  rm -f "${DEB_CONTROL}"
38}
39
40# Setup the installation directory hierachy in the package staging area.
41prep_staging_debian() {
42  prep_staging_common
43  install -m 755 -d "${STAGEDIR}/DEBIAN" \
44    "${STAGEDIR}/etc/cron.daily" \
45    "${STAGEDIR}/usr/share/menu" \
46    "${STAGEDIR}/usr/share/doc/${PACKAGE}"
47}
48
49# Put the package contents in the staging area.
50stage_install_debian() {
51  if [ "$CHANNEL" != "stable" ]; then
52    # Avoid file collisions between channels.
53    local PACKAGE="${PACKAGE}-${CHANNEL}"
54    local INSTALLDIR="${INSTALLDIR}-${CHANNEL}"
55
56    # Make it possible to distinguish between menu entries
57    # for different channels.
58    local MENUNAME="${MENUNAME} (${CHANNEL})"
59
60    # This would ideally be compiled into the app, but that's a bit too
61    # intrusive of a change for these limited use channels, so we'll just hack
62    # it into the wrapper script. The user can still override since it seems to
63    # work to specify --user-data-dir multiple times on the command line, with
64    # the last occurrence winning.
65    local SXS_USER_DATA_DIR="\${XDG_CONFIG_HOME:-\${HOME}/.config}/${PACKAGE}"
66    local DEFAULT_FLAGS="--user-data-dir=\"${SXS_USER_DATA_DIR}\""
67  fi
68  prep_staging_debian
69  stage_install_common
70  echo "Staging Debian install files in '${STAGEDIR}'..."
71  install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/cron"
72  process_template "${BUILDDIR}/installer/common/repo.cron" \
73      "${STAGEDIR}/${INSTALLDIR}/cron/${PACKAGE}"
74  chmod 755 "${STAGEDIR}/${INSTALLDIR}/cron/${PACKAGE}"
75  pushd "${STAGEDIR}/etc/cron.daily/"
76  ln -snf "${INSTALLDIR}/cron/${PACKAGE}" "${PACKAGE}"
77  popd
78  process_template "${BUILDDIR}/installer/debian/debian.menu" \
79    "${STAGEDIR}/usr/share/menu/${PACKAGE}.menu"
80  chmod 644 "${STAGEDIR}/usr/share/menu/${PACKAGE}.menu"
81  process_template "${BUILDDIR}/installer/debian/postinst" \
82    "${STAGEDIR}/DEBIAN/postinst"
83  chmod 755 "${STAGEDIR}/DEBIAN/postinst"
84  process_template "${BUILDDIR}/installer/debian/prerm" \
85    "${STAGEDIR}/DEBIAN/prerm"
86  chmod 755 "${STAGEDIR}/DEBIAN/prerm"
87  process_template "${BUILDDIR}/installer/debian/postrm" \
88    "${STAGEDIR}/DEBIAN/postrm"
89  chmod 755 "${STAGEDIR}/DEBIAN/postrm"
90}
91
92# Actually generate the package file.
93do_package() {
94  echo "Packaging ${ARCHITECTURE}..."
95  PREDEPENDS="$COMMON_PREDEPS"
96  DEPENDS="${COMMON_DEPS}"
97  # Trunk is a special package, mostly for development testing, so don't make
98  # it replace any installed release packages.
99  if [ "$CHANNEL" != "trunk" ] && [ "$CHANNEL" != "asan" ]; then
100    REPLACES="${PACKAGE}"
101    CONFLICTS="${PACKAGE}"
102    PROVIDES="${PACKAGE}, www-browser"
103  fi
104  gen_changelog
105  process_template "${SCRIPTDIR}/control.template" "${DEB_CONTROL}"
106  export DEB_HOST_ARCH="${ARCHITECTURE}"
107  if [ -f "${DEB_CONTROL}" ]; then
108    gen_control
109  fi
110  fakeroot dpkg-deb -Zlzma -b "${STAGEDIR}" .
111}
112
113# Remove temporary files and unwanted packaging output.
114cleanup() {
115  echo "Cleaning..."
116  rm -rf "${STAGEDIR}"
117  rm -rf "${TMPFILEDIR}"
118}
119
120usage() {
121  echo "usage: $(basename $0) [-c channel] [-a target_arch] [-o 'dir'] "
122  echo "                      [-b 'dir']"
123  echo "-c channel the package channel (trunk, asan, unstable, beta, stable)"
124  echo "-a arch    package architecture (ia32 or x64)"
125  echo "-o dir     package output directory [${OUTPUTDIR}]"
126  echo "-b dir     build input directory    [${BUILDDIR}]"
127  echo "-h         this help message"
128}
129
130# Check that the channel name is one of the allowable ones.
131verify_channel() {
132  case $CHANNEL in
133    stable )
134      CHANNEL=stable
135      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Stable%20updates"
136      ;;
137    unstable|dev|alpha )
138      CHANNEL=unstable
139      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Dev%20updates"
140      ;;
141    testing|beta )
142      CHANNEL=beta
143      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Beta%20updates"
144      ;;
145    trunk|asan )
146      # Setting this to empty will prevent it from updating any existing configs
147      # from release packages.
148      REPOCONFIG=""
149      RELEASENOTES="http://googlechromereleases.blogspot.com/"
150      ;;
151    * )
152      echo
153      echo "ERROR: '$CHANNEL' is not a valid channel type."
154      echo
155      exit 1
156      ;;
157  esac
158}
159
160process_opts() {
161  while getopts ":o:b:c:a:h" OPTNAME
162  do
163    case $OPTNAME in
164      o )
165        OUTPUTDIR=$(readlink -f "${OPTARG}")
166        mkdir -p "${OUTPUTDIR}"
167        ;;
168      b )
169        BUILDDIR=$(readlink -f "${OPTARG}")
170        ;;
171      c )
172        CHANNEL="$OPTARG"
173        ;;
174      a )
175        TARGETARCH="$OPTARG"
176        ;;
177      h )
178        usage
179        exit 0
180        ;;
181      \: )
182        echo "'-$OPTARG' needs an argument."
183        usage
184        exit 1
185        ;;
186      * )
187        echo "invalid command-line option: $OPTARG"
188        usage
189        exit 1
190        ;;
191    esac
192  done
193}
194
195#=========
196# MAIN
197#=========
198
199SCRIPTDIR=$(readlink -f "$(dirname "$0")")
200OUTPUTDIR="${PWD}"
201STAGEDIR=$(mktemp -d -t deb.build.XXXXXX) || exit 1
202TMPFILEDIR=$(mktemp -d -t deb.tmp.XXXXXX) || exit 1
203DEB_CHANGELOG="${TMPFILEDIR}/changelog"
204DEB_FILES="${TMPFILEDIR}/files"
205DEB_CONTROL="${TMPFILEDIR}/control"
206CHANNEL="trunk"
207# Default target architecture to same as build host.
208if [ "$(uname -m)" = "x86_64" ]; then
209  TARGETARCH="x64"
210else
211  TARGETARCH="ia32"
212fi
213
214# call cleanup() on exit
215trap cleanup 0
216process_opts "$@"
217if [ ! "$BUILDDIR" ]; then
218  BUILDDIR=$(readlink -f "${SCRIPTDIR}/../../../../../out/Release")
219fi
220
221source ${BUILDDIR}/installer/common/installer.include
222
223get_version_info
224VERSIONFULL="${VERSION}-${PACKAGE_RELEASE}"
225
226if [ "$CHROMIUM_BUILD" = "_google_chrome" ]; then
227  source "${BUILDDIR}/installer/common/google-chrome.info"
228else
229  source "${BUILDDIR}/installer/common/chromium-browser.info"
230fi
231eval $(sed -e "s/^\([^=]\+\)=\(.*\)$/export \1='\2'/" \
232  "${BUILDDIR}/installer/theme/BRANDING")
233
234REPOCONFIG="deb http://dl.google.com/linux/chrome/deb/ stable main"
235verify_channel
236
237# Some Debian packaging tools want these set.
238export DEBFULLNAME="${MAINTNAME}"
239export DEBEMAIL="${MAINTMAIL}"
240
241# We'd like to eliminate more of these deps by relying on the 'lsb' package, but
242# that brings in tons of unnecessary stuff, like an mta and rpm. Until that full
243# 'lsb' package is installed by default on DEB distros, we'll have to stick with
244# the LSB sub-packages, to avoid pulling in all that stuff that's not installed
245# by default.
246
247# Need a dummy debian/control file for dpkg-shlibdeps.
248DUMMY_STAGING_DIR="${TMPFILEDIR}/dummy_staging"
249mkdir "$DUMMY_STAGING_DIR"
250cd "$DUMMY_STAGING_DIR"
251mkdir debian
252touch debian/control
253
254# Generate the dependencies,
255# TODO(mmoss): This is a workaround for a problem where dpkg-shlibdeps was
256# resolving deps using some of our build output shlibs (i.e.
257# out/Release/lib.target/libfreetype.so.6), and was then failing with:
258#   dpkg-shlibdeps: error: no dependency information found for ...
259# It's not clear if we ever want to look in LD_LIBRARY_PATH to resolve deps,
260# but it seems that we don't currently, so this is the most expediant fix.
261SAVE_LDLP=${LD_LIBRARY_PATH:-}
262unset LD_LIBRARY_PATH
263DPKG_SHLIB_DEPS=$(dpkg-shlibdeps -O "$BUILDDIR/chrome" 2> /dev/null | \
264  sed 's/^shlibs:Depends=//')
265if [ -n "$SAVE_LDLP" ]; then
266  LD_LIBRARY_PATH=$SAVE_LDLP
267fi
268
269# Format it nicely and save it for comparison.
270# The grep -v is for a duplicate libc6 dep caused by Lucid glibc silliness.
271echo "$DPKG_SHLIB_DEPS" | sed 's/, /\n/g' | \
272  grep -v '^libc6 (>= 2.3.6-6~)$' > actual
273
274# Compare the expected dependency list to the generate list.
275BAD_DIFF=0
276diff "$SCRIPTDIR/expected_deps" actual || BAD_DIFF=1
277if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
278  echo
279  echo "ERROR: Shared library dependencies changed!"
280  echo "If this is intentional, please update:"
281  echo "chrome/installer/linux/debian/expected_deps"
282  echo
283  exit $BAD_DIFF
284fi
285rm -rf "$DUMMY_STAGING_DIR"
286
287# Additional dependencies not in the dpkg-shlibdeps output.
288# Pull a more recent version of NSS than required by runtime linking, for
289# security and stability updates in NSS.
290ADDITION_DEPS="ca-certificates, libcurl3, libnss3 (>= 3.14.3), \
291  lsb-base (>=3.2), xdg-utils (>= 1.0.2), wget"
292
293# Fix-up libnspr dependency due to renaming in Ubuntu (the old package still
294# exists, but it was moved to "universe" repository, which isn't installed by
295# default).
296DPKG_SHLIB_DEPS=$(sed \
297    's/\(libnspr4-0d ([^)]*)\), /\1 | libnspr4 (>= 4.9.5-0ubuntu0), /g' \
298    <<< $DPKG_SHLIB_DEPS)
299
300# Fix-up libudev dependency because Ubuntu 13.04 has libudev1 instead of
301# libudev0.
302DPKG_SHLIB_DEPS=$(sed 's/\(libudev0 ([^)]*)\), /\1 | libudev1 (>= 198), /g' \
303                  <<< $DPKG_SHLIB_DEPS)
304
305COMMON_DEPS="${DPKG_SHLIB_DEPS}, ${ADDITION_DEPS}"
306COMMON_PREDEPS="dpkg (>= 1.14.0)"
307
308
309# Make everything happen in the OUTPUTDIR.
310cd "${OUTPUTDIR}"
311
312case "$TARGETARCH" in
313  ia32 )
314    export ARCHITECTURE="i386"
315    stage_install_debian
316    ;;
317  x64 )
318    export ARCHITECTURE="amd64"
319    stage_install_debian
320    ;;
321  * )
322    echo
323    echo "ERROR: Don't know how to build DEBs for '$TARGETARCH'."
324    echo
325    exit 1
326    ;;
327esac
328
329do_package
330