[Using CHOLMOD]How to set linker type(with or without underscore as suffix) for BLAS complied by MinGW64?
mygit2hub opened this issue · 10 comments
Hi, Professor Tim Davis
To install CHOLMOD from SuiteSparse v7.6.0, the following sources and tools are used to bulid libblas.lib and liblapack.lib in Windows 10. Well, it seems that CHOLMOD links the Fortran functions in the blas and lapack library without underscore as suffix in default.
LAPACK 3.12.0 (https://www.netlib.org/lapack/lapack-3.12.0.html#_lapack_3_12_0_what_8217_s_new)
Win64 version: GCC 13.2.0 (with POSIX threads) + LLVM/Clang/LLD/LLDB 17.0.6 + MinGW-w64 11.0.1 (UCRT) - release 5 (https://winlibs.com/)
The libblas.lib, liblapack.lib, and .DLLs can be gained by following the "Build Instructions below to create LAPACK and LAPACKE 3.5.0 dlls for Windows with MinGW" (at https://icl.utk.edu/lapack-for-windows/lapack/index.html#libraries).
Requirements: MinGW, CMAKE 2.8.0, VS IDEs
1.~4. are normal install procedures.
5.Open CMAKE
Point to your lapack-3.5.0 folder as the source code folder
Point to a new folder where you want the build to be (not the same is better)
Click configure, check the install path if you want to have the libraries and includes in a particular location.
Choose MinGW Makefiles.
Click "Specify native compilers" and indicate the path to the Mingw compilers.
For x64, on my machine, it is "C:/mingw64/bin/x86_64-w64-mingw32-gfortran.exe" and the C compiler is "C:/mingw64/bin/x86_64-w64-mingw32-gcc.exe"
For x64 build ONLY , add the variable CMAKE_SIZEOF_VOID_P and set it to 8 (string), this will force CMAKE to create the VCVARSAMD64 variable ( see post on forum) Note: CMAKE team corrected the issue, and thus this workaround won't be needed if you are using CMAKE 2.8.13 or above
Click "Specify native compilers" and indicate the path to the Mingw compilers. On my machine, it is "C:/MinGW/bin/gfortran.exe"
Set the 'BUILD_SHARED_LIBS' option to ON.
Set the 'CMAKE_GNUtoMS' option to ON.
if you want to build the LAPACKE library, set the 'LAPACKE' option to ON.
Click again configure until everything becomes white
Click generate, that will create the mingw build.
Close CMAKE
6. Open a cmd prompt (Click Run.. then enter cmd)
7. Go to your build folder using the cd command
8. Type C:/MinGW/bin/mingw32-make.exe
9. Type C:/MinGW/bin/mingw32-make.exe test if you want to run LAPACK testings to make sure everything is ok
10. Your libs are in the lib folder, the dlls are in the bin folder. The resulting build will provide both GNU-format and MS-format import libraries for the DLLs.
11. Now you should be able to create a C application built with MSVC and linked directly to the MinGW-built LAPACK DLLs
12. NOTE: Your C application built with Microsoft Visual Studio and linked to the MinGW-built lapack DLLs will run but requires the GNU runtime DLLs ( both libgfortran-3.dll and libgcc_s_dw2-1.dll are needed.) from MinGW to be available. As you have the GNU runtime directory in your PATH, you should be good to go.
The built liblapack.dll and libblas.dll for BLAS and Lapack were checked that the Fortran functions such as dtrsv, dgemv, dtrsm, dgemm cannot be linked by MSVS 2019(error LNK2019: unresolved external symbol dtrsm referenced in function rd_cholmod_super_numeric_worker), for the mingw32-make complier appending an underscore for each function as suffix (i.e, dtrsv_), which is confirmed by opening the file libblas.dll.
Maybe the problem is due to use the default command mingw32-make.exe, the .lib and .dll are built with underscore suffix for each function. I wonder if the command mingw32-make.exe needs to be changed with certain options to mangling the symbol '_' in the libs and dlls. Or some variables or entries in cmake need to be preset?
Alternatively, shall I define BLAS_UNDERSCORE(in SuiteSparse_config.h) when configure the CMakeLists.txt under SuiteSparse-7.6.0 folder or CHOLMOD folder?
Thank you.
Yes, you would need to configure the BLAS calling mechanism 'manually' by passing -DBLAS_UNDERSCORE to the compiler. I don't have a cmake option for that since it should be rare, but you can tell cmake to add it to the C and C++ compiler flags.
Iiuc, you are trying to build SuiteSparse with MSVC and link it to a BLAS library that was built for a MinGW target with gfortran.
SuiteSparse defaults to the name mangling convention used by the Intel Fortran compiler (that was (or is?) marketed as part of the MS Visual Studio) when it detects that a MSVC compiler is used.
gfortran
uses a different name mangling convention than Intel Fortran on Windows.
You could configure with -DSUITESPARSE_C_TO_FORTRAN="(name,NAME) name##_"
(i.e., lower-case with trailing underscore).
Does that work for your use case?
Yes, you would need to configure the BLAS calling mechanism 'manually' by passing -DBLAS_UNDERSCORE to the compiler. I don't have a cmake option for that since it should be rare, but you can tell cmake to add it to the C and C++ compiler flags.
Iiuc, you are trying to build SuiteSparse with MSVC and link it to a BLAS library that was built for a MinGW target with gfortran. SuiteSparse defaults to the name mangling convention used by the Intel Fortran compiler (that was (or is?) marketed as part of the MS Visual Studio) when it detects that a MSVC compiler is used.
gfortran
uses a different name mangling convention than Intel Fortran on Windows.You could configure with
-DSUITESPARSE_C_TO_FORTRAN="(name,NAME) name##_"
(i.e., lower-case with trailing underscore).Does that work for your use case?
Thanks for the reply @DrTimothyAldenDavis @mmuetzel and the closed issue "Fix blas #698".
Well, it may be difficult for me to passing -DBLAS_NO_UNDERSCORE to the MinGW-w64 compiler. Instead, I passed -DBLAS_UNDERSCORE to the CMAKE_C_FLAGS (the same for CMAKE_CXX_FLAGS) in the configuration of cmake compiler for SuiteSparse, as shown in the following figure from the cmake-gui in Windows. I tried to generate the whole project and compile the CHOLMOD solution by MSVC 2019, and it works.
I wonder if this is a right way to resolve the inconsistency between the Fortran routine with and with no "_" in their names, corresponding to the .lib and .dll generated by MinGW-w64 compiler and CHOLMOD preset link flag in default, respectively.
If it is right, please close this issue. If there is other good method to cope with it , please show me. Thank you!
Here, I deleted the figure in order to avoid misadvice for other users.
You'll need to use the -DSUITESPARSE_C_TO_FORTRAN="(name,NAME) name##_" for cmake, as @mmuetzel points out.
I should make that setting easier to access.
Your request isn't the first one, so I think it might make sense to make this easier to change for the end user.
I just pushed this change to the dev2 branch: 4f45fc4
It adds two new cmake cached variables: SUITESPARSE_BLAS_UNDERSCORE
and SUITESPARSE_BLAS_NO_UNDERSCORE
.
Both default to OFF, which means that the Fortran compiler is used to tell how the names should appear, or SUITESPARSE_C_TO_FORTRAN
is used if there is no Fortran compiler.
If SUITESPARSE_BLAS_UNDERSCORE
is ON, this forces the appending of an underscore, which is what you want.
Then you can just add SUITESPARSE_BLAS_UNDERSCORE=1
to your cmake variables, instead of adding to your CMAKE_C_FLAGS
.
This is simpler than using -DSUITESPARSE_C_TO_FORTRAN="(name,NAME) name##_"
for your cmake options.
@mygit2hub : would you like to give this a try?
@mmuetzel : what do you think? This is a little simpler. It's a bit limited because it assumes the names are all lower case, but that seems typical. If the end user wants full control, they can use the SUITESPARSE_C_TO_FORTRAN
setting. This proposed change just overrides that setting if either of the new options are ON. By default both new options are OFF so the prior behavior is used.
Both default to OFF, which means that the Fortran compiler is used to tell how the names should appear, or
SUITESPARSE_C_TO_FORTRAN
is used if there is no Fortran compiler.If
SUITESPARSE_BLAS_UNDERSCORE
is ON, this forces the appending of an underscore, which is what you want.Then you can just add
SUITESPARSE_BLAS_UNDERSCORE=1
to your cmake variables, instead of adding to yourCMAKE_C_FLAGS
.This is simpler than using
-DSUITESPARSE_C_TO_FORTRAN="(name,NAME) name##_"
for your cmake options.@mygit2hub : would you like to give this a try?
Thanks for the reply. I gave a try and it works!
The SuiteSparse project was configured by cmake-gui 3.28.0 in Windows and the results can be summarized as:
-
If SUITESPARSE_BLAS_UNDERSCORE = SUITESPARSE_BLAS_NO_UNDERSCORE = 'OFF', then SUITESPARSE_C_TO_FORTRAN is set to '(name,NAME) name', which is the default case. --MSVC 2019 cannot link the blas.lib built by MinGW-w64 with an underscore as suffix.
-
If SUITESPARSE_BLAS_UNDERSCORE = 'OFF' and SUITESPARSE_BLAS_NO_UNDERSCORE = 'ON', the same as 1).
-
If SUITESPARSE_BLAS_UNDERSCORE = 'ON' and SUITESPARSE_BLAS_NO_UNDERSCORE = 'OFF', then SUITESPARSE_C_TO_FORTRAN is set to '(name,NAME) name##_. --MSVC 2019 can link the blas.lib built by MinGW-w64 with an underscore as suffix.
It seems that checking the box for 'SUITESPARSE_BLAS_UNDERSCORE' or SUITESPARSE_BLAS_NO_UNDERSCORE is the same as setting its value to 1, as shown in the following figure.
Well, it may be advisable to provide these cmake accessible cache varaibles/entries in the next version to clarify the link mode for the problem (for adding third-party resources), together with the solution for #643(how to add blas or lapack (or the other) resources into the project, with 87cffed - DEFINED BLAS_LIBRARIES OR BLAS_INCLUDE_DIRS, DEFINED LAPACK_LIBRARIES OR APACK_INCLUDE_DIRS).
Hope these improvments can be added into the file README.md of the next version and remind the coming users to configure them in right way.
Again, Thank you all!
@mmuetzel : what do you think? This is a little simpler. It's a bit limited because it assumes the names are all lower case, but that seems typical. If the end user wants full control, they can use the
SUITESPARSE_C_TO_FORTRAN
setting. This proposed change just overrides that setting if either of the new options are ON. By default both new options are OFF so the prior behavior is used.
I'm not a big fan of having several options that all do the same thing and that compete with each other.
Maybe, documentation helps. But apparently the documentation for SUITESPARSE_C_TO_FORTRAN
wasn't good enough.
The following is currently in SuiteSparsePolicy.cmake
:
# SUITESPARSE_C_TO_FORTRAN: a string that defines how C calls Fortran.
# Defaults to "(name,NAME) name" for Windows (lower case,
# no underscore appended to the name), which is the
# system that is most likely not to have a Fortran
# compiler. Defaults to "(name,NAME) name##_" otherwise.
# This setting is only used if no Fortran compiler is
# found.
Maybe, that should be repeated in README.md
?
That setting is currently only mentioned indirectly in README.md
:
* `SUITESPARSE_USE_FORTRAN`
If `ON`, use the Fortran compiler to determine how C calls Fortan, and to
build several optional Fortran routines. If `OFF`, use
`SUITESPARSE_C_TO_FORTRAN` to define how C calls Fortran (see
`SuiteSparse_config/cmake_modules/SuiteSparsePolicy.cmake` for details).
Default: `ON`.
I opened #767 for a documentation update.
I'd vote for reverting 4f45fc4 because the interaction between the various settings with that change is confusing and users are required to carefully read the documentation and understand how cache variables work in CMake to not run into potential issues.
But I don't have strong feelings if you prefer to keep four parameters that need to be set to a correct combination to achieve the desired outcome.
See 5d2e7bf .