Skip to content

Instantly share code, notes, and snippets.

@Interfere
Created August 5, 2020 12:51
Show Gist options
  • Save Interfere/23d836cf39c2f3be8ebc4e6393a3dd39 to your computer and use it in GitHub Desktop.
Save Interfere/23d836cf39c2f3be8ebc4e6393a3dd39 to your computer and use it in GitHub Desktop.
Build openssl
#!/usr/bin/env bash
# This file:
# - Builds openssl fat binary for iPhoneOS and iPhoneSimulator
#
# Usage:
# ./build_openssl.sh [-d <OPENSSL_DIR>]
# The MIT License (MIT)
# Copyright (c) 2017 Amaiz LLC and contributors
set -o errexit
set -o errtrace
set -o nounset
set -o pipefail
# Turn on traces, useful while debugging but commented out by default
#set -o xtrace
# Set magic variables for current file, directory, os, etc.
__dir="$(cd "$(dirname "${BASH_SOURCE[${__b3bp_tmp_source_idx:-0}]}")" && pwd)"
__file="${__dir}/$(basename "${BASH_SOURCE[${__b3bp_tmp_source_idx:-0}]}")"
__base="$(basename "${__file}" .sh)"
### Functions
##############################################################################
function __b3bp_log () {
local log_level="${1}"
shift
# shellcheck disable=SC2034
local color_debug="\x1b[35m"
# shellcheck disable=SC2034
local color_info="\x1b[32m"
# shellcheck disable=SC2034
local color_notice="\x1b[34m"
# shellcheck disable=SC2034
local color_warning="\x1b[33m"
# shellcheck disable=SC2034
local color_error="\x1b[31m"
# shellcheck disable=SC2034
local color_critical="\x1b[1;31m"
# shellcheck disable=SC2034
local color_alert="\x1b[1;33;41m"
# shellcheck disable=SC2034
local color_emergency="\x1b[1;4;5;33;41m"
local colorvar="color_${log_level}"
local color="${!colorvar:-${color_error}}"
local color_reset="\x1b[0m"
if [[ "${NO_COLOR:-}" = "true" ]] || [[ "${TERM:-}" != "xterm"* ]] || [[ ! -t 2 ]]; then
if [[ "${NO_COLOR:-}" != "false" ]]; then
# Don't use colors on pipes or non-recognized terminals
color=""; color_reset=""
fi
fi
# all remaining arguments are to be printed
local log_line=""
while IFS=$'\n' read -r log_line; do
echo -e "$(date -u +"%Y-%m-%d %H:%M:%S UTC") ${color}$(printf "[%9s]" "${log_level}")${color_reset} ${log_line}" 1>&2
done <<< "${@:-}"
}
function emergency () { __b3bp_log emergency "${@}"; exit 1; }
function alert () { [[ "${LOG_LEVEL:-0}" -ge 1 ]] && __b3bp_log alert "${@}"; true; }
function critical () { [[ "${LOG_LEVEL:-0}" -ge 2 ]] && __b3bp_log critical "${@}"; true; }
function error () { [[ "${LOG_LEVEL:-0}" -ge 3 ]] && __b3bp_log error "${@}"; true; }
function warning () { [[ "${LOG_LEVEL:-0}" -ge 4 ]] && __b3bp_log warning "${@}"; true; }
function notice () { [[ "${LOG_LEVEL:-0}" -ge 5 ]] && __b3bp_log notice "${@}"; true; }
function info () { [[ "${LOG_LEVEL:-0}" -ge 6 ]] && __b3bp_log info "${@}"; true; }
function debug () { [[ "${LOG_LEVEL:-0}" -ge 7 ]] && __b3bp_log debug "${@}"; true; }
function help () {
echo "" 1>&2
echo " ${*}" 1>&2
echo "" 1>&2
echo " ${__usage:-No usage available}" 1>&2
echo "" 1>&2
if [[ "${__helptext:-}" ]]; then
echo " ${__helptext}" 1>&2
echo "" 1>&2
fi
exit 1
}
### Parse commandline options
##############################################################################
# Commandline options. This defines the usage page, and is used to parse cli
# opts & defaults from. The parsing is unforgiving so be precise in your syntax
# - A short option must be preset for every long option; but every short option
# need not have a long option
# - `--` is respected as the separator between options and arguments
# - We do not bash-expand defaults, so setting '~/app' as a default will not resolve to ${HOME}.
# you can use bash variables to work around this (so use ${HOME} instead)
# shellcheck disable=SC2015
[[ "${__usage+x}" ]] || read -r -d '' __usage <<-EOF || true # exits non-zero when EOF encountered
-f --dir [arg] OpensSSL directory. Default="${__dir}"
-h --help This page
EOF
# Translate usage string -> getopts arguments, and set $arg_<flag> defaults
while read -r __b3bp_tmp_line; do
if [[ "${__b3bp_tmp_line}" =~ ^- ]]; then
# fetch single character version of option string
__b3bp_tmp_opt="${__b3bp_tmp_line%% *}"
__b3bp_tmp_opt="${__b3bp_tmp_opt:1}"
# fetch long version if present
__b3bp_tmp_long_opt=""
if [[ "${__b3bp_tmp_line}" = *"--"* ]]; then
__b3bp_tmp_long_opt="${__b3bp_tmp_line#*--}"
__b3bp_tmp_long_opt="${__b3bp_tmp_long_opt%% *}"
fi
# map opt long name to+from opt short name
printf -v "__b3bp_tmp_opt_long2short_${__b3bp_tmp_long_opt//-/_}" '%s' "${__b3bp_tmp_opt}"
printf -v "__b3bp_tmp_opt_short2long_${__b3bp_tmp_opt}" '%s' "${__b3bp_tmp_long_opt//-/_}"
# check if option takes an argument
if [[ "${__b3bp_tmp_line}" =~ \[.*\] ]]; then
__b3bp_tmp_opt="${__b3bp_tmp_opt}:" # add : if opt has arg
__b3bp_tmp_init="" # it has an arg. init with ""
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "1"
elif [[ "${__b3bp_tmp_line}" =~ \{.*\} ]]; then
__b3bp_tmp_opt="${__b3bp_tmp_opt}:" # add : if opt has arg
__b3bp_tmp_init="" # it has an arg. init with ""
# remember that this option requires an argument
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "2"
else
__b3bp_tmp_init="0" # it's a flag. init with 0
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "0"
fi
__b3bp_tmp_opts="${__b3bp_tmp_opts:-}${__b3bp_tmp_opt}"
fi
[[ "${__b3bp_tmp_opt:-}" ]] || continue
if [[ "${__b3bp_tmp_line}" =~ (^|\.\ *)Default= ]]; then
# ignore default value if option does not have an argument
__b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}"
if [[ "${!__b3bp_tmp_varname}" != "0" ]]; then
__b3bp_tmp_init="${__b3bp_tmp_line##*Default=}"
__b3bp_tmp_re='^"(.*)"$'
if [[ "${__b3bp_tmp_init}" =~ ${__b3bp_tmp_re} ]]; then
__b3bp_tmp_init="${BASH_REMATCH[1]}"
else
__b3bp_tmp_re="^'(.*)'$"
if [[ "${__b3bp_tmp_init}" =~ ${__b3bp_tmp_re} ]]; then
__b3bp_tmp_init="${BASH_REMATCH[1]}"
fi
fi
fi
fi
if [[ "${__b3bp_tmp_line}" =~ (^|\.\ *)Required\. ]]; then
# remember that this option requires an argument
printf -v "__b3bp_tmp_has_arg_${__b3bp_tmp_opt:0:1}" '%s' "2"
fi
printf -v "arg_${__b3bp_tmp_opt:0:1}" '%s' "${__b3bp_tmp_init}"
done <<< "${__usage:-}"
# run getopts only if options were specified in __usage
if [[ "${__b3bp_tmp_opts:-}" ]]; then
# Allow long options like --this
__b3bp_tmp_opts="${__b3bp_tmp_opts}-:"
# Reset in case getopts has been used previously in the shell.
OPTIND=1
# start parsing command line
set +o nounset # unexpected arguments will cause unbound variables
# to be dereferenced
# Overwrite $arg_<flag> defaults with the actual CLI options
while getopts "${__b3bp_tmp_opts}" __b3bp_tmp_opt; do
[[ "${__b3bp_tmp_opt}" = "?" ]] && help "Invalid use of script: ${*} "
if [[ "${__b3bp_tmp_opt}" = "-" ]]; then
# OPTARG is long-option-name or long-option=value
if [[ "${OPTARG}" =~ .*=.* ]]; then
# --key=value format
__b3bp_tmp_long_opt=${OPTARG/=*/}
# Set opt to the short option corresponding to the long option
__b3bp_tmp_varname="__b3bp_tmp_opt_long2short_${__b3bp_tmp_long_opt//-/_}"
printf -v "__b3bp_tmp_opt" '%s' "${!__b3bp_tmp_varname}"
OPTARG=${OPTARG#*=}
else
# --key value format
# Map long name to short version of option
__b3bp_tmp_varname="__b3bp_tmp_opt_long2short_${OPTARG//-/_}"
printf -v "__b3bp_tmp_opt" '%s' "${!__b3bp_tmp_varname}"
# Only assign OPTARG if option takes an argument
__b3bp_tmp_varname="__b3bp_tmp_has_arg_${__b3bp_tmp_opt}"
printf -v "OPTARG" '%s' "${@:OPTIND:${!__b3bp_tmp_varname}}"
# shift over the argument if argument is expected
((OPTIND+=__b3bp_tmp_has_arg_${__b3bp_tmp_opt}))
fi
# we have set opt/OPTARG to the short value and the argument as OPTARG if it exists
fi
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt:0:1}"
__b3bp_tmp_default="${!__b3bp_tmp_varname}"
__b3bp_tmp_value="${OPTARG}"
if [[ -z "${OPTARG}" ]] && [[ "${__b3bp_tmp_default}" = "0" ]]; then
__b3bp_tmp_value="1"
fi
printf -v "${__b3bp_tmp_varname}" '%s' "${__b3bp_tmp_value}"
debug "cli arg ${__b3bp_tmp_varname} = (${__b3bp_tmp_default}) -> ${!__b3bp_tmp_varname}"
done
set -o nounset # no more unbound variable references expected
shift $((OPTIND-1))
if [[ "${1:-}" = "--" ]] ; then
shift
fi
fi
### Automatic validation of required option arguments
##############################################################################
for __b3bp_tmp_varname in ${!__b3bp_tmp_has_arg_*}; do
# validate only options which required an argument
[[ "${!__b3bp_tmp_varname}" = "2" ]] || continue
__b3bp_tmp_opt_short="${__b3bp_tmp_varname##*_}"
__b3bp_tmp_varname="arg_${__b3bp_tmp_opt_short}"
[[ "${!__b3bp_tmp_varname}" ]] && continue
__b3bp_tmp_varname="__b3bp_tmp_opt_short2long_${__b3bp_tmp_opt_short}"
printf -v "__b3bp_tmp_opt_long" '%s' "${!__b3bp_tmp_varname}"
[[ "${__b3bp_tmp_opt_long:-}" ]] && __b3bp_tmp_opt_long=" (--${__b3bp_tmp_opt_long//_/-})"
help "Option -${__b3bp_tmp_opt_short}${__b3bp_tmp_opt_long:-} requires an argument"
done
### Cleanup Environment variables
##############################################################################
for __tmp_varname in ${!__b3bp_tmp_*}; do
unset -v "${__tmp_varname}"
done
unset -v __tmp_varname
### Externally supplied __usage. Nothing else to do here
##############################################################################
if [[ "${__b3bp_external_usage:-}" = "true" ]]; then
unset -v __b3bp_external_usage
return
fi
### Command-line argument switches (like -d for debugmode, -h for showing helppage)
##############################################################################
# help mode
if [[ "${arg_h:?}" = "1" ]]; then
# Help exists with code 1
help "Help using ${0}"
fi
### Validation. Error out if the things required for your script are not present
##############################################################################
[[ "${arg_f:-}" ]] || help "Setting a directory with -f or --dir is required"
### Build openssl
##############################################################################
[[ "${__opensslconf_h_in+x}" ]] || read -r -d '' __opensslconf_h_in <<-EOF || true # exits non-zero when EOF encountered
/*
* WARNING: do not edit!
* Generated by Makefile from include/openssl/opensslconf.h.in
*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#if defined(__x86_64__)
# include <openssl/opensslconf_x86_64.h>
#elif defined(__arm64__)
# include <openssl/opensslconf_arm64.h>
#else
# error unrecognized GNU C compiler
#endif
EOF
[[ "${__openssl_modulemap+x}" ]] || read -r -d '' __openssl_modulemap <<-EOF || true
framework module OpenSSL {
umbrella header "OpenSSL.h"
export *
module * { export * }
}
EOF
[[ "${__opensslv_h_in+x}" ]] || read -r -d '' __opensslv_h_in <<-EOF || true # exits non-zero when EOF encountered
/*
* WARNING: do not edit!
* Generated by Makefile from include/openssl/opensslconf.h.in
*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#if defined(__x86_64__)
# include <openssl/opensslv_x86_64.h>
#elif defined(__arm64__)
# include <openssl/opensslv_arm64.h>
#else
# error unrecognized GNU C compiler
#endif
EOF
[[ "${__openssl_modulemap+x}" ]] || read -r -d '' __openssl_modulemap <<-EOF || true
framework module OpenSSL {
umbrella header "OpenSSL.h"
export *
module * { export * }
}
EOF
[[ "${__openssl_info_plist+x}" ]] || read -r -d '' __openssl_info_plist <<-EOF || true
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>19B88</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>OpenSSL</string>
<key>CFBundleIdentifier</key>
<string>com.interfere.OpenSSL</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>OpenSSL</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.1.012</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneSimulator</string>
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>MinimumOSVersion</key>
<string>11.4</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
</dict>
</plist>
EOF
[[ "${__openssl_umbrella+x}" ]] || read -r -d '' __openssl_umbrella <<-EOF || true
#import <OpenSSL/opensslconf.h>
#import <OpenSSL/pem2.h>
#import <OpenSSL/kdf.h>
#import <OpenSSL/pem.h>
#import <OpenSSL/md2.h>
#import <OpenSSL/ssl3.h>
#import <OpenSSL/ossl_typ.h>
#import <OpenSSL/dtls1.h>
#import <OpenSSL/err.h>
#import <OpenSSL/bn.h>
#import <OpenSSL/blowfish.h>
#import <OpenSSL/cms.h>
#import <OpenSSL/engine.h>
#import <OpenSSL/conf_api.h>
#import <OpenSSL/x509.h>
#import <OpenSSL/ui.h>
#import <OpenSSL/sha.h>
#import <OpenSSL/symhacks.h>
#import <OpenSSL/asn1.h>
#import <OpenSSL/bio.h>
#import <OpenSSL/rc2.h>
#import <OpenSSL/dh.h>
#import <OpenSSL/x509v3.h>
#import <OpenSSL/conf.h>
#import <OpenSSL/md5.h>
#import <OpenSSL/x509_vfy.h>
#import <OpenSSL/txt_db.h>
#import <OpenSSL/safestack.h>
#import <OpenSSL/ecdsa.h>
#import <OpenSSL/rc5.h>
#import <OpenSSL/objects.h>
#import <OpenSSL/pkcs12.h>
#import <OpenSSL/crypto.h>
#import <OpenSSL/opensslv.h>
#import <OpenSSL/pkcs7.h>
#import <OpenSSL/obj_mac.h>
#import <OpenSSL/ct.h>
#import <OpenSSL/async.h>
#import <OpenSSL/buffer.h>
#import <OpenSSL/ssl.h>
#import <OpenSSL/srp.h>
#import <OpenSSL/camellia.h>
#import <OpenSSL/evp.h>
#import <OpenSSL/e_os2.h>
#import <OpenSSL/md4.h>
#import <OpenSSL/hmac.h>
#import <OpenSSL/aes.h>
#import <OpenSSL/comp.h>
#import <OpenSSL/cast.h>
#import <OpenSSL/rc4.h>
#import <OpenSSL/stack.h>
#import <OpenSSL/des.h>
#import <OpenSSL/ocsp.h>
#import <OpenSSL/ec.h>
#import <OpenSSL/ecdh.h>
#import <OpenSSL/rand.h>
#import <OpenSSL/ts.h>
#import <OpenSSL/seed.h>
#import <OpenSSL/modes.h>
#import <OpenSSL/ssl2.h>
#import <OpenSSL/rsa.h>
#import <OpenSSL/ripemd.h>
#import <OpenSSL/whrlpool.h>
#import <OpenSSL/tls1.h>
#import <OpenSSL/mdc2.h>
#import <OpenSSL/dsa.h>
#import <OpenSSL/srtp.h>
#import <OpenSSL/asn1t.h>
#import <OpenSSL/cmac.h>
#import <OpenSSL/ebcdic.h>
#import <OpenSSL/idea.h>
#import <OpenSSL/lhash.h>
EOF
## Functions
function setup_env {
local __platform="${1}"
local __arch="${2}"
export CROSS_TOP="${__developer}/Platforms/${__platform}.platform/Developer"
export CROSS_SDK="${__platform}${__sdkversion}.sdk"
export BUILD_DIR="${__build_dir}/${__platform}${__sdkversion}-${__arch}.sdk"
}
function build_openssl {
local __lipo_lib=""
local __options=""
local __freamwork_name="OpenSSL.framework"
local __freamwork_path="${__build_dir}/${__freamwork_name}"
local __freamwork_headers_path="${__freamwork_path}/Headers"
local __freamwork_modules_path="${__freamwork_path}/Modules"
mkdir -p "${__freamwork_headers_path}" "${__freamwork_modules_path}"
for __arch in ${__archs}; do
local __disable_ciphers="no-md4 no-rc4 no-rc2"
if [[ "${__arch}" = "arm64" ]]; then
setup_env "iPhoneOS" "${__arch}"
__target="ios64-cross"
__clang_target="arm64-apple-ios11.0"
elif [[ "${__arch}" = "x86_64" ]]; then
setup_env "iPhoneSimulator" "${__arch}"
__options="-mios-simulator-version-min=11.0 ${__options} no-asm"
__target="darwin64-x86_64-cc"
__clang_target="x86_64-apple-ios12.0-simulator"
else
setup_env "iPhoneOS" "${__arch}"
__target="ios-cross"
fi
"${arg_f}/Configure" no-md4 no-rc4 no-rc2 no-shared no-dso no-unit-test no-filenames no-async --prefix="${BUILD_DIR}" -isysroot "${CROSS_TOP}/SDKs/${CROSS_SDK}" ${__options} "${__target}"
make all && make install_sw
pushd "${BUILD_DIR}/lib"
"${__developer}/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar" -x "libcrypto.a"
"${__developer}/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar" -x "libssl.a"
/bin/rm "libssl-lib-packet.o"
"${__developer}/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -target "${__clang_target}" -dynamiclib -isysroot "${CROSS_TOP}/SDKs/${CROSS_SDK}" -install_name @rpath/OpenSSL.framework/OpenSSL -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks -Xlinker -objc_abi_version -Xlinker 2 -fobjc-arc -compatibility_version 1 -current_version 1 -dead_strip *.o -o "OpenSSL"
/bin/rm *.o
popd
__lipo_lib="${__lipo_lib} ${BUILD_DIR}/lib/OpenSSL"
install -m 0644 "${BUILD_DIR}/include/openssl/opensslconf.h" "${__freamwork_headers_path}/opensslconf_${__arch}.h"
install -m 0644 "${BUILD_DIR}/include/openssl/opensslv.h" "${__freamwork_headers_path}/opensslv_${__arch}.h"
make clean
done
# Create fat dylib as framework main executable
"${__developer}/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo" -create ${__lipo_lib} -output "${__freamwork_path}/OpenSSL"
# Copy headers and create opensslconf.h
find "${arg_f}/include/openssl" -type f -name "*.h" -exec install -m 0644 {} "${__freamwork_headers_path}" \;
echo "${__opensslconf_h_in}" > "${__freamwork_headers_path}/opensslconf.h"
echo "${__opensslv_h_in}" > "${__freamwork_headers_path}/opensslv.h"
# Create umbrella header
echo "${__openssl_umbrella}" > "${__freamwork_headers_path}/OpenSSL.h"
# Create .modulemap file
echo "${__openssl_modulemap}" > "${__freamwork_modules_path}/module.modulemap"
# Create Info.plist
echo "${__openssl_info_plist}" > "${__freamwork_path}/Info.plist"
# remove <inttypes.h>
sed -i '' '/inttypes.h/d' "${__freamwork_headers_path}/e_os2.h"
}
# Setup main variables
__developer=`xcode-select -print-path`
__sdkversion=`xcrun --sdk iphoneos --show-sdk-version`
__archs="arm64 x86_64"
export CC="${__developer}/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"
# prepare build directory
__build_dir="${arg_f}/build"
mkdir -p "${__build_dir}"
build_openssl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment