Index: llvm/trunk/utils/gn/build/write_cmake_config.py =================================================================== --- llvm/trunk/utils/gn/build/write_cmake_config.py +++ llvm/trunk/utils/gn/build/write_cmake_config.py @@ -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 @@ /* #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 @@ 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() Index: llvm/trunk/utils/gn/secondary/BUILD.gn =================================================================== --- llvm/trunk/utils/gn/secondary/BUILD.gn +++ llvm/trunk/utils/gn/secondary/BUILD.gn @@ -1,6 +1,7 @@ group("default") { deps = [ "//llvm/lib/Object", + "//llvm/lib/Target", "//llvm/tools/llvm-undname", "//llvm/utils/TableGen:llvm-tblgen", ] Index: llvm/trunk/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn =================================================================== --- llvm/trunk/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn +++ llvm/trunk/utils/gn/secondary/llvm/include/llvm/Config/BUILD.gn @@ -7,7 +7,8 @@ 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 @@ # 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 @@ 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", + ] +} Index: llvm/trunk/utils/gn/secondary/llvm/lib/Support/BUILD.gn =================================================================== --- llvm/trunk/utils/gn/secondary/llvm/lib/Support/BUILD.gn +++ llvm/trunk/utils/gn/secondary/llvm/lib/Support/BUILD.gn @@ -19,6 +19,8 @@ # 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", Index: llvm/trunk/utils/gn/secondary/llvm/lib/Target/BUILD.gn =================================================================== --- llvm/trunk/utils/gn/secondary/llvm/lib/Target/BUILD.gn +++ llvm/trunk/utils/gn/secondary/llvm/lib/Target/BUILD.gn @@ -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", + ] +}