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 SVN_LIST_FILE=$BUILD_DIR/svn-subdirs 342 run find . -type d -name ".svn" > $SVN_LIST_FILE 343 SAVED_SVN_TARBALL=$BUILD_DIR/saved-svn-subdirs.tar.gz 344 run tar czf $SAVED_SVN_TARBALL -T $SVN_LIST_FILE 345 346 # Re-run the import_openssl.sh script. 347 dump "Re-running the 'import_openssl.sh' script to reconfigure all sources." 348 ( 349 cd $ANDROID_SRC_DIR 350 run ./import_openssl.sh import $DOWNLOAD_DIR/$OPENSSL_PACKAGE 351 ) 352 353 dump "Copying new Android sources to final location." 354 clean_openssl_new () { 355 rm -rf "$PROGDIR/openssl.new" 356 } 357 atexit clean_openssl_new 358 359 run cp -rp "$ANDROID_SRC_DIR" "$PROGDIR/openssl.new" 360 run mv "$PROGDIR/openssl" "$PROGDIR/openssl.old" 361 run mv "$PROGDIR/openssl.new" "$PROGDIR/openssl" 362 run rm -rf "$PROGDIR/openssl.old" 363 364 dump "Restoring .svn subdirectores" 365 run tar xzf $SAVED_SVN_TARBALL 366 367 # Extract list of source files or compiler defines from openssl.config 368 # variable definition. This assumes that the lists are in variables that 369 # are named as <prefix><suffix> or <prefix><suffix><arch>. 370 # 371 # A few examples: 372 # get_gyp_list "FOO BAR" _SOURCES 373 # -> returns '$FOO_SOURCES $BAR_SOURCES' 374 # 375 # get_gyp_list FOO _SOURCES_ "arm x86" 376 # -> returns '$FOO_SOURCES_arm $FOO_SOURCES_x86" 377 # 378 # get_gyp_list "FOO BAR" _SOURCES_ "arm x86" 379 # -> returns '$FOO_SOURCES_arm $FOO_SOURCES_x86 $BAR_SOURCES_arm $BAR_SOURCES_x86' 380 # 381 # $1: list of variable prefixes 382 # $2: variable suffix 383 # $3: optional list of architectures. 384 get_gyp_list () { 385 local ALL_PREFIXES="$1" 386 local SUFFIX="$2" 387 local ALL_ARCHS="$3" 388 local LIST PREFIX ARCH 389 for PREFIX in $ALL_PREFIXES; do 390 if [ "$ALL_ARCHS" ]; then 391 for ARCH in $ALL_ARCHS; do 392 LIST="$LIST $(var_value ${PREFIX}${SUFFIX}${ARCH})" 393 done 394 else 395 LIST="$LIST $(var_value ${PREFIX}${SUFFIX})" 396 fi 397 done 398 echo "$LIST" 399 } 400 401 generate_gyp_file () { 402 echo "# Auto-generated file - DO NOT EDIT" 403 echo "# To regenerate - run import_from_android.sh." 404 echo "# See 'import_from_android.sh --help' for details." 405 406 local ALL_PREFIXES="OPENSSL_CRYPTO OPENSSL_SSL" 407 local ALL_ARCHS="arm mips x86 x86_64" 408 local PREFIX ARCH LIST 409 410 print_gyp "{" 411 incr_gyp_margin 412 413 print_gyp "'variables': {" 414 incr_gyp_margin 415 416 # First, the common sources and defines 417 print_gyp_source_variable "openssl_common_sources" \ 418 $(get_gyp_list "$ALL_PREFIXES" _SOURCES) 419 420 print_gyp_variable "openssl_common_defines" \ 421 $(get_gyp_list "$ALL_PREFIXES" _DEFINES) 422 423 # Now, conditions section with add architecture-specific sub-sections. 424 for ARCH in $ALL_ARCHS; do 425 # Convert ARCH to gyp-specific architecture name 426 case $ARCH in 427 x86) 428 GYP_ARCH=ia32 429 ;; 430 x86_64) 431 GYP_ARCH=x64 432 ;; 433 *) 434 GYP_ARCH=$ARCH 435 ;; 436 esac 437 438 print_gyp_source_variable "openssl_${ARCH}_source_excludes" \ 439 $(get_gyp_list "$ALL_PREFIXES" _SOURCES_EXCLUDES_ $ARCH) 440 441 print_gyp_source_variable "openssl_${ARCH}_sources" \ 442 $(get_gyp_list "$ALL_PREFIXES" _SOURCES_ $ARCH) 443 444 print_gyp_variable "openssl_${ARCH}_defines" \ 445 $(get_gyp_list "$ALL_PREFIXES" _DEFINES_ $ARCH) 446 447 done # for ARCH 448 449 decr_gyp_margin 450 print_gyp "}" # variables 451 452 decr_gyp_margin 453 print_gyp "}" # top-level dict. 454 } 455 456 dump "Generating 64-bit configuration header file." 457 mkdir -p $PROGDIR/config/x64/openssl/ 458 sed \ 459 -e 's|^#define BN_LLONG|#undef BN_LLONG|g' \ 460 -e 's|^#define THIRTY_TWO_BIT|#undef THIRTY_TWO_BIT|g' \ 461 -e 's|^#undef SIXTY_FOUR_BIT_LONG|#define SIXTY_FOUR_BIT_LONG|g' \ 462 $PROGDIR/openssl/include/openssl/opensslconf.h \ 463 > $PROGDIR/config/x64/openssl/opensslconf.h 464 465 dump "Generating .gypi file." 466 . $ANDROID_SRC_DIR/openssl.config 467 generate_gyp_file > $PROGDIR/openssl.gypi.new 468 run mv $PROGDIR/openssl.gypi $PROGDIR/openssl.gypi.old 469 run mv $PROGDIR/openssl.gypi.new $PROGDIR/openssl.gypi 470 run rm $PROGDIR/openssl.gypi.old 471 472 dump "Done." 473