Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-fails/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
generated/*
.build/*
target/*
Cargo.lock
TestReleaseFails/*
20 changes: 20 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-fails/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "test-release-fails"
version = "0.1.0"
edition = "2021"
publish = []

build = "build.rs"

[lib]
crate-type = ["staticlib"]

[build-dependencies]
swift-bridge-build = { git = "https://github.com/chinedufn/swift-bridge.git", branch = "master" }

[dependencies]
swift-bridge = { git = "https://github.com/chinedufn/swift-bridge.git", branch = "master", features = [
"async",
] }

[workspace]
26 changes: 26 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-fails/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// swift-tools-version:5.5.0
import PackageDescription
let package = Package(
name: "TestReleaseFails",
products: [
.library(
name: "TestReleaseFails",
targets: ["TestReleaseFails"]),
.executable(
name: "TestReleaseFailsRunner",
targets: ["TestReleaseFailsRunner"]),
],
dependencies: [],
targets: [
.binaryTarget(
name: "RustXcframework",
path: "RustXcframework.xcframework"
),
.target(
name: "TestReleaseFails",
dependencies: ["RustXcframework"]),
.executableTarget(
name: "TestReleaseFailsRunner",
dependencies: ["TestReleaseFails"])
]
)
7 changes: 7 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-fails/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Test Release Builds Fail

This test is a reproduction case for when building for release,
previously as `extern "Swift"` functions were `internal`
the Swift compiler would strip these, as it would infer
that they were dead code, even though these need to be accessible
from the Rust side of the FFI.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Foundation

func add(lhs: Int32, rhs: Int32) -> Int32 {
lhs + rhs
}
13 changes: 13 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-fails/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use std::path::PathBuf;

fn main() {
let out_dir = PathBuf::from("./generated");

let bridges = vec!["src/lib.rs"];
for path in &bridges {
println!("cargo:rerun-if-changed={}", path);
}

swift_bridge_build::parse_bridges(bridges)
.write_all_concatenated(out_dir, env!("CARGO_PKG_NAME"));
}
44 changes: 44 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-fails/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

PACKAGE_NAME=test-release-fails
LIBRARY_NAME=test_release_fails
SWIFT_PACKAGE_NAME=TestReleaseFails
EXECUTABLE_TARGET_NAME="$SWIFT_PACKAGE_NAME"Runner

set -e

THISDIR=$(dirname $0)
cd $THISDIR

echo "Building for macOS..."
rustup target add x86_64-apple-darwin aarch64-apple-darwin
cargo build --target x86_64-apple-darwin --release
cargo build --target aarch64-apple-darwin --release
mkdir -p ./target/universal-macos/release
lipo \
./target/aarch64-apple-darwin/release/lib$LIBRARY_NAME.a \
./target/x86_64-apple-darwin/release/lib$LIBRARY_NAME.a -create -output \
./target/universal-macos/release/lib$LIBRARY_NAME.a

function create_package {
swift-bridge-cli create-package \
--bridges-dir ./generated \
--out-dir $SWIFT_PACKAGE_NAME \
--ios ./target/universal-macos/release/lib$LIBRARY_NAME.a \
--name $SWIFT_PACKAGE_NAME
}

function patch_package {
cp Package.swift $SWIFT_PACKAGE_NAME/Package.swift
mkdir -p $SWIFT_PACKAGE_NAME/Sources/$EXECUTABLE_TARGET_NAME
cp main.swift $SWIFT_PACKAGE_NAME/Sources/$EXECUTABLE_TARGET_NAME/main.swift
cp SwiftExterns.swift $SWIFT_PACKAGE_NAME/Sources/$SWIFT_PACKAGE_NAME/SwiftExterns.swift
}

echo "Creating Swift package..."
create_package
patch_package

echo "Building for release..."
cd $SWIFT_PACKAGE_NAME
xcodebuild archive -scheme $EXECUTABLE_TARGET_NAME -archivePath ./build/$EXECUTABLE_TARGET_NAME.xcarchive -destination "platform=macOS"
4 changes: 4 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-fails/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Foundation
import TestReleaseFails

call_swift_add()
14 changes: 14 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-fails/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[swift_bridge::bridge]
mod ffi {
extern "Rust" {
fn call_swift_add();
}

extern "Swift" {
fn add(lhs: i32, rhs: i32) -> i32;
}
}

fn call_swift_add() {
assert!(ffi::add(1, 1) == 2);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
generated/*
.build/*
target/*
Cargo.lock
TestReleaseSucceeds/*
18 changes: 18 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-succeeds/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "test-release-succeeds"
version = "0.1.0"
edition = "2021"
publish = []

build = "build.rs"

[lib]
crate-type = ["staticlib"]

[build-dependencies]
swift-bridge-build = { path = "../../crates/swift-bridge-build" }

[dependencies]
swift-bridge = { path = "../../", features = ["async"] }

[workspace]
26 changes: 26 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-succeeds/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// swift-tools-version:5.5.0
import PackageDescription
let package = Package(
name: "TestReleaseSucceeds",
products: [
.library(
name: "TestReleaseSucceeds",
targets: ["TestReleaseSucceeds"]),
.executable(
name: "TestReleaseSucceedsRunner",
targets: ["TestReleaseSucceedsRunner"]),
],
dependencies: [],
targets: [
.binaryTarget(
name: "RustXcframework",
path: "RustXcframework.xcframework"
),
.target(
name: "TestReleaseSucceeds",
dependencies: ["RustXcframework"]),
.executableTarget(
name: "TestReleaseSucceedsRunner",
dependencies: ["TestReleaseSucceeds"])
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Test Release

This test makes sure that when building for release,
the Swift compiler doesn't strip functions that need to be accessible
from the Rust side of the FFI.
This test verifies that by making `extern "Swift"` functions `public`
release builds now succeed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Foundation

func add(lhs: Int32, rhs: Int32) -> Int32 {
lhs + rhs
}
13 changes: 13 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-succeeds/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use std::path::PathBuf;

fn main() {
let out_dir = PathBuf::from("./generated");

let bridges = vec!["src/lib.rs"];
for path in &bridges {
println!("cargo:rerun-if-changed={}", path);
}

swift_bridge_build::parse_bridges(bridges)
.write_all_concatenated(out_dir, env!("CARGO_PKG_NAME"));
}
44 changes: 44 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-succeeds/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

PACKAGE_NAME=test-release-succeeds
LIBRARY_NAME=test_release_succeeds
SWIFT_PACKAGE_NAME=TestReleaseSucceeds
EXECUTABLE_TARGET_NAME="$SWIFT_PACKAGE_NAME"Runner

set -e

THISDIR=$(dirname $0)
cd $THISDIR

echo "Building for macOS..."
rustup target add x86_64-apple-darwin aarch64-apple-darwin
cargo build --target x86_64-apple-darwin --release
cargo build --target aarch64-apple-darwin --release
mkdir -p ./target/universal-macos/release
lipo \
./target/aarch64-apple-darwin/release/lib$LIBRARY_NAME.a \
./target/x86_64-apple-darwin/release/lib$LIBRARY_NAME.a -create -output \
./target/universal-macos/release/lib$LIBRARY_NAME.a

function create_package {
swift-bridge-cli create-package \
--bridges-dir ./generated \
--out-dir $SWIFT_PACKAGE_NAME \
--ios ./target/universal-macos/release/lib$LIBRARY_NAME.a \
--name $SWIFT_PACKAGE_NAME
}

function patch_package {
cp Package.swift $SWIFT_PACKAGE_NAME/Package.swift
mkdir -p $SWIFT_PACKAGE_NAME/Sources/$EXECUTABLE_TARGET_NAME
cp main.swift $SWIFT_PACKAGE_NAME/Sources/$EXECUTABLE_TARGET_NAME/main.swift
cp SwiftExterns.swift $SWIFT_PACKAGE_NAME/Sources/$SWIFT_PACKAGE_NAME/SwiftExterns.swift
}

echo "Creating Swift package..."
create_package
patch_package

echo "Building for release..."
cd $SWIFT_PACKAGE_NAME
xcodebuild archive -scheme $EXECUTABLE_TARGET_NAME -archivePath ./build/$EXECUTABLE_TARGET_NAME.xcarchive -destination "platform=macOS"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Foundation
import TestReleaseSucceeds

call_swift_add()
14 changes: 14 additions & 0 deletions SwiftRustIntegrationTestRunner/test-release-succeeds/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[swift_bridge::bridge]
mod ffi {
extern "Rust" {
fn call_swift_add();
}

extern "Swift" {
fn add(lhs: i32, rhs: i32) -> i32;
}
}

fn call_swift_add() {
assert!(ffi::add(1, 1) == 2);
}
1 change: 1 addition & 0 deletions crates/swift-bridge-ir/src/codegen/codegen_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ mod string_codegen_tests;
mod transparent_enum_codegen_tests;
mod transparent_struct_codegen_tests;
mod vec_codegen_tests;
mod visibility_codegen_tests;

struct CodegenTest {
bridge_module: BridgeModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ mod test_swift_takes_no_args_no_return_callback {
ExpectedSwiftCode::ContainsAfterTrim(
r#"
@_cdecl("__swift_bridge__$some_function")
func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
{ let cb0 = __private__RustFnOnceCallbackNoArgsNoRet(ptr: callback); let _ = some_function(callback: { cb0.call() }) }()
}
"#,
Expand Down Expand Up @@ -149,7 +149,7 @@ class __private__RustFnOnceCallback$some_function$param0 {
"#,
r#"
@_cdecl("__swift_bridge__$some_function")
func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
{ let cb0 = __private__RustFnOnceCallback$some_function$param0(ptr: callback); let _ = some_function(callback: { arg0 in cb0.call(arg0) }) }()
}
"#,
Expand Down Expand Up @@ -248,7 +248,7 @@ class __private__RustFnOnceCallback$some_function$param0 {
"#,
r#"
@_cdecl("__swift_bridge__$some_function")
func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
{ let cb0 = __private__RustFnOnceCallback$some_function$param0(ptr: callback); let _ = some_function(callback: { cb0.call() }) }()
}
"#,
Expand Down Expand Up @@ -351,7 +351,7 @@ class __private__RustFnOnceCallback$some_function$param0 {
"#,
r#"
@_cdecl("__swift_bridge__$some_function")
func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
{ let cb0 = __private__RustFnOnceCallback$some_function$param0(ptr: callback); let _ = some_function(callback: { arg0 in cb0.call(arg0) }) }()
}
"#,
Expand Down Expand Up @@ -457,7 +457,7 @@ class __private__RustFnOnceCallback$some_function$param0 {
"#,
r#"
@_cdecl("__swift_bridge__$some_function")
func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
{ let cb0 = __private__RustFnOnceCallback$some_function$param0(ptr: callback); let _ = some_function(callback: { cb0.call() }) }()
}
"#,
Expand Down Expand Up @@ -566,7 +566,7 @@ class __private__RustFnOnceCallback$some_function$param0 {
"#,
r#"
@_cdecl("__swift_bridge__$some_function")
func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
{ let cb0 = __private__RustFnOnceCallback$some_function$param0(ptr: callback); let _ = some_function(callback: { arg0 in cb0.call(arg0) }) }()
}
"#,
Expand Down Expand Up @@ -690,7 +690,7 @@ class __private__RustFnOnceCallback$some_function$param1 {
"#,
r#"
@_cdecl("__swift_bridge__$some_function")
func __swift_bridge__some_function (_ arg0: UnsafeMutableRawPointer, _ arg1: UnsafeMutableRawPointer, _ arg2: UnsafeMutableRawPointer) {
public func __swift_bridge__some_function (_ arg0: UnsafeMutableRawPointer, _ arg1: UnsafeMutableRawPointer, _ arg2: UnsafeMutableRawPointer) {
{ let cb0 = __private__RustFnOnceCallbackNoArgsNoRet(ptr: arg0); let cb1 = __private__RustFnOnceCallback$some_function$param1(ptr: arg1); let cb2 = __private__RustFnOnceCallbackNoArgsNoRet(ptr: arg2); let _ = some_function(arg0: { cb0.call() }, arg1: { arg0 in cb1.call(arg0) }, arg2: { cb2.call() }) }()
}
"#,
Expand Down Expand Up @@ -793,7 +793,7 @@ class __private__RustFnOnceCallback$some_function$param0 {
"#,
r#"
@_cdecl("__swift_bridge__$some_function")
func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__some_function (_ callback: UnsafeMutableRawPointer) {
{ let cb0 = __private__RustFnOnceCallback$some_function$param0(ptr: callback); let _ = some_function(callback: { arg0, arg1 in cb0.call(arg0, arg1) }) }()
}
"#,
Expand Down Expand Up @@ -865,7 +865,7 @@ mod test_swift_method_takes_no_args_no_return_callback {
ExpectedSwiftCode::ContainsAfterTrim(
r#"
@_cdecl("__swift_bridge__$SomeType$some_method")
func __swift_bridge__SomeType_some_method (_ this: UnsafeMutableRawPointer, _ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__SomeType_some_method (_ this: UnsafeMutableRawPointer, _ callback: UnsafeMutableRawPointer) {
{ let cb1 = __private__RustFnOnceCallbackNoArgsNoRet(ptr: callback); let _ = Unmanaged<SomeType>.fromOpaque(this).takeUnretainedValue().some_method(callback: { cb1.call() }) }()
}
"#,
Expand Down Expand Up @@ -967,7 +967,7 @@ class __private__RustFnOnceCallback$SomeType$some_method$param1 {
"#,
r#"
@_cdecl("__swift_bridge__$SomeType$some_method")
func __swift_bridge__SomeType_some_method (_ this: UnsafeMutableRawPointer, _ callback: UnsafeMutableRawPointer) {
public func __swift_bridge__SomeType_some_method (_ this: UnsafeMutableRawPointer, _ callback: UnsafeMutableRawPointer) {
{ let cb1 = __private__RustFnOnceCallback$SomeType$some_method$param1(ptr: callback); let _ = Unmanaged<SomeType>.fromOpaque(this).takeUnretainedValue().some_method(callback: { arg0 in cb1.call(arg0) }) }()
}
"#,
Expand Down
Loading