Skip to content

Conversation

ilammy
Copy link

@ilammy ilammy commented Oct 26, 2020

Okay, let's try this again. Previously we have experimented with 'static frameworks' – regular frameworks but with static libraries in them instead of dynamic ones. It turns out that a special CocoaPods option seems to make them work after all.

Convert CLOpenSSL into a static framework for CocoaPods too, like we already do for Carthage.

Okay, let's try this again. Previously we have experimented with 'static
framworks' -- regular frameworks but with static libraries in them
instead of dynamic ones. It turns out that a special CocoaPods option
seems to make them work after all.

Convert CLOpenSSL into a static framework for CocoaPods too, like we
already do for Carthage.
@ilammy ilammy added the cocoapods CocoaPods packaging label Oct 26, 2020
@vixentael
Copy link

like we already do for Carthage

unification is the key 🔑

@ilammy ilammy merged commit d21e3b7 into cossacklabs:cossacklabs Oct 27, 2020
@ilammy ilammy deleted the cocoapods/static-framework branch October 27, 2020 09:40
vixentael pushed a commit to vixentael/openssl-apple that referenced this pull request Nov 22, 2020
ilammy pushed a commit that referenced this pull request Nov 22, 2020
* 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cocoapods CocoaPods packaging
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants