The UAPI headers contain references to Kconfig's `CONFIG_' macros. Either this is a bug, or there needs to be some standard way for users to provide definitions for these macros, in order to complete Linux's user-space API. Consider: #!/bin/sh cd "${linux_repo}" # Careful! #git reset --hard HEAD #git clean -fdx git checkout v5.1 #zcat /proc/config.gz >.config mkdir -p /tmp/uapi/include make INSTALL_HDR_PATH=/tmp/uapi headers_install printf >/tmp/uapi/raw.c '%s\n%s\n' \ '#include ' \ 'int main() { return MAX_RAW_MINORS; }' Then: $ gcc -c -I/tmp/uapi/include /tmp/uapi/raw.c In file included from /tmp/uapi/raw.c:1:0: /tmp/uapi/raw.c: In function ‘main’: /tmp/uapi/include/linux/raw.h:17:24: error: ‘CONFIG_MAX_RAW_DEVS’ undeclared (first use in this function) #define MAX_RAW_MINORS CONFIG_MAX_RAW_DEVS ^ /tmp/uapi/raw.c:2:21: note: in expansion of macro ‘MAX_RAW_MINORS’ int main() { return MAX_RAW_MINORS; } ^~~~~~~~~~~~~~ /tmp/uapi/include/linux/raw.h:17:24: note: each undeclared identifier is reported only once for each function it appears in #define MAX_RAW_MINORS CONFIG_MAX_RAW_DEVS ^ /tmp/uapi/raw.c:2:21: note: in expansion of macro ‘MAX_RAW_MINORS’ int main() { return MAX_RAW_MINORS; } ^~~~~~~~~~~~~~ As you can see, the UAPI is actually incomplete; there is not a valid definition for `MAX_RAW_MINORS'. Indeed, on my system, `CONFIG_MAX_RAW_DEVS' isn't ever defined anywhere, because `CONFIG_RAW_DRIVER' is not set: $ git show v5.1:drivers/char/Kconfig | sed -n 467,469p config MAX_RAW_DEVS int "Maximum number of RAW devices to support (1-65536)" depends on RAW_DRIVER $ zcat /proc/config.gz | grep RAW_DRIVER # CONFIG_RAW_DRIVER is not set Even if `CONFIG_RAW_DRIVER' were set, the desired definition for the macro `CONFIG_MAX_RAW_DEVS' would only be found in the following header (generated at built-time), which is neither officially nor likely available to user space: "${linux_repo}"/include/generated/autoconf.h Other such references to `CONFIG_*' macros are seen in the following (some appear only in comments, but perhaps that's conceptually a mistake, too): $ (cd /tmp/uapi/include && grep -R . -e \\bCONFIG_) ./asm/mman.h:#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS ./asm/auxvec.h:#if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64) ./asm/e820.h: * kernel was built: MAX_NUMNODES == (1 << CONFIG_NODES_SHIFT), ./asm/e820.h: * unless the CONFIG_X86_PMEM_LEGACY option is set. ./asm/e820.h: * if CONFIG_INTEL_TXT is enabled, memory of this type will be ./mtd/ubi-user.h: * default kernel value of %CONFIG_MTD_UBI_BEB_LIMIT will be used. ./linux/pkt_cls.h: TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */ ./linux/pkt_cls.h: TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */ ./linux/cm4000_cs.h: * member sizes. This leads to CONFIG_COMPAT breakage, since 32bit userspace ./linux/eventpoll.h:#ifdef CONFIG_PM_SLEEP ./linux/hw_breakpoint.h:#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS ./linux/bpf.h: * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set, ./linux/bpf.h: * the **CONFIG_CGROUP_NET_CLASSID** configuration option set to ./linux/bpf.h: * **CONFIG_IP_ROUTE_CLASSID** configuration option. ./linux/bpf.h: * with the **CONFIG_BPF_KPROBE_OVERRIDE** configuration ./linux/bpf.h: * the CONFIG_FUNCTION_ERROR_INJECTION option. As of this writing, ./linux/bpf.h: * **CONFIG_XFRM** configuration option. ./linux/bpf.h: * the **CONFIG_BPF_LIRC_MODE2** configuration option set to ./linux/bpf.h: * the **CONFIG_BPF_LIRC_MODE2** configuration option set to ./linux/bpf.h: * **CONFIG_SOCK_CGROUP_DATA** configuration option. ./linux/bpf.h: * **CONFIG_NET** configuration option. ./linux/bpf.h: * **CONFIG_NET** configuration option. ./linux/bpf.h: * the **CONFIG_BPF_LIRC_MODE2** configuration option set to ./linux/raw.h:#define MAX_RAW_MINORS CONFIG_MAX_RAW_DEVS ./linux/pktcdvd.h:#if defined(CONFIG_CDROM_PKTCDVD_WCACHE) ./linux/flat.h:#ifdef CONFIG_BINFMT_SHARED_FLAT ./linux/videodev2.h: * Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. ./linux/elfcore.h:#ifdef CONFIG_BINFMT_ELF_FDPIC ./linux/atmdev.h:#ifdef CONFIG_COMPAT ./asm-generic/bitsperlong.h: * both 32 and 64 bit user space must not rely on CONFIG_64BIT ./asm-generic/unistd.h:/* mm/, CONFIG_MMU only */ ./asm-generic/mman-common.h:#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED ./asm-generic/fcntl.h:#ifndef CONFIG_64BIT What is the correct way to think about this? * Should the UAPI make no reference to build-time configurations? * Should the UAPI headers include sanity checks on behalf of the user? * Should there be a `/proc/config.h.gz' facility? Sincerely, Michael Witten