CompileARPACKx64 dll & lib ForVS2005 OnWindows 7 by UsingMinGW64
Author : Zeng qiang Date : 2013-3-4
To Use ARPACK functions with C/C++ in VS2005 x64 mode, I've tried many ways and all failed.
By searching a lot of webs, trying for several days, finally I succeeded. OK, no more waste, Let's Begin.
Step 1 - Download and setupMinGW64 andMSYS.
MSYS can get from the URL below(mingw-get-inst-20120426.exe):
(PS: MSYS is a console program which can use many Unix utilities on Windows. There is no 64 bits version of this collection of utilities because it is just a console and a set of tools to run bash instructions, no matter if they are 32 or 64 bits. Please make sure your Internet is work fine before setup!)
Install the software under the directory
D:\MinGW64
When asked what components to install,only select the following:
MSYS Basic System
MSYS Developer ToolKit
Once the install has finished, start the MinGW Shell
D:\MinGW\msys\1.0\msys.bat
For the convenience of using MSYS, input the command below in msys window to install a small tool which can help you use the MSYS:
mingw-get install msys-rxvt
This package is a graphical terminal. To use this terminal create a shortcut of the file msys.bat on the desktop and update the following properties:
Target:D:\MinGW\msys\1.0\msys.bat --rxvt
Start in:D:\MinGW\msys\1.0\bin
Then get MinGW64 from the URL:
It's a 7z-package which include the GCC4.7.2 for 64 & 32 bits.
The files I downloaded is:
x86_64-w64-mingw32-gcc-4.7.2-release-win64_rubenvb.7z
Uncompress the 7z-package into the D:\MinGW directory,
You will find a sub folder in D:\MinGW:
mingw64
You can also setup the MinGW32 in the same way and you can find another sub folder "mingw32" !
The MinGW32's URL is:
The files downloaded is:
i686-w64-mingw32-gcc-4.7.2-release-win32_rubenvb.7z
OK, Return the focus!!!
Now in msys window, create the following additional directories:
mkdir /d/mingw/local32
mkdir /d/mingw/local64
The two directories will be used to compile and install libraries and tool for 32 and 64 bits specific architectures.
Then update the following configuration file to mount these directories automatically.
D:\MinGW\msys\1.0\etc\fstab
Add this content in the file above:
D:\MinGW\ /mingw
D:\MinGW\mingw32\ /mingw32
D:\MinGW\mingw64\ /mingw64
D:\MinGW\local32\ /local32
D:\MinGW\local64\ /local64
Remember to restart the terminal after the above changes.
You can see the msys window changed:
and now in D:\MinGW, you can see the folders below:
Now create the following directories where we are installing common tools and configuration files.
mkdir /local{32,64}/{bin,etc,include,lib,share,dst,src}
mkdir /local{32,64}/lib/pkgconfig
To compile 32 and 64 bits applications independently we must createtwo configuration files.
Run the following command to create a configuration file for32 bits applications:
cat > /local32/etc/profile.local << "EOF" alias dir='ls -la --color=auto' alias ls='ls --color=auto' export PKG_CONFIG_PATH="/local32/lib/pkgconfig" export CPPFLAGS="-I/local32/include" export CFLAGS="-I/local32/include -mms-bitfields -mthreads -mtune=pentium3" export CXXFLAGS="-I/local32/include -mms-bitfields -mthreads -mtune=pentium3" export LDFLAGS="-L/local32/lib -lpthread -mthreads" export PATH=".:/local32/bin:/mingw32/bin:/mingw/bin:/bin:/opt/bin:$PATH" export PS1='\[\033[32m\]\u@\h \[\033[33m\w\033[0m\]$ ' export SRC_DIR=/local32/src export DST_DIR=/local32/dst export MINGW_HOME=/mingw32 export PKG_CONFIG=$DST_DIR/pkgconfig/bin/pkg-config.exe # Configure PATH and FLAGS. APPLICATION_ARRAY=( "LIBICONV_PREFIX:$DST_DIR/libiconv" "ZLIB_PREFIX:$DST_DIR/zlib" "BZIP2_PREFIX:$DST_DIR/bzip2" "LIBTOOL_PREFIX:$DST_DIR/libtool" "LIBXML2_PREFIX:$DST_DIR/libxml2" "LIBPNG_PREFIX:$DST_DIR/libpng" "LIBJPEG_PREFIX:$DST_DIR/libjpeg" "LIBTIFF_PREFIX:$DST_DIR/libtiff" "FREETYPE2_PREFIX:$DST_DIR/freetype2" "LCMS2_PREFIX:$DST_DIR/lcms2" "FFTW_PREFIX:$DST_DIR/fftw" "BOTAN_PREFIX:$DST_DIR/botan" "QT_PREFIX:$DST_DIR/qt" "OPENCV_PREFIX:$DST_DIR/opencv" "LIBUSBX_PREFIX:$DST_DIR/libusbx" "LIBFFI_PREFIX:$DST_DIR/libffi" "PKGCONFIG_PREFIX:$DST_DIR/pkg-config" "GETTEXT_PREFIX:$DST_DIR/gettext" "GLIB_PREFIX:$DST_DIR/glib" "GMQ8_PREFIX:$DST_DIR/gm-q8" "GMQ16_PREFIX:$DST_DIR/gm-q16" "IMQ8_PREFIX:$DST_DIR/im-q8" "IMQ16_PREFIX:$DST_DIR/im-q16" "BOOST_PREFIX:$DST_DIR/boost" "LIBUSBX_PREFIX:$DST_DIR/libusbx" "GLIB_PREFIX:$DST_DIR/glib" "YAFARAY_PREFIX:$DST_DIR/yafaray" ) for app in "${APPLICATION_ARRAY[@]}" ; do KEY=${app%%:*} VALUE=${app##*:} export "$KEY"="$VALUE" export PATH="$VALUE/bin:$PATH" export LDFLAGS="-L$VALUE/lib $LDFLAGS" export CFLAGS="-I$VALUE/include $CFLAGS" export CPPFLAGS="-I$VALUE/include $CPPFLAGS" export CXXFLAGS="-I$VALUE/include $CXXFLAGS" export PKG_CONFIG_PATH="$VALUE/lib/pkgconfig:$PKG_CONFIG_PATH" done export LIBFFI_CFLAGS="-I $DST_DIR/libffi/lib/libffi-3.0.11/include" export LIBFFI_LIBS="-L$DST_DIR/libffi/lib" EOF |
finish commands, you will find a "profile.local" file in your/local32/etc/ directory.
Then run the following command to create a configuration file for64 bits applications:
cat > /local64/etc/profile.local << "EOF" alias dir='ls -la --color=auto' alias ls='ls --color=auto' export PKG_CONFIG_PATH="/local64/lib/pkgconfig" export CPPFLAGS="-I/local64/include" export CFLAGS="-I/local64/include -mms-bitfields -mthreads" export CXXFLAGS="-I/local64/include -mms-bitfields -mthreads" export LDFLAGS="-L/local64/lib -lpthread" export PATH=".:/local64/bin:/mingw64/bin:/mingw/bin:/bin:/opt/bin:$PATH" export PS1='\[\033[32m\]\u@\h \[\033[33m\w\033[0m\]$ ' export SRC_DIR=/local64/src export DST_DIR=/local64/dst export MINGW_HOME=/mingw64 export PKG_CONFIG=$DST_DIR/pkgconfig/bin/pkg-config.exe # Configure PATH and FLAGS. APPLICATION_ARRAY=( "LIBICONV_PREFIX:$DST_DIR/libiconv" "ZLIB_PREFIX:$DST_DIR/zlib" "BZIP2_PREFIX:$DST_DIR/bzip2" "LIBTOOL_PREFIX:$DST_DIR/libtool" "LIBXML2_PREFIX:$DST_DIR/libxml2" "LIBPNG_PREFIX:$DST_DIR/libpng" "LIBJPEG_PREFIX:$DST_DIR/libjpeg" "LIBTIFF_PREFIX:$DST_DIR/libtiff" "FREETYPE2_PREFIX:$DST_DIR/freetype2" "LCMS2_PREFIX:$DST_DIR/lcms2" "FFTW_PREFIX:$DST_DIR/fftw" "BOTAN_PREFIX:$DST_DIR/botan" "QT_PREFIX:$DST_DIR/qt" "OPENCV_PREFIX:$DST_DIR/opencv" "LIBUSBX_PREFIX:$DST_DIR/libusbx" "LIBFFI_PREFIX:$DST_DIR/libffi" "PKGCONFIG_PREFIX:$DST_DIR/pkg-config" "GETTEXT_PREFIX:$DST_DIR/gettext" "GLIB_PREFIX:$DST_DIR/glib" "GMQ8_PREFIX:$DST_DIR/gm-q8" "GMQ16_PREFIX:$DST_DIR/gm-q16" "IMQ8_PREFIX:$DST_DIR/im-q8" "IMQ16_PREFIX:$DST_DIR/im-q16" "BOOST_PREFIX:$DST_DIR/boost" "LIBUSBX_PREFIX:$DST_DIR/libusbx" "GLIB_PREFIX:$DST_DIR/glib" "YAFARAY_PREFIX:$DST_DIR/yafaray" ) for app in "${APPLICATION_ARRAY[@]}" ; do KEY=${app%%:*} VALUE=${app##*:} export "$KEY"="$VALUE" export PATH="$VALUE/bin:$PATH" export LDFLAGS="-L$VALUE/lib $LDFLAGS" export CFLAGS="-I$VALUE/include $CFLAGS" export CPPFLAGS="-I$VALUE/include $CPPFLAGS" export CXXFLAGS="-I$VALUE/include $CXXFLAGS" export PKG_CONFIG_PATH="$VALUE/lib/pkgconfig:$PKG_CONFIG_PATH" done export LIBFFI_CFLAGS="-I $DST_DIR/libffi/lib/libffi-3.0.11/include" export LIBFFI_LIBS="-L$DST_DIR/libffi/lib" EOF |
Ok, the two configuration files have been created.
Finally default the configuration to 64bits when MSYS terminal is launched.(because we want to use the 64bits GCC tools to compile the ARPACK)
Type the following commands to set the default configuration:
cat >> /etc/profile << "EOF" if [ -f /local64/etc/profile.local ]; then source /local64/etc/profile.local fi EOF |
Those commands willappend some code to the end of the file "/msys/1.0/etc/profile" which used to configure the MSYS.
And you can always switch between configurations running any of the following commands:
source /local64/etc/profile.local
source /local32/etc/profile.local
Ok, now we finished the Step 1.
Step 2 - Download theARPACK andsetup.
ARPACK is a collection of Fortran77 subroutines designed to solve large scale eigenvalue problems.
You can download the ARPACK package from the URL:
http://www.caam.rice.edu/software/ARPACK/index.html
the file I downloaded is:
arpack96.tar.gz
patch.tar.gz
Or you can search it from the Netlib Web:
http://www.netlib.org/liblist.html
After download the two files, and copy them to the "/local64/src" directory.
Then launch the msys.bat, entering into the /local64/src directory.
cd $SRC_DIR
equals to the following commands:
cd /local64/src
Then uncompress the arpack96.tar.gz and patch.tar.gz:
tar zxvf arpack96.tar.gz
tar zxvf patch.tar.gz
ls
You can find a ARPACK folder like this:
cd ARPACK
ls
Now let's modify some file:
"ARmake.inc":
home = D:/MinGW/local64/src/ARPACK
FC = gfortran
#FFLAGS = -O -cg89(disable this line)
"UTIL/second.f" (change this file like below):
SUBROUTINE SECOND(T)
REAL T
CALL CPU_TIME(T)
RETURN
END
Ok, now we can compile the ARPACK under MinGW64 msys shell:
cd /local64/src/ARPACK
make lib
dllwrap --export-all-symbols BLAS/*.o LAPACK/*.o SRC/*.o UTIL/*.o -lgfortran --output-def arpack_win64.def -o arpack_win64.dll
Now you can find "libarpack_SUN4.a", "arpack_win64.def", "arpack_win64.dll" in your ARPACK directory like below:
If you want to do aimplicit link with your dll, a lib file will be needed.
Then you have to find your VS2005's lib.exe tool and add its path into the environment variables "PATH" so that we can use it in msys directly.
The lib.exe's path(x64):
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\amd64\lib.exe
(PS: My VS2005 is in the path "C:\Program Files (x86)\Microsoft Visual Studio 8",change that in your own way)
If you want to use x86 32bits 's lib.exe, you can find it in the path:
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\x86_amd64\lib.exe
OK, assume that you already add the lib.exe to the system environment variables:
Then restart the msys, and enter into your ARPACK directory, input those commands:
lib /machine:X64 /def:arpack_win64.def
Finish that, you can find a lib file in your ARPACK directory:
It is"arpack_win64.lib"!
Ok, now you have both arpack_win64.dll & arpack_win64.lib. Wait a moment, for your nomal running a C/C++ project linked with the dll & lib, you still need some other dll !!!
You can download a tool named "Dependency Walker", then run and open the file "arpack_win64.dll", you can find some other dependency:
libgfortran-3.dll
This dll you can find it in the "D:/MinGW/mingw64/bin/" directory.
Open the libgfortran-3.dll in Dependency Walker, you will find another two dependency dll:
libquadmath-0.dll
libgcc_s_sjlj-1.dll
The two dll file also can find in mingw64/bin directory.
(PS: if you were using 32bit x86's ARPACK dll & lib, you may need those three dll in mingw32/bin directory, the three dll have the same name with the mingw64/bin's dll, but in fact they are different.)
Ok, now you only need to copy those file out of the ARPACK directory with your arpack dll & lib, and you can use them in your own way!
Step 3 -calling ARPACK's function inVS2005.
After the step 2, you have those files:
Then you can create a C++ project to call the functions in your compiled ARPACK library.
I create a VC++ win32 project named "HelloARPACK".
First, I copied the dll and lib file into it's directory.
Then, I create a cpp file named HelloARPACK.cpp and add the following code :
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
double dlapy2_(double *x, double *y);
#ifdef __cplusplus
}
#endif
int main(int argc, char **argv)
{
/*********************************/
printf("Hello ARPACK dll&libx64 Test!\n");
double myX=1.0;
double myY=2.0;
double myResult=0.0;
myResult = dlapy2_(&myX,&myY);
printf("myResult=%lf\n",myResult);
/*********************************/
getchar();
return 0;
}
I add the lib into this project:
Then Configure the debug/release mode:
Builder->Configuration Manager:
Active solution platform : x64
Active solution configuration : debug or release
(PS: The dll & lib generated from this method can be used in both debug and release mode! That is more convenience.)
Then Build...
That's great! We succeeded!
You could scan the dlapy2's source code and know that this function is used to return a sqrt(x^2+y^2).
I set x=1.0, y=2.0
So the result in theory is sqrt(5)=2.2360679775...
Let's check the result from our program!
The result is:
Cheers! The result is right!
However, I want to used a modified fortran source code to compute the eigenvalue and eigenvectors, how can I do this?
Don't worry, see the next Step!
Step 4 - callingARPACK function to compute theeigenvalues and eigenvectors.
In ARPACK'sEXAMPLES directory, you will find several source which may be useful to you, now I need to solve a symmetric generalized problem described by Ax=λBx. the A matrix is symmetric, the B matrix is symmetric and positive-definite.
In ARPACK/EXAMPLES/SYM/ directory, I found thedsdrv3.f is used to me, and I change the code to solve my problem.
After change that, I want to calling dsdrv3.f by my C++ project ,I will transfer the A & B & other information into subroutine and wait for the return the eigenvalues and eigenvectors.
So, I decide to compile this dsdrv3.f in my arpack_win64.dll & lib and calling directly!
Then I must do some configuration and compile!
First, copy the changed dsdrv3.f into the ARPACK/SRC.
Second, open and modify the ARPACK/SRC/Makefile, find "DOBJ = d***.o..." position and add "dsdrv3.o" at the end of it:
Third, enter into the /ARPACK, and make lib:
cd /local64/src/ARPACK
make lib
dllwrap --export-all-symbols BLAS/*.o LAPACK/*.o SRC/*.o UTIL/*.o -lgfortran --output-def arpack_win64.def -o arpack_win64.dll
lib /machine:X64 /def:arpack_win64.def
OK, now you have finished the compile and got the new dll & lib.
Loot into the new arpack_win64.dll by using Dependency Walker:
Now you could see dsdrv3_ !!!
in the dsdrv3.f, my subroutine interface is:
subroutine dsdrv3(row,col,vv,dvalue,a_mat,b_mat,binv_mat)
integer row, col
Double precision vv(row*col),dvalue(col),a_mat(row*row),
& b_mat(row*row), binv_mat(row*row)
Then I plan to used it in my "HelloARPACK" project.
First, Update my arpack_win64.dll & lib.
Then, change the code in cpp file to test the dsdrv3_ function:
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
void dsdrv3_(int *row, int *col, double *vv, double *dvalue, double *a_mat, double *b_mat, double *binv_mat);
#ifdef __cplusplus
}
#endif
#define mySIZE 3
int main(int argc, char **argv)
{
/**********************************************/
printf("now test dsdrv3.f!\n");
double myA[mySIZE*mySIZE]={2,1,3,1,4,7,3,7,5};
double myB[mySIZE*mySIZE]={1,0,0,0,1,0,0,0,1};
double myB_inv[mySIZE*mySIZE]={1,0,0,0,1,0,0,0,1};
double myvv[mySIZE*mySIZE];
double mydvalue[2*mySIZE];
int myRow=mySIZE;
int myCol=mySIZE;
dsdrv3_(&myRow,&myCol,myvv,mydvalue,myA,myB,myB_inv);
printf("EigenVector:\n");
for (int i=0;i<mySIZE;i++)
{
for (int j=0;j<2;j++)
{
printf("%lf\t",myvv[j*mySIZE+i]);
}
printf("\n");
}
getchar();
return 0;
}
Ok, Rebult...
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
Cheers again! That's cool !
The A matrix I used is surely symmetric, the B matrix is surely positive-definite and symmetric. So the argument for the dsdrv3 is right!
Then Let's check the result:
Aha, I choosed to output 2 eigenvalue and 2 eigenvectors, compared with the matlab or you can compute it with your own hands, you will say "The result is right!".
Ok, I've finished this article!
I hope it will help other friends to hold ARPACK in Visual studio platform with your C/C++ projects.
If you have any suggestions & questions, or find some errors, please send me a E-mail.
Finally, thanks to the MinGW64/MSYS/ARPACK project group and other relative web-blog authors!
Zeng qiang
2013-3-4