rules_foreign_cc
rules_foreign_cc copied to clipboard
Request for example use case of wrapping out-of-tree linux kernel module compilation.
The linux kernel uses Kbuild for its build process. This is typically run by a simple wrapper Makefile which does something like:
default: $(MAKE) -C $(KERNELDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$$PWD
At first-glance, this should be easy to wrap using the existing bazel make wrappers supported here. However, I run into several problems which are non-obvious to address and I was hoping that you might be able to add a simple example to the codebase/documentation on how to resolve them:
- The Makefile requires the path to the directory which contains the Linux kernel source code to build against. I've not found a way to extract the directory path to the cached/copied kernel source tree, even after asking on the bazel-discuss mailing list.
- I'm unable to figure out how to get the path to the compiler prefix which should be used for cross-compilation. Bazel has rich platform support which I would like to leverage, but the only way I've been able to get cross-compilation to work at all has been to hard-code the cross-compiler to use. (Cross-compilation works well for cc_library targets)
- Adding paths for imported libraries. I have a trivial version-string header file which is built using a genrule(). The output of the genrule is stuffed somewhere in the execroot of the build sandbox. However, I'm unable to reasonably include the header file. The built header file gets put in a path which isn't readily available. Trying to pass it in through an environment variable using $(execpath) results in bazel complaining about the output type of the genrule:
Error: <output file target //usfp-firewall/kernel/usfp_rh:version_gen.h> doesn't contain declared provider 'CcInfo' Attempting to resolve this by wrapping the output of the genrule() in a cc_library() statement using either hdrs or textual_hdrs results in an error: in make rule //usfp-firewall/kernel/usfp_rh:usfp_kernel: label '//usfp-firewall/kernel/usfp_rh:version_header' in $(location) expression expands to no files
For your first issue (extracting the path to the kernel source tree), see BUILD.openssl.bazel, which employs dirname
For your first issue (extracting the path to the kernel source tree), see BUILD.openssl.bazel, which employs
dirname
This is helpful and gets me closer. However, I'm left getting "label '//usfp-firewall:NPU_kernel_src' in $(location) expression expands to no files". Perhaps this doesn't handle tracking the output of other rules going through cc_library textual_hdrs?
Could you share the content of your BUILD file(s) here so i can take a look?
Could you try wrapping the output of the genrule in a cc_import rule?
Could you try wrapping the output of the genrule in a cc_import rule?
I've tried several variations on the theme without success. Here's a trimmed-down version of my current BUILD file:
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@rules_foreign_cc//foreign_cc:defs.bzl", "make", "configure_make")
package(default_visibility = ["//visibility:public"])
#Existing build system substitutes in the git HEAD version - using a fixed string for now.
genrule(
name = "generate_version",
srcs = ["version_gen.h.in"],
outs = ["version_gen.h"],
cmd_bash = 'sed "s/##USFP_RH_VERSION/git-built/" "$<" > "$@"',
)
cc_library(
name = "version_header",
hdrs = [":generate_version"],
)
filegroup(
name = "usfp_kernel_filegroup",
srcs = glob(["*"], exclude = [".git/**"]),
)
make (
name = "usfp_kernel",
lib_source = ":usfp_kernel_filegroup",
# Ideally, we'd list the kernel modules as libraries, but bazel doesn't
# like their extension.
out_bin_dir = ".",
out_binaries = ["usfp.ko"],
target_compatible_with = ["@platforms//cpu:arm64",],
targets = ["default",],
args = [
"-f", "Makefile.kbuild",
],
deps = [
":version_header",
],
env = {
"VERSION_HEADER_LOCATION" : "$(dirname $(execpath :version_header))",
# Other hardcoded directory locations while I try to get this to work.
},
)
Does the following work?
"VERSION_HEADER_LOCATION" : "$(dirname $(execpath :generate_version))"
And change the deps attribute to build_data:
build_data = [":generate_version"]
I'm stuck on version 0.2.0 for reasons logged in ticket 715; build_data is not available for make in this version. If I have ":generate_version" in the deps list, I get the error about (rule 'genrule') doesn't contain declared provider 'CcInfo' If I don't, I get the error that "label '//usfp-firewall/kernel/usfp_rh:generate_version' in $(location) expression is not a declared prerequisite of this rule"
Ah ok, it seems like your only option is to use the deps attribute, which requires a CcInfo provider, which cc_import or cc_library should provide.
not sure why the code you provided here doesn’t work
Perhaps try:
env = {
"VERSION_HEADER_LOCATION" : “$EXT_BUILD_DEPS/version_header“
},
As a follow-up, my work-around for this and similar other issues is to create a separate Makefile (typically Makefile.bazel) and perform all of the required tasks therein. This provides flexibility like genrule() while still exporting the required environment variables to ensure PATHs, compilers, etc., are used.
This issue has been automatically marked as stale because it has not had any activity for 180 days. It will be closed if no further activity occurs in 30 days. Collaborators can add an assignee to keep this open indefinitely. Thanks for your contributions to rules_foreign_cc!
This issue was automatically closed because it went 30 days without a reply since it was labeled "Can Close?"