Code Monkey home page Code Monkey logo

Comments (18)

Jomy10 avatar Jomy10 commented on August 18, 2024 2

Awesome. I'll be looking through the code of this package to get a better understanding of how this all works. After that I can have another attempt at converting to a Swift package.

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024 1

Hey!

If I'm understanding, you're saying that you'd like to be able to have the Rust side of things get packaged up into a Swift package that you can then import from your Swift project? Or are you saying something else?

I'll read up on Swift packages since I don't know much about them at the moment.

Would using Swift packages be strictly better to what we're currently doing, or are there any downsides?

Also, if you could explain your Swift+Rust use case that would be great - just so that I can better understand when and how Swift packages are typically used (I'm new to Swift).

Thanks for opening this issue!

from swift-bridge.

Jomy10 avatar Jomy10 commented on August 18, 2024 1

I do think that compiling to a Swift package could be a huge plus. Right now we can compile Swift code using swiftc and linking the rust library. This is great for cli's. However, if we could either compile the Rust code to a Swift library, or compile the Swift project that includes the Rust code to a Swift library, I think this could be a huge benefit.

If our Swift code is in package form, we can import it in every Swift project (as long as we have compiled our rust code to the right targets, of course).

Swift packages are similar to Rust crates, you can create one with mkdir myPackage && cd $_ && swift package init --type library (Swift Package Manager docs).

Other projects or packages can then depend on the package by specifying the package in the Package.swift file (see above for example of importing a package named HelloSwift in the package named swift).

I guess this would be similar to any other Swift package that wraps a C api (Can't remember a good, simple example, but here is one for LLVM: https://github.com/llvm-swift/llvmswift).

Really love this project, if you need any help, I would love to contribute where I can.


EDIT: I'll also do some research myself and will let you know if I get some working prototype

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024 1

Nice! Just let me know whenever you have any questions and I'll try to add answers to the currently empty internal design chapter.

from swift-bridge.

Jomy10 avatar Jomy10 commented on August 18, 2024 1

Aha! Seems like all I was missing was a modulemap file. I'll clean up what I have now and try it from scratch again.

I'll update you soon

from swift-bridge.

Jomy10 avatar Jomy10 commented on August 18, 2024 1

Ok, here's what I have. Source code on this branch.

1. Rust

I have a Rust project with these functions:

fn print_hello_rust() {
    println!("Hello from Rust!");
}

fn is_from_rust() -> bool {
    true
}

fn get_hello_rust() -> String {
    String::from("Hello Rust!")
}

Build the project like you would do usually with the build.rs file specified in the book.

2. XCFramework

The next step is to make the XCFramework.

Framework
├── include
│   ├── SwiftBridgeCore.h
│   ├── module.modulemap
│   └── rust.h
├── ios
│   └── librust.a
├── macos
│   └── librust.a
└── simulator
    └── librust.a

We have a folder for each target we build for our rust project and copied both header files as well.

We can then build the XCFramework

xcodebuild -create-xcframework \
    -library simulator/librust.a \
    -headers include \
    -library ios/librust.a \
    -headers include \
    -library macos/librust.a \
    -headers include \
    -output rust.xcframework

The order of the targets is important

Note: we could also build the framework without this command I think, as it is just a folder containing the different targets and a .plist file

3. Swift package

Now, we build the swift package that incorporates the XCFramework.

We copy the .xcframework file from the previous step to the root of this folder and add it as a binaryTarget to our Package.swift as well as include it as a dependency.

let package = Package(
    name: "package",
    products: [
        .library(
            name: "package",
            targets: ["package"]),
    ],
    dependencies: [

    ],
    targets: [
        .binaryTarget(
            name: "Rust",
            path: "rust.xcframework"
        ),
        .target(
            name: "package",
            dependencies: ["Rust"]),
    ]
)

Then, we copy the generated swift files to the Sources/{package_name} folder. In the swift file containing the functions, we make the functions public and add import {XCFramework name} (in this case import Rust).

Now, we should also make the methods in SwiftBridgeCore.swift public so we can call get_hello_rust().toString() in this example to convert a RustString to a String in swift, for example.

4. Testing

After the previous steps, we now have a Swift package that can be used in any project targeting MacOs or iOS (we can of course target other Apple devices as well if we build those targets).

Tested on an executable on MacOS and on the simulator for iOS, and a physical device.

Next steps

I can add a chapter to the book explaining the whole process in detail (basically the above, but a little more "cleaned up"). Let me know if you have any comments on the above.

Next would be generating a Swift package with the build file? I think you know best on how we should implement this into swift-bridge-build.

from swift-bridge.

josephg avatar josephg commented on August 18, 2024 1

Hey! just want to say thankyou so much for putting this together. Packaging my code as a swift package is way cleaner for my use case, and I appreciate the effort making it easy! Lots of gratitude for swift-bridge and this PR!

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024

Alright I read up on Swift packages on modules and have a basic understanding.

It seems like if I had to find the closest Rust ecosystem version of them..:

Swift Package == Cargo crate
Swift Module == Rust module

I know they aren't the same.. I'm just going for a rough understanding of what these Swift code organization tools are.


Ok so I'd sum up my current thoughts as:

  • I don't yet understand what your end goal is and would love an explanation / some context around how you're using Swift+Rust so that I can better understand why you want to be able to generate a Swift package.

from swift-bridge.

Jomy10 avatar Jomy10 commented on August 18, 2024

So far I've had no luck, my knowledge of C and headers is quite limited, though.

So far I have found the following:

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024

Thanks the gist and for all of the links. I've read through them and they were helpful as I start to get familiar with Swift packages / modules / etc.

Awesome work and research so far..


Really love this project, if you need any help, I would love to contribute where I can.

I'd love for you to contribute! Awesome, going forwards I'll start creating more issues and you can get involved wherever you like. Figuring out this Swift Package stuff might be a great place to start.


Alright.. I did some more reading and thinking and here's where I'm at.

  • We want people to be able to expose their Swift+Rust libraries as Swift Packages, Cocoapods, Carthage "packages" (not sure what they're really called), or any format that they want.

  • A good starting point would be to add documentation on how to take the current output of swift-bridge-build and turn it into a package yourself.

    • This will teach us about how to create packages and how they should be shaped. For example, right now we emit everything into the global module so everything has access to the SwiftBridgeCore.swift file that we generate. So we'd need to figure out how leveraging SwiftBridgeCore looks in a package world.. Or if it even still makes sense in a package world.
  • Then in the future we might decide to have swift-bridge-build know about some of these target formats so that it can emit a package for you based on some configuration values. Or we might decide that that is out of scope for the library. Who knows.. needs more thinking..


So, here's a potential path forwards (which I think you've already made progress on in your gist.)

  • Write a book chapter on how to take the Swift and C headers that swift-bridge-build currently outputs and bundle them up into a Swift package.

  • Open a pull request with wherever you get stuck (i.e. I think you were stuck on linking in the Rust library).

  • I'm comfortable with linking, so I can try to add a commit to the PR that adds linking related stuff to the chapter to finish up that piece (unless you end up figuring it out beforehand of course).

  • We clean up the PR and merge it. Now people have instructions on how to manually create their own Swift package. Then.. in the future.. we can think through whether or not we want swift-bridge-build to be able to automatically output a package (perhaps as a flag.. or at the default behavior.. who knows).


On the flip side.. we'll also want to eventually explore how to expose Swift + Rust code as a Cargo crate.. (first as documentation.. then later explore having swift-bridge-build emit a crate.. But that isn't important for this issue. Just jotting it down so we remember for the future.

from swift-bridge.

Jomy10 avatar Jomy10 commented on August 18, 2024

Ok, I have started looking at the internals of the project. I just wanted to finish a few of my own projects first before I tackled this.

So if I understand correctly, the swift-bridge-build crate generates the .h and .swift files found in the generated folder.

With swiftc we link those files and the .a file generated by cargo to the compiled swift program. So, if I figure out how to link all of those to an XCFramework, we have a standalone Swift package. I've been doing some research on XCFrameworks and will continue doing that now.

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024

Awesome!!

I'm not familiar with XCFramework but in general that all sounds about right.

from swift-bridge.

Jomy10 avatar Jomy10 commented on August 18, 2024

So far, I have packaged a system library and a c source file into a Swift package. I've had no luck with including a static library, though.

If you have any ideas on including the rust library, let me know, because so far I've had no luck.

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024

I think this might walk you through the entire process of going from Rust code to Swift package -> https://betterprogramming.pub/from-rust-to-swift-df9bde59b7cd

Let me know if that helps?

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024

A quote from Apple's documentation https://developer.apple.com/documentation/swift_packages/distributing_binary_frameworks_as_swift_packages :

In addition, binary dependencies are only available for Apple platforms, which limits the audience for your Swift package.

At the very least I think we'll want our own documentation to make it very clear to people that if they're creating a Swift package it can only be used on Apple hardware.

Which I'd imagine that the vast majority of users will be just fine with.
And we'll still support other output formats for people that aren't targeting Apple hardware (such as what we have right now with just spitting out files).

Not important right now.. Just dropping it here for us to keep in mind as we think through this stuff.

from swift-bridge.

Jomy10 avatar Jomy10 commented on August 18, 2024

I think this might walk you through the entire process of going from Rust code to Swift package -> https://betterprogramming.pub/from-rust-to-swift-df9bde59b7cd

Judging by the linked repo, I’m almost there with linking an XCFramework to Swift.

A quote from Apple's documentation

I’ve come across that as well, so unfortunately this approach will indeed not work for non-Apple devices. I haven’t come across any other solutions to this. I guess we will have to wait until some cross-platform solution comes around.

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024

Awesome work!

Adding a chapter to the book sounds great. My main feedback would be to call the crate something other than rust (such as my-rust-lib and call the package something other than package (such as my-rust-package) so that people can more easily keep track of what these artifacts are.


In terms of generating a package from programatically.. let's create a new issue for that. But yeah I'm happy to help figure out a good starting point for that. Thanks for making so much progress already!

from swift-bridge.

chinedufn avatar chinedufn commented on August 18, 2024

Closed by #30

from swift-bridge.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.