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