Zulip Chat Archive
Stream: lean4
Topic: changes to lake and FFI
Tomas Skrivan (May 29 2025 at 11:10):
With recent changes to lake I'm unable to get my FFI setup working again.
To demonstrate the problem I have set up a simple project which has:
FFI/Basic.lean
def hello := "world"
FFI/Compiled.lean
@[extern "print_usize"]
opaque printUSize (n : USize) : IO Unit
FFI.lean
import FFI.Basic
import FFI.Compiled
Main.lean
import FFI
def main : IO Unit := do
IO.println s!"Hello, {hello}!"
printUSize 42
#eval main
lakefile.lean (inspired by lake ffi example)
lakefile.lean
I have few issues I do not know how to resolve:
lake buildhas no problem evaluating#eval mainbut infoview in VS Code and Emacs hangs on it.- How can I change the setup such that
FFI/Basic.leanis not compiled butFFI/Compiled.leanis compiled? The reason for doing this is thatFFI/Basic.leanimports large part of mathlib which I do not want to compile.
Previously I just replaced
lean_lib FFI where
roots := #[`FFI]
precompileModules := true
moreLinkObjs := #[libleanffi]
with
lean_lib FFI
lean_lib FFICompiled where
roots := #[`FFI.Compiled]
precompileModules := true
moreLinkObjs := #[libleanffi]
but now this fails with
info: stderr:
libc++abi: terminating due to uncaught exception of type lean::exception: error loading plugin, initializer not found 'initialize_FFICompiled'
error: Lean exited with code 134
Some required builds logged failures:
- FFI
Kim Morrison (May 29 2025 at 11:30):
@Mac Malone
Mac Malone (May 29 2025 at 15:16):
@Tomas Skrivan FFICompiled should be
lean_lib FFI.Compiled where
precompileModules := true
moreLinkObjs := #[libleanffi]
Tomas Skrivan (May 29 2025 at 15:18):
What if I have 20 lean files I want to compile? Do I have to make one lean_lib for each?
Tomas Skrivan (May 29 2025 at 15:22):
Why is the name of lean_lib important? It didn't use to be. The files to compile were specified through the roots field.
Tomas Skrivan (May 29 2025 at 15:30):
Ok, I can turn FFI.Compiled.lean into a folder and all the files in it will be compiled. I'm still confused about the lean_lib naming and the roots field.
Mac Malone (May 29 2025 at 15:31):
Tomas Skrivan said:
What if I have 20 lean files I want to compile? Do I have to make one
lean_libfor each?
The standard approach would to have a single precompiled root module which imports the 20.
Tomas Skrivan said:
Why is the name of
lean_libimportant? It didn't use to be. The files to compile were specified through therootsfield.
Lake now tries to load the library as plugin if it can (i.e., via lean --plugin instead of lean --load-dynlib). This requires the root and the library to be named in a speciifc way and Lake's heuristic for detecting this is currently inaccurate. lean4#8528 will fix this.
Tomas Skrivan (May 29 2025 at 16:52):
Why does the order of lean_lib matter?
This works:
lean_lib FFI
lean_lib FFI.Compiled where
precompileModules := true
moreLinkObjs := #[libleanffi]
but this does not:
lean_lib FFI.Compiled where
precompileModules := true
moreLinkObjs := #[libleanffi]
lean_lib FFI
Why is that? I find it quite confusing as there has to be some dependency between the two that is not explicitly written.
Mac Malone (May 29 2025 at 17:21):
Tomas Skrivan said:
Why does the order of
lean_libmatter?
Later libraries shadow earlier ones. Both FFI and FFI.Compiled match FFI.Compiled. That is, they overlap -- FFI matches any module FFI.* and FFI.Compiled matches any module FFI.Compiled.*. If FFI.Compiled comes later, its configuration is used; otherwise, the configuration of FFI is used.
Tomas Skrivan (May 30 2025 at 08:32):
Thanks! I have it working now on v4.19.0
Tomas Skrivan (May 30 2025 at 08:38):
However, not I'm trying to bump to v4.20.0-rc5 and I'm getting bunch of undefined reference errors. For examples:
ld.lld: error: undefined symbol: l_Array_emptyWithCapacity
>>> referenced by Congr.c
>>> /home/tskrivan/Documents/LeanBLAS/.lake/packages/batteries/.lake/build/ir/Batteries/Tactic/Congr.c.o.export:(initialize_Batteries_Tactic_Congr)
full error message
Right now I do not know how to minimize it. I'm updating LeanBLAS, this v4.19.0 commit works but this v4.20.0-rc5 commit does not.
Tomas Skrivan (May 30 2025 at 08:49):
Interestingly it fails with a different error on Linux during CI
info: stderr:
ld.lld: error: undefined symbol: __libc_csu_fini
>>> referenced by start.S:101 (../sysdeps/x86_64/start.S:101)
>>> /home/runner/.elan/toolchains/leanprover--lean4---v4.20.0-rc5/lib/Scrt1.o:(_start)
ld.lld: error: undefined symbol: __libc_csu_init
>>> referenced by start.S:102 (../sysdeps/x86_64/start.S:102)
>>> /home/runner/.elan/toolchains/leanprover--lean4---v4.20.0-rc5/lib/Scrt1.o:(_start)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: external command '/home/runner/.elan/toolchains/leanprover--lean4---v4.20.0-rc5/bin/clang' exited with code 1
Some required builds logged failures:
- CBLASLevelOneTest
error: build failed
and on MacOS it passes
Tomas Skrivan (May 30 2025 at 10:36):
Now I'm updating SciLean that uses LeanBLAS and I'm getting an odd error
✖ [1847/1856] Running LeanBLAS.FFI:shared
error: type mismtach in target 'libleanblasc': expected 'filepath', got unknown
where libleanblasc is the target in LeanBLAS that build the C library
target libleanblasc pkg : FilePath := do
...
buildStaticLib (pkg.sharedLibDir / name) (oFiles)
Tomas Skrivan (May 30 2025 at 11:21):
This makes me wonder if there is an issue when having a project with FFI as a dependency.
I try to reproduce it with the simple ffi project.
Mac Malone (May 30 2025 at 20:26):
The first set of errors seems like it may be an issue caused by an incompatibility with the new LLVM toolchain used in Lean v4.20.0. LLVM has been upgraded from 15 to 19. On your local machine, it might be worth clobbering the .lake directory and seeing if that changes the errors to mirror the CI (some aspect of the version update may have not been caught by Lake).
The 'filepath' issue, on the other hand, may more likely be a Lake problem.
Tomas Skrivan (Jun 07 2025 at 14:58):
I can't reproduce the filepath problem with the minimal example but with LeanBLAS
Steps to reproduce on Ubuntu:
$ sudo apt-get install libopenblas-dev
$ mkdir leanblasdep; cd leanblasdep
$ lake init leanblasdep .lean
replace lakefile.lean with:
import Lake
open Lake DSL
package "leanblasdep" where
version := v!"0.1.0"
moreLinkArgs := #["-L/usr/lib/x86_64-linux-gnu/", "-lblas", "-lm"]
lean_lib «Leanblasdep» where
@[default_target]
lean_exe "leanblasdep" where
root := `Main
require leanblas from git "https://github.com/lecopivo/LeanBLAS" @ "v4.20.1"
Now running lake build LeanBLAS.FFI:static produces this error:
$ lake build LeanBLAS.FFI:static
✖ [13/14] Building leanblas/libleanblasc
trace: .> gcc -c -o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/c/leveltwoext.o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/c/leveltwoext.c -I /home/tskrivan/.elan/toolchains/leanprover--lean4---v4.21.0-rc3/include -DNDEBUG -O3 -fPIC
trace: .> gcc -c -o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/c/util.o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/c/util.c -I /home/tskrivan/.elan/toolchains/leanprover--lean4---v4.21.0-rc3/include -DNDEBUG -O3 -fPIC
trace: .> gcc -c -o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/c/levelone.o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/c/levelone.c -I /home/tskrivan/.elan/toolchains/leanprover--lean4---v4.21.0-rc3/include -DNDEBUG -O3 -fPIC
trace: .> gcc -c -o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/c/leveltwo.o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/c/leveltwo.c -I /home/tskrivan/.elan/toolchains/leanprover--lean4---v4.21.0-rc3/include -DNDEBUG -O3 -fPIC
trace: .> /home/tskrivan/.elan/toolchains/leanprover--lean4---v4.21.0-rc3/bin/llvm-ar rcs /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/lib/libleanblasc.a /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/c/leveltwoext.o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/c/util.o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/c/levelone.o /home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/c/leveltwo.o
info: stderr:
/home/tskrivan/.elan/toolchains/leanprover--lean4---v4.21.0-rc3/bin/llvm-ar: error: unable to load '/home/tskrivan/doodle/lean/leanblasdep/.lake/packages/leanblas/.lake/build/lib/libleanblasc.a': file too small to be an archive
error: external command '/home/tskrivan/.elan/toolchains/leanprover--lean4---v4.21.0-rc3/bin/llvm-ar' exited with code 1
✖ [14/14] Running LeanBLAS.FFI:static
error: type mismtach in target 'libleanblasc': expected 'filepath', got unknown
Some required builds logged failures:
- leanblas/libleanblasc
- LeanBLAS.FFI:static
error: build failed
Tomas Skrivan (Jun 08 2025 at 10:26):
I can reproduce with the SimpleFFI project now.
mkdir SimpleFFIDep; cd SimpleFFIDep
lake init simpleffidep .lean
echo 'require ffi from git "https://github.com/lecopivo/SimpleFFI" @ "alt"' >> lakefile.lean
{ echo 'import FFI'; cat Main.lean; } > tmp.lean && mv tmp.lean Main.lean
lake update
lake build
which ends with
$ lake build
✖ [13/23] Running FFI.Compiled:shared
error: type mismtach in target 'libleanffi': expected 'filepath', got unknown
✖ [23/23] Running simpleffidep
error: type mismtach in target 'libleanffi': expected 'filepath', got unknown
Some required builds logged failures:
- FFI.Compiled:shared
- simpleffidep
error: build failed
Tomas Skrivan (Jun 08 2025 at 10:30):
It has to do something with building the *.c files with
code
vs
code
The first version works, the second does not. It is not clear to me how to generalize the first approach if I want to just compile all the *.c files in the c/ directory.
Tomas Skrivan (Jun 08 2025 at 10:34):
Ahh, it has something to do with pkg.afterBuildCacheAsync. It is leftover code when I was experimenting with github releases. Removing it solves the problem with filepath
Tomas Skrivan (Jun 08 2025 at 10:43):
However, I still have the problem executing ffi functions in the editor.
mwe:
git clone git@github.com:lecopivo/SimpleFFI.git
cd SimpleFFI
lake update
lake build
Open Main.lean in VS Code and the orange line does not go away for me. Same happens in emacs.
Arthur Paulino (Sep 18 2025 at 18:33):
Did anything change regarding the memory layout of Lean objects from 4.21 to 4.23? Like the ordering of constructor pointers or anything else?
Our FFI glue code is now segfaulting. We're trying to minimize the problem but any clue would help. Thanks a lot!
Arthur Paulino (Sep 18 2025 at 19:12):
(deleted)
Last updated: Dec 20 2025 at 21:32 UTC