1# SPDX-License-Identifier: GPL-2.0 2 3# Where to place rustdoc generated documentation 4rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc 5 6obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o 7always-$(CONFIG_RUST) += exports_core_generated.h 8 9# Missing prototypes are expected in the helpers since these are exported 10# for Rust only, thus there is no header nor prototypes. 11obj-$(CONFIG_RUST) += helpers/helpers.o 12CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations 13 14always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs 15obj-$(CONFIG_RUST) += bindings.o pin_init.o kernel.o 16always-$(CONFIG_RUST) += exports_helpers_generated.h \ 17 exports_bindings_generated.h exports_kernel_generated.h 18 19always-$(CONFIG_RUST) += uapi/uapi_generated.rs 20obj-$(CONFIG_RUST) += uapi.o 21 22ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW 23obj-$(CONFIG_RUST) += build_error.o 24else 25always-$(CONFIG_RUST) += build_error.o 26endif 27 28obj-$(CONFIG_RUST) += exports.o 29 30always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib libsyn.rlib 31 32always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs 33always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c 34 35obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.o 36obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o 37 38always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs 39ifndef CONFIG_UML 40always-$(subst y,$(CONFIG_RUST),$(CONFIG_BUG)) += kernel/generated_arch_warn_asm.rs kernel/generated_arch_reachable_asm.rs 41endif 42 43# Avoids running `$(RUSTC)` when it may not be available. 44ifdef CONFIG_RUST 45 46libmacros_name := $(shell MAKEFLAGS= $(RUSTC) --print file-names --crate-name macros --crate-type proc-macro - </dev/null) 47libmacros_extension := $(patsubst libmacros.%,%,$(libmacros_name)) 48 49libpin_init_internal_name := $(shell MAKEFLAGS= $(RUSTC) --print file-names --crate-name pin_init_internal --crate-type proc-macro - </dev/null) 50libpin_init_internal_extension := $(patsubst libpin_init_internal.%,%,$(libpin_init_internal_name)) 51 52always-$(CONFIG_RUST) += $(libmacros_name) $(libpin_init_internal_name) 53 54# `$(rust_flags)` is passed in case the user added `--sysroot`. 55rustc_sysroot := $(shell MAKEFLAGS= $(RUSTC) $(rust_flags) --print sysroot) 56rustc_host_target := $(shell $(RUSTC) --version --verbose | grep -F 'host: ' | cut -d' ' -f2) 57RUST_LIB_SRC ?= $(rustc_sysroot)/lib/rustlib/src/rust/library 58 59ifneq ($(quiet),) 60rust_test_quiet=-q 61rustdoc_test_quiet=--test-args -q 62rustdoc_test_kernel_quiet=>/dev/null 63endif 64 65cfgs-to-flags = $(patsubst %,--cfg='%',$1) 66 67core-cfgs := \ 68 no_fp_fmt_parse 69 70core-edition := $(if $(call rustc-min-version,108700),2024,2021) 71 72core-skip_flags := \ 73 --edition=2021 \ 74 -Wunreachable_pub \ 75 -Wrustdoc::unescaped_backticks 76 77core-flags := \ 78 --edition=$(core-edition) \ 79 $(call cfgs-to-flags,$(core-cfgs)) 80 81proc_macro2-cfgs := \ 82 feature="proc-macro" \ 83 wrap_proc_macro \ 84 $(if $(call rustc-min-version,108800),proc_macro_span_file proc_macro_span_location) 85 86# Stable since Rust 1.79.0: `feature(proc_macro_byte_character,proc_macro_c_str_literals)`. 87proc_macro2-flags := \ 88 --cap-lints=allow \ 89 -Zcrate-attr='feature(proc_macro_byte_character,proc_macro_c_str_literals)' \ 90 $(call cfgs-to-flags,$(proc_macro2-cfgs)) 91 92quote-cfgs := \ 93 feature="proc-macro" 94 95quote-skip_flags := \ 96 --edition=2021 97 98quote-flags := \ 99 --edition=2018 \ 100 --cap-lints=allow \ 101 --extern proc_macro2 \ 102 $(call cfgs-to-flags,$(quote-cfgs)) 103 104# `extra-traits`, `fold` and `visit` may be enabled if needed. 105syn-cfgs := \ 106 feature="clone-impls" \ 107 feature="derive" \ 108 feature="full" \ 109 feature="parsing" \ 110 feature="printing" \ 111 feature="proc-macro" \ 112 feature="visit-mut" 113 114syn-flags := \ 115 --cap-lints=allow \ 116 --extern proc_macro2 \ 117 --extern quote \ 118 $(call cfgs-to-flags,$(syn-cfgs)) 119 120# `rustdoc` did not save the target modifiers, thus workaround for 121# the time being (https://github.com/rust-lang/rust/issues/144521). 122rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-allow-abi-mismatch=fixed-x18) 123 124# Similarly, for doctests (https://github.com/rust-lang/rust/issues/146465). 125doctests_modifiers_workaround := $(rustdoc_modifiers_workaround)$(if $(call rustc-min-version,109100),$(comma)sanitizer) 126 127# `rustc` recognizes `--remap-path-prefix` since 1.26.0, but `rustdoc` only 128# since Rust 1.81.0. Moreover, `rustdoc` ICEs on out-of-tree builds since Rust 129# 1.82.0 (https://github.com/rust-lang/rust/issues/138520). Thus workaround both 130# issues skipping the flag. The former also applies to `RUSTDOC TK`. 131quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< 132 cmd_rustdoc = \ 133 OBJTREE=$(abspath $(objtree)) \ 134 $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \ 135 $(rustc_target_flags) -L$(objtree)/$(obj) \ 136 -Zunstable-options --generate-link-to-definition \ 137 --output $(rustdoc_output) \ 138 --crate-name $(subst rustdoc-,,$@) \ 139 $(rustdoc_modifiers_workaround) \ 140 $(if $(rustdoc_host),,--sysroot=/dev/null) \ 141 @$(objtree)/include/generated/rustc_cfg $< 142 143# The `html_logo_url` and `html_favicon_url` forms of the `doc` attribute 144# can be used to specify a custom logo. However: 145# - The given value is used as-is, thus it cannot be relative or a local file 146# (unlike the non-custom case) since the generated docs have subfolders. 147# - It requires adding it to every crate. 148# - It requires changing `core` which comes from the sysroot. 149# 150# Using `-Zcrate-attr` would solve the last two points, but not the first. 151# The https://github.com/rust-lang/rfcs/pull/3226 RFC suggests two new 152# command-like flags to solve the issue. Meanwhile, we use the non-custom case 153# and then retouch the generated files. 154rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \ 155 rustdoc-kernel rustdoc-pin_init 156 $(Q)grep -Ehro '<a href="srctree/([^"]+)"' $(rustdoc_output) | \ 157 cut -d'"' -f2 | cut -d/ -f2- | while read f; do \ 158 if [ ! -e "$(srctree)/$$f" ]; then \ 159 echo "warning: srctree/ link to $$f does not exist"; \ 160 fi \ 161 done 162 $(Q)cp $(srctree)/Documentation/images/logo.svg $(rustdoc_output)/static.files/ 163 $(Q)cp $(srctree)/Documentation/images/COPYING-logo $(rustdoc_output)/static.files/ 164 $(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed -Ei \ 165 -e 's:rust-logo-[0-9a-f]+\.svg:logo.svg:g' \ 166 -e 's:favicon-[0-9a-f]+\.svg:logo.svg:g' \ 167 -e 's:<link rel="alternate icon" type="image/png" href="[/.]+/static\.files/favicon-(16x16|32x32)-[0-9a-f]+\.png">::g' \ 168 -e 's:<a href="srctree/([^"]+)">:<a href="$(realpath $(srctree))/\1">:g' 169 $(Q)for f in $(rustdoc_output)/static.files/rustdoc-*.css; do \ 170 echo ".logo-container > img { object-fit: contain; }" >> $$f; done 171 172rustdoc-proc_macro2: private rustdoc_host = yes 173rustdoc-proc_macro2: private rustc_target_flags = $(proc_macro2-flags) 174rustdoc-proc_macro2: $(src)/proc-macro2/lib.rs rustdoc-clean FORCE 175 +$(call if_changed,rustdoc) 176 177rustdoc-quote: private rustdoc_host = yes 178rustdoc-quote: private rustc_target_flags = $(quote-flags) 179rustdoc-quote: private skip_flags = $(quote-skip_flags) 180rustdoc-quote: $(src)/quote/lib.rs rustdoc-clean rustdoc-proc_macro2 FORCE 181 +$(call if_changed,rustdoc) 182 183rustdoc-syn: private rustdoc_host = yes 184rustdoc-syn: private rustc_target_flags = $(syn-flags) 185rustdoc-syn: $(src)/syn/lib.rs rustdoc-clean rustdoc-quote FORCE 186 +$(call if_changed,rustdoc) 187 188rustdoc-macros: private rustdoc_host = yes 189rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \ 190 --extern proc_macro --extern proc_macro2 --extern quote --extern syn 191rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 \ 192 rustdoc-quote rustdoc-syn FORCE 193 +$(call if_changed,rustdoc) 194 195# Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should 196# not be needed -- see https://github.com/rust-lang/rust/pull/128307. 197rustdoc-core: private skip_flags = $(core-skip_flags) 198rustdoc-core: private rustc_target_flags = $(core-flags) 199rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs rustdoc-clean FORCE 200 +$(call if_changed,rustdoc) 201 202# Even if `rustdoc` targets are not kernel objects, they should still be 203# treated as such so that we pass the same flags. Otherwise, for instance, 204# `rustdoc` will complain about missing sanitizer flags causing an ABI mismatch. 205rustdoc-compiler_builtins: private is-kernel-object := y 206rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE 207 +$(call if_changed,rustdoc) 208 209rustdoc-ffi: private is-kernel-object := y 210rustdoc-ffi: $(src)/ffi.rs rustdoc-core FORCE 211 +$(call if_changed,rustdoc) 212 213rustdoc-pin_init_internal: private rustdoc_host = yes 214rustdoc-pin_init_internal: private rustc_target_flags = --cfg kernel \ 215 --extern proc_macro --crate-type proc-macro 216rustdoc-pin_init_internal: $(src)/pin-init/internal/src/lib.rs \ 217 rustdoc-clean FORCE 218 +$(call if_changed,rustdoc) 219 220rustdoc-pin_init: private rustdoc_host = yes 221rustdoc-pin_init: private rustc_target_flags = --extern pin_init_internal \ 222 --extern macros --extern alloc --cfg kernel --cfg feature=\"alloc\" 223rustdoc-pin_init: $(src)/pin-init/src/lib.rs rustdoc-pin_init_internal \ 224 rustdoc-macros FORCE 225 +$(call if_changed,rustdoc) 226 227rustdoc-kernel: private is-kernel-object := y 228rustdoc-kernel: private rustc_target_flags = --extern ffi --extern pin_init \ 229 --extern build_error --extern macros \ 230 --extern bindings --extern uapi 231rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-ffi rustdoc-macros \ 232 rustdoc-pin_init rustdoc-compiler_builtins $(obj)/$(libmacros_name) \ 233 $(obj)/bindings.o FORCE 234 +$(call if_changed,rustdoc) 235 236rustdoc-clean: FORCE 237 $(Q)rm -rf $(rustdoc_output) 238 239quiet_cmd_rustc_test_library = $(RUSTC_OR_CLIPPY_QUIET) TL $< 240 cmd_rustc_test_library = \ 241 OBJTREE=$(abspath $(objtree)) \ 242 $(RUSTC_OR_CLIPPY) $(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \ 243 @$(objtree)/include/generated/rustc_cfg \ 244 --crate-type $(if $(rustc_test_library_proc),proc-macro,rlib) \ 245 --out-dir $(objtree)/$(obj)/test --cfg testlib \ 246 -L$(objtree)/$(obj)/test \ 247 --crate-name $(subst rusttest-,,$(subst rusttestlib-,,$@)) $< 248 249rusttestlib-build_error: $(src)/build_error.rs FORCE 250 +$(call if_changed,rustc_test_library) 251 252rusttestlib-ffi: $(src)/ffi.rs FORCE 253 +$(call if_changed,rustc_test_library) 254 255rusttestlib-proc_macro2: private rustc_target_flags = $(proc_macro2-flags) 256rusttestlib-proc_macro2: $(src)/proc-macro2/lib.rs FORCE 257 +$(call if_changed,rustc_test_library) 258 259rusttestlib-quote: private skip_flags = $(quote-skip_flags) 260rusttestlib-quote: private rustc_target_flags = $(quote-flags) 261rusttestlib-quote: $(src)/quote/lib.rs rusttestlib-proc_macro2 FORCE 262 +$(call if_changed,rustc_test_library) 263 264rusttestlib-syn: private rustc_target_flags = $(syn-flags) 265rusttestlib-syn: $(src)/syn/lib.rs rusttestlib-quote FORCE 266 +$(call if_changed,rustc_test_library) 267 268rusttestlib-macros: private rustc_target_flags = --extern proc_macro \ 269 --extern proc_macro2 --extern quote --extern syn 270rusttestlib-macros: private rustc_test_library_proc = yes 271rusttestlib-macros: $(src)/macros/lib.rs \ 272 rusttestlib-proc_macro2 rusttestlib-quote rusttestlib-syn FORCE 273 +$(call if_changed,rustc_test_library) 274 275rusttestlib-pin_init_internal: private rustc_target_flags = --cfg kernel \ 276 --extern proc_macro 277rusttestlib-pin_init_internal: private rustc_test_library_proc = yes 278rusttestlib-pin_init_internal: $(src)/pin-init/internal/src/lib.rs FORCE 279 +$(call if_changed,rustc_test_library) 280 281rusttestlib-pin_init: private rustc_target_flags = --extern pin_init_internal \ 282 --extern macros --cfg kernel 283rusttestlib-pin_init: $(src)/pin-init/src/lib.rs rusttestlib-macros \ 284 rusttestlib-pin_init_internal $(obj)/$(libpin_init_internal_name) FORCE 285 +$(call if_changed,rustc_test_library) 286 287rusttestlib-kernel: private rustc_target_flags = --extern ffi \ 288 --extern build_error --extern macros --extern pin_init \ 289 --extern bindings --extern uapi 290rusttestlib-kernel: $(src)/kernel/lib.rs rusttestlib-bindings rusttestlib-uapi \ 291 rusttestlib-build_error rusttestlib-pin_init $(obj)/$(libmacros_name) \ 292 $(obj)/bindings.o FORCE 293 +$(call if_changed,rustc_test_library) 294 295rusttestlib-bindings: private rustc_target_flags = --extern ffi --extern pin_init 296rusttestlib-bindings: $(src)/bindings/lib.rs rusttestlib-ffi rusttestlib-pin_init FORCE 297 +$(call if_changed,rustc_test_library) 298 299rusttestlib-uapi: private rustc_target_flags = --extern ffi --extern pin_init 300rusttestlib-uapi: $(src)/uapi/lib.rs rusttestlib-ffi rusttestlib-pin_init FORCE 301 +$(call if_changed,rustc_test_library) 302 303quiet_cmd_rustdoc_test = RUSTDOC T $< 304 cmd_rustdoc_test = \ 305 RUST_MODFILE=test.rs \ 306 OBJTREE=$(abspath $(objtree)) \ 307 $(RUSTDOC) --test $(rust_common_flags) \ 308 -Zcrate-attr='feature(used_with_arg)' \ 309 @$(objtree)/include/generated/rustc_cfg \ 310 $(rustc_target_flags) $(rustdoc_test_target_flags) \ 311 $(rustdoc_test_quiet) \ 312 -L$(objtree)/$(obj)/test --output $(rustdoc_output) \ 313 --crate-name $(subst rusttest-,,$@) $< 314 315quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $< 316 cmd_rustdoc_test_kernel = \ 317 rm -rf $(objtree)/$(obj)/test/doctests/kernel; \ 318 mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \ 319 OBJTREE=$(abspath $(objtree)) \ 320 $(RUSTDOC) --test $(filter-out --remap-path-prefix=%,$(rust_flags)) \ 321 -L$(objtree)/$(obj) --extern ffi --extern pin_init \ 322 --extern kernel --extern build_error --extern macros \ 323 --extern bindings --extern uapi \ 324 --no-run --crate-name kernel -Zunstable-options \ 325 --sysroot=/dev/null \ 326 $(doctests_modifiers_workaround) \ 327 --test-builder $(objtree)/scripts/rustdoc_test_builder \ 328 $< $(rustdoc_test_kernel_quiet); \ 329 $(objtree)/scripts/rustdoc_test_gen 330 331%/doctests_kernel_generated.rs %/doctests_kernel_generated_kunit.c: \ 332 $(src)/kernel/lib.rs $(obj)/kernel.o \ 333 $(objtree)/scripts/rustdoc_test_builder \ 334 $(objtree)/scripts/rustdoc_test_gen FORCE 335 +$(call if_changed,rustdoc_test_kernel) 336 337# We cannot use `-Zpanic-abort-tests` because some tests are dynamic, 338# so for the moment we skip `-Cpanic=abort`. 339quiet_cmd_rustc_test = $(RUSTC_OR_CLIPPY_QUIET) T $< 340 cmd_rustc_test = \ 341 OBJTREE=$(abspath $(objtree)) \ 342 $(RUSTC_OR_CLIPPY) --test $(rust_common_flags) \ 343 @$(objtree)/include/generated/rustc_cfg \ 344 $(rustc_target_flags) --out-dir $(objtree)/$(obj)/test \ 345 -L$(objtree)/$(obj)/test \ 346 --crate-name $(subst rusttest-,,$@) $<; \ 347 $(objtree)/$(obj)/test/$(subst rusttest-,,$@) $(rust_test_quiet) \ 348 $(rustc_test_run_flags) 349 350rusttest: rusttest-macros 351 352rusttest-macros: private rustc_target_flags = --extern proc_macro \ 353 --extern macros --extern kernel --extern pin_init \ 354 --extern proc_macro2 --extern quote --extern syn 355rusttest-macros: private rustdoc_test_target_flags = --crate-type proc-macro 356rusttest-macros: $(src)/macros/lib.rs \ 357 rusttestlib-macros rusttestlib-kernel rusttestlib-pin_init FORCE 358 +$(call if_changed,rustc_test) 359 +$(call if_changed,rustdoc_test) 360 361ifdef CONFIG_CC_IS_CLANG 362bindgen_c_flags = $(c_flags) 363else 364# bindgen relies on libclang to parse C. Ideally, bindgen would support a GCC 365# plugin backend and/or the Clang driver would be perfectly compatible with GCC. 366# 367# For the moment, here we are tweaking the flags on the fly. This is a hack, 368# and some kernel configurations may not work (e.g. `GCC_PLUGIN_RANDSTRUCT` 369# if we end up using one of those structs). 370bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \ 371 -mskip-rax-setup -mgeneral-regs-only -msign-return-address=% \ 372 -mindirect-branch=thunk-extern -mindirect-branch-register \ 373 -mfunction-return=thunk-extern -mrecord-mcount -mabi=lp64 \ 374 -mindirect-branch-cs-prefix -mstack-protector-guard% -mtraceback=no \ 375 -mno-pointers-to-nested-functions -mno-string \ 376 -mno-strict-align -mstrict-align -mdirect-extern-access \ 377 -mexplicit-relocs -mno-check-zero-division \ 378 -fconserve-stack -falign-jumps=% -falign-loops=% \ 379 -femit-struct-debug-baseonly -fno-ipa-cp-clone -fno-ipa-sra \ 380 -fno-partial-inlining -fplugin-arg-arm_ssp_per_task_plugin-% \ 381 -fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \ 382 -fzero-call-used-regs=% -fno-stack-clash-protection \ 383 -fno-inline-functions-called-once -fsanitize=bounds-strict \ 384 -fstrict-flex-arrays=% -fmin-function-alignment=% \ 385 -fzero-init-padding-bits=% -mno-fdpic \ 386 --param=% --param asan-% -fno-isolate-erroneous-paths-dereference 387 388# Derived from `scripts/Makefile.clang`. 389BINDGEN_TARGET_x86 := x86_64-linux-gnu 390BINDGEN_TARGET_arm64 := aarch64-linux-gnu 391BINDGEN_TARGET_arm := arm-linux-gnueabi 392BINDGEN_TARGET_loongarch := loongarch64-linux-gnusf 393BINDGEN_TARGET_um := $(BINDGEN_TARGET_$(SUBARCH)) 394BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH)) 395 396# All warnings are inhibited since GCC builds are very experimental, 397# many GCC warnings are not supported by Clang, they may only appear in 398# some configurations, with new GCC versions, etc. 399bindgen_extra_c_flags = -w --target=$(BINDGEN_TARGET) 400 401# Auto variable zero-initialization requires an additional special option with 402# clang that is going to be removed sometime in the future (likely in 403# clang-18), so make sure to pass this option only if clang supports it 404# (libclang major version < 16). 405# 406# https://github.com/llvm/llvm-project/issues/44842 407# https://github.com/llvm/llvm-project/blob/llvmorg-16.0.0-rc2/clang/docs/ReleaseNotes.rst#deprecated-compiler-flags 408ifdef CONFIG_INIT_STACK_ALL_ZERO 409libclang_maj_ver=$(shell $(BINDGEN) $(srctree)/scripts/rust_is_available_bindgen_libclang.h 2>&1 | sed -ne 's/.*clang version \([0-9]*\).*/\1/p') 410ifeq ($(shell expr $(libclang_maj_ver) \< 16), 1) 411bindgen_extra_c_flags += -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang 412endif 413endif 414 415bindgen_c_flags = $(filter-out $(bindgen_skip_c_flags), $(c_flags)) \ 416 $(bindgen_extra_c_flags) 417endif 418 419ifdef CONFIG_LTO 420bindgen_c_flags_lto = $(filter-out $(CC_FLAGS_LTO), $(bindgen_c_flags)) 421else 422bindgen_c_flags_lto = $(bindgen_c_flags) 423endif 424 425# `-fno-builtin` is passed to avoid `bindgen` from using `clang` builtin 426# prototypes for functions like `memcpy` -- if this flag is not passed, 427# `bindgen`-generated prototypes use `c_ulong` or `c_uint` depending on 428# architecture instead of generating `usize`. 429bindgen_c_flags_final = $(bindgen_c_flags_lto) -fno-builtin -D__BINDGEN__ 430 431# Each `bindgen` release may upgrade the list of Rust target versions. By 432# default, the highest stable release in their list is used. Thus we need to set 433# a `--rust-target` to avoid future `bindgen` releases emitting code that 434# `rustc` may not understand. On top of that, `bindgen` does not support passing 435# an unknown Rust target version. 436# 437# Therefore, the Rust target for `bindgen` can be only as high as the minimum 438# Rust version the kernel supports and only as high as the greatest stable Rust 439# target supported by the minimum `bindgen` version the kernel supports (that 440# is, if we do not test the actual `rustc`/`bindgen` versions running). 441# 442# Starting with `bindgen` 0.71.0, we will be able to set any future Rust version 443# instead, i.e. we will be able to set here our minimum supported Rust version. 444quiet_cmd_bindgen = BINDGEN $@ 445 cmd_bindgen = \ 446 $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.68 \ 447 --use-core --with-derive-default --ctypes-prefix ffi --no-layout-tests \ 448 --no-debug '.*' --enable-function-attribute-detection \ 449 -o $@ -- $(bindgen_c_flags_final) -DMODULE \ 450 $(bindgen_target_cflags) $(bindgen_target_extra) 451 452$(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \ 453 $(shell grep -Ev '^#|^$$' $(src)/bindgen_parameters) 454$(obj)/bindings/bindings_generated.rs: private bindgen_target_extra = ; \ 455 sed -Ei 's/pub const RUST_CONST_HELPER_([a-zA-Z0-9_]*)/pub const \1/g' $@ 456$(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \ 457 $(src)/bindgen_parameters FORCE 458 $(call if_changed_dep,bindgen) 459 460$(obj)/uapi/uapi_generated.rs: private bindgen_target_flags = \ 461 $(shell grep -Ev '^#|^$$' $(src)/bindgen_parameters) 462$(obj)/uapi/uapi_generated.rs: $(src)/uapi/uapi_helper.h \ 463 $(src)/bindgen_parameters FORCE 464 $(call if_changed_dep,bindgen) 465 466# See `CFLAGS_REMOVE_helpers.o` above. In addition, Clang on C does not warn 467# with `-Wmissing-declarations` (unlike GCC), so it is not strictly needed here 468# given it is `libclang`; but for consistency, future Clang changes and/or 469# a potential future GCC backend for `bindgen`, we disable it too. 470$(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_flags = \ 471 --blocklist-type '.*' --allowlist-var '' \ 472 --allowlist-function 'rust_helper_.*' 473$(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_cflags = \ 474 -I$(objtree)/$(obj) -Wno-missing-prototypes -Wno-missing-declarations 475$(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_extra = ; \ 476 sed -Ei 's/pub fn rust_helper_([a-zA-Z0-9_]*)/#[link_name="rust_helper_\1"]\n pub fn \1/g' $@ 477$(obj)/bindings/bindings_helpers_generated.rs: $(src)/helpers/helpers.c FORCE 478 $(call if_changed_dep,bindgen) 479 480rust_exports = $(NM) -p --defined-only $(1) | awk '$$2~/(T|R|D|B)/ && $$3!~/__(pfx|cfi|odr_asan)/ { printf $(2),$$3 }' 481 482quiet_cmd_exports = EXPORTS $@ 483 cmd_exports = \ 484 $(call rust_exports,$<,"EXPORT_SYMBOL_RUST_GPL(%s);\n") > $@ 485 486$(obj)/exports_core_generated.h: $(obj)/core.o FORCE 487 $(call if_changed,exports) 488 489# Even though Rust kernel modules should never use the bindings directly, 490# symbols from the `bindings` crate and the C helpers need to be exported 491# because Rust generics and inlined functions may not get their code generated 492# in the crate where they are defined. Other helpers, called from non-inline 493# functions, may not be exported, in principle. However, in general, the Rust 494# compiler does not guarantee codegen will be performed for a non-inline 495# function either. Therefore, we export all symbols from helpers and bindings. 496# In the future, this may be revisited to reduce the number of exports after 497# the compiler is informed about the places codegen is required. 498$(obj)/exports_helpers_generated.h: $(obj)/helpers/helpers.o FORCE 499 $(call if_changed,exports) 500 501$(obj)/exports_bindings_generated.h: $(obj)/bindings.o FORCE 502 $(call if_changed,exports) 503 504$(obj)/exports_kernel_generated.h: $(obj)/kernel.o FORCE 505 $(call if_changed,exports) 506 507quiet_cmd_rustc_procmacrolibrary = $(RUSTC_OR_CLIPPY_QUIET) PL $@ 508 cmd_rustc_procmacrolibrary = \ 509 $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \ 510 $(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \ 511 --emit=dep-info,link --crate-type rlib -O \ 512 --out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \ 513 --crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<; \ 514 mv $(objtree)/$(obj)/$(patsubst lib%.rlib,%,$(notdir $@)).d $(depfile); \ 515 sed -i '/^\#/d' $(depfile) 516 517$(obj)/libproc_macro2.rlib: private skip_clippy = 1 518$(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags) 519$(obj)/libproc_macro2.rlib: $(src)/proc-macro2/lib.rs FORCE 520 +$(call if_changed_dep,rustc_procmacrolibrary) 521 522$(obj)/libquote.rlib: private skip_clippy = 1 523$(obj)/libquote.rlib: private skip_flags = $(quote-skip_flags) 524$(obj)/libquote.rlib: private rustc_target_flags = $(quote-flags) 525$(obj)/libquote.rlib: $(src)/quote/lib.rs $(obj)/libproc_macro2.rlib FORCE 526 +$(call if_changed_dep,rustc_procmacrolibrary) 527 528$(obj)/libsyn.rlib: private skip_clippy = 1 529$(obj)/libsyn.rlib: private rustc_target_flags = $(syn-flags) 530$(obj)/libsyn.rlib: $(src)/syn/lib.rs $(obj)/libquote.rlib FORCE 531 +$(call if_changed_dep,rustc_procmacrolibrary) 532 533quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ 534 cmd_rustc_procmacro = \ 535 $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \ 536 -Clinker-flavor=gcc -Clinker=$(HOSTCC) \ 537 -Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \ 538 --emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \ 539 --crate-type proc-macro -L$(objtree)/$(obj) \ 540 --crate-name $(patsubst lib%.$(libmacros_extension),%,$(notdir $@)) \ 541 @$(objtree)/include/generated/rustc_cfg $< 542 543# Procedural macros can only be used with the `rustc` that compiled it. 544$(obj)/$(libmacros_name): private rustc_target_flags = \ 545 --extern proc_macro2 --extern quote --extern syn 546$(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \ 547 $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE 548 +$(call if_changed_dep,rustc_procmacro) 549 550$(obj)/$(libpin_init_internal_name): private rustc_target_flags = --cfg kernel 551$(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/lib.rs FORCE 552 +$(call if_changed_dep,rustc_procmacro) 553 554quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@ 555 cmd_rustc_library = \ 556 OBJTREE=$(abspath $(objtree)) \ 557 $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \ 558 $(filter-out $(skip_flags),$(rust_flags)) $(rustc_target_flags) \ 559 --emit=dep-info=$(depfile) --emit=obj=$@ \ 560 --emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \ 561 --crate-type rlib -L$(objtree)/$(obj) \ 562 --crate-name $(patsubst %.o,%,$(notdir $@)) $< \ 563 --sysroot=/dev/null \ 564 $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \ 565 $(cmd_objtool) 566 567rust-analyzer: 568 $(Q)MAKEFLAGS= $(srctree)/scripts/generate_rust_analyzer.py \ 569 --cfgs='core=$(core-cfgs)' $(core-edition) \ 570 --cfgs='proc_macro2=$(proc_macro2-cfgs)' \ 571 --cfgs='quote=$(quote-cfgs)' \ 572 --cfgs='syn=$(syn-cfgs)' \ 573 $(realpath $(srctree)) $(realpath $(objtree)) \ 574 $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \ 575 > rust-project.json 576 577redirect-intrinsics = \ 578 __addsf3 __eqsf2 __extendsfdf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __truncdfsf2 __unordsf2 \ 579 __adddf3 __eqdf2 __ledf2 __ltdf2 __muldf3 __unorddf2 \ 580 __muloti4 __multi3 \ 581 __udivmodti4 __udivti3 __umodti3 582 583ifdef CONFIG_ARM 584 # Add eabi initrinsics for ARM 32-bit 585 redirect-intrinsics += \ 586 __aeabi_fadd __aeabi_fmul __aeabi_fcmpeq __aeabi_fcmple __aeabi_fcmplt __aeabi_fcmpun \ 587 __aeabi_dadd __aeabi_dmul __aeabi_dcmple __aeabi_dcmplt __aeabi_dcmpun \ 588 __aeabi_uldivmod 589endif 590ifneq ($(or $(CONFIG_ARM64),$(and $(CONFIG_RISCV),$(CONFIG_64BIT))),) 591 # These intrinsics are defined for ARM64 and RISCV64 592 redirect-intrinsics += \ 593 __ashrti3 \ 594 __ashlti3 __lshrti3 595endif 596 597ifdef CONFIG_MODVERSIONS 598cmd_gendwarfksyms = $(if $(skip_gendwarfksyms),, \ 599 $(call rust_exports,$@,"%s\n") | \ 600 scripts/gendwarfksyms/gendwarfksyms \ 601 $(if $(KBUILD_GENDWARFKSYMS_STABLE), --stable) \ 602 $(if $(KBUILD_SYMTYPES), --symtypes $(@:.o=.symtypes),) \ 603 $@ >> $(dot-target).cmd) 604endif 605 606define rule_rustc_library 607 $(call cmd_and_fixdep,rustc_library) 608 $(call cmd,gen_objtooldep) 609 $(call cmd,gendwarfksyms) 610endef 611 612define rule_rust_cc_library 613 $(call if_changed_rule,cc_o_c) 614 $(call cmd,force_checksrc) 615 $(call cmd,gendwarfksyms) 616endef 617 618# helpers.o uses the same export mechanism as Rust libraries, so ensure symbol 619# versions are calculated for the helpers too. 620$(obj)/helpers/helpers.o: $(src)/helpers/helpers.c $(recordmcount_source) FORCE 621 +$(call if_changed_rule,rust_cc_library) 622 623# Disable symbol versioning for exports.o to avoid conflicts with the actual 624# symbol versions generated from Rust objects. 625$(obj)/exports.o: private skip_gendwarfksyms = 1 626 627$(obj)/core.o: private skip_clippy = 1 628$(obj)/core.o: private skip_flags = $(core-skip_flags) 629$(obj)/core.o: private rustc_objcopy = $(foreach sym,$(redirect-intrinsics),--redefine-sym $(sym)=__rust$(sym)) 630$(obj)/core.o: private rustc_target_flags = $(core-flags) 631$(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs \ 632 $(wildcard $(objtree)/include/config/RUSTC_VERSION_TEXT) FORCE 633 +$(call if_changed_rule,rustc_library) 634ifneq ($(or $(CONFIG_X86_64),$(CONFIG_X86_32)),) 635$(obj)/core.o: scripts/target.json 636endif 637KCOV_INSTRUMENT_core.o := n 638 639$(obj)/compiler_builtins.o: private skip_gendwarfksyms = 1 640$(obj)/compiler_builtins.o: private rustc_objcopy = -w -W '__*' 641$(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE 642 +$(call if_changed_rule,rustc_library) 643 644$(obj)/pin_init.o: private skip_gendwarfksyms = 1 645$(obj)/pin_init.o: private rustc_target_flags = --extern pin_init_internal \ 646 --extern macros --cfg kernel 647$(obj)/pin_init.o: $(src)/pin-init/src/lib.rs $(obj)/compiler_builtins.o \ 648 $(obj)/$(libpin_init_internal_name) $(obj)/$(libmacros_name) FORCE 649 +$(call if_changed_rule,rustc_library) 650 651# Even if normally `build_error` is not a kernel object, it should still be 652# treated as such so that we pass the same flags. Otherwise, for instance, 653# `rustc` will complain about missing sanitizer flags causing an ABI mismatch. 654$(obj)/build_error.o: private is-kernel-object := y 655$(obj)/build_error.o: private skip_gendwarfksyms = 1 656$(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FORCE 657 +$(call if_changed_rule,rustc_library) 658 659$(obj)/ffi.o: private skip_gendwarfksyms = 1 660$(obj)/ffi.o: $(src)/ffi.rs $(obj)/compiler_builtins.o FORCE 661 +$(call if_changed_rule,rustc_library) 662 663$(obj)/bindings.o: private rustc_target_flags = --extern ffi --extern pin_init 664$(obj)/bindings.o: $(src)/bindings/lib.rs \ 665 $(obj)/ffi.o \ 666 $(obj)/pin_init.o \ 667 $(obj)/bindings/bindings_generated.rs \ 668 $(obj)/bindings/bindings_helpers_generated.rs FORCE 669 +$(call if_changed_rule,rustc_library) 670 671$(obj)/uapi.o: private rustc_target_flags = --extern ffi --extern pin_init 672$(obj)/uapi.o: private skip_gendwarfksyms = 1 673$(obj)/uapi.o: $(src)/uapi/lib.rs \ 674 $(obj)/ffi.o \ 675 $(obj)/pin_init.o \ 676 $(obj)/uapi/uapi_generated.rs FORCE 677 +$(call if_changed_rule,rustc_library) 678 679$(obj)/kernel.o: private rustc_target_flags = --extern ffi --extern pin_init \ 680 --extern build_error --extern macros --extern bindings --extern uapi 681$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o $(obj)/pin_init.o \ 682 $(obj)/$(libmacros_name) $(obj)/bindings.o $(obj)/uapi.o FORCE 683 +$(call if_changed_rule,rustc_library) 684 685ifdef CONFIG_JUMP_LABEL 686$(obj)/kernel.o: $(obj)/kernel/generated_arch_static_branch_asm.rs 687endif 688ifndef CONFIG_UML 689ifdef CONFIG_BUG 690$(obj)/kernel.o: $(obj)/kernel/generated_arch_warn_asm.rs $(obj)/kernel/generated_arch_reachable_asm.rs 691endif 692endif 693 694endif # CONFIG_RUST 695