blob: c0634563ca9bc8620688f1d7fabf76aa8dd73a37 [file] [log] [blame]
# Copyright (C) 2022 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Rules for defining a DDK (Driver Development Kit) submodule."""
load(":ddk/ddk_conditional_filegroup.bzl", "flatten_conditional_srcs")
load(":ddk/makefiles.bzl", "makefiles")
visibility("//build/kernel/kleaf/...")
def ddk_submodule(
name,
out,
srcs = None,
deps = None,
hdrs = None,
includes = None,
local_defines = None,
copts = None,
removed_copts = None,
asopts = None,
linkopts = None,
conditional_srcs = None,
crate_root = None,
autofdo_profile = None,
debug_info_for_profiling = None,
**kwargs):
"""Declares a DDK (Driver Development Kit) submodule.
Symbol dependencies between submodules in the same [`ddk_module`](#ddk_module)
are not specified explicitly. This is convenient when you have multiple module
files for a subsystem.
See [Building External Modules](https://www.kernel.org/doc/Documentation/kbuild/modules.rst)
or `Documentation/kbuild/modules.rst`, section "6.3 Symbols From Another External Module",
"Use a top-level kbuild file".
Example:
```
ddk_submodule(
name = "a",
out = "a.ko",
srcs = ["a.c"],
)
ddk_submodule(
name = "b",
out = "b.ko",
srcs = ["b_1.c", "b_2.c"],
)
ddk_module(
name = "mymodule",
kernel_build = ":tuna",
deps = [":a", ":b"],
)
```
`linux_includes` must be specified in the top-level `ddk_module`; see
[`ddk_module.linux_includes`](#ddk_module-linux_includes).
`ddk_submodule` should avoid depending on `ddk_headers` that has
`linux_includes`. See the Submodules section in [`ddk_module`](#ddk_module)
for best practices.
**Ordering of `includes`**
See [`ddk_module`](#ddk_module).
**Caveats**
As an implementation detail, `ddk_submodule` alone does not build any modules. The
`ddk_module` target is the one responsible for building all `.ko` files.
A side effect is that for incremental builds, modules may be rebuilt unexpectedly.
In the above example,
if `a.c` is modified, the whole `mymodule` is rebuilt, causing both `a.ko` and `b.ko` to
be rebuilt. Because `ddk_module` is always built in a sandbox, the object files (`*.o`) for
`b.ko` is not cached.
Hence, it is always recommended to use one `ddk_module` per module (`.ko` file). You may
use `build/kernel/kleaf/build_cleaner.py` to resolve dependencies; see
`build/kernel/kleaf/docs/build_cleaner.md`.
The `ddk_submodule` rule should only be used when the dependencies among modules are too
complicated to be presented in `BUILD.bazel`, and are frequently updated. When the
dependencies are stable, it is recommended to:
1. Replace `ddk_submodule` with `ddk_module`;
2. Specify dependencies in the `deps` attribute explicitly.
Args:
name: See [`ddk_module.name`](#ddk_module-name).
srcs: See [`ddk_module.srcs`](#ddk_module-srcs).
conditional_srcs: See [`ddk_module.conditional_srcs`](#ddk_module-conditional_srcs).
crate_root: See [`ddk_module.crate_root`](#ddk_module-crate_root).
out: See [`ddk_module.out`](#ddk_module-out).
hdrs: See [`ddk_module.hdrs`](#ddk_module-hdrs).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
These are exported to downstream targets that depends on the
`ddk_module` that includes the current target. Example:
```
ddk_submodule(name = "module_parent_a", hdrs = [...])
ddk_module(name = "module_parent", deps = [":module_parent_a"])
ddk_module(name = "module_child", deps = [":module_parent"])
```
`module_child` automatically gets `hdrs` of `module_parent_a`.
deps: See [`ddk_module.deps`](#ddk_module-deps).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
These are not exported to downstream targets that depends on the
`ddk_module` that includes the current target.
includes: See [`ddk_module.includes`](#ddk_module-includes).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
These are exported to downstream targets that depends on the
`ddk_module` that includes the current target. Example:
```
ddk_submodule(name = "module_parent_a", includes = [...])
ddk_module(name = "module_parent", deps = [":module_parent_a"])
ddk_module(name = "module_child", deps = [":module_parent"])
```
`module_child` automatically gets `includes` of `module_parent_a`.
local_defines: See [`ddk_module.local_defines`](#ddk_module-local_defines).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
These are not exported to downstream targets that depends on the
`ddk_module` that includes the current target.
copts: See [`ddk_module.copts`](#ddk_module-copts).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
These are not exported to downstream targets that depends on the
`ddk_module` that includes the current target.
removed_copts: See [`ddk_module.removed_copts`](#ddk_module-removed_copts).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
These are not exported to downstream targets that depends on the
`ddk_module` that includes the current target.
asopts: See [`ddk_module.asopts`](#ddk_module-asopts).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
These are not exported to downstream targets that depends on the
`ddk_module` that includes the current target.
linkopts: See [`ddk_module.linkopts`](#ddk_module-linkopts).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
These are not exported to downstream targets that depends on the
`ddk_module` that includes the current target.
autofdo_profile: See [`ddk_module.autofdo_profile`](#ddk_module-autofdo_profile).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
debug_info_for_profiling: See [`ddk_module.debug_info_for_profiling`](#ddk_module-debug_info_for_profiling).
These are only effective in the current submodule, not other submodules declared in the
same [`ddk_module.deps`](#ddk_module-deps).
**kwargs: Additional attributes to the internal rule, e.g.
[`visibility`](https://docs.bazel.build/versions/main/visibility.html).
See complete list
[here](https://docs.bazel.build/versions/main/be/common-definitions.html#common-attributes).
"""
private_kwargs = dict(kwargs)
private_kwargs["visibility"] = ["//visibility:private"]
flattened_conditional_srcs = flatten_conditional_srcs(
module_name = name,
conditional_srcs = conditional_srcs,
**private_kwargs
)
makefiles(
name = name,
module_srcs = (srcs or []) + flattened_conditional_srcs,
module_crate_root = crate_root,
module_hdrs = hdrs,
module_includes = includes,
module_out = out,
module_deps = deps,
module_local_defines = local_defines,
module_copts = copts,
module_removed_copts = removed_copts,
module_asopts = asopts,
module_linkopts = linkopts,
module_autofdo_profile = autofdo_profile,
module_debug_info_for_profiling = debug_info_for_profiling,
target_type = "submodule",
top_level_makefile = False,
kbuild_has_linux_include = False,
**kwargs
)