143 lines
4.7 KiB
Python
Executable File
143 lines
4.7 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# vim: set ft=python:
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (C) 2018 Apple Inc. All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
# Extract dependency information from the output of `make -d`, generating a
|
|
# list of top-level targets (which are assumed to be generated/output files)
|
|
# and a list of leaf dependencies (which are assumed to be the base input
|
|
# files). Read the make dependency information from stdin and write the results
|
|
# to the specified files.
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import re
|
|
import sys
|
|
|
|
|
|
class Parser(object):
|
|
|
|
fileNamePattern = r"`([^']+)'"
|
|
rePrerequisite = re.compile(r"Prerequisite {} is .* than target {}".format(fileNamePattern, fileNamePattern))
|
|
reMustRemakeTarget = re.compile(r"Must remake target {}".format(fileNamePattern))
|
|
reWasConsideredAlready = re.compile(r"{} was considered already.".format(fileNamePattern))
|
|
rePruningFile = re.compile(r"Pruning file {}.".format(fileNamePattern))
|
|
|
|
def __init__(self):
|
|
self.targets = {}
|
|
self.prereqs = {}
|
|
|
|
def nextLine(self, input):
|
|
while True:
|
|
line = input.readline()
|
|
if not line: break
|
|
line = line.strip()
|
|
if line: yield line
|
|
|
|
def addTarget(self, target):
|
|
if target != 'all' and target != 'force':
|
|
self.targets[target] = 1
|
|
|
|
def addPrereq(self, prereq):
|
|
if prereq != 'all' and prereq != 'force':
|
|
self.prereqs[prereq] = 1
|
|
|
|
def doParse(self, input):
|
|
|
|
# Pull out everything that looks like a target or prerequisite.
|
|
|
|
for line in self.nextLine(input):
|
|
m = Parser.rePrerequisite.search(line)
|
|
if m:
|
|
self.addTarget(m.group(2))
|
|
self.addPrereq(m.group(1))
|
|
continue
|
|
|
|
m = Parser.reMustRemakeTarget.search(line)
|
|
if m:
|
|
self.addTarget(m.group(1))
|
|
continue
|
|
|
|
m = Parser.reWasConsideredAlready.search(line)
|
|
if m:
|
|
self.addTarget(m.group(1))
|
|
continue
|
|
|
|
m = Parser.rePruningFile.search(line)
|
|
if m:
|
|
self.addPrereq(m.group(1))
|
|
continue
|
|
|
|
# Regarding prerequisites, we're interested in only those that aren't
|
|
# also targets. We only want ones that don't have build rules, and
|
|
# hence must already exist. Those are our inputs.
|
|
|
|
for key in self.targets.keys():
|
|
self.prereqs.pop(key, None)
|
|
|
|
def printInputs(self, inputsFile):
|
|
with open(inputsFile, 'w') as toFile:
|
|
[ print("{}".format(f), file = toFile) for f in sorted(self.prereqs.keys()) ]
|
|
|
|
def printOutputs(self, outputsFile):
|
|
with open(outputsFile, 'w') as toFile:
|
|
[ print("{}".format(f), file = toFile) for f in sorted(self.targets.keys()) ]
|
|
|
|
|
|
def parseArgs():
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument(
|
|
'--input',
|
|
metavar='<xcfilelist>',
|
|
type=str,
|
|
required = True,
|
|
help='path to the xcfilelist holding input files')
|
|
|
|
parser.add_argument(
|
|
'--output',
|
|
metavar='<xcfilelist>',
|
|
type=str,
|
|
required = True,
|
|
help='path to the xcfilelist holding output/generated files')
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def main():
|
|
args = parseArgs()
|
|
parser = Parser()
|
|
|
|
parser.doParse(sys.stdin)
|
|
parser.printInputs(args.input)
|
|
parser.printOutputs(args.output)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|