System library targets - "package has unsupported layout; modulemap..."

I'm trying to include this module map as a system library target. (Note that adding this github project as a dependency already works perfectly.)

Structure:

<project>
  |
  - Sources
    |
    - <swift files>
    |
    - graphqlparser
      |
      - module.modulemap

But receiving the following error when building/generating xcodeproj:

$ swift package -Xswiftc -I/usr/local/include/graphqlparser/ -Xlinker -L/usr/local/lib generate-xcodeproj

'GraphQLParserSwift' /Users/<Me>/Documents/projects/graphql-parser-swift: **error:** package has unsupported layout; modulemap '/Users/<Me>/Documents/projects/graphql-parser-swift/Sources/graphqlparser/module.modulemap' should be inside the 'include' directory

Package.swift is this

// swift-tools-version:4.2
import PackageDescription

let package = Package(
    name: "GraphQLParserSwift",
    products: [
        .library(
            name: "GraphQLParserSwift",
            targets: ["GraphQLParserSwift"])
    ],
    targets: [
        .target(
            name: "GraphQLParserSwift",
            dependencies: ["CGraphQLParser"],
            path: "Sources"),
        .systemLibrary(
            name: "CGraphQLParser",
            path: "Sources/graphqlparser"),
//            pkgConfig: "libgraphqlparser",  this needs to be added to homebrew, open a PR.
//            providers: [
//                .brew(["libgraphqlparser"]),
//                .apt(["libgraphqlparser"]),
//                ]
//            ),
        .testTarget(
            name: "GraphQLParserSwiftTests", 
            dependencies: ["GraphQLParserSwift", "CGraphQLParser"],
            path: "Tests")
    ],
    swiftLanguageVersions: [.v4_2]
)

I also looked at this guide but it seems like the setup is somewhat different. Also curious if I could move the linux vs mac header files into a graphqlparser.h header but first just want to get this to work as-is.

@Aciid sorry for pinging you directly, but it seems like you've been able to help others here with system package issues. Does anything here stand out to you?

Still stuck. Any help would be much appreciated.

So, I cloned the repo you have linked in your original post and dug into it a bit. There are several things you will need to change to get this to work.

The biggest issue is that the Package.swift you shared in your original post has bad paths. By not having the "Sources", "Sources/graphqlparser", or "Tests" it causes SwiftPM to fall over dead without any meaningful errors. So we should probably see if there are open bug tickets to fix that.

After fixing that by creating these paths:
Sources/Swift
Sources/C
Tests

you will want to move your modulemap into the C directory.

When importing the C module into swift you will need to do conditional imports based on the OS like this:

#if os(linux)
import CGraphQLParserLinux
#else
import CGraphQLParserMac
#endif

Once you do that you should be able to use CGraphQLParse[Mac/Linux] in the swift file and create your swift bindings.

If you look at my SwiftyPOSIX project you can see how I am linking Swift and C. It should help you out a bit. I'm not using a system library target but you seem to have that part all figured out.

Good luck!

Thanks for helping!

So the repo I linked to is not the directory structure I've been trying to implement, it's simply the module map I'm using in a new directory structure. The directory structure was written down below it, but here it is again

<project>
  |
  - Sources
    |
    - <swift files>
    |
    - graphqlparser
      |
      - module.modulemap

So the paths are there. I'll try to use the format you suggested though and see if that works.

Looking at your Package.swift it doesn't look like you're using a .systemLibrary target, I guess I don't actually need that?

I don't in my case but you will with how yours is set up. They work pretty much the same in this context.

Also, sorry for missing how you had your directories setup.

Update, a much simpler setup that works!

Structure:

<project>
  |
  - Sources
    |
    - Swift
    | |
    | - <swift files>
    |
    - graphqlparser
      |
      - module.modulemap
      - graphqlparser.h

Module map:

module CGraphQLParser [system] {
    umbrella header  "graphqlparser.h"
    link "graphqlparser"
    export *
}

graphqlparser.h (umbrella header)

#import<c/GraphQLAstForEachConcreteType.h>
#import<c/GraphQLAst.h>
#import<c/GraphQLAstNode.h>
#import<c/GraphQLAstToJSON.h>
#import<c/GraphQLAstVisitor.h>
#import<c/GraphQLParser.h>

Package.swift:

// swift-tools-version:4.2
import PackageDescription

let package = Package(
    name: "GraphQLParserSwift",
    products: [
        .library(
            name: "GraphQLParserSwift",
            targets: ["GraphQLParserSwift"])
    ],
    targets: [
        .target(
            name: "GraphQLParserSwift",
            dependencies: ["CGraphQLParser"],
            path: "Sources/Swift"),
        .systemLibrary(
            name: "CGraphQLParser",
            path: "Sources/graphqlparser",
//            pkgConfig: "libgraphqlparser",  this needs to be added to homebrew, open a PR.
            providers: [
                .brew(["libgraphqlparser"]),
                .apt(["libgraphqlparser"]),
                ]
            ),
        .testTarget(
            name: "GraphQLParserSwiftTests", 
            dependencies: ["GraphQLParserSwift", "CGraphQLParser"],
            path: "Tests")
    ],
    swiftLanguageVersions: [.v4_2]
)

However, I still need to build xcode-proj with

-Xswiftc -I/usr/local/include/graphqlparser/ -Xlinker -L/usr/local/lib

E.g.

$ swift package -Xswiftc -I/usr/local/include/graphqlparser/ -Xlinker -L/usr/local/lib generate-xcodeproj

If I do the following

$ swift package generate-xcodeproj

and build in Xcode I get

ld: warning: Could not find auto-linked library 'graphqlparser'
Undefined symbols for architecture x86_64:
  "_graphql_ast_to_json", referenced from:
      GraphQLParserSwift.parse(query: Swift.String) throws -> GraphQLParserSwift.Document in QueryParser.o
  "_graphql_error_free", referenced from:
      GraphQLParserSwift.parse(query: Swift.String) throws -> GraphQLParserSwift.Document in QueryParser.o
  "_graphql_node_free", referenced from:
      $defer #1 () -> () in GraphQLParserSwift.parse(query: Swift.String) throws -> GraphQLParserSwift.Document in QueryParser.o
  "_graphql_parse_string", referenced from:
      closure #1 (Swift.UnsafeMutablePointer<Swift.UnsafePointer<Swift.Int8>?>) -> Swift.OpaquePointer? in GraphQLParserSwift.parse(query: Swift.String) throws -> GraphQLParserSwift.Document in QueryParser.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

However, swift build seems to build without hickup (though I haven't tested if the produced binary actually works in practice.)

Is there any way I can get the semantics of these flags automatically derived from the Package, header, or module map instead? Would love to be able to just do swift package generate-xcodeproj.

Terms of Service

Privacy Policy

Cookie Policy