-
Notifications
You must be signed in to change notification settings - Fork 31
/
nvmex_helper.m
280 lines (246 loc) · 8.47 KB
/
nvmex_helper.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
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 '"'];