C interop, 6 of 7
Native libraries in project.toml
Name a package's C libraries in [native], static, system, or dynamic, and point Extern blocks at them with Lib.
What you’ll build
A package, roots, that calls cbrt and hypot from C’s math library, which it names in
project.toml. Then the other two kinds of C library a package can bring: a static archive in
its folder, linked into the executable, and a dynamic library, shipped beside it.
A library in [native]
A package’s C libraries are listed in its project.toml’s [native] table, each under a name.
An Extern "C" Lib "name" block says its functions are in that library. A system library is
one the system’s linker finds by its name, as -lm finds the math library.
[project]
name = "roots"
version = "0.1.0"
[native]
m = { system = "m" }Import std.core
Extern "C" Lib "m"
Function cbrt(x: Float64): Float64
Function hypot(x: Float64, y: Float64): Float64
End Extern
Print(cbrt(27.0))
Print(hypot(3.0, 4.0))3 5
Lib names a library of the package whose file declares the functions. A name that isn’t in
[native] is an error:
[project]
name = "roots"
version = "0.1.0"
[native]
m = { system = "m" }Import std.core
Extern "C" Lib "zlib"
Function crc32(crc: CULong, bytes: Ptr<UInt8>, count: UInt32): CULong
End Extern
Print("never built")Compiling roots v0.1.0 main.fb:3:16: error: the roots package's project.toml has no [native] library "zlib" | 3 | Extern "C" Lib "zlib" | ^^^^^^ error: couldn't build roots v0.1.0 because of 1 error
A function that isn’t in the library is an error when the program links, at the line that declares it, saying where it should have been:
[project]
name = "roots"
version = "0.1.0"
[native]
m = { system = "m" }Import std.core
Extern "C" Lib "m"
Function cbrt(x: Float64): Float64
Function no_such_function(x: Float64): Float64
End Extern
Print(cbrt(27.0), no_such_function(1.0))Compiling roots v0.1.0 main.fb:5:14: error: the C symbol 'no_such_function' isn't in m, or any library the program links | 5 | Function no_such_function(x: Float64): Float64 | ^^^^^^^^^^^^^^^^ error: couldn't link roots v0.1.0 because of 1 error
A static library
A static library is an archive in the package’s folder, by its path without its lib prefix
and extension: "libs/sqlite3" finds libs/libsqlite3.a, libs/sqlite3.a, or
libs/sqlite3.lib. It’s the default, so a plain string means the same:
[native]
sqlite3 = { static = "libs/sqlite3" }
zstd = "libs/zstd"A static library is linked into the executable, so the program is still one file, with nothing
to install beside it. On Windows, build the archive for the UCRT C runtime, which programs link, as
gcc’s -mcrtdll=ucrt does. A path that names no archive is an error at its line in
project.toml.
A dynamic library
A dynamic library is loaded as the program starts: a DLL on Windows, a .so on Linux, and a
.dylib on macOS. A package ships a build of it for each target it supports, and {target} in
the path is the target being built for: windows-x64, linux-x64, linux-arm64, macos-arm64,
or macos-x64.
[native]
codec = { dynamic = "native/{target}/codec" }On Windows that finds native/windows-x64/codec.dll and its import library beside it, and on
Linux native/linux-x64/libcodec.so. fb build copies each dynamic library the program needs
beside the executable, which finds it there, so the build folder is what you ship. Building for a
target the package has no binary for is an error that names the package.
FutureBlitz calls C, not C++, so a C++ library, static or dynamic, is used through its C API,
functions declared extern "C", which bindgen turns into an Extern
block.
What you learned
[native]lists a package’s C libraries, each by a name thatExtern "C" Lib "name"uses.systemlibraries are found by the linker,staticones are archives linked into the executable, anddynamicones are copied beside it.{target}in a path lets a package ship a binary for each target.- A missing library or symbol is an error that says where it should have been.
The rules are in the language reference.
Report an issue with this page or with FutureBlitz on GitHub.