Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 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" = "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. |
| 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 | # 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. |
| 60 | do_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}, \ |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 127 | libnss3.so(NSS_3.14.3)${PKG_ARCH}, \ |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 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}" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 148 | PKGNAME="${PACKAGE}-${CHANNEL}-${VERSION}-${PACKAGE_RELEASE}" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 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. |
| 158 | cleanup() { |
| 159 | rm -rf "${STAGEDIR}" |
| 160 | rm -rf "${TMPFILEDIR}" |
| 161 | } |
| 162 | |
| 163 | usage() { |
| 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. |
| 174 | verify_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 | |
| 205 | process_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 | |
| 245 | SCRIPTDIR=$(readlink -f "$(dirname "$0")") |
| 246 | OUTPUTDIR="${PWD}" |
| 247 | STAGEDIR=$(mktemp -d -t rpm.build.XXXXXX) || exit 1 |
| 248 | TMPFILEDIR=$(mktemp -d -t rpm.tmp.XXXXXX) || exit 1 |
| 249 | CHANNEL="trunk" |
| 250 | # Default target architecture to same as build host. |
| 251 | if [ "$(uname -m)" = "x86_64" ]; then |
| 252 | TARGETARCH="x64" |
| 253 | else |
| 254 | TARGETARCH="ia32" |
| 255 | fi |
| 256 | SPEC="${TMPFILEDIR}/chrome.spec" |
| 257 | |
| 258 | # call cleanup() on exit |
| 259 | trap cleanup 0 |
| 260 | process_opts "$@" |
| 261 | if [ ! "$BUILDDIR" ]; then |
| 262 | BUILDDIR=$(readlink -f "${SCRIPTDIR}/../../../../../out/Release") |
| 263 | fi |
| 264 | |
| 265 | source ${BUILDDIR}/installer/common/installer.include |
| 266 | |
| 267 | get_version_info |
| 268 | |
| 269 | if [ "$CHROMIUM_BUILD" = "_google_chrome" ]; then |
| 270 | source "${BUILDDIR}/installer/common/google-chrome.info" |
| 271 | else |
| 272 | source "${BUILDDIR}/installer/common/chromium-browser.info" |
| 273 | fi |
| 274 | eval $(sed -e "s/^\([^=]\+\)=\(.*\)$/export \1='\2'/" \ |
| 275 | "${BUILDDIR}/installer/theme/BRANDING") |
| 276 | |
| 277 | REPOCONFIG="http://dl.google.com/linux/${PACKAGE#google-}/rpm/stable" |
| 278 | verify_channel |
| 279 | |
| 280 | # Make everything happen in the OUTPUTDIR. |
| 281 | cd "${OUTPUTDIR}" |
| 282 | |
| 283 | case "$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 | ;; |
| 298 | esac |
| 299 | |
| 300 | do_package |