forked from OSchip/llvm-project
[gn build] Process .def.in files in llvm/Config and add lib/Target/BUILD.gn
Tweak write_cmake_config.py to also handle variable references looking @FOO@ (matching CMake's configure_file() function), and make it replace '\' 'n' in values with a newline literal since there's no good portable way of passing a real newline literal on a command line. Use that to process all the .def.in files in llvm/include/Config and add llvm/lib/Target/BUILD.gn, which (indirectly, through llvm-c/Target.h) includes them. Differential Revision: https://reviews.llvm.org/D55184 llvm-svn: 348503
This commit is contained in:
parent
96f6963708
commit
1be23a901f
|
@ -2,16 +2,17 @@
|
|||
"""Emulates the bits of CMake's configure_file() function needed in LLVM.
|
||||
|
||||
The CMake build uses configure_file() for several things. This emulates that
|
||||
function for the GN build. In the GN build, this runs at build time, instead
|
||||
function for the GN build. In the GN build, this runs at build time instead
|
||||
of at generator time.
|
||||
|
||||
Takes a list of KEY=VALUE pairs (where VALUE can be empty).
|
||||
|
||||
On each line, replaces ${KEY} with VALUE.
|
||||
The sequence `\` `n` in each VALUE is replaced by a newline character.
|
||||
|
||||
After that, also handles these special cases (note that FOO= sets the value of
|
||||
FOO to the empty string, which is falsy, but FOO=0 sets it to '0' which is
|
||||
truthy):
|
||||
On each line, replaces '${KEY}' or '@KEY@' with VALUE.
|
||||
|
||||
Then, handles these special cases (note that FOO= sets the value of FOO to the
|
||||
empty string, which is falsy, but FOO=0 sets it to '0' which is truthy):
|
||||
|
||||
1.) #cmakedefine01 FOO
|
||||
Checks if key FOO is set to a truthy value, and depending on that prints
|
||||
|
@ -28,8 +29,7 @@ truthy):
|
|||
/* #undef FOO */
|
||||
|
||||
Fails if any of the KEY=VALUE arguments aren't needed for processing the
|
||||
.h.cmake file, or if the .h.cmake file has unreplaced ${VAR} references after
|
||||
processing all values.
|
||||
input file, or if the input file references keys that weren't passed in.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
@ -53,18 +53,19 @@ def main():
|
|||
values = {}
|
||||
for value in args.values:
|
||||
key, val = value.split('=', 1)
|
||||
values[key] = val
|
||||
values[key] = val.replace('\\n', '\n')
|
||||
unused_values = set(values.keys())
|
||||
|
||||
# Matches e.g. '${CLANG_FOO}' and captures CLANG_FOO in group 1.
|
||||
var_re = re.compile(r'\$\{([^}]*)\}')
|
||||
# Matches e.g. '${FOO}' or '@FOO@' and captures FOO in group 1 or 2.
|
||||
var_re = re.compile(r'\$\{([^}]*)\}|@([^@]*)@')
|
||||
|
||||
in_lines = open(args.input).readlines()
|
||||
out_lines = []
|
||||
for in_line in in_lines:
|
||||
def repl(m):
|
||||
unused_values.discard(m.group(1))
|
||||
return values[m.group(1)]
|
||||
key = m.group(1) or m.group(2)
|
||||
unused_values.discard(key)
|
||||
return values[key]
|
||||
in_line = var_re.sub(repl, in_line)
|
||||
if in_line.startswith('#cmakedefine01 '):
|
||||
_, var = in_line.split()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
group("default") {
|
||||
deps = [
|
||||
"//llvm/lib/Object",
|
||||
"//llvm/lib/Target",
|
||||
"//llvm/tools/llvm-undname",
|
||||
"//llvm/utils/TableGen:llvm-tblgen",
|
||||
]
|
||||
|
|
|
@ -7,7 +7,8 @@ import("//llvm/utils/gn/build/libs/xml/enable.gni")
|
|||
import("//llvm/utils/gn/build/libs/zlib/enable.gni")
|
||||
import("//llvm/version.gni")
|
||||
|
||||
# Contains actions to create config.h, llvm-config.h and abi-breaking.h.
|
||||
# Contains actions to create config.h, llvm-config.h, abi-breaking.h,
|
||||
# and the various .def files used by llvm/lib/Target.
|
||||
# Other than in the cmake build, these are created at build time, not at
|
||||
# config time. That way, they can run in parallel, and this pattern means that
|
||||
# e.g. creating the clang config header (which happens in another gn file)
|
||||
|
@ -19,6 +20,9 @@ import("//llvm/version.gni")
|
|||
# Other than in the cmake build, header generation doesn't do any feature
|
||||
# checking. See also "Philosophy" in llvm/utils/gn/README.rst.
|
||||
|
||||
##############################################################################
|
||||
# config.h, llvm-config.h, abi-breaking.h
|
||||
|
||||
# FIXME: Several of the config settings go in a global config header but
|
||||
# are only used in a single translation unit -- so toggling that value
|
||||
# causes a full rebuild when it really only has to rebuild a single file.
|
||||
|
@ -356,3 +360,71 @@ action("llvm-config") {
|
|||
args += [ "LLVM_ENABLE_THREADS=" ]
|
||||
}
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
# .def files used by llvm/lib/Target
|
||||
|
||||
template("write_target_def_file") {
|
||||
assert(defined(invoker.key), "callers must set key")
|
||||
assert(defined(invoker.value), "callers must set value")
|
||||
|
||||
action(target_name) {
|
||||
visibility = [ ":write_target_def_files" ]
|
||||
script = "//llvm/utils/gn/build/write_cmake_config.py"
|
||||
|
||||
sources = [
|
||||
"$target_name.in",
|
||||
]
|
||||
outputs = [
|
||||
"$target_gen_dir/$target_name",
|
||||
]
|
||||
|
||||
# Build something like
|
||||
# `LLVM_ENUM_ASM_PARSERS=LLVM_ASM_PARSER(ARM)\nLLVM_ASM_PARSER(X86)\n`. Note
|
||||
# that \n is a literal '\' followed by a literal 'n', not a newline
|
||||
# character. (write_cmake_config.py replaces that with a real newline).
|
||||
value = ""
|
||||
foreach(target, llvm_targets_to_build) {
|
||||
value = "$value${invoker.value}($target)\n"
|
||||
}
|
||||
args = [
|
||||
"-o",
|
||||
rebase_path(outputs[0], root_out_dir),
|
||||
rebase_path(sources[0], root_out_dir),
|
||||
"${invoker.key}=$value",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
write_target_def_file("AsmParsers.def") {
|
||||
key = "LLVM_ENUM_ASM_PARSERS"
|
||||
value = "LLVM_ASM_PARSER"
|
||||
}
|
||||
|
||||
write_target_def_file("AsmPrinters.def") {
|
||||
key = "LLVM_ENUM_ASM_PRINTERS"
|
||||
value = "LLVM_ASM_PRINTER"
|
||||
}
|
||||
|
||||
write_target_def_file("Disassemblers.def") {
|
||||
key = "LLVM_ENUM_DISASSEMBLERS"
|
||||
value = "LLVM_DISASSEMBLER"
|
||||
}
|
||||
|
||||
write_target_def_file("Targets.def") {
|
||||
key = "LLVM_ENUM_TARGETS"
|
||||
value = "LLVM_TARGET"
|
||||
}
|
||||
|
||||
group("write_target_def_files") {
|
||||
visibility = [
|
||||
"//llvm/lib/Support",
|
||||
"//llvm/lib/Target",
|
||||
]
|
||||
deps = [
|
||||
":AsmParsers.def",
|
||||
":AsmPrinters.def",
|
||||
":Disassemblers.def",
|
||||
":Targets.def",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ static_library("Support") {
|
|||
# both Support and ADT.
|
||||
"//llvm/include/llvm/Config:abi-breaking",
|
||||
"//llvm/include/llvm/Config:llvm-config",
|
||||
# public_dep because public header TargetSelect.h includes these .def files.
|
||||
"//llvm/include/llvm/Config:write_target_def_files",
|
||||
]
|
||||
include_dirs = [
|
||||
"Unix",
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import("//llvm/lib/Target/targets.gni")
|
||||
|
||||
static_library("Target") {
|
||||
output_name = "LLVMTarget"
|
||||
deps = [
|
||||
"//llvm/lib/Analysis",
|
||||
"//llvm/lib/IR",
|
||||
"//llvm/lib/MC",
|
||||
"//llvm/lib/Support",
|
||||
]
|
||||
public_deps = [
|
||||
# This is a bit of a hack: llvm-c/Target.h includes llvm/Config/Targets.def,
|
||||
# but there's no target corresponding to llvm-c. Since the functions
|
||||
# declared in llvm-c/Target.h are defined in llvm/lib/Target, clients of
|
||||
# it must depend on llvm/lib/Target, so add the public_dep for Targets.def
|
||||
# here.
|
||||
"//llvm/include/llvm/Config:write_target_def_files",
|
||||
]
|
||||
sources = [
|
||||
"Target.cpp",
|
||||
"TargetIntrinsicInfo.cpp",
|
||||
"TargetLoweringObjectFile.cpp",
|
||||
"TargetMachine.cpp",
|
||||
"TargetMachineC.cpp",
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue