kbuild: add infrastructure to build userspace programs
Kbuild supports the infrastructure to build host programs, but there was no support to build userspace programs for the target architecture (i.e. the same architecture as the kernel). Sam Ravnborg worked on this in 2014 (https://lkml.org/lkml/2014/7/13/154), but it was not merged. One problem at that time was, there was no good way to know whether $(CC) can link standalone programs. In fact, pre-built kernel.org toolchains [1] are often used for building the kernel, but they do not provide libc. Now, we can handle this cleanly because the compiler capability is evaluated at the Kconfig time. If $(CC) cannot link standalone programs, the relevant options are hidden by 'depends on CC_CAN_LINK'. The implementation just mimics scripts/Makefile.host The userspace programs are compiled with the same flags as the host programs. In addition, it uses -m32 or -m64 if it is found in $(KBUILD_CFLAGS). This new syntax has two usecases. - Sample programs Several userspace programs under samples/ include UAPI headers installed in usr/include. Most of them were previously built for the host architecture just to use the 'hostprogs' syntax. However, 'make headers' always works for the target architecture. This caused the arch mismatch in cross-compiling. To fix this distortion, sample code should be built for the target architecture. - Bpfilter net/bpfilter/Makefile compiles bpfilter_umh as the user mode helper, and embeds it into the kernel. Currently, it overrides HOSTCC with CC to use the 'hostprogs' syntax. This hack should go away. [1]: https://mirrors.edge.kernel.org/pub/tools/crosstool/ Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> Acked-by: Sam Ravnborg <sam@ravnborg.org>
This commit is contained in:
Родитель
b1183b6dca
Коммит
7f3a59db27
13
Makefile
13
Makefile
|
@ -406,9 +406,12 @@ else
|
|||
HOSTCC = gcc
|
||||
HOSTCXX = g++
|
||||
endif
|
||||
KBUILD_HOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 \
|
||||
-fomit-frame-pointer -std=gnu89 $(HOST_LFS_CFLAGS) \
|
||||
$(HOSTCFLAGS)
|
||||
|
||||
export KBUILD_USERCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-O2 -fomit-frame-pointer -std=gnu89
|
||||
export KBUILD_USERLDFLAGS :=
|
||||
|
||||
KBUILD_HOSTCFLAGS := $(KBUILD_USERCFLAGS) $(HOST_LFS_CFLAGS) $(HOSTCFLAGS)
|
||||
KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS)
|
||||
KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS)
|
||||
KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
|
||||
|
@ -944,6 +947,10 @@ ifeq ($(CONFIG_RELR),y)
|
|||
LDFLAGS_vmlinux += --pack-dyn-relocs=relr
|
||||
endif
|
||||
|
||||
# Align the bit size of userspace programs with the kernel
|
||||
KBUILD_USERCFLAGS += $(filter -m32 -m64, $(KBUILD_CFLAGS))
|
||||
KBUILD_USERLDFLAGS += $(filter -m32 -m64, $(KBUILD_CFLAGS))
|
||||
|
||||
# make the checker run with the right architecture
|
||||
CHECKFLAGS += --arch=$(ARCH)
|
||||
|
||||
|
|
|
@ -50,6 +50,12 @@ ifneq ($(hostprogs)$(hostcxxlibs-y)$(hostcxxlibs-m),)
|
|||
include scripts/Makefile.host
|
||||
endif
|
||||
|
||||
# Do not include userprogs rules unless needed.
|
||||
userprogs := $(sort $(userprogs))
|
||||
ifneq ($(userprogs),)
|
||||
include scripts/Makefile.userprogs
|
||||
endif
|
||||
|
||||
ifndef obj
|
||||
$(warning kbuild: Makefile.build is included improperly)
|
||||
endif
|
||||
|
|
|
@ -29,7 +29,7 @@ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
|
|||
|
||||
__clean-files := $(extra-y) $(extra-m) $(extra-) \
|
||||
$(always) $(always-y) $(always-m) $(always-) $(targets) $(clean-files) \
|
||||
$(hostprogs) $(hostprogs-y) $(hostprogs-m) $(hostprogs-) \
|
||||
$(hostprogs) $(hostprogs-y) $(hostprogs-m) $(hostprogs-) $(userprogs) \
|
||||
$(hostcxxlibs-y) $(hostcxxlibs-m)
|
||||
|
||||
__clean-files := $(filter-out $(no-clean-files), $(__clean-files))
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Build userspace programs for the target system
|
||||
#
|
||||
|
||||
# Executables compiled from a single .c file
|
||||
user-csingle := $(foreach m, $(userprogs), $(if $($(m)-objs),,$(m)))
|
||||
|
||||
# Executables linked based on several .o files
|
||||
user-cmulti := $(foreach m, $(userprogs), $(if $($(m)-objs),$(m)))
|
||||
|
||||
# Objects compiled from .c files
|
||||
user-cobjs := $(sort $(foreach m, $(userprogs), $($(m)-objs)))
|
||||
|
||||
user-csingle := $(addprefix $(obj)/, $(user-csingle))
|
||||
user-cmulti := $(addprefix $(obj)/, $(user-cmulti))
|
||||
user-cobjs := $(addprefix $(obj)/, $(user-cobjs))
|
||||
|
||||
user_ccflags = -Wp,-MMD,$(depfile) $(KBUILD_USERCFLAGS) $(userccflags) \
|
||||
$($(target-stem)-userccflags)
|
||||
user_ldflags = $(KBUILD_USERLDFLAGS) $(userldflags) $($(target-stem)-userldflags)
|
||||
|
||||
# Create an executable from a single .c file
|
||||
quiet_cmd_user_cc_c = CC [U] $@
|
||||
cmd_user_cc_c = $(CC) $(user_ccflags) $(user_ldflags) -o $@ $< \
|
||||
$($(target-stem)-userldlibs)
|
||||
$(user-csingle): $(obj)/%: $(src)/%.c FORCE
|
||||
$(call if_changed_dep,user_cc_c)
|
||||
|
||||
# Link an executable based on list of .o files
|
||||
quiet_cmd_user_ld = LD [U] $@
|
||||
cmd_user_ld = $(CC) $(user_ldflags) -o $@ \
|
||||
$(addprefix $(obj)/, $($(target-stem)-objs)) \
|
||||
$($(target-stem)-userldlibs)
|
||||
$(user-cmulti): FORCE
|
||||
$(call if_changed,user_ld)
|
||||
$(call multi_depend, $(user-cmulti), , -objs)
|
||||
|
||||
# Create .o file from a .c file
|
||||
quiet_cmd_user_cc_o_c = CC [U] $@
|
||||
cmd_user_cc_o_c = $(CC) $(user_ccflags) -c -o $@ $<
|
||||
$(user-cobjs): $(obj)/%.o: $(src)/%.c FORCE
|
||||
$(call if_changed_dep,user_cc_o_c)
|
||||
|
||||
targets += $(user-csingle) $(user-cmulti) $(user-cobjs)
|
Загрузка…
Ссылка в новой задаче