zfp icon indicating copy to clipboard operation
zfp copied to clipboard

fail to build zfp 1.0.0 due to missing link to libm

Open hubutui opened this issue 3 years ago • 9 comments

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.

hubutui avatar Aug 09 '22 07:08 hubutui

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.

lindstro avatar Aug 09 '22 15:08 lindstro

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

hubutui avatar Aug 10 '22 11:08 hubutui

check also the log.fail.txt with make -C build VERBOSE=1.

hubutui avatar Aug 10 '22 11:08 hubutui

This PKGBUILD works for zfp 0.5.5, not 1.0.0.

hubutui avatar Aug 10 '22 14:08 hubutui

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).

felixonmars avatar Aug 10 '22 14:08 felixonmars

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 avatar Aug 10 '22 15:08 felixonmars

@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.

lindstro avatar Aug 10 '22 15:08 lindstro

#include<math.h> int main(int n,char*v[]){return sqrt(n);}

This works (fails) as expected here, with or without -flto.

felixonmars avatar Aug 10 '22 15:08 felixonmars

Thanks for verifying. We'll add a fix on develop.

lindstro avatar Aug 10 '22 15:08 lindstro

thanks @lindstro, I can confirm that https://github.com/LLNL/zfp/commit/6d7d2424ed082eb41d696036b26831636650a614 fix the issue.

hubutui avatar Aug 11 '22 00:08 hubutui