llvm-build: Add --configure-target-def-file option.

- Can be used to generate the substitution values we currently use for the various target related .def files.

llvm-svn: 144345
This commit is contained in:
Daniel Dunbar 2011-11-11 00:24:00 +00:00
parent 846fb32afc
commit fe59bd30be
3 changed files with 115 additions and 9 deletions

View File

@ -0,0 +1,66 @@
"""
Defines utilities useful for performing standard "configuration" style tasks.
"""
import re
import os
def configure_file(input_path, output_path, substitutions):
"""configure_file(input_path, output_path, substitutions) -> bool
Given an input and output path, "configure" the file at the given input path
by replacing variables in the file with those given in the substitutions
list. Returns true if the output file was written.
The substitutions list should be given as a list of tuples (regex string,
replacement), where the regex and replacement will be used as in 're.sub' to
execute the variable replacement.
The output path's parent directory need not exist (it will be created).
If the output path does exist and the configured data is not different than
it's current contents, the output file will not be modified. This is
designed to limit the impact of configured files on build dependencies.
"""
# Read in the input data.
f = open(input_path, "rb")
try:
data = f.read()
finally:
f.close()
# Perform the substitutions.
for regex_string,replacement in substitutions:
regex = re.compile(regex_string)
data = regex.sub(replacement, data)
# Ensure the output parent directory exists.
output_parent_path = os.path.dirname(os.path.abspath(output_path))
if not os.path.exists(output_parent_path):
os.makedirs(output_parent_path)
# If the output path exists, load it and compare to the configured contents.
if os.path.exists(output_path):
current_data = None
try:
f = open(output_path, "rb")
try:
current_data = f.read()
except:
current_data = None
f.close()
except:
current_data = None
if current_data is not None and current_data == data:
return False
# Write the output contents.
f = open(output_path, "wb")
try:
f.write(data)
finally:
f.close()
return True

View File

@ -2,6 +2,7 @@ import os
import sys
import componentinfo
import configutil
from util import *
@ -616,6 +617,9 @@ def main():
help=(
"If given, an alternate path to search for LLVMBuild.txt files"),
action="store", default=None, metavar="PATH")
group.add_option("", "--build-root", dest="build_root", metavar="PATH",
help="Path to the build directory (if needed) [%default]",
action="store", default=None)
parser.add_option_group(group)
group = OptionGroup(parser, "Output Options")
@ -637,6 +641,14 @@ def main():
dest="write_make_fragment", metavar="PATH",
help="Write the Makefile project information to PATH",
action="store", default=None)
group.add_option("", "--configure-target-def-file",
dest="configure_target_def_files",
help="""Configure the given file at SUBPATH (relative to
the inferred or given source root, and with a '.in' suffix) by replacing certain
substitution variables with lists of targets that support certain features (for
example, targets with AsmPrinters) and write the result to the build root (as
given by --build-root) at the same SUBPATH""",
metavar="SUBPATH", action="append", default=None)
parser.add_option_group(group)
group = OptionGroup(parser, "Configuration Options")
@ -701,5 +713,40 @@ def main():
if opts.write_cmake_fragment:
project_info.write_cmake_fragment(opts.write_cmake_fragment)
# Configure target definition files, if requested.
if opts.configure_target_def_files:
# Verify we were given a build root.
if not opts.build_root:
parser.error("must specify --build-root when using "
"--configure-target-def-file")
# Create the substitution list.
available_targets = [ci for ci in project_info.component_infos
if ci.type_name == 'TargetGroup']
substitutions = [
("@LLVM_ENUM_TARGETS@",
' '.join('LLVM_TARGET(%s)' % ci.name
for ci in available_targets)),
("@LLVM_ENUM_ASM_PRINTERS@",
' '.join('LLVM_ASM_PRINTER(%s)' % ci.name
for ci in available_targets
if ci.has_asmprinter)),
("@LLVM_ENUM_ASM_PARSERS@",
' '.join('LLVM_ASM_PARSER(%s)' % ci.name
for ci in available_targets
if ci.has_asmparser)),
("@LLVM_ENUM_DISASSEMBLERS@",
' '.join('LLVM_DISASSEMBLER(%s)' % ci.name
for ci in available_targets
if ci.has_disassembler))]
# Configure the given files.
for subpath in opts.configure_target_def_files:
inpath = os.path.join(source_root, subpath + '.in')
outpath = os.path.join(opts.build_root, subpath)
result = configutil.configure_file(inpath, outpath, substitutions)
if not result:
note("configured file %r hasn't changed" % outpath)
if __name__=='__main__':
main()

View File

@ -1,16 +1,9 @@
import inspect
import os
import sys
def _write_message(kind, message):
# Get the file/line where this message was generated.
f = inspect.currentframe()
# Step out of _write_message, and then out of wrapper.
f = f.f_back.f_back
file,line,_,_,_ = inspect.getframeinfo(f)
location = '%s:%d' % (os.path.basename(file), line)
print >>sys.stderr, '%s: %s: %s' % (location, kind, message)
program = os.path.basename(sys.argv[0])
print >>sys.stderr, '%s: %s: %s' % (program, kind, message)
note = lambda message: _write_message('note', message)
warning = lambda message: _write_message('warning', message)