From b1e94a02fe7be2001186668227d1837642ee4fce Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Fri, 5 May 2023 12:35:44 -0600 Subject: [PATCH] Meta: Add compiled_action from LLVM, use it to generate TZDB sources --- Meta/gn/build/compiled_action.gni | 77 +++++++++++++++++++ Meta/gn/build/run_compiled_binary.py | 8 ++ .../Userland/Libraries/LibTimeZone/BUILD.gn | 29 ++++++- 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 Meta/gn/build/compiled_action.gni create mode 100644 Meta/gn/build/run_compiled_binary.py diff --git a/Meta/gn/build/compiled_action.gni b/Meta/gn/build/compiled_action.gni new file mode 100644 index 0000000000..513a41d2c7 --- /dev/null +++ b/Meta/gn/build/compiled_action.gni @@ -0,0 +1,77 @@ +# Defines compiled_action(). +# +# compiled_action() is like action(), except that it runs a built binary +# instead of a script. +# +# Parameters: +# +# tool (required) +# [label] Label of the tool to run. This should be an executable, and +# this label should not include a toolchain (anything in parens). This +# tool will be built for the host. +# +# outputs (required) +# [list of files] Same meaning as for action(). +# +# args (required) +# [list of strings] Flags to pass to the built binary. Almost identical +# to action()'s `args`, except that `tool` is implicitly added as first +# element. +# +# depfile +# inputs +# public_configs +# visibility (all optional) +# Same meaning as for action(). +# +# Example use: +# +# compiled_action("run_my_tool") { +# tool = "//tools/something:mytool" +# inputs = [ "my_input_file.txt" ] +# outputs = [ "$target_gen_dir/mysource.inc" ] +# args = [ +# rebase_path(inputs[0], root_build_dir), +# rebase_path(outputs[0], root_build_dir), +# ] +# } +# +# You would typically declare your tool like this: +# if (host_toolchain == current_toolchain) { +# executable("mytool") { +# ... +# } +# } +# The if statement around the executable is optional. It means "I only care +# about this target in the host toolchain". Usually this is what you want, and +# saves unnecessarily compiling your tool for the target platform. If you +# need a target build of your tool as well, omit the if statement. + +template("compiled_action") { + assert(defined(invoker.args), "must set 'args' in $target_name") + assert(defined(invoker.outputs), "must set 'outputs' in $target_name") + assert(defined(invoker.tool), "must set 'tool' in $target_name") + assert(!defined(invoker.sources), + "use 'inputs' instead of 'sources' in $target_name") + + action(target_name) { + forward_variables_from(invoker, + [ + "depfile", + "inputs", + "outputs", + "public_configs", + "testonly", + "visibility", + ]) + host_tool = invoker.tool + "($host_toolchain)" + host_executable = get_label_info(host_tool, "root_out_dir") + "/bin/" + + get_label_info(host_tool, "name") + deps = [ host_tool ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + script = "//Meta/gn/build/run_compiled_binary.py" + args = [ rebase_path(host_executable, root_build_dir) ] + invoker.args + } +} diff --git a/Meta/gn/build/run_compiled_binary.py b/Meta/gn/build/run_compiled_binary.py new file mode 100644 index 0000000000..faac565487 --- /dev/null +++ b/Meta/gn/build/run_compiled_binary.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 +"""Runs a built binary.""" + +import subprocess +import sys + +# Prefix with ./ to run built binary, not arbitrary stuff from PATH. +sys.exit(subprocess.call(['./' + sys.argv[1]] + sys.argv[2:])) diff --git a/Meta/gn/secondary/Userland/Libraries/LibTimeZone/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibTimeZone/BUILD.gn index 7ff9a3c044..e2760028aa 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibTimeZone/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibTimeZone/BUILD.gn @@ -39,11 +39,35 @@ if (enable_timezone_database_download) { "southamerica", ] } + compiled_action("generate_timezone_sources") { + tool = "//Meta/Lagom/Tools/CodeGenerators/LibTimeZone:GenerateTimeZoneData" + deps = [ ":timezone_database_files" ] + inputs = get_target_outputs(":timezone_database_files") + outputs = [ + "$target_gen_dir/TimeZoneData.h", + "$target_gen_dir/TimeZoneData.cpp", + ] + args = [ + "-h", + rebase_path(outputs[0], root_build_dir), + "-c", + rebase_path(outputs[1], root_build_dir), + "-z", + + # NOTE: Coordinates file must be inputs[0] + ] + foreach(data_file, inputs) { + args += [ rebase_path(data_file, root_build_dir) ] + } + } } source_set("LibTimeZone") { output_name = "timezone" - include_dirs = [ "//Userland/Libraries" ] + include_dirs = [ + "//Userland/Libraries", + "$target_gen_dir/..", + ] sources = [ "Forward.h", "TimeZone.cpp", @@ -54,6 +78,7 @@ source_set("LibTimeZone") { "//Userland/Libraries/LibCore", ] if (enable_timezone_database_download) { - deps += [ ":timezone_database_files" ] + deps += [ ":generate_timezone_sources" ] + sources += get_target_outputs(":generate_timezone_sources") } }