bazelbuild / rules_rust

Rust rules for Bazel
https://bazelbuild.github.io/rules_rust/
Apache License 2.0
662 stars 426 forks source link

Additional output during compilation #2561

Open pierfale opened 7 months ago

pierfale commented 7 months ago

Hello,

I use bazel to compile a project using Napi-rs. This crate allow to generate automatically Typescript definition by setting an environment variable TYPE_DEF_TMP_PATH during compilation of rust package. It will create a file containing type definition at path specified in the env.

However, I haven't found an easy way to do this with the rules_rust. For now, the best solution I've found is to patch these rules by adding an extra argument to explicitly add this output in the rustc_compile_action.

Do you know of a better option? If not, should I open a PR to propose this change, or is it too specific?

ericmcbride commented 6 months ago

You can use the crate-annotation key in your WORKSPACE file to declare any build.rs envs from crates you need.

Here is an example using libsqlite

crates_repository(
    name = "crates_index",
    annotations = {
        "libsqlite3-sys": [
            crate.annotation(
                build_script_env = {
                    "SQLITE3_LIB_DIR": SO_PATH,
                    "SQLITE3_INCLUDE_DIR": SO_PATH,
                    "SQLITE3_NO_PKG_CONFIG": "1",
                    "SQLITE3_STATIC": "1",
                },
            ),

This will allow you to set envs for crates if you are using crates_universe. It looks like that napi-rs wants you to import in their build crate, and construct your own build.rs file. If thats the case, just do the following

cargo_build_script(
    name = "build-script",
    srcs = ["build.rs"],
    build_script_env = {
         "TYPE_DEF_TMP_PATH: "MY_TYPE_DEF_VALUE",
    },
    deps = all_crate_deps(build = True),
)

rust_library(
    name = "my-lib",
    srcs = glob(["src/**/*.rs"]),
    deps = [":build-script"] +  all_crate_deps(normal = True, normal_dev = True),
)
pierfale commented 6 months ago

This solution will not solve the problem of additional output. Here's an example with the "extra_outs" parameter I've added

cargo_build_script(
  name = "build_script",
  srcs = ["build.rs"],
  aliases = aliases(),
  deps = all_crate_deps(
    build = True,
  ),
  proc_macro_deps = all_crate_deps(
    build_proc_macro = True,
  ),
)

rust_shared_library(
  name = "rust-lib",
  srcs = glob(["src/**/*.rs"]),
  aliases = aliases(
    normal = True,
    proc_macro = True,
  ),
  deps = all_crate_deps(
    normal = True,
  )+[
    ":build_script",
  ],
  proc_macro_deps = all_crate_deps(
    proc_macro = True,
  ),
  rustc_env = {
    "TYPE_DEF_TMP_PATH": "$(GENDIR)/%s/napi_def.tmp" % package_name(),
  },
  extra_outs = ["napi_def.tmp"]
)

# custom rule to change node-lib.so into index.node
node_native_library(
  name = "node-lib",
  out = "index",
  src = ":rust-lib",
)

# Generate Typescript definition from napi_def.tmp
js_run_binary(
  name = "generate-ts-defs",
  srcs = [":rust-lib"],
  outs = ["index.d.ts"],
  args = ["$(locations :rust-lib)", "$(BINDIR)/$(rootpath :index.d.ts)"],
  tool = "//bazel/rs2ts",
  chdir = '../../..',
  silent_on_success = False,
  copy_srcs_to_bin = False,
)

npm_package(
  name = "my-lib",
  srcs = [
    "index.d.ts",
    "package.json",
    ":node-lib"
  ],
  include_runfiles = False,
)

Currently, I don't see any other way apart from explicitly adding the napi_def.tmp file as an output of the rust_shared_library rule in order to not break the remote execution system.