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