Skip to content

Instantly share code, notes, and snippets.

@briancroom briancroom/Swift.md
Last active Jul 16, 2019

Embed
What would you like to do?
How to create a Swift modular library

I am trying to determine if it is possible to build a Swift dynamic library which is itself composed of one of more private modules, without needing to expose to that fact to outside users. My hope was that I could build the private module as a static library, which would be linked into the primary (dynamic) library. The dylib could then be deployed together with its swiftmodule and swiftdoc and be imported, with the private module and its symbols not being exposed at all.

Unfortunately, what I'm currently observing seems to indicate that the private module's swiftmodule also has to be available for the primary library to be successfully imported.

This can be reproduced as follows. I have the following directory structure:

./Greeter/Logger/Logger.swift:

public func log(_ message: String) {
    print(fullLogString(message))
}

internal func fullLogString(_ message: String) -> String {
    return "(Logger): \(message)"
}

./Greeter/Greeter.swift:

import Logger

public func greet(_ name: String) {
    log("Hello \(name)!")
}

./main.swift:

import Greeter

greet("Swift")

I am building these as follows:

$ cd Greeter/Logger
$ swiftc -emit-object -emit-module -force-single-frontend-invocation -parse-as-library Logger.swift
$ ar -r libLogger.a Logger.o
$ cd ../
$ swiftc -emit-library -emit-module -parse-as-library -ILogger -lLogger -Xlinker -LLogger -Xlinker -install_name -Xlinker @rpath/libGreeter.dylib Greeter.swift
$ cd ../
$ swiftc -emit-executable -IGreeter -IGreeter/Logger -lGreeter -Xlinker -LGreeter -Xlinker -rpath -Xlinker Greeter main.swift

On the final command, if I omit the -IGreeter/Logger flag, compilation fails with the message:

main.swift:1:8: error: missing required module 'Logger'

So I'm wondering...

  1. Why is the Logger.swiftmodule necessary to complete the build, even though main.swift does not import it or use any symbols from it?
  2. Is there a way I could perform the build differently such that it wouldn't be needed?
  3. Where could I have started looking to figure out these answers on my own?
@Pitometsu

This comment has been minimized.

Copy link

commented May 4, 2017

@briancroom, thank you for sharing. Any news yet?
I'm trying get SPM load in swift repl: profburke/swiftreplmadness#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.