Skip to content

Adding XCFramework distribution #671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ce4543e
Initial XCFramework
csjones Apr 22, 2025
c57ad7e
Buildable XCFramework
csjones Feb 3, 2025
9c2b104
P256K framework works example app
csjones Feb 5, 2025
f1f6527
XCFramework Unit Tests
csjones Apr 20, 2025
1f6a1ae
Updating tests
csjones Apr 20, 2025
7a284b1
Moved remaining tests to Swift Testing and running against XCFramework
csjones Apr 20, 2025
705e4ba
Re-organizing tests for bindings
csjones Feb 18, 2025
c7e0c32
Fix symbolic link check
csjones Feb 18, 2025
d6bf9b8
Change symbolic link path
csjones Feb 18, 2025
086bd61
Fixing the rest of the broken links
csjones Feb 18, 2025
aa95424
Update Dockerfile
csjones Feb 19, 2025
916e385
Add missing imports for Linux
csjones Feb 19, 2025
a2e2c97
Updating CI
csjones Feb 19, 2025
e238d2c
Testing XCFramework
csjones Feb 19, 2025
3450b7a
Adding archive command
csjones Feb 19, 2025
642d7e4
Disable visionOS and use xcbeautify
csjones Feb 19, 2025
07f9aed
Create XCFramework and add to Bitrise
csjones Feb 19, 2025
2d93b23
Fixed SKIP_INSTALL
csjones Feb 19, 2025
60e36ad
Adjust build settings and command for deployment
csjones Feb 20, 2025
dd554a3
Pre-release workflow
csjones Mar 2, 2025
9815d15
Use Swift 6
csjones Feb 22, 2025
f5464f8
Test XCFramework
csjones Feb 24, 2025
39eda68
Rename secp256k1 enum to P256K
csjones Apr 20, 2025
69ade16
Updates
csjones Apr 21, 2025
6cd9a7e
Cleanup
csjones Apr 21, 2025
6dfd5bf
Workaround for new XCFramework
csjones Apr 22, 2025
6f50c01
Adding license files
csjones Apr 24, 2025
659a444
Adding Cocoapods deployment
csjones Apr 24, 2025
4f94e2d
Update Readme
csjones Apr 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 8 additions & 4 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ jobs:
with:
submodules: recursive
- name: Check symbolic links
run: find . -type d -name .build -prune -o -type l ! -exec test -e {} \; -print | grep -q . && exit 1 || exit 0
run: |
broken_links=$(find . -type d -name .build -prune -o -type l ! -exec test -e {} \; -print)
if [ -n "$broken_links" ]; then
echo "Broken symbolic links found:"
echo "$broken_links"
exit 1
fi
- name: Build the Docker zkp image
run: docker build .
- name: Build the Docker secp256k1 image
run: docker build -f Exhaustive/Package/Dockerfile .
run: docker build .
130 changes: 130 additions & 0 deletions .github/workflows/xcframework-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
name: XCFramework Release
on:
release:
types: [published]
jobs:
macos:
name: Build XCFramework
runs-on: macos-15
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Generate Xcode project
run: swift package --disable-sandbox tuist generate -p Projects/ --no-open
- name: Archive & Create XCFramework
run: |
# Define workspace and scheme
WORKSPACE='Projects/XCFramework.xcworkspace'
SCHEME='P256K'
CONFIGURATION='Release'
ARCHIVE_DIR='Archives'

# Platforms to archive
PLATFORMS=(
"iOS"
"iOS Simulator"
"macOS"
"tvOS"
"tvOS Simulator"
"watchOS"
"watchOS Simulator"
# "visionOS"
# "XR Simulator"
)

# Loop over platforms and archive for each one
for PLATFORM in "${PLATFORMS[@]}"; do
echo "Archiving for $PLATFORM..."

# Run xcodebuild archive for each platform
xcodebuild archive \
-workspace "$WORKSPACE" \
-scheme "$SCHEME" \
-configuration "$CONFIGURATION" \
-destination "generic/platform=$PLATFORM" \
-archivePath "$ARCHIVE_DIR/P256K-$PLATFORM.xcarchive"

# Check if archive command was successful
if [ $? -eq 0 ]; then
echo "$PLATFORM archive created successfully."
else
echo "Failed to archive for $PLATFORM. Exiting."
exit 1
fi
done

echo "All archives completed successfully."

# Create an XCFramework to support multiple platforms and architectures
# Each -archive parameter specifies a path to a .xcarchive built for a different platform
# -framework specifies the framework within those archives to include in the XCFramework
# The -output parameter specifies the name and location of the XCFramework to be created
xcodebuild -create-xcframework \
-archive "Archives/P256K-iOS.xcarchive" -framework P256K.framework \
-archive "Archives/P256K-iOS Simulator.xcarchive" -framework P256K.framework \
-archive "Archives/P256K-macOS.xcarchive" -framework P256K.framework \
-archive "Archives/P256K-tvOS.xcarchive" -framework P256K.framework \
-archive "Archives/P256K-tvOS Simulator.xcarchive" -framework P256K.framework \
-archive "Archives/P256K-watchOS.xcarchive" -framework P256K.framework \
-archive "Archives/P256K-watchOS Simulator.xcarchive" -framework P256K.framework \
-output P256K.xcframework

# Workaround for Swift issue SR-14195/GitHub #56573:
# When a module has the same name as a type it contains (P256K in this case),
# Swift generates invalid module interfaces with incorrect type qualifications.
# This leads to imports failing with errors like:
# "TypeName is not a member type of class ModuleName.ModuleName"
#
# This script fixes generated .swiftinterface files by:
# 1. Removing double-qualification of the P256K type
# 2. Fixing references to other types that don't need module qualification
# See: https://github.com/swiftlang/swift/issues/56573
find P256K.xcframework -name '*.swiftinterface' -print0 \
| xargs -0 sed -i '' \
-e 's/extension P256K\.P256K/extension P256K/g' \
-e 's/P256K\.P256K\./P256K\./g' \
-e 's/[[:<:]]P256K\.secp256k1Error[[:>:]]/secp256k1Error/g' \
-e 's/[[:<:]]P256K\.Digest[[:>:]]/Digest/g' \
-e 's/[[:<:]]P256K\.CryptoKitError[[:>:]]/CryptoKitError/g' \
-e 's/[[:<:]]P256K\.CryptoKitASN1Error[[:>:]]/CryptoKitASN1Error/g' \
-e 's/[[:<:]]P256K\.SHA256Digest[[:>:]]/SHA256Digest/g' \
-e 's/[[:<:]]P256K\.XonlyKeyImplementation[[:>:]]/XonlyKeyImplementation/g' \
-e 's/[[:<:]]P256K\.HashDigest[[:>:]]/HashDigest/g' \
-e 's/[[:<:]]P256K\.SharedSecret[[:>:]]/SharedSecret/g' \
-e 's/[[:<:]]P256K\.PublicKeyImplementation[[:>:]]/PublicKeyImplementation/g' \
-e 's/[[:<:]]P256K\.PrivateKeyImplementation[[:>:]]/PrivateKeyImplementation/g'
- name: 7z XCFramework
run: |
# Copy COPYING file to current directory to avoid including folder structure
cp "Submodules/secp256k1/COPYING" "COPYING-libsecp256k1"
# Create zip with maximum compression including license files alongside the XCFramework
7z a -tzip -mx=9 P256K.xcframework.zip P256K.xcframework LICENSE "COPYING-libsecp256k1"
- name: Upload XCFramework
run: |
gh release upload ${{ github.ref_name }} P256K.xcframework.zip
- name: Deploy to Cocoapods
run: |
# Install Cocoapods
gem install cocoapods

# Get the current release tag name (version) from GitHub
# This ensures the podspec uses the same version as the GitHub release
export POD_VERSION=$(gh release list -R 21-DOT-DEV/swift-secp256k1 -L 1 --json tagName --jq '.[0].tagName')

# Calculate SHA256 checksum of the XCFramework zip file
# CocoaPods requires this hash for security verification when downloading the binary
export XCFRAMEWORK_SHA=$(shasum -a 256 P256K.xcframework.zip | awk '{print $1}')

# Validate the podspec using the environment variables set above
# This checks that the podspec is valid before attempting to publish
pod spec lint Projects/swift-secp256k1.podspec

# Push the podspec to the CocoaPods Trunk service
# This publishes the new version of the pod to the CocoaPods registry
pod trunk push Projects/swift-secp256k1.podspec
env:
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
20 changes: 17 additions & 3 deletions .swiftformat
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,28 @@
# file options
--swiftversion 5
--exclude .build
--exclude Submodules
--exclude Exhaustive/**/secp256k1Tests.swift
--exclude Exhaustive/**/XCTestManifests.swift
--exclude Sources/**/ArraySliceBigint.swift
--exclude Sources/**/ASN1.swift
--exclude Sources/**/ASN1BitString.swift
--exclude Sources/**/ASN1Boolean.swift
--exclude Sources/**/ASN1Identifier.swift
--exclude Sources/**/ASN1Integer.swift
--exclude Sources/**/ASN1Null.swift
--exclude Sources/**/ASN1OctetString.swift
--exclude Sources/**/ASN1Strings.swift
--exclude Sources/**/Digest.swift
--exclude Sources/**/ECDSASignature.swift
--exclude Sources/**/GeneralizedTime.swift
--exclude Sources/**/ObjectIdentifier.swift
--exclude Sources/**/PEMDocument.swift
--exclude Sources/**/PKCS8PrivateKey.swift
--exclude Sources/**/PrettyBytes.swift
--exclude Sources/**/RNG_boring.swift
--exclude Sources/**/SecureBytes.swift
--exclude Sources/**/Signature.swift
--exclude Exhaustive/**/secp256k1Tests.swift
--exclude Exhaustive/**/XCTestManifests.swift
--exclude Submodules

# rules
# --disable elseOnSameLine,semicolons
Expand Down
42 changes: 36 additions & 6 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
# By default, SwiftLint uses a set of sensible default rules you can adjust:
disabled_rules: # rule identifiers turned on by default to exclude from running
- comment_spacing
# Opt-in rules that we're not using
- accessibility_label_for_image
- accessibility_trait_for_button
- async_without_await
- comma_inheritance
- contrasted_opening_brace
- direct_return
- final_test_case
- local_doc_comment
- no_empty_block
- no_magic_numbers
- non_overridable_class_declaration
- number_separator
- one_declaration_per_file
- period_spacing
- prefer_key_path
- private_swiftui_state
- redundant_self_in_closure
- return_value_from_void_function
- self_binding
- shorthand_argument
- shorthand_optional_binding
- sorted_enum_cases
- superfluous_else
- typesafe_array_init
- unhandled_throwing_task
- unused_parameter
opt_in_rules: # some rules are turned off by default, so you need to opt-in
- empty_count # Find all the available rules by running: `swiftlint rules`
- anonymous_argument_in_multiline_closure
- anyobject_protocol
- array_init
- attributes
- balanced_xctest_lifecycle
- capture_variable
- closure_body_length
- closure_end_indentation
- closure_spacing
Expand Down Expand Up @@ -72,7 +97,6 @@ opt_in_rules: # some rules are turned off by default, so you need to opt-in
- no_grouping_extension
- nslocalizedstring_key
- nslocalizedstring_require_bundle
- number_separator
- object_literal
- operator_usage_whitespace
- optional_enum_case_matching
Expand Down Expand Up @@ -113,8 +137,6 @@ opt_in_rules: # some rules are turned off by default, so you need to opt-in
- unneeded_parentheses_in_closure_argument
- unowned_variable_capture
- untyped_error_in_catch
- unused_declaration
- unused_import
- vertical_parameter_alignment_on_call
- vertical_whitespace_between_cases
- vertical_whitespace_closing_braces
Expand All @@ -138,8 +160,10 @@ excluded: # paths to ignore during linting. Takes precedence over `included`.
- Sources/**/ASN1Boolean.swift
- Sources/**/ASN1Identifier.swift
- Sources/**/ASN1Integer.swift
- Sources/**/ASN1Null.swift
- Sources/**/ASN1OctetString.swift
- Sources/**/ASN1Strings.swift
- Sources/**/ObjectIdentifier.swift
- Sources/**/Digest.swift
- Sources/**/ECDSASignature.swift
- Sources/**/GeneralizedTime.swift
Expand All @@ -151,8 +175,14 @@ excluded: # paths to ignore during linting. Takes precedence over `included`.
- Sources/**/Signature.swift
- Exhaustive/**/secp256k1Tests.swift
- Exhaustive/**/XCTestManifests.swift
analyzer_rules: # Rules run by `swiftlint analyze`
- Sources/P256K/**/*

# Rules run by `swiftlint analyze` - these should only appear here, not in opt_in_rules
analyzer_rules:
- capture_variable
- explicit_self
- unused_declaration
- unused_import

# configurable rules can be customized from this configuration file
# binary rules can set their severity level
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ ADD . /LinuxTests
WORKDIR /LinuxTests

# Execute Linux test suite
RUN swift test -v && swift build --target secp256k1
RUN swift test
11 changes: 0 additions & 11 deletions Exhaustive/Package/Dockerfile

This file was deleted.

18 changes: 0 additions & 18 deletions Exhaustive/Package/Package.swift

This file was deleted.

This file was deleted.

This file was deleted.

18 changes: 11 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,27 @@ let package = Package(
name: "swift-secp256k1",
products: [
// WARNING: These APIs should not be considered stable and may change at any time.
.library(name: "secp256k1", targets: ["secp256k1"]),
.library(name: "zkp", targets: ["zkp"])
.library(name: "libsecp256k1", targets: ["libsecp256k1"]),
.library(name: "libsecp256k1_zkp", targets: ["libsecp256k1_zkp"]),
.library(name: "P256K", targets: ["P256K"]),
.library(name: "ZKP", targets: ["ZKP"])
],
dependencies: [
// Dependencies used for package development
.package(url: "https://github.com/csjones/lefthook-plugin.git", exact: "1.11.11"),
.package(url: "https://github.com/21-DOT-DEV/swift-plugin-tuist.git", exact: "4.48.1"),
.package(url: "https://github.com/nicklockwood/SwiftFormat.git", exact: "0.55.5"),
.package(url: "https://github.com/realm/SwiftLint.git", exact: "0.59.1")
],
targets: [
.target(name: "secp256k1", dependencies: ["secp256k1_bindings"]),
.target(name: "zkp", dependencies: ["zkp_bindings"]),
.target(name: "P256K", dependencies: ["libsecp256k1"]),
.target(name: "ZKP", dependencies: ["libsecp256k1_zkp"]),
.target(
name: "secp256k1_bindings",
name: "libsecp256k1",
cSettings: PackageDescription.CSetting.baseSettings
),
.target(
name: "zkp_bindings",
name: "libsecp256k1_zkp",
cSettings: PackageDescription.CSetting.baseSettings + [
.define("ENABLE_MODULE_BPPP"),
.define("ENABLE_MODULE_ECDSA_ADAPTOR"),
Expand All @@ -38,7 +41,8 @@ let package = Package(
.headerSearchPath("../../Submodules/secp256k1-zkp/src")
]
),
.testTarget(name: "zkpTests", dependencies: ["zkp"])
.testTarget(name: "libsecp256k1zkpTests", dependencies: ["ZKP", "libsecp256k1_zkp"]),
.testTarget(name: "ZKPTests", dependencies: ["ZKP"])
],
swiftLanguageModes: [.v5],
cLanguageStandard: .c89
Expand Down
Loading