function errorCode = nvmex_helper(varargin)
%MEX_HELPER is a helper function that contains the code that MEX.M (an
% autogenerated file) executes. It sets up the inputs to call mex.pl (on PC)
% and mex (on Unix).
%
% For information on how to use MEX see MEX help by typing "help mex" or
% "mex -h".
% Copyright 1984-2006 The MathWorks, Inc.
% $Revision: 1.1.6.1 $
if isunix
mexname = get_mex_opts(varargin{:});
if ~isempty(mexname)
[loaded_m, loaded_mex] = inmem;
if ~isempty(loaded_mex)
clear_mex_file(mexname);
end
end
args = [' "ARCH=' computer('arch') '"'];
if (nargin > 0)
args = [args sprintf(' "%s"', varargin{:})];
end
errCode = unix([matlabroot '/bin/mex' args]);
elseif ispc
mexname = get_mex_opts(varargin{:});
matlab_bin_location=[matlabroot '\bin'];
if ~isempty(mexname)
[loaded_m, loaded_mex] = inmem;
if ~isempty(loaded_mex)
clear_mex_file(mexname);
end
end
% Loop over all the arguments. Put extra quotes around any that
% contain spaces.
for i=1:numel(varargin)
if (find(varargin{i} == ' '))
varargin{i} = [ '"' varargin{i} '"' ];
end
end
% Format the mex command
cmdargs = ['-called_from_matlab -matlab "' matlabroot '" ' sprintf(' %s', varargin{:})];
if (any(matlab_bin_location == ' '))
quote_str = '"';
else
quote_str = '';
end
cmdtool = [quote_str matlabroot '\sys\perl\win32\bin\perl.exe' quote_str ' ' ...
quote_str matlab_bin_location '\nvmex.pl' quote_str];
[cmd, rspfile] = make_rsp_file(cmdtool, cmdargs);
try
errCode = dos([ cmd ' -' computer('arch') ]);
try
% This is done to force a change message in case
% notificationhandles are not working properly. If it fails, we
% just want to keep going.
mexpath = fileparts(mexname);
fschange(mexpath);
catch
end
catch
disp(lasterr);
errCode = 1; % failure
end
delete(rspfile);
end
if (nargout > 0)
errorCode = errCode;
elseif (errCode ~= 0)
errorStruct.identifier='MATLAB:MEX:genericFailure';
errorStruct.message='Unable to complete successfully.';
rethrow(errorStruct);
end
%%%%%%%%%%%%%%%%%%%%
%%% SUBFUNCTIONS %%%
%%%%%%%%%%%%%%%%%%%%
function result = read_response_file(filename)
%
% Read a response file (a filename that starts with '@')
% and return a cell of strings, one per entry in the response file.
% Use Perl to ensure processing of arguments is the same as mex.bat
%
result = {};
cmd = ['"' matlabroot '\sys\perl\win32\bin\perl" -e "' ...
'require ''' matlabroot '\\sys\\perl\\win32\\lib\\shellwords.pl'';' ...
'open(FILE, ''' filename ''') || die ''Could not open ' filename ''';' ...
'while (<FILE>) {$line .= $_;} ' ...
'$line =~ s/\\/\\\\/g;' ...
'@ARGS = &shellwords($line); ' ...
'$\" = \"\n\";' ...
'print \"@ARGS\";'];
[s, r] = dos(cmd);
if s == 0
cr = sprintf('\n');
while ~isempty(r)
[result{end+1}, r] = strtok(r, cr);
end
end
function [mexname, setup] = get_mex_opts(varargin)
%
% GET_MEX_OPTS gets the options from the command line.
%
% name:
% It gets the name of the destination MEX-file. This has two
% purposes:
% 1) All platforms need to clear the MEX-file from memory before
% attempting the build, to avoid problems rebuilding shared
% libraries that the OS considers "in use".
% 2) Windows MATLAB deletes the MEX-file before the build occurs.
% It then checks to see whether the MEX-file was created so as
% to establish error status.
% This function returns the minimum necessary information. Further
% processing is done on the MEX-file name by clear_mex_file to
% successfully clear it.
%
% setup:
% It also returns whether or not '-setup' was passed.
%
mexname = '';
outdir = '';
setup = 0;
% First, check for and expand response files into varargin.
v = {};
for count=1:nargin
arg = varargin{count};
if arg(1) == '@'
new_args = read_response_file(arg(2:end));
v(end+1:end+length(new_args)) = new_args;
else
v{end+1} = arg;
end
end
varargin = v;
count = 1;
while (count <= nargin)
arg = varargin{count};
if isempty(mexname) && arg(1) ~= '-' && ~any(arg=='=') && any(arg=='.')
% Source file: MEX-file will be built in current directory
% Only the first source file matters
mexname = arg;
[notUsed, mexname] = fileparts(mexname); %#ok
elseif strcmp(arg, '-f')
count = count + 1;
elseif strcmp(arg, '-output')
count = count + 1;
if count > length(varargin)
errorStruct.identifier = 'MATLAB:MEX:OutputSwitchMisuse';
errorStruct.message = 'The -output switch must be followed by a file name.';
rethrow(errorStruct);
end
mexname = varargin{count};
[outdirTemp,mexname]=fileparts(mexname);
elseif strcmp(arg, '-outdir')
count = count + 1;
if count > length(varargin)
errorStruct.identifier = 'MATLAB:MEX:OutdirSwitchMisuse';
errorStruct.message = 'The -outdir switch must be followed by a directory name.';
rethrow(errorStruct);
end
outdir = varargin{count};
elseif strcmp(arg, '-setup')
setup = 1;
break;
end
count = count + 1;
end
if isempty(outdir) && exist('outdirTemp','var') %Meaning -ouptut
%used but not -outdir
outdir = outdirTemp;
end
mexname = fullfile(outdir, mexname);
function clear_mex_file(basename)
%
% CLEAR_MEX_FILE Clear a MEX-file from memory. This is a tricky
% business and should be avoided if possible. It takes a relative
% or absolute filename as the MEX-file name, and the list of loaded
% MEX-file names.
%
% If CLEAR_MEX_FILE is unable to clear the MEX-file, it will error.
% This can happen if the MEX-file is locked.
% The purpose of following block is to make sure that fullname is a fully
% qualified path.
seps = find(basename == filesep);
if isempty(seps)
% basename is in the current directory
fullname = fullfile(cd,basename);
else
% -output or -outdir was used to determine the location, as well as the
% name of the mex file.
savedir = cd;
[destdir,destname] = fileparts(basename);
cd(destdir);
fullname = fullfile(cd,destname);
cd(savedir);
end
if ~isempty(findstr(fullname, 'private'))
% Things in private directories are represented by the full
% path
mexname = fullname;
else
modifiers = find(fullname == '@');
if any(modifiers)
% Methods have the class directory prepended
mexname = fullname((modifiers(end)+1):end);
% Methods are always displayed with UNIX file
% separators
mexname(mexname==filesep) = '/';
else
% Otherwise, we just use the base name
mexname = basename;
end
end
clear_mex(mexname);
% Make sure that the MEX-file is cleared
[ms, mexs] = inmem;
if ~isempty(strmatch(mexname, mexs, 'exact'))
errorStruct.identifier = 'MATLAB:MEX:mexFileLocked';
errorStruct.message = 'Your MEX-file is locked and must be unlocked before recompiling.';
rethrow(errorStruct);
end
function clear_mex(varargin)
% This will clear a MEX-file successfully, because it has no internal
% variables. varargin is a builtin function and is therefore not a
% valid MEX-file name.
clear(varargin{:});
function [cmd, rspfile] = make_rsp_file(cmdtool, cmdargs)
rspfile = [tempname '.rsp'];
[Frsp, errmsg] = fopen(rspfile, 'wt');
if Frsp == -1
errorStruct.identifier = 'MATLAB:MEX:RspFilePermissionOpen';
errorStruct.message = sprintf('Cannot open file "%s" for writing: %s.', rspfile, errmsg);
rethrow(errorStruct);
end
try
count = fprintf(Frsp, '%s', cmdargs);
if count < length(cmdargs)
errmsg = ferror(Frsp);
errorStruct.identifier = 'MATLAB:MEX:RspFilePermissionWrite';
errorStruct.message = sprintf('Cannot write to file "%s": %s.', rspfile, errmsg);
rethrow(errorStruct);
end
fclose(Frsp);
catch
fclose(Frsp);
delete(rspfile);
rethrow(lasterror);
end
cmd = [cmdtool ' @"' rspfile '"'];