How to make custom importable module without SPM?

Hi,

Is there a way to compile a swift program into an importable module from Terminal without using SPM? I had successfully use swiftc to produce .swiftmodule file– with -emit-object, -emit-library, and -emit-module –but I'm still unable to import the generated module in a swift program. Swift compiler keeps complaining the module isn't available though it's in the path. Did I miss anything?

Thank you.

Regards.

~Bee

1 Like

Hi.

i don't understand your question.

importable module from Terminal without using SPM: this means import a module in REPL?
I'm still unable to import the generated module in a swift program: this means that you want to import a module (without sharing sources) in another swift project? Or simply import the module.

Below

Import shared object
Compile your client module with

swift build -Xswiftc=-I -Xswiftc LIBPATH -Xswiftc -L -Xswiftc LIBPATH -Xswiftc -lLIBNAME

where LIBPATH is the folder which contains .swiftmodule and .so library file and LIBNAME is the standard unix library name.

Library project should use this piece of Package.swift file
products: [
.library(name: "LIBNAME", type: .dynamic, targets: ["LIBNAME"])
],
to produce a shared library file .so.

Import simple module
To import a module you should import a repository with the
dependencies: [
.package(url: "GITURL", from:"TAG")
`],

Import module in REPL
see Swift.org - REPL Support for Swift Packages

Not in REPL, but in compiled swift program, using swiftc.

Import a binary swift module (no source included) in a swift program.

I know but the program would search the lib in absolute path of the given LIBPATH. The main program couldn't find the lib even if I put the .so in /usr/lib (which is a common path for shared libs). Is there a way to change this behavior? At least to make it locates the lib on relative path to the main program.

As I said, I don't want to use SPM.

I'm on Swift 4.2 and not using REPL.

Thank you for your response.

This is strange, my project works fine with the library in /usr/lib/libname/

The content of my folder is:
libname.swiftdoc
libname.swiftmodule
libname.so

Mmm i don't know this. The main problem is why the first and standard solution don't works for you.
What is the S.O?

Thank you, I've solved the problem. I did many things that I forgot what I've done. But here's what I did on my Mac that works.

  • Here's the content of main.swift:

    import myModule
    hello()
    
  • Here's the content of myModule.swift:

    public func hello() {
      print("Hello world!")
    }
    
  • Project folder structure:

    +- myProject
       +– .build
       |  +- Debug
       |  +- Release
       |  +- Module
       +- module
       |  +- myModule.swift
       +- main.swift
    
  • Compile mySwift.swift module using these commands in order:

    $ swiftc -emit-object module/myModule.swift -o .build/Module/myModule.o -Onone -g
    $ swiftc -emit-library module/myModule.swift -o .build/Module/libmyModule.dylib -Onone -g
    $ swiftc -emit-module module/myModule.swift -o .build/Module/myModule.swiftmodule -Onone -g
    
  • Compile main.swift using this command:

    $ swiftc main.swift -I .build/Module -L .build/Module -o .build/Debug/myProject -Onone -g -lmyModule
    

At this stage, I had:

  • myModule.dylib and myModule.swiftmodule in .build/Module folder.
  • myProject binary in .build/Debug folder.

If I run myProject binary at this stage, everything went fine. If I moved the module files (both the .dylib and .swiftmodule files) to any searchable paths (e.g. /usr/lib and /usr/local/lib), it went fine too. Only if I moved them out of searchable paths then it didn't work because it couldn't find the required library. So, everything works as expected.

Thank you.