Vcpkg: Armadillo/lapack multiple issues using CMake

Created on 28 Jun 2019  路  6Comments  路  Source: microsoft/vcpkg

Apologies for posting this mess as a single bug but I ran into multiple issues installing armadillo today, which now depends on BLAS and LAPACK. I am generally pleased about that but it seems not all of the CMake config has been tidied to reflect it. I innocently ran this on a freshly cloned vcpkg today (at commit 5b6b66512):

vcpkg install --triplet x64-windows-static armadillo

After finishing, it helpfully printed the following:

The package openblas:x64-windows-static provides CMake targets:

    find_package(OpenBLAS CONFIG REQUIRED)
    target_link_libraries(main PRIVATE OpenBLAS::OpenBLAS)

The package clapack:x64-windows-static provides CMake targets:

    find_package(clapack CONFIG REQUIRED)
    target_link_libraries(main PRIVATE f2c lapack)

    find_package(lapack CONFIG REQUIRED)
    target_link_libraries(main PRIVATE lapack clapack::clapack)

Hmm, two different options for linking against LAPACK. I tried the first one to start with (i.e. find_package(clapack) andtarget_link_libraries(... f2c lapack)`). That gave this error when I ran CMake:

CMake Error at D:/src/_misc/vcpkg_master2/installed/x64-windows-static/share/clapack/clapack-config.cmake:1 (include):
  include could not find load file:

    D:/src/_misc/vcpkg_master2/buildtrees/clapack/x64-windows-static-rel/clapack-targets.cmake
Call Stack (most recent call first):
  D:/src/_misc/vcpkg_master2/scripts/buildsystems/vcpkg.cmake:266 (_find_package)
  CMakeLists.txt:3 (find_package)


-- Configuring incomplete, errors occurred!
See also "D:/src/_misc/zarma/build2/CMakeFiles/CMakeOutput.log".

I changed clpack-config.cmake to point at correct location for clapack-targets (I just set it to an absolute path), which changed the error to this warning:

CMake Warning (dev) at D:/src/_misc/vcpkg_master2/scripts/buildsystems/vcpkg.cmake:169 (_add_executable):
  Policy CMP0003 should be set before this line.  Add code such as

    if(COMMAND cmake_policy)
      cmake_policy(SET CMP0003 NEW)
    endif(COMMAND cmake_policy)

  as early as possible but after the most recent call to
  cmake_minimum_required or cmake_policy(VERSION).  This warning appears
  because target "zarma" links to some libraries for which the linker must
  search:

    clapack

  and other libraries with known full path:

    D:/src/_misc/vcpkg_master2/installed/x64-windows-static/debug/lib/openblas.lib
    D:/src/_misc/vcpkg_master2/buildtrees/clapack/x64-windows-static-rel/F2CLIBS/libf2c/libf2c.lib

  CMake is adding directories in the second list to the linker search path in
  case they are needed to find libraries from the first list (for backwards
  compatibility with CMake 2.4).  Set policy CMP0003 to OLD or NEW to enable
  or disable this behavior explicitly.  Run "cmake --help-policy CMP0003" for
  more information.
Call Stack (most recent call first):
  CMakeLists.txt:5 (add_executable)
This warning is for project developers.  Use -Wno-dev to suppress it.

This was suspicious but I tried building anyway. That gave this error:

LINK : fatal error LNK1104: cannot open file 'clapack.lib' [D:\src\_misc\zarma\build2\zarma.vcxproj]

As a note to help debug this, I notice the targets file includes these lines (but no corresponding _DEBUG variables):

set_property(TARGET f2c APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(f2c PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
  IMPORTED_LOCATION_RELEASE "D:/src/_misc/vcpkg_master/buildtrees/clapack/x64-windows-static-rel/F2CLIBS/libf2c/libf2c.lib"
  )

# Import target "lapack" for configuration "Release"
set_property(TARGET lapack APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(lapack PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
  IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "${_IMPORT_PREFIX}/lib/openblas.lib;f2c"
  IMPORTED_LOCATION_RELEASE "D:/src/_misc/vcpkg_master/buildtrees/clapack/x64-windows-static-rel/SRC/lapack.lib"
  )

OK, so I tried the other suggestion, which was find_package(LAPACK CONFIG REQUIRED) and target_link_libraries(... lapack clapack::clapack). This gave a lot of errors like this:

  Target "zarma" links to target "clapack::clapack" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

Unsurprisingly, I got another linker error about not finding the library. After searching the web I found the correct target_link_libraries(...) line is actually against ${LAPACK_LIBRARIES}. (Also FindLAPACK is a module, not a config, so I'm not sure how it found it but it did.) But at this change was finally enough to fix the configuration warnings and find the lapack library. But then I got link errors for missing symbols:

zarmatest.obj : error LNK2019: unresolved external symbol wrapper_sgesv_ referenced in function "void __cdecl arma::lapack::gesv<double>(int *,int *,
double *,int *,int *,double *,int *,int *)" (??$gesv@N@lapack@arma@@YAXPEAH0PEAN00100@Z) [D:\src\_misc\zarma\build2\zarma.vcxproj]
zarmatest.obj : error LNK2019: unresolved external symbol wrapper_dgesv_ referenced in function "void __cdecl arma::lapack::gesv<double>(int *,int *,
double *,int *,int *,double *,int *,int *)" (??$gesv@N@lapack@arma@@YAXPEAH0PEAN00100@Z) [D:\src\_misc\zarma\build2\zarma.vcxproj]
zarmatest.obj : error LNK2019: unresolved external symbol wrapper_cgesv_ referenced in function "void __cdecl arma::lapack::gesv<double>(int *,int *,
double *,int *,int *,double *,int *,int *)" (??$gesv@N@lapack@arma@@YAXPEAH0PEAN00100@Z) [D:\src\_misc\zarma\build2\zarma.vcxproj]
< ... and so on ...>

That's odd, armadillo shouldn't be using the wrapper when installed with vcpkg. I found this in ...\installed\x64-windows-static\include\armadillo_bits\config.hpp:

#define ARMA_USE_WRAPPER
//// Comment out the above line if you're getting linking errors when compiling your programs,
//// or if you prefer to directly link with LAPACK, BLAS + etc instead of the Armadillo runtime library.

After this, finally it built and ran. I was left only with a linker warning:

"D:\src\_misc\zarma\build2\zarma.vcxproj" (default target) (3) ->
(Link target) ->
  LINK : warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of other libs; use /NODEFAULTLIB:library [D:\src\_misc\zarma\build2\zarma.vcxproj]

    1 Warning(s)

In summary:

  • the clapack port suggests two different find_package options, which is confusing
  • the clapack port has a bug that prevents find_package(clapack) working
  • the clapack suggests the wrong target_link_libraries() link for use with find_package(lapack)
  • the armadillo port tries to link against the wrapper library, even though it doesn't exist
port-bug

All 6 comments

BLAS/lapack/armadillo/atlas/whatever is still a little bit of a mess. It鈥檚 also my fault, sorry, never fixed it properly. @neumann-a tried another approach, better continuing investing on it.
About lapack, i鈥檇 suggest you to use find_package(lapack) and then target_link_libraries(targetname PRIVATE ${LAPACK_LIBRARIES}), without listening to the automatic message by vcpkg. That way it works (or at least it works for me).
About the module/config, it works because in the wrapper I redirect everything to the module I wrote, whatever you are asking for.

clapack self-produced configs are broken, and they are known as broken also upstream. Luckily no one use them

No need to apologise! I'm very grateful for the time you've spent on this.

It think a totally reasonable solution would be to get vcpkg to output your CMake suggestion instead of the two broken alternatives. This is actually pretty easy. We just need to create a file that says:

find_package(lapack CONFIG REQUIRED)
target_link_libraries(main PRIVATE ${LAPACK_LIBRARIES}))

Then call that file usage, and copy it to share/clapack when the port is installed. I know this is cheeky, but would you be able to do that? Creating even trivial pull requests is a bit tricky for me (legally speaking).

Maybe I should make a separate issue for the final point I raised, about Armadillo and the LAPACK wrapper?

My apologies were also in fact related to hide the fact that I removed the usage file 馃ぃ
I will do that pr, but maybe even better I'd wait for #6786 to be ready

Now that I understand what CMake commands to use to link against LAPACK, I have had a chance to look into the problems with Armadillo. My original overall goal was just to install and use Armadillo on Windows (x64), which used to work in vcpkg (before it supported BLAS and LAPACK). I have played around quite a bit and found the following.

  • Current vcpkg, wrapper disabled: Works after disabling wrapper in config.hpp

    • As I mentioned in my original comment, I can get Armadillo to work by using as a header-only library (with no target_link_libraries()) and turning off the wrapper by commenting out that one line in config.hpp.
  • Current vcpkg, link to wrapper (via module): Works in debug only after adding link command

    • If I add find_package(Armadillo) and target_link_libraries(...${ARMADILLO_LIBRARIES}) to my CMake project (along with the BLAS and LAPACK commands) then the project compiles and links correctly, even with the wrapper still enabled. However, this only works in debug mode, because in release mode it still links against the debug armadillo.lib, which causes a link error due to mismatched iterator debug level. I believe find_package is picking up the FindArmadillo module in this case, because there is no config in share/armadillo.
  • Older vcpkg, link to wrapper (via config): Works after tweaking path in config

    • I rolled back to an older vcpkg repo (last commit was 12d2020 on 3 June 2019) and used find_package(Armadillo) and target_link_libraries(...${ARMADILLO_LIBRARIES}). This time linking works in debug and release mode. I did first have to make a change: the file ArmadilloConfig.cmake contained a path ../../share/Armadillo/CMake/ArmadilloLibraryDepends.cmake, which has a spurious "CMake" in it. Unfortunately, it seems all the config files were removed by 6a6d350 for #7022.

It seems to me that a reasonable fix would be:

  • Undo the change made in #7022, which removed all the Armadillo config files.
  • Patch the config file to remove the spurious "CMake" path fragment.
  • Add a usage to Armadillo that says to use find_package(Armadillo) and target_link_libraries(...${ARMADILLO_LIBRARIES})

I think these are independent of the changes in #6786

thanks for your very important debugging. We can try to ping @wangli28 to see if it's possible to merge all these fixes in the #7041 PR

Briefly, it's important just to add a usage file to Armadillo and do a regex fix on the restored config files, to change ../../share/Armadillo/CMake/ArmadilloLibraryDepends.cmake into ../../share/Armadillo/ArmadilloLibraryDepends.cmake

(in the meatime, also adding a usage to clapack would be good)

Thanks for posting this issue. This issue has been fixed. You can update vcpkg and rebuild. So I am closing this issue for now.

Was this page helpful?
0 / 5 - 0 ratings