Zulip Chat Archive
Stream: lean4
Topic: Issue with linking
z battleman (Jul 31 2022 at 21:56):
I'm currently working on a project that uses openBLAS for optimized computation. I have a matrix multiplication function which is implented with cblas, and a matrix exponentiation function which is implemented with cblas as well. If its relevant, in Lean, the exponentiation function is defined by recursive calls to multiplication (but it's extern
'ed anyway) When I try to compile, I get
/home/z/.elan/toolchains/leanprover--lean4---nightly-2022-07-24/bin/lean: symbol lookup error: ./build/lib/libleanffi.so: undefined symbol: cblas_dgemm
but what's strange is that this only occurs when I use the exponentiation function. When I compile with just the multiplication function (which also uses cblas_dgemm
I have no issues.
If it helps, here is the exponentiation code
@[extern "mathMatrix_exp"]
def exp (M : mathMatrix n n) : (e : Nat) -> mathMatrix n n
| 0 => mathMatrix.id n
| Nat.succ m => M.multiply_MM (exp M m)
as well as the underlying FFI code
lean_object* mathMatrix_mul_MM(lean_object* m_, lean_object* n_, lean_object* k_, lean_object* M1_, lean_object* M2_) {
mathMatrix* M1 = mathMatrix_unboxer(M1_);
mathMatrix* M2 = mathMatrix_unboxer(M2_);
uint32_t m = M1->rows;
uint32_t n = M1->cols;
uint32_t k = M2->cols;
assert(n == M2->rows);
mathMatrix* out_struct = mathMatrix_alloc(m, k);
double* result = malloc(sizeof(double)*m*k);
for (size_t i = 0; i < m*k; i++) {
result[i] = 0.0;
}
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
m, k, n, 1.0, M1->data, n, M2->data, k, 0.0, result, k);
out_struct->data = result;
return mathMatrix_boxer(out_struct);
}
lean_object* mathMatrix_exp (lean_object* n_, lean_object* M_, lean_object* e_) {
mathMatrix* M = mathMatrix_unboxer(M_);
uint32_t e = lean_unbox_uint32(e_);
uint32_t n = M->rows;
mathMatrix* result = mathMatrix_struct_id(n);
for (size_t i = 0; i < e; i++) {
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
n, n, n, 1.0, result->data, n, M->data, n, 0.0, result->data, n);
}
return mathMatrix_boxer(result);
}
Edit: The issue fixed when I removed precompileModules = true
from my lakefile. Though ideally it would still be able to have it enabled
Sebastian Ullrich (Aug 01 2022 at 07:58):
Is your library properly linked against cblas (lld build/lib/libleanffi.so
should list it)?
z battleman (Aug 01 2022 at 14:50):
There are a couple of functions which are not properly linked
ld: warning: cannot find entry symbol _start; not setting start address
ld: build/lib/libleanffi.so: undefined reference to `lean_big_usize_to_nat'
ld: build/lib/libleanffi.so: undefined reference to `l_Fin_ofNat'
ld: build/lib/libleanffi.so: undefined reference to `cblas_dgemv'
ld: build/lib/libleanffi.so: undefined reference to `lean_register_external_class'
ld: build/lib/libleanffi.so: undefined reference to `lean_mk_string'
ld: build/lib/libleanffi.so: undefined reference to `lean_apply_1'
ld: build/lib/libleanffi.so: undefined reference to `cblas_dgemm'
ld: build/lib/libleanffi.so: undefined reference to `lean_inc_ref_cold'
ld: build/lib/libleanffi.so: undefined reference to `lean_mk_io_user_error'
ld: build/lib/libleanffi.so: undefined reference to `lean_notify_assert'
ld: build/lib/libleanffi.so: undefined reference to `lean_alloc_small'
Admittedly though, I'm not sure how to fix it as I think I am correctly linking as shown here in my lakefile
package LeanAlg {
-- customize layout
--srcDir := "LeanAlg"
--libRoots := #[`mathVec, `mathMatrix]
-- specify the lib as an additional target
--moreLibTargets := #[cLibTarget __dir__]
moreLinkArgs := #["-L", "./third_party/OpenBLASLib/lib",
"-lopenblas",
"-Wl,-R./third_party/OpenBLASLib/lib"]
--precompileModules := true
packagesDir := "third_party"
}
def pkgDir := __dir__
def cSrcDir := pkgDir / "c"
def cBuildDir := pkgDir / _package.buildDir / "c"
def libBuildDir := pkgDir / _package.buildDir / "lib"
def oTarget (filename : String) : FileTarget :=
let oFile := cBuildDir / s!"{filename}.o"
let srcTarget := inputFileTarget <| cSrcDir / s!"{filename}.c"
fileTargetWithDep oFile srcTarget fun srcFile => do
compileO oFile srcFile #["-I", "third_party/OpenBLASLib/include", "-fPIC",
"-I", (← getLeanIncludeDir).toString]
extern_lib cLib :=
let libFile := libBuildDir / nameToStaticLib "leanffi"
staticLibTarget libFile #[oTarget "./utils/utils", oTarget "mathVec_ffi", oTarget "mathMatrix_ffi"]
Mac (Aug 02 2022 at 01:00):
I think this is a bug in Lake due to the fact that I don't pass additional linking arguments to the linker when compiling a shared library from a static library here: https://github.com/leanprover/lake/blob/dcf8e1fc406acfd4dbbfd691f4ecf76966fae407/Lake/Build/Targets.lean#L84-L92
zbatt (Aug 02 2022 at 02:58):
Mac said:
I think this is a bug in Lake due to the fact that I don't pass additional linking arguments to the linker when compiling a shared library from a static library here: https://github.com/leanprover/lake/blob/dcf8e1fc406acfd4dbbfd691f4ecf76966fae407/Lake/Build/Targets.lean#L84-L92
What I think is really interesting is that it seems to only occur with some functions? For example if I just use the multiplication function (which also uses cblas_dgemm
it compiles without complaining. Do you have a guess as to why that could be?
Mac (Aug 02 2022 at 03:01):
@zbatt I think I would need to look at the source of libleanffi
to make any guesses as to why that would be the case.
zbatt (Aug 02 2022 at 03:02):
Mac said:
zbatt I think I would need to look at the source of
libleanffi
to make any guesses as to why that would be the case.
If it's helpful for debugging Lake, I would be more than happy to share the repository, but obviously you don't have to look at it for my bugs haha
James Gallicchio (Aug 02 2022 at 03:17):
(I'm also just interested in taking a gander :eyes:)
Mac (Aug 02 2022 at 03:48):
zbatt said:
If it's helpful for debugging Lake
I think it could be.
zbatt (Aug 02 2022 at 14:21):
Mac said:
zbatt said:
If it's helpful for debugging Lake
I think it could be.
https://github.com/zaxioms/LeanAlg
Here you go :D
Last updated: Dec 20 2023 at 11:08 UTC