1#!/usr/bin/env python 2# encoding: utf-8 3# andersg at 0x63.nu 2007 4# Thomas Nagy 2016-2018 (ita) 5 6""" 7Support for Perl extensions. A C/C++ compiler is required:: 8 9 def options(opt): 10 opt.load('compiler_c perl') 11 def configure(conf): 12 conf.load('compiler_c perl') 13 conf.check_perl_version((5,6,0)) 14 conf.check_perl_ext_devel() 15 conf.check_perl_module('Cairo') 16 conf.check_perl_module('Devel::PPPort 4.89') 17 def build(bld): 18 bld( 19 features = 'c cshlib perlext', 20 source = 'Mytest.xs', 21 target = 'Mytest', 22 install_path = '${ARCHDIR_PERL}/auto') 23 bld.install_files('${ARCHDIR_PERL}', 'Mytest.pm') 24""" 25 26import os 27from waflib import Task, Options, Utils, Errors 28from waflib.Configure import conf 29from waflib.TaskGen import extension, feature, before_method 30 31@before_method('apply_incpaths', 'apply_link', 'propagate_uselib_vars') 32@feature('perlext') 33def init_perlext(self): 34 """ 35 Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the 36 *lib* prefix from library names. 37 """ 38 self.uselib = self.to_list(getattr(self, 'uselib', [])) 39 if not 'PERLEXT' in self.uselib: 40 self.uselib.append('PERLEXT') 41 self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.perlext_PATTERN 42 43@extension('.xs') 44def xsubpp_file(self, node): 45 """ 46 Create :py:class:`waflib.Tools.perl.xsubpp` tasks to process *.xs* files 47 """ 48 outnode = node.change_ext('.c') 49 self.create_task('xsubpp', node, outnode) 50 self.source.append(outnode) 51 52class xsubpp(Task.Task): 53 """ 54 Process *.xs* files 55 """ 56 run_str = '${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' 57 color = 'BLUE' 58 ext_out = ['.h'] 59 60@conf 61def check_perl_version(self, minver=None): 62 """ 63 Check if Perl is installed, and set the variable PERL. 64 minver is supposed to be a tuple 65 """ 66 res = True 67 if minver: 68 cver = '.'.join(map(str,minver)) 69 else: 70 cver = '' 71 72 self.start_msg('Checking for minimum perl version %s' % cver) 73 74 perl = self.find_program('perl', var='PERL', value=getattr(Options.options, 'perlbinary', None)) 75 version = self.cmd_and_log(perl + ["-e", 'printf \"%vd\", $^V']) 76 if not version: 77 res = False 78 version = "Unknown" 79 elif not minver is None: 80 ver = tuple(map(int, version.split("."))) 81 if ver < minver: 82 res = False 83 84 self.end_msg(version, color=res and 'GREEN' or 'YELLOW') 85 return res 86 87@conf 88def check_perl_module(self, module): 89 """ 90 Check if specified perlmodule is installed. 91 92 The minimum version can be specified by specifying it after modulename 93 like this:: 94 95 def configure(conf): 96 conf.check_perl_module("Some::Module 2.92") 97 """ 98 cmd = self.env.PERL + ['-e', 'use %s' % module] 99 self.start_msg('perl module %s' % module) 100 try: 101 r = self.cmd_and_log(cmd) 102 except Errors.WafError: 103 self.end_msg(False) 104 return None 105 self.end_msg(r or True) 106 return r 107 108@conf 109def check_perl_ext_devel(self): 110 """ 111 Check for configuration needed to build perl extensions. 112 113 Sets different xxx_PERLEXT variables in the environment. 114 115 Also sets the ARCHDIR_PERL variable useful as installation path, 116 which can be overridden by ``--with-perl-archdir`` option. 117 """ 118 119 env = self.env 120 perl = env.PERL 121 if not perl: 122 self.fatal('find perl first') 123 124 def cmd_perl_config(s): 125 return perl + ['-MConfig', '-e', 'print \"%s\"' % s] 126 def cfg_str(cfg): 127 return self.cmd_and_log(cmd_perl_config(cfg)) 128 def cfg_lst(cfg): 129 return Utils.to_list(cfg_str(cfg)) 130 def find_xsubpp(): 131 for var in ('privlib', 'vendorlib'): 132 xsubpp = cfg_lst('$Config{%s}/ExtUtils/xsubpp$Config{exe_ext}' % var) 133 if xsubpp and os.path.isfile(xsubpp[0]): 134 return xsubpp 135 return self.find_program('xsubpp') 136 137 env.LINKFLAGS_PERLEXT = cfg_lst('$Config{lddlflags}') 138 env.INCLUDES_PERLEXT = cfg_lst('$Config{archlib}/CORE') 139 env.CFLAGS_PERLEXT = cfg_lst('$Config{ccflags} $Config{cccdlflags}') 140 env.EXTUTILS_TYPEMAP = cfg_lst('$Config{privlib}/ExtUtils/typemap') 141 env.XSUBPP = find_xsubpp() 142 143 if not getattr(Options.options, 'perlarchdir', None): 144 env.ARCHDIR_PERL = cfg_str('$Config{sitearch}') 145 else: 146 env.ARCHDIR_PERL = getattr(Options.options, 'perlarchdir') 147 148 env.perlext_PATTERN = '%s.' + cfg_str('$Config{dlext}') 149 150def options(opt): 151 """ 152 Add the ``--with-perl-archdir`` and ``--with-perl-binary`` command-line options. 153 """ 154 opt.add_option('--with-perl-binary', type='string', dest='perlbinary', help = 'Specify alternate perl binary', default=None) 155 opt.add_option('--with-perl-archdir', type='string', dest='perlarchdir', help = 'Specify directory where to install arch specific files', default=None) 156 157