bindings/python/wscript
changeset 9278 0a749c0f1afd
parent 8896 da8f6d02dbe3
child 9295 268f02304bf7
equal deleted inserted replaced
9277:0f87d1cb030c 9278:0a749c0f1afd
     4 import os
     4 import os
     5 import subprocess
     5 import subprocess
     6 import shutil
     6 import shutil
     7 import sys
     7 import sys
     8 
     8 
     9 import Task
     9 from waflib import Task, Options, Configure, TaskGen, Logs, Build, Utils, Errors
    10 import Options
       
    11 import Configure
       
    12 import TaskGen
       
    13 import Logs
       
    14 import Build
       
    15 import Utils
       
    16 
       
    17 from waflib.Errors import WafError
    10 from waflib.Errors import WafError
       
    11 
       
    12 feature  = TaskGen.feature
       
    13 after = TaskGen.after
    18 
    14 
    19 ## https://launchpad.net/pybindgen/
    15 ## https://launchpad.net/pybindgen/
    20 REQUIRED_PYBINDGEN_VERSION = (0, 15, 0, 809)
    16 REQUIRED_PYBINDGEN_VERSION = (0, 15, 0, 809)
    21 REQUIRED_PYGCCXML_VERSION = (0, 9, 5)
    17 REQUIRED_PYGCCXML_VERSION = (0, 9, 5)
    22 
    18 
    23 
    19 
    24 from TaskGen import feature, after
       
    25 import Task
       
    26 
       
    27 
       
    28 
    20 
    29 def add_to_python_path(path):
    21 def add_to_python_path(path):
    30     if os.environ.get('PYTHONPATH', ''):
    22     if os.environ.get('PYTHONPATH', ''):
    31         os.environ['PYTHONPATH'] = path + os.pathsep + os.environ.get('PYTHONPATH')
    23         os.environ['PYTHONPATH'] = path + os.pathsep + os.environ.get('PYTHONPATH')
    32     else:
    24     else:
    36     if env['WITH_PYBINDGEN']:
    28     if env['WITH_PYBINDGEN']:
    37         add_to_python_path(env['WITH_PYBINDGEN'])
    29         add_to_python_path(env['WITH_PYBINDGEN'])
    38 
    30 
    39 
    31 
    40 def options(opt):
    32 def options(opt):
    41     opt.tool_options('python')
    33     opt.load('python')
    42     opt.add_option('--disable-python',
    34     opt.add_option('--disable-python',
    43                    help=("Don't build Python bindings."),
    35                    help=("Don't build Python bindings."),
    44                    action="store_true", default=False,
    36                    action="store_true", default=False,
    45                    dest='python_disable')
    37                    dest='python_disable')
    46     opt.add_option('--apiscan',
    38     opt.add_option('--apiscan',
    74     enabled_modules.sort()
    66     enabled_modules.sort()
    75     available_modules = list(conf.env['NS3_MODULES'])
    67     available_modules = list(conf.env['NS3_MODULES'])
    76     available_modules.sort()
    68     available_modules.sort()
    77     all_modules_enabled = (enabled_modules == available_modules)
    69     all_modules_enabled = (enabled_modules == available_modules)
    78 
    70 
    79     conf.check_tool('misc', tooldir=['waf-tools'])
    71     conf.load('misc', tooldir=['waf-tools'])
    80 
    72 
    81     if sys.platform == 'cygwin':
    73     if sys.platform == 'cygwin':
    82         conf.report_optional_feature("python", "Python Bindings", False,
    74         conf.report_optional_feature("python", "Python Bindings", False,
    83                                      "unsupported platform 'cygwin'")
    75                                      "unsupported platform 'cygwin'")
    84         Logs.warn("Python is not supported in CygWin environment.  Try MingW instead.")
    76         Logs.warn("Python is not supported in CygWin environment.  Try MingW instead.")
    89 
    81 
    90     if Options.options.with_python is not None:
    82     if Options.options.with_python is not None:
    91         conf.env.PYTHON = Options.options.with_python
    83         conf.env.PYTHON = Options.options.with_python
    92 
    84 
    93     try:
    85     try:
    94         conf.check_tool('python')
    86         conf.load('python')
    95     except Configure.ConfigurationError, ex:
    87     except Errors.ConfigurationError, ex:
    96         conf.report_optional_feature("python", "Python Bindings", False,
    88         conf.report_optional_feature("python", "Python Bindings", False,
    97                                      "The python interpreter was not found")
    89                                      "The python interpreter was not found")
    98         return
    90         return
    99     try:
    91     try:
   100         conf.check_python_version((2,3))
    92         conf.check_python_version((2,3))
   101     except Configure.ConfigurationError, ex:
    93     except Errors.ConfigurationError, ex:
   102         conf.report_optional_feature("python", "Python Bindings", False,
    94         conf.report_optional_feature("python", "Python Bindings", False,
   103                                      "The python found version is too low (2.3 required)")
    95                                      "The python found version is too low (2.3 required)")
   104         return
    96         return
   105     try:
    97     try:
   106         conf.check_python_headers()
    98         conf.check_python_headers()
   107     except Configure.ConfigurationError, ex:
    99     except Errors.ConfigurationError, ex:
   108         conf.report_optional_feature("python", "Python Bindings", False,
   100         conf.report_optional_feature("python", "Python Bindings", False,
   109                                      "Python library or headers missing")
   101                                      "Python library or headers missing")
   110         return
   102         return
   111 
   103 
   112     # stupid Mac OSX Python wants to build extensions as "universal
   104     # stupid Mac OSX Python wants to build extensions as "universal
   159 
   151 
   160     set_pybindgen_pythonpath(conf.env)
   152     set_pybindgen_pythonpath(conf.env)
   161 
   153 
   162     try:
   154     try:
   163         conf.check_python_module('pybindgen')
   155         conf.check_python_module('pybindgen')
   164     except Configure.ConfigurationError:
   156     except Errors.ConfigurationError:
   165         Logs.warn("pybindgen missing => no python bindings")
   157         Logs.warn("pybindgen missing => no python bindings")
   166         conf.report_optional_feature("python", "Python Bindings", False,
   158         conf.report_optional_feature("python", "Python Bindings", False,
   167                                      "PyBindGen missing")
   159                                      "PyBindGen missing")
   168         return
   160         return
   169     else:
   161     else:
   195 }
   187 }
   196 ''' % dict(type1=t1, type2=t2)
   188 ''' % dict(type1=t1, type2=t2)
   197 
   189 
   198         try:
   190         try:
   199             ret = conf.run_c_code(code=test_program,
   191             ret = conf.run_c_code(code=test_program,
   200                                   env=conf.env.copy(), compile_filename='test.cc',
   192                                   env=conf.env.derive(), compile_filename='test.cc',
   201                                   features='cxx cprogram', execute=False)
   193                                   features='cxx cprogram', execute=False)
   202         except Configure.ConfigurationError:
   194         except Errors.ConfigurationError:
   203             ret = 1
   195             ret = 1
   204         conf.msg('Checking for types %s and %s equivalence' % (t1, t2), (ret and 'no' or 'yes'))
   196         conf.msg('Checking for types %s and %s equivalence' % (t1, t2), (ret and 'no' or 'yes'))
   205         return not ret
   197         return not ret
   206 
   198 
   207     uint64_is_long = test("uint64_t", "unsigned long")
   199     uint64_is_long = test("uint64_t", "unsigned long")
   248 
   240 
   249 
   241 
   250     ## Check for pygccxml
   242     ## Check for pygccxml
   251     try:
   243     try:
   252         conf.check_python_module('pygccxml')
   244         conf.check_python_module('pygccxml')
   253     except Configure.ConfigurationError:
   245     except Errors.ConfigurationError:
   254         conf.report_optional_feature("pygccxml", "Python API Scanning Support", False,
   246         conf.report_optional_feature("pygccxml", "Python API Scanning Support", False,
   255                                      "Missing 'pygccxml' Python module")
   247                                      "Missing 'pygccxml' Python module")
   256         return
   248         return
   257 
   249 
   258     out = subprocess.Popen([conf.env['PYTHON'][0], "-c",
   250     out = subprocess.Popen([conf.env['PYTHON'][0], "-c",
   320 
   312 
   321 class apiscan_task(Task.TaskBase):
   313 class apiscan_task(Task.TaskBase):
   322     """Uses gccxml to scan the file 'everything.h' and extract API definitions.
   314     """Uses gccxml to scan the file 'everything.h' and extract API definitions.
   323     """
   315     """
   324     after = 'gen_ns3_module_header ns3header'
   316     after = 'gen_ns3_module_header ns3header'
   325     before = 'cc cxx command'
   317     before = 'cxx command'
   326     color = "BLUE"
   318     color = "BLUE"
   327     def __init__(self, curdirnode, env, bld, target, cflags, module):
   319     def __init__(self, curdirnode, env, bld, target, cflags, module):
   328         self.bld = bld
   320         self.bld = bld
   329         super(apiscan_task, self).__init__(generator=self)
   321         super(apiscan_task, self).__init__(generator=self)
   330         self.curdirnode = curdirnode
   322         self.curdirnode = curdirnode
   391 
   383 
   392 class python_scan_task_collector(Task.TaskBase):
   384 class python_scan_task_collector(Task.TaskBase):
   393     """Tasks that waits for the python-scan-* tasks to complete and then signals WAF to exit
   385     """Tasks that waits for the python-scan-* tasks to complete and then signals WAF to exit
   394     """
   386     """
   395     after = 'apiscan'
   387     after = 'apiscan'
   396     before = 'cc cxx'
   388     before = 'cxx'
   397     color = "BLUE"
   389     color = "BLUE"
   398     def __init__(self, curdirnode, env, bld):
   390     def __init__(self, curdirnode, env, bld):
   399         self.bld = bld
   391         self.bld = bld
   400         super(python_scan_task_collector, self).__init__(generator=self)
   392         super(python_scan_task_collector, self).__init__(generator=self)
   401         self.curdirnode = curdirnode
   393         self.curdirnode = curdirnode
   413 
   405 
   414 
   406 
   415 
   407 
   416 class gen_ns3_compat_pymod_task(Task.Task):
   408 class gen_ns3_compat_pymod_task(Task.Task):
   417     """Generates a 'ns3.py' compatibility module."""
   409     """Generates a 'ns3.py' compatibility module."""
   418     before = 'cc cxx'
   410     before = 'cxx'
   419     color = 'BLUE'
   411     color = 'BLUE'
   420     
   412     
   421     def run(self):
   413     def run(self):
   422         assert len(self.outputs) == 1
   414         assert len(self.outputs) == 1
   423         outfile = file(self.outputs[0].abspath(), "w")
   415         outfile = file(self.outputs[0].abspath(), "w")
   435 def build(bld):
   427 def build(bld):
   436     if Options.options.python_disable:
   428     if Options.options.python_disable:
   437         return
   429         return
   438 
   430 
   439     env = bld.env
   431     env = bld.env
   440     curdir = bld.path.abspath()
       
   441 
       
   442     set_pybindgen_pythonpath(env)
   432     set_pybindgen_pythonpath(env)
   443 
   433 
   444     if Options.options.apiscan:
   434     if Options.options.apiscan:
   445         if not env['ENABLE_PYTHON_SCANNING']:
   435         if not env['ENABLE_PYTHON_SCANNING']:
   446             raise WafError("Cannot re-scan python bindings: (py)gccxml not available")
   436             raise WafError("Cannot re-scan python bindings: (py)gccxml not available")
   487         task.dep_vars = ['PYTHON_MODULES_BUILT']
   477         task.dep_vars = ['PYTHON_MODULES_BUILT']
   488         task.bld = bld
   478         task.bld = bld
   489         grp = bld.get_group(bld.current_group)
   479         grp = bld.get_group(bld.current_group)
   490         grp.append(task)
   480         grp.append(task)
   491 
   481 
   492         bld.new_task_gen(features='copy',
   482         bld(features='copy', source="ns__init__.py", target='ns/__init__.py')
   493                          source="ns__init__.py",
       
   494                          target='ns/__init__.py')
       
   495         bld.install_as('${PYTHONARCHDIR}/ns/__init__.py', 'ns__init__.py')
   483         bld.install_as('${PYTHONARCHDIR}/ns/__init__.py', 'ns__init__.py')
   496 
   484 
   497 
   485 
   498     # note: the actual build commands for the python bindings are in
   486     # note: the actual build commands for the python bindings are in
   499     # src/wscript, not here.
   487     # src/wscript, not here.