SwiftPM unable to wrap C library installed via Homebrew

Hi,

Although my question is specific to ncurses, I suspect it may apply to any libraries included in OS X. I'm trying to wrap the ncurses library by setting up a system library target on my Package.swift and creating a modulemap. However, what differs in my case is that I'm trying to wrap not the default version of ncurses bundled with OS X, but a different version installed via Homebrew.
When compiling this results in multiple errors:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:16:10: note: while building module 'Darwin' imported from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:16:
#include <sys/types.h>
^
:356:9: note: in file included from :356:
#import "ncurses.h"
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/ncurses.h:141:10: note: in file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/ncurses.h:141:
#include <unctrl.h>
^
/usr/local/Cellar/ncurses/6.1/include/ncursesw/unctrl.h:60:54: error: a parameter list without types is only allowed in a function definition
NCURSES_EXPORT(NCURSES_CONST char ) NCURSES_SP_NAME(unctrl) (SCREEN, chtype);
^
:1:9: note: in file included from :1:
#import "Headers/CoreFoundation.h"
^
/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:16:10: error: could not build module 'Darwin'
#include <sys/types.h>
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFStream.h:20:10: note: while building module 'Dispatch' imported from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFStream.h:20:
#include <dispatch/dispatch.h>
^
:1:9: note: in file included from :1:
#import "dispatch.h"
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/dispatch/dispatch.h:25:10: error: could not build module 'Darwin'
#include <Availability.h>
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFStream.h:20:10: note: while building module 'Dispatch' imported from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFStream.h:20:
#include <dispatch/dispatch.h>
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/dispatch/dispatch.h:48:10: note: while building module 'os_object' imported from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/dispatch/dispatch.h:48:
#include <os/object.h>
^
:1:9: note: in file included from :1:
#import "os/object.h"
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/os/object.h:25:10: error: could not build module 'Darwin'
#include <Availability.h>
^
:0: error: could not build Objective-C module 'CoreFoundation'

...

This is what my Package.swift looks like this:

// swift-tools-version:5.0
import PackageDescription

let package = Package(
    name: "NcursesExample",
    products: [
        .executable(name: "NcursesExample", targets: ["NcursesExample"]),
    ],
    dependencies: [
    ],
    targets: [
        .systemLibrary(name: "Cncurses"),
        .target(name: "NcursesExample", dependencies: ["Cncurses"]),
    ]
)

module.modulemap:

module Cncurses [system] {
  header "shim.h"
  link "ncursesw"
  link "panelw"
  export *
}

shim.h:

#include "/usr/local/Cellar/ncurses/6.1/include/ncursesw/panel.h"
#include "/usr/local/Cellar/ncurses/6.1/include/ncursesw/ncurses.h"

Based on the information present on the ncurses pkg-config, I'm trying to compile using the following command:

swift build -Xcc -D_DARWIN_C_SOURCE -Xcc -I/usr/local/Cellar/ncurses/6.1/include/ncursesw -Xcc -I/usr/local/Cellar/ncurses/6.1/include -Xlinker -L/usr/local/Cellar/ncurses/6.1/lib

Am I missing something obvious here? Thanks!

I'm brand new to SwiftPM, but I think your problem is that you need to specify in your Package.swift file in the dependencies array the path to your Cncurses directory like this:

// swift-tools-version:5.0
import PackageDescription

let package = Package(
    name: "NcursesExample",
    products: [
        .executable(name: "NcursesExample", targets: ["NcursesExample"]),
    ],
    dependencies: [
        .package(url: "../Cncurses", from: "0.0.1")
    ],
    targets: [
        .systemLibrary(name: "Cncurses"),
        .target(name: "NcursesExample", dependencies: ["Cncurses"]),
    ]
)

As you can see, you also have to put Cncurses under git versioning, and then tag it with a version number like 0.0.1.

No, that isn't necessary as I'm using a systemLibrary target which I'm already declaring ncurses depends on. The issue here is the fact MacOS SDK already includes a different version of ncurses which causes the conflicts.

I managed to make this compile using the approach suggested in this StackOverflow answer, but this is far from ideal...

Terms of Service

Privacy Policy

Cookie Policy