| #!/usr/bin/env python |
| # |
| # This source file is part of the Swift.org open source project |
| # |
| # Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors |
| # Licensed under Apache License v2.0 with Runtime Library Exception |
| # |
| # See http://swift.org/LICENSE.txt for license information |
| # See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| |
| import os |
| import subprocess |
| import sys |
| |
| import util |
| from simplebuild import * |
| |
| class GetFileInfoRule(SimpleAsyncRule): |
| """ |
| Rule which synchronizes the state of external file. |
| """ |
| |
| def __init__(self, path): |
| self.path = str(path) |
| |
| def run(self): |
| util.note("getting file info: %r" % (self.path,)) |
| return util.get_stat_info(self.path) |
| |
| def is_data_valid(self, engine, data): |
| # Check if the current info is up-to-date. |
| util.note("checking file info: %r" % (self.path,)) |
| return util.get_stat_info(self.path) == data |
| |
| class GetDirectoryContentsRule(SimpleAsyncRule): |
| def __init__(self, path): |
| self.path = path |
| |
| def start(self, engine): |
| # Get the file info for the directory, to ensure we treat the external |
| # directory as an input. |
| engine.task_needs_input(self, GetFileInfoRule.asKey(self.path)) |
| |
| def provide_data(self, engine, input_id, data): |
| pass |
| |
| def run(self): |
| util.note("listing directory contents: %r" % (str(self.path),)) |
| try: |
| return sorted(os.listdir(self.path)) |
| except OSError: |
| return [] |
| |
| class SpawnJobRule(SimpleAsyncRule): |
| def __init__(self, args, input_files, output_files, other_inputs=()): |
| self.args = list(args) |
| self.input_files = list(input_files) |
| self.output_files = list(output_files) |
| self.other_inputs = list(other_inputs) |
| |
| def start(self, engine): |
| # Request all of the inputs. |
| for path in self.input_files: |
| engine.task_needs_input(self, GetFileInfoRule.asKey(path)) |
| for key in self.other_inputs: |
| engine.task_needs_input(self, key) |
| |
| def provide_data(self, engine, input_id, data): |
| pass |
| |
| def run(self): |
| try: |
| util.message(' '.join(self.args)) |
| subprocess.check_call(self.args) |
| except: |
| util.error("error: command failed: %s" % (' '.join(self.args),)) |
| return { "error" : True } |
| |
| # Get the file info on all of the output files. |
| output_infos = [util.get_stat_info(path) |
| for path in self.output_files] |
| return { "output_info" : output_infos } |
| |
| class BuildDirectoryRule(SimpleRule): |
| sources_list_ID = 0 |
| compile_ID = 1 |
| link_ID = 2 |
| |
| def __init__(self, path): |
| self.path = path |
| self.sources = None |
| |
| def start(self, engine): |
| # Request the source files for the current directory. |
| engine.task_needs_input(self, GetDirectoryContentsRule.asKey(self.path), |
| self.sources_list_ID) |
| |
| def provide_data(self, engine, input_id, result): |
| if input_id == self.sources_list_ID: |
| self.sources = [str(name) |
| for name in result |
| if name.endswith(".c")] |
| util.note("building sources: %r" % (self.sources),) |
| |
| # Request compilation of all the sources. |
| objects = [] |
| objects_keys = [] |
| for name in self.sources: |
| input = os.path.join(self.path, name) |
| output = os.path.join(self.path, "%s.o" % name) |
| objects.append(output) |
| |
| cmd = ['cc', '-c', '-o', output, input] |
| job = SpawnJobRule.asKey(cmd, [input], [output]) |
| engine.task_needs_input(self, job, self.compile_ID) |
| objects_keys.append(job) |
| |
| # Request a link of the objects. |
| output = os.path.join(self.path, os.path.basename(self.path)) |
| cmd = ['cc', '-o', output] + objects |
| job = SpawnJobRule.asKey(cmd, [], [output], objects_keys) |
| engine.task_needs_input(self, job, self.link_ID) |
| |
| def inputs_available(self, engine): |
| engine.task_is_complete(self, "done.") |
| |
| # Get the input path. |
| _,path = sys.argv |
| |
| # Build the app. |
| engine = DataDrivenEngine(globals()) |
| engine.attach_db(".build.db") |
| result = engine.build(BuildDirectoryRule.asKey(path)) |
| print result |