This PR prevents symbol clashes between (non-`@[export]`) definitions from different Lean packages. Previously, if two modules define a function with the same name and were transitively imported (even privately) by some downstream module, linking would fail due to a symbol clash. Similarly, if a user defined a symbol with the same name as one in the `Lean` library, Lean would use the core symbol even if one did not import `Lean`. This is solved by changing Lean's name mangling algorithm to include an optional package identifier. This identifier is provided by Lake via `--setup` when building a module. This information is weaved through the elaborator, interpreter, and compiler via a persistent environment extension that associates modules with their package identifier. With a package identifier, standard symbols have the form `lp_<pkg-id>_<mangled-def>`. Without one, the old scheme is used (i.e., `l_<mangled-def>`). Module initializers are also prefixed with package identifier (if any). For example, the initializer for a module `Foo` in a package `test` is now `initialize_test_Foo` (instead of `initialize_Foo`). Lake's default for native library names has also been adjusted accordingly, so that libraries can still, by default, be used as plugins. Thus, the default library name of the `lean_lib Foo` in `package test` will now be `libtest_Foo`. When using Lake to build the Lean core (i.e., `bootstrap = true`), no package identifier will be used. Thus, definitions in user packages can never have symbol clashes with core. Closes #222.
32 lines
939 B
C
32 lines
939 B
C
#include <stdio.h>
|
|
#include <lean/lean.h>
|
|
|
|
extern uint64_t my_length(lean_obj_arg);
|
|
|
|
// see https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=ffi-initialization
|
|
extern void lean_initialize_runtime_module();
|
|
extern void lean_initialize();
|
|
extern void lean_io_mark_end_initialization();
|
|
extern lean_object * initialize_rffi_RFFI(uint8_t builtin);
|
|
|
|
int main() {
|
|
lean_initialize_runtime_module();
|
|
lean_object * res;
|
|
// use same default as for Lean executables
|
|
uint8_t builtin = 1;
|
|
res = initialize_rffi_RFFI(builtin);
|
|
if (lean_io_result_is_ok(res)) {
|
|
lean_dec_ref(res);
|
|
} else {
|
|
lean_io_result_show_error(res);
|
|
lean_dec(res);
|
|
return 1; // do not access Lean declarations if initialization failed
|
|
}
|
|
lean_io_mark_end_initialization();
|
|
|
|
// actual program
|
|
|
|
lean_object * s = lean_mk_string("hello!");
|
|
uint64_t l = my_length(s);
|
|
printf("output: %ld\n", l);
|
|
}
|