SwiftPM: "missing required module" when compiling with a library dependency and a C subdependency (Yams) - Steps to repro included

Hello,

I'm having difficulties with a SPM plugin I'm working on for use with danger-swift (Danger Swift). Without getting into the weeds of how danger swift is implemented, at a high level a developer writes a swift package that is ultimately imported as a dependency and compiled using swiftc by danger-swift under the hood.

I wanted to use the yaml file parsing library Yams (GitHub - jpsim/Yams: A Sweet and Swifty YAML parser.) as a dependency. Yams itself has a C dependency CYaml that seems to be causing issues when using swiftc from the command line.

Package.swift
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "YamsDebuggingPackage",
  platforms: [.macOS(.v10_13)],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "YamsDebuggingLib",
            targets: ["YamsDebugging"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
      .package(url: "https://github.com/jpsim/Yams.git", from: "4.0.3"),
      .package(url: "https://github.com/JohnSundell/ShellOut.git", from:"2.3.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.
        .target(
            name: "YamsDebugging",
          dependencies: 
          [
            "Yams",
            "ShellOut"
           ])
    ]
)
YamsDebugging.swift (ie the simplest possible file to achieve this import error)
import Foundation
import ShellOut
import Yams

Steps to reproduce:

  1. Create a new swift package project YamsDebugging and copy over the Package.swift and YamsDebugging.swift from above
  2. run swift build to compile the dependencies the first time
  3. then run swiftc --driver-mode=swift -g -v -L .build/debug -I .build/debug Sources/YamsDebugging/YamsDebugging.swift to attempt to compile a file with the Yams dependency. You will see the following in terminal:
Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
Target: x86_64-apple-darwin19.6.0
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret Sources/YamsDebugging/YamsDebugging.swift -enable-objc-interop -stack-check -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk -color-diagnostics -I .build/debug -g -enable-anonymous-context-mangled-names -target-sdk-version 11.1 -module-name YamsDebugging
Sources/YamsDebugging/YamsDebugging.swift:4:8: error: missing required module 'CYaml'
import Yams
  1. Comment out import Yams in YamsDebugging.swift and try again, the file compiles successfully.

I'm new to using the swiftc command line and am probably missing something very basic but I couldn't figure out possible flags or configurations I might have wrong? Any help would be greatly appreciated!

So the issue here is resolved when I manually add the modulemap using -Xcc -fmodule-map-file=.build/checkouts/Yams/Sources/CYaml/include/module.modulemap. I wish I could figure out a real way to solve this though as in the danger-swift implementation I don't get to modify the swiftc call in any way. I wonder why the CYaml modulemap is not included within CYaml.build?

This is deliberate to avoid that the module map would be picked up accidentally.

It would also only be a partial solution to this kind of problem, e.g. a package could declare custom linker or compiler flags in the manifest which would also not be part of an arbitrary swiftc invocation. It seems to me as if danger-swift's integration of packages would need to integrate deeper with SwiftPM to actually figure out the right compiler and linker flags required for a dependency.

Hmm that's too bad. It does seem like a pitfall to invoking swiftc manually. Thanks for the reply :+1: