rules_foreign_cc icon indicating copy to clipboard operation
rules_foreign_cc copied to clipboard

Request for example use case of wrapping out-of-tree linux kernel module compilation.

Open garrettkajmowicz-sophos opened this issue 4 years ago • 11 comments
trafficstars

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

garrettkajmowicz-sophos avatar Aug 12 '21 16:08 garrettkajmowicz-sophos

For your first issue (extracting the path to the kernel source tree), see BUILD.openssl.bazel, which employs dirname

jheaff1 avatar Aug 12 '21 20:08 jheaff1

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?

garrettkajmowicz-sophos avatar Aug 13 '21 12:08 garrettkajmowicz-sophos

Could you share the content of your BUILD file(s) here so i can take a look?

jheaff1 avatar Aug 13 '21 12:08 jheaff1

Could you try wrapping the output of the genrule in a cc_import rule?

jheaff1 avatar Aug 13 '21 12:08 jheaff1

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.
    },
)

garrettkajmowicz-sophos avatar Aug 13 '21 13:08 garrettkajmowicz-sophos

Does the following work?

"VERSION_HEADER_LOCATION" : "$(dirname $(execpath :generate_version))"

And change the deps attribute to build_data:

build_data = [":generate_version"]

jheaff1 avatar Aug 13 '21 15:08 jheaff1

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"

garrettkajmowicz-sophos avatar Aug 13 '21 16:08 garrettkajmowicz-sophos

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

jheaff1 avatar Aug 13 '21 17:08 jheaff1

Perhaps try:

env = {
        "VERSION_HEADER_LOCATION" : “$EXT_BUILD_DEPS/version_header“
    },

jheaff1 avatar Aug 13 '21 18:08 jheaff1

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.

garrettkajmowicz-sophos avatar Jan 13 '22 15:01 garrettkajmowicz-sophos

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!

github-actions[bot] avatar Jul 12 '22 22:07 github-actions[bot]

This issue was automatically closed because it went 30 days without a reply since it was labeled "Can Close?"

github-actions[bot] avatar Aug 11 '22 22:08 github-actions[bot]