Skip to content

Commit

Permalink
Remove arm64e slice; return dyn linking for CocoaPods (#18)
Browse files Browse the repository at this point in the history
* Automatically enable Apple Silicon support

Since Xcode 12.2 (stable) is out, Apple Silicon support can be enabled
automatically there. Check the version of the command-line tools and
set APPLE_SILICON_SUPPORT value automatically if possible.

After a while, once Xcode 12.0.1 and earlier are not longer supported
and widely used, this variable can be removed completely. Right now
it won't be really necessary to set it explicitly, unless you want
something strange.

* Revert "Use static frameworks for CocoaPods (#13)"

This reverts commit d21e3b7.

We can't just migrate CLOpenSSL to static frameworks as that requires
all upstream dependencies to migrate to static frameworks too, and
that breaks builds left, right, and center.

Instead, we have figured out what has been breaking dynamic linkage
with CocoaPods, and now we're coming back to using dynamic linkage.

If static versions of CLOpenSSL are published, they will be published
in a separate podspec.

* Drop arm64e to work around CocoaPods issues

arm64e builds are included to test the pointer authentication feature of
iOS devices. We have to include it in binary CLOpenSSL builds so that
upstream users of CLOpenSSL might enable it themselves for testing.

However, inclusion of this architecture slice causes issues with
CocoaPods handling of vendored binary frameworks. arm64e builds include
a certain linker command -- LC_DYLD_CHAINED_FIXUPS (0x80000034) -- which
confuses CocoaPods' detector of dynamic binaries, making it believe that
the vendored framework in a static one, not dynamic. This in turn causes
issues when using CLOpenSSL as CocoaPods refuses to link "static" binary
without "static_framework = true".

This is a know issue in CocoaPods, stemming from the missing features in
Homebrew's Mach-O parser [1][2].

[1]: Homebrew/brew#7857
[2]: Homebrew/ruby-macho#261

There is nothing we can do about it right now, other than disable
"arm64e" builds for the time being. This does not affect deployment to
App Store, but will break dependencies of CLOpenSSL which expect this
architecture to be present. The dependencies will have to disable arm64e
in their projects, if they have it explicitly enabled. (Considering that
CocoaPods packaging of CLOpenSSL was never in good shape, the actual
impact of this change should be minimal.)

* Set install name during linkage

Instead of using "install_name_tool" to fix the LC_ID_DYLIB value of the
dylib, pass the "-install_name" parameter to the linker directly. This
doesn't change anything in the resulting binary but looks a bit cleaner.

* Use ABI-correct install name on macOS

On macOS -- contrary to iOS, watchOS, and tvOS -- it is customary for
frameworks to provide additional internal structure which helps with
binary compatibility. For example, on iOS/watchOS/tvOS a framework
typically has flat structure:

    openssl.framework
    ├── Headers
    ├── Info.plist
    └── openssl

while on macOS it's a bit more involved:

    frameworks/MacOSX/openssl.framework
    ├── Headers -> Versions/Current/Headers
    ├── Resources -> Versions/Current/Resources
    ├── Versions
    │   ├── A
    │   └── Current -> A
    └── openssl -> Versions/Current/openssl

Note that the top-level files are actually symlinks to the
"Versions/Current" which in turn is a symlink to the "A" version,
which actually contains the framework content:

    openssl.framework/Versions/A
    ├── Headers
    ├── Resources
    │   └── Info.plist
    └── openssl

Currently, the 'install name' of all "openssl" binaries is set to
"@rpath/openssl.framework/openssl", which makes the linked binaries
remember and use this path when loading OpenSSL. On macOS this will
involve two additional symlink resolutions. Another thing here is that
if we will need to introduce a different version of OpenSSL framework
on macOS, existing applications will still look up the current one,
instead of using the A version that they should.

Update the install name computation to use

    @rpath/openssl.framework/openssl

for iOS, watchOS, tvOS while using more explicit

    @rpath/openssl.framework/Versions/A/openssl

for macOS.

This is how Apple's system frameworks do it. Though they have a pressing
issue of supporting multiple possible ABIs and it's not that important
in our case, you never know when this turns out to be necessary or
whether some weird tool might choke on the symlinks.
  • Loading branch information
vixentael authored Nov 22, 2020
1 parent 6a8e199 commit 75b8306
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 19 deletions.
20 changes: 14 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,30 @@ endif
VERSION ?= 1.1.1h

## Extra version of the distributed package
PACKAGE_VERSION ?= 1
PACKAGE_VERSION ?= 2
export PACKAGE_VERSION

MIN_IOS_SDK = 10.0
MIN_OSX_SDK = 10.11
export MIN_IOS_SDK MIN_OSX_SDK

BUILD_ARCHS += ios_i386 ios_x86_64 ios_arm64 ios_arm64e ios_armv7s ios_armv7
BUILD_ARCHS += ios_i386 ios_x86_64 ios_arm64 ios_armv7s ios_armv7
BUILD_ARCHS += mac_x86_64
BUILD_TARGETS += ios-sim-cross-i386 ios-sim-cross-x86_64
BUILD_TARGETS += ios64-cross-arm64 ios64-cross-arm64e ios-cross-armv7s ios-cross-armv7
BUILD_TARGETS += ios64-cross-arm64 ios-cross-armv7s ios-cross-armv7
BUILD_TARGETS += macos64-x86_64

# Apple Silicon support is currently experimental. It is available only with
# beta Xcode versions installed. Once iOS 14 and macOS 11 are released and
# stable Xcode supports arm64, these settings are going to become default.
# Automatically enable Apple Silicon support if running with Xcode 12.2+
# unless the user has decided explicitly.
ifeq ($(APPLE_SILICON_SUPPORT),)
xcode_version := $(shell xcodebuild -version | awk '/Xcode/ {print $$2}')
ifeq ($(shell printf '%s\n' "12.2" "$(xcode_version)" | sort -V | head -1),12.2)
APPLE_SILICON_SUPPORT := yes
endif
endif

# Not all currently used Xcode versions support building for Apple Silicon.
# Enable this architecture only when requested.
ifeq ($(APPLE_SILICON_SUPPORT),yes)
BUILD_ARCHS += mac_arm64
BUILD_TARGETS += macos64-arm64
Expand Down
4 changes: 0 additions & 4 deletions cocoapods/CLOpenSSL.podspec.template
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,6 @@ EOF
done
EOF

# Tell CocoaPods that the frameworks we publish are "static frameworks".
# This ensures correct resolution of transitive dependencies.
s.static_framework = true

# Set the minimum platform versions. We just know the right ones from the
# prebuilt frameworks we download.
s.ios.deployment_target = min_target_ios
Expand Down
6 changes: 4 additions & 2 deletions config/20-all-platforms.conf
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ my %targets = ();
cflags => add(sub { defined($ENV{'MACOS_MIN_SDK_VERSION'}) ? '-mmacosx-version-min=$(MACOS_MIN_SDK_VERSION)' : '-mmacosx-version-min=10.11'; }),
},

# Apple Silicon support
# https://github.com/openssl/openssl/pull/12369
"darwin64-arm64-cc" => {
inherit_from => [ "darwin-common", asm("") ],
inherit_from => [ "darwin-common", asm("aarch64_asm") ],
CFLAGS => add("-Wall"),
cflags => add("-arch arm64"),
lib_cppflags => add("-DL_ENDIAN"),
bn_ops => "SIXTY_FOUR_BIT_LONG",
perlasm_scheme => "macosx",
perlasm_scheme => "ios64",
},

## Apple WatchOS
Expand Down
11 changes: 8 additions & 3 deletions create-openssl-framework.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ function get_openssl_version() {

if [ $FWTYPE == "dynamic" ]; then
DEVELOPER=`xcode-select -print-path`
FW_EXEC_NAME="${FWNAME}.framework/${FWNAME}"
INSTALL_NAME="@rpath/${FW_EXEC_NAME}"
COMPAT_VERSION="1.0.0"
CURRENT_VERSION="1.0.0"
NORMALIZE_OPENSSL_VERSION=yes
Expand Down Expand Up @@ -178,6 +176,13 @@ if [ $FWTYPE == "dynamic" ]; then
ar -x ../lib/libssl.a
cd ..

# macOS frameworks have a bit different structure inside.
if [[ $PLATFORM == MacOSX* ]]; then
INSTALL_NAME="@rpath/${FWNAME}.framework/Versions/A/${FWNAME}"
else
INSTALL_NAME="@rpath/${FWNAME}.framework/${FWNAME}"
fi

ld obj/*.o \
-dylib \
-bitcode_bundle \
Expand All @@ -188,8 +193,8 @@ if [ $FWTYPE == "dynamic" ]; then
-compatibility_version $COMPAT_VERSION \
-current_version $CURRENT_VERSION \
-application_extension \
-install_name $INSTALL_NAME \
-o $FWNAME.dylib
install_name_tool -id $INSTALL_NAME $FWNAME.dylib

cd ..
done
Expand Down
8 changes: 4 additions & 4 deletions scripts/update-specs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ sed -e "s/%%OPENSSL_VERSION%%/$version/g" \
-e "s!%%GITHUB_REPO%%!$GITHUB_REPO!g" \
-e "s/%%MIN_IOS_SDK%%/$MIN_IOS_SDK/g" \
-e "s/%%MIN_OSX_SDK%%/$MIN_OSX_SDK/g" \
-e "s/%%IPHONE_ARCHIVE_NAME%%/$IPHONE_STATIC_NAME/g" \
-e "s/%%IPHONE_ARCHIVE_HASH%%/$(shasum -a 256 "$OUTPUT/$IPHONE_STATIC_NAME" | awk '{print $1}')/g" \
-e "s/%%MACOSX_ARCHIVE_NAME%%/$MACOSX_STATIC_NAME/g" \
-e "s/%%MACOSX_ARCHIVE_HASH%%/$(shasum -a 256 "$OUTPUT/$MACOSX_STATIC_NAME" | awk '{print $1}')/g" \
-e "s/%%IPHONE_ARCHIVE_NAME%%/$IPHONE_DYNAMIC_NAME/g" \
-e "s/%%IPHONE_ARCHIVE_HASH%%/$(shasum -a 256 "$OUTPUT/$IPHONE_DYNAMIC_NAME" | awk '{print $1}')/g" \
-e "s/%%MACOSX_ARCHIVE_NAME%%/$MACOSX_DYNAMIC_NAME/g" \
-e "s/%%MACOSX_ARCHIVE_HASH%%/$(shasum -a 256 "$OUTPUT/$MACOSX_DYNAMIC_NAME" | awk '{print $1}')/g" \
$podspec.template > $podspec
echo "Updated $podspec"
echo

0 comments on commit 75b8306

Please sign in to comment.