zfp
zfp copied to clipboard
fail to build zfp 1.0.0 due to missing link to libm
OS: ArchLinux gcc: 12.1.1 python: 3.10.5
cmake -B build -S zfp-1.0.0 \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_SKIP_RPATH=ON \
-DBUILD_CFP=ON \
-DBUILD_ZFPY=ON \
-DBUILD_ZFORP=ON
make -C build
error log:
/usr/bin/ld: /tmp/ccK8Frb4.ltrans0.ltrans.o: in function `main':
<artificial>:(.text.startup+0x17fe): undefined reference to `sqrt'
/usr/bin/ld: <artificial>:(.text.startup+0x1838): undefined reference to `log10'
collect2: error: ld returned 1 exit status
make[2]: *** [utils/CMakeFiles/zfpcmd.dir/build.make:98: bin/zfp] Error 1
make[2]: Leaving directory '/build/zfp/src/build'
make[1]: *** [CMakeFiles/Makefile2:1048: utils/CMakeFiles/zfpcmd.dir/all] Error 2
make[1]: Leaving directory '/build/zfp/src/build'
make: *** [Makefile:146: all] Error 2
make: Leaving directory '/build/zfp/src/build'
check the complete build log.fail.txt.
check the PKGBUILD I used to build zfp. I only update the pkgver to 1.0.0, and the sha256sums.
I could build it with -DCMAKE_C_FLAGS="-lm". It seems we forget to add target_link_libraries(libname PRIVATE m) somewhere.
The logic here and here should take care of this. Your CMake log indicates that HAVE_MATH is set, i.e., your compiler should not need -lm. Perhaps something got outdated in the CMake cache?
Can you try the same sequence of build commands after first doing this:
git clone https://github.com/LLNL/zfp.git zfp-1.0.0 --branch master
rm -f -r build
Might be useful to also run make -C build VERBOSE=1.
It's wired. If I build zfp without Building_in_a_clean_chroot, I got this:
-- Performing Test HAVE_MATH
-- Performing Test HAVE_MATH - Failed
-- Performing Test HAVE_LIBM_MATH
-- Performing Test HAVE_LIBM_MATH - Success
However, as this log shows, when I build it in a clean chroot,
-- Performing Test HAVE_MATH
-- Performing Test HAVE_MATH - Success
It pass the test HAVE_MATH, so HAVE_LIBM_MATH is not tested. And it seems -lm is only added when HAVE_LIBM_MATH is true.
BTW, it's also wired that we test both HAVE_MATH and HAVE_LIBM_MATH here:
https://github.com/LLNL/zfp/blob/35155961eca5bce0714c7ed0eb0e3735ae0f3045/CMakeLists.txt#L260-L268
check also the log.fail.txt with make -C build VERBOSE=1.
This PKGBUILD works for zfp 0.5.5, not 1.0.0.
Turns out the culprit here is -flto.
$ cat zfp-libm.c
#include<math.h>
float f; int main(){sqrt(f);return 0;}
$ cc -O1 zfp-libm.c -o zfp-libm
/usr/bin/ld: /tmp/ccltkL2I.o: in function `main':
zfp-libm.c:(.text+0x21): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
$ cc -O1 zfp-libm.c -o zfp-libm -lm
$ cc -O1 zfp-libm.c -flto -o zfp-libm-lto
zfp-libm:
0000000000001020 <main>:
1020: f3 0f 1e fa endbr64
1024: 66 0f ef c0 pxor %xmm0,%xmm0
1028: 66 0f ef c9 pxor %xmm1,%xmm1
102c: f3 0f 5a 05 e0 2f 00 cvtss2sd 0x2fe0(%rip),%xmm0 # 4014 <f>
1033: 00
1034: 66 0f 2e c8 ucomisd %xmm0,%xmm1
1038: 77 03 ja 103d <main+0x1d>
103a: 31 c0 xor %eax,%eax
103c: c3 ret
103d: 50 push %rax
103e: ff 15 ac 2f 00 00 call *0x2fac(%rip) # 3ff0 <sqrt@GLIBC_2.2.5>
1044: 31 c0 xor %eax,%eax
1046: 5a pop %rdx
1047: c3 ret
1048: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
104f: 00
zfp-libm-lto:
0000000000001020 <main>:
1020: f3 0f 1e fa endbr64
1024: 31 c0 xor %eax,%eax
1026: c3 ret
1027: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
102e: 00 00
So the sqrt call was optimized out by LTO. Possible solutions include introducing I/O side effect (run sqrt against argc), making the float f volatile, or using a different function (like the victim log10 here).
The older versions have -rdynamic in the test command, which came from CMP0065. This is no longer the case after the cmake version bump introduced in https://github.com/LLNL/zfp/commit/2fba7f6904e41abe2486d7070c3358a584601679. Hence the difference.
@felixonmars Wow--thanks for finding the issue. It's odd that 0.5.5 would build and 1.0.0 wouldn't when they use the same HAVE_MATH logic.
I'm not sure volatile would solve the problem since the return value is not used and sqrt() has no side effects. I like the argc solution better, e.g.:
#include<math.h>
int main(int n,char*v[]){return sqrt(n);}
We have a number of other minor issues to address and hope to release a patch in the near future. In the meantime, it would be great if one of you could test this fix since we do not really have access to the build environment you're using.
#include<math.h> int main(int n,char*v[]){return sqrt(n);}
This works (fails) as expected here, with or without -flto.
Thanks for verifying. We'll add a fix on develop.
thanks @lindstro, I can confirm that https://github.com/LLNL/zfp/commit/6d7d2424ed082eb41d696036b26831636650a614 fix the issue.