Swift Package Manager – system-module and code


(Omri Mor) #1

I’m trying to link some Swift code a C library. I have generated a Swift package for the library, but the library cannot be directly used from Swift – it relies on some complex macros that cannot be imported.
I’ve created C code and header files that replace these macros with variables and functions (where applicable). I’d like to be able to have this code within the package for the library and have the C code be compiled so that Swift code is linked with both it and the library.

I think I can have the C code be in a different package and have the library package depend on it, but I’d prefer to avoid that – using the library from Swift is impossible without the C bridge, so it should be part of the same package.

Is this possible?

Thanks,
Omri Mor


(Andrey Fidrya) #2

It's possible to declare multiple submodules in Package.swift. For example:

import PackageDescription

let package = Package(
    name: "SQLite.swift",
    targets: [
        Target(
            name: "SQLite",
            dependencies: [
                .Target(name: "CSQLite")
            ]),
        Target(
            name: "CSQLite")
    ]
)

Sources/CSQLite/ contains sqlite3.c, module.map etc
Source/SQLite/ - contains Swift code.

···

--
Andrey

On 15 Jul 2016, at 20:56, Omri Mor via swift-users <swift-users@swift.org> wrote:

I’m trying to link some Swift code a C library. I have generated a Swift package for the library, but the library cannot be directly used from Swift – it relies on some complex macros that cannot be imported.
I’ve created C code and header files that replace these macros with variables and functions (where applicable). I’d like to be able to have this code within the package for the library and have the C code be compiled so that Swift code is linked with both it and the library.

I think I can have the C code be in a different package and have the library package depend on it, but I’d prefer to avoid that – using the library from Swift is impossible without the C bridge, so it should be part of the same package.

Is this possible?

Thanks,
Omri Mor
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Omri Mor) #3

That isn’t quite what I mean.

There’s a system-level library, in say /usr/local/lib/libfoo.dylib (or libfoo.so on Linux), with a header in /usr/local/include/foo.h.
foo.h has complex macros that cannot be imported into Swift, so they need a C wrapper/bridge.
This is, say, foo_bridge.c and foo_bridge.h, where the source code defines global variables and functions, as necessary, to replace the macros and the header file has extern variables and function declarations. This must be compiled into a library that itself links with libfoo.
To use libfoo from Swift, it must be linked with foo_bridge so that it can use the macro replacements.

Currently, I can create a package called CFoo and one called CFooBridge that depends on CFoo, and have Swift code (e.g. a Swift wrapper called Foo) depend on CFooBridge. However, this is not ideal. I would prefer that the bridging code is within the CFoo package, as using CFoo without the bridging code is impossible from Swift. It is this that I have not figured out how to do, or if it is possible.

Omri

···

On Jul 24, 2016, at 09:12, Andrey Fidrya <af@zabiyaka.com> wrote:

It's possible to declare multiple submodules in Package.swift. For example:

import PackageDescription

let package = Package(
    name: "SQLite.swift",
    targets: [
        Target(
            name: "SQLite",
            dependencies: [
                .Target(name: "CSQLite")
            ]),
        Target(
            name: "CSQLite")
    ]
)

Sources/CSQLite/ contains sqlite3.c, module.map etc
Source/SQLite/ - contains Swift code.

--
Andrey

On 15 Jul 2016, at 20:56, Omri Mor via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I’m trying to link some Swift code a C library. I have generated a Swift package for the library, but the library cannot be directly used from Swift – it relies on some complex macros that cannot be imported.
I’ve created C code and header files that replace these macros with variables and functions (where applicable). I’d like to be able to have this code within the package for the library and have the C code be compiled so that Swift code is linked with both it and the library.

I think I can have the C code be in a different package and have the library package depend on it, but I’d prefer to avoid that – using the library from Swift is impossible without the C bridge, so it should be part of the same package.

Is this possible?

Thanks,
Omri Mor
_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Andrey Fidrya) #4

Imho CFooBridge is unnecessary, bridging code can be added to CFoo itself.
For example, in CCurl some methods which can't be called directly from Swift
have additional wrappers in shim.h:

https://github.com/IBM-Swift/CCurl

In module.modulemap shim.h is used instead of system header,
and the system header is included in shim.h.

Regards,
Andrey

···

On 02 Aug 2016, at 06:51, Omri Mor <omri50@gmail.com> wrote:

That isn’t quite what I mean.

There’s a system-level library, in say /usr/local/lib/libfoo.dylib (or libfoo.so on Linux), with a header in /usr/local/include/foo.h.
foo.h has complex macros that cannot be imported into Swift, so they need a C wrapper/bridge.
This is, say, foo_bridge.c and foo_bridge.h, where the source code defines global variables and functions, as necessary, to replace the macros and the header file has extern variables and function declarations. This must be compiled into a library that itself links with libfoo.
To use libfoo from Swift, it must be linked with foo_bridge so that it can use the macro replacements.

Currently, I can create a package called CFoo and one called CFooBridge that depends on CFoo, and have Swift code (e.g. a Swift wrapper called Foo) depend on CFooBridge. However, this is not ideal. I would prefer that the bridging code is within the CFoo package, as using CFoo without the bridging code is impossible from Swift. It is this that I have not figured out how to do, or if it is possible.

Omri

On Jul 24, 2016, at 09:12, Andrey Fidrya <af@zabiyaka.com <mailto:af@zabiyaka.com>> wrote:

It's possible to declare multiple submodules in Package.swift. For example:

import PackageDescription

let package = Package(
    name: "SQLite.swift",
    targets: [
        Target(
            name: "SQLite",
            dependencies: [
                .Target(name: "CSQLite")
            ]),
        Target(
            name: "CSQLite")
    ]
)

Sources/CSQLite/ contains sqlite3.c, module.map etc
Source/SQLite/ - contains Swift code.

--
Andrey

On 15 Jul 2016, at 20:56, Omri Mor via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I’m trying to link some Swift code a C library. I have generated a Swift package for the library, but the library cannot be directly used from Swift – it relies on some complex macros that cannot be imported.
I’ve created C code and header files that replace these macros with variables and functions (where applicable). I’d like to be able to have this code within the package for the library and have the C code be compiled so that Swift code is linked with both it and the library.

I think I can have the C code be in a different package and have the library package depend on it, but I’d prefer to avoid that – using the library from Swift is impossible without the C bridge, so it should be part of the same package.

Is this possible?

Thanks,
Omri Mor
_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users