~ubuntu-branches/debian/stretch/adios/stretch

« back to all changes in this revision

Viewing changes to wrappers/numpy/conf/mpidistutils.py

  • Committer: Package Import Robot
  • Author(s): Alastair McKinstry
  • Date: 2014-06-16 23:06:38 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20140616230638-5a0z7ylxx8i0edrg
Tags: 1.7.0-1
* New upstream release.
* Add adios.pc pkgconfig file. adios_config now uses this.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Author:  Lisandro Dalcin
 
2
# Contact: dalcinl@gmail.com
 
3
 
 
4
"""
 
5
Support for building mpi4py with distutils.
 
6
"""
 
7
 
 
8
# -----------------------------------------------------------------------------
 
9
 
 
10
import sys
 
11
if sys.version[:3] == '3.0':
 
12
    from distutils import version
 
13
    version.cmp = lambda a, b : (a > b) - (a < b)
 
14
    del version
 
15
del sys
 
16
 
 
17
# -----------------------------------------------------------------------------
 
18
 
 
19
import sys, os, platform, re
 
20
from distutils import sysconfig
 
21
from distutils.util  import convert_path
 
22
from distutils.util  import split_quoted
 
23
from distutils.spawn import find_executable
 
24
from distutils import log
 
25
 
 
26
def fix_config_vars(names, values):
 
27
    values = list(values)
 
28
    if sys.platform == 'darwin':
 
29
        if 'ARCHFLAGS' in os.environ:
 
30
            ARCHFLAGS = os.environ['ARCHFLAGS']
 
31
            for i, flag in enumerate(list(values)):
 
32
                flag, count = re.subn('-arch\s+\w+', ' ', flag)
 
33
                if count and ARCHFLAGS:
 
34
                    flag = flag + ' ' + ARCHFLAGS
 
35
                values[i] = flag
 
36
        if 'SDKROOT' in os.environ:
 
37
            SDKROOT = os.environ['SDKROOT']
 
38
            for i, flag in enumerate(list(values)):
 
39
                flag, count = re.subn('-isysroot [^ \t]*', ' ', flag)
 
40
                if count and SDKROOT:
 
41
                    flag = flag + ' ' + '-isysroot ' + SDKROOT
 
42
                values[i] = flag
 
43
    return values
 
44
 
 
45
def get_config_vars(*names):
 
46
    # Core Python configuration
 
47
    values = sysconfig.get_config_vars(*names)
 
48
    # Do any distutils flags fixup right now
 
49
    values = fix_config_vars(names, values)
 
50
    return values
 
51
 
 
52
def fix_compiler_cmd(cc, mpicc):
 
53
    if not mpicc: return cc
 
54
    if not cc:    return mpicc
 
55
    from os.path import basename
 
56
    cc = split_quoted(cc)
 
57
    i = 0
 
58
    while basename(cc[i]) == 'env':
 
59
        i = 1
 
60
        while '=' in cc[i]:
 
61
            i = i + 1
 
62
    cc[i] = mpicc
 
63
    return ' '.join(cc)
 
64
 
 
65
def fix_linker_cmd(ld, mpild):
 
66
    if not mpild: return ld
 
67
    if not ld:    return mpild
 
68
    from os.path import basename
 
69
    ld = split_quoted(ld)
 
70
    i = 0
 
71
    if (sys.platform.startswith('aix') and
 
72
        basename(ld[i]) == 'ld_so_aix'):
 
73
        i = i + 1
 
74
    while basename(ld[i]) == 'env':
 
75
        i = i + 1
 
76
        while '=' in ld[i]:
 
77
            i = i + 1
 
78
    ld[i] = mpild
 
79
    return ' '.join(ld)
 
80
 
 
81
def split_linker_cmd(ld):
 
82
    from os.path import basename
 
83
    ld = split_quoted(ld)
 
84
    i = 0
 
85
    if (sys.platform.startswith('aix') and
 
86
        basename(pyld[i]) == 'ld_so_aix'):
 
87
        i = i + 1
 
88
    while basename(ld[i]) == 'env':
 
89
        i = i + 1
 
90
        while '=' in ld[i]:
 
91
            i = i + 1
 
92
    p = i + 1
 
93
    ld, flags = ' '.join(ld[:p]), ' '.join(ld[p:])
 
94
    return ld, flags
 
95
 
 
96
from distutils.unixccompiler import UnixCCompiler
 
97
rpath_option_orig = UnixCCompiler.runtime_library_dir_option
 
98
def rpath_option(compiler, dir):
 
99
    option = rpath_option_orig(compiler, dir)
 
100
    if sys.platform.startswith('linux'):
 
101
        if option.startswith('-R'):
 
102
            option =  option.replace('-R', '-Wl,-rpath,', 1)
 
103
        elif option.startswith('-Wl,-R,'):
 
104
            option =  option.replace('-Wl,-R,', '-Wl,-rpath,', 1)
 
105
    return option
 
106
UnixCCompiler.runtime_library_dir_option = rpath_option
 
107
 
 
108
def customize_compiler(compiler, lang=None,
 
109
                       mpicc=None, mpicxx=None, mpild=None,
 
110
                       environ=None):
 
111
    if environ is None:
 
112
        environ = os.environ
 
113
    if compiler.compiler_type == 'unix':
 
114
        # Distutils configuration, actually obtained by parsing
 
115
        # :file:{prefix}/lib[32|64]/python{X}.{Y}/config/Makefile
 
116
        (cc, cxx, ccshared, ld,
 
117
         basecflags, opt) = get_config_vars (
 
118
            'CC', 'CXX', 'CCSHARED', 'LDSHARED',
 
119
            'BASECFLAGS', 'OPT')
 
120
        cc  = cc  .replace('-pthread', '')
 
121
        cxx = cxx .replace('-pthread', '')
 
122
        ld  = ld  .replace('-pthread', '')
 
123
        ld, ldshared = split_linker_cmd(ld)
 
124
        basecflags, opt = basecflags or '', opt or ''
 
125
        ccshared = ccshared or ''
 
126
        ldshared = ldshared or ''
 
127
        # Compiler command overriding
 
128
        if not mpild and (mpicc or mpicxx):
 
129
            if lang == 'c':
 
130
                mpild = mpicc
 
131
            elif lang == 'c++':
 
132
                mpild = mpicxx
 
133
            else:
 
134
                mpild = mpicc or mpicxx
 
135
        if mpicc:
 
136
            cc = fix_compiler_cmd(cc, mpicc)
 
137
        if mpicxx:
 
138
            cxx = fix_compiler_cmd(cxx, mpicxx)
 
139
        if mpild:
 
140
            ld = fix_linker_cmd(ld, mpild)
 
141
        # Environment handling
 
142
        cppflags = cflags = cxxflags = ldflags = ''
 
143
        CPPFLAGS = environ.get('CPPFLAGS', '')
 
144
        CFLAGS   = environ.get('CFLAGS',   '')
 
145
        CXXFLAGS = environ.get('CXXFLAGS', '')
 
146
        LDFLAGS  = environ.get('LDFLAGS',  '')
 
147
        if CPPFLAGS:
 
148
            cppflags = cppflags + ' ' + CPPFLAGS
 
149
            cflags   = cflags   + ' ' + CPPFLAGS
 
150
            cxxflags = cxxflags + ' ' + CPPFLAGS
 
151
            ldflags  = ldflags  + ' ' + CPPFLAGS
 
152
        if CFLAGS:
 
153
            cflags   = cflags   + ' ' + CFLAGS
 
154
            ldflags  = ldflags  + ' ' + CFLAGS
 
155
        if CXXFLAGS:
 
156
            cxxflags = cxxflags + ' ' + CXXFLAGS
 
157
            ldflags  = ldflags  + ' ' + CXXFLAGS
 
158
        if LDFLAGS:
 
159
            ldflags  = ldflags  + ' ' + LDFLAGS
 
160
        basecflags = environ.get('BASECFLAGS', basecflags)
 
161
        opt        = environ.get('OPT',        opt       )
 
162
        ccshared   = environ.get('CCSHARED', ccshared)
 
163
        ldshared   = environ.get('LDSHARED', ldshared)
 
164
        cflags     = ' '.join((basecflags, opt, cflags))
 
165
        cxxflags   = ' '.join((basecflags, opt, cxxflags))
 
166
        cxxflags = cxxflags.replace('-Wstrict-prototypes', '')
 
167
        # Distutils compiler setup
 
168
        cpp    = os.environ.get('CPP') or (cc + ' -E')
 
169
        cc_so  = cc  + ' ' + ccshared
 
170
        cxx_so = cxx + ' ' + ccshared
 
171
        ld_so  = ld  + ' ' + ldshared
 
172
        compiler.set_executables(
 
173
            preprocessor = cpp    + ' ' + cppflags,
 
174
            compiler     = cc     + ' ' + cflags,
 
175
            compiler_so  = cc_so  + ' ' + cflags,
 
176
            compiler_cxx = cxx_so + ' ' + cxxflags,
 
177
            linker_so    = ld_so  + ' ' + ldflags,
 
178
            linker_exe   = ld     + ' ' + ldflags,
 
179
            )
 
180
        try: compiler.compiler_cxx.remove('-Wstrict-prototypes')
 
181
        except: pass
 
182
    if compiler.compiler_type == 'mingw32':
 
183
        compiler.set_executables(
 
184
            preprocessor = 'gcc -mno-cygwin -E',
 
185
            )
 
186
    if compiler.compiler_type in ('unix', 'cygwin', 'mingw32'):
 
187
        if lang == 'c++':
 
188
            def find_cmd_pos(cmd):
 
189
                pos = 0
 
190
                if os.path.basename(cmd[pos]) == "env":
 
191
                    pos = 1
 
192
                    while '=' in cmd[pos]:
 
193
                        pos = pos + 1
 
194
                return pos
 
195
            i = find_cmd_pos(compiler.compiler_so)
 
196
            j = find_cmd_pos(compiler.compiler_cxx)
 
197
            compiler.compiler_so[i] = compiler.compiler_cxx[j]
 
198
            try: compiler.compiler_so.remove('-Wstrict-prototypes')
 
199
            except: pass
 
200
    if compiler.compiler_type == 'msvc':
 
201
        if not compiler.initialized:
 
202
            compiler.initialize()
 
203
        compiler.ldflags_shared.append('/MANIFEST')
 
204
        compiler.ldflags_shared_debug.append('/MANIFEST')
 
205
 
 
206
# -----------------------------------------------------------------------------
 
207
 
 
208
try:
 
209
    from mpiconfig import Config
 
210
except ImportError:
 
211
    from conf.mpiconfig import Config
 
212
 
 
213
def configuration(command_obj, verbose=True):
 
214
    config = Config()
 
215
    config.setup(command_obj)
 
216
    if verbose:
 
217
        if config.section and config.filename:
 
218
            log.info("MPI configuration: [%s] from '%s'",
 
219
                     config.section, ','.join(config.filename))
 
220
            config.info(log)
 
221
    return config
 
222
 
 
223
def configure_compiler(compiler, config, lang=None):
 
224
    #
 
225
    mpicc  = config.get('mpicc')
 
226
    mpicxx = config.get('mpicxx')
 
227
    mpild  = config.get('mpild')
 
228
    customize_compiler(compiler, lang,
 
229
                       mpicc=mpicc, mpicxx=mpicxx, mpild=mpild)
 
230
    #
 
231
    for k, v in config.get('define_macros', []):
 
232
        compiler.define_macro(k, v)
 
233
    for v in config.get('undef_macros', []):
 
234
        compiler.undefine_macro(v)
 
235
    for v in config.get('include_dirs', []):
 
236
        compiler.add_include_dir(v)
 
237
    for v in config.get('libraries', []):
 
238
        compiler.add_library(v)
 
239
    for v in config.get('library_dirs', []):
 
240
        compiler.add_library_dir(v)
 
241
    for v in config.get('runtime_library_dirs', []):
 
242
        compiler.add_runtime_library_dir(v)
 
243
    for v in config.get('extra_objects', []):
 
244
        compiler.add_link_object(v)
 
245
    if compiler.compiler_type in \
 
246
        ('unix', 'intel', 'cygwin', 'mingw32'):
 
247
        cc_args = config.get('extra_compile_args', [])
 
248
        ld_args = config.get('extra_link_args', [])
 
249
        compiler.compiler += cc_args
 
250
        compiler.compiler_so += cc_args
 
251
        compiler.compiler_cxx += cc_args
 
252
        compiler.linker_so += ld_args
 
253
        compiler.linker_exe += ld_args
 
254
    return compiler
 
255
 
 
256
# -----------------------------------------------------------------------------
 
257
 
 
258
try:
 
259
    from mpiscanner import Scanner
 
260
except ImportError:
 
261
    try:
 
262
        from conf.mpiscanner import Scanner
 
263
    except ImportError:
 
264
        class Scanner(object):
 
265
            def parse_file(self, *args):
 
266
                raise NotImplementedError(
 
267
                    "You forgot to grab 'mpiscanner.py'")
 
268
 
 
269
class ConfigureMPI(object):
 
270
 
 
271
    SRCDIR = 'src'
 
272
    SOURCES = [os.path.join('include', 'mpi4py', 'mpi.pxi')]
 
273
    DESTDIR = 'src'
 
274
    CONFIG_H = 'config.h'
 
275
    MISSING_H = 'missing.h'
 
276
 
 
277
    def __init__(self, config_cmd):
 
278
        self.scanner = Scanner()
 
279
        for filename in self.SOURCES:
 
280
            fullname = os.path.join(self.SRCDIR, filename)
 
281
            self.scanner.parse_file(fullname)
 
282
        self.config_cmd = config_cmd
 
283
 
 
284
    def run(self):
 
285
        results = []
 
286
        for name, code in self.scanner.itertests():
 
287
            log.info("checking for '%s' ..." % name)
 
288
            body = self.gen_one(results, code)
 
289
            ok   = self.run_one(body)
 
290
            if not ok:
 
291
                log.info("**** failed check for '%s'" % name)
 
292
            results.append((name, ok))
 
293
        return results
 
294
 
 
295
    def dump(self, results):
 
296
        destdir = self.DESTDIR
 
297
        config_h  = os.path.join(destdir, self.CONFIG_H)
 
298
        missing_h = os.path.join(destdir, self.MISSING_H)
 
299
        log.info("writing '%s'", config_h)
 
300
        self.scanner.dump_config_h(config_h, results)
 
301
        log.info("writing '%s'", missing_h)
 
302
        self.scanner.dump_missing_h(missing_h, None)
 
303
 
 
304
    def gen_one(self, results, code):
 
305
        #
 
306
        configtest_h = "_configtest.h"
 
307
        self.config_cmd.temp_files.insert(0, configtest_h)
 
308
        fh = open(configtest_h, "w")
 
309
        try:
 
310
            sep = "/* " + ('-'*72)+ " */\n"
 
311
            fh.write(sep)
 
312
            self.scanner.dump_config_h(fh, results)
 
313
            fh.write(sep)
 
314
            self.scanner.dump_missing_h(fh, results)
 
315
            fh.write(sep)
 
316
        finally:
 
317
            fh.close()
 
318
        #
 
319
        body = ['#include "%s"' % configtest_h,
 
320
                'int main(int argc, char **argv) {',
 
321
                '  %s' % code,
 
322
                '  return 0;',
 
323
                '}']
 
324
        body = '\n'.join(body) + '\n'
 
325
        return body
 
326
 
 
327
    def run_one(self, body, lang='c'):
 
328
        ok = self.config_cmd.try_link(body, headers=['mpi.h'], lang=lang)
 
329
        return ok
 
330
 
 
331
# -----------------------------------------------------------------------------
 
332
 
 
333
cmd_mpi_opts = [
 
334
 
 
335
    ('mpild=',   None,
 
336
     "MPI linker command, "
 
337
     "overridden by environment variable 'MPILD' "
 
338
     "(defaults to 'mpicc' or 'mpicxx' if any is available)"),
 
339
 
 
340
    ('mpif77=',  None,
 
341
     "MPI F77 compiler command, "
 
342
     "overridden by environment variable 'MPIF77' "
 
343
     "(defaults to 'mpif77' if available)"),
 
344
 
 
345
    ('mpif90=',  None,
 
346
     "MPI F90 compiler command, "
 
347
     "overridden by environment variable 'MPIF90' "
 
348
     "(defaults to 'mpif90' if available)"),
 
349
 
 
350
    ('mpif95=',  None,
 
351
     "MPI F95 compiler command, "
 
352
     "overridden by environment variable 'MPIF95' "
 
353
     "(defaults to 'mpif95' if available)"),
 
354
 
 
355
    ('mpicxx=',  None,
 
356
     "MPI C++ compiler command, "
 
357
     "overridden by environment variable 'MPICXX' "
 
358
     "(defaults to 'mpicxx', 'mpiCC', or 'mpic++' if any is available)"),
 
359
 
 
360
    ('mpicc=',   None,
 
361
     "MPI C compiler command, "
 
362
     "overridden by environment variables 'MPICC' "
 
363
     "(defaults to 'mpicc' if available)"),
 
364
 
 
365
    ('mpi=',     None,
 
366
     "specify a configuration section, "
 
367
     "and an optional list of configuration files "
 
368
     + "(e.g. --mpi=section,file1" + os.path.pathsep + "file2), " +
 
369
     "to look for MPI includes/libraries, "
 
370
     "overridden by environment variable 'MPICFG' "
 
371
     "(defaults to section 'mpi' in configuration file 'mpi.cfg')"),
 
372
 
 
373
    ('configure', None,
 
374
     "exhaustive test for checking missing MPI constants/types/functions"),
 
375
 
 
376
    ]
 
377
 
 
378
def cmd_get_mpi_options(cmd_opts):
 
379
    optlist = []
 
380
    for (option, _, _) in cmd_opts:
 
381
        if option[-1] == '=':
 
382
            option = option[:-1]
 
383
        option = option.replace('-','_')
 
384
        optlist.append(option)
 
385
    return optlist
 
386
 
 
387
def cmd_initialize_mpi_options(cmd):
 
388
    mpiopts = cmd_get_mpi_options(cmd_mpi_opts)
 
389
    for op in mpiopts:
 
390
        setattr(cmd, op, None)
 
391
 
 
392
def cmd_set_undefined_mpi_options(cmd, basecmd):
 
393
    mpiopts = cmd_get_mpi_options(cmd_mpi_opts)
 
394
    optlist = tuple(zip(mpiopts, mpiopts))
 
395
    cmd.set_undefined_options(basecmd, *optlist)
 
396
 
 
397
# -----------------------------------------------------------------------------
 
398
 
 
399
from distutils.core import setup        as fcn_setup
 
400
from distutils.core import Distribution as cls_Distribution
 
401
from distutils.core import Extension    as cls_Extension
 
402
from distutils.core import Command
 
403
 
 
404
from distutils.command import config  as cmd_config
 
405
from distutils.command import build   as cmd_build
 
406
from distutils.command import install as cmd_install
 
407
from distutils.command import sdist   as cmd_sdist
 
408
from distutils.command import clean   as cmd_clean
 
409
 
 
410
from distutils.command import build_py     as cmd_build_py
 
411
from distutils.command import build_clib   as cmd_build_clib
 
412
from distutils.command import build_ext    as cmd_build_ext
 
413
from distutils.command import install_data as cmd_install_data
 
414
from distutils.command import install_lib  as cmd_install_lib
 
415
 
 
416
from distutils.errors import DistutilsError
 
417
from distutils.errors import DistutilsSetupError
 
418
from distutils.errors import DistutilsPlatformError
 
419
from distutils.errors import DistutilsOptionError
 
420
from distutils.errors import CCompilerError
 
421
 
 
422
# -----------------------------------------------------------------------------
 
423
 
 
424
# Distribution class supporting a 'executables' keyword
 
425
 
 
426
class Distribution(cls_Distribution):
 
427
 
 
428
    def __init__ (self, attrs=None):
 
429
        # support for pkg data
 
430
        self.package_data = {}
 
431
        # PEP 314
 
432
        self.provides = None
 
433
        self.requires = None
 
434
        self.obsoletes = None
 
435
        # supports 'executables' keyword
 
436
        self.executables = None
 
437
        cls_Distribution.__init__(self, attrs)
 
438
 
 
439
    def has_executables(self):
 
440
        return self.executables and len(self.executables) > 0
 
441
 
 
442
    def is_pure (self):
 
443
        return (cls_Distribution.is_pure(self) and
 
444
                not self.has_executables())
 
445
 
 
446
# Extension class
 
447
 
 
448
class Extension(cls_Extension):
 
449
    def __init__ (self, **kw):
 
450
        optional = kw.pop('optional', None)
 
451
        configure = kw.pop('configure', None)
 
452
        cls_Extension.__init__(self, **kw)
 
453
        self.optional = optional
 
454
        self.configure = configure
 
455
 
 
456
# Library class
 
457
 
 
458
class Library(Extension):
 
459
    def __init__ (self, **kw):
 
460
        kind = kw.pop('kind', "static")
 
461
        package = kw.pop('package', None)
 
462
        dest_dir = kw.pop('dest_dir', None)
 
463
        Extension.__init__(self, **kw)
 
464
        self.kind = kind
 
465
        self.package = package
 
466
        self.dest_dir = dest_dir
 
467
 
 
468
# Executable class
 
469
 
 
470
class Executable(Extension):
 
471
    def __init__ (self, **kw):
 
472
        package = kw.pop('package', None)
 
473
        dest_dir = kw.pop('dest_dir', None)
 
474
        Extension.__init__(self, **kw)
 
475
        self.package = package
 
476
        self.dest_dir = dest_dir
 
477
 
 
478
# setup function
 
479
 
 
480
def setup(**attrs):
 
481
    if 'distclass' not in attrs:
 
482
        attrs['distclass'] = Distribution
 
483
    if 'cmdclass' not in attrs:
 
484
        attrs['cmdclass'] = {}
 
485
    cmdclass = attrs['cmdclass']
 
486
    for cmd in (config, build, install,
 
487
                test, clean, sdist,
 
488
                build_src, build_py,
 
489
                build_clib, build_ext, build_exe,
 
490
                install_lib, install_data, install_exe,
 
491
                ):
 
492
        if cmd.__name__ not in cmdclass:
 
493
            cmdclass[cmd.__name__] = cmd
 
494
    return fcn_setup(**attrs)
 
495
 
 
496
# -----------------------------------------------------------------------------
 
497
 
 
498
# A minimalistic MPI program :-)
 
499
 
 
500
ConfigTest = """\
 
501
int main(int argc, char **argv)
 
502
{
 
503
  int ierr;
 
504
  ierr = MPI_Init(&argc, &argv);
 
505
  if (ierr) return -1;
 
506
  ierr = MPI_Finalize();
 
507
  if (ierr) return -1;
 
508
  return 0;
 
509
}
 
510
"""
 
511
 
 
512
class config(cmd_config.config):
 
513
 
 
514
    user_options = cmd_config.config.user_options + cmd_mpi_opts
 
515
 
 
516
    def initialize_options (self):
 
517
        cmd_config.config.initialize_options(self)
 
518
        cmd_initialize_mpi_options(self)
 
519
        self.noisy = 0
 
520
 
 
521
    def finalize_options (self):
 
522
        cmd_config.config.finalize_options(self)
 
523
        if not self.noisy:
 
524
            self.dump_source = 0
 
525
 
 
526
    def _clean(self, *a, **kw):
 
527
        if sys.platform.startswith('win'):
 
528
            for fn in ('_configtest.exe.manifest', ):
 
529
                if os.path.exists(fn):
 
530
                    self.temp_files.append(fn)
 
531
        cmd_config.config._clean(self, *a, **kw)
 
532
 
 
533
    def check_header (self, header, headers=None, include_dirs=None):
 
534
        if headers is None: headers = []
 
535
        log.info("checking for header '%s' ..." % header)
 
536
        body = "int main(int n, char**v) { return 0; }"
 
537
        ok = self.try_compile(body, list(headers) + [header], include_dirs)
 
538
        log.info(ok and 'success!' or 'failure.')
 
539
        return ok
 
540
 
 
541
    def check_macro (self, macro, headers=None, include_dirs=None):
 
542
        log.info("checking for macro '%s' ..." % macro)
 
543
        body = ("#ifndef %s\n"
 
544
                "#error macro '%s' not defined\n"
 
545
                "#endif\n") % (macro, macro)
 
546
        body += "int main(int n, char**v) { return 0; }\n"
 
547
        ok = self.try_compile(body, headers, include_dirs)
 
548
        return ok
 
549
 
 
550
    def check_library (self, library, library_dirs=None,
 
551
                   headers=None, include_dirs=None,
 
552
                   other_libraries=[], lang="c"):
 
553
        log.info("checking for library '%s' ..." % library)
 
554
        body = "int main(int n, char**v) { return 0; }"
 
555
        ok = self.try_link(body,  headers, include_dirs,
 
556
                           [library]+other_libraries, library_dirs,
 
557
                           lang=lang)
 
558
        return ok
 
559
 
 
560
    def check_function (self, function,
 
561
                        headers=None, include_dirs=None,
 
562
                        libraries=None, library_dirs=None,
 
563
                        decl=0, call=0, lang="c"):
 
564
        log.info("checking for function '%s' ..." % function)
 
565
        body = []
 
566
        if decl:
 
567
            if call: proto = "int %s (void);"
 
568
            else:    proto = "int %s;"
 
569
            if lang == "c":
 
570
                proto = "\n".join([
 
571
                        "#ifdef __cplusplus",
 
572
                        "extern \"C\"",
 
573
                        "#endif", proto])
 
574
            body.append(proto % function)
 
575
        body.append(    "int main (int n, char**v) {")
 
576
        if call:
 
577
            body.append("  (void)%s();" % function)
 
578
        else:
 
579
            body.append("  %s;" % function)
 
580
        body.append(    "  return 0;")
 
581
        body.append(    "}")
 
582
        body = "\n".join(body) + "\n"
 
583
        ok = self.try_link(body, headers, include_dirs,
 
584
                           libraries, library_dirs, lang=lang)
 
585
        return ok
 
586
 
 
587
    def check_symbol (self, symbol, type="int",
 
588
                      headers=None, include_dirs=None,
 
589
                      libraries=None, library_dirs=None,
 
590
                      decl=0, lang="c"):
 
591
        log.info("checking for symbol '%s' ..." % symbol)
 
592
        body = []
 
593
        if decl:
 
594
            body.append("%s %s;" % (type, symbol))
 
595
        body.append("int main (int n, char**v) {")
 
596
        body.append("  %s v; v = %s;" % (type, symbol))
 
597
        body.append("  return 0;")
 
598
        body.append("}")
 
599
        body = "\n".join(body) + "\n"
 
600
        ok = self.try_link(body, headers, include_dirs,
 
601
                           libraries, library_dirs, lang=lang)
 
602
        return ok
 
603
 
 
604
    check_hdr  = check_header
 
605
    check_lib  = check_library
 
606
    check_func = check_function
 
607
    check_sym  = check_symbol
 
608
 
 
609
    def run (self):
 
610
        #
 
611
        config = configuration(self, verbose=True)
 
612
        # test MPI C compiler
 
613
        self.compiler = getattr(
 
614
            self.compiler, 'compiler_type', self.compiler)
 
615
        self._check_compiler()
 
616
        configure_compiler(self.compiler, config, lang='c')
 
617
        self.try_link(ConfigTest, headers=['mpi.h'], lang='c')
 
618
        # test MPI C++ compiler
 
619
        self.compiler = getattr(
 
620
            self.compiler, 'compiler_type', self.compiler)
 
621
        self._check_compiler()
 
622
        configure_compiler(self.compiler, config, lang='c++')
 
623
        self.try_link(ConfigTest, headers=['mpi.h'], lang='c++')
 
624
 
 
625
 
 
626
class build(cmd_build.build):
 
627
 
 
628
    user_options = cmd_build.build.user_options + cmd_mpi_opts
 
629
 
 
630
    def initialize_options(self):
 
631
        cmd_build.build.initialize_options(self)
 
632
        cmd_initialize_mpi_options(self)
 
633
 
 
634
    def finalize_options(self):
 
635
        cmd_build.build.finalize_options(self)
 
636
        config_cmd = self.get_finalized_command('config')
 
637
        if isinstance(config_cmd, config):
 
638
            cmd_set_undefined_mpi_options(self, 'config')
 
639
 
 
640
    def has_executables (self):
 
641
        return self.distribution.has_executables()
 
642
 
 
643
    sub_commands = \
 
644
        [('build_src', lambda *args: True)] + \
 
645
        cmd_build.build.sub_commands + \
 
646
        [('build_exe', has_executables),
 
647
         ]
 
648
 
 
649
 
 
650
class build_src(Command):
 
651
    description = "build C sources from Cython files"
 
652
    user_options = [
 
653
        ('force', 'f',
 
654
         "forcibly build everything (ignore file timestamps)"),
 
655
        ]
 
656
    boolean_options = ['force']
 
657
    def initialize_options(self):
 
658
        self.force = False
 
659
    def finalize_options(self):
 
660
        self.set_undefined_options('build',
 
661
                                   ('force', 'force'),
 
662
                                   )
 
663
    def run(self):
 
664
        pass
 
665
 
 
666
 
 
667
class build_py(cmd_build_py.build_py):
 
668
 
 
669
  if sys.version[:3] < '2.4':
 
670
 
 
671
    def initialize_options(self):
 
672
        self.package_data = None
 
673
        cmd_build_py.build_py.initialize_options(self)
 
674
 
 
675
    def finalize_options (self):
 
676
        cmd_build_py.build_py.finalize_options(self)
 
677
        self.package_data = self.distribution.package_data
 
678
        self.data_files = self.get_data_files()
 
679
 
 
680
    def run(self):
 
681
        cmd_build_py.build_py.run(self)
 
682
        if self.packages:
 
683
            self.build_package_data()
 
684
 
 
685
    def get_data_files (self):
 
686
        """Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
 
687
        data = []
 
688
        if not self.packages:
 
689
            return data
 
690
        for package in self.packages:
 
691
            # Locate package source directory
 
692
            src_dir = self.get_package_dir(package)
 
693
 
 
694
            # Compute package build directory
 
695
            build_dir = os.path.join(*([self.build_lib] + package.split('.')))
 
696
 
 
697
            # Length of path to strip from found files
 
698
            plen = len(src_dir)+1
 
699
 
 
700
            # Strip directory from globbed filenames
 
701
            filenames = [
 
702
                file[plen:] for file in self.find_data_files(package, src_dir)
 
703
                ]
 
704
            data.append((package, src_dir, build_dir, filenames))
 
705
        return data
 
706
 
 
707
    def find_data_files (self, package, src_dir):
 
708
        """Return filenames for package's data files in 'src_dir'"""
 
709
        from glob import glob
 
710
        globs = (self.package_data.get('', [])
 
711
                 + self.package_data.get(package, []))
 
712
        files = []
 
713
        for pattern in globs:
 
714
            # Each pattern has to be converted to a platform-specific path
 
715
            filelist = glob(os.path.join(src_dir, convert_path(pattern)))
 
716
            # Files that match more than one pattern are only added once
 
717
            files.extend([fn for fn in filelist if fn not in files])
 
718
        return files
 
719
 
 
720
    def get_package_dir (self, package):
 
721
        """Return the directory, relative to the top of the source
 
722
           distribution, where package 'package' should be found
 
723
           (at least according to the 'package_dir' option, if any)."""
 
724
        import string
 
725
        path = string.split(package, '.')
 
726
 
 
727
        if not self.package_dir:
 
728
            if path:
 
729
                return os.path.join(*path)
 
730
            else:
 
731
                return ''
 
732
        else:
 
733
            tail = []
 
734
            while path:
 
735
                try:
 
736
                    pdir = self.package_dir[string.join(path, '.')]
 
737
                except KeyError:
 
738
                    tail.insert(0, path[-1])
 
739
                    del path[-1]
 
740
                else:
 
741
                    tail.insert(0, pdir)
 
742
                    return os.path.join(*tail)
 
743
            else:
 
744
                pdir = self.package_dir.get('')
 
745
                if pdir is not None:
 
746
                    tail.insert(0, pdir)
 
747
 
 
748
                if tail:
 
749
                    return os.path.join(*tail)
 
750
                else:
 
751
                    return ''
 
752
 
 
753
    def build_package_data (self):
 
754
        """Copy data files into build directory"""
 
755
        lastdir = None
 
756
        for package, src_dir, build_dir, filenames in self.data_files:
 
757
            for filename in filenames:
 
758
                target = os.path.join(build_dir, filename)
 
759
                self.mkpath(os.path.dirname(target))
 
760
                self.copy_file(os.path.join(src_dir, filename), target,
 
761
                               preserve_mode=False)
 
762
 
 
763
 
 
764
# Command class to build libraries
 
765
 
 
766
class build_clib(cmd_build_clib.build_clib):
 
767
 
 
768
    user_options = [
 
769
        ('build-clib-a=', 's',
 
770
         "directory to build C/C++ static libraries to"),
 
771
        ('build-clib-so=', 's',
 
772
         "directory to build C/C++ shared libraries to"),
 
773
        ]
 
774
 
 
775
    user_options += cmd_build_clib.build_clib.user_options + cmd_mpi_opts
 
776
 
 
777
    def initialize_options (self):
 
778
        self.libraries = None
 
779
        self.libraries_a = []
 
780
        self.libraries_so = []
 
781
 
 
782
        self.library_dirs = None
 
783
        self.rpath = None
 
784
        self.link_objects = None
 
785
 
 
786
        self.build_lib = None
 
787
        self.build_clib_a = None
 
788
        self.build_clib_so = None
 
789
        cmd_build_clib.build_clib.initialize_options(self)
 
790
        cmd_initialize_mpi_options(self)
 
791
 
 
792
    def finalize_options (self):
 
793
        cmd_build_clib.build_clib.finalize_options(self)
 
794
        build_cmd = self.get_finalized_command('build')
 
795
        if isinstance(build_cmd,  build):
 
796
            cmd_set_undefined_mpi_options(self, 'build')
 
797
        #
 
798
        self.set_undefined_options('build',
 
799
                                   ('build_lib', 'build_lib'),
 
800
                                   ('build_lib', 'build_clib_a'),
 
801
                                   ('build_lib', 'build_clib_so'))
 
802
        #
 
803
        if self.libraries:
 
804
            libraries = self.libraries[:]
 
805
            self.libraries = []
 
806
            self.check_library_list (libraries)
 
807
            for i, lib in enumerate(libraries):
 
808
                if isinstance(lib, Library):
 
809
                    if lib.kind == "static":
 
810
                        self.libraries_a.append(lib)
 
811
                    else:
 
812
                        self.libraries_so.append(lib)
 
813
                else:
 
814
                    self.libraries.append(lib)
 
815
 
 
816
    def check_library_list (self, libraries):
 
817
        ListType, TupleType = type([]), type(())
 
818
        if not isinstance(libraries, ListType):
 
819
            raise DistutilsSetupError(
 
820
                "'libraries' option must be a list of "
 
821
                "Library instances or 2-tuples")
 
822
        for lib in libraries:
 
823
            #
 
824
            if isinstance(lib, Library):
 
825
                lib_name = lib.name
 
826
                build_info = lib.__dict__
 
827
            elif isinstance(lib, TupleType) and len(lib) == 2:
 
828
                lib_name, build_info = lib
 
829
            else:
 
830
                raise DistutilsSetupError(
 
831
                    "each element of 'libraries' option must be an "
 
832
                    "Library instance or 2-tuple")
 
833
            #
 
834
            if not isinstance(lib_name, str):
 
835
                raise DistutilsSetupError(
 
836
                    "first element of each tuple in 'libraries' "
 
837
                    "must be a string (the library name)")
 
838
            if '/' in lib_name or (os.sep != '/' and os.sep in lib_name):
 
839
                raise DistutilsSetupError(
 
840
                    "bad library name '%s': "
 
841
                    "may not contain directory separators" % lib[0])
 
842
            if not isinstance(build_info, dict):
 
843
                raise DistutilsSetupError(
 
844
                    "second element of each tuple in 'libraries' "
 
845
                    "must be a dictionary (build info)")
 
846
            lib_type = build_info.get('kind', 'static')
 
847
            if lib_type not in ('static', 'shared', 'dylib'):
 
848
                raise DistutilsSetupError(
 
849
                    "in 'kind' option (library '%s'), "
 
850
                    "'kind' must be one of "
 
851
                    " \"static\", \"shared\", \"dylib\"" % lib_name)
 
852
            sources = build_info.get('sources')
 
853
            if (sources is None or
 
854
                type(sources) not in (ListType, TupleType)):
 
855
                raise DistutilsSetupError(
 
856
                    "in 'libraries' option (library '%s'), "
 
857
                    "'sources' must be present and must be "
 
858
                    "a list of source filenames" % lib_name)
 
859
            depends = build_info.get('depends')
 
860
            if (depends is not None and
 
861
                type(depends) not in (ListType, TupleType)):
 
862
                raise DistutilsSetupError(
 
863
                    "in 'libraries' option (library '%s'), "
 
864
                    "'depends' must be a list "
 
865
                    "of source filenames" % lib_name)
 
866
 
 
867
    def run (self):
 
868
        cmd_build_clib.build_clib.run(self)
 
869
        if (not self.libraries_a and
 
870
            not self.libraries_so):
 
871
            return
 
872
        #
 
873
        from distutils.ccompiler import new_compiler
 
874
        self.compiler = new_compiler(compiler=self.compiler,
 
875
                                     dry_run=self.dry_run,
 
876
                                     force=self.force)
 
877
        #
 
878
        if self.define is not None:
 
879
            for (name, value) in self.define:
 
880
                self.compiler.define_macro(name, value)
 
881
        if self.undef is not None:
 
882
            for macro in self.undef:
 
883
                self.compiler.undefine_macro(macro)
 
884
        if self.include_dirs is not None:
 
885
            self.compiler.set_include_dirs(self.include_dirs)
 
886
        if self.library_dirs is not None:
 
887
            self.compiler.set_library_dirs(self.library_dirs)
 
888
        if self.rpath is not None:
 
889
            self.compiler.set_runtime_library_dirs(self.rpath)
 
890
        if self.link_objects is not None:
 
891
            self.compiler.set_link_objects(self.link_objects)
 
892
        #
 
893
        config = configuration(self, verbose=True)
 
894
        configure_compiler(self.compiler, config)
 
895
        #
 
896
        self.build_libraries(self.libraries)
 
897
        self.build_libraries(self.libraries_a)
 
898
        self.build_libraries(self.libraries_so)
 
899
 
 
900
    def build_libraries (self, libraries):
 
901
        for lib in libraries:
 
902
            # old-style
 
903
            if not isinstance(lib, Library):
 
904
                cmd_build_clib.build_clib.build_libraries(self, [lib])
 
905
                continue
 
906
            # new-style
 
907
            try:
 
908
                self.build_library(lib)
 
909
            except (DistutilsError, CCompilerError):
 
910
                if not lib.optional: raise
 
911
                e = sys.exc_info()[1]
 
912
                self.warn('building library "%s" failed' % lib.name)
 
913
                self.warn('%s' % e)
 
914
 
 
915
    def config_library (self, lib):
 
916
        if lib.configure:
 
917
            config_cmd = self.get_finalized_command('config')
 
918
            config_cmd.compiler = self.compiler # fix compiler
 
919
            return lib.configure(lib, config_cmd)
 
920
 
 
921
    def build_library(self, lib):
 
922
        from distutils.dep_util import newer_group
 
923
 
 
924
        sources = [convert_path(p) for p in lib.sources]
 
925
        depends = [convert_path(p) for p in lib.depends]
 
926
        depends = sources + depends
 
927
 
 
928
        if lib.kind == "static":
 
929
            build_dir = self.build_clib_a
 
930
        else:
 
931
            build_dir = self.build_clib_so
 
932
        lib_fullpath = self.get_lib_fullpath(lib, build_dir)
 
933
 
 
934
        if not (self.force or newer_group(depends, lib_fullpath, 'newer')):
 
935
            log.debug("skipping '%s' %s library (up-to-date)",
 
936
                      lib.name, lib.kind)
 
937
            return
 
938
 
 
939
        ok = self.config_library(lib)
 
940
        log.info("building '%s' %s library", lib.name, lib.kind)
 
941
 
 
942
        # First, compile the source code to object files in the library
 
943
        # directory.  (This should probably change to putting object
 
944
        # files in a temporary build directory.)
 
945
        macros = lib.define_macros[:]
 
946
        for undef in lib.undef_macros:
 
947
            macros.append((undef,))
 
948
 
 
949
        objects = self.compiler.compile(
 
950
            sources,
 
951
            depends=lib.depends,
 
952
            output_dir=self.build_temp,
 
953
            macros=macros,
 
954
            include_dirs=lib.include_dirs,
 
955
            extra_preargs=None,
 
956
            extra_postargs=lib.extra_compile_args,
 
957
            debug=self.debug,
 
958
            )
 
959
 
 
960
        if lib.kind == "static":
 
961
            # Now "link" the object files together
 
962
            # into a static library.
 
963
            self.compiler.create_static_lib(
 
964
                objects,
 
965
                lib.name,
 
966
                output_dir=os.path.dirname(lib_fullpath),
 
967
                debug=self.debug,
 
968
                )
 
969
        else:
 
970
            extra_objects = lib.extra_objects[:]
 
971
            export_symbols = lib.export_symbols[:]
 
972
            extra_link_args = lib.extra_link_args[:]
 
973
            objects.extend(extra_objects)
 
974
            if (self.compiler.compiler_type == 'msvc' and
 
975
                export_symbols is not None):
 
976
                output_dir = os.path.dirname(lib_fullpath)
 
977
                implib_filename = self.compiler.library_filename(lib.name)
 
978
                implib_file = os.path.join(output_dir, lib_fullpath)
 
979
                extra_link_args.append ('/IMPLIB:' + implib_file)
 
980
            # Detect target language, if not provided
 
981
            src_language = self.compiler.detect_language(sources)
 
982
            language = (lib.language or src_language)
 
983
            # Now "link" the object files together
 
984
            # into a shared library.
 
985
            self.compiler.link(
 
986
                self.compiler.SHARED_LIBRARY,
 
987
                objects, lib_fullpath,
 
988
                #
 
989
                libraries=lib.libraries,
 
990
                library_dirs=lib.library_dirs,
 
991
                runtime_library_dirs=lib.runtime_library_dirs,
 
992
                export_symbols=export_symbols,
 
993
                extra_preargs=None,
 
994
                extra_postargs=extra_link_args,
 
995
                debug=self.debug,
 
996
                target_lang=language,
 
997
                )
 
998
        return
 
999
 
 
1000
    def get_lib_fullpath (self, lib, build_dir):
 
1001
        package_dir = (lib.package or '').split('.')
 
1002
        dest_dir = convert_path(lib.dest_dir or '')
 
1003
        output_dir = os.path.join(build_dir, *package_dir+[dest_dir])
 
1004
        lib_type =  lib.kind
 
1005
        if sys.platform != 'darwin':
 
1006
            if lib_type == 'dylib':
 
1007
                lib_type = 'shared'
 
1008
        compiler = self.compiler # XXX
 
1009
        lib_fullpath = compiler.library_filename(
 
1010
            lib.name, lib_type=lib_type, output_dir=output_dir)
 
1011
        return lib_fullpath
 
1012
 
 
1013
    def get_source_files (self):
 
1014
        filenames = cmd_build_clib.build_clib.get_source_files(self)
 
1015
        self.check_library_list(self.libraries)
 
1016
        self.check_library_list(self.libraries_a)
 
1017
        self.check_library_list(self.libraries_so)
 
1018
        for (lib_name, build_info) in self.libraries:
 
1019
            filenames.extend(build_info.get(sources, []))
 
1020
        for lib in self.libraries_so + self.libraries_a:
 
1021
            filenames.extend(lib.sources)
 
1022
        return filenames
 
1023
 
 
1024
    def get_outputs (self):
 
1025
        outputs = []
 
1026
        for lib in self.libraries_a:
 
1027
            lib_fullpath = self.get_lib_fullpath(lib, self.build_clib_a)
 
1028
            outputs.append(lib_fullpath)
 
1029
        for lib in self.libraries_so:
 
1030
            lib_fullpath = self.get_lib_fullpath(lib, self.build_clib_so)
 
1031
            outputs.append(lib_fullpath)
 
1032
        return outputs
 
1033
 
 
1034
 
 
1035
# Command class to build extension modules
 
1036
 
 
1037
class build_ext(cmd_build_ext.build_ext):
 
1038
 
 
1039
    user_options = cmd_build_ext.build_ext.user_options + cmd_mpi_opts
 
1040
 
 
1041
    def initialize_options(self):
 
1042
        cmd_build_ext.build_ext.initialize_options(self)
 
1043
        cmd_initialize_mpi_options(self)
 
1044
 
 
1045
    def finalize_options(self):
 
1046
        cmd_build_ext.build_ext.finalize_options(self)
 
1047
        build_cmd = self.get_finalized_command('build')
 
1048
        if isinstance(build_cmd,  build):
 
1049
            cmd_set_undefined_mpi_options(self, 'build')
 
1050
        #
 
1051
        if ((sys.platform.startswith('linux') or
 
1052
             sys.platform.startswith('gnu') or
 
1053
             sys.platform.startswith('sunos')) and
 
1054
            sysconfig.get_config_var('Py_ENABLE_SHARED')):
 
1055
            py_version = sysconfig.get_python_version()
 
1056
            bad_pylib_dir = os.path.join(sys.prefix, "lib",
 
1057
                                         "python" + py_version,
 
1058
                                         "config")
 
1059
            try:
 
1060
                self.library_dirs.remove(bad_pylib_dir)
 
1061
            except ValueError:
 
1062
                pass
 
1063
            pylib_dir = sysconfig.get_config_var("LIBDIR")
 
1064
            if pylib_dir not in self.library_dirs:
 
1065
                self.library_dirs.append(pylib_dir)
 
1066
            if pylib_dir not in self.rpath:
 
1067
                self.rpath.append(pylib_dir)
 
1068
            if sys.exec_prefix == '/usr':
 
1069
                self.library_dirs.remove(pylib_dir)
 
1070
                self.rpath.remove(pylib_dir)
 
1071
 
 
1072
    def run (self):
 
1073
        if self.distribution.has_c_libraries():
 
1074
            build_clib = self.get_finalized_command('build_clib')
 
1075
            if build_clib.libraries:
 
1076
                build_clib.run()
 
1077
        cmd_build_ext.build_ext.run(self)
 
1078
 
 
1079
    def build_extensions(self):
 
1080
        # First, sanity-check the 'extensions' list
 
1081
        self.check_extensions_list(self.extensions)
 
1082
        # parse configuration file and configure compiler
 
1083
        config = configuration(self, verbose=True)
 
1084
        configure_compiler(self.compiler, config)
 
1085
        if self.compiler.compiler_type == "unix":
 
1086
            so_ext = sysconfig.get_config_var('SO')
 
1087
            self.compiler.shared_lib_extension = so_ext
 
1088
        self.config = config # XXX
 
1089
        # extra configuration, check for all MPI symbols
 
1090
        if self.configure:
 
1091
            log.info('testing for missing MPI symbols')
 
1092
            config_cmd = self.get_finalized_command('config')
 
1093
            config_cmd.compiler = self.compiler # fix compiler
 
1094
            configure = ConfigureMPI(config_cmd)
 
1095
            results = configure.run()
 
1096
            configure.dump(results)
 
1097
            #
 
1098
            macro = 'HAVE_CONFIG_H'
 
1099
            log.info("defining preprocessor macro '%s'" % macro)
 
1100
            self.compiler.define_macro(macro, 1)
 
1101
        # build extensions
 
1102
        for ext in self.extensions:
 
1103
            try:
 
1104
                self.build_extension(ext)
 
1105
            except (DistutilsError, CCompilerError):
 
1106
                if not ext.optional: raise
 
1107
                e = sys.exc_info()[1]
 
1108
                self.warn('building extension "%s" failed' % ext.name)
 
1109
                self.warn('%s' % e)
 
1110
 
 
1111
    def config_extension (self, ext):
 
1112
        configure = getattr(ext, 'configure', None)
 
1113
        if configure:
 
1114
            config_cmd = self.get_finalized_command('config')
 
1115
            config_cmd.compiler = self.compiler # fix compiler
 
1116
            configure(ext, config_cmd)
 
1117
 
 
1118
    def build_extension (self, ext):
 
1119
        from distutils.dep_util import newer_group
 
1120
        fullname = self.get_ext_fullname(ext.name)
 
1121
        filename = os.path.join(
 
1122
            self.build_lib, self.get_ext_filename(fullname))
 
1123
        depends = ext.sources + ext.depends
 
1124
        if not (self.force or newer_group(depends, filename, 'newer')):
 
1125
            log.debug("skipping '%s' extension (up-to-date)", ext.name)
 
1126
            return
 
1127
        #
 
1128
        self.config_extension(ext)
 
1129
        cmd_build_ext.build_ext.build_extension(self, ext)
 
1130
        #
 
1131
        # XXX -- this is a Vile HACK!
 
1132
        if ext.name == 'mpi4py.MPI':
 
1133
            dest_dir = os.path.dirname(filename)
 
1134
            self.mkpath(dest_dir)
 
1135
            mpi_cfg = os.path.join(dest_dir, 'mpi.cfg')
 
1136
            log.info("writing %s" % mpi_cfg)
 
1137
            if not self.dry_run:
 
1138
                self.config.dump(filename=mpi_cfg)
 
1139
 
 
1140
    def get_outputs(self):
 
1141
        outputs = cmd_build_ext.build_ext.get_outputs(self)
 
1142
        for ext in self.extensions:
 
1143
            # XXX -- this is a Vile HACK!
 
1144
            if ext.name == 'mpi4py.MPI':
 
1145
                fullname = self.get_ext_fullname(ext.name)
 
1146
                filename = os.path.join(
 
1147
                    self.build_lib,
 
1148
                    self.get_ext_filename(fullname))
 
1149
                dest_dir = os.path.dirname(filename)
 
1150
                mpi_cfg = os.path.join(dest_dir, 'mpi.cfg')
 
1151
                outputs.append(mpi_cfg)
 
1152
        return outputs
 
1153
 
 
1154
 
 
1155
# Command class to build executables
 
1156
 
 
1157
class build_exe(build_ext):
 
1158
 
 
1159
    description = "build binary executable components"
 
1160
 
 
1161
    user_options = [
 
1162
        ('build-exe=', None,
 
1163
         "build directory for executable components"),
 
1164
        ] + build_ext.user_options
 
1165
 
 
1166
 
 
1167
    def initialize_options (self):
 
1168
        build_ext.initialize_options(self)
 
1169
        self.build_base = None
 
1170
        self.build_exe  = None
 
1171
 
 
1172
    def finalize_options (self):
 
1173
        build_ext.finalize_options(self)
 
1174
        self.configure = None
 
1175
        self.set_undefined_options('build',
 
1176
                                   ('build_base','build_base'),
 
1177
                                   ('build_lib', 'build_exe'))
 
1178
        #from distutils.util import get_platform
 
1179
        #plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3])
 
1180
        #if hasattr(sys, 'gettotalrefcount') and sys.version[0:3] > '2.5':
 
1181
        #    plat_specifier += '-pydebug'
 
1182
        #if self.build_exe is None:
 
1183
        #    self.build_exe = os.path.join(self.build_base,
 
1184
        #                                  'exe' + plat_specifier)
 
1185
        self.executables = self.distribution.executables
 
1186
        # XXX This is a hack
 
1187
        self.extensions  = self.distribution.executables
 
1188
        self.check_extensions_list = self.check_executables_list
 
1189
        self.build_extension = self.build_executable
 
1190
        self.get_ext_filename = self.get_exe_filename
 
1191
        self.build_lib = self.build_exe
 
1192
 
 
1193
    def check_executables_list (self, executables):
 
1194
        ListType, TupleType = type([]), type(())
 
1195
        if type(executables) is not ListType:
 
1196
            raise DistutilsSetupError(
 
1197
                "'executables' option must be a list of Executable instances")
 
1198
        for exe in executables:
 
1199
            if not isinstance(exe, Executable):
 
1200
                raise DistutilsSetupError(
 
1201
                    "'executables' items must be Executable instances")
 
1202
            if (exe.sources is None or
 
1203
                type(exe.sources) not in (ListType, TupleType)):
 
1204
                raise DistutilsSetupError(
 
1205
                    ("in 'executables' option (executable '%s'), " +
 
1206
                     "'sources' must be present and must be " +
 
1207
                     "a list of source filenames") % exe.name)
 
1208
 
 
1209
    def get_exe_filename(self, exe_name):
 
1210
        exe_ext = sysconfig.get_config_var('EXE') or ''
 
1211
        return exe_name + exe_ext
 
1212
 
 
1213
    def get_exe_fullpath(self, exe, build_dir=None):
 
1214
        build_dir = build_dir or self.build_exe
 
1215
        package_dir = (exe.package or '').split('.')
 
1216
        dest_dir = convert_path(exe.dest_dir or '')
 
1217
        output_dir = os.path.join(build_dir, *package_dir+[dest_dir])
 
1218
        exe_filename = self.get_exe_filename(exe.name)
 
1219
        return os.path.join(output_dir, exe_filename)
 
1220
 
 
1221
    def config_executable (self, exe):
 
1222
        build_ext.config_extension(self, exe)
 
1223
 
 
1224
    def build_executable (self, exe):
 
1225
        from distutils.dep_util import newer_group
 
1226
        sources = list(exe.sources)
 
1227
        depends = list(exe.depends)
 
1228
        exe_fullpath = self.get_exe_fullpath(exe)
 
1229
        depends = sources + depends
 
1230
        if not (self.force or newer_group(depends, exe_fullpath, 'newer')):
 
1231
            log.debug("skipping '%s' executable (up-to-date)", exe.name)
 
1232
            return
 
1233
 
 
1234
        self.config_executable(exe)
 
1235
        log.info("building '%s' executable", exe.name)
 
1236
 
 
1237
        # Next, compile the source code to object files.
 
1238
 
 
1239
        # XXX not honouring 'define_macros' or 'undef_macros' -- the
 
1240
        # CCompiler API needs to change to accommodate this, and I
 
1241
        # want to do one thing at a time!
 
1242
 
 
1243
        macros = exe.define_macros[:]
 
1244
        for undef in exe.undef_macros:
 
1245
            macros.append((undef,))
 
1246
 
 
1247
        # Two possible sources for extra compiler arguments:
 
1248
        #   - 'extra_compile_args' in Extension object
 
1249
        #   - CFLAGS environment variable (not particularly
 
1250
        #     elegant, but people seem to expect it and I
 
1251
        #     guess it's useful)
 
1252
        # The environment variable should take precedence, and
 
1253
        # any sensible compiler will give precedence to later
 
1254
        # command line args.  Hence we combine them in order:
 
1255
        extra_args = exe.extra_compile_args[:]
 
1256
 
 
1257
        objects =  self.compiler.compile(
 
1258
            sources,
 
1259
            output_dir=self.build_temp,
 
1260
            macros=macros,
 
1261
            include_dirs=exe.include_dirs,
 
1262
            debug=self.debug,
 
1263
            extra_postargs=extra_args,
 
1264
            depends=exe.depends)
 
1265
        self._built_objects = objects[:]
 
1266
 
 
1267
        # XXX -- this is a Vile HACK!
 
1268
        #
 
1269
        # Remove msvcrXX.dll when building executables with MinGW
 
1270
        #
 
1271
        if self.compiler.compiler_type == 'mingw32':
 
1272
            try: del self.compiler.dll_libraries[:]
 
1273
            except: pass
 
1274
 
 
1275
        # Now link the object files together into a "shared object" --
 
1276
        # of course, first we have to figure out all the other things
 
1277
        # that go into the mix.
 
1278
        if exe.extra_objects:
 
1279
            objects.extend(exe.extra_objects)
 
1280
        extra_args = exe.extra_link_args[:]
 
1281
        # Get special linker flags for building a executable with
 
1282
        # bundled Python library, also fix location of needed
 
1283
        # python.exp file on AIX
 
1284
        ldshflag = sysconfig.get_config_var('LINKFORSHARED') or ''
 
1285
        ldshflag = ldshflag.replace('-Xlinker ', '-Wl,')
 
1286
        if sys.platform == 'darwin': # fix wrong framework paths
 
1287
            fwkprefix = sysconfig.get_config_var('PYTHONFRAMEWORKPREFIX')
 
1288
            fwkdir = sysconfig.get_config_var('PYTHONFRAMEWORKDIR')
 
1289
            if fwkprefix and fwkdir and fwkdir != 'no-framework':
 
1290
                for flag in split_quoted(ldshflag):
 
1291
                    if flag.startswith(fwkdir):
 
1292
                        fwkpath = os.path.join(fwkprefix, flag)
 
1293
                        ldshflag = ldshflag.replace(flag, fwkpath)
 
1294
        if sys.platform.startswith('aix'):
 
1295
            python_lib = sysconfig.get_python_lib(standard_lib=1)
 
1296
            python_exp = os.path.join(python_lib, 'config', 'python.exp')
 
1297
            ldshflag = ldshflag.replace('Modules/python.exp', python_exp)
 
1298
        # Detect target language, if not provided
 
1299
        language = exe.language or self.compiler.detect_language(sources)
 
1300
        self.compiler.link(
 
1301
            self.compiler.EXECUTABLE,
 
1302
            objects, exe_fullpath,
 
1303
            output_dir=None,
 
1304
            libraries=self.get_libraries(exe),
 
1305
            library_dirs=exe.library_dirs,
 
1306
            runtime_library_dirs=exe.runtime_library_dirs,
 
1307
            extra_preargs=split_quoted(ldshflag),
 
1308
            extra_postargs=extra_args,
 
1309
            debug=self.debug,
 
1310
            target_lang=language)
 
1311
 
 
1312
    def get_outputs (self):
 
1313
        outputs = []
 
1314
        for exe in self.executables:
 
1315
            outputs.append(self.get_exe_fullpath(exe))
 
1316
        return outputs
 
1317
 
 
1318
 
 
1319
class install(cmd_install.install):
 
1320
 
 
1321
    user_options = cmd_install.install.user_options + [
 
1322
        ('single-version-externally-managed', None,
 
1323
         "setuptools compatibility option"),
 
1324
    ]
 
1325
    boolean_options = cmd_install.install.boolean_options + [
 
1326
        'single-version-externally-managed',
 
1327
    ]
 
1328
 
 
1329
    def initialize_options(self):
 
1330
        cmd_install.install.initialize_options(self)
 
1331
        self.single_version_externally_managed = None
 
1332
        self.no_compile = None
 
1333
 
 
1334
    def has_lib (self):
 
1335
        return (cmd_install.install.has_lib(self) and
 
1336
                self.has_exe())
 
1337
 
 
1338
    def has_exe (self):
 
1339
        return self.distribution.has_executables()
 
1340
 
 
1341
    sub_commands = \
 
1342
        cmd_install.install.sub_commands[:] + \
 
1343
        [('install_exe', has_exe),
 
1344
         ]
 
1345
 
 
1346
    # XXX disable install_exe subcommand !!!
 
1347
    del sub_commands[-1]
 
1348
 
 
1349
 
 
1350
class install_lib(cmd_install_lib.install_lib):
 
1351
 
 
1352
    def get_outputs(self):
 
1353
        outputs = cmd_install_lib.install_lib.get_outputs(self)
 
1354
        for (build_cmd, build_dir) in (('build_clib', 'build_lib'),
 
1355
                                       ('build_exe',  'build_exe')):
 
1356
            outs = self._mutate_outputs(1, build_cmd, build_dir,
 
1357
                                        self.install_dir)
 
1358
            build_cmd = self.get_finalized_command(build_cmd)
 
1359
            build_files = build_cmd.get_outputs()
 
1360
            outputs.extend(outs)
 
1361
        return outputs
 
1362
 
 
1363
 
 
1364
class install_data (cmd_install_data.install_data):
 
1365
 
 
1366
    def finalize_options (self):
 
1367
        self.set_undefined_options('install',
 
1368
                                   ('install_lib', 'install_dir'),
 
1369
                                   ('root', 'root'),
 
1370
                                   ('force', 'force'),
 
1371
                                   )
 
1372
 
 
1373
 
 
1374
class install_exe(cmd_install_lib.install_lib):
 
1375
 
 
1376
    description = "install binary executable components"
 
1377
 
 
1378
    user_options = [
 
1379
        ('install-dir=', 'd', "directory to install to"),
 
1380
        ('build-dir=','b', "build directory (where to install from)"),
 
1381
        ('force', 'f', "force installation (overwrite existing files)"),
 
1382
        ('skip-build', None, "skip the build steps"),
 
1383
        ]
 
1384
 
 
1385
    boolean_options = ['force', 'skip-build']
 
1386
    negative_opt = { }
 
1387
 
 
1388
    def initialize_options (self):
 
1389
        self.install_dir = None
 
1390
        self.build_dir = None
 
1391
        self.force = 0
 
1392
        self.skip_build = None
 
1393
 
 
1394
    def finalize_options (self):
 
1395
        self.set_undefined_options('build_exe',
 
1396
                                   ('build_exe', 'build_dir'))
 
1397
        self.set_undefined_options('install',
 
1398
                                   ('force', 'force'),
 
1399
                                   ('skip_build', 'skip_build'),
 
1400
                                   ('install_scripts', 'install_dir'))
 
1401
 
 
1402
    def run (self):
 
1403
        self.build()
 
1404
        self.install()
 
1405
 
 
1406
    def build (self):
 
1407
        if not self.skip_build:
 
1408
            if self.distribution.has_executables():
 
1409
                self.run_command('build_exe')
 
1410
 
 
1411
    def install (self):
 
1412
        self.outfiles = []
 
1413
        if self.distribution.has_executables():
 
1414
            build_exe = self.get_finalized_command('build_exe')
 
1415
            for exe in build_exe.executables:
 
1416
                exe_fullpath = build_exe.get_exe_fullpath(exe)
 
1417
                exe_filename = os.path.basename(exe_fullpath)
 
1418
                if (os.name == "posix" and
 
1419
                    exe_filename.startswith("python-")):
 
1420
                    install_name = exe_filename.replace(
 
1421
                        "python-","python%s-" % sys.version[:3])
 
1422
                    link = None
 
1423
                else:
 
1424
                    install_name = exe_fullpath
 
1425
                    link = None
 
1426
                source = exe_fullpath
 
1427
                target = os.path.join(self.install_dir, install_name)
 
1428
                self.mkpath(self.install_dir)
 
1429
                out, done = self.copy_file(source, target, link=link)
 
1430
                self.outfiles.append(out)
 
1431
 
 
1432
    def get_outputs (self):
 
1433
        return self.outfiles
 
1434
 
 
1435
    def get_inputs (self):
 
1436
        inputs = []
 
1437
        if self.distribution.has_executables():
 
1438
            build_exe = self.get_finalized_command('build_exe')
 
1439
            inputs.extend(build_exe.get_outputs())
 
1440
        return inputs
 
1441
 
 
1442
 
 
1443
class test(Command):
 
1444
    description = "run the test suite"
 
1445
    user_options = [
 
1446
        ('args=', None, "options"),
 
1447
        ]
 
1448
 
 
1449
    def initialize_options(self):
 
1450
        self.args = None
 
1451
    def finalize_options(self):
 
1452
        if self.args:
 
1453
            self.args = split_quoted(self.args)
 
1454
        else:
 
1455
            self.args = []
 
1456
    def run(self):
 
1457
        pass
 
1458
 
 
1459
 
 
1460
class sdist(cmd_sdist.sdist):
 
1461
 
 
1462
    def run (self):
 
1463
        build_src = self.get_finalized_command('build_src')
 
1464
        build_src.run()
 
1465
        cmd_sdist.sdist.run(self)
 
1466
 
 
1467
 
 
1468
class clean(cmd_clean.clean):
 
1469
 
 
1470
    description = "clean up temporary files from 'build' command"
 
1471
    user_options = \
 
1472
        cmd_clean.clean.user_options[:2] + [
 
1473
        ('build-exe=', None,
 
1474
         "build directory for executable components "
 
1475
         "(default: 'build_exe.build-exe')"),
 
1476
        ] + cmd_clean.clean.user_options[2:]
 
1477
 
 
1478
    def initialize_options(self):
 
1479
        cmd_clean.clean.initialize_options(self)
 
1480
        self.build_exe  = None
 
1481
 
 
1482
    def finalize_options(self):
 
1483
        cmd_clean.clean.finalize_options(self)
 
1484
        self.set_undefined_options('build_exe',
 
1485
                                   ('build_exe', 'build_exe'))
 
1486
 
 
1487
    def run(self):
 
1488
        from distutils.dir_util import remove_tree
 
1489
 
 
1490
        # remove the build/temp.<plat> directory
 
1491
        # (unless it's already gone)
 
1492
        if os.path.exists(self.build_temp):
 
1493
            remove_tree(self.build_temp, dry_run=self.dry_run)
 
1494
        else:
 
1495
            log.debug("'%s' does not exist -- can't clean it",
 
1496
                      self.build_temp)
 
1497
 
 
1498
        if self.all:
 
1499
            # remove build directories
 
1500
            for directory in (self.build_lib,
 
1501
                              self.build_exe,
 
1502
                              self.build_scripts,
 
1503
                              self.bdist_base,
 
1504
                              ):
 
1505
                if os.path.exists(directory):
 
1506
                    remove_tree(directory, dry_run=self.dry_run)
 
1507
                else:
 
1508
                    log.debug("'%s' does not exist -- can't clean it",
 
1509
                              directory)
 
1510
 
 
1511
        # just for the heck of it, try to remove the base build directory:
 
1512
        # we might have emptied it right now, but if not we don't care
 
1513
        if not self.dry_run:
 
1514
            try:
 
1515
                os.rmdir(self.build_base)
 
1516
                log.info("removing '%s'", self.build_base)
 
1517
            except OSError:
 
1518
                pass
 
1519
 
 
1520
# -----------------------------------------------------------------------------
 
1521
 
 
1522
try:
 
1523
    import msilib
 
1524
    Directory_make_short = msilib.Directory.make_short
 
1525
    def make_short(self, file):
 
1526
        parts = file.split('.')
 
1527
        if len(parts) > 1:
 
1528
            file = '_'.join(parts[:-1])+'.'+parts[-1]
 
1529
        return Directory_make_short(self, file)
 
1530
    msilib.Directory.make_short = make_short
 
1531
except:
 
1532
    pass
 
1533
 
 
1534
# -----------------------------------------------------------------------------