This repository contains documentation on building Swift libraries using only swiftc
. There are examples presented in the repository. Below is some basic documentation.
Let's say we have a library consisting of files mylib.swift, mylib2.swift, lib.h and lib.c. We'll build these into a library and module both statically and dynamically.
To build a dynamic Swift library run the following command on macOS, Linux and Windows
swiftc -parse-as-library -emit-module -emit-library -module-name NAME_OF_SWIFT_MODULE mylib.swift mylib2.swift
To build a dynamic C Library run the following command on macOS (.dylib), Linux (.so) and Windows (.dll)
clang -shared lib.c -o NAME_OF_C_MODULE(.dll/.so/.dylib)
For C modules you need to create a modulemap file, for example module.modulemap
module NAME_OF_C_MODULE {
header "lib.h"
export *
}
To use the libraries, you need to import them in the Swift file by
import NAME_OF_SWIFT_MODULE
import NAME_OF_C_MODULE
and compile the file with
swiftc -I. -L. -lNAME_OF_SWIFT_MODULE -lNAME_OF_C_MODULE main.swift
On Linux if you get an error "Cannot open shared object file: No such file or directory" when running the program, copy the dynamic libraries into /usr/local/lib and run sudo ldconfig
and it should fix it.
On Windows, at the moment, you have to specify the linker separately
swiftc -parse-as-library -use-ld=lld-link -emit-module -emit-library -static -module-name NAME_OF_SWIFT_MODULE mylib.swift mylib2.swift -o NAME_OF_SWIFT_MODULE.lib
clang -static -fuse-ld=llvm-lib lib.c -o NAME_OF_C_MODULE.lib
On Linux and macOS you have to explicity link the static library
swiftc -parse-as-library -emit-module -emit-library -static -module-name <NAME_OF_MODULE> mylib.swift mylib2.swift
clang -c -fPIC lib.c -o lib.o
ar r NAME_OF_C_MODULE.a lib.o
For C modules you need to create a modulemap file, for example
module NAME_OF_C_MODULE {
header "lib.h"
export *
}
To use the libraries, you need to import them by
import NAME_OF_SWIFT_MODULE
import NAME_OF_C_MODULE
and compile the file with
swiftc -I. -L. -lNAME_OF_SWIFT_MODULE -lNAME_OF_C_MODULE main.swift
also the methods need to be annotated by __declspec(dllexport)
, so you could do something like
#if _WIN32
#define SEBBU_LIB_EXPORT __declspec(dllexport)
#else
#define SEBBU_LIB_EXPORT __attribute__((visibility(default)))
#endif
You can also use Swift functions marked as @_cdecl from C:
swiftc -parse-as-library -emit-library -emit-module -module-name NAME_OF_SWIFT_MODULE library.swift
Static Swift libraries used by C-code only work on Linux at the moment (i.e. flag -static works only on Linux). Then as per usual compile the C executable with
clang -I. -L. -lNAME_OF_MODULE main.c -o main.exe
On linux you can use
readelf -a <file> | grep "Shared library"
(grep Shared is also enough) to find all the needed shared libraries of an executable or .so file.