Zulip Chat Archive
Stream: lean4
Topic: Compile package as plugin
Jannis Limperg (Aug 05 2021 at 11:37):
Does anyone know how to compile a Lean 4 package into a .so
that Lean can load with lean --plugin
? There are some previous conversations about this on Zulip and there's the test case in the Lean repo, but I'm still unable to figure this out. (My ignorance of C may have something to do with that.)
Wojciech Nawrocki (Aug 06 2021 at 00:50):
It seems leanmake
does not support plugins. I guess we'll have this in Lake. You could try this Makefile in the meantime
CFLAGS = -O3 -fPIC
%.olean : %.lean
LEAN_PATH=${HOME}/mathlib4/build/ lean -o $@ $<
%.c : %.lean
LEAN_PATH=${HOME}/mathlib4/build/ lean -c $@ $<
%.o : %.c
leanc -c $< -o $@ $(CFLAGS)
%.so : %.o
leanc -shared -x none $< -L${HOME}/mathlib4/build/lib/ -lMathlib -o $@ $(CFLAGS)
And then make MyPlugin.so
.
Wojciech Nawrocki (Aug 06 2021 at 00:51):
(Btw, that links against Mathlib. If you don't need Mathlib4, remove the LEAN_PATH=..mathlib
and -L..mathlib..
and -lMathlib
.
Mac (Aug 06 2021 at 00:52):
@Wojciech Nawrocki Do you know if this works on Windows yet? if I recall correctly, plugins with Lean code need to link to the Lean binary, and this does not work properly on the Windows MSYS2 build of Lean.
Wojciech Nawrocki (Aug 06 2021 at 00:54):
I would not expect that to work on MSYS2 Windows, no :/ I use WSL.
Sebastian Ullrich (Aug 06 2021 at 07:27):
It's kind of weird that even that works given that the stdlib is not yet compiled with fPIC
Sebastian Ullrich (Aug 06 2021 at 07:28):
If anyone wants to debug https://github.com/leanprover/lean4/pull/555 on Windows, please do
Jannis Limperg (Aug 06 2021 at 15:37):
@Wojciech Nawrocki Your recipe works (thanks!), but apparently not with plugins that use initialize
. Full MWE:
Plugin.lean:
import Lean
open Lean
open Lean.Elab.Tactic
initialize opt : Lean.Option Bool <-
Option.register `opt { defValue := true, group := "", descr := "" }
syntax (name := aesop) &"aesop" : tactic
@[tactic aesop]
def evalAesop : Tactic := λ _ => do evalTactic (<- `(tactic| assumption))
Client.lean:
import Plugin
example (h : α) : α := by aesop
Makefile:
CFLAGS = -O3 -fPIC
Client.olean : Client.lean Plugin.so Plugin.olean
env LEAN_PATH="." lean --plugin=Plugin.so -o Client.olean Client.lean
%.olean : %.lean
lean -o $@ $<
%.c : %.lean
lean -c $@ $<
%.o : %.c
leanc -c $< -o $@ $(CFLAGS)
%.so : %.o
leanc -shared -x none $< -o $@ $(CFLAGS)
.PHONY: clean
clean:
rm -rf Plugin.olean Plugin.so Plugin.c Plugin.so Client.olean
make Client.olean
fails with
Client.lean:1:0: error: invalid option declaration 'opt', option already exists
When I remove the initialize
block from Plugin.lean
, the same command succeeds.
Wojciech Nawrocki (Aug 06 2021 at 18:08):
Note that the current version (commit a230fe2) runs initialize
blocks on import
, so if you just want the custom option you don't need a plugin. The error you're seeing is because Lean tries to run your initialize
twice -- once from the --plugin
and once because you import Plugin
.
Mario Carneiro (Aug 06 2021 at 18:21):
How does the plugin option impact the environment? Is it as though you had import Plugin
in every file?
Jannis Limperg (Aug 06 2021 at 18:30):
Wojciech Nawrocki said:
Note that the current version (commit a230fe2) runs
initialize
blocks onimport
, so if you just want the custom option you don't need a plugin. The error you're seeing is because Lean tries to run yourinitialize
twice -- once from the--plugin
and once because youimport Plugin
.
Yeah, everything works fine without the --plugin
. I'm writing a search tactic that would benefit from being compiled. But this is not urgent, so I'll just wait until initialize
works in plugins. I could also split the library into an initialize
part and a compiled part; that might be okay.
Wojciech Nawrocki (Aug 06 2021 at 18:36):
Mario Carneiro said:
How does the plugin option impact the environment? Is it as though you had
import Plugin
in every file?
AFAIK it shouldn't impact the environment at all. Using --plugin
will run the initialize
blocks and that's it. So you can register custom linters, options, and so on. But for the def
s, you need a manual import
.
Mario Carneiro (Aug 06 2021 at 18:51):
Doesn't that mean that it is problematic to import
something that is also --plugin
'd? Since you will have to somehow dodge the initialize
but do everything else
Wojciech Nawrocki (Aug 06 2021 at 18:57):
Yeah, I suppose it does. You could have a do-once mechanism with an IO.Ref Bool
. This part of the system still seems a bit in flux.
Wojciech Nawrocki (Aug 06 2021 at 18:59):
Or maybe Lean could auto-insert those. The semantics of initialize
are not very clear (to me, at least).
Sebastian Ullrich (Aug 06 2021 at 19:30):
Yes, it's not expected to also import a plugin, though we should probably make sure it still works since you might not be able to avoid it in case of some shared module. I'm not sure initialize
being run in a plugin is even intended, usually builtin*
means "run when native code is loaded, register into some global IO.Ref" and non-builtin means "run when imported, register into the environment".
Mac (Aug 07 2021 at 00:45):
To clarify @Sebastian Ullrich's point @Jannis Limperg, you should use builtin_initialize
if you are planning to use the module via a --plugin
and initialize
only if you are planning to use the module via import
.
Last updated: Dec 20 2023 at 11:08 UTC