1function klu_make (metis_path)
2%KLU_MAKE compiles the KLU mexFunctions
3%
4% Example:
5%   klu_make
6%
7% KLU relies on AMD, COLAMD, and BTF for its ordering options, and can
8% optionally use CHOLMOD, CCOLAMD, CAMD, and METIS as well.
9%
10% You must type the klu_make command while in the KLU/MATLAB directory.
11%
12% See also klu.
13
14% Copyright 2004-2016, Univ. of Florida
15
16if (nargin < 1)
17    metis_path = '../../metis-5.1.0' ;
18end
19with_cholmod = exist (metis_path, 'dir') ;
20
21details = 0 ;       % if 1, print details of each command
22
23d = '' ;
24if (~isempty (strfind (computer, '64')))
25    % 64-bit MATLAB
26    d = '-largeArrayDims' ;
27end
28
29% MATLAB 8.3.0 now has a -silent option to keep 'mex' from burbling too much
30if (~verLessThan ('matlab', '8.3.0'))
31    d = ['-silent ' d] ;
32end
33
34fprintf ('Compiling KLU ') ;
35kk = 0 ;
36
37include = '-I. -I../../AMD/Include -I../../COLAMD/Include -I../Include -I../../SuiteSparse_config -I../../BTF/Include' ;
38
39if (with_cholmod)
40    include = [include ' -I../../CCOLAMD/Include -I../../CAMD/Include -I../../CHOLMOD/Include -I../../SuiteSparse_config -I../User'] ;
41    include = [include ' -I' metis_path '/include'] ;
42    include = [include ' -I' metis_path '/GKlib'] ;
43    include = [include ' -I' metis_path '/libmetis'] ;
44end
45
46% do not attempt to compile CHOLMOD with large file support (not needed)
47include = [include ' -DNLARGEFILE'] ;
48
49% fix the METIS 4.0.1 rename.h file
50if (with_cholmod)
51    fprintf ('with CHOLMOD, CAMD, CCOLAMD, and METIS\n') ;
52    include = ['-DNSUPERNODAL -DNMODIFY -DNMATRIXOPS -DNCHECK ' include] ;
53else
54    fprintf ('without CHOLMOD, CAMD, CCOLAMD, and METIS\n') ;
55    include = ['-DNCHOLMOD ' include] ;
56end
57
58suitesparse_src = { '../../SuiteSparse_config/SuiteSparse_config' } ;
59
60amd_src = { ...
61    '../../AMD/Source/amd_1', ...
62    '../../AMD/Source/amd_2', ...
63    '../../AMD/Source/amd_aat', ...
64    '../../AMD/Source/amd_control', ...
65    '../../AMD/Source/amd_defaults', ...
66    '../../AMD/Source/amd_dump', ...
67    '../../AMD/Source/amd_global', ...
68    '../../AMD/Source/amd_info', ...
69    '../../AMD/Source/amd_order', ...
70    '../../AMD/Source/amd_postorder', ...
71    '../../AMD/Source/amd_post_tree', ...
72    '../../AMD/Source/amd_preprocess', ...
73    '../../AMD/Source/amd_valid' } ;
74
75colamd_src = {
76    '../../COLAMD/Source/colamd' } ;
77
78if (with_cholmod)
79
80    camd_src = { ...
81        '../../CAMD/Source/camd_1', ...
82        '../../CAMD/Source/camd_2', ...
83        '../../CAMD/Source/camd_aat', ...
84        '../../CAMD/Source/camd_control', ...
85        '../../CAMD/Source/camd_defaults', ...
86        '../../CAMD/Source/camd_dump', ...
87        '../../CAMD/Source/camd_global', ...
88        '../../CAMD/Source/camd_info', ...
89        '../../CAMD/Source/camd_order', ...
90        '../../CAMD/Source/camd_postorder', ...
91        '../../CAMD/Source/camd_preprocess', ...
92        '../../CAMD/Source/camd_valid' } ;
93
94    ccolamd_src = {
95        '../../CCOLAMD/Source/ccolamd' } ;
96
97    metis_src = {
98        'GKlib/b64', ...
99        'GKlib/blas', ...
100        'GKlib/csr', ...
101        'GKlib/error', ...
102        'GKlib/evaluate', ...
103        'GKlib/fkvkselect', ...
104        'GKlib/fs', ...
105        'GKlib/getopt', ...
106        'GKlib/gkregex', ...
107        'GKlib/graph', ...
108        'GKlib/htable', ...
109        'GKlib/io', ...
110        'GKlib/itemsets', ...
111        'GKlib/mcore', ...
112        'GKlib/memory', ...
113        'GKlib/omp', ...
114        'GKlib/pdb', ...
115        'GKlib/pqueue', ...
116        'GKlib/random', ...
117        'GKlib/rw', ...
118        'GKlib/seq', ...
119        'GKlib/sort', ...
120        'GKlib/string', ...
121        'GKlib/timers', ...
122        'GKlib/tokenizer', ...
123        'GKlib/util', ...
124        'libmetis/auxapi', ...
125        'libmetis/balance', ...
126        'libmetis/bucketsort', ...
127        'libmetis/checkgraph', ...
128        'libmetis/coarsen', ...
129        'libmetis/compress', ...
130        'libmetis/contig', ...
131        'libmetis/debug', ...
132        'libmetis/fm', ...
133        'libmetis/fortran', ...
134        'libmetis/frename', ...
135        'libmetis/gklib', ...
136        'libmetis/graph', ...
137        'libmetis/initpart', ...
138        'libmetis/kmetis', ...
139        'libmetis/kwayfm', ...
140        'libmetis/kwayrefine', ...
141        'libmetis/mcutil', ...
142        'libmetis/mesh', ...
143        'libmetis/meshpart', ...
144        'libmetis/minconn', ...
145        'libmetis/mincover', ...
146        'libmetis/mmd', ...
147        'libmetis/ometis', ...
148        'libmetis/options', ...
149        'libmetis/parmetis', ...
150        'libmetis/pmetis', ...
151        'libmetis/refine', ...
152        'libmetis/separator', ...
153        'libmetis/sfm', ...
154        'libmetis/srefine', ...
155        'libmetis/stat', ...
156        'libmetis/timing', ...
157        'libmetis/util', ...
158        'libmetis/wspace', ...
159    } ;
160
161    for i = 1:length (metis_src)
162        metis_src {i} = [metis_path '/' metis_src{i}] ;
163    end
164
165    cholmod_src = {
166        '../../CHOLMOD/Core/cholmod_aat', ...
167        '../../CHOLMOD/Core/cholmod_add', ...
168        '../../CHOLMOD/Core/cholmod_band', ...
169        '../../CHOLMOD/Core/cholmod_change_factor', ...
170        '../../CHOLMOD/Core/cholmod_common', ...
171        '../../CHOLMOD/Core/cholmod_complex', ...
172        '../../CHOLMOD/Core/cholmod_copy', ...
173        '../../CHOLMOD/Core/cholmod_dense', ...
174        '../../CHOLMOD/Core/cholmod_error', ...
175        '../../CHOLMOD/Core/cholmod_factor', ...
176        '../../CHOLMOD/Core/cholmod_memory', ...
177        '../../CHOLMOD/Core/cholmod_sparse', ...
178        '../../CHOLMOD/Core/cholmod_transpose', ...
179        '../../CHOLMOD/Core/cholmod_triplet', ...
180        '../../CHOLMOD/Cholesky/cholmod_amd', ...
181        '../../CHOLMOD/Cholesky/cholmod_analyze', ...
182        '../../CHOLMOD/Cholesky/cholmod_colamd', ...
183        '../../CHOLMOD/Cholesky/cholmod_etree', ...
184        '../../CHOLMOD/Cholesky/cholmod_postorder', ...
185        '../../CHOLMOD/Cholesky/cholmod_rowcolcounts', ...
186        '../../CHOLMOD/Partition/cholmod_ccolamd', ...
187        '../../CHOLMOD/Partition/cholmod_csymamd', ...
188        '../../CHOLMOD/Partition/cholmod_camd', ...
189        '../../CHOLMOD/Partition/cholmod_metis', ...
190        '../../CHOLMOD/Partition/cholmod_nesdis' } ;
191
192else
193    camd_src = { } ;
194    ccolamd_src = { } ;
195    metis_src = { } ;
196    cholmod_src = { } ;
197end
198
199btf_src = {
200    '../../BTF/Source/btf_maxtrans', ...
201    '../../BTF/Source/btf_order', ...
202    '../../BTF/Source/btf_strongcomp' } ;
203
204klu_src = {
205    '../Source/klu_free_symbolic', ...
206    '../Source/klu_defaults', ...
207    '../Source/klu_analyze_given', ...
208    '../Source/klu_analyze', ...
209    '../Source/klu_memory' } ;
210
211if (with_cholmod)
212    klu_src = [klu_src { '../User/klu_l_cholmod' }] ;                       %#ok
213end
214
215klu_zlsrc = {
216    '../Source/klu', ...
217    '../Source/klu_kernel', ...
218    '../Source/klu_dump', ...
219    '../Source/klu_factor', ...
220    '../Source/klu_free_numeric', ...
221    '../Source/klu_solve', ...
222    '../Source/klu_scale', ...
223    '../Source/klu_refactor', ...
224    '../Source/klu_tsolve', ...
225    '../Source/klu_diagnostics', ...
226    '../Source/klu_sort', ...
227    '../Source/klu_extract', ...
228    } ;
229
230klu_lobj = {
231    'klu_l', ...
232    'klu_l_kernel', ...
233    'klu_l_dump', ...
234    'klu_l_factor', ...
235    'klu_l_free_numeric', ...
236    'klu_l_solve', ...
237    'klu_l_scale', ...
238    'klu_l_refactor', ...
239    'klu_l_tsolve', ...
240    'klu_l_diagnostics', ...
241    'klu_l_sort', ...
242    'klu_l_extract', ...
243    } ;
244
245klu_zlobj = {
246    'klu_zl', ...
247    'klu_zl_kernel', ...
248    'klu_zl_dump', ...
249    'klu_zl_factor', ...
250    'klu_zl_free_numeric', ...
251    'klu_zl_solve', ...
252    'klu_zl_scale', ...
253    'klu_zl_refactor', ...
254    'klu_zl_tsolve', ...
255    'klu_zl_diagnostics', ...
256    'klu_zl_sort', ...
257    'klu_zl_extract', ...
258    } ;
259
260try
261    % ispc does not appear in MATLAB 5.3
262    pc = ispc ;
263catch
264    % if ispc fails, assume we are on a Windows PC if it's not unix
265    pc = ~isunix ;
266end
267
268if (pc)
269    % Windows does not have drand48 and srand48, required by METIS.  Use
270    % drand48 and srand48 in CHOLMOD/MATLAB/Windows/rand48.c instead.
271    obj_extension = '.obj' ;
272    cholmod_src = [cholmod_src {'../../CHOLMOD/MATLAB/Windows/rand48'}] ;
273    include = [include ' -I../../CHOLMOD/MATLAB/Windows'] ;
274else
275    obj_extension = '.o' ;
276end
277
278% compile each library source file
279obj = ' ' ;
280
281source = [suitesparse_src amd_src btf_src klu_src colamd_src] ;
282if (with_cholmod)
283    source = [metis_src ccolamd_src camd_src cholmod_src source] ;
284end
285
286for f = source
287    ff = f {1} ;
288    if (isequal (ff, [metis_path '/GKlib/util']))
289        % special case, since a file with the same name also exists in libmetis
290        copyfile ([ff '.c'], 'GKlib_util.c', 'f') ;
291        ff = 'GKlib_util' ;
292        o = 'GKlib_util' ;
293    elseif (isequal (ff, [metis_path '/GKlib/graph']))
294        % special case, since a file with the same name also exist in libmetis
295        copyfile ([ff '.c'], 'GKlib_graph.c', 'f') ;
296        ff = 'GKlib_graph' ;
297        o = 'GKlib_graph' ;
298    else
299        slash = strfind (ff, '/') ;
300        if (isempty (slash))
301            slash = 1 ;
302        else
303            slash = slash (end) + 1 ;
304        end
305        o = ff (slash:end) ;
306    end
307    % fprintf ('%s\n', o) ;
308    o = [o obj_extension] ;
309    obj = [obj  ' ' o] ;					            %#ok
310    s = sprintf ('mex %s -DDLONG -O %s -c %s.c', d, include, ff) ;
311    kk = do_cmd (s, kk, details) ;
312end
313
314for k = 1:length(klu_zlsrc)
315    ff = klu_zlsrc {k} ;
316    slash = strfind (ff, '/') ;
317    if (isempty (slash))
318        slash = 1 ;
319    else
320        slash = slash (end) + 1 ;
321    end
322    o = ff (slash:end) ;
323    s = sprintf ('mex %s -DDLONG -O %s -c %s.c', d, include, ff) ;
324    kk = do_cmd (s, kk, details) ;
325    lobj = klu_lobj {k} ;
326    obj = [obj  ' ' lobj obj_extension] ;                                   %#ok
327    mvfile ([o obj_extension], [lobj obj_extension]) ;
328    s = sprintf ('mex %s -DDLONG -DCOMPLEX -O %s -c %s.c', d, include, ff) ;
329    kk = do_cmd (s, kk, details) ;
330    zlobj = klu_zlobj {k} ;
331    obj = [obj  ' ' zlobj obj_extension] ;                                  %#ok
332    mvfile ([o obj_extension], [zlobj obj_extension]) ;
333end
334
335% compile the KLU mexFunction
336s = sprintf ('mex %s -DDLONG -O %s -output klu klu_mex.c', d, include) ;
337s = [s obj] ;                                                               %#ok
338
339if (~(ispc || ismac))
340    % for POSIX timing routine
341    s = [s ' -lrt'] ;
342end
343
344kk = do_cmd (s, kk, details) ;
345
346% clean up
347s = ['delete ' obj] ;
348do_cmd (s, kk, details) ;
349
350rmfile ('GKlib_util.c') ;
351rmfile ('GKlib_graph.c') ;
352
353fprintf ('\nKLU successfully compiled\n') ;
354
355%-------------------------------------------------------------------------------
356
357function rmfile (file)
358% rmfile:  delete a file, but only if it exists
359if (length (dir (file)) > 0)                                                %#ok
360    delete (file) ;
361end
362
363%-------------------------------------------------------------------------------
364
365function cpfile (src, dst)
366% cpfile:  copy the src file to the filename dst, overwriting dst if it exists
367rmfile (dst)
368if (length (dir (src)) == 0)    %#ok
369    fprintf ('File does not exist: %s\n', src) ;
370    error ('File does not exist') ;
371end
372try
373    copyfile (src, dst) ;
374catch ME
375    % ignore errors of the form "cp: preserving permissions: ...
376    % Operation not supported".  rethrow all other errors.
377    if (isempty (strfind (ME.message, 'Operation not supported')))
378        rethrow (ME) ;
379    end
380end
381
382%-------------------------------------------------------------------------------
383
384function mvfile (src, dst)
385% mvfile:  move the src file to the filename dst, overwriting dst if it exists
386cpfile (src, dst) ;
387rmfile (src) ;
388
389%-------------------------------------------------------------------------------
390function kk = do_cmd (s, kk, details)
391%DO_CMD: evaluate a command, and either print it or print a "."
392if (details)
393    fprintf ('%s\n', s) ;
394else
395    if (mod (kk, 60) == 0)
396        fprintf ('\n') ;
397    end
398    kk = kk + 1 ;
399    fprintf ('.') ;
400end
401eval (s) ;
402
403