"""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
/* #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
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()
group("default") {
deps = [
"//llvm/lib/Object",
+ "//llvm/lib/Target",
"//llvm/tools/llvm-undname",
"//llvm/utils/TableGen:llvm-tblgen",
]
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)
# 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.
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",
+ ]
+}
# 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",
--- /dev/null
+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",
+ ]
+}