blob: fb399f5046ac4179708eb24d6f4059dbb143758a [file] [log] [blame]
# ==========================================================================
# Support for building klibc programs and klibc library
# ==========================================================================
#
# To create a kbuild file for a userspace program do the following:
#
# Kbuild:
#
# static-y := cat
# # This will compile a file named cat.c -> the executable 'cat'
# # The executable will be linked statically
#
# shared-y := cats
# # This will compile a file named cats.c -> the executable 'cats'
# # The executable will be linked shared
#
# If the userspace program consist of composite files do the following:
# Kbuild:
#
# static-y := kinit
# kinit-y := main.o netdev.c
# So kinit will be linked statically using the two .o files
# specified with kinit-y.
#
# Are part of the program located in a sub-directory do like this:
# kinit-y += ipconfig/
#
# And in the subdirectory:
# ipconfig/Kbuild:
# lib-y := packet.o dhcp_proto.o
# # All .o files listed with lib-y will be used to create a single .a file.
# # The .a file is created before any subdirectories are visited so it
# # may be used in the sub-directory programs.
#
#####
# For a klibc libary file do like this
# klibc/Kbuild
# klib-y := error.o pipe.o zlib/
#
#####
# Handling of compiler/linker options
#
# To set directory wide CFLAGS use:
# EXTRA_KLIBCCFLAGS := -DDEBUG
# To set directory wide AFLAGS use:
# EXTRA_KLIBCAFLAGS := -DDEBUG
#
# To set target specific CFLAGS (for .c files) use
# KLIBCCFLAGS-main.o := -DDEBUG=3
# To set target specific AFLAGS (for .s files) use
# KLIBCAFLAGS-main.o := -DDEBUG=3
src := $(obj)
# Preset target and make sure it is a ':=' variable
targets :=
.phony: __build
__build:
# Read .config if it exist, otherwise ignore
-include $(objtree)/.config
# Generic Kbuild routines
include $(srctree)/scripts/Kbuild.include
# Defines used when compiling early userspace (klibc programs)
# ---------------------------------------------------------------------------
KLIBCREQFLAGS := $(call cc-option, -fno-stack-protector, ) \
$(call cc-option, -fwrapv, )
KLIBCARCHREQFLAGS :=
KLIBCOPTFLAGS :=
KLIBCWARNFLAGS := -W -Wall -Wno-sign-compare -Wno-unused-parameter
KLIBCSHAREDFLAGS :=
KLIBCBITSIZE :=
KLIBCLDFLAGS :=
KLIBCCFLAGS :=
# Defaults for arch to override
KLIBCARCHINCFLAGS = -I$(KLIBCKERNELOBJ)/arch/$(KLIBCARCH)/include
# Arch specific definitions for klibc
include $(srctree)/$(KLIBCSRC)/arch/$(KLIBCARCHDIR)/MCONFIG
# include/asm-* architecture
KLIBCASMARCH ?= $(KLIBCARCH)
# klibc version
KLIBCMAJOR := $(shell cut -d. -f1 $(srctree)/usr/klibc/version)
KLIBCMINOR := $(shell cut -d. -f2 $(srctree)/usr/klibc/version)
# binutils
KLIBCLD := $(LD)
KLIBCCC := $(CC)
KLIBCAR := $(AR)
# klibc-ar is a macro that invokes KLIBCAR and takes 2 arguments of ar commands.
# The second will be used for reproducible builds, the first otherwise.
klibc-ar = $(KLIBCAR) $(if $(KBUILD_REPRODUCIBLE),$(2),$(1))
KLIBCRANLIB := $(call klibc-ar,s,Ds)
KLIBCSTRIP := $(STRIP)
KLIBCNM := $(NM)
KLIBCOBJCOPY := $(OBJCOPY)
KLIBCOBJDUMP := $(OBJDUMP)
# klibc include paths
KLIBCCPPFLAGS := -nostdinc -iwithprefix include \
-I$(KLIBCINC)/arch/$(KLIBCARCHDIR) \
-I$(KLIBCINC)/bits$(KLIBCBITSIZE) \
-I$(KLIBCOBJ)/../include \
-I$(KLIBCINC)
# kernel include paths
KLIBCKERNELSRC ?= $(srctree)
KLIBCKERNELOBJ ?= $(objtree)
KLIBCCPPFLAGS += -I$(KLIBCKERNELSRC)/include \
$(if $(KBUILD_SRC),-I$(KLIBCKERNELOBJ)/include2 \
-I$(KLIBCKERNELOBJ)/include -I$(srctree)/include) \
$(KLIBCARCHINCFLAGS)
# klibc definitions
KLIBCDEFS += -D__KLIBC__=$(KLIBCMAJOR) \
-D__KLIBC_MINOR__=$(KLIBCMINOR) \
-D_BITSIZE=$(KLIBCBITSIZE)
KLIBCCPPFLAGS += $(KLIBCDEFS)
KLIBCCFLAGS += $(KLIBCCPPFLAGS) $(KLIBCREQFLAGS) $(KLIBCARCHREQFLAGS) \
$(KLIBCOPTFLAGS) $(KLIBCWARNFLAGS)
KLIBCAFLAGS += -D__ASSEMBLY__ $(KLIBCCFLAGS)
KLIBCSTRIPFLAGS += --strip-all -R .comment -R .note
KLIBCLIBGCC_DEF := $(shell $(KLIBCCC) $(KLIBCCFLAGS) --print-libgcc)
KLIBCLIBGCC ?= $(KLIBCLIBGCC_DEF)
KLIBCCRT0 := $(KLIBCOBJ)/arch/$(KLIBCARCHDIR)/crt0.o
KLIBCLIBC := $(KLIBCOBJ)/libc.a
KLIBCCRTSHARED := $(KLIBCOBJ)/interp.o
KLIBCLIBCSHARED := $(KLIBCOBJ)/libc.so
# How to tell the linker main() is the entrypoint
KLIBCEMAIN ?= -e main
#
# This indicates the location of the final version of the shared library.
# THIS MUST BE AN ABSOLUTE PATH WITH NO FINAL SLASH.
# Leave this empty to make it the root.
#
SHLIBDIR = /lib
export KLIBCLD KLIBCCC KLIBCAR KLIBCSTRIP KLIBCNM
export KLIBCCFLAGS KLIBCAFLAGS KLIBCLIBGCC KLIBCSHAREDFLAGS KLIBCSTRIPFLAGS
export KLIBCCRT0 KLIBCLIBC SHLIBDIR
# Add $(obj)/ for paths that is not absolute
objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
# Kbuild file in the directory that is being build
include $(srctree)/$(obj)/Kbuild
#####
# static-y + shared-y handling
kprogs := $(static-y) $(shared-y)
# kprogs based on a single .o file (with same name + .o)
kprog-objs := $(foreach p, $(kprogs), $(if $($(p)-y),,$(p)))
kprog-objs := $(addsuffix .o, $(kprog-objs))
# kprogs which is based on several .o files
kprog-multi := $(foreach p, $(kprogs), $(if $($(p)-y),$(p)))
# objects used for kprogs with more then one .o file
kprog-objs += $(foreach p, $(kprog-multi), $($(p)-y))
# objects build in this dir
kprog-real-objs := $(patsubst %/,,$(kprog-objs))
# Directories we need to visit before kprogs-objs are up-to-date
kprog-dirs := $(patsubst %/,%,$(filter %/, $(kprog-objs)))
# replace all dir/ with dir/lib.a
kprog-objs := $(patsubst %/, %/lib.a, $(kprog-objs))
targets += $(static-y) $(shared-y)
#####
# klib-y handling
# .o files to build in this dir
klib-real-objs := $(patsubst %/,,$(klib-y))
# Directories we need to visit before libs are up-to-date
klib-dirs := $(patsubst %/,%,$(filter %/, $(klib-y)))
# replace all dir/ with dir/klib.list
klib-objs := $(patsubst %/, %/klib.list, $(klib-y))
# $(output-dirs) are a list of directories that contain object files
output-dirs := $(dir $(kprog-dirs) $(kprog-objs))
output-dirs += $(foreach f, $(hostprogs-y) $(targets), \
$(if $(dir $(f)), $(dir $(f))))
output-dirs += $(dir $(klib-objs))
output-dirs := $(strip $(sort $(filter-out ./,$(output-dirs))))
# prefix so we get full dir
static-y := $(addprefix $(obj)/,$(static-y))
shared-y := $(addprefix $(obj)/,$(shared-y))
kprog-objs := $(addprefix $(obj)/,$(kprog-objs))
kprog-real-objs := $(addprefix $(obj)/,$(kprog-real-objs))
output-dirs := $(addprefix $(obj)/,$(output-dirs))
kprog-dirs := $(addprefix $(obj)/,$(kprog-dirs))
subdir-y := $(addprefix $(obj)/,$(subdir-y))
always := $(addprefix $(obj)/,$(always))
targets := $(addprefix $(obj)/,$(targets))
lib-y := $(addprefix $(obj)/,$(lib-y))
klib-y := $(addprefix $(obj)/,$(klib-y))
klib-objs := $(addprefix $(obj)/,$(klib-objs))
klib-real-objs := $(addprefix $(obj)/,$(klib-real-objs))
klib-dirs := $(addprefix $(obj)/,$(klib-dirs))
#####
# Handle options to gcc. Support building with separate output directory
__klibccflags = $(KLIBCCFLAGS) $(EXTRA_KLIBCCFLAGS) $(KLIBCCFLAGS_$(*F).o)
__klibcaflags = $(KLIBCAFLAGS) $(EXTRA_KLIBCAFLAGS) $(KLIBCAFLAGS_$(*F).o)
_klibccflags = $(call flags,__klibccflags)
_klibcaflags = $(call flags,__klibcaflags)
klibccflags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(_klibccflags)
klibcaflags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(_klibcaflags)
# Create output directory if not already present
_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
# Create directories for object files if directory does not exist
# Needed when lib-y := dir/file.o syntax is used
_dummy := $(foreach d,$(output-dirs), $(shell [ -d $(d) ] || mkdir -p $(d)))
# Do we have to make a lib.a in this dir?
ifneq ($(strip $(lib-y) $(lib-n) $(lib-)),)
lib-target := $(obj)/lib.a
endif
__build: $(subdir-y) $(lib-target) $(always)
$(Q):
# Compile C sources (.c)
# ---------------------------------------------------------------------------
quiet_cmd_cc_s_c = KLIBCCC $@
cmd_cc_s_c = $(KLIBCCC) $(klibccflags) -S -o $@ $<
%.s: %.c FORCE
$(call if_changed_dep,cc_s_c)
quiet_cmd_cc_o_c = KLIBCCC $@
cmd_cc_o_c = $(KLIBCCC) $(klibccflags) -c -o $@ $<
%.o: %.c FORCE
$(call if_changed_dep,cc_o_c)
quiet_cmd_cc_i_c = CPP $@
cmd_cc_i_c = $(KLIBCCC) -E $(klibccflags) -o $@ $<
%.i: %.c FORCE
$(call if_changed_dep,cc_i_c)
# Compile assembler sources (.S)
# ---------------------------------------------------------------------------
quiet_cmd_as_o_S = KLIBCAS $@
cmd_as_o_S = $(KLIBCCC) $(klibcaflags) -c -o $@ $<
%.o: %.S FORCE
$(call if_changed_dep,as_o_S)
targets += $(real-objs-y)
#
# Rule to compile a set of .o files into one .o file
#
ifdef lib-target
quiet_cmd_link_o_target = LD $@
# If the list of objects to link is empty, just create an empty lib.a
cmd_link_o_target = $(if $(strip $(lib-y)),\
rm -f $@; $(call klibc-ar,cru,Dcr) $@ $(filter $(lib-y), $^),\
rm -f $@; $(call klibc-ar,crs,Dcrs) $@)
$(lib-target): $(lib-y) FORCE
$(call if_changed,link_o_target)
targets += $(lib-target) $(lib-y)
endif # lib-target
#
# Create klib.list
#
# Do we have to create a klibc library file in this dir?
ifneq ($(strip $(klib-y) $(klib-n) $(klib-)),)
klib-target := $(obj)/klib.list
endif
ifdef klib-target
# include this in build
__build: $(klib-target) $(klib-dirs)
# descend if needed
$(sort $(addsuffix /klib.list,$(klib-dirs))): $(klib-dirs) ;
# create klib.list
quiet_cmd_klib-list = LIST $@
cmd_klib-list = echo $(klib-real-objs) > $@
$(klib-target): $(klib-objs) FORCE
$(call if_changed,klib-list)
targets += $(klib-target) $(klib-real-objs)
endif # klib-target
ifdef kprogs
# Compile klibc-programs for the target
# ===========================================================================
__build : $(kprog-dirs) $(static-y) $(shared-y)
# Descend if needed
$(sort $(addsuffix /lib.a,$(kprog-dirs))): $(kprog-dirs) ;
# Define dependencies for link of progs
# For the simple program:
# file.o => file
# A program with multiple objects
# filea.o, fileb.o => file
# A program with .o files in another dir
# dir/lib.a filea.o => file
stripobj = $(subst $(obj)/,,$@)
addliba = $(addprefix $(obj)/, $(patsubst %/, %/lib.a, $(1)))
link-deps = $(if $($(stripobj)-y), $(call addliba, $($(stripobj)-y)), $@.o) \
$(call objectify,$($(stripobj)-lib))
quiet_cmd_ld-static = KLIBCLD $@
cmd_ld-static = $(KLIBCLD) $(KLIBCLDFLAGS) -o $@ \
$(EXTRA_KLIBCLDFLAGS) \
$(KLIBCCRT0) \
--start-group \
$(link-deps) \
$(KLIBCLIBC) \
$(KLIBCLIBGCC) \
--end-group ; \
cp -f $@ $@.g ; \
$(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $@
$(static-y): $(kprog-objs) $(lib-target) $(KLIBCCRT0) $(KLIBCLIBC) FORCE
$(call if_changed,ld-static)
quiet_cmd_ld-shared = KLIBCLD $@
cmd_ld-shared = $(KLIBCLD) $(KLIBCLDFLAGS) -o $@ \
$(EXTRA_KLIBCLDFLAGS) \
$(KLIBCEMAIN) $(KLIBCCRTSHARED) \
--start-group \
$(link-deps) \
-R $(KLIBCLIBCSHARED) \
$(KLIBCLIBGCC) \
--end-group ; \
cp -f $@ $@.g ; \
$(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $@
$(shared-y): $(kprog-objs) $(lib-target) $(KLIBCCRTSHARED) \
$(KLIBCLIBCSHARED) FORCE
$(call if_changed,ld-shared)
# Do not try to build KLIBC libaries if we are building klibc
ifeq ($(klibc-build),)
$(KLIBCCRT0) $(KLIBCLIBC): ;
$(KLIBCCRTSHARED) $(KLIBCLIBCSHARED): ;
endif
targets += $(kprog-real-objs)
endif
# Compile programs on the host
# ===========================================================================
ifdef hostprogs-y
include $(srctree)/scripts/Makefile.host
endif
# Descending
# ---------------------------------------------------------------------------
.PHONY: $(subdir-y) $(kprog-dirs) $(klib-dirs)
$(sort $(subdir-y) $(kprog-dirs) $(klib-dirs)): $(lib-target)
$(Q)$(MAKE) $(klibc)=$@
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
.PHONY: FORCE
FORCE:
# Linking
# Create a reloctable composite object file
# ---------------------------------------------------------------------------
quiet_cmd_klibcld = KLIBCLD $@
cmd_klibcld = $(KLIBCLD) -r $(KLIBCLDFLAGS) \
$(EXTRA_KLIBCLDFLAGS) $(KLIBCLDFLAGS_$(@F)) \
$(filter-out FORCE,$^) -o $@
# Link target to a new name
# ---------------------------------------------------------------------------
quiet_cmd_ln = LN $@
cmd_ln = rm -f $@ && ln $< $@
# Strip target (remove all debugging info)
quiet_cmd_strip = STRIP $@
cmd_strip = $(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $< -o $@
# Read all saved command lines and dependencies for the $(targets) we
# may be building above, using $(if_changed{,_dep}). As an
# optimization, we don't need to read them if the target does not
# exist, we will rebuild anyway in that case.
targets := $(wildcard $(sort $(targets)))
cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
ifneq ($(cmd_files),)
include $(cmd_files)
endif
# Shorthand for $(Q)$(MAKE) -f scripts/Kbuild.klibc obj
# Usage:
# $(Q)$(MAKE) $(klibc)=dir
klibc := -rR -f $(srctree)/scripts/Kbuild.klibc obj