You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
476 lines
16 KiB
476 lines
16 KiB
% mtimesx_build compiles mtimesx.c with BLAS libraries
|
|
%******************************************************************************
|
|
%
|
|
% MATLAB (R) is a trademark of The Mathworks (R) Corporation
|
|
%
|
|
% Function: mtimesx_build
|
|
% Filename: mtimesx_build.m
|
|
% Programmer: James Tursa
|
|
% Version: 1.40
|
|
% Date: October 4, 2010
|
|
% Copyright: (c) 2009, 2010 by James Tursa, All Rights Reserved
|
|
%
|
|
% This code uses the BSD License:
|
|
%
|
|
% Redistribution and use in source and binary forms, with or without
|
|
% modification, are permitted provided that the following conditions are
|
|
% met:
|
|
%
|
|
% * Redistributions of source code must retain the above copyright
|
|
% notice, this list of conditions and the following disclaimer.
|
|
% * Redistributions in binary form must reproduce the above copyright
|
|
% notice, this list of conditions and the following disclaimer in
|
|
% the documentation and/or other materials provided with the distribution
|
|
%
|
|
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
% POSSIBILITY OF SUCH DAMAGE.
|
|
%
|
|
%--
|
|
%
|
|
% mtimesx_build compiles mtimesx.c and mtimesx_RealTimesReal.c with the BLAS
|
|
% libraries libmwblas.lib (if present) or libmwlapack.lib (if libmwblas.lib
|
|
% is not present). This function basically works as follows:
|
|
%
|
|
% - Opens the current mexopts.bat file in the directory [prefdir], and
|
|
% checks to make sure that the compiler selected is cl or lcc. If it
|
|
% is not, then a warning is issued and the compilation continues with
|
|
% the assumption that the microsoft BLAS libraries will work.
|
|
%
|
|
% - Looks for the file libmwblas.lib or libmwlapack.lib files in the
|
|
% appropriate directory: [matlabroot '\extern\lib\win32\microsoft']
|
|
% or [matlabroot '\extern\lib\win32\lcc']
|
|
% or [matlabroot '\extern\lib\win64\microsoft']
|
|
% or [matlabroot '\extern\lib\win64\lcc']
|
|
%
|
|
% - Changes directory to the directory of the file mtimesx.m.
|
|
%
|
|
% - Compiles mtimesx.c (which includes mtimesx_RealTimesReal.c) along with
|
|
% either libmwblas.lib or libmwlapack.lib depending on the version of
|
|
% MATLAB. The resulting exedcutable mex file is placed in the same
|
|
% directory as the source code. The files mtimesx.m, mtimesx.c, and
|
|
% mtimesx_RealTimesReal.c must all be in the same directory.
|
|
%
|
|
% - Changes the directory back to the original directory.
|
|
%
|
|
% Change Log:
|
|
% 2009/Sep/27 --> 1.00, Initial Release
|
|
% 2010/Feb/15 --> 1.10, Fixed largearrardims typo to largeArrayDims
|
|
% 2010/Oct/04 --> 1.40, Updated support for OpenMP compiling
|
|
%
|
|
%**************************************************************************
|
|
|
|
function mtimesx_build(x)
|
|
disp(' ');
|
|
disp('... Build routine for mtimesx');
|
|
|
|
TRUE = 1;
|
|
FALSE = 0;
|
|
|
|
%\
|
|
% Check for number of inputs & outputs
|
|
%/
|
|
|
|
noopenmp = FALSE;
|
|
if( nargin == 1 )
|
|
if( isequal(upper(x),'NOOPENMP') )
|
|
noopenmp = TRUE;
|
|
else
|
|
error('Invalid input.');
|
|
end
|
|
elseif( nargin ~= 0 )
|
|
error('Too many inputs. Expected none.');
|
|
end
|
|
if( nargout ~= 0 )
|
|
error('Too many outputs. Expected none.');
|
|
end
|
|
|
|
%\
|
|
% Check for non-PC
|
|
%/
|
|
|
|
disp('... Checking for PC');
|
|
try
|
|
% ispc does not appear in MATLAB 5.3
|
|
pc = ispc ;
|
|
catch
|
|
% if ispc fails, assume we are on a Windows PC if it's not unix
|
|
pc = ~isunix ;
|
|
end
|
|
|
|
if( ~pc )
|
|
disp('Non-PC auto build is not currently supported. You will have to');
|
|
disp('manually compile the mex routine. E.g., as follows:');
|
|
disp(' ');
|
|
disp('>> blas_lib = ''the_actual_path_and_name_of_your_systems_BLAS_library''');
|
|
disp('>> mex(''-DDEFINEUNIX'',''mtimesx.c'',blas_lib)');
|
|
disp(' ');
|
|
disp('or');
|
|
disp(' ');
|
|
disp('>> mex(''-DDEFINEUNIX'',''-largeArrayDims'',''mtimesx.c'',blas_lib)');
|
|
disp(' ');
|
|
error('Unable to compile mtimesx.c');
|
|
end
|
|
|
|
%\
|
|
% Check to see that mtimesx.c source code is present
|
|
%/
|
|
|
|
disp('... Finding path of mtimesx C source code files');
|
|
try
|
|
mname = mfilename('fullpath');
|
|
catch
|
|
mname = mfilename;
|
|
end
|
|
cname = [mname(1:end-6) '.c'];
|
|
if( isempty(dir(cname)) )
|
|
disp('Cannot find the file mtimesx.c in the same directory as the');
|
|
disp('file mtimesx_build.m. Please ensure that they are in the same');
|
|
disp('directory and try again. The following file was not found:');
|
|
disp(' ');
|
|
disp(cname);
|
|
disp(' ');
|
|
error('Unable to compile mtimesx.c');
|
|
end
|
|
disp(['... Found file mtimesx.c in ' cname]);
|
|
|
|
%\
|
|
% Check to see that mtimesx_RealTimesReal.c source code is present
|
|
%/
|
|
|
|
rname = [mname(1:end-13) 'mtimesx_RealTimesReal.c'];
|
|
if( isempty(dir(rname)) )
|
|
disp('Cannot find the file mtimesx_RealTimesReal.c in the same');
|
|
disp('directory as the file mtimesx_build.m. Please ensure that');
|
|
disp('they are in the same directory and try again. The');
|
|
disp('following file was not found:');
|
|
disp(' ');
|
|
disp(rname);
|
|
disp(' ');
|
|
error('Unable to compile mtimesx.c');
|
|
end
|
|
disp(['... Found file mtimesx_RealTimesReal.c in ' rname]);
|
|
|
|
%\
|
|
% Open the current mexopts.bat file
|
|
%/
|
|
|
|
% mexopts = [prefdir '\mexopts.bat'];
|
|
mexopts = [prefdir '\mex_C_win64.xml'];
|
|
fid = fopen(mexopts);
|
|
if( fid == -1 )
|
|
error('A C/C++ compiler has not been selected with mex -setup');
|
|
end
|
|
disp(['... Opened the mexopts.bat file in ' mexopts]);
|
|
disp('... Reading the mexopts.bat file to find the compiler and options used.');
|
|
|
|
%\
|
|
% Check for the correct compiler selected.
|
|
%/
|
|
|
|
ok_cl = FALSE;
|
|
ok_lcc = FALSE;
|
|
omp_option = '';
|
|
compiler = '(unknown)';
|
|
compilername = '';
|
|
while( TRUE )
|
|
tline = fgets(fid);
|
|
if( isequal(tline,-1) )
|
|
break;
|
|
else
|
|
if( isempty(compilername) )
|
|
y = findstr(tline,'OPTS.BAT');
|
|
if( ~isempty(y) )
|
|
x = findstr(tline,'rem ');
|
|
if( ~isempty(x) )
|
|
compilername = tline(x+4:y-1);
|
|
end
|
|
end
|
|
end
|
|
x = findstr(tline,'COMPILER=lcc');
|
|
if( ~isempty(x) )
|
|
ok_lcc = TRUE;
|
|
libdir = 'lcc';
|
|
compiler = 'LCC';
|
|
disp(['... ' compiler ' is the selected compiler']);
|
|
break;
|
|
end
|
|
x = findstr(tline,'COMPILER=cl');
|
|
if( ~isempty(x) )
|
|
ok_cl = TRUE;
|
|
libdir = 'microsoft';
|
|
compiler = ['Microsoft_' compilername '_cl'];
|
|
omp_option = ' /openmp';
|
|
disp(['... ' compiler ' is the selected compiler']);
|
|
break;
|
|
end
|
|
x = findstr(tline,'COMPILER=bcc32');
|
|
if( ~isempty(x) )
|
|
ok_cl = TRUE;
|
|
libdir = 'microsoft';
|
|
compiler = ['Borland_' compilername '_bcc32'];
|
|
disp(['... ' compiler ' is the selected compiler']);
|
|
disp('... Assuming that Borland will link with Microsoft libraries');
|
|
break;
|
|
end
|
|
x = findstr(tline,'COMPILER=icl');
|
|
if( ~isempty(x) )
|
|
ok_cl = TRUE;
|
|
if( pc )
|
|
omp_option = ' -Qopenmp';
|
|
else
|
|
omp_option = ' -openmp';
|
|
end
|
|
libdir = 'microsoft';
|
|
compiler = ['Intel_' compilername '_icl'];
|
|
disp(['... ' compiler ' is the selected compiler']);
|
|
disp('... Assuming that Intel will link with Microsoft libraries');
|
|
break;
|
|
end
|
|
x = findstr(tline,'COMPILER=wc1386');
|
|
if( ~isempty(x) )
|
|
ok_cl = TRUE;
|
|
libdir = 'microsoft';
|
|
compiler = ['Watcom_' compilername '_wc1386'];
|
|
disp(['... ' compiler ' is the selected compiler']);
|
|
disp('... Assuming that Watcom will link with Microsoft libraries');
|
|
break;
|
|
end
|
|
x = findstr(tline,'COMPILER=gcc');
|
|
if( ~isempty(x) )
|
|
ok_cl = TRUE;
|
|
libdir = 'microsoft';
|
|
omp_option = ' -fopenmp';
|
|
compiler = 'GCC';
|
|
disp(['... ' compiler ' is the selected compiler']);
|
|
disp('... Assuming that GCC will link with Microsoft libraries');
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
fclose(fid);
|
|
|
|
%\
|
|
% MS Visual C/C++ or lcc compiler has not been selected
|
|
%/
|
|
|
|
if( ~(ok_cl | ok_lcc) )
|
|
warning('... Supported C/C++ compiler has not been selected with mex -setup');
|
|
warning('... Assuming that Selected Compiler will link with Microsoft libraries');
|
|
warning('... Continuing at risk ...');
|
|
libdir = 'microsoft';
|
|
end
|
|
|
|
%\
|
|
% If an OpenMP supported compiler is potentially present, make sure that the
|
|
% necessary compile option is present in the mexopts.bat file on the COMPFLAGS
|
|
% line. If necessary, build a new mexopts.bat file with the correct option
|
|
% added to the COMPFLAGS line.
|
|
%/
|
|
|
|
while( TRUE )
|
|
ok_openmp = FALSE;
|
|
ok_compflags = FALSE;
|
|
xname = '';
|
|
if( isempty(omp_option) )
|
|
disp('... OpenMP compiler not detected ... you may want to check this website:');
|
|
disp(' http://openmp.org/wp/openmp-compilers/');
|
|
elseif( noopenmp )
|
|
disp(['... OpenMP compiler potentially detected, but not checking for ''' omp_option ''' compile option']);
|
|
else
|
|
disp('... OpenMP compiler potentially detected');
|
|
disp(['... Checking to see that the ''' omp_option ''' compile option is present']);
|
|
fid = fopen(mexopts);
|
|
while( TRUE )
|
|
tline = fgets(fid);
|
|
if( isequal(tline,-1) )
|
|
break;
|
|
else
|
|
x = findstr(tline,'set COMPFLAGS');
|
|
if( ~isempty(x) )
|
|
ok_compflags = TRUE;
|
|
x = findstr(tline,omp_option);
|
|
if( ~isempty(x) )
|
|
ok_openmp = TRUE;
|
|
end
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
fclose(fid);
|
|
if( ~ok_compflags )
|
|
warning(['... COMPFLAGS line not found ... ''' omp_option ''' will not be added.']);
|
|
elseif( ~ok_openmp )
|
|
disp(['... The ''' omp_option ''' compile option is not present ... adding it']);
|
|
xname = [mname(1:end-6) '_mexopts.bat'];
|
|
disp(['... Creating custom options file ' xname ' with the ''' omp_option ''' option added.']);
|
|
fid = fopen(mexopts);
|
|
fidx = fopen(xname,'w');
|
|
if( fidx == -1 )
|
|
xname = '';
|
|
warning(['... Unable to create custom mexopts.bat file ... ''' omp_option ''' will not be added']);
|
|
else
|
|
while( TRUE )
|
|
tline = fgets(fid);
|
|
if( isequal(tline,-1) )
|
|
break;
|
|
else
|
|
x = findstr(tline,'set COMPFLAGS');
|
|
if( ~isempty(x) )
|
|
n = numel(tline);
|
|
e = n;
|
|
while( tline(e) < 32 )
|
|
e = e - 1;
|
|
end
|
|
tline = [tline(1:e) omp_option tline(e+1:n)];
|
|
end
|
|
fwrite(fidx,tline);
|
|
end
|
|
end
|
|
fclose(fidx);
|
|
end
|
|
fclose(fid);
|
|
end
|
|
end
|
|
|
|
%\
|
|
% Construct full file name of libmwblas.lib and libmwlapack.lib. Note that
|
|
% not all versions have both files. Earlier versions only had the lapack
|
|
% file, which contained both blas and lapack routines.
|
|
%/
|
|
|
|
comp = computer;
|
|
mext = mexext;
|
|
lc = length(comp);
|
|
lm = length(mext);
|
|
cbits = comp(max(1:lc-1):lc);
|
|
mbits = mext(max(1:lm-1):lm);
|
|
if( isequal(cbits,'64') | isequal(mbits,'64') )
|
|
compdir = 'win64';
|
|
largearraydims = '-largeArrayDims';
|
|
else
|
|
compdir = 'win32';
|
|
largearraydims = '';
|
|
end
|
|
|
|
lib_blas = [matlabroot '\extern\lib\' compdir '\' libdir '\libmwblas.lib'];
|
|
d = dir(lib_blas);
|
|
if( isempty(d) )
|
|
disp('... BLAS library file not found, so linking with the LAPACK library');
|
|
lib_blas = [matlabroot '\extern\lib\' compdir '\' libdir '\libmwlapack.lib'];
|
|
end
|
|
disp(['... Using BLAS library lib_blas = ''' lib_blas '''']);
|
|
|
|
%\
|
|
% Save old directory and change to source code directory
|
|
%/
|
|
|
|
cdold = cd;
|
|
if( length(mname) > 13 )
|
|
cd(mname(1:end-13));
|
|
end
|
|
|
|
%\
|
|
% Do the compile
|
|
%/
|
|
|
|
disp('... Now attempting to compile ...');
|
|
disp(' ');
|
|
try
|
|
if( isunix )
|
|
if( isempty(largearraydims) )
|
|
if( isempty(xname) )
|
|
disp(['mex(''-DDEFINEUNIX'',''' cname ''',lib_blas,''-DCOMPILER=' compiler ''')']);
|
|
disp(' ');
|
|
mex('-DDEFINEUNIX',cname,lib_blas,['-DCOMPILER=' compiler]);
|
|
else
|
|
disp(['mex(''-f'',''' xname ''',''-DDEFINEUNIX'',''' cname ''',lib_blas,''-DCOMPILER=' compiler ''')']);
|
|
disp(' ');
|
|
mex('-f',xname,'-DDEFINEUNIX',cname,lib_blas,['-DCOMPILER=' compiler]);
|
|
end
|
|
else
|
|
if( isempty(xname) )
|
|
disp(['mex(''-DDEFINEUNIX'',''' cname ''',''' largearraydims ''',lib_blas,''-DCOMPILER=' compiler ''')']);
|
|
disp(' ');
|
|
mex('-DDEFINEUNIX',largearraydims,cname,lib_blas,['-DCOMPILER=' compiler]);
|
|
else
|
|
disp(['mex(''-f'',''' xname ''',''-DDEFINEUNIX'',''' cname ''',''' largearraydims ''',lib_blas,''-DCOMPILER=' compiler ''')']);
|
|
disp(' ');
|
|
mex('-f',xname,'-DDEFINEUNIX',largearraydims,cname,lib_blas,['-DCOMPILER=' compiler]);
|
|
end
|
|
end
|
|
else
|
|
if( isempty(largearraydims) )
|
|
if( isempty(xname) )
|
|
disp(['mex(''' cname ''',lib_blas,''-DCOMPILER=' compiler ''')']);
|
|
disp(' ');
|
|
mex(cname,lib_blas,['-DCOMPILER=' compiler]);
|
|
else
|
|
disp(['mex(''-f'',''' xname ''',''' cname ''',lib_blas,''-DCOMPILER=' compiler ''')']);
|
|
disp(' ');
|
|
mex('-f',xname,cname,lib_blas,['-DCOMPILER=' compiler]);
|
|
end
|
|
else
|
|
if( isempty(xname) )
|
|
disp(['mex(''' cname ''',''' largearraydims ''',lib_blas,''-DCOMPILER=' compiler ''')']);
|
|
disp(' ');
|
|
mex(cname,largearraydims,lib_blas,['-DCOMPILER=' compiler]);
|
|
else
|
|
disp(['mex(''-f'',''' xname ''',''' cname ''',''' largearraydims ''',lib_blas,''-DCOMPILER=' compiler ''')']);
|
|
disp(' ');
|
|
mex('-f',xname,cname,largearraydims,lib_blas,['-DCOMPILER=' compiler]);
|
|
end
|
|
end
|
|
end
|
|
disp('... mex mtimesx.c build completed ... you may now use mtimesx.');
|
|
disp(' ');
|
|
mtimesx;
|
|
break;
|
|
catch
|
|
if( noopenmp )
|
|
cd(cdold);
|
|
disp(' ');
|
|
disp('... Well, *that* didn''t work either!');
|
|
disp(' ');
|
|
disp('The mex command failed. This may be because you have already run');
|
|
disp('mex -setup and selected a non-C compiler, such as Fortran. If this');
|
|
disp('is the case, then rerun mex -setup and select a C/C++ compiler.');
|
|
disp(' ');
|
|
error('Unable to compile mtimesx.c');
|
|
else
|
|
disp(' ');
|
|
disp('... Well, *that* didn''t work ...');
|
|
disp(' ');
|
|
if( isequal(omp_option,' /openmp') )
|
|
disp('This may be because an OpenMP compile option was added that the');
|
|
disp('compiler did not like. For example, the Standard versions of the');
|
|
disp('Microsoft C/C++ compilers do not support OpenMP, only the');
|
|
disp('Professional versions do. Attempting to compile again but this');
|
|
disp(['time will not add the ''' omp_option ''' option.'])
|
|
else
|
|
disp('This may be because an OpenMP compile option was added that the');
|
|
disp('compiler did not like. Attempting to compile again, but this time');
|
|
disp(['will not add the ''' omp_option ''' option.'])
|
|
end
|
|
disp(' ');
|
|
noopenmp = TRUE;
|
|
end
|
|
end
|
|
end
|
|
|
|
%\
|
|
% Restore old directory
|
|
%/
|
|
|
|
cd(cdold);
|
|
|
|
return
|
|
end
|
|
|