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
7set -e
8if [ "$VERBOSE" ]; then
9  set -x
10fi
11set -u
12
13gen_spec() {
14  rm -f "${SPEC}"
15  # Different channels need to install to different locations so they
16  # don't conflict with each other.
17  local PACKAGE_ORIG="${PACKAGE}"
18  local PACKAGE_FILENAME="${PACKAGE}-${CHANNEL}"
19  if [ "$CHANNEL" != "stable" ]; then
20    local INSTALLDIR="${INSTALLDIR}-${CHANNEL}"
21    local PACKAGE="${PACKAGE}-${CHANNEL}"
22    local MENUNAME="${MENUNAME} (${CHANNEL})"
23  fi
24  process_template "${SCRIPTDIR}/chrome.spec.template" "${SPEC}"
25}
26
27# Setup the installation directory hierarchy in the package staging area.
28prep_staging_rpm() {
29  prep_staging_common
30  install -m 755 -d "${STAGEDIR}/etc/cron.daily"
31}
32
33# Put the package contents in the staging area.
34stage_install_rpm() {
35  # TODO(phajdan.jr): Deduplicate this and debian/build.sh .
36  # For now duplication is going to help us avoid merge conflicts
37  # as changes are frequently merged to older branches related to SxS effort.
38  local PACKAGE_ORIG="${PACKAGE}"
39  if [ "$CHANNEL" != "stable" ]; then
40    # Avoid file collisions between channels.
41    local PACKAGE="${PACKAGE}-${CHANNEL}"
42    local INSTALLDIR="${INSTALLDIR}-${CHANNEL}"
43
44    # Make it possible to distinguish between menu entries
45    # for different channels.
46    local MENUNAME="${MENUNAME} (${CHANNEL})"
47  fi
48  prep_staging_rpm
49  SHLIB_PERMS=755
50  stage_install_common
51  log_cmd echo "Staging RPM install files in '${STAGEDIR}'..."
52  process_template "${OUTPUTDIR}/installer/common/rpmrepo.cron" \
53    "${STAGEDIR}/etc/cron.daily/${PACKAGE}"
54  chmod 755 "${STAGEDIR}/etc/cron.daily/${PACKAGE}"
55}
56
57verify_package() {
58  local DEPENDS="$1"
59  local EXPECTED_DEPENDS="${TMPFILEDIR}/expected_rpm_depends"
60  local ACTUAL_DEPENDS="${TMPFILEDIR}/actual_rpm_depends"
61  local ADDITIONAL_RPM_DEPENDS="/bin/sh, \
62  rpmlib(CompressedFileNames) <= 3.0.4-1, \
63  rpmlib(FileDigests) <= 4.6.0-1, \
64  rpmlib(PayloadFilesHavePrefix) <= 4.0-1, \
65  /usr/sbin/update-alternatives"
66  if [ ${IS_OFFICIAL_BUILD} -ne 0 ]; then
67    ADDITIONAL_RPM_DEPENDS="${ADDITIONAL_RPM_DEPENDS}, \
68      rpmlib(PayloadIsXz) <= 5.2-1"
69  fi
70  echo "${DEPENDS}" "${ADDITIONAL_RPM_DEPENDS}" | sed 's/,/\n/g' | \
71      sed 's/^ *//' | LANG=C sort | uniq > "${EXPECTED_DEPENDS}"
72  rpm -qpR "${OUTPUTDIR}/${PKGNAME}.${ARCHITECTURE}.rpm" | LANG=C sort | uniq \
73      > "${ACTUAL_DEPENDS}"
74  BAD_DIFF=0
75  diff -u "${EXPECTED_DEPENDS}" "${ACTUAL_DEPENDS}" || BAD_DIFF=1
76  if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
77    echo
78    echo "ERROR: bad rpm dependencies!"
79    echo
80    exit $BAD_DIFF
81  fi
82}
83
84# Actually generate the package file.
85do_package() {
86  log_cmd echo "Packaging ${ARCHITECTURE}..."
87  PROVIDES="${PACKAGE}"
88  RPM_COMMON_DEPS="${OUTPUTDIR}/rpm_common.deps"
89  DEPENDS=$(cat "${RPM_COMMON_DEPS}" | tr '\n' ',')
90  gen_spec
91
92  # Create temporary rpmbuild dirs.
93  mkdir -p "$RPMBUILD_DIR/BUILD"
94  mkdir -p "$RPMBUILD_DIR/RPMS"
95
96  if [ ${IS_OFFICIAL_BUILD} -ne 0 ]; then
97    local COMPRESSION_OPT="_binary_payload w9.xzdio"
98  else
99    local COMPRESSION_OPT="_binary_payload w0.gzdio"
100  fi
101
102  # '__os_install_post ${nil}' disables a bunch of automatic post-processing
103  # (brp-compress, etc.), which by default appears to only be enabled on 32-bit,
104  # and which doesn't gain us anything since we already explicitly do all the
105  # compression, symbol stripping, etc. that we want.
106  log_cmd fakeroot rpmbuild -bb --target="$ARCHITECTURE" --rmspec \
107    --define "_topdir $RPMBUILD_DIR" \
108    --define "${COMPRESSION_OPT}" \
109    --define "__os_install_post  %{nil}" \
110    --define "_build_id_links none" \
111    "${SPEC}"
112  PKGNAME="${PACKAGE}-${CHANNEL}-${VERSION}-${PACKAGE_RELEASE}"
113  mv "$RPMBUILD_DIR/RPMS/$ARCHITECTURE/${PKGNAME}.${ARCHITECTURE}.rpm" \
114     "${OUTPUTDIR}"
115  # Make sure the package is world-readable, otherwise it causes problems when
116  # copied to share drive.
117  chmod a+r "${OUTPUTDIR}/${PKGNAME}.${ARCHITECTURE}.rpm"
118
119  verify_package "$DEPENDS"
120}
121
122# Remove temporary files and unwanted packaging output.
123cleanup() {
124  rm -rf "${STAGEDIR}"
125  rm -rf "${TMPFILEDIR}"
126  rm -rf "${RPMBUILD_DIR}"
127}
128
129usage() {
130  echo "usage: $(basename $0) [-a target_arch] -c channel -d branding"
131  echo "                      [-f] [-o 'dir'] -t target_os"
132  echo "-a arch     rpm package architecture"
133  echo "-c channel  the package channel (unstable, beta, stable)"
134  echo "-d brand    either chromium or google_chrome"
135  echo "-f          indicates that this is an official build"
136  echo "-h          this help message"
137  echo "-o dir      package output directory [${OUTPUTDIR}]"
138  echo "-t platform target platform"
139}
140
141# Check that the channel name is one of the allowable ones.
142verify_channel() {
143  case $CHANNEL in
144    stable )
145      CHANNEL=stable
146      ;;
147    unstable|dev|alpha )
148      CHANNEL=unstable
149      ;;
150    testing|beta )
151      CHANNEL=beta
152      ;;
153    * )
154      echo
155      echo "ERROR: '$CHANNEL' is not a valid channel type."
156      echo
157      exit 1
158      ;;
159  esac
160}
161
162process_opts() {
163  while getopts ":a:b:c:d:fho:t:" OPTNAME
164  do
165    case $OPTNAME in
166      a )
167        ARCHITECTURE="$OPTARG"
168        ;;
169      c )
170        CHANNEL="$OPTARG"
171        verify_channel
172        ;;
173      d )
174        BRANDING="$OPTARG"
175        ;;
176      f )
177        IS_OFFICIAL_BUILD=1
178        ;;
179      h )
180        usage
181        exit 0
182        ;;
183      o )
184        OUTPUTDIR=$(readlink -f "${OPTARG}")
185        mkdir -p "${OUTPUTDIR}"
186        ;;
187      t )
188        TARGET_OS="$OPTARG"
189        ;;
190     \: )
191        echo "'-$OPTARG' needs an argument."
192        usage
193        exit 1
194        ;;
195      * )
196        echo "invalid command-line option: $OPTARG"
197        usage
198        exit 1
199        ;;
200    esac
201  done
202}
203
204#=========
205# MAIN
206#=========
207
208SCRIPTDIR=$(readlink -f "$(dirname "$0")")
209OUTPUTDIR="${PWD}"
210
211# call cleanup() on exit
212trap cleanup 0
213process_opts "$@"
214export ARCHITECTURE="${ARCHITECTURE}"
215IS_OFFICIAL_BUILD=${IS_OFFICIAL_BUILD:=0}
216
217STAGEDIR="${OUTPUTDIR}/rpm-staging-${CHANNEL}"
218mkdir -p "${STAGEDIR}"
219TMPFILEDIR="${OUTPUTDIR}/rpm-tmp-${CHANNEL}"
220mkdir -p "${TMPFILEDIR}"
221RPMBUILD_DIR="${OUTPUTDIR}/rpm-build-${CHANNEL}"
222mkdir -p "${RPMBUILD_DIR}"
223SPEC="${TMPFILEDIR}/chrome.spec"
224
225source ${OUTPUTDIR}/installer/common/installer.include
226
227get_version_info
228
229if [ "$BRANDING" = "google_chrome" ]; then
230  source "${OUTPUTDIR}/installer/common/google-chrome.info"
231else
232  source "${OUTPUTDIR}/installer/common/chromium-browser.info"
233fi
234eval $(sed -e "s/^\([^=]\+\)=\(.*\)$/export \1='\2'/" \
235  "${OUTPUTDIR}/installer/theme/BRANDING")
236
237REPOCONFIG="http://dl.google.com/linux/${PACKAGE#google-}/rpm/stable"
238verify_channel
239export USR_BIN_SYMLINK_NAME="${PACKAGE}-${CHANNEL}"
240
241stage_install_rpm
242do_package
243