文章目录
- 1. 前言
- 2. 安装头文件
1. 前言
限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。
2. 安装头文件
Linux通过下面的命令
$makeARCH=arm headers_install导出头文件给用户空间,通常是给glibc这样的库使用,但用户空间程序也可以直接使用。
先看linux/Makefile:
...PHONY+=__headers __headers:$(version_h)scripts_basic uapi-asm-generic archheaders archscripts $(Q)$(MAKE)$(build)=scripts build_unifdef...PHONY+=headers_install headers_install:__headers $(if$(wildcard $(srctree)/arch/$(hdr-arch)/include/uapi/asm/Kbuild),,\ $(error Headers not exportableforthe $(SRCARCH)architecture))$(Q)$(MAKE)$(hdr-inst)=include/uapi dst=include $(Q)$(MAKE)$(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst)具体的安装操作见./scripts/Makefile.headersinst:
#SPDX-License-Identifier:GPL-2.0#==========================================================================#Installing headers##All headers under include/uapi,include/generated/uapi,#arch/<arch>/include/uapi and arch/<arch>/include/generated/uapi are#exported.#They are preprocessed to remove __KERNEL__ section of the file.# #==========================================================================PHONY:=__headers __headers:include scripts/Kbuild.include srcdir:=$(srctree)/$(obj)#When make is run under a fakechroot environment,the function# $(wildcard $(srcdir)/*/.) doesn't only return directories, but also regular # files. So, we are using a combination of sort/dir/wildcard which works # with fakechroot. subdirs := $(patsubst $(srcdir)/%/,%,\ $(filter-out $(srcdir)/,\ $(sort $(dir $(wildcard $(srcdir)/*/)))))#Recursion__headers:$(subdirs).PHONY:$(subdirs)$(subdirs):$(Q)$(MAKE)$(hdr-inst)=$(obj)/$@ dst=$(dst)/$@#Skip header install/checkforinclude/uapi and arch/$(hdr-arch)/include/uapi.#We have only sub-directories there.skip-inst:=$(if$(filter%/uapi,$(obj)),1)ifeq($(skip-inst),)#Kbuild file is optionalkbuild-file:=$(srctree)/$(obj)/Kbuild-include $(kbuild-file)installdir:=$(INSTALL_HDR_PATH)/$(dst)gendir:=$(objtree)/$(subst include/,include/generated/,$(obj))header-files:=$(notdir $(wildcard $(srcdir)/*.h)) header-files += $(notdir $(wildcard $(srcdir)/*.agh)) header-files := $(filter-out $(no-export-headers), $(header-files)) genhdr-files := $(notdir $(wildcard $(gendir)/*.h)) genhdr-files := $(filter-out $(header-files), $(genhdr-files)) # files used to track state of install/check install-file := $(installdir)/.install check-file := $(installdir)/.check # all headers files for this dir all-files := $(header-files) $(genhdr-files) output-files := $(addprefix $(installdir)/, $(all-files)) ifneq ($(mandatory-y),) missing := $(filter-out $(all-files),$(mandatory-y)) ifneq ($(missing),) $(error Some mandatory headers ($(missing)) are missing in $(obj)) endif endif # Work out what needs to be removed oldheaders := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h)) unwanted := $(filter-out $(all-files),$(oldheaders)) # Prefix unwanted with full paths to $(INSTALL_HDR_PATH) unwanted-file := $(addprefix $(installdir)/, $(unwanted)) printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@)) quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ file$(if $(word 2, $(all-files)),s)) cmd_install = \ $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(header-files); \ $(CONFIG_SHELL) $< $(installdir) $(gendir) $(genhdr-files); \ touch $@ quiet_cmd_remove = REMOVE $(unwanted) cmd_remove = rm -f $(unwanted-file) quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files) # Headers list can be pretty long, xargs helps to avoid # the "Argument list too long" error. cmd_check = for f in $(all-files); do \ echo "$(installdir)/$${f}"; done \ | xargs \ $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \ touch $@ ifndef HDRCHECK # Rules for installing headers __headers: $(install-file) @: targets += $(install-file) $(install-file): scripts/headers_install.sh \ $(addprefix $(srcdir)/,$(header-files)) \ $(addprefix $(gendir)/,$(genhdr-files)) FORCE $(if $(unwanted),$(call cmd,remove),) $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@))) $(call if_changed,install) else __headers: $(check-file) @: targets += $(check-file) $(check-file): scripts/headers_check.pl $(output-files) FORCE $(call if_changed,check) endif targets := $(wildcard $(sort $(targets))) cmd_files := $(wildcard \ $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) ifneq ($(cmd_files),) include $(cmd_files) endif endif # skip-inst .PHONY: $(PHONY) PHONY += FORCE FORCE: ;可以看到,安装下面这4个目录下的头文件:
# 公用 UAPI 头文件include/uapi include/generated/uapi# 编译时生成# 架构 UAPI 头文件arch/$(hdr-arch)/include/uapi# 如 arch/arm/include/uapiarch/<arch>/include/generated/uapi# 编译时生成./scripts/Makefile.headersinst调用scripts/headers_install.sh进行头文件安装,默认安装在linux/usr目录下,生成一个linux/usr/include文件夹,其中包含所有安装的头文件。
看看4个安装目录下都有哪些头文件:
# 这个有点多,就不用 tree 命令展开了$lsinclude/uapi asm-generic drm linux misc mtd rdma scsi sound video xen $ tree include/generated/uapi/ include/generated/uapi/ └── linux └── version.h1directory,1file$ tree arch/arm/include/uapi arch/arm/include/uapi └── asm ├── auxvec.h ├── byteorder.h ├── fcntl.h ├── hwcap.h ├── ioctls.h ├── Kbuild ├── kvm.h ├── kvm_para.h ├── mman.h ├── perf_regs.h ├── posix_types.h ├── ptrace.h ├── setup.h ├── sigcontext.h ├── signal.h ├── statfs.h ├── stat.h ├── swab.h ├── types.h └── unistd.h1directory,20files asm $ tree arch/arm/include/generated/uapi arch/arm/include/generated/uapi └── asm ├── bitsperlong.h ├── errno.h ├── ioctl.h ├── ipcbuf.h ├── msgbuf.h ├── param.h ├── poll.h ├── resource.h ├── sembuf.h ├── shmbuf.h ├── siginfo.h ├── socket.h ├── sockios.h ├── termbits.h ├── termios.h ├── unistd-common.h ├── unistd-eabi.h └── unistd-oabi.h1directory,18files看一下安装过程:
$makeARCH=arm headers_installO=output/ make[1]: Entering directory'/home/lxj/Work/qemu-lab/linux-4.14.111'CHK include/generated/uapi/linux/version.h HOSTCC scripts/unifdef INSTALL usr/include/asm-generic/(36files)INSTALL usr/include/drm/(25files)INSTALL usr/include/linux/(485files)INSTALL usr/include/linux/android/(1file)INSTALL usr/include/linux/byteorder/(2files)INSTALL usr/include/linux/caif/(2files)INSTALL usr/include/linux/can/(6files)INSTALL usr/include/linux/cifs/(1file)INSTALL usr/include/linux/dvb/(8files)INSTALL usr/include/linux/genwqe/(1file)INSTALL usr/include/linux/hdlc/(1file)INSTALL usr/include/linux/hsi/(2files)INSTALL usr/include/linux/iio/(2files)INSTALL usr/include/linux/isdn/(1file)INSTALL usr/include/linux/mmc/(1file)INSTALL usr/include/linux/netfilter/(87files)INSTALL usr/include/linux/netfilter/ipset/(4files)INSTALL usr/include/linux/netfilter_arp/(2files)INSTALL usr/include/linux/netfilter_bridge/(17files)INSTALL usr/include/linux/netfilter_ipv4/(9files)INSTALL usr/include/linux/netfilter_ipv6/(12files)INSTALL usr/include/linux/nfsd/(5files)INSTALL usr/include/linux/raid/(2files)INSTALL usr/include/linux/sched/(1file)INSTALL usr/include/linux/spi/(1file)INSTALL usr/include/linux/sunrpc/(1file)INSTALL usr/include/linux/tc_act/(15files)INSTALL usr/include/linux/tc_ematch/(4files)INSTALL usr/include/linux/usb/(12files)INSTALL usr/include/linux/wimax/(1file)INSTALL usr/include/misc/(1file)INSTALL usr/include/mtd/(5files)INSTALL usr/include/rdma/(20files)INSTALL usr/include/rdma/hfi/(2files)INSTALL usr/include/scsi/(4files)INSTALL usr/include/scsi/fc/(4files)INSTALL usr/include/sound/(15files)INSTALL usr/include/video/(3files)INSTALL usr/include/xen/(4files)INSTALL usr/include/asm/(37files)make[1]: Leaving directory'/home/lxj/Work/qemu-lab/linux-4.14.111'默认在linux/usr目录下,创建linux/usr/include目录,然后安装所有UAPI头文件。为什么只安装uapi目录下头文件?因为 linux uapi 下头文件就是导出给用户使用的,其它的头文件不应该导出,是不对用户开放的黑盒子。
另外,可以通过 INSTALL_HDR_PATH 将头文件安装到指定目录:
$makeARCH=armINSTALL_HDR_PATH=<target-path>headers_install同样会在<target-path>目录下创建<target-path>/include文件夹安装所有头文件。另外,O=参数也是支持的,如:
$makeARCH=armO=output headers_install则会在output/usr/include目录下安装所有头文件。当然,也可以同时使用 INSTALL_HDR_PATH= 和O=参数:
$makeARCH=armO=outputINSTALL_HDR_PATH=<target-path>headers_install最后,还可以通过命令:
$makeheaders_install_all安装所有架构的头文件。
调试可以加上V=1参数。