build.sh revision bb1529ce867d8845a77ec7cdf3e3003ef1771a40
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
16gen_spec() {
17  rm -f "${SPEC}"
18  # Trunk packages need to install to a custom path so they don't conflict with
19  # release channel packages.
20  local PACKAGE_FILENAME="${PACKAGE}"
21  if [ "$CHANNEL" = "trunk" ] || [ "$CHANNEL" = "asan" ]; then
22    local INSTALLDIR="${INSTALLDIR}-${CHANNEL}"
23    PACKAGE_FILENAME="${PACKAGE}-${CHANNEL}"
24    local MENUNAME="${MENUNAME} (${CHANNEL})"
25  fi
26  process_template "${SCRIPTDIR}/chrome.spec.template" "${SPEC}"
27}
28
29# Setup the installation directory hierachy in the package staging area.
30prep_staging_rpm() {
31  prep_staging_common
32  install -m 755 -d "${STAGEDIR}/etc/cron.daily"
33}
34
35# Put the package contents in the staging area.
36stage_install_rpm() {
37  # Trunk packages need to install to a custom path and with custom filenames
38  # (e.g. not /usr/bin/google-chrome) so they don't conflict with release
39  # channel packages.
40  if [ "$CHANNEL" = "trunk" ] || [ "$CHANNEL" = "asan" ]; then
41    local PACKAGE="${PACKAGE}-${CHANNEL}"
42    local INSTALLDIR="${INSTALLDIR}-${CHANNEL}"
43    # This would ideally be compiled into the app, but that's a bit too
44    # intrusive of a change for these limited use channels, so we'll just hack
45    # it into the wrapper script. The user can still override since it seems to
46    # work to specify --user-data-dir multiple times on the command line, with
47    # the last occurrence winning.
48    local DEFAULT_FLAGS="--user-data-dir=\"\${HOME}/.config/${PACKAGE}\""
49    local MENUNAME="${MENUNAME} (${CHANNEL})"
50  fi
51  prep_staging_rpm
52  stage_install_common
53  echo "Staging RPM install files in '${STAGEDIR}'..."
54  process_template "${BUILDDIR}/installer/common/rpmrepo.cron" \
55    "${STAGEDIR}/etc/cron.daily/${PACKAGE}"
56  chmod 755 "${STAGEDIR}/etc/cron.daily/${PACKAGE}"
57}
58
59# Actually generate the package file.
60do_package() {
61  echo "Packaging ${ARCHITECTURE}..."
62  PROVIDES="${PACKAGE}"
63  local REPS="$REPLACES"
64  REPLACES=""
65  for rep in $REPS; do
66    if [ -z "$REPLACES" ]; then
67      REPLACES="$PACKAGE-$rep"
68    else
69      REPLACES="$REPLACES $PACKAGE-$rep"
70    fi
71  done
72
73  # The symbols in libX11.so are not versioned, so when a newer version has new
74  # symbols like _XGetRequest, RPM's find-requires tool does not detect it, and
75  # there is no way to specify a libX11.so version number to prevent
76  # installation on affected distros like OpenSUSE 12.1 and Fedora 16.
77  # Thus there has to be distro-specific conflict here.
78  # TODO(thestig) Remove these in the future when other requirements prevent
79  # installation on affected distros.
80  ADDITIONAL_CONFLICTS="xorg-x11-libX11 < 7.6_1 libX11 < 1.4.99"
81  REPLACES="$REPLACES $ADDITIONAL_CONFLICTS"
82
83  # If we specify a dependecy of foo.so below, we would depend on both the
84  # 32 and 64-bit versions on a 64-bit machine. The current version of RPM
85  # we use is too old and doesn't provide %{_isa}, so we do this manually.
86  if [ "$ARCHITECTURE" = "x86_64" ] ; then
87    local EMPTY_VERSION="()"
88    local PKG_ARCH="(64bit)"
89  elif [ "$ARCHITECTURE" = "i386" ] ; then
90    local EMPTY_VERSION=""
91    local PKG_ARCH=""
92  fi
93
94  # Use find-requires script to make sure the dependencies are complete
95  # (especially libc and libstdc++ versions). Filter out udev to avoid
96  # libudev.so.0 vs. libudev.so.1 mismatches.
97  DETECTED_DEPENDS="$(echo "${BUILDDIR}/chrome" | /usr/lib/rpm/find-requires |
98      grep -v udev)"
99
100  # Compare the expected dependency list to the generated list.
101  BAD_DIFF=0
102  diff "$SCRIPTDIR/expected_deps_$ARCHITECTURE" \
103      <(echo "${DETECTED_DEPENDS}") || BAD_DIFF=1
104  if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
105    echo
106    echo "ERROR: Shared library dependencies changed!"
107    echo "If this is intentional, please update:"
108    echo "chrome/installer/linux/rpm/expected_deps_i686"
109    echo "chrome/installer/linux/rpm/expected_deps_x86_64"
110    echo
111    exit $BAD_DIFF
112  fi
113
114  # libgdk_pixbuf is added in LSB 3.2 and no longer explicitly required.
115  # libcairo, libpangocairo, libasound are in LSB 4. and no longer explicitly
116  # required.
117  # xdg-utils is still optional in LSB 4.0.
118  # nss (bundled) is optional in LSB 4.0.
119  #
120  # We want to depend on the system SSL certs so wget can upload crash reports
121  # securely, but there's no common capability between the distros. Bugs filed:
122  # https://qa.mandriva.com/show_bug.cgi?id=55714
123  # https://bugzilla.redhat.com/show_bug.cgi?id=538158
124  # https://bugzilla.novell.com/show_bug.cgi?id=556248
125  DEPENDS="lsb >= 4.0, \
126  libcurl.so.4${EMPTY_VERSION}${PKG_ARCH}, \
127  libnss3.so(NSS_3.14.3)${PKG_ARCH}, \
128  wget, \
129  xdg-utils, \
130  zlib, \
131  $(echo "${DETECTED_DEPENDS}" | tr '\n' ',')"
132  gen_spec
133
134  # Create temporary rpmbuild dirs.
135  RPMBUILD_DIR=$(mktemp -d -t rpmbuild.XXXXXX) || exit 1
136  mkdir -p "$RPMBUILD_DIR/BUILD"
137  mkdir -p "$RPMBUILD_DIR/RPMS"
138
139  # '__os_install_post ${nil}' disables a bunch of automatic post-processing
140  # (brp-compress, etc.), which by default appears to only be enabled on 32-bit,
141  # and which doesn't gain us anything since we already explicitly do all the
142  # compression, symbol stripping, etc. that we want.
143  fakeroot rpmbuild -bb --target="$ARCHITECTURE" --rmspec \
144    --define "_topdir $RPMBUILD_DIR" \
145    --define "_binary_payload w9.bzdio" \
146    --define "__os_install_post  %{nil}" \
147    "${SPEC}"
148  PKGNAME="${PACKAGE}-${CHANNEL}-${VERSION}-${PACKAGE_RELEASE}"
149  mv "$RPMBUILD_DIR/RPMS/$ARCHITECTURE/${PKGNAME}.${ARCHITECTURE}.rpm" \
150     "${OUTPUTDIR}"
151  # Make sure the package is world-readable, otherwise it causes problems when
152  # copied to share drive.
153  chmod a+r "${OUTPUTDIR}/${PKGNAME}.$ARCHITECTURE.rpm"
154  rm -rf "$RPMBUILD_DIR"
155}
156
157# Remove temporary files and unwanted packaging output.
158cleanup() {
159  rm -rf "${STAGEDIR}"
160  rm -rf "${TMPFILEDIR}"
161}
162
163usage() {
164  echo "usage: $(basename $0) [-c channel] [-a target_arch] [-o 'dir']"
165  echo "                      [-b 'dir']"
166  echo "-c channel the package channel (trunk, asan, unstable, beta, stable)"
167  echo "-a arch    package architecture (ia32 or x64)"
168  echo "-o dir     package output directory [${OUTPUTDIR}]"
169  echo "-b dir     build input directory    [${BUILDDIR}]"
170  echo "-h         this help message"
171}
172
173# Check that the channel name is one of the allowable ones.
174verify_channel() {
175  case $CHANNEL in
176    stable )
177      CHANNEL=stable
178      REPLACES="unstable beta"
179      ;;
180    unstable|dev|alpha )
181      CHANNEL=unstable
182      REPLACES="stable beta"
183      ;;
184    testing|beta )
185      CHANNEL=beta
186      REPLACES="unstable stable"
187      ;;
188    trunk|asan )
189      # This is a special package, mostly for development testing, so don't make
190      # it replace any installed release packages.
191      REPLACES="dummy"
192      # Setting this to empty will prevent it from updating any existing configs
193      # from release packages.
194      REPOCONFIG=""
195      ;;
196    * )
197      echo
198      echo "ERROR: '$CHANNEL' is not a valid channel type."
199      echo
200      exit 1
201      ;;
202  esac
203}
204
205process_opts() {
206  while getopts ":o:b:c:a:h" OPTNAME
207  do
208    case $OPTNAME in
209      o )
210        OUTPUTDIR=$(readlink -f "${OPTARG}")
211        mkdir -p "${OUTPUTDIR}"
212        ;;
213      b )
214        BUILDDIR=$(readlink -f "${OPTARG}")
215        ;;
216      c )
217        CHANNEL="$OPTARG"
218        verify_channel
219        ;;
220      a )
221        TARGETARCH="$OPTARG"
222        ;;
223      h )
224        usage
225        exit 0
226        ;;
227      \: )
228        echo "'-$OPTARG' needs an argument."
229        usage
230        exit 1
231        ;;
232      * )
233        echo "invalid command-line option: $OPTARG"
234        usage
235        exit 1
236        ;;
237    esac
238  done
239}
240
241#=========
242# MAIN
243#=========
244
245SCRIPTDIR=$(readlink -f "$(dirname "$0")")
246OUTPUTDIR="${PWD}"
247STAGEDIR=$(mktemp -d -t rpm.build.XXXXXX) || exit 1
248TMPFILEDIR=$(mktemp -d -t rpm.tmp.XXXXXX) || exit 1
249CHANNEL="trunk"
250# Default target architecture to same as build host.
251if [ "$(uname -m)" = "x86_64" ]; then
252  TARGETARCH="x64"
253else
254  TARGETARCH="ia32"
255fi
256SPEC="${TMPFILEDIR}/chrome.spec"
257
258# call cleanup() on exit
259trap cleanup 0
260process_opts "$@"
261if [ ! "$BUILDDIR" ]; then
262  BUILDDIR=$(readlink -f "${SCRIPTDIR}/../../../../../out/Release")
263fi
264
265source ${BUILDDIR}/installer/common/installer.include
266
267get_version_info
268
269if [ "$CHROMIUM_BUILD" = "_google_chrome" ]; then
270  source "${BUILDDIR}/installer/common/google-chrome.info"
271else
272  source "${BUILDDIR}/installer/common/chromium-browser.info"
273fi
274eval $(sed -e "s/^\([^=]\+\)=\(.*\)$/export \1='\2'/" \
275  "${BUILDDIR}/installer/theme/BRANDING")
276
277REPOCONFIG="http://dl.google.com/linux/${PACKAGE#google-}/rpm/stable"
278verify_channel
279
280# Make everything happen in the OUTPUTDIR.
281cd "${OUTPUTDIR}"
282
283case "$TARGETARCH" in
284  ia32 )
285    export ARCHITECTURE="i386"
286    stage_install_rpm
287    ;;
288  x64 )
289    export ARCHITECTURE="x86_64"
290    stage_install_rpm
291    ;;
292  * )
293    echo
294    echo "ERROR: Don't know how to build RPMs for '$TARGETARCH'."
295    echo
296    exit 1
297    ;;
298esac
299
300do_package
301