Skip to content

Instantly share code, notes, and snippets.

@briancroom
Last active February 6, 2024 18:26
Show Gist options
  • Select an option

  • Save briancroom/5d0f1b966fa9ef0ae4950e97f9d76f77 to your computer and use it in GitHub Desktop.

Select an option

Save briancroom/5d0f1b966fa9ef0ae4950e97f9d76f77 to your computer and use it in GitHub Desktop.

Revisions

  1. briancroom revised this gist May 17, 2016. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Swift.md
    Original file line number Diff line number Diff line change
    @@ -16,7 +16,7 @@ internal func fullLogString(_ message: String) -> String {
    }

    ```
    `./Greeter/Greeter.swift`
    `./Greeter/Greeter.swift`:

    ```swift
    import Logger
    @@ -25,7 +25,7 @@ public func greet(_ name: String) {
    log("Hello \(name)!")
    }
    ```
    `./main.swift`
    `./main.swift`:

    ```swift
    import Greeter
  2. briancroom renamed this gist May 17, 2016. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  3. briancroom created this gist May 17, 2016.
    57 changes: 57 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    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`:

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

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

    ```
    `./Greeter/Greeter.swift`

    ```swift
    import Logger

    public func greet(_ name: String) {
    log("Hello \(name)!")
    }
    ```
    `./main.swift`

    ```swift
    import Greeter

    greet("Swift")
    ```

    I am building these as follows:

    ```sh
    $ 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?