Kbuild updates for v6.8
- Make Kconfig parse the input .config more precisely - Support W=c and W=e options for Kconfig - Set Kconfig int/hex symbols to zero if the 'default' property is missing - Add .editorconfig - Add scripts/git.orderFile - Add a script to detect backward-incompatible changes in UAPI headers - Resolve the symlink passed to O= option properly - Use the user-supplied mtime for all files in the builtin initramfs, which provides better reproducible builds - Fix the direct execution of debian/rules for Debian package builds - Use build ID instead of the .gnu_debuglink section for the Debian dbg package -----BEGIN PGP SIGNATURE----- iQJJBAABCgAzFiEEbmPs18K1szRHjPqEPYsBB53g2wYFAmWnEQ8VHG1hc2FoaXJv eUBrZXJuZWwub3JnAAoJED2LAQed4NsGbn8P/RpJ6f4eYAVG/Jnsf5xkkuoOCdWP ADA9I5VfgiUzEZV48tjjUOOhk9LO/QDwlxtbLZjlo9jC5TI+IVrXzCu4ShRhmE+4 eM/VXFur9RN6CuNWNmkf7yzd0dawiwL4QR/0L82ZNmwXGymeEUzzmFviD5KfJRY8 z6bgA4jLu9qsHNzX8eYA2LU+jpOoNiRQAlGzTE0oDgQnv/ZXJB/H+8tEhzH85oZk F087IQCct25yGAbZhEkuX2PHx5kus9ICF72Pkqxh075aOQzfKIO8S3PPkt4nAiHK Cb6sahRcO7QwxH7MJVWgmfbXNMbs9p8fOj9Aiudl2EEWVRav1mw9UuA5kCnTh6vi LpI4bYNChl8fNTX2gX+Dfkmbc5r2Yl65ufW23VlRdZfdrXbJWlQbkkdvJeb7NoEj u6z26b/2WMaTecxr0Bw50PbleHYZwWIscN5lGoK6rgUU04mr4t8g1ejpcxfj+79S MfbpEvPGKMJjelRBHf2x4qzzHQZHeqIbaItCNt8wGSVipgTvrWED2UaaEnW02SoL pwIcBjV9xiUo8UUVil/R8W6xr/Ybv0lWYcIBzQjibiCzhFgw4adPnzZ6eTlaV+6e ne527SqxQ0gF3xgDhxOz4VUF/b4TlnVycArIl80Kk/sFd8jX+AObkCtamZEPc0Rz GjsorSF/s+Fw7XMp =HXZB -----END PGP SIGNATURE----- Merge tag 'kbuild-v6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild Pull Kbuild updates from Masahiro Yamada: - Make Kconfig parse the input .config more precisely - Support W=c and W=e options for Kconfig - Set Kconfig int/hex symbols to zero if the 'default' property is missing - Add .editorconfig - Add scripts/git.orderFile - Add a script to detect backward-incompatible changes in UAPI headers - Resolve the symlink passed to O= option properly - Use the user-supplied mtime for all files in the builtin initramfs, which provides better reproducible builds - Fix the direct execution of debian/rules for Debian package builds - Use build ID instead of the .gnu_debuglink section for the Debian dbg package * tag 'kbuild-v6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (53 commits) kbuild: deb-pkg: use debian/<package> for tmpdir kbuild: deb-pkg: move 'make headers' to build-arch kbuild: deb-pkg: do not search for 'scripts' directory under arch/ kbuild: deb-pkg: use build ID instead of debug link for dbg package kbuild: deb-pkg: use more debhelper commands in builddeb kbuild: deb-pkg: remove unneeded '-f $srctree/Makefile' in debian/rules kbuild: deb-pkg: allow to run debian/rules from output directory kbuild: deb-pkg: set DEB_* variables if debian/rules is directly executed kbuild: deb-pkg: squash scripts/package/deb-build-option to debian/rules kbuild: deb-pkg: factor out common Make options in debian/rules kbuild: deb-pkg: hard-code Build-Depends kbuild: deb-pkg: split debian/copyright from the mkdebian script gen_init_cpio: Apply mtime supplied by user to all file types kbuild: resolve symlinks for O= properly docs: dev-tools: Add UAPI checker documentation check-uapi: Introduce check-uapi.sh scripts: Introduce a default git.orderFile kconfig: WERROR unmet symbol dependency Add .editorconfig file for basic formatting kconfig: Use KCONFIG_CONFIG instead of .config ...
This commit is contained in:
commit
b5f66ba2d0
32
.editorconfig
Normal file
32
.editorconfig
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[{*.{awk,c,dts,dtsi,dtso,h,mk,s,S},Kconfig,Makefile,Makefile.*}]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 8
|
||||||
|
|
||||||
|
[*.{json,py,rs}]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# this must be below the general *.py to overwrite it
|
||||||
|
[tools/{perf,power,rcu,testing/kunit}/**.py,]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 8
|
||||||
|
|
||||||
|
[*.yaml]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = unset
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -96,6 +96,7 @@ modules.order
|
|||||||
#
|
#
|
||||||
!.clang-format
|
!.clang-format
|
||||||
!.cocciconfig
|
!.cocciconfig
|
||||||
|
!.editorconfig
|
||||||
!.get_maintainer.ignore
|
!.get_maintainer.ignore
|
||||||
!.gitattributes
|
!.gitattributes
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
477
Documentation/dev-tools/checkuapi.rst
Normal file
477
Documentation/dev-tools/checkuapi.rst
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
.. SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
============
|
||||||
|
UAPI Checker
|
||||||
|
============
|
||||||
|
|
||||||
|
The UAPI checker (``scripts/check-uapi.sh``) is a shell script which
|
||||||
|
checks UAPI header files for userspace backwards-compatibility across
|
||||||
|
the git tree.
|
||||||
|
|
||||||
|
Options
|
||||||
|
=======
|
||||||
|
|
||||||
|
This section will describe the options with which ``check-uapi.sh``
|
||||||
|
can be run.
|
||||||
|
|
||||||
|
Usage::
|
||||||
|
|
||||||
|
check-uapi.sh [-b BASE_REF] [-p PAST_REF] [-j N] [-l ERROR_LOG] [-i] [-q] [-v]
|
||||||
|
|
||||||
|
Available options::
|
||||||
|
|
||||||
|
-b BASE_REF Base git reference to use for comparison. If unspecified or empty,
|
||||||
|
will use any dirty changes in tree to UAPI files. If there are no
|
||||||
|
dirty changes, HEAD will be used.
|
||||||
|
-p PAST_REF Compare BASE_REF to PAST_REF (e.g. -p v6.1). If unspecified or empty,
|
||||||
|
will use BASE_REF^1. Must be an ancestor of BASE_REF. Only headers
|
||||||
|
that exist on PAST_REF will be checked for compatibility.
|
||||||
|
-j JOBS Number of checks to run in parallel (default: number of CPU cores).
|
||||||
|
-l ERROR_LOG Write error log to file (default: no error log is generated).
|
||||||
|
-i Ignore ambiguous changes that may or may not break UAPI compatibility.
|
||||||
|
-q Quiet operation.
|
||||||
|
-v Verbose operation (print more information about each header being checked).
|
||||||
|
|
||||||
|
Environmental args::
|
||||||
|
|
||||||
|
ABIDIFF Custom path to abidiff binary
|
||||||
|
CC C compiler (default is "gcc")
|
||||||
|
ARCH Target architecture of C compiler (default is host arch)
|
||||||
|
|
||||||
|
Exit codes::
|
||||||
|
|
||||||
|
0) Success
|
||||||
|
1) ABI difference detected
|
||||||
|
2) Prerequisite not met
|
||||||
|
|
||||||
|
Examples
|
||||||
|
========
|
||||||
|
|
||||||
|
Basic Usage
|
||||||
|
-----------
|
||||||
|
|
||||||
|
First, let's try making a change to a UAPI header file that obviously
|
||||||
|
won't break userspace::
|
||||||
|
|
||||||
|
cat << 'EOF' | patch -l -p1
|
||||||
|
--- a/include/uapi/linux/acct.h
|
||||||
|
+++ b/include/uapi/linux/acct.h
|
||||||
|
@@ -21,7 +21,9 @@
|
||||||
|
#include <asm/param.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
|
-/*
|
||||||
|
+#define FOO
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* comp_t is a 16-bit "floating" point number with a 3-bit base 8
|
||||||
|
* exponent and a 13-bit fraction.
|
||||||
|
* comp2_t is 24-bit with 5-bit base 2 exponent and 20 bit fraction
|
||||||
|
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
|
||||||
|
EOF
|
||||||
|
|
||||||
|
Now, let's use the script to validate::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh
|
||||||
|
Installing user-facing UAPI headers from dirty tree... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||||
|
All 912 UAPI headers compatible with x86 appear to be backwards compatible
|
||||||
|
|
||||||
|
Let's add another change that *might* break userspace::
|
||||||
|
|
||||||
|
cat << 'EOF' | patch -l -p1
|
||||||
|
--- a/include/uapi/linux/bpf.h
|
||||||
|
+++ b/include/uapi/linux/bpf.h
|
||||||
|
@@ -74,7 +74,7 @@ struct bpf_insn {
|
||||||
|
__u8 dst_reg:4; /* dest register */
|
||||||
|
__u8 src_reg:4; /* source register */
|
||||||
|
__s16 off; /* signed offset */
|
||||||
|
- __s32 imm; /* signed immediate constant */
|
||||||
|
+ __u32 imm; /* unsigned immediate constant */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
|
||||||
|
EOF
|
||||||
|
|
||||||
|
The script will catch this::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh
|
||||||
|
Installing user-facing UAPI headers from dirty tree... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||||
|
==== ABI differences detected in include/linux/bpf.h from HEAD -> dirty tree ====
|
||||||
|
[C] 'struct bpf_insn' changed:
|
||||||
|
type size hasn't changed
|
||||||
|
1 data member change:
|
||||||
|
type of '__s32 imm' changed:
|
||||||
|
typedef name changed from __s32 to __u32 at int-ll64.h:27:1
|
||||||
|
underlying type 'int' changed:
|
||||||
|
type name changed from 'int' to 'unsigned int'
|
||||||
|
type size hasn't changed
|
||||||
|
==================================================================================
|
||||||
|
|
||||||
|
error - 1/912 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||||
|
|
||||||
|
In this case, the script is reporting the type change because it could
|
||||||
|
break a userspace program that passes in a negative number. Now, let's
|
||||||
|
say you know that no userspace program could possibly be using a negative
|
||||||
|
value in ``imm``, so changing to an unsigned type there shouldn't hurt
|
||||||
|
anything. You can pass the ``-i`` flag to the script to ignore changes
|
||||||
|
in which the userspace backwards compatibility is ambiguous::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh -i
|
||||||
|
Installing user-facing UAPI headers from dirty tree... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||||
|
All 912 UAPI headers compatible with x86 appear to be backwards compatible
|
||||||
|
|
||||||
|
Now, let's make a similar change that *will* break userspace::
|
||||||
|
|
||||||
|
cat << 'EOF' | patch -l -p1
|
||||||
|
--- a/include/uapi/linux/bpf.h
|
||||||
|
+++ b/include/uapi/linux/bpf.h
|
||||||
|
@@ -71,8 +71,8 @@ enum {
|
||||||
|
|
||||||
|
struct bpf_insn {
|
||||||
|
__u8 code; /* opcode */
|
||||||
|
- __u8 dst_reg:4; /* dest register */
|
||||||
|
__u8 src_reg:4; /* source register */
|
||||||
|
+ __u8 dst_reg:4; /* dest register */
|
||||||
|
__s16 off; /* signed offset */
|
||||||
|
__s32 imm; /* signed immediate constant */
|
||||||
|
};
|
||||||
|
EOF
|
||||||
|
|
||||||
|
Since we're re-ordering an existing struct member, there's no ambiguity,
|
||||||
|
and the script will report the breakage even if you pass ``-i``::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh -i
|
||||||
|
Installing user-facing UAPI headers from dirty tree... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||||
|
==== ABI differences detected in include/linux/bpf.h from HEAD -> dirty tree ====
|
||||||
|
[C] 'struct bpf_insn' changed:
|
||||||
|
type size hasn't changed
|
||||||
|
2 data member changes:
|
||||||
|
'__u8 dst_reg' offset changed from 8 to 12 (in bits) (by +4 bits)
|
||||||
|
'__u8 src_reg' offset changed from 12 to 8 (in bits) (by -4 bits)
|
||||||
|
==================================================================================
|
||||||
|
|
||||||
|
error - 1/912 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||||
|
|
||||||
|
Let's commit the breaking change, then commit the innocuous change::
|
||||||
|
|
||||||
|
% git commit -m 'Breaking UAPI change' include/uapi/linux/bpf.h
|
||||||
|
[detached HEAD f758e574663a] Breaking UAPI change
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
% git commit -m 'Innocuous UAPI change' include/uapi/linux/acct.h
|
||||||
|
[detached HEAD 2e87df769081] Innocuous UAPI change
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Now, let's run the script again with no arguments::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD^1... OK
|
||||||
|
Checking changes to UAPI headers between HEAD^1 and HEAD...
|
||||||
|
All 912 UAPI headers compatible with x86 appear to be backwards compatible
|
||||||
|
|
||||||
|
It doesn't catch any breaking change because, by default, it only
|
||||||
|
compares ``HEAD`` to ``HEAD^1``. The breaking change was committed on
|
||||||
|
``HEAD~2``. If we wanted the search scope to go back further, we'd have to
|
||||||
|
use the ``-p`` option to pass a different past reference. In this case,
|
||||||
|
let's pass ``-p HEAD~2`` to the script so it checks UAPI changes between
|
||||||
|
``HEAD~2`` and ``HEAD``::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh -p HEAD~2
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD~2... OK
|
||||||
|
Checking changes to UAPI headers between HEAD~2 and HEAD...
|
||||||
|
==== ABI differences detected in include/linux/bpf.h from HEAD~2 -> HEAD ====
|
||||||
|
[C] 'struct bpf_insn' changed:
|
||||||
|
type size hasn't changed
|
||||||
|
2 data member changes:
|
||||||
|
'__u8 dst_reg' offset changed from 8 to 12 (in bits) (by +4 bits)
|
||||||
|
'__u8 src_reg' offset changed from 12 to 8 (in bits) (by -4 bits)
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
error - 1/912 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||||
|
|
||||||
|
Alternatively, we could have also run with ``-b HEAD~``. This would set the
|
||||||
|
base reference to ``HEAD~`` so then the script would compare it to ``HEAD~^1``.
|
||||||
|
|
||||||
|
Architecture-specific Headers
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Consider this change::
|
||||||
|
|
||||||
|
cat << 'EOF' | patch -l -p1
|
||||||
|
--- a/arch/arm64/include/uapi/asm/sigcontext.h
|
||||||
|
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
|
||||||
|
@@ -70,6 +70,7 @@ struct sigcontext {
|
||||||
|
struct _aarch64_ctx {
|
||||||
|
__u32 magic;
|
||||||
|
__u32 size;
|
||||||
|
+ __u32 new_var;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FPSIMD_MAGIC 0x46508001
|
||||||
|
EOF
|
||||||
|
|
||||||
|
This is a change to an arm64-specific UAPI header file. In this example, I'm
|
||||||
|
running the script from an x86 machine with an x86 compiler, so, by default,
|
||||||
|
the script only checks x86-compatible UAPI header files::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh
|
||||||
|
Installing user-facing UAPI headers from dirty tree... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
No changes to UAPI headers were applied between HEAD and dirty tree
|
||||||
|
|
||||||
|
With an x86 compiler, we can't check header files in ``arch/arm64``, so the
|
||||||
|
script doesn't even try.
|
||||||
|
|
||||||
|
If we want to check the header file, we'll have to use an arm64 compiler and
|
||||||
|
set ``ARCH`` accordingly::
|
||||||
|
|
||||||
|
% CC=aarch64-linux-gnu-gcc ARCH=arm64 ./scripts/check-uapi.sh
|
||||||
|
Installing user-facing UAPI headers from dirty tree... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||||
|
==== ABI differences detected in include/asm/sigcontext.h from HEAD -> dirty tree ====
|
||||||
|
[C] 'struct _aarch64_ctx' changed:
|
||||||
|
type size changed from 64 to 96 (in bits)
|
||||||
|
1 data member insertion:
|
||||||
|
'__u32 new_var', at offset 64 (in bits) at sigcontext.h:73:1
|
||||||
|
-- snip --
|
||||||
|
[C] 'struct zt_context' changed:
|
||||||
|
type size changed from 128 to 160 (in bits)
|
||||||
|
2 data member changes (1 filtered):
|
||||||
|
'__u16 nregs' offset changed from 64 to 96 (in bits) (by +32 bits)
|
||||||
|
'__u16 __reserved[3]' offset changed from 80 to 112 (in bits) (by +32 bits)
|
||||||
|
=======================================================================================
|
||||||
|
|
||||||
|
error - 1/884 UAPI headers compatible with arm64 appear _not_ to be backwards compatible
|
||||||
|
|
||||||
|
We can see with ``ARCH`` and ``CC`` set properly for the file, the ABI
|
||||||
|
change is reported properly. Also notice that the total number of UAPI
|
||||||
|
header files checked by the script changes. This is because the number
|
||||||
|
of headers installed for arm64 platforms is different than x86.
|
||||||
|
|
||||||
|
Cross-Dependency Breakages
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Consider this change::
|
||||||
|
|
||||||
|
cat << 'EOF' | patch -l -p1
|
||||||
|
--- a/include/uapi/linux/types.h
|
||||||
|
+++ b/include/uapi/linux/types.h
|
||||||
|
@@ -52,7 +52,7 @@ typedef __u32 __bitwise __wsum;
|
||||||
|
#define __aligned_be64 __be64 __attribute__((aligned(8)))
|
||||||
|
#define __aligned_le64 __le64 __attribute__((aligned(8)))
|
||||||
|
|
||||||
|
-typedef unsigned __bitwise __poll_t;
|
||||||
|
+typedef unsigned short __bitwise __poll_t;
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
#endif /* _UAPI_LINUX_TYPES_H */
|
||||||
|
EOF
|
||||||
|
|
||||||
|
Here, we're changing a ``typedef`` in ``types.h``. This doesn't break
|
||||||
|
a UAPI in ``types.h``, but other UAPIs in the tree may break due to
|
||||||
|
this change::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh
|
||||||
|
Installing user-facing UAPI headers from dirty tree... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||||
|
==== ABI differences detected in include/linux/eventpoll.h from HEAD -> dirty tree ====
|
||||||
|
[C] 'struct epoll_event' changed:
|
||||||
|
type size changed from 96 to 80 (in bits)
|
||||||
|
2 data member changes:
|
||||||
|
type of '__poll_t events' changed:
|
||||||
|
underlying type 'unsigned int' changed:
|
||||||
|
type name changed from 'unsigned int' to 'unsigned short int'
|
||||||
|
type size changed from 32 to 16 (in bits)
|
||||||
|
'__u64 data' offset changed from 32 to 16 (in bits) (by -16 bits)
|
||||||
|
========================================================================================
|
||||||
|
include/linux/eventpoll.h did not change between HEAD and dirty tree...
|
||||||
|
It's possible a change to one of the headers it includes caused this error:
|
||||||
|
#include <linux/fcntl.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
Note that the script noticed the failing header file did not change,
|
||||||
|
so it assumes one of its includes must have caused the breakage. Indeed,
|
||||||
|
we can see ``linux/types.h`` is used from ``eventpoll.h``.
|
||||||
|
|
||||||
|
UAPI Header Removals
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Consider this change::
|
||||||
|
|
||||||
|
cat << 'EOF' | patch -l -p1
|
||||||
|
diff --git a/include/uapi/asm-generic/Kbuild b/include/uapi/asm-generic/Kbuild
|
||||||
|
index ebb180aac74e..a9c88b0a8b3b 100644
|
||||||
|
--- a/include/uapi/asm-generic/Kbuild
|
||||||
|
+++ b/include/uapi/asm-generic/Kbuild
|
||||||
|
@@ -31,6 +31,6 @@ mandatory-y += stat.h
|
||||||
|
mandatory-y += statfs.h
|
||||||
|
mandatory-y += swab.h
|
||||||
|
mandatory-y += termbits.h
|
||||||
|
-mandatory-y += termios.h
|
||||||
|
+#mandatory-y += termios.h
|
||||||
|
mandatory-y += types.h
|
||||||
|
mandatory-y += unistd.h
|
||||||
|
EOF
|
||||||
|
|
||||||
|
This script removes a UAPI header file from the install list. Let's run
|
||||||
|
the script::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh
|
||||||
|
Installing user-facing UAPI headers from dirty tree... OK
|
||||||
|
Installing user-facing UAPI headers from HEAD... OK
|
||||||
|
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||||
|
==== UAPI header include/asm/termios.h was removed between HEAD and dirty tree ====
|
||||||
|
|
||||||
|
error - 1/912 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||||
|
|
||||||
|
Removing a UAPI header is considered a breaking change, and the script
|
||||||
|
will flag it as such.
|
||||||
|
|
||||||
|
Checking Historic UAPI Compatibility
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
You can use the ``-b`` and ``-p`` options to examine different chunks of your
|
||||||
|
git tree. For example, to check all changed UAPI header files between tags
|
||||||
|
v6.0 and v6.1, you'd run::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh -b v6.1 -p v6.0
|
||||||
|
Installing user-facing UAPI headers from v6.1... OK
|
||||||
|
Installing user-facing UAPI headers from v6.0... OK
|
||||||
|
Checking changes to UAPI headers between v6.0 and v6.1...
|
||||||
|
|
||||||
|
--- snip ---
|
||||||
|
error - 37/907 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||||
|
|
||||||
|
Note: Before v5.3, a header file needed by the script is not present,
|
||||||
|
so the script is unable to check changes before then.
|
||||||
|
|
||||||
|
You'll notice that the script detected many UAPI changes that are not
|
||||||
|
backwards compatible. Knowing that kernel UAPIs are supposed to be stable
|
||||||
|
forever, this is an alarming result. This brings us to the next section:
|
||||||
|
caveats.
|
||||||
|
|
||||||
|
Caveats
|
||||||
|
=======
|
||||||
|
|
||||||
|
The UAPI checker makes no assumptions about the author's intention, so some
|
||||||
|
types of changes may be flagged even though they intentionally break UAPI.
|
||||||
|
|
||||||
|
Removals For Refactoring or Deprecation
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
Sometimes drivers for very old hardware are removed, such as in this example::
|
||||||
|
|
||||||
|
% ./scripts/check-uapi.sh -b ba47652ba655
|
||||||
|
Installing user-facing UAPI headers from ba47652ba655... OK
|
||||||
|
Installing user-facing UAPI headers from ba47652ba655^1... OK
|
||||||
|
Checking changes to UAPI headers between ba47652ba655^1 and ba47652ba655...
|
||||||
|
==== UAPI header include/linux/meye.h was removed between ba47652ba655^1 and ba47652ba655 ====
|
||||||
|
|
||||||
|
error - 1/910 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||||
|
|
||||||
|
The script will always flag removals (even if they're intentional).
|
||||||
|
|
||||||
|
Struct Expansions
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Depending on how a structure is handled in kernelspace, a change which
|
||||||
|
expands a struct could be non-breaking.
|
||||||
|
|
||||||
|
If a struct is used as the argument to an ioctl, then the kernel driver
|
||||||
|
must be able to handle ioctl commands of any size. Beyond that, you need
|
||||||
|
to be careful when copying data from the user. Say, for example, that
|
||||||
|
``struct foo`` is changed like this::
|
||||||
|
|
||||||
|
struct foo {
|
||||||
|
__u64 a; /* added in version 1 */
|
||||||
|
+ __u32 b; /* added in version 2 */
|
||||||
|
+ __u32 c; /* added in version 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
By default, the script will flag this kind of change for further review::
|
||||||
|
|
||||||
|
[C] 'struct foo' changed:
|
||||||
|
type size changed from 64 to 128 (in bits)
|
||||||
|
2 data member insertions:
|
||||||
|
'__u32 b', at offset 64 (in bits)
|
||||||
|
'__u32 c', at offset 96 (in bits)
|
||||||
|
|
||||||
|
However, it is possible that this change was made safely.
|
||||||
|
|
||||||
|
If a userspace program was built with version 1, it will think
|
||||||
|
``sizeof(struct foo)`` is 8. That size will be encoded in the
|
||||||
|
ioctl value that gets sent to the kernel. If the kernel is built
|
||||||
|
with version 2, it will think the ``sizeof(struct foo)`` is 16.
|
||||||
|
|
||||||
|
The kernel can use the ``_IOC_SIZE`` macro to get the size encoded
|
||||||
|
in the ioctl code that the user passed in and then use
|
||||||
|
``copy_struct_from_user()`` to safely copy the value::
|
||||||
|
|
||||||
|
int handle_ioctl(unsigned long cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
switch _IOC_NR(cmd) {
|
||||||
|
0x01: {
|
||||||
|
struct foo my_cmd; /* size 16 in the kernel */
|
||||||
|
|
||||||
|
ret = copy_struct_from_user(&my_cmd, arg, sizeof(struct foo), _IOC_SIZE(cmd));
|
||||||
|
...
|
||||||
|
|
||||||
|
``copy_struct_from_user`` will zero the struct in the kernel and then copy
|
||||||
|
only the bytes passed in from the user (leaving new members zeroized).
|
||||||
|
If the user passed in a larger struct, the extra members are ignored.
|
||||||
|
|
||||||
|
If you know this situation is accounted for in the kernel code, you can
|
||||||
|
pass ``-i`` to the script, and struct expansions like this will be ignored.
|
||||||
|
|
||||||
|
Flex Array Migration
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
While the script handles expansion into an existing flex array, it does
|
||||||
|
still flag initial migration to flex arrays from 1-element fake flex
|
||||||
|
arrays. For example::
|
||||||
|
|
||||||
|
struct foo {
|
||||||
|
__u32 x;
|
||||||
|
- __u32 flex[1]; /* fake flex */
|
||||||
|
+ __u32 flex[]; /* real flex */
|
||||||
|
};
|
||||||
|
|
||||||
|
This change would be flagged by the script::
|
||||||
|
|
||||||
|
[C] 'struct foo' changed:
|
||||||
|
type size changed from 64 to 32 (in bits)
|
||||||
|
1 data member change:
|
||||||
|
type of '__u32 flex[1]' changed:
|
||||||
|
type name changed from '__u32[1]' to '__u32[]'
|
||||||
|
array type size changed from 32 to 'unknown'
|
||||||
|
array type subrange 1 changed length from 1 to 'unknown'
|
||||||
|
|
||||||
|
At this time, there's no way to filter these types of changes, so be
|
||||||
|
aware of this possible false positive.
|
||||||
|
|
||||||
|
Summary
|
||||||
|
-------
|
||||||
|
|
||||||
|
While many types of false positives are filtered out by the script,
|
||||||
|
it's possible there are some cases where the script flags a change
|
||||||
|
which does not break UAPI. It's also possible a change which *does*
|
||||||
|
break userspace would not be flagged by this script. While the script
|
||||||
|
has been run on much of the kernel history, there could still be corner
|
||||||
|
cases that are not accounted for.
|
||||||
|
|
||||||
|
The intention is for this script to be used as a quick check for
|
||||||
|
maintainers or automated tooling, not as the end-all authority on
|
||||||
|
patch compatibility. It's best to remember: use your best judgment
|
||||||
|
(and ideally a unit test in userspace) to make sure your UAPI changes
|
||||||
|
are backwards-compatible!
|
@ -31,6 +31,7 @@ Documentation/dev-tools/testing-overview.rst
|
|||||||
kselftest
|
kselftest
|
||||||
kunit/index
|
kunit/index
|
||||||
ktap
|
ktap
|
||||||
|
checkuapi
|
||||||
|
|
||||||
|
|
||||||
.. only:: subproject and html
|
.. only:: subproject and html
|
||||||
|
@ -66,6 +66,10 @@ for aligning variables/macros, for reflowing text and other similar tasks.
|
|||||||
See the file :ref:`Documentation/process/clang-format.rst <clangformat>`
|
See the file :ref:`Documentation/process/clang-format.rst <clangformat>`
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
|
Some basic editor settings, such as indentation and line endings, will be
|
||||||
|
set automatically if you are using an editor that is compatible with
|
||||||
|
EditorConfig. See the official EditorConfig website for more information:
|
||||||
|
https://editorconfig.org/
|
||||||
|
|
||||||
Abstraction layers
|
Abstraction layers
|
||||||
******************
|
******************
|
||||||
|
@ -735,6 +735,10 @@ for aligning variables/macros, for reflowing text and other similar tasks.
|
|||||||
See the file :ref:`Documentation/process/clang-format.rst <clangformat>`
|
See the file :ref:`Documentation/process/clang-format.rst <clangformat>`
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
|
Some basic editor settings, such as indentation and line endings, will be
|
||||||
|
set automatically if you are using an editor that is compatible with
|
||||||
|
EditorConfig. See the official EditorConfig website for more information:
|
||||||
|
https://editorconfig.org/
|
||||||
|
|
||||||
10) Kconfig configuration files
|
10) Kconfig configuration files
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
23
Makefile
23
Makefile
@ -155,6 +155,15 @@ endif
|
|||||||
|
|
||||||
export KBUILD_EXTMOD
|
export KBUILD_EXTMOD
|
||||||
|
|
||||||
|
# backward compatibility
|
||||||
|
KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)
|
||||||
|
|
||||||
|
ifeq ("$(origin W)", "command line")
|
||||||
|
KBUILD_EXTRA_WARN := $(W)
|
||||||
|
endif
|
||||||
|
|
||||||
|
export KBUILD_EXTRA_WARN
|
||||||
|
|
||||||
# Kbuild will save output files in the current working directory.
|
# Kbuild will save output files in the current working directory.
|
||||||
# This does not need to match to the root of the kernel source tree.
|
# This does not need to match to the root of the kernel source tree.
|
||||||
#
|
#
|
||||||
@ -181,14 +190,11 @@ ifeq ("$(origin O)", "command line")
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(KBUILD_OUTPUT),)
|
ifneq ($(KBUILD_OUTPUT),)
|
||||||
# Make's built-in functions such as $(abspath ...), $(realpath ...) cannot
|
# $(realpath ...) gets empty if the path does not exist. Run 'mkdir -p' first.
|
||||||
# expand a shell special character '~'. We use a somewhat tedious way here.
|
$(shell mkdir -p "$(KBUILD_OUTPUT)")
|
||||||
abs_objtree := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) && pwd)
|
|
||||||
$(if $(abs_objtree),, \
|
|
||||||
$(error failed to create output directory "$(KBUILD_OUTPUT)"))
|
|
||||||
|
|
||||||
# $(realpath ...) resolves symlinks
|
# $(realpath ...) resolves symlinks
|
||||||
abs_objtree := $(realpath $(abs_objtree))
|
abs_objtree := $(realpath $(KBUILD_OUTPUT))
|
||||||
|
$(if $(abs_objtree),,$(error failed to create output directory "$(KBUILD_OUTPUT)"))
|
||||||
endif # ifneq ($(KBUILD_OUTPUT),)
|
endif # ifneq ($(KBUILD_OUTPUT),)
|
||||||
|
|
||||||
ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
|
ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
|
||||||
@ -609,8 +615,6 @@ export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL KBUILD_RUSTFLAGS_KERNEL
|
|||||||
export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o \
|
export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o \
|
||||||
-name CVS -o -name .pc -o -name .hg -o -name .git \) \
|
-name CVS -o -name .pc -o -name .hg -o -name .git \) \
|
||||||
-prune -o
|
-prune -o
|
||||||
export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
|
|
||||||
--exclude CVS --exclude .pc --exclude .hg --exclude .git
|
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# Rules shared between *config targets and build targets
|
# Rules shared between *config targets and build targets
|
||||||
@ -1662,6 +1666,7 @@ help:
|
|||||||
@echo ' 1: warnings which may be relevant and do not occur too often'
|
@echo ' 1: warnings which may be relevant and do not occur too often'
|
||||||
@echo ' 2: warnings which occur quite often but may still be relevant'
|
@echo ' 2: warnings which occur quite often but may still be relevant'
|
||||||
@echo ' 3: more obscure warnings, can most likely be ignored'
|
@echo ' 3: more obscure warnings, can most likely be ignored'
|
||||||
|
@echo ' c: extra checks in the configuration stage (Kconfig)'
|
||||||
@echo ' e: warnings are being treated as errors'
|
@echo ' e: warnings are being treated as errors'
|
||||||
@echo ' Multiple levels can be combined with W=12 or W=123'
|
@echo ' Multiple levels can be combined with W=12 or W=123'
|
||||||
@$(if $(dtstree), \
|
@$(if $(dtstree), \
|
||||||
|
@ -3,9 +3,6 @@
|
|||||||
# Building vDSO images for sparc.
|
# Building vDSO images for sparc.
|
||||||
#
|
#
|
||||||
|
|
||||||
VDSO64-$(CONFIG_SPARC64) := y
|
|
||||||
VDSOCOMPAT-$(CONFIG_COMPAT) := y
|
|
||||||
|
|
||||||
# files to link into the vdso
|
# files to link into the vdso
|
||||||
vobjs-y := vdso-note.o vclock_gettime.o
|
vobjs-y := vdso-note.o vclock_gettime.o
|
||||||
|
|
||||||
@ -13,22 +10,15 @@ vobjs-y := vdso-note.o vclock_gettime.o
|
|||||||
obj-y += vma.o
|
obj-y += vma.o
|
||||||
|
|
||||||
# vDSO images to build
|
# vDSO images to build
|
||||||
vdso_img-$(VDSO64-y) += 64
|
obj-$(CONFIG_SPARC64) += vdso-image-64.o
|
||||||
vdso_img-$(VDSOCOMPAT-y) += 32
|
obj-$(CONFIG_COMPAT) += vdso-image-32.o
|
||||||
|
|
||||||
vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
|
vobjs := $(addprefix $(obj)/, $(vobjs-y))
|
||||||
|
|
||||||
$(obj)/vdso.o: $(obj)/vdso.so
|
$(obj)/vdso.o: $(obj)/vdso.so
|
||||||
|
|
||||||
targets += vdso.lds $(vobjs-y)
|
targets += vdso.lds $(vobjs-y)
|
||||||
|
targets += $(foreach x, 32 64, vdso-image-$(x).c vdso$(x).so vdso$(x).so.dbg)
|
||||||
# Build the vDSO image C files and link them in.
|
|
||||||
vdso_img_objs := $(vdso_img-y:%=vdso-image-%.o)
|
|
||||||
vdso_img_cfiles := $(vdso_img-y:%=vdso-image-%.c)
|
|
||||||
vdso_img_sodbg := $(vdso_img-y:%=vdso%.so.dbg)
|
|
||||||
obj-y += $(vdso_img_objs)
|
|
||||||
targets += $(vdso_img_cfiles)
|
|
||||||
targets += $(vdso_img_sodbg) $(vdso_img-y:%=vdso%.so)
|
|
||||||
|
|
||||||
CPPFLAGS_vdso.lds += -P -C
|
CPPFLAGS_vdso.lds += -P -C
|
||||||
|
|
||||||
|
@ -6,15 +6,6 @@
|
|||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <linux/stringify.h>
|
#include <linux/stringify.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* Export symbols from the kernel to modules. Forked from module.h
|
|
||||||
* to reduce the amount of pointless cruft we feed to gcc when only
|
|
||||||
* exporting a simple symbol or two.
|
|
||||||
*
|
|
||||||
* Try not to add #includes here. It slows compilation and makes kernel
|
|
||||||
* hackers place grumpy comments in header files.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This comment block is used by fixdep. Please do not remove.
|
* This comment block is used by fixdep. Please do not remove.
|
||||||
*
|
*
|
||||||
@ -23,15 +14,6 @@
|
|||||||
* side effect of the *.o build rule.
|
* side effect of the *.o build rule.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
|
||||||
#ifdef MODULE
|
|
||||||
extern struct module __this_module;
|
|
||||||
#define THIS_MODULE (&__this_module)
|
|
||||||
#else
|
|
||||||
#define THIS_MODULE ((struct module *)0)
|
|
||||||
#endif
|
|
||||||
#endif /* __ASSEMBLY__ */
|
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
#define __EXPORT_SYMBOL_REF(sym) \
|
#define __EXPORT_SYMBOL_REF(sym) \
|
||||||
.balign 8 ASM_NL \
|
.balign 8 ASM_NL \
|
||||||
|
@ -179,6 +179,13 @@ extern void (*late_time_init)(void);
|
|||||||
|
|
||||||
extern bool initcall_debug;
|
extern bool initcall_debug;
|
||||||
|
|
||||||
|
#ifdef MODULE
|
||||||
|
extern struct module __this_module;
|
||||||
|
#define THIS_MODULE (&__this_module)
|
||||||
|
#else
|
||||||
|
#define THIS_MODULE ((struct module *)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
|
@ -82,15 +82,6 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init)
|
|||||||
# Warn if there is an enum types mismatch
|
# Warn if there is an enum types mismatch
|
||||||
KBUILD_CFLAGS += $(call cc-option,-Wenum-conversion)
|
KBUILD_CFLAGS += $(call cc-option,-Wenum-conversion)
|
||||||
|
|
||||||
# backward compatibility
|
|
||||||
KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)
|
|
||||||
|
|
||||||
ifeq ("$(origin W)", "command line")
|
|
||||||
KBUILD_EXTRA_WARN := $(W)
|
|
||||||
endif
|
|
||||||
|
|
||||||
export KBUILD_EXTRA_WARN
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# W=1 - warnings which may be relevant and do not occur too often
|
# W=1 - warnings which may be relevant and do not occur too often
|
||||||
#
|
#
|
||||||
|
@ -83,8 +83,8 @@ dtb-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
|
|||||||
multi-dtb-y := $(call multi-search, $(dtb-y), .dtb, -dtbs)
|
multi-dtb-y := $(call multi-search, $(dtb-y), .dtb, -dtbs)
|
||||||
# Primitive DTB compiled from *.dts
|
# Primitive DTB compiled from *.dts
|
||||||
real-dtb-y := $(call real-search, $(dtb-y), .dtb, -dtbs)
|
real-dtb-y := $(call real-search, $(dtb-y), .dtb, -dtbs)
|
||||||
# Base DTB that overlay is applied onto (each first word of $(*-dtbs) expansion)
|
# Base DTB that overlay is applied onto
|
||||||
base-dtb-y := $(foreach m, $(multi-dtb-y), $(firstword $(call suffix-search, $m, .dtb, -dtbs)))
|
base-dtb-y := $(filter %.dtb, $(call real-search, $(multi-dtb-y), .dtb, -dtbs))
|
||||||
|
|
||||||
always-y += $(dtb-y)
|
always-y += $(dtb-y)
|
||||||
|
|
||||||
|
@ -4,27 +4,6 @@
|
|||||||
include $(srctree)/scripts/Kbuild.include
|
include $(srctree)/scripts/Kbuild.include
|
||||||
include $(srctree)/scripts/Makefile.lib
|
include $(srctree)/scripts/Makefile.lib
|
||||||
|
|
||||||
KERNELPATH := kernel-$(subst -,_,$(KERNELRELEASE))
|
|
||||||
# Include only those top-level files that are needed by make, plus the GPL copy
|
|
||||||
TAR_CONTENT := Documentation LICENSES arch block certs crypto drivers fs \
|
|
||||||
include init io_uring ipc kernel lib mm net rust \
|
|
||||||
samples scripts security sound tools usr virt \
|
|
||||||
.config Makefile \
|
|
||||||
Kbuild Kconfig COPYING $(wildcard localversion*)
|
|
||||||
|
|
||||||
quiet_cmd_src_tar = TAR $(2).tar.gz
|
|
||||||
cmd_src_tar = \
|
|
||||||
if test "$(objtree)" != "$(srctree)"; then \
|
|
||||||
echo >&2; \
|
|
||||||
echo >&2 " ERROR:"; \
|
|
||||||
echo >&2 " Building source tarball is not possible outside the"; \
|
|
||||||
echo >&2 " kernel source tree. Don't set KBUILD_OUTPUT"; \
|
|
||||||
echo >&2; \
|
|
||||||
false; \
|
|
||||||
fi ; \
|
|
||||||
tar -I $(KGZIP) -c $(RCS_TAR_IGNORE) -f $(2).tar.gz \
|
|
||||||
--transform 's:^:$(2)/:S' $(TAR_CONTENT) $(3)
|
|
||||||
|
|
||||||
# Git
|
# Git
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -130,8 +109,6 @@ debian-orig: linux.tar$(debian-orig-suffix) debian
|
|||||||
cp $< ../$(orig-name); \
|
cp $< ../$(orig-name); \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
KBUILD_PKG_ROOTCMD ?= 'fakeroot -u'
|
|
||||||
|
|
||||||
PHONY += deb-pkg srcdeb-pkg bindeb-pkg
|
PHONY += deb-pkg srcdeb-pkg bindeb-pkg
|
||||||
|
|
||||||
deb-pkg: private build-type := source,binary
|
deb-pkg: private build-type := source,binary
|
||||||
@ -146,7 +123,7 @@ deb-pkg srcdeb-pkg bindeb-pkg:
|
|||||||
$(if $(findstring source, $(build-type)), \
|
$(if $(findstring source, $(build-type)), \
|
||||||
--unsigned-source --compression=$(KDEB_SOURCE_COMPRESS)) \
|
--unsigned-source --compression=$(KDEB_SOURCE_COMPRESS)) \
|
||||||
$(if $(findstring binary, $(build-type)), \
|
$(if $(findstring binary, $(build-type)), \
|
||||||
--rules-file='$(MAKE) -f debian/rules' --jobs=1 -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch), \
|
-R'$(MAKE) -f debian/rules' -j1 -a$$(cat debian/arch), \
|
||||||
--no-check-builddeps) \
|
--no-check-builddeps) \
|
||||||
$(DPKG_FLAGS))
|
$(DPKG_FLAGS))
|
||||||
|
|
||||||
@ -157,9 +134,8 @@ snap-pkg:
|
|||||||
rm -rf $(objtree)/snap
|
rm -rf $(objtree)/snap
|
||||||
mkdir $(objtree)/snap
|
mkdir $(objtree)/snap
|
||||||
$(MAKE) clean
|
$(MAKE) clean
|
||||||
$(call cmd,src_tar,$(KERNELPATH))
|
|
||||||
sed "s@KERNELRELEASE@$(KERNELRELEASE)@; \
|
sed "s@KERNELRELEASE@$(KERNELRELEASE)@; \
|
||||||
s@SRCTREE@$(shell realpath $(KERNELPATH).tar.gz)@" \
|
s@SRCTREE@$(abs_srctree)@" \
|
||||||
$(srctree)/scripts/package/snapcraft.template > \
|
$(srctree)/scripts/package/snapcraft.template > \
|
||||||
$(objtree)/snap/snapcraft.yaml
|
$(objtree)/snap/snapcraft.yaml
|
||||||
cd $(objtree)/snap && \
|
cd $(objtree)/snap && \
|
||||||
|
573
scripts/check-uapi.sh
Executable file
573
scripts/check-uapi.sh
Executable file
@ -0,0 +1,573 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
# Script to check commits for UAPI backwards compatibility
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
print_usage() {
|
||||||
|
name=$(basename "$0")
|
||||||
|
cat << EOF
|
||||||
|
$name - check for UAPI header stability across Git commits
|
||||||
|
|
||||||
|
By default, the script will check to make sure the latest commit (or current
|
||||||
|
dirty changes) did not introduce ABI changes when compared to HEAD^1. You can
|
||||||
|
check against additional commit ranges with the -b and -p options.
|
||||||
|
|
||||||
|
The script will not check UAPI headers for architectures other than the one
|
||||||
|
defined in ARCH.
|
||||||
|
|
||||||
|
Usage: $name [-b BASE_REF] [-p PAST_REF] [-j N] [-l ERROR_LOG] [-i] [-q] [-v]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-b BASE_REF Base git reference to use for comparison. If unspecified or empty,
|
||||||
|
will use any dirty changes in tree to UAPI files. If there are no
|
||||||
|
dirty changes, HEAD will be used.
|
||||||
|
-p PAST_REF Compare BASE_REF to PAST_REF (e.g. -p v6.1). If unspecified or empty,
|
||||||
|
will use BASE_REF^1. Must be an ancestor of BASE_REF. Only headers
|
||||||
|
that exist on PAST_REF will be checked for compatibility.
|
||||||
|
-j JOBS Number of checks to run in parallel (default: number of CPU cores).
|
||||||
|
-l ERROR_LOG Write error log to file (default: no error log is generated).
|
||||||
|
-i Ignore ambiguous changes that may or may not break UAPI compatibility.
|
||||||
|
-q Quiet operation.
|
||||||
|
-v Verbose operation (print more information about each header being checked).
|
||||||
|
|
||||||
|
Environmental args:
|
||||||
|
ABIDIFF Custom path to abidiff binary
|
||||||
|
CC C compiler (default is "gcc")
|
||||||
|
ARCH Target architecture for the UAPI check (default is host arch)
|
||||||
|
|
||||||
|
Exit codes:
|
||||||
|
$SUCCESS) Success
|
||||||
|
$FAIL_ABI) ABI difference detected
|
||||||
|
$FAIL_PREREQ) Prerequisite not met
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly SUCCESS=0
|
||||||
|
readonly FAIL_ABI=1
|
||||||
|
readonly FAIL_PREREQ=2
|
||||||
|
|
||||||
|
# Print to stderr
|
||||||
|
eprintf() {
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
printf "$@" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Expand an array with a specific character (similar to Python string.join())
|
||||||
|
join() {
|
||||||
|
local IFS="$1"
|
||||||
|
shift
|
||||||
|
printf "%s" "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create abidiff suppressions
|
||||||
|
gen_suppressions() {
|
||||||
|
# Common enum variant names which we don't want to worry about
|
||||||
|
# being shifted when new variants are added.
|
||||||
|
local -a enum_regex=(
|
||||||
|
".*_AFTER_LAST$"
|
||||||
|
".*_CNT$"
|
||||||
|
".*_COUNT$"
|
||||||
|
".*_END$"
|
||||||
|
".*_LAST$"
|
||||||
|
".*_MASK$"
|
||||||
|
".*_MAX$"
|
||||||
|
".*_MAX_BIT$"
|
||||||
|
".*_MAX_BPF_ATTACH_TYPE$"
|
||||||
|
".*_MAX_ID$"
|
||||||
|
".*_MAX_SHIFT$"
|
||||||
|
".*_NBITS$"
|
||||||
|
".*_NETDEV_NUMHOOKS$"
|
||||||
|
".*_NFT_META_IIFTYPE$"
|
||||||
|
".*_NL80211_ATTR$"
|
||||||
|
".*_NLDEV_NUM_OPS$"
|
||||||
|
".*_NUM$"
|
||||||
|
".*_NUM_ELEMS$"
|
||||||
|
".*_NUM_IRQS$"
|
||||||
|
".*_SIZE$"
|
||||||
|
".*_TLSMAX$"
|
||||||
|
"^MAX_.*"
|
||||||
|
"^NUM_.*"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Common padding field names which can be expanded into
|
||||||
|
# without worrying about users.
|
||||||
|
local -a padding_regex=(
|
||||||
|
".*end$"
|
||||||
|
".*pad$"
|
||||||
|
".*pad[0-9]?$"
|
||||||
|
".*pad_[0-9]?$"
|
||||||
|
".*padding$"
|
||||||
|
".*padding[0-9]?$"
|
||||||
|
".*padding_[0-9]?$"
|
||||||
|
".*res$"
|
||||||
|
".*resv$"
|
||||||
|
".*resv[0-9]?$"
|
||||||
|
".*resv_[0-9]?$"
|
||||||
|
".*reserved$"
|
||||||
|
".*reserved[0-9]?$"
|
||||||
|
".*reserved_[0-9]?$"
|
||||||
|
".*rsvd[0-9]?$"
|
||||||
|
".*unused$"
|
||||||
|
)
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
[suppress_type]
|
||||||
|
type_kind = enum
|
||||||
|
changed_enumerators_regexp = $(join , "${enum_regex[@]}")
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for p in "${padding_regex[@]}"; do
|
||||||
|
cat << EOF
|
||||||
|
[suppress_type]
|
||||||
|
type_kind = struct
|
||||||
|
has_data_member_inserted_at = offset_of_first_data_member_regexp(${p})
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$IGNORE_AMBIGUOUS_CHANGES" = "true" ]; then
|
||||||
|
cat << EOF
|
||||||
|
[suppress_type]
|
||||||
|
type_kind = struct
|
||||||
|
has_data_member_inserted_at = end
|
||||||
|
has_size_change = yes
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if git tree is dirty
|
||||||
|
tree_is_dirty() {
|
||||||
|
! git diff --quiet
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get list of files installed in $ref
|
||||||
|
get_file_list() {
|
||||||
|
local -r ref="$1"
|
||||||
|
local -r tree="$(get_header_tree "$ref")"
|
||||||
|
|
||||||
|
# Print all installed headers, filtering out ones that can't be compiled
|
||||||
|
find "$tree" -type f -name '*.h' -printf '%P\n' | grep -v -f "$INCOMPAT_LIST"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add to the list of incompatible headers
|
||||||
|
add_to_incompat_list() {
|
||||||
|
local -r ref="$1"
|
||||||
|
|
||||||
|
# Start with the usr/include/Makefile to get a list of the headers
|
||||||
|
# that don't compile using this method.
|
||||||
|
if [ ! -f usr/include/Makefile ]; then
|
||||||
|
eprintf "error - no usr/include/Makefile present at %s\n" "$ref"
|
||||||
|
eprintf "Note: usr/include/Makefile was added in the v5.3 kernel release\n"
|
||||||
|
exit "$FAIL_PREREQ"
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
printf 'all: ; @echo $(no-header-test)\n'
|
||||||
|
cat usr/include/Makefile
|
||||||
|
} | SRCARCH="$ARCH" make --always-make -f - | tr " " "\n" \
|
||||||
|
| grep -v "asm-generic" >> "$INCOMPAT_LIST"
|
||||||
|
|
||||||
|
# The makefile also skips all asm-generic files, but prints "asm-generic/%"
|
||||||
|
# which won't work for our grep match. Instead, print something grep will match.
|
||||||
|
printf "asm-generic/.*\.h\n" >> "$INCOMPAT_LIST"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compile the simple test app
|
||||||
|
do_compile() {
|
||||||
|
local -r inc_dir="$1"
|
||||||
|
local -r header="$2"
|
||||||
|
local -r out="$3"
|
||||||
|
printf "int main(void) { return 0; }\n" | \
|
||||||
|
"$CC" -c \
|
||||||
|
-o "$out" \
|
||||||
|
-x c \
|
||||||
|
-O0 \
|
||||||
|
-std=c90 \
|
||||||
|
-fno-eliminate-unused-debug-types \
|
||||||
|
-g \
|
||||||
|
"-I${inc_dir}" \
|
||||||
|
-include "$header" \
|
||||||
|
-
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run make headers_install
|
||||||
|
run_make_headers_install() {
|
||||||
|
local -r ref="$1"
|
||||||
|
local -r install_dir="$(get_header_tree "$ref")"
|
||||||
|
make -j "$MAX_THREADS" ARCH="$ARCH" INSTALL_HDR_PATH="$install_dir" \
|
||||||
|
headers_install > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install headers for both git refs
|
||||||
|
install_headers() {
|
||||||
|
local -r base_ref="$1"
|
||||||
|
local -r past_ref="$2"
|
||||||
|
|
||||||
|
for ref in "$base_ref" "$past_ref"; do
|
||||||
|
printf "Installing user-facing UAPI headers from %s... " "${ref:-dirty tree}"
|
||||||
|
if [ -n "$ref" ]; then
|
||||||
|
git archive --format=tar --prefix="${ref}-archive/" "$ref" \
|
||||||
|
| (cd "$TMP_DIR" && tar xf -)
|
||||||
|
(
|
||||||
|
cd "${TMP_DIR}/${ref}-archive"
|
||||||
|
run_make_headers_install "$ref"
|
||||||
|
add_to_incompat_list "$ref" "$INCOMPAT_LIST"
|
||||||
|
)
|
||||||
|
else
|
||||||
|
run_make_headers_install "$ref"
|
||||||
|
add_to_incompat_list "$ref" "$INCOMPAT_LIST"
|
||||||
|
fi
|
||||||
|
printf "OK\n"
|
||||||
|
done
|
||||||
|
sort -u -o "$INCOMPAT_LIST" "$INCOMPAT_LIST"
|
||||||
|
sed -i -e '/^$/d' "$INCOMPAT_LIST"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print the path to the headers_install tree for a given ref
|
||||||
|
get_header_tree() {
|
||||||
|
local -r ref="$1"
|
||||||
|
printf "%s" "${TMP_DIR}/${ref}/usr"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check file list for UAPI compatibility
|
||||||
|
check_uapi_files() {
|
||||||
|
local -r base_ref="$1"
|
||||||
|
local -r past_ref="$2"
|
||||||
|
local -r abi_error_log="$3"
|
||||||
|
|
||||||
|
local passed=0;
|
||||||
|
local failed=0;
|
||||||
|
local -a threads=()
|
||||||
|
set -o errexit
|
||||||
|
|
||||||
|
printf "Checking changes to UAPI headers between %s and %s...\n" "$past_ref" "${base_ref:-dirty tree}"
|
||||||
|
# Loop over all UAPI headers that were installed by $past_ref (if they only exist on $base_ref,
|
||||||
|
# there's no way they're broken and no way to compare anyway)
|
||||||
|
while read -r file; do
|
||||||
|
if [ "${#threads[@]}" -ge "$MAX_THREADS" ]; then
|
||||||
|
if wait "${threads[0]}"; then
|
||||||
|
passed=$((passed + 1))
|
||||||
|
else
|
||||||
|
failed=$((failed + 1))
|
||||||
|
fi
|
||||||
|
threads=("${threads[@]:1}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_individual_file "$base_ref" "$past_ref" "$file" &
|
||||||
|
threads+=("$!")
|
||||||
|
done < <(get_file_list "$past_ref")
|
||||||
|
|
||||||
|
for t in "${threads[@]}"; do
|
||||||
|
if wait "$t"; then
|
||||||
|
passed=$((passed + 1))
|
||||||
|
else
|
||||||
|
failed=$((failed + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$abi_error_log" ]; then
|
||||||
|
printf 'Generated by "%s %s" from git ref %s\n\n' \
|
||||||
|
"$0" "$*" "$(git rev-parse HEAD)" > "$abi_error_log"
|
||||||
|
fi
|
||||||
|
|
||||||
|
while read -r error_file; do
|
||||||
|
{
|
||||||
|
cat "$error_file"
|
||||||
|
printf "\n\n"
|
||||||
|
} | tee -a "${abi_error_log:-/dev/null}" >&2
|
||||||
|
done < <(find "$TMP_DIR" -type f -name '*.error' | sort)
|
||||||
|
|
||||||
|
total="$((passed + failed))"
|
||||||
|
if [ "$failed" -gt 0 ]; then
|
||||||
|
eprintf "error - %d/%d UAPI headers compatible with %s appear _not_ to be backwards compatible\n" \
|
||||||
|
"$failed" "$total" "$ARCH"
|
||||||
|
if [ -n "$abi_error_log" ]; then
|
||||||
|
eprintf "Failure summary saved to %s\n" "$abi_error_log"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
printf "All %d UAPI headers compatible with %s appear to be backwards compatible\n" \
|
||||||
|
"$total" "$ARCH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return "$failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check an individual file for UAPI compatibility
|
||||||
|
check_individual_file() {
|
||||||
|
local -r base_ref="$1"
|
||||||
|
local -r past_ref="$2"
|
||||||
|
local -r file="$3"
|
||||||
|
|
||||||
|
local -r base_header="$(get_header_tree "$base_ref")/${file}"
|
||||||
|
local -r past_header="$(get_header_tree "$past_ref")/${file}"
|
||||||
|
|
||||||
|
if [ ! -f "$base_header" ]; then
|
||||||
|
mkdir -p "$(dirname "$base_header")"
|
||||||
|
printf "==== UAPI header %s was removed between %s and %s ====" \
|
||||||
|
"$file" "$past_ref" "$base_ref" \
|
||||||
|
> "${base_header}.error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
compare_abi "$file" "$base_header" "$past_header" "$base_ref" "$past_ref"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Perform the A/B compilation and compare output ABI
|
||||||
|
compare_abi() {
|
||||||
|
local -r file="$1"
|
||||||
|
local -r base_header="$2"
|
||||||
|
local -r past_header="$3"
|
||||||
|
local -r base_ref="$4"
|
||||||
|
local -r past_ref="$5"
|
||||||
|
local -r log="${TMP_DIR}/log/${file}.log"
|
||||||
|
local -r error_log="${TMP_DIR}/log/${file}.error"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$log")"
|
||||||
|
|
||||||
|
if ! do_compile "$(get_header_tree "$base_ref")/include" "$base_header" "${base_header}.bin" 2> "$log"; then
|
||||||
|
{
|
||||||
|
warn_str=$(printf "==== Could not compile version of UAPI header %s at %s ====\n" \
|
||||||
|
"$file" "$base_ref")
|
||||||
|
printf "%s\n" "$warn_str"
|
||||||
|
cat "$log"
|
||||||
|
printf -- "=%.0s" $(seq 0 ${#warn_str})
|
||||||
|
} > "$error_log"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! do_compile "$(get_header_tree "$past_ref")/include" "$past_header" "${past_header}.bin" 2> "$log"; then
|
||||||
|
{
|
||||||
|
warn_str=$(printf "==== Could not compile version of UAPI header %s at %s ====\n" \
|
||||||
|
"$file" "$past_ref")
|
||||||
|
printf "%s\n" "$warn_str"
|
||||||
|
cat "$log"
|
||||||
|
printf -- "=%.0s" $(seq 0 ${#warn_str})
|
||||||
|
} > "$error_log"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local ret=0
|
||||||
|
"$ABIDIFF" --non-reachable-types \
|
||||||
|
--suppressions "$SUPPRESSIONS" \
|
||||||
|
"${past_header}.bin" "${base_header}.bin" > "$log" || ret="$?"
|
||||||
|
if [ "$ret" -eq 0 ]; then
|
||||||
|
if [ "$VERBOSE" = "true" ]; then
|
||||||
|
printf "No ABI differences detected in %s from %s -> %s\n" \
|
||||||
|
"$file" "$past_ref" "$base_ref"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Bits in abidiff's return code can be used to determine the type of error
|
||||||
|
if [ $((ret & 0x2)) -gt 0 ]; then
|
||||||
|
eprintf "error - abidiff did not run properly\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$IGNORE_AMBIGUOUS_CHANGES" = "true" ] && [ "$ret" -eq 4 ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If the only changes were additions (not modifications to existing APIs), then
|
||||||
|
# there's no problem. Ignore these diffs.
|
||||||
|
if grep "Unreachable types summary" "$log" | grep -q "0 removed" &&
|
||||||
|
grep "Unreachable types summary" "$log" | grep -q "0 changed"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
warn_str=$(printf "==== ABI differences detected in %s from %s -> %s ====" \
|
||||||
|
"$file" "$past_ref" "$base_ref")
|
||||||
|
printf "%s\n" "$warn_str"
|
||||||
|
sed -e '/summary:/d' -e '/changed type/d' -e '/^$/d' -e 's/^/ /g' "$log"
|
||||||
|
printf -- "=%.0s" $(seq 0 ${#warn_str})
|
||||||
|
if cmp "$past_header" "$base_header" > /dev/null 2>&1; then
|
||||||
|
printf "\n%s did not change between %s and %s...\n" "$file" "$past_ref" "${base_ref:-dirty tree}"
|
||||||
|
printf "It's possible a change to one of the headers it includes caused this error:\n"
|
||||||
|
grep '^#include' "$base_header"
|
||||||
|
printf "\n"
|
||||||
|
fi
|
||||||
|
} > "$error_log"
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check that a minimum software version number is satisfied
|
||||||
|
min_version_is_satisfied() {
|
||||||
|
local -r min_version="$1"
|
||||||
|
local -r version_installed="$2"
|
||||||
|
|
||||||
|
printf "%s\n%s\n" "$min_version" "$version_installed" \
|
||||||
|
| sort -Vc > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure we have the tools we need and the arguments make sense
|
||||||
|
check_deps() {
|
||||||
|
ABIDIFF="${ABIDIFF:-abidiff}"
|
||||||
|
CC="${CC:-gcc}"
|
||||||
|
ARCH="${ARCH:-$(uname -m)}"
|
||||||
|
if [ "$ARCH" = "x86_64" ]; then
|
||||||
|
ARCH="x86"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -r abidiff_min_version="2.4"
|
||||||
|
local -r libdw_min_version_if_clang="0.171"
|
||||||
|
|
||||||
|
if ! command -v "$ABIDIFF" > /dev/null 2>&1; then
|
||||||
|
eprintf "error - abidiff not found!\n"
|
||||||
|
eprintf "Please install abigail-tools version %s or greater\n" "$abidiff_min_version"
|
||||||
|
eprintf "See: https://sourceware.org/libabigail/manual/libabigail-overview.html\n"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -r abidiff_version="$("$ABIDIFF" --version | cut -d ' ' -f 2)"
|
||||||
|
if ! min_version_is_satisfied "$abidiff_min_version" "$abidiff_version"; then
|
||||||
|
eprintf "error - abidiff version too old: %s\n" "$abidiff_version"
|
||||||
|
eprintf "Please install abigail-tools version %s or greater\n" "$abidiff_min_version"
|
||||||
|
eprintf "See: https://sourceware.org/libabigail/manual/libabigail-overview.html\n"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v "$CC" > /dev/null 2>&1; then
|
||||||
|
eprintf 'error - %s not found\n' "$CC"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if "$CC" --version | grep -q clang; then
|
||||||
|
local -r libdw_version="$(ldconfig -v 2>/dev/null | grep -v SKIPPED | grep -m 1 -o 'libdw-[0-9]\+.[0-9]\+' | cut -c 7-)"
|
||||||
|
if ! min_version_is_satisfied "$libdw_min_version_if_clang" "$libdw_version"; then
|
||||||
|
eprintf "error - libdw version too old for use with clang: %s\n" "$libdw_version"
|
||||||
|
eprintf "Please install libdw from elfutils version %s or greater\n" "$libdw_min_version_if_clang"
|
||||||
|
eprintf "See: https://sourceware.org/elfutils/\n"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "arch/${ARCH}" ]; then
|
||||||
|
eprintf 'error - ARCH "%s" is not a subdirectory under arch/\n' "$ARCH"
|
||||||
|
eprintf "Please set ARCH to one of:\n%s\n" "$(find arch -maxdepth 1 -mindepth 1 -type d -printf '%f ' | fmt)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
|
||||||
|
eprintf "error - this script requires the kernel tree to be initialized with Git\n"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git rev-parse --verify "$past_ref" > /dev/null 2>&1; then
|
||||||
|
printf 'error - invalid git reference "%s"\n' "$past_ref"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$base_ref" ]; then
|
||||||
|
if ! git merge-base --is-ancestor "$past_ref" "$base_ref" > /dev/null 2>&1; then
|
||||||
|
printf 'error - "%s" is not an ancestor of base ref "%s"\n' "$past_ref" "$base_ref"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ "$(git rev-parse "$base_ref")" = "$(git rev-parse "$past_ref")" ]; then
|
||||||
|
printf 'error - "%s" and "%s" are the same reference\n' "$past_ref" "$base_ref"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run() {
|
||||||
|
local base_ref="$1"
|
||||||
|
local past_ref="$2"
|
||||||
|
local abi_error_log="$3"
|
||||||
|
shift 3
|
||||||
|
|
||||||
|
if [ -z "$KERNEL_SRC" ]; then
|
||||||
|
KERNEL_SRC="$(realpath "$(dirname "$0")"/..)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$KERNEL_SRC"
|
||||||
|
|
||||||
|
if [ -z "$base_ref" ] && ! tree_is_dirty; then
|
||||||
|
base_ref=HEAD
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$past_ref" ]; then
|
||||||
|
if [ -n "$base_ref" ]; then
|
||||||
|
past_ref="${base_ref}^1"
|
||||||
|
else
|
||||||
|
past_ref=HEAD
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! check_deps; then
|
||||||
|
exit "$FAIL_PREREQ"
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
readonly TMP_DIR
|
||||||
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||||
|
|
||||||
|
readonly INCOMPAT_LIST="${TMP_DIR}/incompat_list.txt"
|
||||||
|
touch "$INCOMPAT_LIST"
|
||||||
|
|
||||||
|
readonly SUPPRESSIONS="${TMP_DIR}/suppressions.txt"
|
||||||
|
gen_suppressions > "$SUPPRESSIONS"
|
||||||
|
|
||||||
|
# Run make install_headers for both refs
|
||||||
|
install_headers "$base_ref" "$past_ref"
|
||||||
|
|
||||||
|
# Check for any differences in the installed header trees
|
||||||
|
if diff -r -q "$(get_header_tree "$base_ref")" "$(get_header_tree "$past_ref")" > /dev/null 2>&1; then
|
||||||
|
printf "No changes to UAPI headers were applied between %s and %s\n" "$past_ref" "${base_ref:-dirty tree}"
|
||||||
|
exit "$SUCCESS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! check_uapi_files "$base_ref" "$past_ref" "$abi_error_log"; then
|
||||||
|
exit "$FAIL_ABI"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
MAX_THREADS=$(nproc)
|
||||||
|
VERBOSE="false"
|
||||||
|
IGNORE_AMBIGUOUS_CHANGES="false"
|
||||||
|
quiet="false"
|
||||||
|
local base_ref=""
|
||||||
|
while getopts "hb:p:j:l:iqv" opt; do
|
||||||
|
case $opt in
|
||||||
|
h)
|
||||||
|
print_usage
|
||||||
|
exit "$SUCCESS"
|
||||||
|
;;
|
||||||
|
b)
|
||||||
|
base_ref="$OPTARG"
|
||||||
|
;;
|
||||||
|
p)
|
||||||
|
past_ref="$OPTARG"
|
||||||
|
;;
|
||||||
|
j)
|
||||||
|
MAX_THREADS="$OPTARG"
|
||||||
|
;;
|
||||||
|
l)
|
||||||
|
abi_error_log="$OPTARG"
|
||||||
|
;;
|
||||||
|
i)
|
||||||
|
IGNORE_AMBIGUOUS_CHANGES="true"
|
||||||
|
;;
|
||||||
|
q)
|
||||||
|
quiet="true"
|
||||||
|
VERBOSE="false"
|
||||||
|
;;
|
||||||
|
v)
|
||||||
|
VERBOSE="true"
|
||||||
|
quiet="false"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exit "$FAIL_PREREQ"
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$quiet" = "true" ]; then
|
||||||
|
exec > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
run "$base_ref" "$past_ref" "$abi_error_log" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
@ -82,21 +82,12 @@ LxPs()
|
|||||||
|
|
||||||
thread_info_type = utils.CachedType("struct thread_info")
|
thread_info_type = utils.CachedType("struct thread_info")
|
||||||
|
|
||||||
ia64_task_size = None
|
|
||||||
|
|
||||||
|
|
||||||
def get_thread_info(task):
|
def get_thread_info(task):
|
||||||
thread_info_ptr_type = thread_info_type.get_type().pointer()
|
thread_info_ptr_type = thread_info_type.get_type().pointer()
|
||||||
if utils.is_target_arch("ia64"):
|
if task.type.fields()[0].type == thread_info_type.get_type():
|
||||||
global ia64_task_size
|
return task['thread_info']
|
||||||
if ia64_task_size is None:
|
thread_info = task['stack'].cast(thread_info_ptr_type)
|
||||||
ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)")
|
|
||||||
thread_info_addr = task.address + ia64_task_size
|
|
||||||
thread_info = thread_info_addr.cast(thread_info_ptr_type)
|
|
||||||
else:
|
|
||||||
if task.type.fields()[0].type == thread_info_type.get_type():
|
|
||||||
return task['thread_info']
|
|
||||||
thread_info = task['stack'].cast(thread_info_ptr_type)
|
|
||||||
return thread_info.dereference()
|
return thread_info.dereference()
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,9 +16,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#ifdef __GNU_LIBRARY__
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#endif /* __GNU_LIBRARY__ */
|
|
||||||
|
|
||||||
#include "genksyms.h"
|
#include "genksyms.h"
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
@ -718,8 +716,6 @@ void error_with_pos(const char *fmt, ...)
|
|||||||
static void genksyms_usage(void)
|
static void genksyms_usage(void)
|
||||||
{
|
{
|
||||||
fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
|
fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
|
||||||
#ifdef __GNU_LIBRARY__
|
|
||||||
" -s, --symbol-prefix Select symbol prefix\n"
|
|
||||||
" -d, --debug Increment the debug level (repeatable)\n"
|
" -d, --debug Increment the debug level (repeatable)\n"
|
||||||
" -D, --dump Dump expanded symbol defs (for debugging only)\n"
|
" -D, --dump Dump expanded symbol defs (for debugging only)\n"
|
||||||
" -r, --reference file Read reference symbols from a file\n"
|
" -r, --reference file Read reference symbols from a file\n"
|
||||||
@ -729,18 +725,6 @@ static void genksyms_usage(void)
|
|||||||
" -q, --quiet Disable warnings (default)\n"
|
" -q, --quiet Disable warnings (default)\n"
|
||||||
" -h, --help Print this message\n"
|
" -h, --help Print this message\n"
|
||||||
" -V, --version Print the release version\n"
|
" -V, --version Print the release version\n"
|
||||||
#else /* __GNU_LIBRARY__ */
|
|
||||||
" -s Select symbol prefix\n"
|
|
||||||
" -d Increment the debug level (repeatable)\n"
|
|
||||||
" -D Dump expanded symbol defs (for debugging only)\n"
|
|
||||||
" -r file Read reference symbols from a file\n"
|
|
||||||
" -T file Dump expanded types into file\n"
|
|
||||||
" -p Preserve reference modversions or fail\n"
|
|
||||||
" -w Enable warnings\n"
|
|
||||||
" -q Disable warnings (default)\n"
|
|
||||||
" -h Print this message\n"
|
|
||||||
" -V Print the release version\n"
|
|
||||||
#endif /* __GNU_LIBRARY__ */
|
|
||||||
, stderr);
|
, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,7 +733,6 @@ int main(int argc, char **argv)
|
|||||||
FILE *dumpfile = NULL, *ref_file = NULL;
|
FILE *dumpfile = NULL, *ref_file = NULL;
|
||||||
int o;
|
int o;
|
||||||
|
|
||||||
#ifdef __GNU_LIBRARY__
|
|
||||||
struct option long_opts[] = {
|
struct option long_opts[] = {
|
||||||
{"debug", 0, 0, 'd'},
|
{"debug", 0, 0, 'd'},
|
||||||
{"warnings", 0, 0, 'w'},
|
{"warnings", 0, 0, 'w'},
|
||||||
@ -763,11 +746,8 @@ int main(int argc, char **argv)
|
|||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
|
while ((o = getopt_long(argc, argv, "dwqVDr:T:ph",
|
||||||
&long_opts[0], NULL)) != EOF)
|
&long_opts[0], NULL)) != EOF)
|
||||||
#else /* __GNU_LIBRARY__ */
|
|
||||||
while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
|
|
||||||
#endif /* __GNU_LIBRARY__ */
|
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case 'd':
|
case 'd':
|
||||||
flag_debug++;
|
flag_debug++;
|
||||||
|
42
scripts/git.orderFile
Normal file
42
scripts/git.orderFile
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
# order file for git, to produce patches which are easier to review
|
||||||
|
# by diffing the important stuff like header changes first.
|
||||||
|
#
|
||||||
|
# one-off usage:
|
||||||
|
# git diff -O scripts/git.orderFile ...
|
||||||
|
#
|
||||||
|
# add to git config:
|
||||||
|
# git config diff.orderFile scripts/git.orderFile
|
||||||
|
#
|
||||||
|
|
||||||
|
MAINTAINERS
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
Documentation/*
|
||||||
|
*.rst
|
||||||
|
|
||||||
|
# git-specific
|
||||||
|
.gitignore
|
||||||
|
scripts/git.orderFile
|
||||||
|
|
||||||
|
# build system
|
||||||
|
Kconfig*
|
||||||
|
*/Kconfig*
|
||||||
|
Kbuild*
|
||||||
|
*/Kbuild*
|
||||||
|
Makefile*
|
||||||
|
*/Makefile*
|
||||||
|
*.mak
|
||||||
|
*.mk
|
||||||
|
scripts/*
|
||||||
|
|
||||||
|
# semantic patches
|
||||||
|
*.cocci
|
||||||
|
|
||||||
|
# headers
|
||||||
|
*types.h
|
||||||
|
*.h
|
||||||
|
|
||||||
|
# code
|
||||||
|
*.c
|
@ -17,7 +17,6 @@ arch/arm/kernel/head-nommu.o
|
|||||||
arch/arm/kernel/head.o
|
arch/arm/kernel/head.o
|
||||||
arch/csky/kernel/head.o
|
arch/csky/kernel/head.o
|
||||||
arch/hexagon/kernel/head.o
|
arch/hexagon/kernel/head.o
|
||||||
arch/ia64/kernel/head.o
|
|
||||||
arch/loongarch/kernel/head.o
|
arch/loongarch/kernel/head.o
|
||||||
arch/m68k/68000/head.o
|
arch/m68k/68000/head.o
|
||||||
arch/m68k/coldfire/head.o
|
arch/m68k/coldfire/head.o
|
||||||
|
@ -27,6 +27,14 @@ KCONFIG_DEFCONFIG_LIST += \
|
|||||||
endif
|
endif
|
||||||
KCONFIG_DEFCONFIG_LIST += arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)
|
KCONFIG_DEFCONFIG_LIST += arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)
|
||||||
|
|
||||||
|
ifneq ($(findstring c, $(KBUILD_EXTRA_WARN)),)
|
||||||
|
export KCONFIG_WARN_UNKNOWN_SYMBOLS=1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(findstring e, $(KBUILD_EXTRA_WARN)),)
|
||||||
|
export KCONFIG_WERROR=1
|
||||||
|
endif
|
||||||
|
|
||||||
# We need this, in case the user has it in its environment
|
# We need this, in case the user has it in its environment
|
||||||
unexport CONFIG_
|
unexport CONFIG_
|
||||||
|
|
||||||
@ -99,7 +107,7 @@ config-fragments = $(call configfiles,$@)
|
|||||||
|
|
||||||
%.config: $(obj)/conf
|
%.config: $(obj)/conf
|
||||||
$(if $(config-fragments),, $(error $@ fragment does not exists on this architecture))
|
$(if $(config-fragments),, $(error $@ fragment does not exists on this architecture))
|
||||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(config-fragments)
|
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments)
|
||||||
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
|
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
|
||||||
|
|
||||||
PHONY += tinyconfig
|
PHONY += tinyconfig
|
||||||
@ -166,7 +174,7 @@ conf-objs := conf.o $(common-objs)
|
|||||||
|
|
||||||
# nconf: Used for the nconfig target based on ncurses
|
# nconf: Used for the nconfig target based on ncurses
|
||||||
hostprogs += nconf
|
hostprogs += nconf
|
||||||
nconf-objs := nconf.o nconf.gui.o $(common-objs)
|
nconf-objs := nconf.o nconf.gui.o mnconf-common.o $(common-objs)
|
||||||
|
|
||||||
HOSTLDLIBS_nconf = $(call read-file, $(obj)/nconf-libs)
|
HOSTLDLIBS_nconf = $(call read-file, $(obj)/nconf-libs)
|
||||||
HOSTCFLAGS_nconf.o = $(call read-file, $(obj)/nconf-cflags)
|
HOSTCFLAGS_nconf.o = $(call read-file, $(obj)/nconf-cflags)
|
||||||
@ -179,7 +187,7 @@ $(obj)/nconf.o $(obj)/nconf.gui.o: | $(obj)/nconf-cflags
|
|||||||
hostprogs += mconf
|
hostprogs += mconf
|
||||||
lxdialog := $(addprefix lxdialog/, \
|
lxdialog := $(addprefix lxdialog/, \
|
||||||
checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
|
checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
|
||||||
mconf-objs := mconf.o $(lxdialog) $(common-objs)
|
mconf-objs := mconf.o $(lxdialog) mnconf-common.o $(common-objs)
|
||||||
|
|
||||||
HOSTLDLIBS_mconf = $(call read-file, $(obj)/mconf-libs)
|
HOSTLDLIBS_mconf = $(call read-file, $(obj)/mconf-libs)
|
||||||
$(foreach f, mconf.o $(lxdialog), \
|
$(foreach f, mconf.o $(lxdialog), \
|
||||||
|
@ -827,6 +827,9 @@ int main(int ac, char **av)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conf_errors())
|
||||||
|
exit(1);
|
||||||
|
|
||||||
if (sync_kconfig) {
|
if (sync_kconfig) {
|
||||||
name = getenv("KCONFIG_NOSILENTUPDATE");
|
name = getenv("KCONFIG_NOSILENTUPDATE");
|
||||||
if (name && *name) {
|
if (name && *name) {
|
||||||
@ -890,6 +893,9 @@ int main(int ac, char **av)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sym_dep_errors())
|
||||||
|
exit(1);
|
||||||
|
|
||||||
if (input_mode == savedefconfig) {
|
if (input_mode == savedefconfig) {
|
||||||
if (conf_write_defconfig(defconfig_file)) {
|
if (conf_write_defconfig(defconfig_file)) {
|
||||||
fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
|
fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
|
||||||
|
@ -155,6 +155,13 @@ static void conf_message(const char *fmt, ...)
|
|||||||
static const char *conf_filename;
|
static const char *conf_filename;
|
||||||
static int conf_lineno, conf_warnings;
|
static int conf_lineno, conf_warnings;
|
||||||
|
|
||||||
|
bool conf_errors(void)
|
||||||
|
{
|
||||||
|
if (conf_warnings)
|
||||||
|
return getenv("KCONFIG_WERROR");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void conf_warning(const char *fmt, ...)
|
static void conf_warning(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@ -289,16 +296,12 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|||||||
#define LINE_GROWTH 16
|
#define LINE_GROWTH 16
|
||||||
static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
|
static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
|
||||||
{
|
{
|
||||||
char *nline;
|
|
||||||
size_t new_size = slen + 1;
|
size_t new_size = slen + 1;
|
||||||
|
|
||||||
if (new_size > *n) {
|
if (new_size > *n) {
|
||||||
new_size += LINE_GROWTH - 1;
|
new_size += LINE_GROWTH - 1;
|
||||||
new_size *= 2;
|
new_size *= 2;
|
||||||
nline = xrealloc(*lineptr, new_size);
|
*lineptr = xrealloc(*lineptr, new_size);
|
||||||
if (!nline)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
*lineptr = nline;
|
|
||||||
*n = new_size;
|
*n = new_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,19 +344,37 @@ e_out:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* like getline(), but the newline character is stripped away */
|
||||||
|
static ssize_t getline_stripped(char **lineptr, size_t *n, FILE *stream)
|
||||||
|
{
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
len = compat_getline(lineptr, n, stream);
|
||||||
|
|
||||||
|
if (len > 0 && (*lineptr)[len - 1] == '\n') {
|
||||||
|
len--;
|
||||||
|
(*lineptr)[len] = '\0';
|
||||||
|
|
||||||
|
if (len > 0 && (*lineptr)[len - 1] == '\r') {
|
||||||
|
len--;
|
||||||
|
(*lineptr)[len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
int conf_read_simple(const char *name, int def)
|
int conf_read_simple(const char *name, int def)
|
||||||
{
|
{
|
||||||
FILE *in = NULL;
|
FILE *in = NULL;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t line_asize = 0;
|
size_t line_asize = 0;
|
||||||
char *p, *p2;
|
char *p, *val;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
int i, def_flags;
|
int i, def_flags;
|
||||||
const char *warn_unknown;
|
const char *warn_unknown, *sym_name;
|
||||||
const char *werror;
|
|
||||||
|
|
||||||
warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS");
|
warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS");
|
||||||
werror = getenv("KCONFIG_WERROR");
|
|
||||||
if (name) {
|
if (name) {
|
||||||
in = zconf_fopen(name);
|
in = zconf_fopen(name);
|
||||||
} else {
|
} else {
|
||||||
@ -417,8 +438,7 @@ load:
|
|||||||
case S_INT:
|
case S_INT:
|
||||||
case S_HEX:
|
case S_HEX:
|
||||||
case S_STRING:
|
case S_STRING:
|
||||||
if (sym->def[def].val)
|
free(sym->def[def].val);
|
||||||
free(sym->def[def].val);
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
sym->def[def].val = NULL;
|
sym->def[def].val = NULL;
|
||||||
@ -426,90 +446,68 @@ load:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (compat_getline(&line, &line_asize, in) != -1) {
|
while (getline_stripped(&line, &line_asize, in) != -1) {
|
||||||
conf_lineno++;
|
conf_lineno++;
|
||||||
sym = NULL;
|
|
||||||
|
if (!line[0]) /* blank line */
|
||||||
|
continue;
|
||||||
|
|
||||||
if (line[0] == '#') {
|
if (line[0] == '#') {
|
||||||
if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
|
if (line[1] != ' ')
|
||||||
continue;
|
continue;
|
||||||
p = strchr(line + 2 + strlen(CONFIG_), ' ');
|
p = line + 2;
|
||||||
|
if (memcmp(p, CONFIG_, strlen(CONFIG_)))
|
||||||
|
continue;
|
||||||
|
sym_name = p + strlen(CONFIG_);
|
||||||
|
p = strchr(sym_name, ' ');
|
||||||
if (!p)
|
if (!p)
|
||||||
continue;
|
continue;
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
if (strncmp(p, "is not set", 10))
|
if (strcmp(p, "is not set"))
|
||||||
continue;
|
continue;
|
||||||
if (def == S_DEF_USER) {
|
|
||||||
sym = sym_find(line + 2 + strlen(CONFIG_));
|
|
||||||
if (!sym) {
|
|
||||||
if (warn_unknown)
|
|
||||||
conf_warning("unknown symbol: %s",
|
|
||||||
line + 2 + strlen(CONFIG_));
|
|
||||||
|
|
||||||
conf_set_changed(true);
|
val = "n";
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
|
|
||||||
if (sym->type == S_UNKNOWN)
|
|
||||||
sym->type = S_BOOLEAN;
|
|
||||||
}
|
|
||||||
if (sym->flags & def_flags) {
|
|
||||||
conf_warning("override: reassigning to symbol %s", sym->name);
|
|
||||||
}
|
|
||||||
switch (sym->type) {
|
|
||||||
case S_BOOLEAN:
|
|
||||||
case S_TRISTATE:
|
|
||||||
sym->def[def].tri = no;
|
|
||||||
sym->flags |= def_flags;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
|
|
||||||
p = strchr(line + strlen(CONFIG_), '=');
|
|
||||||
if (!p)
|
|
||||||
continue;
|
|
||||||
*p++ = 0;
|
|
||||||
p2 = strchr(p, '\n');
|
|
||||||
if (p2) {
|
|
||||||
*p2-- = 0;
|
|
||||||
if (*p2 == '\r')
|
|
||||||
*p2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sym = sym_find(line + strlen(CONFIG_));
|
|
||||||
if (!sym) {
|
|
||||||
if (def == S_DEF_AUTO) {
|
|
||||||
/*
|
|
||||||
* Reading from include/config/auto.conf
|
|
||||||
* If CONFIG_FOO previously existed in
|
|
||||||
* auto.conf but it is missing now,
|
|
||||||
* include/config/FOO must be touched.
|
|
||||||
*/
|
|
||||||
conf_touch_dep(line + strlen(CONFIG_));
|
|
||||||
} else {
|
|
||||||
if (warn_unknown)
|
|
||||||
conf_warning("unknown symbol: %s",
|
|
||||||
line + strlen(CONFIG_));
|
|
||||||
|
|
||||||
conf_set_changed(true);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sym->flags & def_flags) {
|
|
||||||
conf_warning("override: reassigning to symbol %s", sym->name);
|
|
||||||
}
|
|
||||||
if (conf_set_sym_val(sym, def, def_flags, p))
|
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
if (line[0] != '\r' && line[0] != '\n')
|
if (memcmp(line, CONFIG_, strlen(CONFIG_))) {
|
||||||
conf_warning("unexpected data: %.*s",
|
conf_warning("unexpected data: %s", line);
|
||||||
(int)strcspn(line, "\r\n"), line);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_name = line + strlen(CONFIG_);
|
||||||
|
p = strchr(sym_name, '=');
|
||||||
|
if (!p) {
|
||||||
|
conf_warning("unexpected data: %s", line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*p = 0;
|
||||||
|
val = p + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym = sym_find(sym_name);
|
||||||
|
if (!sym) {
|
||||||
|
if (def == S_DEF_AUTO) {
|
||||||
|
/*
|
||||||
|
* Reading from include/config/auto.conf.
|
||||||
|
* If CONFIG_FOO previously existed in auto.conf
|
||||||
|
* but it is missing now, include/config/FOO
|
||||||
|
* must be touched.
|
||||||
|
*/
|
||||||
|
conf_touch_dep(sym_name);
|
||||||
|
} else {
|
||||||
|
if (warn_unknown)
|
||||||
|
conf_warning("unknown symbol: %s", sym_name);
|
||||||
|
|
||||||
|
conf_set_changed(true);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sym->flags & def_flags)
|
||||||
|
conf_warning("override: reassigning to symbol %s", sym->name);
|
||||||
|
|
||||||
|
if (conf_set_sym_val(sym, def, def_flags, val))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (sym && sym_is_choice_value(sym)) {
|
if (sym && sym_is_choice_value(sym)) {
|
||||||
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||||
switch (sym->def[def].tri) {
|
switch (sym->def[def].tri) {
|
||||||
@ -533,9 +531,6 @@ load:
|
|||||||
free(line);
|
free(line);
|
||||||
fclose(in);
|
fclose(in);
|
||||||
|
|
||||||
if (conf_warnings && werror)
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +589,7 @@ int conf_read(const char *name)
|
|||||||
/* Reset a string value if it's out of range */
|
/* Reset a string value if it's out of range */
|
||||||
if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
|
if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
|
||||||
break;
|
break;
|
||||||
sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
|
sym->flags &= ~SYMBOL_VALID;
|
||||||
conf_unsaved++;
|
conf_unsaved++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1131,7 +1131,6 @@ static int expr_compare_type(enum expr_type t1, enum expr_type t2)
|
|||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
printf("[%dgt%d?]", t1, t2);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +99,6 @@ bool menu_is_visible(struct menu *menu);
|
|||||||
bool menu_has_prompt(struct menu *menu);
|
bool menu_has_prompt(struct menu *menu);
|
||||||
const char *menu_get_prompt(struct menu *menu);
|
const char *menu_get_prompt(struct menu *menu);
|
||||||
struct menu *menu_get_parent_menu(struct menu *menu);
|
struct menu *menu_get_parent_menu(struct menu *menu);
|
||||||
bool menu_has_help(struct menu *menu);
|
|
||||||
const char *menu_get_help(struct menu *menu);
|
|
||||||
int get_jump_key_char(void);
|
int get_jump_key_char(void);
|
||||||
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
|
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
|
||||||
void menu_get_ext_help(struct menu *menu, struct gstr *help);
|
void menu_get_ext_help(struct menu *menu, struct gstr *help);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef LKC_PROTO_H
|
||||||
|
#define LKC_PROTO_H
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
/* confdata.c */
|
/* confdata.c */
|
||||||
@ -12,6 +15,7 @@ void conf_set_changed(bool val);
|
|||||||
bool conf_get_changed(void);
|
bool conf_get_changed(void);
|
||||||
void conf_set_changed_callback(void (*fn)(void));
|
void conf_set_changed_callback(void (*fn)(void));
|
||||||
void conf_set_message_callback(void (*fn)(const char *s));
|
void conf_set_message_callback(void (*fn)(const char *s));
|
||||||
|
bool conf_errors(void);
|
||||||
|
|
||||||
/* symbol.c */
|
/* symbol.c */
|
||||||
extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
|
extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
|
||||||
@ -22,6 +26,7 @@ void print_symbol_for_listconfig(struct symbol *sym);
|
|||||||
struct symbol ** sym_re_search(const char *pattern);
|
struct symbol ** sym_re_search(const char *pattern);
|
||||||
const char * sym_type_name(enum symbol_type type);
|
const char * sym_type_name(enum symbol_type type);
|
||||||
void sym_calc_value(struct symbol *sym);
|
void sym_calc_value(struct symbol *sym);
|
||||||
|
bool sym_dep_errors(void);
|
||||||
enum symbol_type sym_get_type(struct symbol *sym);
|
enum symbol_type sym_get_type(struct symbol *sym);
|
||||||
bool sym_tristate_within_range(struct symbol *sym,tristate tri);
|
bool sym_tristate_within_range(struct symbol *sym,tristate tri);
|
||||||
bool sym_set_tristate_value(struct symbol *sym,tristate tri);
|
bool sym_set_tristate_value(struct symbol *sym,tristate tri);
|
||||||
@ -50,3 +55,5 @@ char *expand_one_token(const char **str);
|
|||||||
|
|
||||||
/* expr.c */
|
/* expr.c */
|
||||||
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
|
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
|
||||||
|
|
||||||
|
#endif /* LKC_PROTO_H */
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "lkc.h"
|
#include "lkc.h"
|
||||||
#include "lxdialog/dialog.h"
|
#include "lxdialog/dialog.h"
|
||||||
|
#include "mnconf-common.h"
|
||||||
|
|
||||||
static const char mconf_readme[] =
|
static const char mconf_readme[] =
|
||||||
"Overview\n"
|
"Overview\n"
|
||||||
@ -247,7 +248,7 @@ search_help[] =
|
|||||||
" -> PCI support (PCI [=y])\n"
|
" -> PCI support (PCI [=y])\n"
|
||||||
"(1) -> PCI access mode (<choice> [=y])\n"
|
"(1) -> PCI access mode (<choice> [=y])\n"
|
||||||
" Defined at drivers/pci/Kconfig:47\n"
|
" Defined at drivers/pci/Kconfig:47\n"
|
||||||
" Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
|
" Depends on: X86_LOCAL_APIC && X86_IO_APIC\n"
|
||||||
" Selects: LIBCRC32\n"
|
" Selects: LIBCRC32\n"
|
||||||
" Selected by: BAR [=n]\n"
|
" Selected by: BAR [=n]\n"
|
||||||
"-----------------------------------------------------------------\n"
|
"-----------------------------------------------------------------\n"
|
||||||
@ -286,7 +287,6 @@ static int single_menu_mode;
|
|||||||
static int show_all_options;
|
static int show_all_options;
|
||||||
static int save_and_exit;
|
static int save_and_exit;
|
||||||
static int silent;
|
static int silent;
|
||||||
static int jump_key_char;
|
|
||||||
|
|
||||||
static void conf(struct menu *menu, struct menu *active_menu);
|
static void conf(struct menu *menu, struct menu *active_menu);
|
||||||
|
|
||||||
@ -378,58 +378,6 @@ static void show_help(struct menu *menu)
|
|||||||
str_free(&help);
|
str_free(&help);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct search_data {
|
|
||||||
struct list_head *head;
|
|
||||||
struct menu *target;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int next_jump_key(int key)
|
|
||||||
{
|
|
||||||
if (key < '1' || key > '9')
|
|
||||||
return '1';
|
|
||||||
|
|
||||||
key++;
|
|
||||||
|
|
||||||
if (key > '9')
|
|
||||||
key = '1';
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_search_keys(int key, size_t start, size_t end, void *_data)
|
|
||||||
{
|
|
||||||
struct search_data *data = _data;
|
|
||||||
struct jump_key *pos;
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (key < '1' || key > '9')
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
list_for_each_entry(pos, data->head, entries) {
|
|
||||||
index = next_jump_key(index);
|
|
||||||
|
|
||||||
if (pos->offset < start)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pos->offset >= end)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (key == index) {
|
|
||||||
data->target = pos->target;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_jump_key_char(void)
|
|
||||||
{
|
|
||||||
jump_key_char = next_jump_key(jump_key_char);
|
|
||||||
|
|
||||||
return jump_key_char;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void search_conf(void)
|
static void search_conf(void)
|
||||||
{
|
{
|
||||||
struct symbol **sym_arr;
|
struct symbol **sym_arr;
|
||||||
|
@ -673,19 +673,6 @@ struct menu *menu_get_parent_menu(struct menu *menu)
|
|||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool menu_has_help(struct menu *menu)
|
|
||||||
{
|
|
||||||
return menu->help != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *menu_get_help(struct menu *menu)
|
|
||||||
{
|
|
||||||
if (menu->help)
|
|
||||||
return menu->help;
|
|
||||||
else
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_def_str(struct gstr *r, struct menu *menu)
|
static void get_def_str(struct gstr *r, struct menu *menu)
|
||||||
{
|
{
|
||||||
str_printf(r, "Defined at %s:%d\n",
|
str_printf(r, "Defined at %s:%d\n",
|
||||||
@ -856,10 +843,10 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
|
|||||||
struct symbol *sym = menu->sym;
|
struct symbol *sym = menu->sym;
|
||||||
const char *help_text = nohelp_text;
|
const char *help_text = nohelp_text;
|
||||||
|
|
||||||
if (menu_has_help(menu)) {
|
if (menu->help) {
|
||||||
if (sym->name)
|
if (sym->name)
|
||||||
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
|
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
|
||||||
help_text = menu_get_help(menu);
|
help_text = menu->help;
|
||||||
}
|
}
|
||||||
str_printf(help, "%s\n", help_text);
|
str_printf(help, "%s\n", help_text);
|
||||||
if (sym)
|
if (sym)
|
||||||
|
53
scripts/kconfig/mnconf-common.c
Normal file
53
scripts/kconfig/mnconf-common.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#include "expr.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "mnconf-common.h"
|
||||||
|
|
||||||
|
int jump_key_char;
|
||||||
|
|
||||||
|
int next_jump_key(int key)
|
||||||
|
{
|
||||||
|
if (key < '1' || key > '9')
|
||||||
|
return '1';
|
||||||
|
|
||||||
|
key++;
|
||||||
|
|
||||||
|
if (key > '9')
|
||||||
|
key = '1';
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle_search_keys(int key, size_t start, size_t end, void *_data)
|
||||||
|
{
|
||||||
|
struct search_data *data = _data;
|
||||||
|
struct jump_key *pos;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
if (key < '1' || key > '9')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
list_for_each_entry(pos, data->head, entries) {
|
||||||
|
index = next_jump_key(index);
|
||||||
|
|
||||||
|
if (pos->offset < start)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pos->offset >= end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (key == index) {
|
||||||
|
data->target = pos->target;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_jump_key_char(void)
|
||||||
|
{
|
||||||
|
jump_key_char = next_jump_key(jump_key_char);
|
||||||
|
|
||||||
|
return jump_key_char;
|
||||||
|
}
|
18
scripts/kconfig/mnconf-common.h
Normal file
18
scripts/kconfig/mnconf-common.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
#ifndef MNCONF_COMMON_H
|
||||||
|
#define MNCONF_COMMON_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct search_data {
|
||||||
|
struct list_head *head;
|
||||||
|
struct menu *target;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int jump_key_char;
|
||||||
|
|
||||||
|
int next_jump_key(int key);
|
||||||
|
int handle_search_keys(int key, size_t start, size_t end, void *_data);
|
||||||
|
int get_jump_key_char(void);
|
||||||
|
|
||||||
|
#endif /* MNCONF_COMMON_H */
|
@ -12,6 +12,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "lkc.h"
|
#include "lkc.h"
|
||||||
|
#include "mnconf-common.h"
|
||||||
#include "nconf.h"
|
#include "nconf.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
@ -216,7 +217,7 @@ search_help[] =
|
|||||||
"Symbol: FOO [ = m]\n"
|
"Symbol: FOO [ = m]\n"
|
||||||
"Prompt: Foo bus is used to drive the bar HW\n"
|
"Prompt: Foo bus is used to drive the bar HW\n"
|
||||||
"Defined at drivers/pci/Kconfig:47\n"
|
"Defined at drivers/pci/Kconfig:47\n"
|
||||||
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
|
"Depends on: X86_LOCAL_APIC && X86_IO_APIC\n"
|
||||||
"Location:\n"
|
"Location:\n"
|
||||||
" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
|
" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
|
||||||
" -> PCI support (PCI [ = y])\n"
|
" -> PCI support (PCI [ = y])\n"
|
||||||
@ -279,7 +280,6 @@ static const char *current_instructions = menu_instructions;
|
|||||||
|
|
||||||
static char *dialog_input_result;
|
static char *dialog_input_result;
|
||||||
static int dialog_input_result_len;
|
static int dialog_input_result_len;
|
||||||
static int jump_key_char;
|
|
||||||
|
|
||||||
static void selected_conf(struct menu *menu, struct menu *active_menu);
|
static void selected_conf(struct menu *menu, struct menu *active_menu);
|
||||||
static void conf(struct menu *menu);
|
static void conf(struct menu *menu);
|
||||||
@ -691,57 +691,6 @@ static int do_exit(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct search_data {
|
|
||||||
struct list_head *head;
|
|
||||||
struct menu *target;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int next_jump_key(int key)
|
|
||||||
{
|
|
||||||
if (key < '1' || key > '9')
|
|
||||||
return '1';
|
|
||||||
|
|
||||||
key++;
|
|
||||||
|
|
||||||
if (key > '9')
|
|
||||||
key = '1';
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_search_keys(int key, size_t start, size_t end, void *_data)
|
|
||||||
{
|
|
||||||
struct search_data *data = _data;
|
|
||||||
struct jump_key *pos;
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (key < '1' || key > '9')
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
list_for_each_entry(pos, data->head, entries) {
|
|
||||||
index = next_jump_key(index);
|
|
||||||
|
|
||||||
if (pos->offset < start)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pos->offset >= end)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (key == index) {
|
|
||||||
data->target = pos->target;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_jump_key_char(void)
|
|
||||||
{
|
|
||||||
jump_key_char = next_jump_key(jump_key_char);
|
|
||||||
|
|
||||||
return jump_key_char;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void search_conf(void)
|
static void search_conf(void)
|
||||||
{
|
{
|
||||||
|
@ -29,14 +29,9 @@ struct symbol symbol_no = {
|
|||||||
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct symbol symbol_empty = {
|
|
||||||
.name = "",
|
|
||||||
.curr = { "", no },
|
|
||||||
.flags = SYMBOL_VALID,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct symbol *modules_sym;
|
struct symbol *modules_sym;
|
||||||
static tristate modules_val;
|
static tristate modules_val;
|
||||||
|
static int sym_warnings;
|
||||||
|
|
||||||
enum symbol_type sym_get_type(struct symbol *sym)
|
enum symbol_type sym_get_type(struct symbol *sym)
|
||||||
{
|
{
|
||||||
@ -317,6 +312,14 @@ static void sym_warn_unmet_dep(struct symbol *sym)
|
|||||||
" Selected by [m]:\n");
|
" Selected by [m]:\n");
|
||||||
|
|
||||||
fputs(str_get(&gs), stderr);
|
fputs(str_get(&gs), stderr);
|
||||||
|
sym_warnings++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sym_dep_errors(void)
|
||||||
|
{
|
||||||
|
if (sym_warnings)
|
||||||
|
return getenv("KCONFIG_WERROR");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sym_calc_value(struct symbol *sym)
|
void sym_calc_value(struct symbol *sym)
|
||||||
@ -344,9 +347,13 @@ void sym_calc_value(struct symbol *sym)
|
|||||||
|
|
||||||
switch (sym->type) {
|
switch (sym->type) {
|
||||||
case S_INT:
|
case S_INT:
|
||||||
|
newval.val = "0";
|
||||||
|
break;
|
||||||
case S_HEX:
|
case S_HEX:
|
||||||
|
newval.val = "0x0";
|
||||||
|
break;
|
||||||
case S_STRING:
|
case S_STRING:
|
||||||
newval = symbol_empty.curr;
|
newval.val = "";
|
||||||
break;
|
break;
|
||||||
case S_BOOLEAN:
|
case S_BOOLEAN:
|
||||||
case S_TRISTATE:
|
case S_TRISTATE:
|
||||||
@ -697,13 +704,12 @@ const char *sym_get_string_default(struct symbol *sym)
|
|||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
struct symbol *ds;
|
struct symbol *ds;
|
||||||
const char *str;
|
const char *str = "";
|
||||||
tristate val;
|
tristate val;
|
||||||
|
|
||||||
sym_calc_visibility(sym);
|
sym_calc_visibility(sym);
|
||||||
sym_calc_value(modules_sym);
|
sym_calc_value(modules_sym);
|
||||||
val = symbol_no.curr.tri;
|
val = symbol_no.curr.tri;
|
||||||
str = symbol_empty.curr.val;
|
|
||||||
|
|
||||||
/* If symbol has a default value look it up */
|
/* If symbol has a default value look it up */
|
||||||
prop = sym_get_default_prop(sym);
|
prop = sym_get_default_prop(sym);
|
||||||
@ -753,14 +759,17 @@ const char *sym_get_string_default(struct symbol *sym)
|
|||||||
case yes: return "y";
|
case yes: return "y";
|
||||||
}
|
}
|
||||||
case S_INT:
|
case S_INT:
|
||||||
|
if (!str[0])
|
||||||
|
str = "0";
|
||||||
|
break;
|
||||||
case S_HEX:
|
case S_HEX:
|
||||||
return str;
|
if (!str[0])
|
||||||
case S_STRING:
|
str = "0x0";
|
||||||
return str;
|
break;
|
||||||
case S_UNKNOWN:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "";
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *sym_get_string_value(struct symbol *sym)
|
const char *sym_get_string_value(struct symbol *sym)
|
||||||
|
@ -42,8 +42,7 @@ struct gstr str_new(void)
|
|||||||
/* Free storage for growable string */
|
/* Free storage for growable string */
|
||||||
void str_free(struct gstr *gs)
|
void str_free(struct gstr *gs)
|
||||||
{
|
{
|
||||||
if (gs->s)
|
free(gs->s);
|
||||||
free(gs->s);
|
|
||||||
gs->s = NULL;
|
gs->s = NULL;
|
||||||
gs->len = 0;
|
gs->len = 0;
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,7 @@ static unsigned int nr_unresolved;
|
|||||||
|
|
||||||
#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr))
|
#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr))
|
||||||
|
|
||||||
void __attribute__((format(printf, 2, 3)))
|
void modpost_log(enum loglevel loglevel, const char *fmt, ...)
|
||||||
modpost_log(enum loglevel loglevel, const char *fmt, ...)
|
|
||||||
{
|
{
|
||||||
va_list arglist;
|
va_list arglist;
|
||||||
|
|
||||||
@ -91,6 +90,9 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
|
|||||||
error_occurred = true;
|
error_occurred = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __attribute__((alias("modpost_log")))
|
||||||
|
modpost_log_noret(enum loglevel loglevel, const char *fmt, ...);
|
||||||
|
|
||||||
static inline bool strends(const char *str, const char *postfix)
|
static inline bool strends(const char *str, const char *postfix)
|
||||||
{
|
{
|
||||||
if (strlen(str) < strlen(postfix))
|
if (strlen(str) < strlen(postfix))
|
||||||
@ -474,11 +476,9 @@ static int parse_elf(struct elf_info *info, const char *filename)
|
|||||||
fatal("%s: not relocatable object.", filename);
|
fatal("%s: not relocatable object.", filename);
|
||||||
|
|
||||||
/* Check if file offset is correct */
|
/* Check if file offset is correct */
|
||||||
if (hdr->e_shoff > info->size) {
|
if (hdr->e_shoff > info->size)
|
||||||
fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n",
|
fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n",
|
||||||
(unsigned long)hdr->e_shoff, filename, info->size);
|
(unsigned long)hdr->e_shoff, filename, info->size);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hdr->e_shnum == SHN_UNDEF) {
|
if (hdr->e_shnum == SHN_UNDEF) {
|
||||||
/*
|
/*
|
||||||
@ -516,12 +516,11 @@ static int parse_elf(struct elf_info *info, const char *filename)
|
|||||||
const char *secname;
|
const char *secname;
|
||||||
int nobits = sechdrs[i].sh_type == SHT_NOBITS;
|
int nobits = sechdrs[i].sh_type == SHT_NOBITS;
|
||||||
|
|
||||||
if (!nobits && sechdrs[i].sh_offset > info->size) {
|
if (!nobits && sechdrs[i].sh_offset > info->size)
|
||||||
fatal("%s is truncated. sechdrs[i].sh_offset=%lu > sizeof(*hrd)=%zu\n",
|
fatal("%s is truncated. sechdrs[i].sh_offset=%lu > sizeof(*hrd)=%zu\n",
|
||||||
filename, (unsigned long)sechdrs[i].sh_offset,
|
filename, (unsigned long)sechdrs[i].sh_offset,
|
||||||
sizeof(*hdr));
|
sizeof(*hdr));
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
secname = secstrings + sechdrs[i].sh_name;
|
secname = secstrings + sechdrs[i].sh_name;
|
||||||
if (strcmp(secname, ".modinfo") == 0) {
|
if (strcmp(secname, ".modinfo") == 0) {
|
||||||
if (nobits)
|
if (nobits)
|
||||||
@ -1419,7 +1418,7 @@ static void section_rel(struct module *mod, struct elf_info *elf,
|
|||||||
|
|
||||||
for (rel = start; rel < stop; rel++) {
|
for (rel = start; rel < stop; rel++) {
|
||||||
Elf_Sym *tsym;
|
Elf_Sym *tsym;
|
||||||
Elf_Addr taddr = 0, r_offset;
|
Elf_Addr taddr, r_offset;
|
||||||
unsigned int r_type, r_sym;
|
unsigned int r_type, r_sym;
|
||||||
void *loc;
|
void *loc;
|
||||||
|
|
||||||
|
@ -197,7 +197,11 @@ enum loglevel {
|
|||||||
LOG_FATAL
|
LOG_FATAL
|
||||||
};
|
};
|
||||||
|
|
||||||
void modpost_log(enum loglevel loglevel, const char *fmt, ...);
|
void __attribute__((format(printf, 2, 3)))
|
||||||
|
modpost_log(enum loglevel loglevel, const char *fmt, ...);
|
||||||
|
|
||||||
|
void __attribute__((format(printf, 2, 3), noreturn))
|
||||||
|
modpost_log_noret(enum loglevel loglevel, const char *fmt, ...);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* warn - show the given message, then let modpost continue running, still
|
* warn - show the given message, then let modpost continue running, still
|
||||||
@ -214,4 +218,4 @@ void modpost_log(enum loglevel loglevel, const char *fmt, ...);
|
|||||||
*/
|
*/
|
||||||
#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
|
#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
|
||||||
#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
|
#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
|
||||||
#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)
|
#define fatal(fmt, args...) modpost_log_noret(LOG_FATAL, fmt, ##args)
|
||||||
|
@ -25,35 +25,20 @@ if_enabled_echo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create_package() {
|
create_package() {
|
||||||
local pname="$1" pdir="$2"
|
export DH_OPTIONS="-p${1}"
|
||||||
local dpkg_deb_opts
|
|
||||||
|
|
||||||
mkdir -m 755 -p "$pdir/DEBIAN"
|
dh_installdocs
|
||||||
mkdir -p "$pdir/usr/share/doc/$pname"
|
dh_installchangelogs
|
||||||
cp debian/copyright "$pdir/usr/share/doc/$pname/"
|
dh_compress
|
||||||
cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian"
|
dh_fixperms
|
||||||
gzip -n -9 "$pdir/usr/share/doc/$pname/changelog.Debian"
|
dh_gencontrol
|
||||||
sh -c "cd '$pdir'; find . -type f ! -path './DEBIAN/*' -printf '%P\0' \
|
dh_md5sums
|
||||||
| xargs -r0 md5sum > DEBIAN/md5sums"
|
dh_builddeb -- ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS}
|
||||||
|
|
||||||
# Fix ownership and permissions
|
|
||||||
if [ "$DEB_RULES_REQUIRES_ROOT" = "no" ]; then
|
|
||||||
dpkg_deb_opts="--root-owner-group"
|
|
||||||
else
|
|
||||||
chown -R root:root "$pdir"
|
|
||||||
fi
|
|
||||||
# a+rX in case we are in a restrictive umask environment like 0077
|
|
||||||
# ug-s in case we build in a setuid/setgid directory
|
|
||||||
chmod -R go-w,a+rX,ug-s "$pdir"
|
|
||||||
|
|
||||||
# Create the package
|
|
||||||
dpkg-gencontrol -p$pname -P"$pdir"
|
|
||||||
dpkg-deb $dpkg_deb_opts ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS} --build "$pdir" ..
|
|
||||||
}
|
}
|
||||||
|
|
||||||
install_linux_image () {
|
install_linux_image () {
|
||||||
pdir=$1
|
pname=$1
|
||||||
pname=$2
|
pdir=debian/$1
|
||||||
|
|
||||||
rm -rf ${pdir}
|
rm -rf ${pdir}
|
||||||
|
|
||||||
@ -62,7 +47,7 @@ install_linux_image () {
|
|||||||
${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install
|
${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install
|
${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" INSTALL_MOD_STRIP=1 modules_install
|
||||||
rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build"
|
rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build"
|
||||||
|
|
||||||
# Install the kernel
|
# Install the kernel
|
||||||
@ -122,26 +107,22 @@ install_linux_image () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_linux_image_dbg () {
|
install_linux_image_dbg () {
|
||||||
pdir=$1
|
pdir=debian/$1
|
||||||
image_pdir=$2
|
|
||||||
|
|
||||||
rm -rf ${pdir}
|
rm -rf ${pdir}
|
||||||
|
|
||||||
for module in $(find ${image_pdir}/lib/modules/ -name *.ko -printf '%P\n'); do
|
# Parse modules.order directly because 'make modules_install' may sign,
|
||||||
module=lib/modules/${module}
|
# compress modules, and then run unneeded depmod.
|
||||||
mkdir -p $(dirname ${pdir}/usr/lib/debug/${module})
|
while read -r mod; do
|
||||||
# only keep debug symbols in the debug file
|
mod="${mod%.o}.ko"
|
||||||
${OBJCOPY} --only-keep-debug ${image_pdir}/${module} ${pdir}/usr/lib/debug/${module}
|
dbg="${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/kernel/${mod}"
|
||||||
# strip original module from debug symbols
|
buildid=$("${READELF}" -n "${mod}" | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p')
|
||||||
${OBJCOPY} --strip-debug ${image_pdir}/${module}
|
link="${pdir}/usr/lib/debug/.build-id/${buildid}.debug"
|
||||||
# then add a link to those
|
|
||||||
${OBJCOPY} --add-gnu-debuglink=${pdir}/usr/lib/debug/${module} ${image_pdir}/${module}
|
|
||||||
done
|
|
||||||
|
|
||||||
# re-sign stripped modules
|
mkdir -p "${dbg%/*}" "${link%/*}"
|
||||||
if is_enabled CONFIG_MODULE_SIG_ALL; then
|
"${OBJCOPY}" --only-keep-debug "${mod}" "${dbg}"
|
||||||
${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${image_pdir}" modules_sign
|
ln -sf --relative "${dbg}" "${link}"
|
||||||
fi
|
done < modules.order
|
||||||
|
|
||||||
# Build debug package
|
# Build debug package
|
||||||
# Different tools want the image in different locations
|
# Different tools want the image in different locations
|
||||||
@ -156,8 +137,8 @@ install_linux_image_dbg () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_kernel_headers () {
|
install_kernel_headers () {
|
||||||
pdir=$1
|
pdir=debian/$1
|
||||||
version=$2
|
version=${1#linux-headers-}
|
||||||
|
|
||||||
rm -rf $pdir
|
rm -rf $pdir
|
||||||
|
|
||||||
@ -168,18 +149,16 @@ install_kernel_headers () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_libc_headers () {
|
install_libc_headers () {
|
||||||
pdir=$1
|
pdir=debian/$1
|
||||||
|
|
||||||
rm -rf $pdir
|
rm -rf $pdir
|
||||||
|
|
||||||
$MAKE -f $srctree/Makefile headers
|
|
||||||
$MAKE -f $srctree/Makefile headers_install INSTALL_HDR_PATH=$pdir/usr
|
$MAKE -f $srctree/Makefile headers_install INSTALL_HDR_PATH=$pdir/usr
|
||||||
|
|
||||||
# move asm headers to /usr/include/<libc-machine>/asm to match the structure
|
# move asm headers to /usr/include/<libc-machine>/asm to match the structure
|
||||||
# used by Debian-based distros (to support multi-arch)
|
# used by Debian-based distros (to support multi-arch)
|
||||||
host_arch=$(dpkg-architecture -a$DEB_HOST_ARCH -qDEB_HOST_MULTIARCH)
|
mkdir "$pdir/usr/include/${DEB_HOST_MULTIARCH}"
|
||||||
mkdir $pdir/usr/include/$host_arch
|
mv "$pdir/usr/include/asm" "$pdir/usr/include/${DEB_HOST_MULTIARCH}"
|
||||||
mv $pdir/usr/include/asm $pdir/usr/include/$host_arch/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rm -f debian/files
|
rm -f debian/files
|
||||||
@ -190,30 +169,13 @@ for package in ${packages_enabled}
|
|||||||
do
|
do
|
||||||
case ${package} in
|
case ${package} in
|
||||||
*-dbg)
|
*-dbg)
|
||||||
# This must be done after linux-image, that is, we expect the
|
install_linux_image_dbg "${package}";;
|
||||||
# debug package appears after linux-image in debian/control.
|
|
||||||
install_linux_image_dbg debian/linux-image-dbg debian/linux-image;;
|
|
||||||
linux-image-*|user-mode-linux-*)
|
linux-image-*|user-mode-linux-*)
|
||||||
install_linux_image debian/linux-image ${package};;
|
install_linux_image "${package}";;
|
||||||
linux-libc-dev)
|
linux-libc-dev)
|
||||||
install_libc_headers debian/linux-libc-dev;;
|
install_libc_headers "${package}";;
|
||||||
linux-headers-*)
|
linux-headers-*)
|
||||||
install_kernel_headers debian/linux-headers ${package#linux-headers-};;
|
install_kernel_headers "${package}";;
|
||||||
esac
|
esac
|
||||||
|
create_package "${package}"
|
||||||
done
|
done
|
||||||
|
|
||||||
for package in ${packages_enabled}
|
|
||||||
do
|
|
||||||
case ${package} in
|
|
||||||
*-dbg)
|
|
||||||
create_package ${package} debian/linux-image-dbg;;
|
|
||||||
linux-image-*|user-mode-linux-*)
|
|
||||||
create_package ${package} debian/linux-image;;
|
|
||||||
linux-libc-dev)
|
|
||||||
create_package ${package} debian/linux-libc-dev;;
|
|
||||||
linux-headers-*)
|
|
||||||
create_package ${package} debian/linux-headers;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
|
@ -23,7 +23,6 @@ tmpdir=$1
|
|||||||
#
|
#
|
||||||
rm -rf -- "${tmpdir}"
|
rm -rf -- "${tmpdir}"
|
||||||
mkdir -p -- "${tmpdir}/boot"
|
mkdir -p -- "${tmpdir}/boot"
|
||||||
dirs=boot
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -38,12 +37,9 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Try to install modules
|
# Install modules
|
||||||
#
|
#
|
||||||
if grep -q '^CONFIG_MODULES=y' include/config/auto.conf; then
|
make ARCH="${ARCH}" -f ${srctree}/Makefile INSTALL_MOD_PATH="${tmpdir}" modules_install
|
||||||
make ARCH="${ARCH}" -f ${srctree}/Makefile INSTALL_MOD_PATH="${tmpdir}" modules_install
|
|
||||||
dirs="$dirs lib"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
|
|
||||||
# Set up CROSS_COMPILE if not defined yet
|
|
||||||
if [ "${CROSS_COMPILE+set}" != "set" -a "${DEB_HOST_ARCH}" != "${DEB_BUILD_ARCH}" ]; then
|
|
||||||
echo CROSS_COMPILE=${DEB_HOST_GNU_TYPE}-
|
|
||||||
fi
|
|
||||||
|
|
||||||
version=$(dpkg-parsechangelog -S Version)
|
|
||||||
debian_revision="${version##*-}"
|
|
||||||
|
|
||||||
if [ "${version}" != "${debian_revision}" ]; then
|
|
||||||
echo KBUILD_BUILD_VERSION=${debian_revision}
|
|
||||||
fi
|
|
16
scripts/package/debian/copyright
Normal file
16
scripts/package/debian/copyright
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
This is a packaged upstream version of the Linux kernel.
|
||||||
|
|
||||||
|
The sources may be found at most Linux archive sites, including:
|
||||||
|
https://www.kernel.org/pub/linux/kernel
|
||||||
|
|
||||||
|
Copyright: 1991 - 2023 Linus Torvalds and others.
|
||||||
|
|
||||||
|
The git repository for mainline kernel development is at:
|
||||||
|
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991.
|
||||||
|
|
||||||
|
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||||
|
License version 2 can be found in `/usr/share/common-licenses/GPL-2'.
|
@ -1,33 +1,46 @@
|
|||||||
#!/usr/bin/make -f
|
#!/usr/bin/make -f
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
include debian/rules.vars
|
# in case debian/rules is executed directly
|
||||||
|
export DEB_RULES_REQUIRES_ROOT := no
|
||||||
|
|
||||||
srctree ?= .
|
include debian/rules.vars
|
||||||
|
|
||||||
ifneq (,$(filter-out parallel=1,$(filter parallel=%,$(DEB_BUILD_OPTIONS))))
|
ifneq (,$(filter-out parallel=1,$(filter parallel=%,$(DEB_BUILD_OPTIONS))))
|
||||||
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
|
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
|
||||||
MAKEFLAGS += -j$(NUMJOBS)
|
MAKEFLAGS += -j$(NUMJOBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
revision = $(lastword $(subst -, ,$(shell dpkg-parsechangelog -S Version)))
|
||||||
|
CROSS_COMPILE ?= $(filter-out $(DEB_BUILD_GNU_TYPE)-, $(DEB_HOST_GNU_TYPE)-)
|
||||||
|
make-opts = ARCH=$(ARCH) KERNELRELEASE=$(KERNELRELEASE) KBUILD_BUILD_VERSION=$(revision) $(addprefix CROSS_COMPILE=,$(CROSS_COMPILE))
|
||||||
|
|
||||||
.PHONY: binary binary-indep binary-arch
|
.PHONY: binary binary-indep binary-arch
|
||||||
binary: binary-arch binary-indep
|
binary: binary-arch binary-indep
|
||||||
binary-indep: build-indep
|
binary-indep: build-indep
|
||||||
binary-arch: build-arch
|
binary-arch: build-arch
|
||||||
$(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) \
|
$(MAKE) $(make-opts) \
|
||||||
KERNELRELEASE=$(KERNELRELEASE) \
|
run-command KBUILD_RUN_COMMAND='+$$(srctree)/scripts/package/builddeb'
|
||||||
run-command KBUILD_RUN_COMMAND=+$(srctree)/scripts/package/builddeb
|
|
||||||
|
|
||||||
.PHONY: build build-indep build-arch
|
.PHONY: build build-indep build-arch
|
||||||
build: build-arch build-indep
|
build: build-arch build-indep
|
||||||
build-indep:
|
build-indep:
|
||||||
build-arch:
|
build-arch:
|
||||||
$(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) \
|
$(MAKE) $(make-opts) olddefconfig
|
||||||
KERNELRELEASE=$(KERNELRELEASE) \
|
$(MAKE) $(make-opts) $(if $(filter um,$(ARCH)),,headers) all
|
||||||
$(shell $(srctree)/scripts/package/deb-build-option) \
|
|
||||||
olddefconfig all
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf debian/files debian/linux-*
|
rm -rf debian/files debian/linux-* debian/deb-env.vars*
|
||||||
$(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) clean
|
$(MAKE) ARCH=$(ARCH) clean
|
||||||
|
|
||||||
|
# If DEB_HOST_ARCH is empty, it is likely that debian/rules was executed
|
||||||
|
# directly. Run 'dpkg-architecture --print-set --print-format=make' to
|
||||||
|
# generate a makefile construct that exports all DEB_* variables.
|
||||||
|
ifndef DEB_HOST_ARCH
|
||||||
|
include debian/deb-env.vars
|
||||||
|
|
||||||
|
debian/deb-env.vars:
|
||||||
|
dpkg-architecture -a$$(cat debian/arch) --print-set --print-format=make > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
|
endif
|
||||||
|
@ -20,7 +20,7 @@ mkdir -p "${destdir}"
|
|||||||
find "arch/${SRCARCH}" -maxdepth 1 -name 'Makefile*'
|
find "arch/${SRCARCH}" -maxdepth 1 -name 'Makefile*'
|
||||||
find include scripts -type f -o -type l
|
find include scripts -type f -o -type l
|
||||||
find "arch/${SRCARCH}" -name Kbuild.platforms -o -name Platform
|
find "arch/${SRCARCH}" -name Kbuild.platforms -o -name Platform
|
||||||
find "arch/${SRCARCH}" -name include -o -name scripts -type d
|
find "arch/${SRCARCH}" -name include -type d
|
||||||
) | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${destdir}"
|
) | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${destdir}"
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -56,13 +56,7 @@ patch -p1 < %{SOURCE2}
|
|||||||
|
|
||||||
%install
|
%install
|
||||||
mkdir -p %{buildroot}/boot
|
mkdir -p %{buildroot}/boot
|
||||||
%ifarch ia64
|
|
||||||
mkdir -p %{buildroot}/boot/efi
|
|
||||||
cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/efi/vmlinuz-%{KERNELRELEASE}
|
|
||||||
ln -s efi/vmlinuz-%{KERNELRELEASE} %{buildroot}/boot/
|
|
||||||
%else
|
|
||||||
cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/vmlinuz-%{KERNELRELEASE}
|
cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/vmlinuz-%{KERNELRELEASE}
|
||||||
%endif
|
|
||||||
%{make} %{makeflags} INSTALL_MOD_PATH=%{buildroot} modules_install
|
%{make} %{makeflags} INSTALL_MOD_PATH=%{buildroot} modules_install
|
||||||
%{make} %{makeflags} INSTALL_HDR_PATH=%{buildroot}/usr headers_install
|
%{make} %{makeflags} INSTALL_HDR_PATH=%{buildroot}/usr headers_install
|
||||||
cp System.map %{buildroot}/boot/System.map-%{KERNELRELEASE}
|
cp System.map %{buildroot}/boot/System.map-%{KERNELRELEASE}
|
||||||
|
@ -26,7 +26,7 @@ set_debarch() {
|
|||||||
|
|
||||||
# Attempt to find the correct Debian architecture
|
# Attempt to find the correct Debian architecture
|
||||||
case "$UTS_MACHINE" in
|
case "$UTS_MACHINE" in
|
||||||
i386|ia64|alpha|m68k|riscv*)
|
i386|alpha|m68k|riscv*)
|
||||||
debarch="$UTS_MACHINE" ;;
|
debarch="$UTS_MACHINE" ;;
|
||||||
x86_64)
|
x86_64)
|
||||||
debarch=amd64 ;;
|
debarch=amd64 ;;
|
||||||
@ -176,8 +176,6 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo $debarch > debian/arch
|
echo $debarch > debian/arch
|
||||||
extra_build_depends=", $(if_enabled_echo CONFIG_UNWINDER_ORC libelf-dev:native)"
|
|
||||||
extra_build_depends="$extra_build_depends, $(if_enabled_echo CONFIG_SYSTEM_TRUSTED_KEYRING libssl-dev:native)"
|
|
||||||
|
|
||||||
# Generate a simple changelog template
|
# Generate a simple changelog template
|
||||||
cat <<EOF > debian/changelog
|
cat <<EOF > debian/changelog
|
||||||
@ -188,26 +186,6 @@ $sourcename ($packageversion) $distribution; urgency=low
|
|||||||
-- $maintainer $(date -R)
|
-- $maintainer $(date -R)
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Generate copyright file
|
|
||||||
cat <<EOF > debian/copyright
|
|
||||||
This is a packaged upstream version of the Linux kernel.
|
|
||||||
|
|
||||||
The sources may be found at most Linux archive sites, including:
|
|
||||||
https://www.kernel.org/pub/linux/kernel
|
|
||||||
|
|
||||||
Copyright: 1991 - 2018 Linus Torvalds and others.
|
|
||||||
|
|
||||||
The git repository for mainline kernel development is at:
|
|
||||||
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 dated June, 1991.
|
|
||||||
|
|
||||||
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
|
||||||
License version 2 can be found in \`/usr/share/common-licenses/GPL-2'.
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Generate a control file
|
# Generate a control file
|
||||||
cat <<EOF > debian/control
|
cat <<EOF > debian/control
|
||||||
Source: $sourcename
|
Source: $sourcename
|
||||||
@ -215,7 +193,8 @@ Section: kernel
|
|||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: $maintainer
|
Maintainer: $maintainer
|
||||||
Rules-Requires-Root: no
|
Rules-Requires-Root: no
|
||||||
Build-Depends: bc, debhelper, rsync, kmod, cpio, bison, flex $extra_build_depends
|
Build-Depends: debhelper-compat (= 12)
|
||||||
|
Build-Depends-Arch: bc, bison, cpio, flex, kmod, libelf-dev:native, libssl-dev:native, rsync
|
||||||
Homepage: https://www.kernel.org/
|
Homepage: https://www.kernel.org/
|
||||||
|
|
||||||
Package: $packagename-$version
|
Package: $packagename-$version
|
||||||
@ -268,6 +247,7 @@ ARCH := ${ARCH}
|
|||||||
KERNELRELEASE := ${KERNELRELEASE}
|
KERNELRELEASE := ${KERNELRELEASE}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
cp "${srctree}/scripts/package/debian/copyright" debian/
|
||||||
cp "${srctree}/scripts/package/debian/rules" debian/
|
cp "${srctree}/scripts/package/debian/rules" debian/
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -10,5 +10,5 @@ parts:
|
|||||||
kernel:
|
kernel:
|
||||||
plugin: kernel
|
plugin: kernel
|
||||||
source: SRCTREE
|
source: SRCTREE
|
||||||
source-type: tar
|
source-type: local
|
||||||
kernel-with-firmware: false
|
kernel-with-firmware: false
|
||||||
|
@ -590,7 +590,6 @@ static int do_file(char const *const fname)
|
|||||||
ideal_nop = ideal_nop4_arm64;
|
ideal_nop = ideal_nop4_arm64;
|
||||||
is_fake_mcount64 = arm64_is_fake_mcount;
|
is_fake_mcount64 = arm64_is_fake_mcount;
|
||||||
break;
|
break;
|
||||||
case EM_IA_64: reltype = R_IA64_IMM64; break;
|
|
||||||
case EM_MIPS: /* reltype: e_class */ break;
|
case EM_MIPS: /* reltype: e_class */ break;
|
||||||
case EM_LOONGARCH: /* reltype: e_class */ break;
|
case EM_LOONGARCH: /* reltype: e_class */ break;
|
||||||
case EM_PPC: reltype = R_PPC_ADDR32; break;
|
case EM_PPC: reltype = R_PPC_ADDR32; break;
|
||||||
|
@ -275,13 +275,6 @@ if ($arch eq "x86_64") {
|
|||||||
$section_type = '%progbits';
|
$section_type = '%progbits';
|
||||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
|
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
|
||||||
$type = ".quad";
|
$type = ".quad";
|
||||||
} elsif ($arch eq "ia64") {
|
|
||||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
|
|
||||||
$type = "data8";
|
|
||||||
|
|
||||||
if ($is_module eq "0") {
|
|
||||||
$cc .= " -mconstant-gp";
|
|
||||||
}
|
|
||||||
} elsif ($arch eq "sparc64") {
|
} elsif ($arch eq "sparc64") {
|
||||||
# In the objdump output there are giblets like:
|
# In the objdump output there are giblets like:
|
||||||
# 0000000000000000 <igmp_net_exit-0x18>:
|
# 0000000000000000 <igmp_net_exit-0x18>:
|
||||||
|
@ -15,7 +15,6 @@ LZMA2OPTS=
|
|||||||
case $SRCARCH in
|
case $SRCARCH in
|
||||||
x86) BCJ=--x86 ;;
|
x86) BCJ=--x86 ;;
|
||||||
powerpc) BCJ=--powerpc ;;
|
powerpc) BCJ=--powerpc ;;
|
||||||
ia64) BCJ=--ia64; LZMA2OPTS=pb=4 ;;
|
|
||||||
arm) BCJ=--arm ;;
|
arm) BCJ=--arm ;;
|
||||||
sparc) BCJ=--sparc ;;
|
sparc) BCJ=--sparc ;;
|
||||||
esac
|
esac
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
static unsigned int offset;
|
static unsigned int offset;
|
||||||
static unsigned int ino = 721;
|
static unsigned int ino = 721;
|
||||||
static time_t default_mtime;
|
static time_t default_mtime;
|
||||||
|
static bool do_file_mtime;
|
||||||
static bool do_csum = false;
|
static bool do_csum = false;
|
||||||
|
|
||||||
struct file_handler {
|
struct file_handler {
|
||||||
@ -329,6 +330,7 @@ static int cpio_mkfile(const char *name, const char *location,
|
|||||||
int file;
|
int file;
|
||||||
int retval;
|
int retval;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
time_t mtime;
|
||||||
int namesize;
|
int namesize;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uint32_t csum = 0;
|
uint32_t csum = 0;
|
||||||
@ -347,16 +349,21 @@ static int cpio_mkfile(const char *name, const char *location,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf.st_mtime > 0xffffffff) {
|
if (do_file_mtime) {
|
||||||
fprintf(stderr, "%s: Timestamp exceeds maximum cpio timestamp, clipping.\n",
|
mtime = default_mtime;
|
||||||
location);
|
} else {
|
||||||
buf.st_mtime = 0xffffffff;
|
mtime = buf.st_mtime;
|
||||||
}
|
if (mtime > 0xffffffff) {
|
||||||
|
fprintf(stderr, "%s: Timestamp exceeds maximum cpio timestamp, clipping.\n",
|
||||||
|
location);
|
||||||
|
mtime = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
if (buf.st_mtime < 0) {
|
if (mtime < 0) {
|
||||||
fprintf(stderr, "%s: Timestamp negative, clipping.\n",
|
fprintf(stderr, "%s: Timestamp negative, clipping.\n",
|
||||||
location);
|
location);
|
||||||
buf.st_mtime = 0;
|
mtime = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf.st_size > 0xffffffff) {
|
if (buf.st_size > 0xffffffff) {
|
||||||
@ -387,7 +394,7 @@ static int cpio_mkfile(const char *name, const char *location,
|
|||||||
(long) uid, /* uid */
|
(long) uid, /* uid */
|
||||||
(long) gid, /* gid */
|
(long) gid, /* gid */
|
||||||
nlinks, /* nlink */
|
nlinks, /* nlink */
|
||||||
(long) buf.st_mtime, /* mtime */
|
(long) mtime, /* mtime */
|
||||||
size, /* filesize */
|
size, /* filesize */
|
||||||
3, /* major */
|
3, /* major */
|
||||||
1, /* minor */
|
1, /* minor */
|
||||||
@ -536,8 +543,9 @@ static void usage(const char *prog)
|
|||||||
"file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n"
|
"file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n"
|
||||||
"\n"
|
"\n"
|
||||||
"<timestamp> is time in seconds since Epoch that will be used\n"
|
"<timestamp> is time in seconds since Epoch that will be used\n"
|
||||||
"as mtime for symlinks, special files and directories. The default\n"
|
"as mtime for symlinks, directories, regular and special files.\n"
|
||||||
"is to use the current time for these entries.\n"
|
"The default is to use the current time for all files, but\n"
|
||||||
|
"preserve modification time for regular files.\n"
|
||||||
"-c: calculate and store 32-bit checksums for file data.\n",
|
"-c: calculate and store 32-bit checksums for file data.\n",
|
||||||
prog);
|
prog);
|
||||||
}
|
}
|
||||||
@ -594,6 +602,7 @@ int main (int argc, char *argv[])
|
|||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
do_file_mtime = true;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
do_csum = true;
|
do_csum = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user