# ========================================================================== # 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) KLIBCRANLIB := $(RANLIB) 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 $@; $(KLIBCAR) cru $@ $(filter $(lib-y), $^),\ rm -f $@; $(KLIBCAR) crs $@) $(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