build.sh revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
18483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita#!/bin/bash
28483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita#
38483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# Copyright (c) 2012 The Chromium Authors. All rights reserved.
48483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# Use of this source code is governed by a BSD-style license that can be
58483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# found in the LICENSE file.
68483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita
78483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# TODO(mmoss) This currently only works with official builds, since non-official
88483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# builds don't add the "${BUILDDIR}/installer/" files needed for packaging.
98483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita
108483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitaset -e
118483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitaif [ "$VERBOSE" ]; then
128483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  set -x
138483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitafi
148483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitaset -u
158483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita
168483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# Create the Debian changelog file needed by dpkg-gencontrol. This just adds a
178483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# placeholder change, indicating it is the result of an automatic build.
188483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# TODO(mmoss) Release packages should create something meaningful for a
198483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# changelog, but simply grabbing the actual 'svn log' is way too verbose. Do we
208483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# have any type of "significant/visible changes" log that we could use for this?
218483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitagen_changelog() {
228483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  rm -f "${DEB_CHANGELOG}"
238483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  process_template "${SCRIPTDIR}/changelog.template" "${DEB_CHANGELOG}"
248483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  debchange -a --nomultimaint -m --changelog "${DEB_CHANGELOG}" \
258483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    "Release Notes: ${RELEASENOTES}"
268483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  # Trunk packages need to install to a custom path and with custom filenames
278483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  # (e.g. not /usr/bin/google-chrome) so they don't conflict with release
288483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  # channel packages.
298483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  if [ "$CHANNEL" = "trunk" ] || [ "$CHANNEL" = "asan" ]; then
308483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    local PACKAGE="${PACKAGE}-${CHANNEL}"
318483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  fi
328483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  GZLOG="${STAGEDIR}/usr/share/doc/${PACKAGE}/changelog.gz"
338483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  mkdir -p "$(dirname "${GZLOG}")"
348483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  gzip -9 -c "${DEB_CHANGELOG}" > "${GZLOG}"
358483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  chmod 644 "${GZLOG}"
368483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita}
378483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita
388483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# Create the Debian control file needed by dpkg-deb.
398483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitagen_control() {
408483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  dpkg-gencontrol -v"${VERSIONFULL}" -c"${DEB_CONTROL}" -l"${DEB_CHANGELOG}" \
418483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  -f"${DEB_FILES}" -p"${PACKAGE}-${CHANNEL}" -P"${STAGEDIR}" \
428483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  -O > "${STAGEDIR}/DEBIAN/control"
438483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  rm -f "${DEB_CONTROL}"
448483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita}
458483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita
468483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# Setup the installation directory hierachy in the package staging area.
478483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitaprep_staging_debian() {
488483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  prep_staging_common
498483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  install -m 755 -d "${STAGEDIR}/DEBIAN" \
508483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    "${STAGEDIR}/etc/cron.daily" \
518483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    "${STAGEDIR}/usr/share/menu" \
528483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    "${STAGEDIR}/usr/share/doc/${PACKAGE}"
538483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita}
548483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita
558483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# Put the package contents in the staging area.
568483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitastage_install_debian() {
578483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  # Trunk packages need to install to a custom path and with custom filenames
588483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  # (e.g. not /usr/bin/google-chrome) so they don't conflict with release
598483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  # channel packages.
608483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  if [ "$CHANNEL" = "trunk" ] || [ "$CHANNEL" = "asan" ]; then
618483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    local PACKAGE="${PACKAGE}-${CHANNEL}"
628483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    local INSTALLDIR="${INSTALLDIR}-${CHANNEL}"
638483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    # This would ideally be compiled into the app, but that's a bit too
648483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    # intrusive of a change for these limited use channels, so we'll just hack
658483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    # it into the wrapper script. The user can still override since it seems to
668483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    # work to specify --user-data-dir multiple times on the command line, with
678483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    # the last occurrence winning.
688483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    local DEFAULT_FLAGS="--user-data-dir=\"\${HOME}/.config/${PACKAGE}\""
698483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    local MENUNAME="${MENUNAME} (${CHANNEL})"
708483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  fi
718483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  prep_staging_debian
728483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  stage_install_common
738483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  echo "Staging Debian install files in '${STAGEDIR}'..."
748483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/cron"
758483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  process_template "${BUILDDIR}/installer/common/repo.cron" \
768483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita      "${STAGEDIR}/${INSTALLDIR}/cron/${PACKAGE}"
778483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  chmod 755 "${STAGEDIR}/${INSTALLDIR}/cron/${PACKAGE}"
788483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  pushd "${STAGEDIR}/etc/cron.daily/"
798483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  ln -snf "${INSTALLDIR}/cron/${PACKAGE}" "${PACKAGE}"
808483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  popd
818483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  process_template "${BUILDDIR}/installer/debian/debian.menu" \
828483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    "${STAGEDIR}/usr/share/menu/${PACKAGE}.menu"
838483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  chmod 644 "${STAGEDIR}/usr/share/menu/${PACKAGE}.menu"
848483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  process_template "${BUILDDIR}/installer/debian/postinst" \
858483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    "${STAGEDIR}/DEBIAN/postinst"
868483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  chmod 755 "${STAGEDIR}/DEBIAN/postinst"
878483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  process_template "${BUILDDIR}/installer/debian/prerm" \
888483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    "${STAGEDIR}/DEBIAN/prerm"
898483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  chmod 755 "${STAGEDIR}/DEBIAN/prerm"
908483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  process_template "${BUILDDIR}/installer/debian/postrm" \
918483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    "${STAGEDIR}/DEBIAN/postrm"
928483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  chmod 755 "${STAGEDIR}/DEBIAN/postrm"
938483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita}
948483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita
958483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita# Actually generate the package file.
968483326704eff3b6a5fcce3f36d857a9779a4dd2fmalitado_package() {
978483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  echo "Packaging ${ARCHITECTURE}..."
988483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  PREDEPENDS="$COMMON_PREDEPS"
998483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  DEPENDS="${COMMON_DEPS}"
1008483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  # Trunk is a special package, mostly for development testing, so don't make
1018483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  # it replace any installed release packages.
1028483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  if [ "$CHANNEL" != "trunk" ] && [ "$CHANNEL" != "asan" ]; then
1038483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    REPLACES="${PACKAGE}"
1048483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    CONFLICTS="${PACKAGE}"
1058483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    PROVIDES="${PACKAGE}, www-browser"
1068483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  fi
1078483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  gen_changelog
1088483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  process_template "${SCRIPTDIR}/control.template" "${DEB_CONTROL}"
1098483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  export DEB_HOST_ARCH="${ARCHITECTURE}"
1108483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  if [ -f "${DEB_CONTROL}" ]; then
1118483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita    gen_control
1128483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  fi
1138483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita  fakeroot dpkg-deb -Zlzma -b "${STAGEDIR}" .
1148483326704eff3b6a5fcce3f36d857a9779a4dd2fmalita}
115
116# Remove temporary files and unwanted packaging output.
117cleanup() {
118  echo "Cleaning..."
119  rm -rf "${STAGEDIR}"
120  rm -rf "${TMPFILEDIR}"
121}
122
123usage() {
124  echo "usage: $(basename $0) [-c channel] [-a target_arch] [-o 'dir'] "
125  echo "                      [-b 'dir']"
126  echo "-c channel the package channel (trunk, asan, unstable, beta, stable)"
127  echo "-a arch    package architecture (ia32 or x64)"
128  echo "-o dir     package output directory [${OUTPUTDIR}]"
129  echo "-b dir     build input directory    [${BUILDDIR}]"
130  echo "-h         this help message"
131}
132
133# Check that the channel name is one of the allowable ones.
134verify_channel() {
135  case $CHANNEL in
136    stable )
137      CHANNEL=stable
138      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Stable%20updates"
139      ;;
140    unstable|dev|alpha )
141      CHANNEL=unstable
142      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Dev%20updates"
143      ;;
144    testing|beta )
145      CHANNEL=beta
146      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Beta%20updates"
147      ;;
148    trunk|asan )
149      # Setting this to empty will prevent it from updating any existing configs
150      # from release packages.
151      REPOCONFIG=""
152      RELEASENOTES="http://googlechromereleases.blogspot.com/"
153      ;;
154    * )
155      echo
156      echo "ERROR: '$CHANNEL' is not a valid channel type."
157      echo
158      exit 1
159      ;;
160  esac
161}
162
163process_opts() {
164  while getopts ":o:b:c:a:h" OPTNAME
165  do
166    case $OPTNAME in
167      o )
168        OUTPUTDIR=$(readlink -f "${OPTARG}")
169        mkdir -p "${OUTPUTDIR}"
170        ;;
171      b )
172        BUILDDIR=$(readlink -f "${OPTARG}")
173        ;;
174      c )
175        CHANNEL="$OPTARG"
176        ;;
177      a )
178        TARGETARCH="$OPTARG"
179        ;;
180      h )
181        usage
182        exit 0
183        ;;
184      \: )
185        echo "'-$OPTARG' needs an argument."
186        usage
187        exit 1
188        ;;
189      * )
190        echo "invalid command-line option: $OPTARG"
191        usage
192        exit 1
193        ;;
194    esac
195  done
196}
197
198#=========
199# MAIN
200#=========
201
202SCRIPTDIR=$(readlink -f "$(dirname "$0")")
203OUTPUTDIR="${PWD}"
204STAGEDIR=$(mktemp -d -t deb.build.XXXXXX) || exit 1
205TMPFILEDIR=$(mktemp -d -t deb.tmp.XXXXXX) || exit 1
206DEB_CHANGELOG="${TMPFILEDIR}/changelog"
207DEB_FILES="${TMPFILEDIR}/files"
208DEB_CONTROL="${TMPFILEDIR}/control"
209CHANNEL="trunk"
210# Default target architecture to same as build host.
211if [ "$(uname -m)" = "x86_64" ]; then
212  TARGETARCH="x64"
213else
214  TARGETARCH="ia32"
215fi
216
217# call cleanup() on exit
218trap cleanup 0
219process_opts "$@"
220if [ ! "$BUILDDIR" ]; then
221  BUILDDIR=$(readlink -f "${SCRIPTDIR}/../../../../../out/Release")
222fi
223
224source ${BUILDDIR}/installer/common/installer.include
225
226get_version_info
227VERSIONFULL="${VERSION}-${PACKAGE_RELEASE}"
228
229if [ "$CHROMIUM_BUILD" = "_google_chrome" ]; then
230  source "${BUILDDIR}/installer/common/google-chrome.info"
231else
232  source "${BUILDDIR}/installer/common/chromium-browser.info"
233fi
234eval $(sed -e "s/^\([^=]\+\)=\(.*\)$/export \1='\2'/" \
235  "${BUILDDIR}/installer/theme/BRANDING")
236
237REPOCONFIG="deb http://dl.google.com/linux/${PACKAGE#google-}/deb/ stable main"
238verify_channel
239
240# Some Debian packaging tools want these set.
241export DEBFULLNAME="${MAINTNAME}"
242export DEBEMAIL="${MAINTMAIL}"
243
244# We'd like to eliminate more of these deps by relying on the 'lsb' package, but
245# that brings in tons of unnecessary stuff, like an mta and rpm. Until that full
246# 'lsb' package is installed by default on DEB distros, we'll have to stick with
247# the LSB sub-packages, to avoid pulling in all that stuff that's not installed
248# by default.
249
250# Need a dummy debian/control file for dpkg-shlibdeps.
251DUMMY_STAGING_DIR="${TMPFILEDIR}/dummy_staging"
252mkdir "$DUMMY_STAGING_DIR"
253cd "$DUMMY_STAGING_DIR"
254mkdir debian
255touch debian/control
256
257# Generate the dependencies,
258# TODO(mmoss): This is a workaround for a problem where dpkg-shlibdeps was
259# resolving deps using some of our build output shlibs (i.e.
260# out/Release/lib.target/libfreetype.so.6), and was then failing with:
261#   dpkg-shlibdeps: error: no dependency information found for ...
262# It's not clear if we ever want to look in LD_LIBRARY_PATH to resolve deps,
263# but it seems that we don't currently, so this is the most expediant fix.
264SAVE_LDLP=${LD_LIBRARY_PATH:-}
265unset LD_LIBRARY_PATH
266DPKG_SHLIB_DEPS=$(dpkg-shlibdeps -O "$BUILDDIR/chrome" 2> /dev/null | \
267  sed 's/^shlibs:Depends=//')
268if [ -n "$SAVE_LDLP" ]; then
269  LD_LIBRARY_PATH=$SAVE_LDLP
270fi
271
272# Format it nicely and save it for comparison.
273# The grep -v is for a duplicate libc6 dep caused by Lucid glibc silliness.
274echo "$DPKG_SHLIB_DEPS" | sed 's/, /\n/g' | \
275  grep -v '^libc6 (>= 2.3.6-6~)$' > actual
276
277# Compare the expected dependency list to the generate list.
278BAD_DIFF=0
279diff "$SCRIPTDIR/expected_deps" actual || BAD_DIFF=1
280if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
281  echo
282  echo "ERROR: Shared library dependencies changed!"
283  echo "If this is intentional, please update:"
284  echo "chrome/installer/linux/debian/expected_deps"
285  echo
286  exit $BAD_DIFF
287fi
288rm -rf "$DUMMY_STAGING_DIR"
289
290# Additional dependencies not in the dpkg-shlibdeps output.
291ADDITION_DEPS="ca-certificates, libcurl3, \
292  lsb-base (>=3.2), xdg-utils (>= 1.0.2), wget"
293
294# Fix-up libnspr dependency due to renaming in Ubuntu (the old package still
295# exists, but it was moved to "universe" repository, which isn't installed by
296# default).
297DPKG_SHLIB_DEPS=$(sed \
298    's/\(libnspr4-0d ([^)]*)\), /\1 | libnspr4 (>= 4.8.7-0ubuntu1), /g' \
299    <<< $DPKG_SHLIB_DEPS)
300
301# Fix-up libudev dependency because Ubuntu 13.04 has libudev1 instead of
302# libudev0.
303DPKG_SHLIB_DEPS=$(sed 's/\(libudev0 ([^)]*)\), /\1 | libudev1 (>= 198), /g' \
304                  <<< $DPKG_SHLIB_DEPS)
305
306COMMON_DEPS="${DPKG_SHLIB_DEPS}, ${ADDITION_DEPS}"
307COMMON_PREDEPS="dpkg (>= 1.14.0)"
308
309
310# Make everything happen in the OUTPUTDIR.
311cd "${OUTPUTDIR}"
312
313case "$TARGETARCH" in
314  ia32 )
315    export ARCHITECTURE="i386"
316    stage_install_debian
317    ;;
318  x64 )
319    export ARCHITECTURE="amd64"
320    stage_install_debian
321    ;;
322  * )
323    echo
324    echo "ERROR: Don't know how to build DEBs for '$TARGETARCH'."
325    echo
326    exit 1
327    ;;
328esac
329
330do_package
331