Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake build with BUILD_PROG=ON fails on Linux due to libm #759

Open
cho-m opened this issue Oct 25, 2024 · 10 comments · May be fixed by #760
Open

CMake build with BUILD_PROG=ON fails on Linux due to libm #759

cho-m opened this issue Oct 25, 2024 · 10 comments · May be fixed by #760

Comments

@cho-m
Copy link
Contributor

cho-m commented Oct 25, 2024

Was experimenting with CMake build at Homebrew Homebrew/homebrew-core#194875 (mainly due to #757) and noticed the Linux build kept failing on libm.

Probably similar to BSD (d5c36c8).

One note is that failure is happening in a file not specified in list, i.e. blend4_reg

  /usr/bin/ld: CMakeFiles/blend4_reg.dir/blend4_reg.c.o: undefined reference to symbol 'sqrt@@GLIBC_2.2.5'
  /usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line

set(math_progs "dna_reg|extrema_reg|insert_reg|locminmax_reg|numa1_reg|otsutest1|plottest|pta_reg|rotatefastalt|watershed_reg")

Can also see Fedora's workaround to always use -lm - https://src.fedoraproject.org/rpms/leptonica/blob/rawhide/f/leptonica_cmake.patch#_41


Many of these look like test programs, so perhaps putting them behind a CMake option so that users can build only the INSTALL_PROGS would be useful.

@cho-m cho-m linked a pull request Oct 25, 2024 that will close this issue
@DanBloomberg
Copy link
Owner

Thank you for those suggestions, Michael. I don't maintain the cmake files, but was wondering why about half of the programs that require including math.h are not in that list.

Thank you also for PR #760. Someone will get to that soon.

@zdenop
Copy link
Collaborator

zdenop commented Oct 25, 2024

Can you please be more clear about what you are doing? E.g. steps to reproduction of issue?
IMO combination of linux and homebrew is not very standard.
I just tried the cmake build of the latest leptonica code on Raspberry PI (armv7l) with Debian GNU/Linux 12 (bookworm) and there was no problem.

cd /tmp
git clone https://github.com/DanBloomberg/leptonica.git --depth 1
cd leptonica/
cmake -Bbuild -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_PREFIX_PATH=/usr -DCMAKE_MODULE_PATH=/usr/lib/cmake -DBUILD_PROG=ON .
cmake --build build --config Release

build.zip

config.zip

@zdenop
Copy link
Collaborator

zdenop commented Oct 25, 2024

I added programs using sqrt to math_progs. I hope this fixes libm issue.

@cho-m
Copy link
Contributor Author

cho-m commented Oct 25, 2024

Fedora is more standard and this is their workaround: https://src.fedoraproject.org/rpms/leptonica/blob/rawhide/f/leptonica_cmake.patch#_41

The difference is static vs shared build. You should be able to reproduce by running same commands with -DBUILD_SHARED_LIBS=ON. Static builds will pull in extra linker flags via pkg-config (Requires.private / Libs.private) or CMake files.


Specifically, can reproduce (on Ubuntu 22.04 / glibc 2.35 / aarch64) by updating one command in your example to:

cmake -Bbuild -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_PREFIX_PATH=/usr -DCMAKE_MODULE_PATH=/usr/lib/cmake -DBUILD_PROG=ON -DBUILD_SHARED_LIBS=ON .

For Homebrew, we run on Ubuntu 22.04 and use the system glibc 2.35 and gcc 11 so I think it should be reproducible on Debian. Our CI runs on x86_64(GitHub actions). I'm personally running on aarch64(armv8) in a docker container.

So, I'd expect this to impact modern glibc. Haven't tested other C libraries, e.g. musl. Behavior would be similar if they use a shared library but could be different if inlining or something else.

@cho-m
Copy link
Contributor Author

cho-m commented Nov 2, 2024

Trying #761 to see if CI can catch this

EDIT: and it worked:

FAILED: bin/blend4_reg 
: && /usr/bin/cc -O3 -DNDEBUG  prog/CMakeFiles/blend4_reg.dir/blend4_reg.c.o -o bin/blend4_reg  -Wl,-rpath,/home/runner/work/leptonica/leptonica/build/src  src/libleptonica.so.6.0.0 && :
/usr/bin/ld: prog/CMakeFiles/blend4_reg.dir/blend4_reg.c.o: undefined reference to symbol 'sqrt@@GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

@zdenop
Copy link
Collaborator

zdenop commented Nov 2, 2024

Sorry for the late reply. Thank you for example I am able to reproduce the problem.
I would like to understand why there is no problem with the library building (sqrt is used many times in src/ see git grep sqrt) but there is the problem with progs building... .

I tried several different compiler (clang, msvc, MinGW 8.1) to compile simple a program:

#include<stdio.h>
#include <math.h>

int main() {
	double x = pow(2.0, 3.0);
	printf("Value of x = %f\n", x);
	double factor = sqrt(2.0);
	printf("Factor (sqrt of 2) = %f\n", factor);
	return 0;
    }

none of them required linking libm.... Fedora uses approach "if libm is present => used it", but I do not feel this is right approach.

@cho-m
Copy link
Contributor Author

cho-m commented Nov 2, 2024

I would like to understand why there is no problem with the library building

Library does link to libm:

target_link_libraries (leptonica PRIVATE m)


none of them required linking libm....

The example may be too simple as a constant can be computed at compile time. Can try moving to function and passing in as variables.

Also make sure to run in separate steps like CMake does for compilation and linking. This is needed so the .o has undefined symbols that are resolved by linker

For example, assuming code is moved to function f, then

int main() {
    return f(2.0, 3.0);
}
$ /usr/bin/gcc -o test.o -c test.c

$ nm test.o
0000000000000058 T main
                 U pow
                 U printf
                 U sqrt
0000000000000000 T test

$ /usr/bin/gcc -o test test.o
/usr/bin/ld: test.o: in function `test':
test.c:(.text+0x18): undefined reference to `pow'
/usr/bin/ld: test.c:(.text+0x34): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

$ /usr/bin/gcc -o test test.o -lm

Fedora uses approach "if libm is present => used it", but I do not feel this is right approach.

I think many modern Linux distros use --as-needed when linking so there is less concern with adding an extra linker flag which will get stripped out if unused.

@zdenop
Copy link
Collaborator

zdenop commented Nov 2, 2024

Library does link to libm:

target_link_libraries (leptonica PRIVATE m)

But it is restricted to UNIX. We can do add UNIX to

if(FREEBSD AND HAVE_LIBM AND ${target} MATCHES ${math_progs})

or simplify that conditions to if (HAVE_LIBM AND ${target} MATCHES ${math_progs}).

I saw some reports about a misbehaviour of programs when --as-needed was used, so maybe the safer option is to maintain math_progs list.

@cho-m
Copy link
Contributor Author

cho-m commented Nov 2, 2024

or simplify that conditions to if (HAVE_LIBM AND ${target} MATCHES ${math_progs}).

That is simplest option. I did try it in #760 and seemed to work.

--as-needed was referring to downstreams' builds rather than Leptonica change.

@zdenop
Copy link
Collaborator

zdenop commented Nov 5, 2024

Thanks. IMO most of Fedora patch should be applied. I need some time to evaluate effect of lib${LIB_SUFFIX} (instead of lib) as it is effecting all platforms...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants