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.
Create a library of the Graphics Gems code
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.c += get_sources_path (src, '*.h') # copy header files for the c sources 78 self.cc = [join(build + '/' + src, f) for f in get_sources_name (src, '*.c') ] 79 self.cc += [join(build + '/' + src, f.replace('.vala', '.c')) for f in get_sources_name (src, '*.vala')] 80 self.obj = [self.build + '/' + self.src + '/' + f.replace('.c', '.o') for f in get_sources_name (src, '*.c')] 81 self.obj += [self.build + '/' + self.src + '/' + f.replace('.vala', '.o') for f in get_sources_name (src, '*.vala')] 82 83 if library: 84 self.header = join(build, library) + '.h' 85 self.vapi = join(build, library) + '.vapi' 86 self.so = join(build, src) + '.so.' + so_version 87 self.so_link = join(build, src) + '.so' 88 self.so_link_name = src + '.so' 89 self.so_version = so_version 90 self.so_name = 'lib' + library + '.so.' + so_version 91 92 93 def gen_c(self, opts): 94 """translate code from vala to C and create .vapi""" 95 options = ['--ccode'] 96 options.extend(opts) 97 params = { 98 'basedir': join(self.build, self.src), 99 'vapidir': './', 100 'pkg': self.pkg_libs, 101 } 102 if self.library: 103 params['library'] = self.library 104 params['vapi'] = self.vapi 105 params['header'] = self.header 106 107 dep_vapi = [d.vapi for d in self.vala_deps] 108 action = cmd('valac', options, params, dep_vapi, self.vala) 109 targets = self.cc[:] 110 if self.library: 111 targets += [self.header, self.vapi] 112 113 for f in self.c: 114 yield { 115 'name': 'copy_c_' + f, 116 'actions': [ 117 'mkdir -p '+ self.build + '/' + self.src + '/', 118 'cp ' + f + ' ' + self.build + '/' + self.src + '/' 119 ], 120 } 121 122 print (action) 123 yield { 124 'name': 'compile_c', 125 'actions': [ action ], 126 'file_dep': self.vala + dep_vapi, 127 'targets': targets, 128 } 129 130 131 def gen_o(self, opts): 132 """compile C files to obj `.o` """ 133 def compile_cmd(conf, opts, libs, pos): 134 flags = [] 135 for l in libs: 136 if not l == "posix" and not l == "posixtypes": 137 process = subprocess.Popen ('pkg-config --cflags ' + l, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 138 cflags = process.stdout.readline() 139 process.communicate()[0] 140 if not process.returncode == 0: 141 print ( "Library not found: " + l) 142 exit (1) 143 flags += [cflags.strip ()] 144 145 return cmd(config.CC, opts, flags, pos) 146 147 for cc, obj in zip(self.cc, self.obj): 148 pos = ["-c " + cc, "-o " + obj ] 149 cmd_args = {'libs':self.pkg_libs, 'opts':opts, 'pos':pos} 150 action = CmdAction((compile_cmd, [], cmd_args)) 151 yield { 152 'name': obj.rsplit('/')[-1], 153 'file_dep': [ cc ], 154 'actions': [ action ], 155 'getargs': { 'conf': ('pkg_flags', 'out') }, 156 'targets': [ obj ], 157 } 158 159 160 def gen_so(self, generated_libs = None): 161 """generate ".so" lib file""" 162 def compile_cmd(conf, libs): 163 obj_glob = join(self.build, self.src, '*.o') 164 opts = ['-shared ' 165 + '-Wl,-soname,' + self.so_name 166 + ' ' + obj_glob 167 + ' -o ' + self.so ] 168 169 flags = [] 170 for l in libs: 171 if not l == "posix" and not l == "posixtypes": 172 process = subprocess.Popen ('pkg-config --cflags ' + l, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 173 cflags = process.stdout.readline() 174 process.communicate()[0] 175 if not process.returncode == 0: 176 print ( "Library not found: " + l) 177 exit (1) 178 flags += [cflags.strip ()] 179 180 if generated_libs: 181 flags += [generated_libs] 182 183 return cmd(config.CC, opts, flags) 184 185 return { 186 'name': self.so.rsplit('/')[-1], 187 'actions': [ CmdAction((compile_cmd, [], {'libs':self.pkg_libs})) ], 188 'getargs': { 'conf': ('pkg_flags', 'out') }, 189 'file_dep': self.obj, 190 'targets': [ self.so ], 191 } 192 193 def gen_ln(self): 194 """generate a symbolic link to the generated ".so" file""" 195 so_file = self.so.rsplit('/')[-1] 196 create_link = "ln -s -T " + so_file + " " + self.so_link_name + " " 197 create_link += "&& mv " + self.so_link_name + " " + self.build + "/" 198 return { 199 'name': self.so_link_name, 200 'actions': [ create_link], 201 'file_dep': [ self.so ], 202 'targets': [ self.so_link ], 203 } 204 205 def gen_bin(self, opts): 206 """generate binary""" 207 def compile_cmd(conf, opts, libs): 208 flags = [conf[l].strip() for l in libs] 209 return cmd(config.CC, opts, flags) 210 211 bin_path = join(self.build, 'bin') 212 target = join(bin_path, self.src) 213 opts = (self.cc + opts + 214 ['-o ' + target, '-I ' + self.build, '-L ' + self.build] + 215 ['-l ' + d.library for d in self.vala_deps]) 216 action = CmdAction((compile_cmd, [], {'opts':opts, 'libs':self.pkg_libs})) 217 yield { 218 'name': "bin", 219 'actions': [ 'mkdir -p %s' % bin_path, action ], 220 'getargs': { 'conf': ('pkg_flags', 'out') }, 221 'file_dep': self.cc + [ d.so_link for d in self.vala_deps ], 222 'targets': [ target ], 223 } 224 225 226 227 228