Chris Frantz | 3215669 | 2022-06-21 22:03:26 -0700 | [diff] [blame] | 1 | # Copyright lowRISC contributors. |
| 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | # SPDX-License-Identifier: Apache-2.0 |
| 4 | |
| 5 | load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain") |
| 6 | |
| 7 | """Rust generation rules for `ujson`.""" |
| 8 | |
| 9 | def _ujson_rust(ctx): |
| 10 | cc_toolchain = find_cc_toolchain(ctx).cc |
| 11 | module = ctx.actions.declare_file("{}.rs".format(ctx.label.name)) |
| 12 | ujson_lib = ctx.attr.ujson_lib[CcInfo].compilation_context.headers.to_list() |
| 13 | |
| 14 | srcs = [] |
| 15 | for src in ctx.attr.srcs: |
| 16 | srcs.extend(src[CcInfo].compilation_context.direct_public_headers) |
| 17 | |
| 18 | # TODO(cfrantz): Is there a better way to find the `rustfmt` binary? |
| 19 | rustfmt_files = ctx.attr._rustfmt.data_runfiles.files.to_list() |
| 20 | rustfmt = [f for f in rustfmt_files if f.basename == "rustfmt"][0] |
| 21 | |
Chris Frantz | a941319 | 2022-08-04 21:03:00 -0700 | [diff] [blame] | 22 | defines = ["-D{}".format(d) for d in ctx.attr.defines] |
| 23 | |
Chris Frantz | 3215669 | 2022-06-21 22:03:26 -0700 | [diff] [blame] | 24 | # The pipeline for generating rust code from a ujson header file: |
| 25 | # 1. Preprocess the file with RUST_PREPROCESSOR_EMIT |
| 26 | # 2. Grep out all the preprocessor noise (which starts with `#`). |
| 27 | # 3. Substitute all `rust_attr` for `#`, thus creating rust attributes. |
| 28 | # 4. Format it with `rustfmt` so it looks nice and can be inspected. |
| 29 | command = """ |
Chris Frantz | a941319 | 2022-08-04 21:03:00 -0700 | [diff] [blame] | 30 | {preprocessor} -nostdinc -I. -DRUST_PREPROCESSOR_EMIT=1 -DNOSTDINC=1 {defines} $@ \ |
Chris Frantz | 3215669 | 2022-06-21 22:03:26 -0700 | [diff] [blame] | 31 | | grep -v '#' \ |
| 32 | | sed -e "s/rust_attr/#/g" \ |
| 33 | | {rustfmt} > {module}""".format( |
| 34 | preprocessor = cc_toolchain.preprocessor_executable, |
Chris Frantz | a941319 | 2022-08-04 21:03:00 -0700 | [diff] [blame] | 35 | defines = " ".join(defines), |
Chris Frantz | 3215669 | 2022-06-21 22:03:26 -0700 | [diff] [blame] | 36 | module = module.path, |
| 37 | rustfmt = rustfmt.path, |
| 38 | ) |
| 39 | |
| 40 | ctx.actions.run_shell( |
| 41 | outputs = [module], |
| 42 | inputs = ujson_lib + srcs, |
| 43 | tools = cc_toolchain.all_files.to_list() + rustfmt_files, |
| 44 | arguments = [src.path for src in srcs], |
| 45 | command = command, |
| 46 | ) |
| 47 | return [ |
| 48 | DefaultInfo(files = depset([module]), runfiles = ctx.runfiles([module])), |
| 49 | ] |
| 50 | |
| 51 | ujson_rust = rule( |
| 52 | implementation = _ujson_rust, |
| 53 | attrs = { |
| 54 | "srcs": attr.label_list( |
| 55 | providers = [CcInfo], |
| 56 | doc = "ujson cc_library targets to generate Rust for", |
| 57 | ), |
Chris Frantz | a941319 | 2022-08-04 21:03:00 -0700 | [diff] [blame] | 58 | "defines": attr.string_list( |
| 59 | doc = "C preprocessor defines", |
| 60 | ), |
Chris Frantz | 3215669 | 2022-06-21 22:03:26 -0700 | [diff] [blame] | 61 | "ujson_lib": attr.label( |
| 62 | default = "//sw/device/lib/ujson", |
| 63 | doc = "Location of the ujson library", |
| 64 | providers = [CcInfo], |
| 65 | ), |
| 66 | "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), |
| 67 | "_rustfmt": attr.label( |
| 68 | default = "@rules_rust//rust/toolchain:current_exec_rustfmt_files", |
| 69 | cfg = "exec", |
| 70 | ), |
| 71 | }, |
| 72 | toolchains = ["@rules_cc//cc:toolchain_type"], |
| 73 | ) |