blob: 1206dabfca1f50baab7ea411de35d89a10135c08 [file] [log] [blame]
#!/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