Build static lib without blas
Expected behavior
Do this.
Actual behavior
Fails without system lib and ignores BLAS_blas_LIBRARY
Where/how to reproduce the problem
- arpack-ng: 3.7.0
I build static arpack as a cmake external project to be linkend to our own software. All works fine, but on one gitlab-runner, I have no direct access to, arpack does not build because FindBLAS() fails in CMakeLists.txt:169 (find_package)
Unfortunately I have no system available without any libblas to reproduce the error.
I provide -DBLAS_blas_LIBRARY:FILEPATH=${BLAS_LIBRARY} where ${BLAS_LIBRARY} is our own built blas (static) but this seems to be ignored. Probably something dynamic is expected?
My Understanding is, that blas is not needed for building libarpack.a as we provide blas when we link our application where arpack is part of. Is this right?
I assume arpack needs blas for the examples, but I don't enable them. If this is the case, I ask for having the option to build libarpack.a without providing blas.
blas is not needed for building libarpack.a, ..., I assume arpack needs blas for the examples,
You are probably right. Propose a PR (cmake should be easy, autotools likely less !...) and add a no-example-no-blas job in .travis.yml to check it out.
Sorry, thats to much of a burden for me - I'm not involved in arpack development at all, nor do I know how to edit .yml.
I'm not involved in arpack development at all
Nobody is anymore ! All people are volunteers here.
I know its volunteers, but some have a glue about what is done, others don't (me, when it comes to arpack) :)
I created a patch for myself which enables SYSTEM_BLAS and SYSTEM_LAPACK again, wich was commented 5 years ago. However, some SYSTEM_* stuff is still commented and I don't understand their implications.
Doing this, libarpack.a is built.
I also had to add option(TESTS "..") to prevent some tests which require blas as they have a add_exeecutable(). I did not test this further, e.g. in combination with MPI.
So far it works for me, probably someone with more knowledge about arpack build system wants to have a look at it an possibly apply it.
Changing dependencies could be costly-to-endless (not really motivating...) : CMake may be easy, autotools likely not... You added SYSTEM_BLAS and SYSTEM_LAPACK "only" for building without BLAS/LAPACK ?
I know its volunteers, but some have a glue about what is done, others don't
Yeah... I know too a bunch of glued-depressing walking dead F77 maniacs...
I don't know what you want to say with autotools. Apparently there are more build options than cmake?
Yes I "added" SYSTEM_* to build w/o blas/lapack. The code was already there but commented 5 years ago. It is on by default to have the same default behavior as before. blas/lapack is required the for testing, which was done before automatically. I even suggest to switch off TESTS by default (as are the examples) as the lib is what one usually wants. But I do not know, what this bug_158, ... stuff ist.
I suppose what you want is not possible : you should try to check your environment or to set hints (from or outside your external project) for FindBLAS() to find something (setting BLA_STATIC=ON if you need *.a ?). This may be the baseline problem you actually have, or, the problem may lie in FindBLAS.cmake (called from external project ?) : did you report to cmake on a dummy case ?
-
all tests are binaries which use
libarpack.a/so. -
libarpack.acontains the same things thanlibarpack.so(only loading / symbol-export is handled differently) -
libarpack.soseems to export symbols from BLAS/LAPACK, so, thatlibarpack.so(aslibarpack.a) seems to need BLAS/LAPACK
> nm -gD /tmp/local/lib/libarpack.so | grep axpy
2: U caxpy_
34: U daxpy_
108: U saxpy_
165: U zaxpy_
> nm -gD /tmp/local/lib/libarpack.so | grep laset
15: U claset_
56: U dlaset_
129: U slaset_
179: U zlaset_
Removing BLAS/LAPACK as a dependency may be painfull... For realizing they are indeed needed
> git grep axpy SRC/
SRC/cnaitr.f:c caxpy Level 1 BLAS that computes a vector triad.
SRC/cnaitr.f: external caxpy, ccopy, cscal, csscal, cgemv, cgetv0,
...
> git grep lamch SRC/dnaupd.f
SRC/dnaupd.f:c dlamch LAPACK routine that determines machine constants.
SRC/dnaupd.f: & dlamch
SRC/dnaupd.f: external dlamch
SRC/dnaupd.f: if (tol .le. zero) tol = dlamch ('EpsMach')
I don't know what you want to say with autotools
autotools is the set of autoconf (which produces configure), automake (based on Makefile.am) and autoheader. CMake is maintained and is meant for the same things than autotools which is no more maintained.
I think we have a misunderstanding.
- I need a static libarpack.a to be built which I can link to my own application.
- I provide blas to my own application (usually mkl or openblas)
- the current arpack 3.7.0 requires in line 169 unconditionally a system blas to be found by cmake. This is the case, because conditional "find_package(BLAS REQUIRED)" by SYSTEM_BLAS was removed 5 years ago.
- For this reason, building arpack fails with 3.7.0 on our gitlab-runners which have no system blas. They need no system blas, because we provide it building our application.
- Our objective is to have a libarpack.a. To build this, no blas is needed! One needs blas only when linking libarpack to a application. This is the case for examples and tests. The examples could be disabled, I added TESTS to also disable the tests.
- With my patch one can build libarpack.a on a system without system blas.
- This solution works for me.
- I believe the hardcoded requirement for system blas is 3.7.0 should not be, as it is not required for libarpack, which is, what most arpack users might want. I did not test for the dynamic case.
- To your point 3, I think the U means, that arpack uses blas (when running), which is clear. It's just not required to build the lib.
I hope for a discussion on this issue and I thank you for your discussion.
Not clear enough to me. Your problem looks really like a pure cmake problem, not an arpack-ng problem. Seems you need :
-
Either to
sethints and/or relevant environment variables (CMAKE_PREFIX_PATH, BLAS_LIBRARY, ... - https://stackoverflow.com/questions/19858134/how-to-share-variables-between-different-cmake-files/19859882#19859882) inside yourCMakeLists.txtbetween yourfind_package(BLAS)and yourfind_package(arpack-ng)so that arpack-ng knows already where to find BLAS/LAPACK when he needs them (If I understand correctly what you do in the CMakeLists.txt of your app) -
Reduce your problem and report to cmake
Using imported targets (to reuse BLAS/LAPACK already found) in arpack-ng may help : test this 2-minutes patch #282 to know.
One needs blas only when linking libarpack to a application.
If you end-up with a libarpack.a which can not be used because BLAS/LAPACK are missing and which can not be tested what's the point ?! You try to create something nobody can do anything with... Because you miss the real problem
If you end-up with a
libarpack.awhich can not be used because BLAS/LAPACK are missing and which can not be tested what's the point ?! You try to create something nobody can do anything with... Because you miss the real problem
Please believe me, that's wrong.
- BLAS/ARPACK is NOT required to build the libs but only for the tests and examples.
- The libarpack is the same, independent if BLAS/ARPACK is on the system or not.
- Therefore I added in my patch the option TESTS, to have only the lib an no examples and no tests
- I have no cmake issue or cmake bug at all. In current 3.7.0 in line 169
find_package(BLAS REQUIRED)always wants a system blas. But this is not needed without tests and examples.
All I want is an option to build libarpack on a system without BLAS/LAPACK. And I know that this works, as I do it with my patch at the moment. My patch has as default the old behaviour - hence tests are built and for that BLAS/LAPACK is required.
It makes no sense to enforce BLAS/LAPACK of only libarpack is build and BLAS/LAPACK are note used for that build.
When I run arpack with my patch as
cmake .. -DSYSTEM_BLAS=OFF -DSYSTEM_LAPACK=OFF -DTESTS=OFF -DEXAMPLES=OFF
I get after make clean; make
...
[ 98%] Building Fortran object CMakeFiles/arpack.dir/staini.f.o
[100%] Linking Fortran static library libarpack.a
[100%] Built target arpack
With EXAMPLES or TESTS on libarpack is built, but tests and/or examples fail. Here for examples
cmake .. -DSYSTEM_BLAS=OFF -DSYSTEM_LAPACK=OFF -DTESTS=OFF -DEXAMPLES=ON
...
[ 31%] Building Fortran object CMakeFiles/arpack.dir/staini.f.o
[ 32%] Linking Fortran static library libarpack.a
[ 32%] Built target arpack
Scanning dependencies of target ssdrv3
[ 33%] Building Fortran object CMakeFiles/ssdrv3.dir/EXAMPLES/SYM/ssdrv3.f.o
[ 33%] Linking Fortran executable Examples/sym/ssdrv3
Undefined symbols for architecture x86_64:
"_saxpy_", referenced from:
_MAIN__ in ssdrv3.f.o
_ssapps_ in libarpack.a(ssapps.f.o)
...
You see, libarpack is built. And same is with TESTS on
cmake .. -DSYSTEM_BLAS=OFF -DSYSTEM_LAPACK=OFF -DTESTS=ON -DEXAMPLES=OFF
...
[ 82%] Building Fortran object CMakeFiles/arpack.dir/staini.f.o
[ 83%] Linking Fortran static library libarpack.a
[ 83%] Built target arpack
[ 84%] Building Fortran object CMakeFiles/bug_142_gen.dir/TESTS/bug_142_gen.f.o
[ 85%] Linking Fortran executable Tests/bug_142_gen
Undefined symbols for architecture x86_64:
"_daxpy_", referenced from:
_MAIN__ in bug_142_gen.f.o
_dnaitr_ in libarpack.a(dnaitr.f.o)
_dnapps_ in libarpack.a(dnapps.f.o)
...
Again libarpack.a is built nicely, it's just the tests that fail to link.
Clearly BLAS/LAPACK is needed for any application linking arpack - just nut to build libarpack itself.
@fghoussen could I convince you?
Please believe me
I believe no one but the code. Arpack's API are the *[ae]upd, git grep external SRC/*[ae]upd.f shows already lots of BLAS/LAPACK hits (*ger, *lacpy, ...): arpack (the core of it - not the tests of it) needs BLAS/LAPACK.
All I want is an option to build libarpack on a system without BLAS/LAPACK.
There is no way you get that, as, there's no way you can build a house without walls. But, you may get a way to give arpack what you already found (so that arpack no more need to search): I believe cmake targets is the right tool for that.
@fghoussen could I convince you?
Not at all. Your problem is pure cmake: it has nothing to do with arpack.
Your problem is that you have concurrent find_package at different cmake levels :
find_package(A)
find_package(B) # where B needs A.
In your case, A = BLAS and B = ARPACK.
Now Say A = BLAS, say B = LAPACK, and say that FindLAPACK.cmake calls find_package(BLAS) (it could be the case, but, it's not as LAPACK ships his own BLAS) : you'll get the exact same problem... And arpack is not involved here as this is a very generic problem : if you'd ask cmake people, they may answer you "find_package should now set targets: in B, search for A only if its target is not set, then use A target instead of A variables" that is "if you found A before elsewhere, in B you can reuse it as is (as target is some kind of alias)"
I believe no one but the code. Arpack's API are the
*[ae]upd,git grep external SRC/*[ae]upd.fshows already lots of BLAS/LAPACK hits (*ger, *lacpy, ...): arpack (the core of it - not the tests of it) needs BLAS/LAPACK.
Then it makes no sense to discuss here any more. I'm sure I'm right, your're sure your're right. I give my point a last time, and this are my arguments: a) To run functions from libarpack, one needs blas/lapack, because arpack depends on them. Here we have common understanding. b) To build libarpack, blas/lapack are not required - they are only required at runtime of arpack. Here we apparently have different understanding. I claim, I'm right, because this is how libraries work - the code from the libs are needed only at linking (static libs) or even at runtime (dynamic libs). I showed above, that libarpack was successfully built. c) Therefore I claim, I have no cmake issue. The find_package(A,B) fail, as the gitlabrunner has no system blas and lapack, so cmake cannot find anything. All is proved for me, as my patch works for me.
I think the only way to continue are more people sharing their thoughts and knowledge.
There's no right or wrong ?!... CMake evolves to "modern CMake" as it learns from it's errors : CMake fix same rules from anybody https://levelup.gitconnected.com/simple-modern-cmake-tutorial-b0c1c362cd2c
I submitted a pull request that decouples the BLAS/LAPACK dependencies when the user does not need tests or examples. I have tried the resulting libarpack.[a|so] and it is working fine, as it should, but it would be nice if somebody could double-check.
(...) Arpack's API are the
*[ae]upd,git grep external SRC/*[ae]upd.fshows already lots of BLAS/LAPACK hits (*ger, *lacpy, ...): arpack (the core of it - not the tests of it) needs BLAS/LAPACK.
These are references to BLAS/LAPACK functions that are not needed at compile-time of SRC/*[ae]upd.f. They are not needed at link-time of libarpack.[a|so] either. BLAS/LAPACK are only needed during link-time of the executable consuming libarpack, that is, when the references to (*ger, *lacpy, ...) present in libarpack need to be resolved. The consumer of libarpack must then link with -l <path>/libarpack.[a|so] -llapack -lblas (or -lopenblas or whichever the user likes) to avoid getting undefined references.
As it is done currently the lines CMakeLists.txt:309,310, will hard-code the path of whatever BLAS/LAPACK libraries were found with find_package a bit further up, as seen with ldd
>> ldd libarpack.so
linux-vdso.so.1 (0x00007ffd383bf000)
* libmkl_gf_lp64.so => /opt/intel/mkl/lib/intel64/libmkl_gf_lp64.so (0x00007fc1bd891000)
* libmkl_gnu_thread.so => /opt/intel/mkl/lib/intel64/libmkl_gnu_thread.so (0x00007fc1bc046000)
* libmkl_core.so => /opt/intel/mkl/lib/intel64/libmkl_core.so (0x00007fc1b7dfc000)
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007fc1b7dba000)
libgfortran.so.5 => /usr/lib/x86_64-linux-gnu/libgfortran.so.5 (0x00007fc1b7af2000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc1b79a3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc1b77af000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc1b77a9000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc1b7786000)
libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007fc1b773c000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc1b7721000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc1be467000)
This is an unnecessary constraint, making the library less flexible. At least that's my current understanding.
Thank you very much!