@@ -120,6 +120,15 @@ endif
120
120
121
121
export KBUILD_CHECKSRC
122
122
123
+ # Enable "clippy" (a linter) as part of the Rust compilation.
124
+ #
125
+ # Use 'make CLIPPY=1' to enable it.
126
+ ifeq ("$(origin CLIPPY ) ", "command line")
127
+ KBUILD_CLIPPY := $(CLIPPY )
128
+ endif
129
+
130
+ export KBUILD_CLIPPY
131
+
123
132
# Use make M=dir or set the environment variable KBUILD_EXTMOD to specify the
124
133
# directory of external module to build. Setting M= takes precedence.
125
134
ifeq ("$(origin M ) ", "command line")
@@ -270,14 +279,14 @@ no-dot-config-targets := $(clean-targets) \
270
279
cscope gtags TAGS tags help% %docs check% coccicheck \
271
280
$(version_h ) headers headers_% archheaders archscripts \
272
281
%asm-generic kernelversion %src-pkg dt_binding_check \
273
- outputmakefile
282
+ outputmakefile rustavailable rustfmt rustfmtcheck
274
283
# Installation targets should not require compiler. Unfortunately, vdso_install
275
284
# is an exception where build artifacts may be updated. This must be fixed.
276
285
no-compiler-targets := $(no-dot-config-targets ) install dtbs_install \
277
286
headers_install modules_install kernelrelease image_name
278
287
no-sync-config-targets := $(no-dot-config-targets ) %install kernelrelease \
279
288
image_name
280
- single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/
289
+ single-targets := %.a %.i %.rsi %. ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/
281
290
282
291
config-build :=
283
292
mixed-build :=
439
448
HOSTCC = gcc
440
449
HOSTCXX = g++
441
450
endif
451
+ HOSTRUSTC = rustc
442
452
HOSTPKG_CONFIG = pkg-config
443
453
444
454
KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
@@ -447,8 +457,26 @@ KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
447
457
KBUILD_USERCFLAGS := $(KBUILD_USERHOSTCFLAGS ) $(USERCFLAGS )
448
458
KBUILD_USERLDFLAGS := $(USERLDFLAGS )
449
459
460
+ # These flags apply to all Rust code in the tree, including the kernel and
461
+ # host programs.
462
+ export rust_common_flags := --edition=2021 \
463
+ -Zbinary_dep_depinfo=y \
464
+ -Dunsafe_op_in_unsafe_fn -Drust_2018_idioms \
465
+ -Dunreachable_pub -Dnon_ascii_idents \
466
+ -Wmissing_docs \
467
+ -Drustdoc::missing_crate_level_docs \
468
+ -Dclippy::correctness -Dclippy::style \
469
+ -Dclippy::suspicious -Dclippy::complexity \
470
+ -Dclippy::perf \
471
+ -Dclippy::let_unit_value -Dclippy::mut_mut \
472
+ -Dclippy::needless_bitwise_bool \
473
+ -Dclippy::needless_continue \
474
+ -Wclippy::dbg_macro
475
+
450
476
KBUILD_HOSTCFLAGS := $(KBUILD_USERHOSTCFLAGS ) $(HOST_LFS_CFLAGS ) $(HOSTCFLAGS )
451
477
KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS ) $(HOSTCXXFLAGS )
478
+ KBUILD_HOSTRUSTFLAGS := $(rust_common_flags ) -O -Cstrip=debuginfo \
479
+ -Zallow-features= $(HOSTRUSTFLAGS )
452
480
KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS ) $(HOSTLDFLAGS )
453
481
KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS ) $(HOSTLDLIBS )
454
482
@@ -473,6 +501,12 @@ OBJDUMP = $(CROSS_COMPILE)objdump
473
501
READELF = $(CROSS_COMPILE ) readelf
474
502
STRIP = $(CROSS_COMPILE ) strip
475
503
endif
504
+ RUSTC = rustc
505
+ RUSTDOC = rustdoc
506
+ RUSTFMT = rustfmt
507
+ CLIPPY_DRIVER = clippy-driver
508
+ BINDGEN = bindgen
509
+ CARGO = cargo
476
510
PAHOLE = pahole
477
511
RESOLVE_BTFIDS = $(objtree ) /tools/bpf/resolve_btfids/resolve_btfids
478
512
LEX = flex
@@ -498,9 +532,11 @@ CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
498
532
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF )
499
533
NOSTDINC_FLAGS :=
500
534
CFLAGS_MODULE =
535
+ RUSTFLAGS_MODULE =
501
536
AFLAGS_MODULE =
502
537
LDFLAGS_MODULE =
503
538
CFLAGS_KERNEL =
539
+ RUSTFLAGS_KERNEL =
504
540
AFLAGS_KERNEL =
505
541
LDFLAGS_vmlinux =
506
542
@@ -529,15 +565,43 @@ KBUILD_CFLAGS := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
529
565
-Werror=return-type -Wno-format-security \
530
566
-std=gnu11
531
567
KBUILD_CPPFLAGS := -D__KERNEL__
568
+ KBUILD_RUSTFLAGS := $(rust_common_flags ) \
569
+ --target=$(objtree ) /rust/target.json \
570
+ -Cpanic=abort -Cembed-bitcode=n -Clto=n \
571
+ -Cforce-unwind-tables=n -Ccodegen-units=1 \
572
+ -Csymbol-mangling-version=v0 \
573
+ -Crelocation-model=static \
574
+ -Zfunction-sections=n \
575
+ -Dclippy::float_arithmetic
576
+
532
577
KBUILD_AFLAGS_KERNEL :=
533
578
KBUILD_CFLAGS_KERNEL :=
579
+ KBUILD_RUSTFLAGS_KERNEL :=
534
580
KBUILD_AFLAGS_MODULE := -DMODULE
535
581
KBUILD_CFLAGS_MODULE := -DMODULE
582
+ KBUILD_RUSTFLAGS_MODULE := --cfg MODULE
536
583
KBUILD_LDFLAGS_MODULE :=
537
584
KBUILD_LDFLAGS :=
538
585
CLANG_FLAGS :=
539
586
587
+ ifeq ($(KBUILD_CLIPPY ) ,1)
588
+ RUSTC_OR_CLIPPY_QUIET := CLIPPY
589
+ RUSTC_OR_CLIPPY = $(CLIPPY_DRIVER)
590
+ else
591
+ RUSTC_OR_CLIPPY_QUIET := RUSTC
592
+ RUSTC_OR_CLIPPY = $(RUSTC)
593
+ endif
594
+
595
+ ifdef RUST_LIB_SRC
596
+ export RUST_LIB_SRC
597
+ endif
598
+
599
+ # Allows the usage of unstable features in stable compilers.
600
+ export RUSTC_BOOTSTRAP := 1
601
+
540
602
export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
603
+ export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN CARGO
604
+ export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
541
605
export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
542
606
export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
543
607
export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD
@@ -546,9 +610,10 @@ export KBUILD_USERCFLAGS KBUILD_USERLDFLAGS
546
610
547
611
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
548
612
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
613
+ export KBUILD_RUSTFLAGS RUSTFLAGS_KERNEL RUSTFLAGS_MODULE
549
614
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
550
- export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
551
- export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
615
+ export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_RUSTFLAGS_MODULE KBUILD_LDFLAGS_MODULE
616
+ export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL KBUILD_RUSTFLAGS_KERNEL
552
617
export PAHOLE_FLAGS
553
618
554
619
# Files to ignore in find ... statements
@@ -729,7 +794,7 @@ $(KCONFIG_CONFIG):
729
794
#
730
795
# Do not use $(call cmd,...) here. That would suppress prompts from syncconfig,
731
796
# so you cannot notice that Kconfig is waiting for the user input.
732
- % /config/auto.conf % /config/auto.conf.cmd % /generated/autoconf.h : $(KCONFIG_CONFIG )
797
+ % /config/auto.conf % /config/auto.conf.cmd % /generated/autoconf.h % /generated/rustc_cfg : $(KCONFIG_CONFIG )
733
798
$(Q )$(kecho ) " SYNC $@ "
734
799
$(Q )$(MAKE ) -f $(srctree ) /Makefile syncconfig
735
800
else # !may-sync-config
@@ -758,10 +823,17 @@ KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
758
823
759
824
ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
760
825
KBUILD_CFLAGS += -O2
826
+ KBUILD_RUSTFLAGS += -Copt-level=2
761
827
else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
762
828
KBUILD_CFLAGS += -Os
829
+ KBUILD_RUSTFLAGS += -Copt-level=s
763
830
endif
764
831
832
+ # Always set `debug-assertions` and `overflow-checks` because their default
833
+ # depends on `opt-level` and `debug-assertions`, respectively.
834
+ KBUILD_RUSTFLAGS += -Cdebug-assertions=$(if $(CONFIG_RUST_DEBUG_ASSERTIONS ) ,y,n)
835
+ KBUILD_RUSTFLAGS += -Coverflow-checks=$(if $(CONFIG_RUST_OVERFLOW_CHECKS ) ,y,n)
836
+
765
837
# Tell gcc to never replace conditional load with a non-conditional one
766
838
ifdef CONFIG_CC_IS_GCC
767
839
# gcc-10 renamed --param=allow-store-data-races=0 to
@@ -792,6 +864,9 @@ KBUILD_CFLAGS-$(CONFIG_WERROR) += -Werror
792
864
KBUILD_CFLAGS-$(CONFIG_CC_NO_ARRAY_BOUNDS) += -Wno-array-bounds
793
865
KBUILD_CFLAGS += $(KBUILD_CFLAGS-y ) $(CONFIG_CC_IMPLICIT_FALLTHROUGH )
794
866
867
+ KBUILD_RUSTFLAGS-$(CONFIG_WERROR) += -Dwarnings
868
+ KBUILD_RUSTFLAGS += $(KBUILD_RUSTFLAGS-y )
869
+
795
870
ifdef CONFIG_CC_IS_CLANG
796
871
KBUILD_CPPFLAGS += -Qunused-arguments
797
872
# The kernel builds with '-std=gnu11' so use of GNU extensions is acceptable.
@@ -812,12 +887,15 @@ KBUILD_CFLAGS += $(call cc-disable-warning, dangling-pointer)
812
887
813
888
ifdef CONFIG_FRAME_POINTER
814
889
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
890
+ KBUILD_RUSTFLAGS += -Cforce-frame-pointers=y
815
891
else
816
892
# Some targets (ARM with Thumb2, for example), can't be built with frame
817
893
# pointers. For those, we don't have FUNCTION_TRACER automatically
818
894
# select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is
819
895
# incompatible with -fomit-frame-pointer with current GCC, so we don't use
820
896
# -fomit-frame-pointer with FUNCTION_TRACER.
897
+ # In the Rust target specification, "frame-pointer" is set explicitly
898
+ # to "may-omit".
821
899
ifndef CONFIG_FUNCTION_TRACER
822
900
KBUILD_CFLAGS += -fomit-frame-pointer
823
901
endif
@@ -882,8 +960,10 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH
882
960
KBUILD_CFLAGS += -fno-inline-functions-called-once
883
961
endif
884
962
963
+ # `rustc`'s `-Zfunction-sections` applies to data too (as of 1.59.0).
885
964
ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
886
965
KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
966
+ KBUILD_RUSTFLAGS_KERNEL += -Zfunction-sections=y
887
967
LDFLAGS_vmlinux += --gc-sections
888
968
endif
889
969
@@ -1026,10 +1106,11 @@ include $(addprefix $(srctree)/, $(include-y))
1026
1106
# Do not add $(call cc-option,...) below this line. When you build the kernel
1027
1107
# from the clean source tree, the GCC plugins do not exist at this point.
1028
1108
1029
- # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
1109
+ # Add user supplied CPPFLAGS, AFLAGS, CFLAGS and RUSTFLAGS as the last assignments
1030
1110
KBUILD_CPPFLAGS += $(KCPPFLAGS )
1031
1111
KBUILD_AFLAGS += $(KAFLAGS )
1032
1112
KBUILD_CFLAGS += $(KCFLAGS )
1113
+ KBUILD_RUSTFLAGS += $(KRUSTFLAGS )
1033
1114
1034
1115
KBUILD_LDFLAGS_MODULE += --build-id=sha1
1035
1116
LDFLAGS_vmlinux += --build-id=sha1
@@ -1104,6 +1185,7 @@ ifeq ($(KBUILD_EXTMOD),)
1104
1185
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/
1105
1186
core-$(CONFIG_BLOCK) += block/
1106
1187
core-$(CONFIG_IO_URING) += io_uring/
1188
+ core-$(CONFIG_RUST) += rust/
1107
1189
1108
1190
vmlinux-dirs := $(patsubst % /,% ,$(filter % /, \
1109
1191
$(core-y ) $(core-m ) $(drivers-y ) $(drivers-m ) \
@@ -1206,6 +1288,10 @@ prepare0: archprepare
1206
1288
1207
1289
# All the preparing..
1208
1290
prepare : prepare0
1291
+ ifdef CONFIG_RUST
1292
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh -v
1293
+ $(Q)$(MAKE) $(build)=rust
1294
+ endif
1209
1295
1210
1296
PHONY += remove-stale-files
1211
1297
remove-stale-files :
@@ -1499,7 +1585,7 @@ endif # CONFIG_MODULES
1499
1585
# Directories & files removed with 'make clean'
1500
1586
CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \
1501
1587
modules.builtin modules.builtin.modinfo modules.nsdeps \
1502
- compile_commands.json .thinlto-cache
1588
+ compile_commands.json .thinlto-cache rust/test rust/doc
1503
1589
1504
1590
# Directories & files removed with 'make mrproper'
1505
1591
MRPROPER_FILES += include/config include/generated \
@@ -1510,7 +1596,8 @@ MRPROPER_FILES += include/config include/generated \
1510
1596
certs/signing_key.pem \
1511
1597
certs/x509.genkey \
1512
1598
vmlinux-gdb.py \
1513
- *.spec
1599
+ *.spec \
1600
+ rust/target.json rust/libmacros.so
1514
1601
1515
1602
# clean - Delete most, but leave enough to build external modules
1516
1603
#
@@ -1535,6 +1622,9 @@ $(mrproper-dirs):
1535
1622
1536
1623
mrproper : clean $(mrproper-dirs )
1537
1624
$(call cmd,rmfiles)
1625
+ @find . $(RCS_FIND_IGNORE ) \
1626
+ \( -name ' *.rmeta' \) \
1627
+ -type f -print | xargs rm -f
1538
1628
1539
1629
# distclean
1540
1630
#
@@ -1622,6 +1712,24 @@ help:
1622
1712
@echo ' kselftest-merge - Merge all the config dependencies of'
1623
1713
@echo ' kselftest to existing .config.'
1624
1714
@echo ' '
1715
+ @echo ' Rust targets:'
1716
+ @echo ' rustavailable - Checks whether the Rust toolchain is'
1717
+ @echo ' available and, if not, explains why.'
1718
+ @echo ' rustfmt - Reformat all the Rust code in the kernel'
1719
+ @echo ' rustfmtcheck - Checks if all the Rust code in the kernel'
1720
+ @echo ' is formatted, printing a diff otherwise.'
1721
+ @echo ' rustdoc - Generate Rust documentation'
1722
+ @echo ' (requires kernel .config)'
1723
+ @echo ' rusttest - Runs the Rust tests'
1724
+ @echo ' (requires kernel .config; downloads external repos)'
1725
+ @echo ' rust-analyzer - Generate rust-project.json rust-analyzer support file'
1726
+ @echo ' (requires kernel .config)'
1727
+ @echo ' dir/file.[os] - Build specified target only'
1728
+ @echo ' dir/file.rsi - Build macro expanded source, similar to C preprocessing.'
1729
+ @echo ' Run with RUSTFMT=n to skip reformatting if needed.'
1730
+ @echo ' The output is not intended to be compilable.'
1731
+ @echo ' dir/file.ll - Build the LLVM assembly file'
1732
+ @echo ' '
1625
1733
@$(if $(dtstree ) , \
1626
1734
echo ' Devicetree:' ; \
1627
1735
echo ' * dtbs - Build device tree blobs for enabled boards' ; \
@@ -1694,6 +1802,52 @@ PHONY += $(DOC_TARGETS)
1694
1802
$(DOC_TARGETS ) :
1695
1803
$(Q )$(MAKE ) $(build ) =Documentation $@
1696
1804
1805
+
1806
+ # Rust targets
1807
+ # ---------------------------------------------------------------------------
1808
+
1809
+ # "Is Rust available?" target
1810
+ PHONY += rustavailable
1811
+ rustavailable :
1812
+ $(Q )$(CONFIG_SHELL ) $(srctree ) /scripts/rust_is_available.sh -v && echo " Rust is available!"
1813
+
1814
+ # Documentation target
1815
+ #
1816
+ # Using the singular to avoid running afoul of `no-dot-config-targets`.
1817
+ PHONY += rustdoc
1818
+ rustdoc : prepare
1819
+ $(Q )$(MAKE ) $(build ) =rust $@
1820
+
1821
+ # Testing target
1822
+ PHONY += rusttest
1823
+ rusttest : prepare
1824
+ $(Q )$(MAKE ) $(build ) =rust $@
1825
+
1826
+ # Formatting targets
1827
+ PHONY += rustfmt rustfmtcheck
1828
+
1829
+ # We skip `rust/alloc` since we want to minimize the diff w.r.t. upstream.
1830
+ #
1831
+ # We match using absolute paths since `find` does not resolve them
1832
+ # when matching, which is a problem when e.g. `srctree` is `..`.
1833
+ # We `grep` afterwards in order to remove the directory entry itself.
1834
+ rustfmt :
1835
+ $(Q ) find $(abs_srctree ) -type f -name ' *.rs' \
1836
+ -o -path $(abs_srctree ) /rust/alloc -prune \
1837
+ -o -path $(abs_objtree ) /rust/test -prune \
1838
+ | grep -Fv $(abs_srctree ) /rust/alloc \
1839
+ | grep -Fv $(abs_objtree ) /rust/test \
1840
+ | grep -Fv generated \
1841
+ | xargs $(RUSTFMT ) $(rustfmt_flags )
1842
+
1843
+ rustfmtcheck : rustfmt_flags = --check
1844
+ rustfmtcheck : rustfmt
1845
+
1846
+ # IDE support targets
1847
+ PHONY += rust-analyzer
1848
+ rust-analyzer :
1849
+ $(Q )$(MAKE ) $(build ) =rust $@
1850
+
1697
1851
# Misc
1698
1852
# ---------------------------------------------------------------------------
1699
1853
@@ -1861,7 +2015,7 @@ $(clean-dirs):
1861
2015
clean : $(clean-dirs )
1862
2016
$(call cmd,rmfiles)
1863
2017
@find $(or $(KBUILD_EXTMOD ) , .) $(RCS_FIND_IGNORE ) \
1864
- \( -name ' *.[aios]' -o -name ' *.ko' -o -name ' .*.cmd' \
2018
+ \( -name ' *.[aios]' -o -name ' *.rsi ' -o -name ' *. ko' -o -name ' .*.cmd' \
1865
2019
-o -name ' *.ko.*' \
1866
2020
-o -name ' *.dtb' -o -name ' *.dtbo' -o -name ' *.dtb.S' -o -name ' *.dt.yaml' \
1867
2021
-o -name ' *.dwo' -o -name ' *.lst' \
0 commit comments