Home | History | Annotate | Download | only in openssl
      1 #!/bin/sh
      2 #
      3 # Copyright (c) 2013 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 # Sanitize environment.
      8 set -e
      9 export LANG=C
     10 export LC_ALL=C
     11 
     12 PROGDIR=$(dirname "$0")
     13 PROGNAME=$(basename "$0")
     14 
     15 # Defaults
     16 VERBOSE=1
     17 
     18 . "$PROGDIR/openssl-chromium.config"
     19 
     20 # Print error message and exit script.
     21 # $1+: Error message.
     22 panic () {
     23   echo "ERROR: $@"
     24   exit 1
     25 }
     26 
     27 # $1: Variable name
     28 # Output: variable value.
     29 var_value () {
     30   # NOTE: Don't use 'echo' here, it is sensitive to options like -n.
     31   eval printf \"%s\\n\" \$$1
     32 }
     33 
     34 # Print a message if verbosity is sufficiently high.
     35 # $1: Verbosity threshold, only if '$VERBOSE > $1' does this print.
     36 # $2+: Message.
     37 dump_n () {
     38   local LEVEL=$1
     39   shift
     40   if [ "$VERBOSE" -gt "$LEVEL" ]; then
     41     printf "%s\n" "$@"
     42   fi
     43 }
     44 
     45 # Print a message, unless --quiet was used.
     46 dump () {
     47   dump_n 0 "$@"
     48 }
     49 
     50 # Print a message if --verbose was used.
     51 log () {
     52   dump_n 1 "$@"
     53 }
     54 
     55 # Print a message if --verbose --verbose was used.
     56 log2 () {
     57   dump_n 2 "$@"
     58 }
     59 
     60 # Run a command silently, unless --verbose is used.
     61 # More specifically:
     62 #  - By default, this runs the command but redirects its stdout/stderr
     63 #    to /dev/null to avoid printing anything.
     64 #  - If --verbose is used, this prints the command's name, and stderr
     65 #    will not be redirected.
     66 #  - If '--verbose --verbose' is used, this prints the commands and its
     67 #    complete output.
     68 # $1+: Command
     69 # Return: Command status
     70 run () {
     71   if [ "$VERBOSE" -gt 1 ]; then
     72     echo "COMMAND: $@"
     73   fi
     74   case $VERBOSE in
     75     0)
     76         "$@" > /dev/null 2>&1
     77         ;;
     78     1)
     79         "$@" > /dev/null
     80         ;;
     81     *)
     82         "$@"
     83         ;;
     84   esac
     85 }
     86 
     87 # Support cleaning up stuff when the script exits, even in case of
     88 # error.
     89 _ALL_CLEANUPS=
     90 
     91 clean_atexit () {
     92   local CLEANUPS CLEANUP
     93   CLEANUPS=$_ALL_CLEANUPS
     94   _ALL_CLEANUPS=
     95   for CLEANUP in $CLEANUPS; do
     96     ($CLEANUP)
     97   done
     98   exit $1
     99 }
    100 
    101 trap "clean_atexit 0" EXIT
    102 trap "clean_atexit \$?" HUP INT QUIT TERM
    103 
    104 # Add a cleanup function to the list of cleanups that will be run when
    105 # the script exits.
    106 atexit () {
    107     # Prepend to ensure that the cleanup steps are performed in reverse
    108     # order or registration.
    109     _ALL_CLEANUPS="$* $_ALL_CLEANUPS"
    110 }
    111 
    112 # Support code to write into a gyp file
    113 _GYP_MARGIN=""
    114 
    115 # Increment margin of gyp printer.
    116 incr_gyp_margin () {
    117   _GYP_MARGIN="$_GYP_MARGIN  "
    118 }
    119 
    120 decr_gyp_margin () {
    121   _GYP_MARGIN=$(echo "$_GYP_MARGIN" | cut --bytes=3-)
    122 }
    123 
    124 print_gyp () {
    125   printf "%s%s\n" "$_GYP_MARGIN" "$@"
    126 }
    127 
    128 # This prints a list variable definition in a gyp file.
    129 # $1: Variable name (e.g. 'openssl_common_defines')
    130 # $2+: List items (e.g. defines)
    131 print_gyp_variable () {
    132   local VARNAME=$1
    133   local VALUE
    134   shift
    135   print_gyp "'$VARNAME': ["
    136   for VALUE; do
    137     print_gyp "  '$VALUE',"
    138   done
    139   print_gyp "],"
    140 }
    141 
    142 # Same as print_gyp_variable, but for source file lists, this
    143 # prepends openssl/ as required by the Chromium build to each item
    144 # in the list.
    145 # $1: Variable name (e.g. 'openssl_common_sources')
    146 # $2+: List items (source file names).
    147 print_gyp_source_variable () {
    148   local VARNAME=$1
    149   local VALUE
    150   shift
    151   print_gyp "'$VARNAME': ["
    152   for VALUE; do
    153     print_gyp "  'openssl/$VALUE',"
    154   done
    155   print_gyp "],"
    156 }
    157 
    158 # Print usage instructions.
    159 usage () {
    160     echo \
    161 "Usage: $PROGNAME [options]
    162 
    163 This script is used to regenerate the content of the Chromium
    164 third_party/openssl/ directory according to the configuration file
    165 named 'openssl-chromium.config'.
    166 
    167 In particular, it will perform the following steps:
    168 
    169   1) Download the Android sources from the AOSP git servers.
    170 
    171   2) Add Chromium-specific patches to the Android source tree.
    172      (they must be under patches.chromium/ in $PROGDIR).
    173 
    174   3) Download a versioned openssl package from the official OpenSSL
    175      servers, and check its MD5. The version is taken from the
    176      'openssl.version' file in the Android source tree.
    177 
    178   4) Run the Android 'import_openssl.sh' script that rebuilds all sources
    179      from a clean slate.
    180 
    181   5) Generate the 'openssl.gypi' that contains gyp-specific declarations
    182      for the library.
    183 
    184   6) Generate 64-bit compatible opensslconf.h header.
    185 
    186 Valid options are the following (defaults are in brackets):
    187 
    188   --help|-h|-?          Display this message.
    189   --aosp-git=<url>      Change git source for Android repository.
    190                         [$ANDROID_OPENSSL_GIT_SOURCE]
    191   --aosp-commit=<name>  Specify git commit or branch name [$ANDROID_OPENSSL_GIT_COMMIT]
    192   --temp-dir=<path>     Specify temporary directory, will not be cleaned.
    193                         [<random-temp-file-cleaned-on-exit>]
    194   --verbose             Increase verbosity.
    195   --quiet               Decrease verbosity.
    196 "
    197   exit 1
    198 }
    199 
    200 # Parse command-line.
    201 DO_HELP=
    202 
    203 for OPT; do
    204   OPTARG=$()
    205   case $OPT in
    206     --help|-h|-?)
    207         DO_HELP=true
    208         ;;
    209     --aosp-commit=*)
    210         ANDROID_OPENSSL_GIT_COMMIT=${OPT#--aosp-commit=}
    211         if [ -z "$ANDROID_OPENSSL_GIT_COMMIT" ]; then
    212             panic "Missing option value: $OPT"
    213         fi
    214         ;;
    215     --aosp-git=*)
    216         ANDROID_OPENSSL_GIT_SOURCE=${OPT#--aosp-git=}
    217         if [ -z "$ANDROID_OPENSSL_GIT_SOURCE" ]; then
    218             panic "Missing option value: $OPT"
    219         fi
    220         ;;
    221     --temp-dir=*)
    222         TEMP_DIR=${OPT#--temp-dir=}
    223         if [ -z "$TEMP_DIR" ]; then
    224             panic "Missing option value: $OPT"
    225         fi
    226         ;;
    227     --quiet)
    228         VERBOSE=$(( $VERBOSE - 1 ))
    229         ;;
    230     --verbose)
    231         VERBOSE=$(( $VERBOSE + 1 ))
    232         ;;
    233     -*)
    234         panic "Invalid option '$OPT', see --help for details."
    235         ;;
    236     *)
    237         panic "This script doesn't take parameters. See --help for details."
    238         ;;
    239   esac
    240 done
    241 
    242 if [ "$DO_HELP" ]; then
    243   usage
    244 fi
    245 
    246 # Create temporary directory. Ensure it's always cleaned up on exit.
    247 if [ -z "$TEMP_DIR" ]; then
    248   TEMP_DIR=$(mktemp -d)
    249   clean_tempdir () {
    250     rm -rf "$TEMP_DIR"
    251   }
    252   atexit clean_tempdir
    253   log "Temporary directory created: $TEMP_DIR"
    254 else
    255   log "Using user-provided temp directory: $TEMP_DIR"
    256 fi
    257 
    258 GIT_FLAGS=
    259 case $VERBOSE in
    260   0|1)
    261     GIT_CLONE_FLAGS="--quiet"
    262     GIT_CHECKOUT_FLAGS="--quiet"
    263     CURL_FLAGS="-s"
    264     ;;
    265   2)
    266     GIT_CLONE_FLAGS=""
    267     GIT_CHECKOUT_FLAGS=""
    268     CURL_FLAGS=""
    269     ;;
    270   *)
    271     GIT_CLONE_FLAGS="--verbose"
    272     GIT_CHECKOUT_FLAGS=""
    273     CURL_FLAGS=""
    274     ;;
    275 esac
    276 
    277 BUILD_DIR=$TEMP_DIR/build
    278 mkdir -p "$BUILD_DIR" && rm -rf "$BUILD_DIR"/*
    279 
    280 # Download the Android sources.
    281 ANDROID_SRC_DIR=$BUILD_DIR/android-openssl
    282 dump "Downloading Android sources"
    283 log "Downloading branch $ANDROID_OPENSSL_GIT_COMMIT from: $ANDROID_OPENSSL_GIT_SOURCE"
    284 (
    285   run mkdir -p $ANDROID_SRC_DIR
    286   run cd $ANDROID_SRC_DIR
    287   run git clone $GIT_CLONE_FLAGS $ANDROID_OPENSSL_GIT_SOURCE .
    288   run git checkout $GIT_CHECKOUT_FLAGS $ANDROID_OPENSSL_GIT_COMMIT
    289   run rm -rf .git
    290 )
    291 
    292 # Apply chromium-specific patches located in patches.chromium
    293 CHROMIUM_PATCHES_DIR=$PROGDIR/patches.chromium
    294 if [ ! -d "$CHROMIUM_PATCHES_DIR" ]; then
    295   dump "No Chromium-specific patches to apply."
    296 else
    297   dump "Applying Chromium-specific patches:"
    298   CHROMIUM_PATCHES=$(/bin/ls $CHROMIUM_PATCHES_DIR/*.patch 2>/dev/null)
    299   for CHROMIUM_PATCH in $CHROMIUM_PATCHES; do
    300     dump "Applying: $CHROMIUM_PATCH"
    301     (cd $ANDROID_SRC_DIR && run patch -p1) < $CHROMIUM_PATCH
    302   done
    303 fi
    304 
    305 # Get the openssl version
    306 . $ANDROID_SRC_DIR/openssl.version
    307 if [ -z "$OPENSSL_VERSION" ]; then
    308   panic "Could not find OPENSSL_VERSION definition from $ANDROID_SRC_DIR!"
    309 fi
    310 dump "Found OpenSSL version: $OPENSSL_VERSION"
    311 
    312 # Download OpenSSL package
    313 DOWNLOAD_DIR=$BUILD_DIR/download
    314 mkdir -p "$DOWNLOAD_DIR"
    315 
    316 OPENSSL_PACKAGE=openssl-$OPENSSL_VERSION.tar.gz
    317 dump "Downloading $OPENSSL_PACKAGE from $OPENSSL_TAR_SOURCE"
    318 run curl $CURL_FLAGS -o $DOWNLOAD_DIR/$OPENSSL_PACKAGE $OPENSSL_TAR_SOURCE/$OPENSSL_PACKAGE
    319 run curl $CURL_FLAGS -o $DOWNLOAD_DIR/$OPENSSL_PACKAGE.md5 $OPENSSL_TAR_SOURCE/$OPENSSL_PACKAGE.md5
    320 
    321 OPENSSL_SHA1_DOWNLOADED=$(sha1sum $DOWNLOAD_DIR/$OPENSSL_PACKAGE | cut -d" " -f1)
    322 OPENSSL_SHA1_EXPECTED=$OPENSSL_TAR_SHA1
    323 if [ "$OPENSSL_SHA1_DOWNLOADED" != "$OPENSSL_SHA1_EXPECTED" ]; then
    324   echo "ERROR: Content mismatch for downloaded OpenSSL package:"
    325   echo "       Downloaded SHA-1: $OPENSSL_SHA1_DOWNLOADED"
    326   echo "       Expected SHA-1  : $OPENSSL_SHA1_EXPECTED"
    327   exit 1
    328 fi
    329 dump "Checking content of downloaded package: ok"
    330 
    331 # The import_openssl.sh script will really remove the existing 'openssl'
    332 # directory and replace it with something completely new. This is a problem
    333 # when using subversion because this also gets rid of all .svn
    334 # subdirectories. This makes it impossible to commit the right set of
    335 # changes with "gcl commit".
    336 #
    337 # To work-around this, copy all the .svn subdirectories into a temporary
    338 # tarball, which will be extracted after the import process.
    339 #
    340 dump "Saving .svn subdirectories"
    341 SAVED_SVN_TARBALL=$BUILD_DIR/saved-svn-subdirs.tar.gz
    342 run tar czf $SAVED_SVN_TARBALL $(find . -type d -name ".svn")
    343 
    344 # Re-run the import_openssl.sh script.
    345 dump "Re-running the 'import_openssl.sh' script to reconfigure all sources."
    346 (
    347   cd $ANDROID_SRC_DIR
    348   run ./import_openssl.sh import $DOWNLOAD_DIR/$OPENSSL_PACKAGE
    349 )
    350 
    351 dump "Copying new Android sources to final location."
    352 clean_openssl_new () {
    353   rm -rf "$PROGDIR/openssl.new"
    354 }
    355 atexit clean_openssl_new
    356 
    357 run cp -rp "$ANDROID_SRC_DIR" "$PROGDIR/openssl.new"
    358 run mv "$PROGDIR/openssl" "$PROGDIR/openssl.old"
    359 run mv "$PROGDIR/openssl.new" "$PROGDIR/openssl"
    360 run rm -rf "$PROGDIR/openssl.old"
    361 
    362 dump "Restoring .svn subdirectores"
    363 run tar xzf $SAVED_SVN_TARBALL
    364 
    365 # Extract list of source files or compiler defines from openssl.config
    366 # variable definition. This assumes that the lists are in variables that
    367 # are named as <prefix><suffix> or <prefix><suffix><arch>.
    368 #
    369 # A few examples:
    370 #   get_gyp_list "FOO BAR" _SOURCES
    371 #     -> returns '$FOO_SOURCES $BAR_SOURCES'
    372 #
    373 #   get_gyp_list FOO _SOURCES_ "arm x86"
    374 #     -> returns '$FOO_SOURCES_arm $FOO_SOURCES_x86"
    375 #
    376 #   get_gyp_list "FOO BAR" _SOURCES_ "arm x86"
    377 #     -> returns '$FOO_SOURCES_arm $FOO_SOURCES_x86 $BAR_SOURCES_arm $BAR_SOURCES_x86'
    378 #
    379 # $1: list of variable prefixes
    380 # $2: variable suffix
    381 # $3: optional list of architectures.
    382 get_gyp_list () {
    383   local ALL_PREFIXES="$1"
    384   local SUFFIX="$2"
    385   local ALL_ARCHS="$3"
    386   local LIST PREFIX ARCH
    387   for PREFIX in $ALL_PREFIXES; do
    388     if [ "$ALL_ARCHS" ]; then
    389       for ARCH in $ALL_ARCHS; do
    390         LIST="$LIST $(var_value ${PREFIX}${SUFFIX}${ARCH})"
    391       done
    392     else
    393       LIST="$LIST $(var_value ${PREFIX}${SUFFIX})"
    394     fi
    395   done
    396   echo "$LIST"
    397 }
    398 
    399 generate_gyp_file () {
    400   echo "# Auto-generated file - DO NOT EDIT"
    401   echo "# To regenerate - run import_from_android.sh."
    402   echo "# See 'import_from_android.sh --help' for details."
    403 
    404   local ALL_PREFIXES="OPENSSL_CRYPTO OPENSSL_SSL"
    405   local ALL_ARCHS="arm mips x86 x86_64"
    406   local PREFIX ARCH LIST
    407 
    408   print_gyp "{"
    409   incr_gyp_margin
    410 
    411     print_gyp "'variables': {"
    412     incr_gyp_margin
    413 
    414       # First, the common sources and defines
    415       print_gyp_source_variable "openssl_common_sources" \
    416           $(get_gyp_list "$ALL_PREFIXES" _SOURCES)
    417 
    418       print_gyp_variable "openssl_common_defines" \
    419           $(get_gyp_list "$ALL_PREFIXES" _DEFINES)
    420 
    421       # Now, conditions section with add architecture-specific sub-sections.
    422       for ARCH in $ALL_ARCHS; do
    423         # Convert ARCH to gyp-specific architecture name
    424         case $ARCH in
    425           x86)
    426             GYP_ARCH=ia32
    427             ;;
    428           x86_64)
    429             GYP_ARCH=x64
    430             ;;
    431           *)
    432             GYP_ARCH=$ARCH
    433             ;;
    434         esac
    435 
    436         print_gyp_source_variable "openssl_${ARCH}_source_excludes" \
    437             $(get_gyp_list "$ALL_PREFIXES" _SOURCES_EXCLUDES_ $ARCH)
    438 
    439         print_gyp_source_variable "openssl_${ARCH}_sources" \
    440             $(get_gyp_list "$ALL_PREFIXES" _SOURCES_ $ARCH)
    441 
    442         print_gyp_variable "openssl_${ARCH}_defines" \
    443             $(get_gyp_list "$ALL_PREFIXES" _DEFINES_ $ARCH)
    444 
    445       done # for ARCH
    446 
    447     decr_gyp_margin
    448     print_gyp "}"  # variables
    449 
    450   decr_gyp_margin
    451   print_gyp "}"  # top-level dict.
    452 }
    453 
    454 dump "Generating 64-bit configuration header file."
    455 mkdir -p $PROGDIR/config/x64/openssl/
    456 sed \
    457   -e 's|^#define BN_LLONG|#undef BN_LLONG|g' \
    458   -e 's|^#define THIRTY_TWO_BIT|#undef THIRTY_TWO_BIT|g' \
    459   -e 's|^#undef SIXTY_FOUR_BIT_LONG|#define SIXTY_FOUR_BIT_LONG|g' \
    460   $PROGDIR/openssl/include/openssl/opensslconf.h \
    461   > $PROGDIR/config/x64/openssl/opensslconf.h
    462 
    463 dump "Generating .gypi file."
    464 . $ANDROID_SRC_DIR/openssl.config
    465 generate_gyp_file > $PROGDIR/openssl.gypi.new
    466 run mv $PROGDIR/openssl.gypi $PROGDIR/openssl.gypi.old
    467 run mv $PROGDIR/openssl.gypi.new $PROGDIR/openssl.gypi
    468 run rm $PROGDIR/openssl.gypi.old
    469 
    470 dump "Done."
    471