The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

builder.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/builder.py.
Remove old SVG parser code
1 import os 2 import fnmatch 3 import glob 4 import types 5 import time 6 from os import path 7 from scripts.run import run 8 9 def get_sources_path(directory, pattern): 10 """obtain path of all source files for a matching pattern""" 11 matches = [] 12 for root, dirnames, filenames in os.walk(directory): 13 for filename in filenames: 14 full_path = os.path.join(root, filename) 15 if fnmatch.filter([full_path], pattern): 16 matches.append(os.path.join(root, filename)) 17 return matches 18 19 class Builder(object): 20 """helper to generate tasks to compile vala code""" 21 22 def __init__(self, 23 source_directory, 24 valac_command, 25 cc_command, 26 linker_command, 27 target_binary, 28 link = None, 29 dependencies = None): 30 self.source_directory = source_directory 31 self.valac_command = valac_command 32 self.cc_command = cc_command 33 self.linker_command = linker_command 34 self.target_binary = target_binary 35 self.link = link 36 self.dependencies = dependencies 37 38 def build(self): 39 source_directory = self.source_directory 40 valac_command = self.valac_command 41 cc_command = self.cc_command 42 linker_command = self.linker_command 43 target_binary = self.target_binary 44 45 if not self.dependencies == None: 46 bindep = [path.join('build', 'bin', f) for f in self.dependencies] 47 else: 48 bindep = [] 49 50 copied_csource_paths = get_sources_path(source_directory, '*.c') 51 copied_cheader_paths = get_sources_path(source_directory, '*.h') 52 vala_source_paths = get_sources_path(source_directory, '*.vala') 53 build_directory = path.join('build', source_directory) 54 55 csource_files = [path.basename(f) for f in copied_csource_paths] 56 generated_csource_paths = [] 57 for vala_path in vala_source_paths: 58 vala_file = path.basename(vala_path) 59 cfile = vala_file.replace('.vala', '.c') 60 cpath = path.join(build_directory, cfile) 61 generated_csource_paths.append(cpath) 62 csource_files.append(cfile) 63 64 build_file = path.join(build_directory, 'placeholder') 65 yield { 66 'basename': 'mkdir ' + build_directory, 67 'actions': ['mkdir -p ' + path.join('build', 'bin'), 68 'mkdir -p ' + build_directory, 69 '[ -e "' + build_file + '" ] || touch "' + build_file + '"'], 70 'targets': [build_file], 71 } 72 73 copied_csources = [] 74 copied_cheader = [] 75 for csource in copied_cheader_paths + copied_csource_paths: 76 dest = path.join(build_directory, path.basename(csource)) 77 78 if not dest[-2:] == ".h": 79 copied_csources.append(dest) 80 else: 81 copied_cheader.append(dest) 82 83 yield { 84 'basename': 'copy ' + csource, 85 'file_dep': [build_file] + [csource], 86 'actions': ['cp ' + csource + ' ' + build_directory], 87 'targets': [dest] 88 } 89 90 yield { 91 'basename': 'valac ' + source_directory, 92 'file_dep': [build_file] + vala_source_paths + bindep, 93 'actions': [valac_command], 94 'targets': generated_csource_paths 95 } 96 97 csource_paths = generated_csource_paths + copied_csources 98 object_files = [] 99 100 for csource in csource_paths: 101 object_file = path.basename (csource.replace('.c', '.o')) 102 object_files.append(object_file); 103 104 command = cc_command.replace('C_SOURCE', csource) 105 object_path = path.join(build_directory, object_file) 106 command = command.replace('OBJECT_FILE', object_path) 107 yield { 108 'basename': 'compile ' + csource, 109 'file_dep': [build_file, csource] + copied_cheader, 110 'actions': [command], 111 'targets': [path.join(build_directory, object_file)], 112 } 113 114 object_paths = [path.join(build_directory, f) for f in object_files] 115 yield { 116 'basename': source_directory, 117 'file_dep': object_paths + [build_file], 118 'actions': [linker_command], 119 'targets': [path.join('build', 'bin', target_binary)] 120 } 121 122 if not self.link == None: 123 createlink = 'cd build/bin/ && ln -s -f ' + target_binary + ' ' + self.link 124 yield { 125 'basename': 'Create link ' + target_binary + ' ' + self.link, 126 'file_dep': [path.join('build', 'bin', target_binary)], 127 'actions': [createlink], 128 'targets': [path.join('build', 'bin', self.link)] 129 } 130 131 def is_up_to_date(task): 132 for target in task['targets']: 133 if not path.isfile(target): 134 return False 135 136 if not 'file_dep' in task.keys(): 137 return False 138 139 for dep in task['file_dep']: 140 if not path.isfile(dep): 141 print('Dependency is not created yet: ' + dep + ' needed for ' + task['targets']) 142 exit(1) 143 144 target_times = [] 145 for target in task['targets']: 146 target_times.append(path.getmtime(target)) 147 target_times.sort() 148 149 dependency_times = [] 150 for dependency in task['file_dep']: 151 if not path.basename(dependency) == 'placeholder': 152 dependency_times.append(path.getmtime(dependency)) 153 dependency_times.sort() 154 155 if len(dependency_times) == 0 or len(target_times) == 0: 156 return False 157 158 return dependency_times[-1] <= target_times[0] 159 160 161 def get_name(task): 162 try: 163 return task['name'] 164 except KeyError: 165 return task['basename'] 166 167 def execute_task(task): 168 if is_up_to_date(task): 169 print(get_name(task) + ' - up to date.') 170 else: 171 for action in task['actions']: 172 print(action) 173 run(action) 174 175 def process_tasks(generator): 176 for task in generator: 177 if isinstance(task, types.GeneratorType): 178 process_tasks(task) 179 else: 180 execute_task(task) 181 182