The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

bavala.py in scripts

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of scripts/bavala.py.
Update readme
1 """ 2 Copyright (C) 2012, 2013, 2014 Eduardo Naufel Schettino and Johan Mattsson 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 """ 17 18 """bavala is a build-tool for Vala that uses doit (http://pydoit.org)""" 19 20 import glob 21 import os 22 import sys 23 from os.path import join 24 from doit.action import CmdAction 25 import config 26 import fnmatch 27 import subprocess 28 29 def cmd(name, *args): 30 """create string for command line""" 31 parts = [name] 32 for item in args: 33 if isinstance(item, basestring): 34 parts.append(item) 35 elif isinstance(item, dict): 36 for param, value in item.iteritems(): 37 if isinstance(value, basestring): 38 value = [value] 39 parts.extend('--{0} {1}'.format(param, v) for v in value) 40 else: 41 parts.extend(item) 42 return ' '.join(parts) 43 44 45 def get_sources_path (folder, pattern): 46 """obtain the path to all source files that matches pattern""" 47 files = [] 48 for root, dirnames, filenames in os.walk(folder): 49 for filename in fnmatch.filter(filenames, pattern): 50 files.append(os.path.join(root, filename)) 51 return files 52 53 54 55 def get_sources_name (folder, pattern): 56 """obtain name of all source files that matches pattern""" 57 files = [] 58 for root, dirnames, filenames in os.walk(folder): 59 for filename in fnmatch.filter(filenames, pattern): 60 files.append(filename) 61 return files 62 63 64 65 class Vala(object): 66 """helper to generate tasks to compile vala code""" 67 68 def __init__(self, src, build, pkg_libs, library=None, vala_deps=None, so_version=None): 69 self.src = src 70 self.build = build 71 self.pkg_libs = pkg_libs 72 self.vala_deps = vala_deps or [] 73 self.library = library 74 75 self.vala = get_sources_path (src, '*.vala') 76 self.c = get_sources_path (src, '*.c') # copy regular c sources 77 self.cc = [join(build + '/' + src, f) for f in get_sources_name (src, '*.c') ] 78 self.cc += [join(build + '/' + src, f.replace('.vala', '.c')) for f in get_sources_name (src, '*.vala')] 79 self.obj = [self.build + '/' + self.src + '/' + f.replace('.c', '.o') for f in get_sources_name (src, '*.c')] 80 self.obj += [self.build + '/' + self.src + '/' + f.replace('.vala', '.o') for f in get_sources_name (src, '*.vala')] 81 82 if library: 83 self.header = join(build, library) + '.h' 84 self.vapi = join(build, library) + '.vapi' 85 self.so = join(build, src) + '.so.' + so_version 86 self.so_link = join(build, src) + '.so' 87 self.so_link_name = src + '.so' 88 self.so_version = so_version 89 self.so_name = 'lib' + library + '.so.' + so_version 90 91 92 def gen_c(self, opts): 93 """translate code from vala to C and create .vapi""" 94 options = ['--ccode'] 95 options.extend(opts) 96 params = { 97 'basedir': join(self.build, self.src), 98 'vapidir': './', 99 'pkg': self.pkg_libs, 100 } 101 if self.library: 102 params['library'] = self.library 103 params['vapi'] = self.vapi 104 params['header'] = self.header 105 106 dep_vapi = [d.vapi for d in self.vala_deps] 107 action = cmd('valac', options, params, dep_vapi, self.vala) 108 targets = self.cc[:] 109 if self.library: 110 targets += [self.header, self.vapi] 111 112 for f in self.c: 113 yield { 114 'name': 'copy_c', 115 'actions': [ 116 'mkdir -p '+ self.build + '/' + self.src + '/', 117 'cp ' + f + ' ' + self.build + '/' + self.src + '/' 118 ], 119 } 120 121 print (action) 122 yield { 123 'name': 'compile_c', 124 'actions': [ action ], 125 'file_dep': self.vala + dep_vapi, 126 'targets': targets, 127 } 128 129 130 def gen_o(self, opts): 131 """compile C files to obj `.o` """ 132 def compile_cmd(conf, opts, libs, pos): 133 flags = [] 134 for l in libs: 135 if not l == "posix" and not l == "posixtypes": 136 process = subprocess.Popen ('pkg-config --cflags ' + l, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 137 cflags = process.stdout.readline() 138 process.communicate()[0] 139 if not process.returncode == 0: 140 print ( "Library not found: " + l) 141 exit (1) 142 flags += [cflags.strip ()] 143 144 return cmd(config.CC, opts, flags, pos) 145 146 for cc, obj in zip(self.cc, self.obj): 147 pos = ["-c " + cc, "-o " + obj ] 148 cmd_args = {'libs':self.pkg_libs, 'opts':opts, 'pos':pos} 149 action = CmdAction((compile_cmd, [], cmd_args)) 150 yield { 151 'name': obj.rsplit('/')[-1], 152 'file_dep': [ cc ], 153 'actions': [ action ], 154 'getargs': { 'conf': ('pkg_flags', 'out') }, 155 'targets': [ obj ], 156 } 157 158 159 def gen_so(self, generated_libs = None): 160 """generate ".so" lib file""" 161 def compile_cmd(conf, libs): 162 obj_glob = join(self.build, self.src, '*.o') 163 opts = ['-shared ' 164 + '-Wl,-soname,' + self.so_name 165 + ' ' + obj_glob 166 + ' -o ' + self.so ] 167 168 flags = [] 169 for l in libs: 170 if not l == "posix" and not l == "posixtypes": 171 process = subprocess.Popen ('pkg-config --cflags ' + l, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 172 cflags = process.stdout.readline() 173 process.communicate()[0] 174 if not process.returncode == 0: 175 print ( "Library not found: " + l) 176 exit (1) 177 flags += [cflags.strip ()] 178 179 if generated_libs: 180 flags += [generated_libs] 181 182 return cmd(config.CC, opts, flags) 183 184 return { 185 'name': self.so.rsplit('/')[-1], 186 'actions': [ CmdAction((compile_cmd, [], {'libs':self.pkg_libs})) ], 187 'getargs': { 'conf': ('pkg_flags', 'out') }, 188 'file_dep': self.obj, 189 'targets': [ self.so ], 190 } 191 192 def gen_ln(self): 193 """generate a symbolic link to the generated ".so" file""" 194 so_file = self.so.rsplit('/')[-1] 195 create_link = "ln -s -T " + so_file + " " + self.so_link_name + " " 196 create_link += "&& mv " + self.so_link_name + " " + self.build + "/" 197 return { 198 'name': self.so_link_name, 199 'actions': [ create_link], 200 'file_dep': [ self.so ], 201 'targets': [ self.so_link ], 202 } 203 204 def gen_bin(self, opts): 205 """generate binary""" 206 def compile_cmd(conf, opts, libs): 207 flags = [conf[l].strip() for l in libs] 208 return cmd(config.CC, opts, flags) 209 210 bin_path = join(self.build, 'bin') 211 target = join(bin_path, self.src) 212 opts = (self.cc + opts + 213 ['-o ' + target, '-I ' + self.build, '-L ' + self.build] + 214 ['-l ' + d.library for d in self.vala_deps]) 215 action = CmdAction((compile_cmd, [], {'opts':opts, 'libs':self.pkg_libs})) 216 yield { 217 'name': "bin", 218 'actions': [ 'mkdir -p %s' % bin_path, action ], 219 'getargs': { 'conf': ('pkg_flags', 'out') }, 220 'file_dep': self.cc + [ d.so_link for d in self.vala_deps ], 221 'targets': [ target ], 222 } 223 224 225 226 227